]> err.no Git - scalable-opengroupware.org/commitdiff
New UIxElemBuilder and associated elements
authorznek <znek@d1b88da0-ebda-0310-925b-ed51d893ca5b>
Fri, 11 Jun 2004 12:07:09 +0000 (12:07 +0000)
committerznek <znek@d1b88da0-ebda-0310-925b-ed51d893ca5b>
Fri, 11 Jun 2004 12:07:09 +0000 (12:07 +0000)
git-svn-id: http://svn.opengroupware.org/SOGo/trunk@30 d1b88da0-ebda-0310-925b-ed51d893ca5b

16 files changed:
ZideStore/UI-X/Common/GNUmakefile
ZideStore/UI-X/Common/UIxElemBuilder.m [new file with mode: 0644]
ZideStore/UI-X/Common/UIxTabItem.m [new file with mode: 0644]
ZideStore/UI-X/Common/UIxTabView.h [new file with mode: 0644]
ZideStore/UI-X/Common/UIxTabView.m [new file with mode: 0644]
ZideStore/UI-X/Common/bundle-info.plist
ZideStore/UI-X/Common/common.h
ZideStore/UI-X/Common/images/closewindow.gif [new file with mode: 0644]
ZideStore/UI-X/Common/images/corner_right.gif [new file with mode: 0644]
ZideStore/UI-X/Common/images/tab_.gif [new file with mode: 0644]
ZideStore/UI-X/Common/images/tab_selected.gif [new file with mode: 0644]
ZideStore/UI-X/Common/product.plist
ZideStore/UI-X/Scheduler/GNUmakefile
ZideStore/UI-X/Scheduler/OGoCalSelectTab.m [new file with mode: 0644]
ZideStore/UI-X/Scheduler/OGoCalSelectTab.wox [new file with mode: 0644]
ZideStore/UI-X/Scheduler/OGoCalWeekOverview.wox

index 2b76be679f75bc998d3e217ba3dc2b044ec06bfb..f713025bc94c9fb9c8c889f26f89fb37a560584b 100644 (file)
@@ -14,6 +14,10 @@ CommonUI_OBJC_FILES = \
        OGoAppFrame.m           \
        OGoAppHeader.m          \
        OGoAppNavigation.m      \
+       \
+       UIxElemBuilder.m \
+       UIxTabView.m \
+       UIxTabItem.m \
 
 CommonUI_RESOURCE_FILES += \
        Version                 \
@@ -39,6 +43,10 @@ CommonUI_RESOURCE_FILES += \
        images/box_botleft.gif  \
        images/box_bottom.gif\
        images/box_botright.gif\
+       images/tab_selected.gif\
+       images/tab_.gif\
+       images/corner_right.gif\
+       images/closewindow.gif
 
 ZIDESTORE=$(GNUSTEP_USER_ROOT)/Headers/ZideStore12
 
