/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include @class WOAssociation; @interface WECollapsibleComponentContent : WODynamicElement { @protected WOAssociation *condition; WOAssociation *visibility; WOAssociation *allowScript; /* perform clicks on browser (use javaScript) */ WOElement *template; } @end @interface WECollapsibleAction : WODynamicElement { @protected WOAssociation *openedImageFileName; WOAssociation *closedImageFileName; WOAssociation *framework; WOAssociation *openedLabel; WOAssociation *closedLabel; WOAssociation *submitActionName; WOAssociation *action; // if submit button, use submitActionName instead WOAssociation *fragmentIdentifier; WOAssociation *isClicked; WOElement *template; } @end #include "WEContextConditional.h" #include #include "common.h" static NSString *WECollapsible_TitleMode = @"WECollapsible_TitleMode"; static NSString *WECollapsible_ContentMode = @"WECollapsible_ContentMode"; static NSString *WECollapsible_IsCollapsed = @"WECollapsible_IsCollapsed"; static NSString *WECollapsible_ScriptId = @"WECollapsible_ScriptId"; static NSString *WECollapsible_HasScript = @"WECollapsible_HasScript"; static NSString *Yes = @"YES"; static NSString *No = @"NO"; @implementation WECollapsibleComponentContent - (id)initWithName:(NSString *)_name associations:(NSDictionary *)_config template:(WOElement *)_tmp { if ((self = [super initWithName:_name associations:_config template:_tmp])) { self->condition = WOExtGetProperty(_config, @"condition"); self->visibility = WOExtGetProperty(_config, @"visibility"); self->allowScript = WOExtGetProperty(_config, @"allowScript"); if (self->visibility == nil) NSLog(@"WARNING: WECollapsibleComponent 'visibility' not set"); if (self->visibility && ![self->visibility isValueSettable]) NSLog(@"WARNING: WECollapsibleComponent 'visibility' is not settable"); self->template = [_tmp retain]; } return self; } - (void)dealloc { [self->condition release]; [self->visibility release]; [self->allowScript release]; [self->template release]; [super dealloc]; } /* responder */ - (void)takeValuesFromRequest:(WORequest *)_req inContext:(WOContext *)_ctx { BOOL isCollapsed; isCollapsed = ![self->visibility boolValueInComponent:[_ctx component]]; // content if (!isCollapsed) { [_ctx setObject:Yes forKey:WECollapsible_ContentMode]; [self->template takeValuesFromRequest:_req inContext:_ctx]; [_ctx removeObjectForKey:WECollapsible_ContentMode]; } // title [_ctx setObject:Yes forKey:WECollapsible_TitleMode]; [self->template takeValuesFromRequest:_req inContext:_ctx]; [_ctx removeObjectForKey:WECollapsible_TitleMode]; } - (id)invokeActionForRequest:(WORequest *)_request inContext:(WOContext *)_ctx { id result = nil; BOOL isCollapsed; isCollapsed = ![self->visibility boolValueInComponent:[_ctx component]]; // title [_ctx setObject:Yes forKey:WECollapsible_TitleMode]; [_ctx setObject:Yes forKey:WECollapsible_ContentMode]; [_ctx setObject:(isCollapsed) ? Yes : No forKey:WECollapsible_IsCollapsed]; result = [self->template invokeActionForRequest:_request inContext:_ctx]; isCollapsed = [[_ctx objectForKey:WECollapsible_IsCollapsed] boolValue]; if ([self->visibility isValueSettable]) [self->visibility setBoolValue:!isCollapsed inComponent:[_ctx component]]; [_ctx removeObjectForKey:WECollapsible_IsCollapsed]; [_ctx removeObjectForKey:WECollapsible_ContentMode]; [_ctx removeObjectForKey:WECollapsible_TitleMode]; return result; } - (void)appendToResponse:(WOResponse *)_resp inContext:(WOContext *)_ctx { WOComponent *comp; BOOL isCollapsed; BOOL doScript; NSString *scriptId; comp = [_ctx component]; doScript = [self->allowScript boolValueInComponent:comp]; scriptId = [[[_ctx elementID] componentsSeparatedByString:@"."] componentsJoinedByString:@"_"]; if (doScript) { WEClientCapabilities *ccaps; ccaps = [[_ctx request] clientCapabilities]; doScript = [ccaps isInternetExplorer]; } if (doScript) [_ctx setObject:scriptId forKey:WECollapsible_ScriptId]; if ([self->visibility valueInComponent:comp] == nil) { isCollapsed = ![self->condition boolValueInComponent:comp]; if ([self->visibility isValueSettable]) [self->visibility setBoolValue:!isCollapsed inComponent:comp]; } else isCollapsed = ![self->visibility boolValueInComponent:comp]; // append title [_ctx setObject:Yes forKey:WECollapsible_TitleMode]; [_ctx setObject:(isCollapsed) ? Yes : No forKey:WECollapsible_IsCollapsed]; [self->template appendToResponse:_resp inContext:_ctx]; [_ctx removeObjectForKey:WECollapsible_IsCollapsed]; [_ctx removeObjectForKey:WECollapsible_TitleMode]; // append content if (!isCollapsed || doScript) { [_ctx setObject:Yes forKey:WECollapsible_ContentMode]; if (doScript) { [_resp appendContentString:@"
"]; } [self->template appendToResponse:_resp inContext:_ctx]; if (doScript) [_resp appendContentString:@"
"]; [_ctx removeObjectForKey:WECollapsible_ContentMode]; } [_ctx removeObjectForKey:WECollapsible_ScriptId]; } @end /* WECollapsibleComponentContent */ @implementation WECollapsibleAction - (id)initWithName:(NSString *)_name associations:(NSDictionary *)_config template:(WOElement *)_temp { if ((self = [super initWithName:_name associations:_config template:_temp])) { self->openedImageFileName = WOExtGetProperty(_config, @"openedImageFileName"); self->closedImageFileName = WOExtGetProperty(_config, @"closedImageFileName"); self->framework = WOExtGetProperty(_config, @"framework"); self->openedLabel = WOExtGetProperty(_config, @"openedLabel"); self->closedLabel = WOExtGetProperty(_config, @"closedLabel"); self->submitActionName = WOExtGetProperty(_config, @"submitActionName"); self->action = WOExtGetProperty(_config, @"action"); self->fragmentIdentifier = WOExtGetProperty(_config, @"fragmentIdentifier"); self->isClicked = WOExtGetProperty(_config, @"isClicked"); self->template = [_temp retain]; } return self; } - (void)dealloc { [self->openedImageFileName release]; [self->closedImageFileName release]; [self->framework release]; [self->openedLabel release]; [self->closedLabel release]; [self->submitActionName release]; [self->action release]; [self->fragmentIdentifier release]; [self->isClicked release]; [self->template release]; [super dealloc]; } /* requests */ - (void)takeValuesFromRequest:(WORequest *)_request inContext:(WOContext *)_ctx { NSString *eid; eid = [_ctx elementID]; if ([_request formValueForKey:[eid stringByAppendingString:@".c.x"]]) { [_ctx addActiveFormElement:self]; [_ctx setRequestSenderID:[[_ctx senderID] stringByAppendingString:@".c"]]; } else if ([_request formValueForKey:[eid stringByAppendingString:@".e.x"]]) { [_ctx addActiveFormElement:self]; [_ctx setRequestSenderID:[[_ctx senderID] stringByAppendingString:@".e"]]; } } - (id)invokeActionForRequest:(WORequest *)_request inContext:(WOContext *)_ctx { NSString *state; BOOL doForm; state = [[_ctx currentElementID] stringValue]; doForm = ([_ctx isInForm] && self->submitActionName && ([self->submitActionName valueInComponent:[_ctx component]])); [_ctx consumeElementID]; // consume state-id if ([state isEqualToString:@"e"]) { [_ctx setObject:[NSNumber numberWithBool:YES] forKey:WECollapsible_IsCollapsed]; if (doForm) [self->submitActionName valueInComponent:[_ctx component]]; else if ([self->action valueInComponent:[_ctx component]] != nil) [self->action valueInComponent:[_ctx component]]; } else if ([state isEqualToString:@"c"]) { [_ctx setObject:[NSNumber numberWithBool:NO] forKey:WECollapsible_IsCollapsed]; if (doForm) [self->submitActionName valueInComponent:[_ctx component]]; else if ([self->action valueInComponent:[_ctx component]] != nil) [self->action valueInComponent:[_ctx component]]; } if ([self->isClicked isValueSettable]) [self->isClicked setBoolValue:YES inComponent:[_ctx component]]; return nil; } - (void)_appendScriptWithID:(NSString *)scriptId label:(NSString *)label imageURL:(NSString *)img toResponse:(WOResponse *)_resp inContext:(WOContext *)_ctx { WOComponent *comp; NSString *openedImg = nil; NSString *closedImg = nil; NSString *openLabel = nil; NSString *closeLabel = nil; comp = [_ctx component]; closedImg = [self->closedImageFileName stringValueInComponent:comp]; openedImg = [self->openedImageFileName stringValueInComponent:comp]; openLabel = [self->openedLabel stringValueInComponent:comp]; closeLabel = [self->closedLabel stringValueInComponent:comp]; closedImg = WEUriOfResource(closedImg, _ctx); openedImg = WEUriOfResource(openedImg, _ctx); if (![_ctx objectForKey:WECollapsible_HasScript]) { [_resp appendContentString: @"\n\n"]; [_ctx setObject:Yes forKey:WECollapsible_HasScript]; } [_resp appendContentString:@""]; } - (void)_appendLinkWithFragmentID:(NSString *)fragId label:(NSString *)label imageURL:(NSString *)img isCollapsed:(BOOL)isCollapsed toResponse:(WOResponse *)_resp inContext:(WOContext *)_ctx { [_resp appendContentString:@""]; if (img != nil) { [_resp appendContentString:@"\""];"]; } else [_resp appendContentString:(isCollapsed) ? @"[+]" : @"[-]"]; [_resp appendContentString:@""]; } - (void)appendToResponse:(WOResponse *)_resp inContext:(WOContext *)_ctx { /* TODO: split up this huge method */ BOOL isCollapsed; BOOL doForm; BOOL doScript; WOComponent *comp; NSString *img = nil; NSString *label = nil; NSString *fragId = nil; NSString *scriptId = nil; comp = [_ctx component]; fragId = [self->fragmentIdentifier stringValueInComponent:comp]; isCollapsed = [[_ctx objectForKey:WECollapsible_IsCollapsed] boolValue]; scriptId = [_ctx objectForKey:WECollapsible_ScriptId]; doScript = [scriptId isNotEmpty] ? YES : NO; img = (isCollapsed) ? [self->closedImageFileName stringValueInComponent:comp] : [self->openedImageFileName stringValueInComponent:comp]; label = (isCollapsed) ? [self->closedLabel stringValueInComponent:comp] : [self->openedLabel stringValueInComponent:comp]; img = WEUriOfResource(img, _ctx); /* if (isCollapsed) [_resp appendContentString:@" "]; */ doForm = ([_ctx isInForm] && self->submitActionName && img); [_ctx appendElementIDComponent:(isCollapsed) ? @"c" : @"e"]; if (doScript) { [self _appendScriptWithID:scriptId label:label imageURL:img toResponse:_resp inContext:_ctx]; } else if (doForm) { [_resp appendContentString:@""]; } else { [self _appendLinkWithFragmentID:fragId label:label imageURL:img isCollapsed:isCollapsed toResponse:_resp inContext:_ctx]; } if (fragId) { WEClientCapabilities *ccaps; ccaps = [[_ctx request] clientCapabilities]; [_resp appendContentString:@" "]; if ([self->isClicked boolValueInComponent:comp] && ([ccaps isInternetExplorer] || [ccaps isMozilla] || [ccaps isNetscape6])) { if ([self->isClicked isValueSettable]) [self->isClicked setBoolValue:NO inComponent:comp]; [_resp appendContentString: [NSString stringWithFormat: @"\n\n", fragId]]; } } else [_resp appendContentString:@" "]; if (label && !doScript) { if (!doForm) { [_resp appendContentString:@""]; } [_resp appendContentString:label]; if (!doForm) [_resp appendContentString:@""]; } [_ctx deleteLastElementIDComponent]; } @end /* WECollapsibleAction */ @interface WECollapsibleTitleMode: WEContextConditional @end @implementation WECollapsibleTitleMode - (NSString *)_contextKey { return WECollapsible_TitleMode; } @end /* WECollapsibleTitleMode */ @interface WECollapsibleContentMode: WEContextConditional @end @implementation WECollapsibleContentMode - (NSString *)_contextKey { return WECollapsible_ContentMode; } @end /* WECollapsibleContentMode */