--- /dev/null
+/*
+ Copyright (C) 2000-2004 SKYRIX Software AG
+
+ This file is part of OpenGroupware.org.
+
+ OGo 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.
+
+ OGo 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 OGo; see the file COPYING. If not, write to the
+ Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA.
+*/
+// $Id$
+
+#include "UIxTabView.h"
+#include "common.h"
+
+#if DEBUG
+# define DEBUG_JS 1
+#endif
+
+/* context keys */
+extern NSString *UIxTabView_HEAD;
+extern NSString *UIxTabView_BODY;
+extern NSString *UIxTabView_KEYS;
+extern NSString *UIxTabView_SCRIPT;
+extern NSString *UIxTabView_ACTIVEKEY;
+extern NSString *UIxTabView_COLLECT;
+
+@implementation UIxTabItem
+
+static Class StrClass = Nil;
+
++ (int)version {
+ return [super version] + 0;
+}
++ (void)initialize {
+ StrClass = [NSString class];
+}
+
+static NSString *retStrForInt(int i) {
+ switch(i) {
+ case 0: return @"0";
+ case 1: return @"1";
+ case 2: return @"2";
+ case 3: return @"3";
+ case 4: return @"4";
+ case 5: return @"5";
+ case 6: return @"6";
+ case 7: return @"7";
+ case 8: return @"8";
+ case 9: return @"9";
+ case 10: return @"10";
+ // TODO: find useful count!
+ default:
+ return [[StrClass alloc] initWithFormat:@"%i", i];
+ }
+}
+
+- (id)initWithName:(NSString *)_name
+ associations:(NSDictionary *)_config
+ template:(WOElement *)_subs
+{
+ if ((self = [super initWithName:_name associations:_config template:_subs])) {
+ self->key = WOExtGetProperty(_config, @"key");
+ self->icon = WOExtGetProperty(_config, @"icon");
+ self->label = WOExtGetProperty(_config, @"label");
+ self->action = WOExtGetProperty(_config, @"action");
+ self->isScript = WOExtGetProperty(_config, @"isScript");
+
+ self->tabIcon = WOExtGetProperty(_config, @"tabIcon");
+ self->leftTabIcon = WOExtGetProperty(_config, @"leftTabIcon");
+ self->selectedTabIcon = WOExtGetProperty(_config, @"selectedTabIcon");
+
+ self->asBackground = WOExtGetProperty(_config, @"asBackground");
+ self->width = WOExtGetProperty(_config, @"width");
+ self->height = WOExtGetProperty(_config, @"height");
+ self->activeBgColor = WOExtGetProperty(_config, @"activeBgColor");
+ self->inactiveBgColor = WOExtGetProperty(_config, @"inactiveBgColor");
+
+ self->template = [_subs retain];
+ }
+ return self;
+}
+
+- (void)dealloc {
+ [self->action release];
+ [self->label release];
+ [self->icon release];
+ [self->key release];
+ [self->isScript release];
+ [self->template release];
+
+ [self->leftTabIcon release];
+ [self->selectedTabIcon release];
+ [self->tabIcon release];
+
+ [self->asBackground release];
+ [self->width release];
+ [self->height release];
+
+ [self->activeBgColor release];
+ [self->inactiveBgColor release];
+
+ [super dealloc];
+}
+
+/* responder */
+
+- (void)takeValuesFromRequest:(WORequest *)_rq inContext:(WOContext *)_ctx {
+ NSString *activeTabKey;
+ NSString *myTabKey;
+ BOOL doCheck;
+
+ if ([_ctx objectForKey:UIxTabView_HEAD]) {
+ /* head clicks */
+ [[_ctx component] debugWithFormat:
+ @"UIxTabItem: head takes (no) values, eid='%@'",
+ [_ctx elementID]];
+ return;
+ }
+
+ if ((activeTabKey = [_ctx objectForKey:UIxTabView_BODY]) == nil) {
+ [[_ctx component] debugWithFormat:@"UIxTabItem: invalid state"];
+ [self->template takeValuesFromRequest:_rq inContext:_ctx];
+ return;
+ }
+
+ myTabKey = [self->key stringValueInComponent:[_ctx component]];
+ doCheck = [self->isScript boolValueInComponent:[_ctx component]];
+
+ if ([activeTabKey isEqualToString:myTabKey] || doCheck) {
+#if ADD_OWN_ELEMENTIDS
+ [_ctx appendElementIDComponent:activeTabKey];
+#endif
+
+#if DEBUG_TAKEVALUES
+ [[_ctx component] debugWithFormat:
+ @"UIxTabItem: body takes values, eid='%@'",
+ [_ctx elementID]];
+#endif
+
+ [self->template takeValuesFromRequest:_rq inContext:_ctx];
+#if ADD_OWN_ELEMENTIDS
+ [_ctx deleteLastElementIDComponent];
+#endif
+ }
+#if DEBUG_TAKEVALUES
+ else {
+ [[_ctx component] debugWithFormat:
+ @"UIxTabItem: body takes no values, eid='%@'",
+ [_ctx elementID]];
+ }
+#endif
+}
+
+- (id)invokeActionForRequest:(WORequest *)_req inContext:(WOContext *)_ctx {
+ id result;
+ WOAssociation *tmp;
+ NSString *activeTabKey;
+
+ if ((tmp = [_ctx objectForKey:UIxTabView_HEAD])) {
+ /* click on tab icon */
+ NSString *tabkey;
+
+ tabkey = [_ctx currentElementID];
+ [_ctx consumeElementID];
+ [_ctx appendElementIDComponent:tabkey];
+
+ if ([tmp isValueSettable])
+ [tmp setValue:tabkey inComponent:[_ctx component]];
+
+ result = [self->action valueInComponent:[_ctx component]];
+
+ [_ctx deleteLastElementIDComponent];
+ }
+ else if ((activeTabKey = [_ctx objectForKey:UIxTabView_BODY])) {
+ /* clicked somewhere in the (active) body */
+ result = [self->template invokeActionForRequest:_req inContext:_ctx];
+ }
+ else {
+ [[_ctx component] logWithFormat:@"UIxTabItem: invalid invoke state"];
+ result = [self->template invokeActionForRequest:_req inContext:_ctx];
+ }
+
+ return result;
+}
+
+/* info collection */
+
+- (void)_collectInContext:(WOContext *)_ctx key:(NSString *)k {
+ BOOL isLeft = NO;
+ NSMutableArray *keys;
+ UIxTabItemInfo *info;
+ WOComponent *cmp;
+
+ cmp = [_ctx component];
+ keys = [_ctx objectForKey:UIxTabView_KEYS];
+ if (keys == nil) {
+ keys = [[[NSMutableArray alloc] init] autorelease];
+ [_ctx setObject:keys forKey:UIxTabView_KEYS];
+ isLeft = YES;
+ }
+
+ if (k == nil) {
+ /* auto-assign a key */
+ k = retStrForInt([keys count]);
+ }
+ else
+ k = [k retain];
+ [_ctx appendElementIDComponent:k];
+
+ info = [[UIxTabItemInfo alloc] init];
+ info->key = [k copy];
+ info->label = [[self->label stringValueInComponent:cmp] copy];
+ info->icon = [[self->icon stringValueInComponent:cmp] copy];
+ info->uri = [[_ctx componentActionURL] copy];
+ info->isScript = [self->isScript boolValueInComponent:cmp];
+ info->tabIcon = [[self->tabIcon stringValueInComponent:cmp] copy];
+ info->leftIcon = [[self->leftTabIcon stringValueInComponent:cmp] copy];
+ info->selIcon = [[self->selectedTabIcon stringValueInComponent:cmp]
+ copy];
+ if (self->asBackground == nil)
+ info->asBackground = 0;
+ else {
+ info->asBackground
+ = ([self->asBackground boolValueInComponent:cmp]) ? 1 : -1;
+ }
+ info->width = [[self->width stringValueInComponent:cmp] copy];
+ info->height = [[self->height stringValueInComponent:cmp] copy];
+ info->activeBg = [[self->activeBgColor stringValueInComponent:cmp]
+ copy];
+ info->inactiveBg = [[self->inactiveBgColor stringValueInComponent:cmp]
+ copy];
+
+ if (info->leftIcon == nil) info->leftIcon = [info->tabIcon copy];
+
+ [keys addObject:info];
+ [info release];
+ [k release];
+
+ [_ctx deleteLastElementIDComponent];
+}
+
+/* header generation */
+
+- (void)_appendHeadToResponse:(WOResponse *)_response
+ inContext:(WOContext *)_ctx
+ activeKey:(NSString *)activeKey
+ key:(NSString *)k
+{
+ /* head is currently generated in UIxTabView */
+#if 0
+ // note: some associations can be inherited by UIxTabView !
+ BOOL doImages;
+ WOComponent *comp;
+ BOOL doBgIcon;
+ NSString *label;
+ NSString *w, *h;
+
+ doImages = ![[[_ctx request] clientCapabilities] isTextModeBrowser];
+ comp = [_ctx component];
+
+ doBgIcon = self->asBackground && doImages
+ ? [self->asBackground boolValueInComponent:comp] ? YES : NO
+ : NO;
+
+ if ((label = [self->label stringValueInComponent:comp]) == nil)
+ label = k;
+
+ if (doImages) {
+ /* lookup image */
+ NSString *imgName = nil;
+ // ...
+
+ imgUri = WEUriOfResource(imgName, _ctx);
+ if ([imgUri length] < 1)
+ doImages = NO;
+ }
+
+ // .... _isActive
+#endif
+}
+
+/* body generation */
+
+- (void)_appendBodyToResponse:(WOResponse *)_response
+ inContext:(WOContext *)_ctx
+ activeKey:(NSString *)tmp
+ key:(NSString *)k
+{
+ BOOL doScript;
+ BOOL isScript_;
+ BOOL isActive;
+
+ doScript = [[_ctx objectForKey:UIxTabView_SCRIPT] boolValue];
+ isScript_ = [self->isScript boolValueInComponent:[_ctx component]];
+ isActive = [tmp isEqualToString:k];
+
+ if (doScript && (isActive || isScript_)) {
+ [_response appendContentString:@"<div id=\""];
+ [_response appendContentString:k];
+ [_response appendContentString:@"TabLayer\" style=\"display: none;\">\n"];
+ }
+
+ if (isActive || (doScript && isScript_)) {
+ /* content is active or used as layer*/
+#if ADD_OWN_ELEMENTIDS
+ [_ctx appendElementIDComponent:k];
+#endif
+#if DEBUG && 0
+ NSLog(@"TAB: %@", k);
+#endif
+
+ [self->template appendToResponse:_response inContext:_ctx];
+
+#if ADD_OWN_ELEMENTIDS
+ [_ctx deleteLastElementIDComponent];
+#endif
+ }
+
+ if (doScript && (isActive || isScript_)) {
+ NSString *jsout;
+ [_response appendContentString:@"</div>"];
+
+ jsout = [NSString alloc];
+ jsout = [jsout initWithFormat:
+ @"<script language=\"JavaScript\">\n<!--\n"
+ @"%@Tab[\"Div\"] = %@TabLayer;\n",
+ k, k];
+
+ [_response appendContentString:jsout];
+ [jsout release];
+
+#if DEBUG_JS
+ jsout = [NSString alloc];
+ jsout = [jsout initWithFormat:
+ @"if (%@Tab[\"Div\"].style==null) {"
+ @"alert('missing style in div for tab %@');}",
+ k, k];
+
+ [_response appendContentString:jsout];
+ [jsout release];
+#endif
+
+ if (isActive) {
+ [_response appendContentString:@"showTab("];
+ [_response appendContentString:k];
+ [_response appendContentString:@"Tab);\n"];
+ }
+ [_response appendContentString:@"//-->\n</script>"];
+ }
+}
+
+/* master generation method */
+
+- (void)appendToResponse:(WOResponse *)_response inContext:(WOContext *)_ctx {
+ NSString *k;
+ BOOL doForm;
+ id tmp;
+
+ doForm = [_ctx isInForm];
+ k = [self->key stringValueInComponent:[_ctx component]];
+
+ if ((tmp = [_ctx objectForKey:UIxTabView_HEAD])) {
+ if ([tmp isEqual:UIxTabView_COLLECT]) {
+ [self _collectInContext:_ctx key:k];
+ }
+ else {
+ [self _appendHeadToResponse:_response inContext:_ctx
+ activeKey:tmp key:k];
+ }
+ }
+ else if ((tmp = [_ctx objectForKey:UIxTabView_BODY])) {
+ [self _appendBodyToResponse:_response inContext:_ctx
+ activeKey:tmp key:k];
+ }
+ else {
+ NSLog(@"WARNING(%s): invalid UIxTabItem state !!!", __PRETTY_FUNCTION__);
+ [_response appendContentString:@"[invalid state]"];
+ }
+}
+
+@end /* UIxTabItem */
+
+@implementation UIxTabItemInfo
+
+- (void)dealloc {
+ [self->uri release];
+ [self->icon release];
+ [self->label release];
+ [self->key release];
+ [self->tabStyle release];
+ [self->selectedTabStyle release];
+ [self->tabIcon release];
+ [self->selIcon release];
+ [self->leftIcon release];
+ [self->width release];
+ [self->height release];
+ [self->activeBg release];
+ [self->inactiveBg release];
+
+ [super dealloc];
+}
+
+/* accessors */
+
+- (NSString *)key {
+ return self->key;
+}
+- (NSString *)label {
+ return self->label;
+}
+- (NSString *)icon {
+ return self->icon;
+}
+- (NSString *)uri {
+ return self->uri;
+}
+- (BOOL)isScript {
+ return self->isScript;
+}
+
+- (int)asBackground {
+ return self->asBackground;
+}
+
+- (NSString *)width {
+ return self->width;
+}
+
+- (NSString *)height {
+ return self->height;
+}
+
+- (NSString *)activeBg {
+ return self->activeBg;
+}
+
+- (NSString *)inactiveBg {
+ return self->inactiveBg;
+}
+
+@end /* UIxTabItemInfo */
--- /dev/null
+/*
+ Copyright (C) 2000-2004 SKYRIX Software AG
+
+ This file is part of OpenGroupware.org.
+
+ OGo 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.
+
+ OGo 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 OGo; see the file COPYING. If not, write to the
+ Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA.
+*/
+// $Id$
+
+#include "UIxTabView.h"
+#include "common.h"
+#import <NGObjWeb/NGObjWeb.h>
+#import <NGExtensions/NGExtensions.h>
+#import <EOControl/EOControl.h>
+#include <WEExtensions/WEClientCapabilities.h>
+
+#if DEBUG
+// # define DEBUG_TAKEVALUES 1
+# define DEBUG_JS 1
+#endif
+
+/* context keys */
+NSString *UIxTabView_HEAD = @"UIxTabView_head";
+NSString *UIxTabView_BODY = @"UIxTabView_body";
+NSString *UIxTabView_KEYS = @"UIxTabView_keys";
+NSString *UIxTabView_SCRIPT = @"UIxTabView_script";
+NSString *UIxTabView_ACTIVEKEY = @"UIxTabView_activekey";
+NSString *UIxTabView_COLLECT = @"~tv~";
+
+@implementation UIxTabView
+
+static NSNumber *YesNumber;
+
++ (void)initialize {
+ if (YesNumber == nil)
+ YesNumber = [[NSNumber numberWithBool:YES] retain];
+}
+
++ (int)version {
+ return [super version] + 0;
+}
+
+- (id)initWithName:(NSString *)_name
+ associations:(NSDictionary *)_config
+ template:(WOElement *)_subs
+{
+ if ((self = [super initWithName:_name associations:_config template:_subs])) {
+ self->selection = WOExtGetProperty(_config, @"selection");
+
+ self->headerStyle = WOExtGetProperty(_config, @"headerStyle");
+ self->tabStyle = WOExtGetProperty(_config, @"tabStyle");
+ self->selectedTabStyle = WOExtGetProperty(_config, @"selectedTabStyle");
+
+ self->bgColor = WOExtGetProperty(_config, @"bgColor");
+ self->nonSelectedBgColor = WOExtGetProperty(_config, @"nonSelectedBgColor");
+ self->leftCornerIcon = WOExtGetProperty(_config, @"leftCornerIcon");
+ self->rightCornerIcon = WOExtGetProperty(_config, @"rightCornerIcon");
+
+ self->tabIcon = WOExtGetProperty(_config, @"tabIcon");
+ self->leftTabIcon = WOExtGetProperty(_config, @"leftTabIcon");
+ self->selectedTabIcon = WOExtGetProperty(_config, @"selectedTabIcon");
+
+ self->asBackground = WOExtGetProperty(_config, @"asBackground");
+ self->width = WOExtGetProperty(_config, @"width");
+ self->height = WOExtGetProperty(_config, @"height");
+ self->activeBgColor = WOExtGetProperty(_config, @"activeBgColor");
+ self->inactiveBgColor = WOExtGetProperty(_config, @"inactiveBgColor");
+
+ self->fontColor = WOExtGetProperty(_config, @"fontColor");
+ self->fontSize = WOExtGetProperty(_config, @"fontSize");
+ self->fontFace = WOExtGetProperty(_config, @"fontFace");
+
+ NSLog(@"%s foobar", __PRETTY_FUNCTION__);
+ self->template = RETAIN(_subs);
+ }
+ return self;
+}
+
+- (void)dealloc {
+ [self->selection release];
+
+ [self->headerStyle release];
+ [self->tabStyle release];
+ [self->selectedTabStyle release];
+
+ RELEASE(self->bgColor);
+ RELEASE(self->nonSelectedBgColor);
+ RELEASE(self->leftCornerIcon);
+ RELEASE(self->rightCornerIcon);
+
+ RELEASE(self->leftTabIcon);
+ RELEASE(self->selectedTabIcon);
+ RELEASE(self->tabIcon);
+
+ RELEASE(self->width);
+ RELEASE(self->height);
+
+ RELEASE(self->activeBgColor);
+ RELEASE(self->inactiveBgColor);
+
+ RELEASE(self->fontColor);
+ RELEASE(self->fontSize);
+ RELEASE(self->fontFace);
+
+ RELEASE(self->template);
+ [super dealloc];
+}
+
+/* nesting */
+
+- (id)saveNestedStateInContext:(WOContext *)_ctx {
+ return nil;
+}
+- (void)restoreNestedState:(id)_state inContext:(WOContext *)_ctx {
+ if (_state == nil) return;
+}
+
+- (NSArray *)collectKeysInContext:(WOContext *)_ctx {
+ /* collect mode, collects all keys */
+ [_ctx setObject:UIxTabView_COLLECT forKey:UIxTabView_HEAD];
+
+ [self->template appendToResponse:nil inContext:_ctx];
+
+ [_ctx removeObjectForKey:UIxTabView_HEAD];
+ return [_ctx objectForKey:UIxTabView_KEYS];
+}
+
+/* responder */
+
+- (void)takeValuesFromRequest:(WORequest *)_req inContext:(WOContext *)_ctx {
+ id nestedState;
+ NSString *activeTabKey;
+
+ activeTabKey = [self->selection stringValueInComponent:[_ctx component]];
+
+ nestedState = [self saveNestedStateInContext:_ctx];
+ [_ctx appendElementIDComponent:@"b"];
+ [_ctx appendElementIDComponent:activeTabKey];
+
+ [_ctx setObject:activeTabKey forKey:UIxTabView_BODY];
+
+#if DEBUG_TAKEVALUES
+ [[_ctx component] debugWithFormat:@"UIxTabView: body takes values, eid='%@'",
+ [_ctx elementID]];
+#endif
+
+ [self->template takeValuesFromRequest:_req inContext:_ctx];
+
+ [_ctx removeObjectForKey:UIxTabView_BODY];
+ [_ctx deleteLastElementIDComponent]; // activeKey
+ [_ctx deleteLastElementIDComponent]; /* 'b' */
+ [self restoreNestedState:nestedState inContext:_ctx];
+}
+
+- (id)invokeActionForRequest:(WORequest *)_req inContext:(WOContext *)_ctx {
+ NSString *key;
+ id result;
+ id nestedState;
+
+ if ((key = [_ctx currentElementID]) == nil)
+ return nil;
+
+ result = nil;
+ nestedState = [self saveNestedStateInContext:_ctx];
+
+ if ([key isEqualToString:@"h"]) {
+ /* header action */
+ //NSString *urlKey;
+
+ [_ctx consumeElementID];
+ [_ctx appendElementIDComponent:@"h"];
+#if 0
+ if ((urlKey = [_ctx currentElementID]) == nil) {
+ [[_ctx application]
+ debugWithFormat:@"missing active head tab key !"];
+ }
+ else {
+ //NSLog(@"clicked: %@", urlKey);
+ [_ctx consumeElementID];
+ [_ctx appendElementIDComponent:urlKey];
+ }
+#endif
+
+ [_ctx setObject:self->selection forKey:UIxTabView_HEAD];
+ result = [self->template invokeActionForRequest:_req inContext:_ctx];
+ [_ctx removeObjectForKey:UIxTabView_HEAD];
+
+#if 0
+ if (urlKey)
+ [_ctx deleteLastElementIDComponent]; // active key
+#endif
+ [_ctx deleteLastElementIDComponent]; // 'h'
+ }
+ else if ([key isEqualToString:@"b"]) {
+ /* body action */
+ NSString *activeTabKey, *urlKey;
+
+ [_ctx consumeElementID];
+ [_ctx appendElementIDComponent:@"b"];
+
+ if ((urlKey = [_ctx currentElementID]) == nil) {
+ [[_ctx application]
+ debugWithFormat:@"missing active body tab key !"];
+ }
+ else {
+ //NSLog(@"clicked: %@", urlKey);
+ [_ctx consumeElementID];
+ [_ctx appendElementIDComponent:urlKey];
+ }
+
+ activeTabKey = [self->selection stringValueInComponent:[_ctx component]];
+ [_ctx setObject:activeTabKey forKey:UIxTabView_BODY];
+
+ result = [self->template invokeActionForRequest:_req inContext:_ctx];
+
+ [_ctx removeObjectForKey:UIxTabView_BODY];
+
+ if (urlKey)
+ [_ctx deleteLastElementIDComponent]; // active key
+ [_ctx deleteLastElementIDComponent]; // 'b'
+ }
+ else {
+ [[_ctx application]
+ debugWithFormat:@"unknown tab container key '%@'", key];
+ }
+
+ [self restoreNestedState:nestedState inContext:_ctx];
+ return result;
+}
+
+- (NSString *)_tabViewCountInContext:(WOContext *)_ctx {
+ int count;
+ count = [[_ctx valueForKey:@"UIxTabViewScriptDone"] intValue];
+ return [NSString stringWithFormat:@"%d",count];
+}
+
+- (NSString *)scriptHref:(UIxTabItemInfo *)_info
+ inContext:(WOContext *)_ctx
+ isLeft:(BOOL)_isLeft
+ keys:(NSArray *)_keys
+{
+ NSMutableString *result = [NSMutableString string];
+ UIxTabItemInfo *tmp;
+ NSString *activeKey;
+ int i, cnt;
+ NSString *elID;
+ NSString *tstring;
+
+ activeKey = [self->selection stringValueInComponent:[_ctx component]];
+ [result appendString:@"JavaScript:showTab("];
+ [result appendString:_info->key];
+ [result appendString:@"Tab);"];
+
+ [result appendString:@"swapCorners("];
+ tstring = (!_isLeft)
+ ? @"tabCorner%@,tabCornerLeft%@);"
+ : @"tabCornerLeft%@,tabCorner%@);";
+ elID = [self _tabViewCountInContext:_ctx];
+ [result appendString:[NSString stringWithFormat:tstring,elID,elID]];
+
+ for (i=0, cnt = [_keys count]; i < cnt; i++) {
+ tmp = [_keys objectAtIndex:i];
+
+ if ((tmp->isScript || [tmp->key isEqualToString:activeKey])
+ && ![tmp->key isEqualToString:_info->key]) {
+ [result appendString:@"hideTab("];
+ [result appendString:tmp->key];
+ [result appendString:@"Tab);"];
+ }
+ }
+ return result;
+}
+
+- (void)appendLink:(UIxTabItemInfo *)_info
+ toResponse:(WOResponse *)_response
+ inContext:(WOContext *)_ctx
+ isActive:(BOOL)_isActive isLeft:(BOOL)_isLeft
+ doScript:(BOOL)_doScript keys:(NSArray *)_keys
+{
+ BOOL doBgIcon;
+ BOOL doImages;
+ NSString *headUri = nil;
+ NSString *imgUri = nil;
+ NSString *label = nil;
+ NSString *bgcolor = nil;
+ NSString *w = nil;
+ NSString *h = nil;
+ NSString *scriptHref = nil;
+ NSString *styleName = nil;
+
+ WOComponent *comp;
+
+ doImages = ![[[_ctx request] clientCapabilities] isTextModeBrowser];
+
+ comp = [_ctx component];
+ headUri = _info->uri;
+
+ if (_info->asBackground == 0)
+ doBgIcon = [self->asBackground boolValueInComponent:comp];
+ else
+ doBgIcon = (_info->asBackground == 1) ? YES : NO;
+
+ if ((label = _info->label) == nil)
+ label = _info->key;
+
+ if (doImages) {
+ /* lookup image */
+ NSString *imgName = nil;
+
+ if (_isActive) {
+ imgName = _info->selIcon; // selectedTabIcon
+ if (imgName == nil)
+ imgName = [self->selectedTabIcon stringValueInComponent:comp];
+ }
+ else if (_isLeft) {
+ imgName = _info->leftIcon; // leftTabIcon
+ if (imgName == nil)
+ imgName = [self->leftTabIcon stringValueInComponent:comp];
+ }
+ else {
+ imgName = _info->tabIcon; // tabIcon
+ if (imgName == nil)
+ imgName = [self->tabIcon stringValueInComponent:comp];
+ }
+
+ if (imgName == nil) {
+ imgName = _info->icon;
+ }
+
+ imgUri = WEUriOfResource(imgName, _ctx);
+
+ if ([imgUri length] < 1)
+ doImages = NO;
+ }
+
+ if (_isActive) {
+ bgcolor = (_info->activeBg)
+ ? _info->activeBg
+ : [self->activeBgColor stringValueInComponent:comp];
+ styleName = (_info->selectedTabStyle)
+ ? _info->selectedTabStyle
+ : [self->selectedTabStyle stringValueInComponent:comp];
+ }
+ else {
+ bgcolor = (_info->inactiveBg)
+ ? _info->inactiveBg
+ : [self->inactiveBgColor stringValueInComponent:comp];
+ styleName = (_info->tabStyle)
+ ? _info->tabStyle
+ : [self->tabStyle stringValueInComponent:comp];
+ }
+
+ w = (_info->width)
+ ? _info->width
+ : [self->width stringValueInComponent:comp];
+ h = (_info->height)
+ ? _info->height
+ : [self->height stringValueInComponent:comp];
+
+ [_response appendContentString:@"<td align='center' valign='middle'"];
+
+ if (w) {
+ [_response appendContentString:@" width='"];
+ [_response appendContentHTMLAttributeValue:w];
+ [_response appendContentCharacter:'\''];
+ }
+ if (h) {
+ [_response appendContentString:@" height='"];
+ [_response appendContentHTMLAttributeValue:h];
+ [_response appendContentCharacter:'\''];
+ }
+ if (bgcolor) {
+ [_response appendContentString:@" bgcolor='"];
+ [_response appendContentHTMLAttributeValue:bgcolor];
+ [_response appendContentCharacter:'\''];
+ }
+ if (styleName) {
+ [_response appendContentString:@" class='"];
+ [_response appendContentHTMLAttributeValue:styleName];
+ [_response appendContentCharacter:'\''];
+ }
+ if (doBgIcon && doImages) {
+ WEClientCapabilities *ccaps;
+
+ ccaps = [[_ctx request] clientCapabilities];
+
+ [_response appendContentString:@" background='"];
+ [_response appendContentHTMLAttributeValue:imgUri];
+ [_response appendContentCharacter:'\''];
+
+ // click on td background
+ if ([ccaps isInternetExplorer] && [ccaps isJavaScriptBrowser]) {
+ [_response appendContentString:@" onclick=\"window.location.href='"];
+ [_response appendContentHTMLAttributeValue:headUri];
+ [_response appendContentString:@"'\""];
+ }
+ }
+
+ [_response appendContentCharacter:'>'];
+
+ if (!doImages) [_response appendContentString:@"["];
+
+ [_response appendContentString:@"<a style=\"text-decoration:none;\" href=\""];
+
+ if (_doScript && doImages && (_info->isScript || _isActive)) {
+ scriptHref =
+ [self scriptHref:_info inContext:_ctx isLeft:_isLeft keys:_keys];
+ [_response appendContentHTMLAttributeValue:scriptHref];
+ }
+ else {
+ [_response appendContentHTMLAttributeValue:headUri];
+ }
+
+ [_response appendContentString:@"\" "];
+ [_response appendContentString:
+ [NSString stringWithFormat:@"name='%@TabLink'", _info->key]];
+ [_response appendContentString:@">"];
+
+ if (!doImages && _isActive)
+ [_response appendContentString:@"<b>"];
+
+ if (doImages && !doBgIcon) {
+ [_response appendContentString:@"<img border='0' src='"];
+ [_response appendContentString:imgUri];
+ [_response appendContentString:@"' name='"];
+ [_response appendContentString:_info->key];
+ [_response appendContentString:@"TabImg' alt='"];
+ [_response appendContentHTMLAttributeValue:label];
+ [_response appendContentString:@"' title='"];
+ [_response appendContentHTMLAttributeValue:label];
+ [_response appendContentString:@"'"];
+ [_response appendContentString:@" />"];
+ }
+ else {
+ NSString *fc = [self->fontColor stringValueInComponent:comp];
+ NSString *fs = [self->fontSize stringValueInComponent:comp];
+ NSString *ff = [self->fontFace stringValueInComponent:comp];
+ BOOL hasFont;
+
+ hasFont = (fc || fs || ff) ? YES : NO;
+
+ if ([label length] < 1)
+ label = _info->key;
+ [_response appendContentString:@"<nobr>"];
+ if (hasFont) WEAppendFont(_response, fc, ff, fs); // <font>
+
+ if (_isActive) [_response appendContentString:@"<b>"];
+ [_response appendContentHTMLString:label];
+ if (_isActive) [_response appendContentString:@"</b>"];
+
+ if (hasFont) [_response appendContentString:@"</font>"]; // </font>
+ [_response appendContentString:@"</nobr>"];
+ }
+
+ if (!doImages && _isActive)
+ [_response appendContentString:@"</b>"];
+
+ [_response appendContentString:@"</a>"];
+ if (!doImages) [_response appendContentString:@"]"];
+
+
+ [_response appendContentString:@"</td>"];
+
+ if (_doScript && doImages && (_info->isScript || _isActive)) {
+ NSString *k; // key
+ NSString *s; // selected tab icon
+ NSString *u; // unselected tab icon
+ //NSString *out;
+
+ k = _info->key;
+ s = _info->selIcon; // selectedTabIcon
+ u = (_isLeft) ? _info->leftIcon : _info->tabIcon;
+
+ s = WEUriOfResource(s, _ctx);
+ u = WEUriOfResource(u, _ctx);
+
+ s = ([s length] < 1) ? imgUri : s;
+ u = ([u length] < 1) ? imgUri : u;
+
+#if 0
+ out = [NSString alloc];
+ out = [out initWithFormat:
+ @"<script language=\"JavaScript\">\n"
+ @"<!--\n"
+ @"var %@Tab = new Array();\n"
+ @"%@Tab[\"link\"] = %@TabLink;\n"
+ @"%@Tab[\"href1\"] = \"%@\";\n"
+ @"%@Tab[\"href2\"] = \"%@\";\n"
+ @"%@Tab[\"Img\"] = window.document.%@TabImg;\n"
+ @"%@Tab[\"Ar\"] = new Array();\n"
+ @"%@Tab[\"Ar\"][0] = new Image();\n"
+ @"%@Tab[\"Ar\"][0].src = \"%@\";\n"
+ @"%@Tab[\"Ar\"][1] = new Image();\n"
+ @"%@Tab[\"Ar\"][1].src = \"%@\";\n"
+ @"//-->\n</script>",
+ k, k, k, k, scriptHref, k, headUri,
+ k, k, k, k,
+ k, u, k, k, s
+ ];
+
+ [_response appendContentString:out];
+ RELEASE(out);
+#else
+# define _appendStr_(_str_) [_response appendContentString:_str_]
+ _appendStr_(@"<script language=\"JavaScript\">\n<!--\nvar ");
+ _appendStr_(k); _appendStr_(@"Tab = new Array();\n");
+
+ _appendStr_(k); _appendStr_(@"Tab[\"link\"] = ");
+ _appendStr_(k); _appendStr_(@"TabLink;\n"); // linkName
+
+ _appendStr_(k); _appendStr_(@"Tab[\"href1\"] = \"");
+ _appendStr_(scriptHref); _appendStr_(@"\";\n"); // scriptHref
+
+ _appendStr_(k); _appendStr_(@"Tab[\"href2\"] = \"");
+ _appendStr_(_info->uri); _appendStr_(@"\";\n"); // actionHref
+
+ _appendStr_(k); _appendStr_(@"Tab[\"Img\"] = window.document.");
+ _appendStr_(k); _appendStr_(@"TabImg;\n");
+ _appendStr_(k); _appendStr_(@"Tab[\"Ar\"] = new Array();\n");
+ _appendStr_(k); _appendStr_(@"Tab[\"Ar\"][0] = new Image();\n");
+ _appendStr_(k); _appendStr_(@"Tab[\"Ar\"][0].src = \"");
+ _appendStr_(u); _appendStr_(@"\";\n"); // unselected img
+ _appendStr_(k); _appendStr_(@"Tab[\"Ar\"][1] = new Image();\n");
+ _appendStr_(k); _appendStr_(@"Tab[\"Ar\"][1].src = \"");
+ _appendStr_(s); _appendStr_(@"\";\n"); // selected img
+ _appendStr_(@"//-->\n</script>");
+#undef _appendStr_
+#endif
+ }
+}
+
+- (void)appendSubmitButton:(UIxTabItemInfo *)_info
+ toResponse:(WOResponse *)_response
+ inContext:(WOContext *)_ctx
+ isActive:(BOOL)_isActive isLeft:(BOOL)_left
+ doScript:(BOOL)_doScript keys:(NSArray *)_keys
+{
+ [self appendLink:_info
+ toResponse:_response
+ inContext:_ctx
+ isActive:_isActive isLeft:_left
+ doScript:_doScript keys:_keys];
+}
+
+- (void)_appendTabViewJSScriptToResponse:(WOResponse *)_response
+ inContext:(WOContext *)_ctx
+{
+ [_response appendContentString:
+ @"<script language=\"JavaScript\">\n<!--\n\n"
+ @"function showTab(obj) {\n"
+#if DEBUG_JS
+ @" if (obj==null) { alert('missing tab obj ..'); return; }\n"
+ @" if (obj['Div']==null) {"
+ @" alert('missing div key in ' + obj); return; }\n"
+ @" if (obj['Div'].style==null) {"
+ @" alert('missing style key in div ' + obj['Div']);return; }\n"
+#endif
+ @" obj['Div'].style.display = \"\";\n"
+ @" obj['Img'].src = obj[\"Ar\"][1].src;\n"
+ @" obj['link'].href = obj[\"href2\"];\n"
+ @"}\n"
+ @"function hideTab(obj) {\n"
+#if DEBUG_JS
+ @" if (obj==null) { alert('missing tab obj ..'); return; }\n"
+ @" if (obj['Div']==null) {"
+ @" alert('missing div key in ' + obj); return; }\n"
+ @" if (obj['Div'].style==null) {"
+ @" alert('missing style key in div ' + obj['Div']);return; }\n"
+#endif
+ @" obj['Div'].style.display = \"none\";\n"
+ @" obj['Img'].src = obj[\"Ar\"][0].src;\n"
+ @" obj['link'].href = obj[\"href1\"];\n"
+ @"}\n"
+ @"function swapCorners(obj1,obj2) {\n"
+ @" if (obj1==null) { alert('missing corner 1'); return; }\n"
+ @" if (obj2==null) { alert('missing corner 2'); return; }\n"
+ @" obj1.style.display = \"none\";\n"
+ @" obj2.style.display = \"\";\n"
+ @"}\n"
+ @"//-->\n</script>"];
+}
+
+- (void)_appendHeaderRowToResponse:(WOResponse *)_response
+ inContext:(WOContext *)_ctx
+ keys:(NSArray *)keys activeKey:(NSString *)activeKey
+ doScript:(BOOL)doScript
+{
+ unsigned i, count;
+ BOOL doForm;
+
+ doForm = NO; /* generate form controls ? */
+
+ [_response appendContentString:@"<tr><td colspan='2'>"];
+ [_response appendContentString:
+ @"<table border='0' cellpadding='0' cellspacing='0'><tr>"];
+
+ for (i = 0, count = [keys count]; i < count; i++) {
+ UIxTabItemInfo *info;
+ NSString *key;
+ BOOL isActive;
+
+ info = [keys objectAtIndex:i];
+ key = info->key;
+ isActive = [key isEqualToString:activeKey];
+
+ [_ctx appendElementIDComponent:key];
+
+ if (doForm) {
+ /* tab is inside of a FORM, so produce submit buttons */
+ [self appendSubmitButton:info
+ toResponse:_response
+ inContext:_ctx
+ isActive:isActive
+ isLeft:(i == 0) ? YES : NO
+ doScript:doScript
+ keys:keys];
+ }
+ else {
+ /* tab is not in a FORM, generate hyperlinks for tab */
+ [self appendLink:info
+ toResponse:_response
+ inContext:_ctx
+ isActive:isActive
+ isLeft:(i == 0) ? YES : NO
+ doScript:doScript
+ keys:keys];
+ }
+
+ [_ctx deleteLastElementIDComponent];
+ }
+ // [_response appendContentString:@"<td></td>"];
+ [_response appendContentString:@"</tr></table>"];
+ [_response appendContentString:@"</td></tr>"];
+}
+
+- (void)_appendHeaderFootRowToResponse:(WOResponse *)_response
+ inContext:(WOContext *)_ctx
+ bgcolor:(NSString *)bgcolor
+ doScript:(BOOL)doScript
+ isLeftActive:(BOOL)isLeftActive
+{
+ [_response appendContentString:@" <tr"];
+ if (bgcolor) {
+ [_response appendContentString:@" bgcolor=\""];
+ [_response appendContentHTMLAttributeValue:bgcolor];
+ [_response appendContentString:@"\""];
+ }
+ [_response appendContentString:@">\n"];
+
+ /* left corner */
+ [_response appendContentString:@" <td align=\"left\" width=\"10\">"];
+
+ if (doScript) {
+ [_response appendContentString:@"<div id=\"tabCorner"];
+ [_response appendContentString:[self _tabViewCountInContext:_ctx]];
+ [_response appendContentString:@"\" "];
+ [_response appendContentString:@"style=\"display: "];
+ [_response appendContentString:(isLeftActive) ? @"" : @"none"];
+ [_response appendContentString:@";\">"];
+ [_response appendContentString:@" "];
+ [_response appendContentString:@"</div>"];
+ }
+ else if (isLeftActive)
+ [_response appendContentString:@" "];
+
+ if (doScript) {
+ [_response appendContentString:@"<div id=\"tabCornerLeft"];
+ [_response appendContentString:[self _tabViewCountInContext:_ctx]];
+ [_response appendContentString:@"\" "];
+ [_response appendContentString:@"style=\"display: "];
+ [_response appendContentString:(!isLeftActive) ? @"visible" : @"none"];
+ [_response appendContentString:@";\">"];
+ }
+
+ if (!isLeftActive || doScript) {
+ NSString *uri;
+
+ uri = [self->leftCornerIcon stringValueInComponent:[_ctx component]];
+ if ((uri = WEUriOfResource(uri, _ctx))) {
+ [_response appendContentString:@"<img border=\"0\" alt=\"\" src=\""];
+ [_response appendContentString:uri];
+ [_response appendContentString:@"\">"];
+ }
+ else
+ [_response appendContentString:@" "];
+ }
+ if (doScript)
+ [_response appendContentString:@"</div>"];
+
+ [_response appendContentString:@"</td>\n"];
+
+ /* right corner */
+ [_response appendContentString:@" <td align=\"right\">"];
+ {
+ NSString *uri;
+
+ uri = [self->rightCornerIcon stringValueInComponent:[_ctx component]];
+ if ((uri = WEUriOfResource(uri, _ctx))) {
+ [_response appendContentString:@"<img border=\"0\" alt=\"\" src=\""];
+ [_response appendContentString:uri];
+ [_response appendContentString:@"\" />"];
+ }
+ else
+ [_response appendContentString:@" "];
+ }
+ [_response appendContentString:@"</td>\n"];
+
+ [_response appendContentString:@" </tr>\n"];
+}
+
+- (void)_appendBodyRowToResponse:(WOResponse *)_response
+ inContext:(WOContext *)_ctx
+ bgcolor:(NSString *)bgcolor
+ activeKey:(NSString *)activeKey
+{
+ WEClientCapabilities *ccaps;
+ BOOL indentContent;
+
+ ccaps = [[_ctx request] clientCapabilities];
+
+ /* put additional padding table into content ??? */
+ indentContent = [ccaps isFastTableBrowser] && ![ccaps isTextModeBrowser];
+
+ [_response appendContentString:@"<tr><td colspan='2'"];
+
+ if (bgcolor) {
+ [_response appendContentString:@" bgcolor=\""];
+ [_response appendContentHTMLAttributeValue:bgcolor];
+ [_response appendContentString:@"\""];
+ }
+ [_response appendContentString:@">"];
+
+ if (indentContent) {
+ /* start padding table */
+ [_response appendContentString:
+ @"<table border='0' width='100%'"
+ @" cellpadding='10' cellspacing='0'>"];
+ [_response appendContentString:@"<tr><td>"];
+ }
+
+ [_ctx appendElementIDComponent:@"b"];
+ [_ctx appendElementIDComponent:activeKey];
+
+ /* generate currently active body */
+ {
+ [_ctx setObject:activeKey forKey:UIxTabView_BODY];
+ [self->template appendToResponse:_response inContext:_ctx];
+ [_ctx removeObjectForKey:UIxTabView_BODY];
+ }
+
+ [_ctx deleteLastElementIDComponent]; // activeKey
+ [_ctx deleteLastElementIDComponent]; // 'b'
+
+ if (indentContent)
+ /* close padding table */
+ [_response appendContentString:@"</td></tr></table>"];
+
+ [_response appendContentString:@"</td></tr>"];
+}
+
+- (BOOL)isLeftActiveInKeys:(NSArray *)keys activeKey:(NSString *)activeKey{
+ unsigned i, count;
+ BOOL isLeftActive;
+
+ isLeftActive = NO;
+
+ for (i = 0, count = [keys count]; i < count; i++) {
+ UIxTabItemInfo *info;
+
+ info = [keys objectAtIndex:i];
+
+ if ((i == 0) && [info->key isEqualToString:activeKey])
+ isLeftActive = YES;
+ }
+
+ return isLeftActive;
+}
+
+- (void)appendToResponse:(WOResponse *)_response inContext:(WOContext *)_ctx {
+ WOComponent *cmp;
+ NSString *bgcolor;
+ BOOL isLeftActive;
+ BOOL doScript;
+ id nestedState;
+ NSString *activeKey;
+ NSArray *keys;
+ int tabViewCount; /* used for image id's and writing script once */
+
+ doScript = NO; /* perform tab-clicks on browser (use javascript) */
+ tabViewCount = [[_ctx valueForKey:@"UIxTabViewScriptDone"] intValue];
+ cmp = [_ctx component];
+
+ /* check for browser */
+ {
+ WEClientCapabilities *ccaps;
+ //BOOL isJavaScriptBrowser;
+
+ ccaps = [[_ctx request] clientCapabilities];
+ doScript = [ccaps isInternetExplorer] && [ccaps isJavaScriptBrowser];
+ doScript = (doScript &&
+ [[[cmp session]
+ valueForKey:@"isJavaScriptEnabled"] boolValue]);
+ }
+
+ /* disable javascript */
+ doScript = NO;
+
+ /* save state */
+
+ nestedState = [self saveNestedStateInContext:_ctx];
+
+ /* configure */
+
+ activeKey = [self->selection stringValueInComponent:cmp];
+
+ bgcolor = [self->bgColor stringValueInComponent:cmp];
+ bgcolor = [bgcolor stringValue];
+
+ [_ctx appendElementIDComponent:@"h"];
+
+ /* collect & process keys (= available tabs) */
+
+ keys = [self collectKeysInContext:_ctx];
+
+ if (![[keys valueForKey:@"key"] containsObject:activeKey])
+ /* selection is not available in keys */
+ activeKey = nil;
+
+ if ((activeKey == nil) && ([keys count] > 0)) {
+ /* no or invalid selection, use first key */
+ activeKey = [[keys objectAtIndex:0] key];
+ if ([self->selection isValueSettable])
+ [self->selection setValue:activeKey inComponent:[_ctx component]];
+ }
+
+ if (doScript) {
+ doScript = [[keys valueForKey:@"isScript"] containsObject:YesNumber];
+ [_ctx setObject:[NSNumber numberWithBool:doScript]
+ forKey:UIxTabView_SCRIPT];
+ }
+
+ /* start appending */
+
+ if ((doScript) && (tabViewCount == 0))
+ [self _appendTabViewJSScriptToResponse:_response inContext:_ctx];
+
+ /* count up for unique tabCorner/tabCornerLeft images */
+ [_ctx takeValue:[NSNumber numberWithInt:(tabViewCount + 1)]
+ forKey:@"UIxTabViewScriptDone"];
+
+ [_response appendContentString:
+ @"<table border='0' width='100%'"
+ @" cellpadding='0' cellspacing='0'>"];
+
+ /* find out whether left is active */
+
+ isLeftActive = [self isLeftActiveInKeys:keys activeKey:activeKey];
+
+ /* generate header row */
+
+ [self _appendHeaderRowToResponse:_response inContext:_ctx
+ keys:keys activeKey:activeKey
+ doScript:doScript];
+
+ [_ctx deleteLastElementIDComponent]; // 'h' for head
+ [_ctx removeObjectForKey:UIxTabView_HEAD];
+
+ /* header foot row */
+
+ [self _appendHeaderFootRowToResponse:_response inContext:_ctx
+ bgcolor:bgcolor
+ doScript:doScript
+ isLeftActive:isLeftActive];
+
+ /* body row */
+
+ [self _appendBodyRowToResponse:_response inContext:_ctx
+ bgcolor:bgcolor
+ activeKey:activeKey];
+
+ /* close table */
+
+ [_response appendContentString:@"</table>"];
+ [_ctx removeObjectForKey:UIxTabView_ACTIVEKEY];
+ [_ctx removeObjectForKey:UIxTabView_KEYS];
+ [self restoreNestedState:nestedState inContext:_ctx];
+}
+
+@end /* UIxTabView */