diff --git a/ZideStore/UI-X/Common/UIxElemBuilder.m b/ZideStore/UI-X/Common/UIxElemBuilder.m
new file mode 100644 (file)
index 0000000..0057908
--- /dev/null
@@ -0,0 +1,86 @@
+/*
+  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 <NGObjWeb/WOxElemBuilder.h>
+
+/*
+  This builder builds various elements from the UI-X product.
+
+  All tags are mapped into the <uix:> namespace (XMLNS_OD_BIND).
+
+    <var:tabview   .../>    maps to UIxTabView
+    <var:tab       .../>    maps to UIxTabItem
+*/
+
+@interface UIxElemBuilder : WOxTagClassElemBuilder
+{
+}
+
+@end
+
+#include <SaxObjC/XMLNamespaces.h>
+#include "common.h"
+
+#define XMLNS_UIX @"OGo:uix"
+
+
+@implementation UIxElemBuilder
+
+- (Class)classForElement:(id<DOMElement>)_element {
+  NSString *tagName;
+  unsigned tl;
+  unichar c1;
+  
+  if (![[_element namespaceURI] isEqualToString:XMLNS_UIX])
+    return Nil;
+
+  tagName = [_element tagName];
+  if ((tl = [tagName length]) < 2)
+    return Nil;
+
+  c1 = [tagName characterAtIndex:0];
+
+  switch (c1) {
+    case 't': { /* starting with 't' */
+      unichar c2;
+      
+      c2 = [tagName characterAtIndex:1];
+      
+      if (tl == 3 && c2 == 'a') {
+        if ([tagName characterAtIndex:2] == 'b')
+          return NSClassFromString(@"UIxTabItem");
+      }
+
+      if (tl > 5) {
+        if (c2 == 'a') {
+          if ([tagName isEqualToString:@"tabview"])
+            return NSClassFromString(@"UIxTabView");
+        }
+      }
+      break;
+    }
+  }
+  
+  return Nil;
+}
+
+@end /* UIxElemBuilder */
diff --git a/ZideStore/UI-X/Common/UIxTabItem.m b/ZideStore/UI-X/Common/UIxTabItem.m
new file mode 100644 (file)
index 0000000..5a70748
--- /dev/null
@@ -0,0 +1,452 @@
+/*
+  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 */
diff --git a/ZideStore/UI-X/Common/UIxTabView.h b/ZideStore/UI-X/Common/UIxTabView.h
new file mode 100644 (file)
index 0000000..6863eb9
--- /dev/null
@@ -0,0 +1,126 @@
+/*
+  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$
+
+#ifndef __UIxTabView_H__
+#define __UIxTabView_H__
+
+/*
+  This is a library private header !
+*/
+
+#include <NGObjWeb/WODynamicElement.h>
+
+/*
+  Does not support tab-head-creation from nested components !!!
+
+  hh: Why not ??? -> Because selection is manipulated in sub-elements
+
+  UIxTabView creates element-IDs like
+
+    .h.*.$key.  for the tab-items   (head-mode)
+    .b.$key...  for the tab-content (content-mode) (new, hh)
+
+  !!! UIxTabView JavaScript can't handle duplicate tab-keys !!!
+*/
+
+@interface UIxTabView : WODynamicElement
+{
+  WOAssociation *selection;
+
+  /* config: */
+  WOAssociation *headerStyle;
+  WOAssociation *tabStyle;
+  WOAssociation *selectedTabStyle;
+
+  /* old config: */
+  WOAssociation *bgColor;
+  WOAssociation *nonSelectedBgColor;
+  WOAssociation *leftCornerIcon;
+  WOAssociation *rightCornerIcon;
+  
+  WOAssociation *tabIcon;
+  WOAssociation *leftTabIcon;
+  WOAssociation *selectedTabIcon;
+  
+  WOAssociation *asBackground;
+  WOAssociation *width;
+  WOAssociation *height;
+  WOAssociation *activeBgColor;
+  WOAssociation *inactiveBgColor;
+
+  WOAssociation *fontColor;
+  WOAssociation *fontSize;
+  WOAssociation *fontFace;
+
+  id            template;
+}
+
+@end
+
+@interface UIxTabItem : WODynamicElement
+{
+  WOAssociation *key;
+  WOAssociation *icon;
+  WOAssociation *label;
+  WOAssociation *action;
+  WOAssociation *isScript;
+
+  /* config: */
+  WOAssociation *tabIcon;
+  WOAssociation *leftTabIcon;
+  WOAssociation *selectedTabIcon;
+
+  WOAssociation *asBackground;
+  WOAssociation *width;
+  WOAssociation *height;
+  WOAssociation *activeBgColor;
+  WOAssociation *inactiveBgColor;
+  
+  id            template;
+}
+
+@end
+
+@interface UIxTabItemInfo : NSObject
+{
+@public
+  NSString *label;
+  NSString *icon;
+  NSString *key;
+  NSString *uri;
+  NSString *tabIcon;
+  NSString *leftIcon;
+  NSString *selIcon;
+  NSString *tabStyle;
+  NSString *selectedTabStyle;
+
+  int      asBackground; // 0 -> not set, 1 -> YES, else -> NO
+  NSString *width;
+  NSString *height;
+  NSString *activeBg;
+  NSString *inactiveBg;
+
+  BOOL     isScript;
+}
+@end
+
+#endif /* __UIxTabView_H__ */
diff --git a/ZideStore/UI-X/Common/UIxTabView.m b/ZideStore/UI-X/Common/UIxTabView.m
new file mode 100644 (file)
index 0000000..e8b7ea5
--- /dev/null
@@ -0,0 +1,902 @@
+/*
+  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:@"&nbsp;"];
+    [_response appendContentString:@"</div>"];
+  }
+  else if (isLeftActive)
+    [_response appendContentString:@"&nbsp;"];
+  
+  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:@"&nbsp;"];
+  }
+  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:@"&nbsp;"];
+  }
+  [_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 */
index 2488770b13d22357130c9e41acce74cf215b7e60..037b651ee52589dc32dd9c6f41bac0fba82a2eed 100644 (file)
     classes = (
       { name = CommonUIProduct;       },
       { name = OGoPageFrame;          },
+      { name = "UIxElemBuilder"; },
+      { name = "UIxTabView";          },
+      { name = "UIxTabItem";          },
     );
 
     WOComponents = (
-      { name = OGoPageFrame; }
+      { name = OGoPageFrame; },
+    );
+    
+    WOxElemBuilder = (
+      { name = "UIxElemBuilder"; },
+    );
+
+    WODynamicElements = (
+      { name = "UIxTabView";          },
+      { name = "UIxTabItem";          },
     );
   };
 }
index 093af0b3815e51574b7481f895e9b93285c58622..9a7a307721564cdb0afa714f4a6f4a41841123a9 100644 (file)
 #include <NGExtensions/NGExtensions.h>
 #include <NGObjWeb/NGObjWeb.h>
 #include <NGObjWeb/SoObjects.h>
+
+@interface WOContext(WOExtensionsPrivate)
+- (void)addActiveFormElement:(WOElement *)_element;
+@end
+
+static inline id WOExtGetProperty(NSDictionary *_set, NSString *_name) {
+    id propValue = [_set objectForKey:_name];
+    
+    if (propValue) {
+        propValue = RETAIN(propValue);
+        [(id)_set removeObjectForKey:_name];
+    }
+    return propValue;
+}
+
+static inline NSString *WEUriOfResource(NSString *_name, WOContext *_ctx) {
+    NSArray           *languages;
+    WOResourceManager *resourceManager;
+    NSString          *uri;
+    
+    if (_name == nil)
+        return nil;
+    
+    languages = [_ctx hasSession]
+        ? [[_ctx session] languages]
+        : [[_ctx request] browserLanguages];
+    
+    resourceManager = [[_ctx application] resourceManager];
+    
+    uri = [resourceManager urlForResourceNamed:_name
+                                   inFramework:nil
+                                     languages:languages
+                                       request:[_ctx request]];
+    if ([uri rangeOfString:@"/missingresource?"].length > 0)
+        uri = nil;
+    
+    return uri;
+}
+
+static inline void WEAppendFont(WOResponse *_resp,
+                                NSString   *_color,
+                                NSString   *_face,
+                                NSString   *_size)
+{
+    [_resp appendContentString:@"<font"];
+    if (_color) {
+        [_resp appendContentString:@" color=\""];
+        [_resp appendContentHTMLAttributeValue:_color];
+        [_resp appendContentCharacter:'"'];
+    }
+    if (_face) {
+        [_resp appendContentString:@" face=\""];
+        [_resp appendContentHTMLAttributeValue:_face];
+        [_resp appendContentCharacter:'"'];
+    }
+    if (_size) {
+        [_resp appendContentString:@" size=\""];
+        [_resp appendContentHTMLAttributeValue:_size];
+        [_resp appendContentCharacter:'"'];
+    }
+    [_resp appendContentCharacter:'>'];
+}
+
+static inline void WEAppendTD(WOResponse *_resp,
+                              NSString   *_align,
+                              NSString   *_valign,
+                              NSString   *_bgColor)
+{
+    [_resp appendContentString:@"<td"];
+    if (_bgColor) {
+        [_resp appendContentString:@" bgcolor=\""];
+        [_resp appendContentHTMLAttributeValue:_bgColor];
+        [_resp appendContentCharacter:'"'];
+    }
+    if (_align) {
+        [_resp appendContentString:@" align=\""];
+        [_resp appendContentHTMLAttributeValue:_align];
+        [_resp appendContentCharacter:'"'];
+    }
+    if (_valign) {
+        [_resp appendContentString:@" valign=\""];
+        [_resp appendContentHTMLAttributeValue:_valign];
+        [_resp appendContentCharacter:'"'];
+    }
+    [_resp appendContentCharacter:'>'];
+}
+
+static inline WOElement *WECreateElement(NSString *_className,
+                                         NSString *_name,
+                                         NSDictionary *_config,
+                                         WOElement *_template)
+{
+    Class               c;
+    WOElement           *result = nil;
+    NSMutableDictionary *config = nil;
+    
+    if ((c = NSClassFromString(_className)) == Nil) {
+        NSLog(@"%s: missing '%@' class", __PRETTY_FUNCTION__, _className);
+        return nil;
+    }
+    config = [NSMutableDictionary dictionaryWithCapacity:4];
+    {
+        NSEnumerator *keyEnum;
+        id           key;
+        
+        keyEnum = [_config keyEnumerator];
+        
+        while ((key = [keyEnum nextObject])) {
+            WOAssociation *a;
+            
+            a = [WOAssociation associationWithValue:[_config objectForKey:key]];
+            [config setObject:a forKey:key];
+        }
+    }
+    result = [[c alloc] initWithName:_name
+                        associations:config
+                            template:_template];
+    return [result autorelease];
+}
+
+#define OWGetProperty WOExtGetProperty
diff --git a/ZideStore/UI-X/Common/images/closewindow.gif b/ZideStore/UI-X/Common/images/closewindow.gif
new file mode 100644 (file)
index 0000000..f4305d6
Binary files /dev/null and b/ZideStore/UI-X/Common/images/closewindow.gif differ
diff --git a/ZideStore/UI-X/Common/images/corner_right.gif b/ZideStore/UI-X/Common/images/corner_right.gif
new file mode 100644 (file)
index 0000000..75b945d
Binary files /dev/null and b/ZideStore/UI-X/Common/images/corner_right.gif differ
diff --git a/ZideStore/UI-X/Common/images/tab_.gif b/ZideStore/UI-X/Common/images/tab_.gif
new file mode 100644 (file)
index 0000000..ad720a0
Binary files /dev/null and b/ZideStore/UI-X/Common/images/tab_.gif differ
diff --git a/ZideStore/UI-X/Common/images/tab_selected.gif b/ZideStore/UI-X/Common/images/tab_selected.gif
new file mode 100644 (file)
index 0000000..2cbdea6
Binary files /dev/null and b/ZideStore/UI-X/Common/images/tab_selected.gif differ
index 430ec864d85c08f07d2b80cf9d9db693b5cde7ae..8f826d2d49bfe58d49e539e04e39f02fd9e23739 100644 (file)
     box_botleft.gif,
     box_bottom.gif,
     box_botright.gif,
+    tab_selected.gif,
+    tab_.gif,
+    corner_right.gif,
+    closewindow.gif,
     OGoLogo.gif
   );
   
index 27c47d03c7504e1f0210d8fa4d31e50f9cbfdcd0..f890bcad8b1d5c4bc2a95b3f67b3b1ef833a5ad7 100644 (file)
@@ -18,6 +18,7 @@ SchedulerUI_OBJC_FILES = \
        OGoCalWeekOverview.m    \
        OGoCalMonthOverview.m   \
        OGoAppointmentView.m    \
+       OGoCalSelectTab.m \
 
 SchedulerUI_RESOURCE_FILES += \
        Version                         \
@@ -27,8 +28,10 @@ SchedulerUI_RESOURCE_FILES += \
        OGoCalWeekOverview.wox          \
        OGoCalMonthOverview.wox         \
        OGoAppointmentView.wox          \
+       OGoCalSelectTab.wox \
        images/next_week.gif            \
        images/previous_week.gif        \
+       
 
 ifeq ($(FOUNDATION_LIB),apple)
 ZIDESTORE=$(GNUSTEP_USER_ROOT)/Library/Headers/ZideStore12
diff --git a/ZideStore/UI-X/Scheduler/OGoCalSelectTab.m b/ZideStore/UI-X/Scheduler/OGoCalSelectTab.m
new file mode 100644 (file)
index 0000000..a8bc839
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+  Copyright (C) 2000-2004 SKYRIX Software AG
+
+  This file is part of OGo
+
+  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 <NGObjWeb/NGObjWeb.h>
+
+
+@interface OGoCalSelectTab : WOComponent
+{
+    NSString *selection;
+    NSCalendarDate *currentDate;
+}
+
+@end
+
+
+@implementation OGoCalSelectTab
+
+- (void)dealloc {
+    [self->selection release];
+    [self->currentDate release];
+    [super dealloc];
+}
+
+- (void)setSelection:(NSString *)_selection {
+    ASSIGN(self->selection, _selection);
+}
+
+- (NSString *)selection {
+    return self->selection;
+}
+
+- (void)setCurrentDate:(NSCalendarDate *)_date {
+    ASSIGN(self->currentDate, _date);
+}
+
+- (NSCalendarDate *)currentDate {
+    return self->currentDate;
+}
+
+- (NSString *)dayLabel {
+    return @"TODO: day";
+}
+
+- (NSString *)weekLabel {
+    return @"TODO: week";
+}
+
+- (NSString *)monthLabel {
+    return @"TODO: month";
+}
+
+- (NSString *)yearLabel {
+    return @"TODO: year";
+}
+
+@end
diff --git a/ZideStore/UI-X/Scheduler/OGoCalSelectTab.wox b/ZideStore/UI-X/Scheduler/OGoCalSelectTab.wox
new file mode 100644 (file)
index 0000000..4a02b55
--- /dev/null
@@ -0,0 +1,24 @@
+<?xml version='1.0' standalone='yes'?>
+
+<uix:tabview xmlns="http://www.w3.org/1999/xhtml"
+             xmlns:var="http://www.skyrix.com/od/binding"
+             xmlns:const="http://www.skyrix.com/od/constant"
+             xmlns:rsrc="OGo:url"
+             xmlns:uix="OGo:uix"
+             selection="selection"
+             const:tabStyle="tab"
+             const:selectedTabStyle="selectedTab"
+>
+     <uix:tab const:key="day" var:label="dayLabel" const:href="dayoverview">
+     <var:component-content />
+     </uix:tab>
+     <uix:tab const:key="week" var:label="weekLabel" const:href="weekoverview">
+     <var:component-content />
+     </uix:tab>
+     <uix:tab const:key="month" var:label="monthLabel" const:href="monthoverview">
+     <var:component-content />
+     </uix:tab>
+     <uix:tab const:key="year" var:label="yearLabel" const:href="yearoverview">
+     <var:component-content />
+     </uix:tab>
+</uix:tabview>
index 49d50a8aa9de45ac881bf84594e1ae34c4b831b6..14c0bdbd0de725a2894d4da08b7a638e448800bd 100644 (file)
@@ -1,64 +1,87 @@
-<?xml version='1.0' standalone='yes'?>
-<var:component className="OGoPageFrame" title="name"
-  xmlns="http://www.w3.org/1999/xhtml"
-  xmlns:var="http://www.skyrix.com/od/binding"
-  xmlns:const="http://www.skyrix.com/od/constant"
-  xmlns:rsrc="OGo:url"
->
-  <br />
-    OGo ZideStore Server - <var:string value="name"/>
-    <br />
-    Client: <var:string value="clientObject"/>
-    <br />
-    Appointments: #<var:string value="appointments.count"/>
-    <br />
-
-    <hr />
-
+<?xml version="1.0" standalone="yes"?>
+<var:component xmlns="http://www.w3.org/1999/xhtml"
+               xmlns:var="http://www.skyrix.com/od/binding"
+               xmlns:const="http://www.skyrix.com/od/constant"
+               xmlns:rsrc="OGo:url"
+               xmlns:uix="OGo:uix"
+               className="OGoPageFrame"
+               title="name">
+    <br/>
+    OGo ZideStore Server - <var:string value="name"/><br/>
+    Client: <var:string value="clientObject"/><br/>
+    Appointments: #<var:string value="appointments.count"/><br/>
+    <hr/>
     <table border="0" cellpadding="0" cellspacing="0" width="100%">
-      <tr bgcolor="#E0E0E0">
-        <td align="left" valign="middle" width="80%">other stuff</td> <!-- 99% -->
-        <td align="right"><table border="0"><tr>
-        <td align="right" valign="middle"><a var:href="prevWeekURL"><img rsrc:src="previous_week.gif" alt="previous week" border="0" /></a></td>
-        <td align="right" valign="middle"><a var:href="thisWeekURL" class="button_auto">this<var:entity const:name="nbsp" />week</a></td>
-        <td align="right" valign="middle"><a var:href="nextWeekURL"><img rsrc:src="next_week.gif" alt="next week" border="0" /></a></td>
-        </tr></table></td>
-      </tr>
+    <tr bgcolor="#E0E0E0">
+    <td align="left" valign="middle" width="80%">other stuff</td><!-- 99% -->
+    <td align="right">
+    <table border="0">
+    <tr>
+    <td align="right" valign="middle">
+    <a var:href="prevWeekURL"><img rsrc:src="previous_week.gif" alt="previous week" border="0"/></a></td>
+    <td align="right" valign="middle">
+    <a var:href="thisWeekURL" class="button_auto">this<var:entity const:name="nbsp"/>week</a>
+    </td>
+    <td align="right" valign="middle">
+    <a var:href="nextWeekURL"><img rsrc:src="next_week.gif" alt="next week" border="0"/></a>
+    </td>
+    </tr>
     </table>
-    <br />
-  <a href="dayoverview">day</a>
-  | <a href="weekoverview">week</a>
-  | <a href="monthoverview">month</a>
-  | <a href="yearoverview">year</a>
-    <br />
-
-    <var:tabview const:selection="weekoverview">
-        <var:tab const:key="dayoverview" const:label="day" />
-        <var:tab const:key="weekoverview" const:label="week">
-    <var:week-overview
-      list="appointments"
-      item="appointment"
-      weekStart="startDate"
-      const:startDateKey = "startDate"
-      const:endDateKey   = "endDate"
-      const:titleStyle   = "weekoverview_title"
-      const:contentStyle = "weekoverview_content"
-    >
-      <var:week>
-       <a var:href="appointmentViewURL"
-          ><var:string value="appointment.title" /></a>
-      </var:week>
-    </var:week-overview>
-
-    <hr />
+    </td>
+    </tr>
+    </table>
+    <br/>
+    
+  <!-- $Id: SkyNews.html,v 1.3 2003/12/22 16:53:55 helge Exp $ -->
+  <table id="skywintable" class="wintable" cellspacing="0" cellpadding="5" width="100%">
+  <tr>
+  <td class="wintitle">
+  <table cellpadding="0" cellspacing="0" width="100%">
+  <tr>
+  <td width="5"/>
+  <td class="wintitle">TODO:Date</td>
+  <td width="36" align="right" valign="center">
+  <a href="winclose">
+  <img border="0" alt="X" rsrc:src="closewindow.gif"/>
+  </a>
+  </td>
+  </tr>
+  </table>
+  </td>
+  </tr>
+  <tr>
+  <td id="skywinbodycell" class="wincontent">
+  <table border="0" width="100%" cellpadding="0" cellspacing="0">
+  <tr>
+  <td colspan="2">
+  <var:component className="OGoCalSelectTab" const:selection="week" currentDate="startDate">
+  week content, right?
+  </var:component>
+  </td>
+  </tr>
+  <tr bgcolor="#F5F5E9">
+  <td align="left" width="10"><var:entity const:name="nbsp"/></td>
+  <td align="right"><img border="0" alt="" rsrc:src="corner_right.gif"/></td>
+  </tr>
+  <tr>
+  <td colspan="2" bgcolor="#F5F5E9">
+  <table border="0" width="100%" cellpadding="10" cellspacing="0">
+  <tr/>
+  </table>
+  </td>
+  </tr>
+  </table>
+  </td>
+  </tr>
+  </table>
+  <var:week-overview list="appointments" item="appointment" weekStart="startDate" const:startDateKey="startDate" const:endDateKey="endDate" const:titleStyle="weekoverview_title" const:contentStyle="weekoverview_content">
+  <var:week>
+  <a var:href="appointmentViewURL"><var:string value="appointment.title"/></a>
+  </var:week>
+  </var:week-overview>
+  <hr/>
     
     Appointments: 
     <var:component className="OGoAptTableView" appointments="appointments"/>
-    
     <!-- pre><var:string value="appointments" const:insertBR="YES"/></pre -->
-
-        </var:tab>
-        <var:tab const:key="monthoverview" const:label="month" />
-        <var:tab const:key="yearoverview" const:label="year" />
-    </var:tabview>
 </var:component>