]> err.no Git - scalable-opengroupware.org/commitdiff
created branch of ZideStore/UI-X for SOGo
authorznek <znek@d1b88da0-ebda-0310-925b-ed51d893ca5b>
Wed, 30 Jun 2004 09:13:47 +0000 (09:13 +0000)
committerznek <znek@d1b88da0-ebda-0310-925b-ed51d893ca5b>
Wed, 30 Jun 2004 09:13:47 +0000 (09:13 +0000)
git-svn-id: http://svn.opengroupware.org/SOGo/trunk@101 d1b88da0-ebda-0310-925b-ed51d893ca5b

92 files changed:
SOGo/UI/ChangeLog [new file with mode: 0644]
SOGo/UI/Common/CommonUIProduct.m [new file with mode: 0644]
SOGo/UI/Common/GNUmakefile [new file with mode: 0644]
SOGo/UI/Common/GNUmakefile.postamble [new file with mode: 0644]
SOGo/UI/Common/GNUmakefile.preamble [new file with mode: 0644]
SOGo/UI/Common/UIxAppFrame.m [new file with mode: 0644]
SOGo/UI/Common/UIxAppFrame.wox [new file with mode: 0644]
SOGo/UI/Common/UIxAppHeader.m [new file with mode: 0644]
SOGo/UI/Common/UIxAppHeader.wox [new file with mode: 0644]
SOGo/UI/Common/UIxAppNavView.m [new file with mode: 0644]
SOGo/UI/Common/UIxAppNavView.wox [new file with mode: 0644]
SOGo/UI/Common/UIxAppNavigation.m [new file with mode: 0644]
SOGo/UI/Common/UIxAppNavigation.wox [new file with mode: 0644]
SOGo/UI/Common/UIxComponent.h [new file with mode: 0644]
SOGo/UI/Common/UIxComponent.m [new file with mode: 0644]
SOGo/UI/Common/UIxElemBuilder.m [new file with mode: 0644]
SOGo/UI/Common/UIxPageFrame.m [new file with mode: 0644]
SOGo/UI/Common/UIxPageFrame.wox [new file with mode: 0644]
SOGo/UI/Common/UIxTabItem.m [new file with mode: 0644]
SOGo/UI/Common/UIxTabView.h [new file with mode: 0644]
SOGo/UI/Common/UIxTabView.m [new file with mode: 0644]
SOGo/UI/Common/UIxWinClose.m [new file with mode: 0644]
SOGo/UI/Common/UIxWinClose.wox [new file with mode: 0644]
SOGo/UI/Common/Version [new file with mode: 0644]
SOGo/UI/Common/bundle-info.plist [new file with mode: 0644]
SOGo/UI/Common/calendar.css [new file with mode: 0644]
SOGo/UI/Common/common.h [new file with mode: 0644]
SOGo/UI/Common/images/OGoLogo.gif [new file with mode: 0755]
SOGo/UI/Common/images/box_botleft.gif [new file with mode: 0644]
SOGo/UI/Common/images/box_botright.gif [new file with mode: 0644]
SOGo/UI/Common/images/box_bottom.gif [new file with mode: 0644]
SOGo/UI/Common/images/box_left.gif [new file with mode: 0644]
SOGo/UI/Common/images/box_right.gif [new file with mode: 0644]
SOGo/UI/Common/images/box_top.gif [new file with mode: 0644]
SOGo/UI/Common/images/box_topleft.gif [new file with mode: 0644]
SOGo/UI/Common/images/box_topright.gif [new file with mode: 0644]
SOGo/UI/Common/images/closewindow.gif [new file with mode: 0644]
SOGo/UI/Common/images/corner_right.gif [new file with mode: 0644]
SOGo/UI/Common/images/line_left.gif [new file with mode: 0644]
SOGo/UI/Common/images/line_right.gif [new file with mode: 0644]
SOGo/UI/Common/images/line_stretch.gif [new file with mode: 0644]
SOGo/UI/Common/images/menu_logo_top.gif [new file with mode: 0644]
SOGo/UI/Common/images/tab_.gif [new file with mode: 0644]
SOGo/UI/Common/images/tab_selected.gif [new file with mode: 0644]
SOGo/UI/Common/product.plist [new file with mode: 0644]
SOGo/UI/Common/zidestoreui.css [new file with mode: 0644]
SOGo/UI/GNUmakefile [new file with mode: 0644]
SOGo/UI/Scheduler/COPYING [new file with mode: 0644]
SOGo/UI/Scheduler/COPYRIGHT [new file with mode: 0644]
SOGo/UI/Scheduler/GNUmakefile [new file with mode: 0644]
SOGo/UI/Scheduler/GNUmakefile.postamble [new file with mode: 0644]
SOGo/UI/Scheduler/GNUmakefile.preamble [new file with mode: 0644]
SOGo/UI/Scheduler/NOTES [new file with mode: 0644]
SOGo/UI/Scheduler/SchedulerUIProduct.m [new file with mode: 0644]
SOGo/UI/Scheduler/UIxAppointmentEditor.m [new file with mode: 0644]
SOGo/UI/Scheduler/UIxAppointmentEditor.wox [new file with mode: 0644]
SOGo/UI/Scheduler/UIxAppointmentFormatter.h [new file with mode: 0644]
SOGo/UI/Scheduler/UIxAppointmentFormatter.m [new file with mode: 0644]
SOGo/UI/Scheduler/UIxAppointmentView.h [new file with mode: 0644]
SOGo/UI/Scheduler/UIxAppointmentView.m [new file with mode: 0644]
SOGo/UI/Scheduler/UIxAppointmentView.wox [new file with mode: 0644]
SOGo/UI/Scheduler/UIxAptTableView.m [new file with mode: 0644]
SOGo/UI/Scheduler/UIxAptTableView.wox [new file with mode: 0644]
SOGo/UI/Scheduler/UIxCalBackForthNavView.m [new file with mode: 0644]
SOGo/UI/Scheduler/UIxCalBackForthNavView.wox [new file with mode: 0644]
SOGo/UI/Scheduler/UIxCalDateLabel.m [new file with mode: 0644]
SOGo/UI/Scheduler/UIxCalDateLabel.wox [new file with mode: 0644]
SOGo/UI/Scheduler/UIxCalMonthOverview.m [new file with mode: 0644]
SOGo/UI/Scheduler/UIxCalMonthOverview.wox [new file with mode: 0644]
SOGo/UI/Scheduler/UIxCalMonthView.h [new file with mode: 0644]
SOGo/UI/Scheduler/UIxCalMonthView.m [new file with mode: 0644]
SOGo/UI/Scheduler/UIxCalSelectTab.m [new file with mode: 0644]
SOGo/UI/Scheduler/UIxCalSelectTab.wox [new file with mode: 0644]
SOGo/UI/Scheduler/UIxCalView.h [new file with mode: 0644]
SOGo/UI/Scheduler/UIxCalView.m [new file with mode: 0644]
SOGo/UI/Scheduler/UIxCalWeekOverview.m [new file with mode: 0644]
SOGo/UI/Scheduler/UIxCalWeekOverview.wox [new file with mode: 0644]
SOGo/UI/Scheduler/UIxCalWeekView.h [new file with mode: 0644]
SOGo/UI/Scheduler/UIxCalWeekView.m [new file with mode: 0644]
SOGo/UI/Scheduler/Version [new file with mode: 0644]
SOGo/UI/Scheduler/bundle-info.plist [new file with mode: 0644]
SOGo/UI/Scheduler/common.h [new file with mode: 0644]
SOGo/UI/Scheduler/images/icon_apt_chart.gif [new file with mode: 0644]
SOGo/UI/Scheduler/images/icon_apt_chart_inactive.gif [new file with mode: 0644]
SOGo/UI/Scheduler/images/icon_apt_column_view.gif [new file with mode: 0644]
SOGo/UI/Scheduler/images/icon_apt_list.gif [new file with mode: 0644]
SOGo/UI/Scheduler/images/icon_apt_list_inactive.gif [new file with mode: 0644]
SOGo/UI/Scheduler/images/icon_apt_overview.gif [new file with mode: 0644]
SOGo/UI/Scheduler/images/icon_apt_overview_inactive.gif [new file with mode: 0644]
SOGo/UI/Scheduler/images/next_week.gif [new file with mode: 0644]
SOGo/UI/Scheduler/images/previous_week.gif [new file with mode: 0644]
SOGo/UI/Scheduler/product.plist [new file with mode: 0644]

diff --git a/SOGo/UI/ChangeLog b/SOGo/UI/ChangeLog
new file mode 100644 (file)
index 0000000..f8c8667
--- /dev/null
@@ -0,0 +1,208 @@
+2004-06-30  Marcus Müller  <znek@mulle-kybernetik.com>
+
+       * Scheduler/UIxAppointmentEditor.m: improved -saveAction. Does
+         everything in a complete manner now - except for saving which isn't
+         done at all.
+
+2004-06-30  Helge Hess  <helge.hess@opengroupware.org>
+
+       * Scheduler/UIxAppointmentEditor.m: made the hack more hackish to work
+         on MacOSX
+
+2004-06-28  Marcus Mueller  <znek@mulle-kybernetik.com>
+
+       * Common/UIxComponent.[hm]: moved -ownMethodName here.
+
+       * Scheduler/UIxCalView.[hm]: removed -ownMethodName, moved to
+         UIxComponent (reuse).
+
+       * Scheduler/UIxAppointmentView.[hm]: first "draft" of view component.
+         The look of OGo is resembled closely, but most features are still
+         missing.
+
+2004-06-28  Marcus Mueller  <znek@mulle-kybernetik.com>
+
+       * Scheduler/GNUmakefile.preamble: links against libSOGoLogic now.
+
+       * Scheduler/UIxAppointmentView.m, Scheduler/UIxAppointmentView.wox:
+         test of iCal object.
+
+2004-06-23  Marcus Mueller  <znek@mulle-kybernetik.com>
+
+       * UIxCalMonthOverview.[m,wox]: completed month view. Turned out to
+         be much more difficult to improve with style sheets than expected.
+         Requires version 4.2.45 of WEExtensions.
+
+2004-06-22  Marcus Mueller  <znek@mulle-kybernetik.com>
+
+       * Refactoring: Renamed everything from OGo to UIx in order to avoid
+         nameclashes (happens on OSX related to NGBundleManager)
+
+       * Refactoring 2: Moved methods from UIxWeekOverview to UIxCalView.
+
+       * Highlighting in UIxWeekOverview works now.
+
+2004-06-22  Helge Hess  <helge.hess@skyrix.com>
+
+       * Common/GNUmakefile.preamble: fixed linking for OGo gstep-make
+
+2004-06-21  Helge Hess  <helge.hess@opengroupware.org>
+
+       * Scheduler/OGoCalWeekOverview.m: fixed syntax errors
+
+2004-06-18  Marcus Mueller  <znek@mulle-kybernetik.com>
+
+       * Implemented proper calendar in week overview. Highlighting isn't
+         enabled, yet.
+
+2004-06-18  Marcus Mueller  <znek@mulle-kybernetik.com>
+
+       * Common/OGoComponent.[hm]: new component which serves as a base
+         component for calendar components now. Knows how to deal with
+         queryParameters and offers url construction method(s).
+
+       * All existing components have been rewritten to use queryParameters
+         instead of hardcoded strings where this is feasible. This provides
+         future extensibility and flexibility.
+
+       * Handling of dates has been fixed to center around the use of a
+         'day' parameter. startDate/endDate are coupled to this, but
+         don't override it as it's the duty of the individual view to set
+         its (feasible) ranges accordingly. The new behaviour is noticable
+         in the calendar selection tabview instantly, as it now replicates
+         what OGo does.
+
+2004-06-16  Marcus Mueller  <znek@mulle-kybernetik.com>
+
+       * Common/OGoAppNavView.m: construct URL correctly.
+
+       * Common/OGoPageFrame.m: display login correctly.
+
+       * Common/calendar.css: cosmetic changes.
+
+       * Scheduler/OGoCalSelectTab.m: always display mondayOfWeek.
+
+       * Scheduler/OGoCalBackForthNavView.m: created.
+
+2004-06-16  Marcus Mueller  <znek@mulle-kybernetik.com>
+
+       * Common/zidestoreui.css: new style for button_auto.
+
+       * Scheduler/OGoCalView.[hm]: API for completing hrefs with necessary
+         query parts.
+
+       * Scheduler/OGoCalWeekView.m: bugfix for startDate.
+
+       * Scheduler/product.plist: added still missing views -> point to
+         weekoverview for the time being.
+       
+2004-06-15  Marcus Mueller  <znek@mulle-kybernetik.com>
+
+       * Common/UIxTabView.m: removed class from <a> tag, removed rendering
+         of headerFooter (what's that good for anyways?)
+
+       * Several resources which resolved to wrong products added statically
+         in templates.
+
+       * Cosmetic changes in templates.
+
+2004-06-14  Helge Hess  <helge.hess@opengroupware.org>
+
+       * Scheduler/OGoCalMonthOverview.wox: added missing rsrc namespace
+
+2004-06-14  Helge Hess  <helge.hess@skyrix.com>
+
+       * Common/common.h: fixed a gcc 3.4 warning
+
+2004-06-14  Helge Hess  <helge.hess@opengroupware.org>
+
+       * added aggregate project for UI-X
+
+2004-06-14  Marcus Mueller  <znek@mulle-kybernetik.com>
+
+       * Common/calendar.css: new date_label (unused)
+
+       * Scheduler/OGoCalSelectTab.m: finished all labels
+
+       * Scheduler/OGoCalDateLabel.m, Scheduler/OGoCalDateLabel.wox: new
+         component for rendering the correct date label based on startDate,
+         endDate and selection
+
+       * Scheduler/OGoCalMonthView.m: prev/next month corrected
+
+       * Scheduler/OGoCalMonthOverview.wox: uses date label and tabs now
+
+       * Scheduler/OGoCalWeekOverview.wox: completed layout
+
+       * Scheduler/GNUmakefile: new component added
+
+2004-06-14  Marcus Mueller  <znek@mulle-kybernetik.com>
+
+       * Common/UIxTabView.[hm]: more stylesheet support via headerStyle
+         and bodyStyle bindings.
+       
+       * Common/zidestoreui.css: styles for tabs, resembling OGo look.
+
+       * Scheduler/OGoCalSelectTab.m: implemented dateLabel (for testing).
+
+       * Scheduler/OGoCalSelectTab.wox: corrected selection binding namespace.
+
+2004-06-08  Helge Hess  <helge.hess@opengroupware.org>
+
+       * Scheduler/NOTES: added class hierarchy
+
+       * */common.h, GNUmakefile.preamble.: fixed for OSX compile
+
+2004-06-08  Marcus Mueller  <znek@mulle-kybernetik.com>
+
+       * Common/images: added a bunch of images from OGo
+
+2004-06-07  Marcus Mueller  <znek@mulle-kybernetik.com>
+
+       * Custom/GNUmakefile: changed ZIDESTORE to include installed version
+         (ZideStore12). Removed post install hooks.
+
+       * Custom/GNUmakefile.postamble: new file, post install hooks and
+         xmllint for .wox.
+
+2004-06-07  Marcus Mueller  <znek@mulle-kybernetik.com>
+
+       * Scheduler/GNUmakefile: changed ZIDESTORE to include installed version
+         (ZideStore12). Removed post install hooks.
+
+       * Scheduler/GNUmakefile.postamble: post install hooks updated for
+         GNUSTEP_BUILD_DIR.
+
+2004-06-03  Helge Hess  <helge.hess@opengroupware.org>
+
+       * Scheduler/OGoCalWeekOverview.m: moved navigation URL generation to
+         superclass (now generic because we use the 'ownMethodName'). Could
+         even be moved to OGoCalView?
+       
+       * Scheduler/OGoCalMonthView.m: added next/prev month URL generation
+         methods, calculate startdate from form value
+
+       * Scheduler/OGoCalView.m: added -ownMethodName method to return the
+         last path component of the request URL (the SOPE method), eg
+         'weekoverview' for OGoCalWeekView, added 
+         -dateNavigationURLWithNewStartDate: method to calculate 'startDate'
+         URLs (should be improved to include existing query parameters!)
+
+       * Scheduler/OGoCalWeekOverview.m: minor tweaks ;-)
+
+2004-06-03  Marcus Mueller  <znek@mulle-kybernetik.com>
+
+       * Scheduler/OGoCalWeekView.m: construct startDate from formValue,
+         otherwise use current week's monday as startDate.
+
+       * Scheduler/OGoCalWeekOverview.wox: switch back/forth
+
+       * Scheduler/OGoCalWeekOverview.m: provide URLs for switching back/forth
+         weekoverview.
+
+       * Scheduler/OGoCalView.[hm]: methods for converting dates into strings
+         and vice versa.
+
+       * Scheduler/OGoAppointmentView.m, Scheduler/OGoCalView.m: fixed include
+
+       * ChangeLog: created
diff --git a/SOGo/UI/Common/CommonUIProduct.m b/SOGo/UI/Common/CommonUIProduct.m
new file mode 100644 (file)
index 0000000..b5a4da4
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+  Copyright (C) 2000-2003 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: CommonUIProduct.m,v 1.1 2003/11/24 01:24:40 helge Exp $
+
+#import <Foundation/NSObject.h>
+
+@interface CommonUIProduct : NSObject
+{
+}
+
+@end
+
+#include "common.h"
+
+@implementation CommonUIProduct
+@end /* CommonUIProduct */
diff --git a/SOGo/UI/Common/GNUmakefile b/SOGo/UI/Common/GNUmakefile
new file mode 100644 (file)
index 0000000..0fda272
--- /dev/null
@@ -0,0 +1,82 @@
+# $Id: GNUmakefile,v 1.2 2003/12/09 17:38:42 helge Exp $
+
+include $(GNUSTEP_MAKEFILES)/common.make
+
+ZIDESTORE=$(GNUSTEP_USER_ROOT)/Headers/ZideStore12
+
+
+BUNDLE_NAME        = CommonUI
+BUNDLE_EXTENSION   = .zsp
+BUNDLE_INSTALL_DIR = $(GNUSTEP_USER_ROOT)/Library/ZideStore12
+
+LIBRARY_NAME = libZideStoreCommonUI
+
+
+libZideStoreCommonUI_HEADER_FILES_DIR         = .
+libZideStoreCommonUI_HEADER_FILES_INSTALL_DIR = $(ZIDESTORE)/Common
+
+libZideStoreCommonUI_HEADER_FILES += \
+       UIxComponent.h \
+
+libZideStoreCommonUI_OBJC_FILES += \
+       UIxComponent.m \
+
+
+CommonUI_PRINCIPAL_CLASS = CommonUIProduct
+
+CommonUI_OBJC_FILES += \
+       CommonUIProduct.m       \
+       UIxPageFrame.m          \
+       UIxAppFrame.m           \
+       UIxAppHeader.m          \
+       UIxAppNavigation.m      \
+       UIxWinClose.m   \
+       UIxAppNavView.m \
+       \
+       UIxElemBuilder.m \
+       UIxTabView.m \
+       UIxTabItem.m \
+
+
+CommonUI_RESOURCE_FILES += \
+       Version                 \
+       product.plist           \
+       UIxPageFrame.wox        \
+       UIxAppFrame.wox         \
+       UIxAppHeader.wox        \
+       UIxAppNavigation.wox    \
+       UIxWinClose.wox \
+       UIxAppNavView.wox \
+       \
+       zidestoreui.css         \
+       calendar.css            \
+       \
+       images/OGoLogo.gif      \
+       images/menu_logo_top.gif        \
+       images/line_left.gif    \
+       images/line_stretch.gif \
+       images/line_right.gif   \
+       images/box_topleft.gif  \
+       images/box_top.gif      \
+       images/box_topright.gif \
+       images/box_left.gif     \
+       images/box_right.gif    \
+       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
+
+ADDITIONAL_INCLUDE_DIRS += \
+       -I. \
+       -I$(ZIDESTORE)/Frontend -I$(ZIDESTORE)/Backend -I$(ZIDESTORE)
+
+
+# make
+
+-include GNUmakefile.preamble
+include $(GNUSTEP_MAKEFILES)/library.make
+include $(GNUSTEP_MAKEFILES)/bundle.make
+-include GNUmakefile.postamble
diff --git a/SOGo/UI/Common/GNUmakefile.postamble b/SOGo/UI/Common/GNUmakefile.postamble
new file mode 100644 (file)
index 0000000..3986bcc
--- /dev/null
@@ -0,0 +1,17 @@
+# $Id: GNUmakefile.postamble,v 1.1 2004/05/12 14:45:56 helge Exp $
+
+validate-wox:
+       xmllint --noout *.wox
+
+before-all :: validate-wox
+
+
+ifneq ($(GNUSTEP_BUILD_DIR),)
+after-all ::
+       @(cp bundle-info.plist \
+         $(GNUSTEP_BUILD_DIR)/$(BUNDLE_NAME)$(BUNDLE_EXTENSION))
+else
+after-all ::
+       @(cd $(BUNDLE_NAME)$(BUNDLE_EXTENSION);\
+         cp ../bundle-info.plist .)
+endif
diff --git a/SOGo/UI/Common/GNUmakefile.preamble b/SOGo/UI/Common/GNUmakefile.preamble
new file mode 100644 (file)
index 0000000..e76e480
--- /dev/null
@@ -0,0 +1,16 @@
+# $Id$
+
+ifneq ($(GNUSTEP_BUILD_DIR),)
+       RELBUILD_DIR_libZideStoreCommonUI = $(GNUSTEP_OBJ_DIR)
+else
+       RELBUILD_DIR_libZideStoreCommonUI = $(GNUSTEP_OBJ_DIR)
+endif
+
+libZideStoreCommonUI_LIBRARIES_DEPEND_UPON += -lNGObjWeb
+
+CommonUI_LIB_DIRS += -L$(RELBUILD_DIR_libZideStoreCommonUI)
+
+CommonUI_BUNDLE_LIBS += \
+       -lNGObjWeb -lNGScripting \
+       -lNGMime -lNGStreams -lNGExtensions -lEOControl \
+       -lXmlRpc -lDOM -lSaxObjC -lZideStoreCommonUI
diff --git a/SOGo/UI/Common/UIxAppFrame.m b/SOGo/UI/Common/UIxAppFrame.m
new file mode 100644 (file)
index 0000000..8d9553f
--- /dev/null
@@ -0,0 +1,11 @@
+// $Id$
+
+#include <NGObjWeb/SoComponent.h>
+
+@interface UIxAppFrame : SoComponent
+@end
+
+#include "common.h"
+
+@implementation UIxAppFrame
+@end /* UIxAppFrame */
diff --git a/SOGo/UI/Common/UIxAppFrame.wox b/SOGo/UI/Common/UIxAppFrame.wox
new file mode 100644 (file)
index 0000000..0437cf3
--- /dev/null
@@ -0,0 +1,44 @@
+<?xml version='1.0' standalone='yes'?>
+
+<html xmlns="http://www.w3.org/1999/xhtml"
+      xmlns:var="http://www.skyrix.com/od/binding"
+      xmlns:const="http://www.skyrix.com/od/constant"
+>
+  <head>
+    <title><var:string value="title"/></title>
+    
+    <meta name="description" content="ZideStore Web Interface" />
+    <meta name="author"      content="SKYRIX Software AG" />
+    <meta name="robots"      content="stop" />
+    
+    <link href="mailto:hh@skyrix.com" rev="made" />
+  </head>
+  
+  <frameset rows="48,*" frameborder="0" framespacing="0" border="0">
+    
+    <frame src="appheader"
+           name="head"
+           leftmargin="0" topmargin="0" marginheight="0" marginwidth="0" 
+           scrolling="no" noresize="yes" />
+
+    <frameset cols="150,*">
+
+      <frame src="appnavigation"
+             name="navi"
+             leftmargin="0" topmargin="0" marginheight="0" marginwidth="0" 
+             scrolling="yes" />
+
+      <frame src="view"
+             name="content"
+             leftmargin="0" topmargin="0" marginheight="0" marginwidth="0" 
+             scrolling="yes" />
+
+    </frameset>
+
+  </frameset>
+
+  <noframes>
+    This pages requires frame tags, which your browser does not support,
+    sorry ;->
+  </noframes>
+</html>
diff --git a/SOGo/UI/Common/UIxAppHeader.m b/SOGo/UI/Common/UIxAppHeader.m
new file mode 100644 (file)
index 0000000..5a4db92
--- /dev/null
@@ -0,0 +1,11 @@
+// $Id$
+
+#include <NGObjWeb/SoComponent.h>
+
+@interface UIxAppHeader : SoComponent
+@end
+
+#include "common.h"
+
+@implementation UIxAppHeader
+@end /* UIxAppHeader */
diff --git a/SOGo/UI/Common/UIxAppHeader.wox b/SOGo/UI/Common/UIxAppHeader.wox
new file mode 100644 (file)
index 0000000..4f8c0d2
--- /dev/null
@@ -0,0 +1,32 @@
+<?xml version='1.0' standalone='yes'?>
+
+<html 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"
+>
+  <head>
+    <link type="text/css" rel="stylesheet" rsrc:href="zidestoreui.css" />
+
+    <script language="javascript">
+      function viewInNavi(url) {
+        parent.navi.location=url;
+        return true
+      }
+    </script>
+  </head>
+
+  <body>
+    <div id="header">
+      <img filename="OGoLogo.gif" class="headerlogo" alt="Logo" />
+      <div id="headerhistory">
+        <span id="navtitle">ZideStore UI - Experimental</span>
+      </div>
+    </div>
+    
+    <div style="text-align: right; font-size: 8pt;">
+      <a href="#" onClick="viewInNavi('appnavigation')">reload</a> -
+      resistance is obsolete <entity name="trade"/> ;-)
+    </div>
+  </body>
+</html>
diff --git a/SOGo/UI/Common/UIxAppNavView.m b/SOGo/UI/Common/UIxAppNavView.m
new file mode 100644 (file)
index 0000000..8bf1ff1
--- /dev/null
@@ -0,0 +1,104 @@
+/*
+  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$
+
+
+#import <NGObjWeb/NGObjWeb.h>
+#import <NGObjWeb/SoObject+SoDAV.h>
+#import <NGObjWeb/WOContext+SoObjects.h>
+#import <Foundation/Foundation.h>
+
+
+@interface UIxAppNavView : WOComponent
+{
+    id element;
+    id lastElement;
+}
+
+@end
+
+
+@implementation UIxAppNavView
+
+- (void)dealloc {
+    [self->element release];
+    [self->lastElement release];
+    [super dealloc];
+}
+
+- (void)setElement:(id)_element {
+    ASSIGN(self->element, _element);
+}
+
+- (id)element {
+    return self->element;
+}
+
+- (void)setLastElement:(id)_element {
+    ASSIGN(self->lastElement, _element);
+}
+
+- (id)lastElement {
+    return self->lastElement;
+}
+
+- (NSArray *)navPathElements {
+    NSArray *traversalObjects;
+    NSMutableArray *navPathComponents;
+    NSMutableString *navURL;
+    unsigned int i, count;
+
+    traversalObjects = [[self context] objectTraversalStack];
+    count = ([traversalObjects count] - 1); /* remove SoPageInvocation */
+    navPathComponents = [[NSMutableArray alloc] initWithCapacity:count];
+    navURL = [[NSMutableString alloc] initWithString:@"/"];
+
+    for(i = 0; i < count; i++) {
+        NSString *name, *url;
+        id obj;
+        
+        obj = [traversalObjects objectAtIndex:i];
+
+        name = [obj davDisplayName];
+        if(!name)
+            name = NSStringFromClass([obj class]);
+
+        [navURL appendString:name];
+        [navURL appendString:@"/"];
+        
+        if(! [name hasPrefix:@"ZideStore"]) {
+            NSMutableDictionary *c;
+
+            c = [[NSMutableDictionary alloc] initWithCapacity:2];
+            [c setObject:name forKey:@"name"];
+            url = [navURL copy];
+            [c setObject:url forKey:@"url"];
+            [url release];
+            [navPathComponents addObject:c];
+            [c release];
+        }
+    }
+
+    [self setLastElement:[navPathComponents lastObject]];
+    return [navPathComponents autorelease];
+}
+
+@end
diff --git a/SOGo/UI/Common/UIxAppNavView.wox b/SOGo/UI/Common/UIxAppNavView.wox
new file mode 100644 (file)
index 0000000..6e924d4
--- /dev/null
@@ -0,0 +1,10 @@
+<?xml version='1.0' standalone='yes'?>
+
+<font 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"
+      class="defaultfont"
+>
+<b>You are here:</b><var:entity const:name="nbsp" /><var:foreach list="navPathElements" item="element"><var:if condition="element" value="lastElement" const:negate="YES"><a var:href="element.url"><var:string value="element.name" /></a><var:entity const:name="nbsp" />/<var:entity const:name="nbsp" /></var:if><var:if condition="element" value="lastElement"><var:string value="element.name" /></var:if></var:foreach>
+</font>
\ No newline at end of file
diff --git a/SOGo/UI/Common/UIxAppNavigation.m b/SOGo/UI/Common/UIxAppNavigation.m
new file mode 100644 (file)
index 0000000..529127d
--- /dev/null
@@ -0,0 +1,11 @@
+// $Id$
+
+#include <NGObjWeb/SoComponent.h>
+
+@interface UIxAppNavigation : SoComponent
+@end
+
+#include "common.h"
+
+@implementation UIxAppNavigation
+@end /* UIxAppNavigation */
diff --git a/SOGo/UI/Common/UIxAppNavigation.wox b/SOGo/UI/Common/UIxAppNavigation.wox
new file mode 100644 (file)
index 0000000..27eadaf
--- /dev/null
@@ -0,0 +1,85 @@
+<?xml version='1.0' standalone='yes'?>
+
+<html 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"
+>
+  <head>
+    <link type="text/css" rel="stylesheet" rsrc:href="zidestoreui.css" />
+
+    <style>
+      a:link, a:visited, a:active, a:hover { 
+        text-decoration: none; 
+        font-family:     Arial, Helvetica, Helv, Sans-Serif;
+        font-size:       9pt;
+        color:           #0000FF;
+      }
+      a.reloadlink {
+        color:      black;
+      }
+
+      ul {
+        margin:          0; /*removes indent IE and Opera*/
+        padding:         0; /*removes indent Mozilla and NN7*/
+        /* list-style-type: none; */ /*turns off display of bullet*/
+        font-family:     Arial, Helvetica, sans-serif;
+        font-size:       14pt;
+      }
+
+      ul li {
+        /* padding-left: 4px; */
+        /* list-style: url(http://vesper.in.skyrix.com/SKYRiXgreen/WebServerResources/EN.lproj/nav_folder_open.gif); */
+        list-style: url(http://move:9000/OpenGroupware.woa/WebServerResources/English.lproj/icon_folder.gif);
+      }
+
+      ul li a {
+        display: block;
+        border:           1px solid #FFFFFF;
+        padding:          2px 2px 2px 24px;
+        width:            80%;
+        background-color: #EEEEEE;
+      }
+
+      ul li a:link, ul li a:visited {
+        text-decoration:  none;
+      }
+      ul li a:hover {
+        border:           1px solid #333333;
+        background-color: #CCCCCC;
+      }
+    </style>
+
+    <script language="javascript"><![CDATA[
+      function viewInContent(url) {
+        parent.content.location=url;
+        return true;
+      }
+    ]]></script>
+  </head>
+
+  <body leftmargin="0"  topmargin="0" marginwidth="0" marginheight="0">
+    <br />
+    <ul>
+      <li><a href="#">OGo</a></li>
+      <li><a href="#" onclick="viewInContent('view')"         >View</a></li>
+      <li><a href="#" onclick="viewInContent('weekoverview')" >Week</a></li>
+      <li><a href="#" onclick="viewInContent('monthoverview')">Month</a></li>
+      <li><a href="#">OGo</a></li>
+    </ul>
+    <br />
+    
+    <div style="border-top: 1px solid #000000;">
+      <a href="appnavigation" class="reloadlink" 
+         var:_o="context.contextID"><i>(reload)</i></a>
+    </div>
+
+    <br />
+
+    <div style="border-top: 1px solid #000000; font-size: 8pt">
+      <var:string value="context.contextID" />
+    </div>
+    <a href="http://www.projectseven.com/tutorials/css_menus/list_01/"
+       target="extlink">CSS Menues</a>
+  </body>
+</html>
diff --git a/SOGo/UI/Common/UIxComponent.h b/SOGo/UI/Common/UIxComponent.h
new file mode 100644 (file)
index 0000000..d9a0c6f
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+  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$
+
+
+#ifndef        __UIxComponent_H_
+#define        __UIxComponent_H_
+
+#include <NGObjWeb/SoComponent.h>
+
+@class NSCalendarDate;
+
+
+@interface UIxComponent : SoComponent
+{
+    NSMutableDictionary *queryParameters;
+}
+
+- (NSString *)queryParameterForKey:(NSString *)_key;
+- (NSDictionary *)queryParameters;
+
+/* use this to set 'sticky' query parameters */
+- (void)setQueryParameter:(NSString *)_param forKey:(NSString *)_key;
+
+/* appends queryParameters to _method if any are set */
+- (NSString *)completeHrefForMethod:(NSString *)_method;
+
+- (NSString *)ownMethodName;
+
+/* date selection */
+- (NSCalendarDate *)selectedDate;
+- (NSString *)dateStringForDate:(NSCalendarDate *)_date;
+- (NSCalendarDate *)dateForDateString:(NSString *)_dateString;
+
+@end
+
+#endif /* __UIxComponent_H_ */
diff --git a/SOGo/UI/Common/UIxComponent.m b/SOGo/UI/Common/UIxComponent.m
new file mode 100644 (file)
index 0000000..280bcd7
--- /dev/null
@@ -0,0 +1,168 @@
+/*
+  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 "UIxComponent.h"
+#include <Foundation/Foundation.h>
+#include <NGObjWeb/NGObjWeb.h>
+#include <NGExtensions/NGExtensions.h>
+
+
+@interface UIxComponent (PrivateAPI)
+- (void)_parseQueryString:(NSString *)_s;
+@end
+
+
+@implementation UIxComponent
+
+- (id)init {
+    if ((self = [super init])) {
+        self->queryParameters = [[NSMutableDictionary alloc] init];
+    }
+    return self;
+}
+
+- (void)dealloc {
+    [self->queryParameters release];
+    [super dealloc];
+}
+
+
+- (void)awake {
+    WORequest *req;
+    NSString *uri;
+    NSRange r;
+
+    [super awake];
+
+    req = [[self context] request];
+    uri = [req uri];
+    r = [uri rangeOfString:@"?"];
+    if(r.length > 0) {
+        NSString *qs;
+        
+        qs = [uri substringFromIndex:(r.location + r.length)];
+        [self->queryParameters removeAllObjects];
+        [self _parseQueryString:qs];
+    }    
+}
+
+- (void)_parseQueryString:(NSString *)_s {
+    NSEnumerator *e;
+    NSString *part;
+    
+    e = [[_s componentsSeparatedByString:@"&"] objectEnumerator];
+    while ((part = [e nextObject])) {
+        NSRange  r;
+        NSString *key, *value;
+        
+        r = [part rangeOfString:@"="];
+        if (r.length == 0) {
+            /* missing value of query parameter */
+            key   = [part stringByUnescapingURL];
+            value = @"1";
+        }
+        else {
+            key   = [[part substringToIndex:r.location] stringByUnescapingURL];
+            value = [[part substringFromIndex:(r.location + r.length)] 
+                stringByUnescapingURL];
+        }
+        [self->queryParameters setObject:value forKey:key];
+    }
+}
+
+- (NSString *)queryParameterForKey:(NSString *)_key {
+    return [self->queryParameters objectForKey:_key];
+}
+
+- (void)setQueryParameter:(NSString *)_param forKey:(NSString *)_key {
+    if(_key == nil)
+        return;
+
+    if(_param != nil)
+        [self->queryParameters setObject:_param forKey:_key];
+    else
+        [self->queryParameters removeObjectForKey:_key];
+}
+
+- (NSDictionary *)queryParameters {
+    return self->queryParameters;
+}
+
+- (NSString *)completeHrefForMethod:(NSString *)_method {
+    NSDictionary *qp;
+    NSString *qs;
+    
+    qp = [self queryParameters];
+    if([qp count] == 0)
+        return _method;
+    
+    qs = [[self context] queryStringFromDictionary:qp];
+    return [_method stringByAppendingFormat:@"?%@", qs];
+}
+
+- (NSString *)ownMethodName {
+    NSString *uri;
+    NSRange  r;
+    
+    uri = [[[self context] request] uri];
+    
+    /* first: cut off query parameters */
+    
+    r = [uri rangeOfString:@"?" options:NSBackwardsSearch];
+    if (r.length > 0)
+        uri = [uri substringToIndex:r.location];
+    
+    /* next: strip trailing slash */
+    
+    if ([uri hasSuffix:@"/"]) uri = [uri substringToIndex:([uri length] - 1)];
+    r = [uri rangeOfString:@"/" options:NSBackwardsSearch];
+    
+    /* then: cut of last path component */
+    
+    if (r.length == 0) // no slash? are we at root?
+        return @"/";
+    
+    return [uri substringFromIndex:(r.location + 1)];
+}
+
+/* date */
+
+- (NSCalendarDate *)selectedDate {
+    NSString *s;
+    
+    s = [self queryParameterForKey:@"day"];
+    if(s) {
+        return [self dateForDateString:s];
+    }
+    return [NSCalendarDate date];
+}
+
+- (NSString *)dateStringForDate:(NSCalendarDate *)_date {
+    return [_date descriptionWithCalendarFormat:@"%Y%m%d"];
+}
+
+- (NSCalendarDate *)dateForDateString:(NSString *)_dateString {
+    return [NSCalendarDate dateWithString:_dateString calendarFormat:@"%Y%m%d"];
+}
+
+@end
diff --git a/SOGo/UI/Common/UIxElemBuilder.m b/SOGo/UI/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/SOGo/UI/Common/UIxPageFrame.m b/SOGo/UI/Common/UIxPageFrame.m
new file mode 100644 (file)
index 0000000..ba39e5f
--- /dev/null
@@ -0,0 +1,44 @@
+// $Id$
+
+#include <NGObjWeb/SoComponent.h>
+#include <NGObjWeb/SoHTTPAuthenticator.h>
+#include <NGObjWeb/SoUser.h>
+
+
+@interface UIxPageFrame : SoComponent
+{
+  NSString *title;
+}
+
+@end
+
+#include "common.h"
+
+@implementation UIxPageFrame
+
+- (void)dealloc {
+  [self->title release];
+  [super dealloc];
+}
+
+/* accessors */
+
+- (void)setTitle:(NSString *)_value {
+  ASSIGN(self->title, _value);
+}
+
+- (NSString *)title {
+  return self->title;
+}
+
+- (NSString *)login {
+    WOContext *ctx;
+    SoUser *user;
+    
+    ctx = [self context];
+    user = [[[self clientObject] authenticatorInContext:ctx]
+                                 userInContext:ctx];
+    return [user login];
+}
+
+@end /* UIxPageFrame */
diff --git a/SOGo/UI/Common/UIxPageFrame.wox b/SOGo/UI/Common/UIxPageFrame.wox
new file mode 100644 (file)
index 0000000..efc1f4d
--- /dev/null
@@ -0,0 +1,308 @@
+<?xml version="1.0" standalone="yes"?>
+<html 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">
+  <head>
+    <title>
+      <var:string value="title"/>
+    </title>
+    <meta name="description" content="ZideStore Web Interface"/>
+    <meta name="author" content="SKYRIX Software AG"/>
+    <meta name="robots" content="stop"/>
+    <link type="text/css" rel="stylesheet" rsrc:href="zidestoreui.css"/>
+    <link type="text/css" rel="stylesheet" rsrc:href="calendar.css"/>
+    <link href="mailto:hh@skyrix.com" rev="made"/>
+  </head>
+  <body>
+<!--
+    <div id="header">
+      <img filename="OGoLogo.gif" class="headerlogo" alt="Logo" />
+      <div id="headerhistory">
+        <span id="navtitle">ZideStore UI - Experimental</span>
+      </div>
+    </div>
+    <br />
+-->
+    <table cellpadding="5" cellspacing="0" border="0" width="100%">
+      <tr>
+        <td colspan="2">
+          <table cellpadding="0" cellspacing="0" border="0" width="100%">
+            <tr>
+              <td valign="bottom">
+              <var:component className="UIxAppNavView" />
+              </td>
+              <td align="right">
+                <a href="http://www.opengroupware.org:80/" target="OGo">
+                  <img rsrc:src="menu_logo_top.gif" align="center" border="0" ALT="" Valign="middle"/>
+                </a>
+              </td>
+            </tr>
+          </table>
+          <table cellpadding="0" cellspacing="0" border="0" width="100%">
+            <tr>
+              <td class="linecolor">
+                <img rsrc:src="line_left.gif"/>
+              </td>
+              <td class="linecolor" width="100%">
+                <img rsrc:src="line_stretch.gif"/>
+              </td>
+              <td class="linecolor">
+                <img rsrc:src="line_right.gif"/>
+              </td>
+            </tr>
+          </table>
+        </td>
+      </tr>
+      <tr>
+        <td valign="top">
+          <table cellpadding="0" cellspacing="0" border="0" width="100%">
+            <tr>
+<!-- $Id: SkyDock.html,v 1.13 2004/02/13 14:08:27 helge Exp $ -->
+              <td valign="top">
+                <table border="0" cellspacing="0" cellpadding="0" class="leftmenu">
+                  <tr>
+                    <td>
+                      <img rsrc:src="box_topleft.gif"/>
+                    </td>
+                    <td valign="top" rsrc:background="box_top.gif">
+                      <img rsrc:src="box_top.gif"/>
+                    </td>
+                    <td>
+                      <img rsrc:src="box_topright.gif"/>
+                    </td>
+                  </tr>
+                  <tr valign="top">
+                    <td rsrc:background="box_left.gif">
+                      <img rsrc:src="box_left.gif"/>
+                    </td>
+                    <td width="100%">
+                      <table width="100%" border="0" cellspacing="2" cellpadding="" class="leftmenu">
+                        <tr>
+                          <td>
+                            <font class="skydockfont">
+                              <a href="/ZideStore/" class="skydockfont">SOGo (<var:string value="login" />)</a>
+                            </font>
+                          </td>
+                        </tr>
+                        <tr>
+                          <td colspan="2">
+                            <table cellpadding="0" cellspacing="0" border="0" width="100%">
+                              <tr>
+                                <td class="linecolor">
+                                  <img rsrc:src="line_left.gif"/>
+                                </td>
+                                <td class="linecolor" width="100%">
+                                  <img rsrc:src="line_stretch.gif"/>
+                                </td>
+                                <td class="linecolor">
+                                  <img rsrc:src="line_right.gif"/>
+                                </td>
+                              </tr>
+                            </table>
+                          </td>
+                        </tr>
+                        <tr>
+                          <td height="3"/>
+                        </tr>
+                        <tr>
+                          <td valign="middle">
+                            <font class="skydockfont">
+                              <a href="/OpenGroupware/x/dock" class="skydockfont">News</a>
+                            </font>
+                          </td>
+                        </tr>
+                        <tr>
+                          <td valign="middle">
+                            <font class="skydockfont">
+                              <a href="/OpenGroupware/x/dock" class="skydockfont">Projects</a>
+                            </font>
+                          </td>
+                        </tr>
+                        <tr>
+                          <td valign="middle">
+                            <font class="skydockfont">
+                              <a href="/OpenGroupware/x/dock" class="skydockfont">Contacts</a>
+                            </font>
+                          </td>
+                        </tr>
+                        <tr>
+                          <td valign="middle">
+                            <font class="skydockfont">
+                              <a href="/OpenGroupware/x/dock" class="skydockfont">Companies</a>
+                            </font>
+                          </td>
+                        </tr>
+                        <tr>
+                          <td valign="middle">
+                            <font class="skydockfont">
+                              <a href="/OpenGroupware/x/dock" class="skyDockFont">Calendar</a>
+                            </font>
+                          </td>
+                        </tr>
+                        <tr>
+                          <td valign="middle">
+                            <font class="skydockfont">
+                              <a href="/OpenGroupware/x/dock" class="skydockfont">Tasks</a>
+                            </font>
+                          </td>
+                        </tr>
+                      </table>
+                    </td>
+                    <td rsrc:background="box_right.gif">
+                      <img rsrc:src="box_right.gif"/>
+                    </td>
+                  </tr>
+                  <tr>
+                    <td>
+                      <img rsrc:src="box_botleft.gif"/>
+                    </td>
+                    <td rsrc:background="box_bottom.gif">
+                      <img rsrc:src="box_bottom.gif"/>
+                    </td>
+                    <td>
+                      <img rsrc:src="box_botright.gif"/>
+                    </td>
+                  </tr>
+                </table>
+<!-- $Id: SkyDockedProjects.html,v 1.10 2004/05/07 16:05:03 helge Exp $ -->
+              </td>
+            </tr>
+          </table>
+          <br/>
+<!-- $Id: SkyFavorites.html,v 1.5 2003/10/29 18:06:00 helge Exp $ -->
+<!-- the misc box -->
+          <span>
+            <table cellspacing="0" class="leftmenu" border="0" cellpadding="0">
+              <tr>
+                <td>
+                  <img rsrc:src="box_topleft.gif"/>
+                </td>
+                <td rsrc:background="box_top.gif">
+                  <img rsrc:src="box_top.gif"/>
+                </td>
+                <td>
+                  <img rsrc:src="box_topright.gif"/>
+                </td>
+              </tr>
+              <tr valign="top">
+                <td rsrc:background="box_left.gif">
+                  <img rsrc:src="box_left.gif"/>
+                </td>
+                <td width="100%">
+                  <table width="100%" cellspacing="2" class="leftmenu" border="0" cellpadding="">
+                    <tr>
+                      <td>
+                        <font class="skydockfont">Misc</font>
+                      </td>
+                    </tr>
+                    <tr>
+                      <td colspan="2">
+                        <table width="100%" cellspacing="0" border="0" cellpadding="0">
+                          <tr>
+                            <td class="linecolor">
+                              <img rsrc:src="line_left.gif"/>
+                            </td>
+                            <td width="100%" class="linecolor">
+                              <img rsrc:src="line_stretch.gif"/>
+                            </td>
+                            <td class="linecolor">
+                              <img rsrc:src="line_right.gif"/>
+                            </td>
+                          </tr>
+                        </table>
+                      </td>
+                    </tr>
+                    <tr>
+                      <td height="3"/>
+                    </tr>
+                    <tr>
+                      <td valign="middle">
+                        <a href="/OpenGroupware/x/mail" class="skydockfont">New Email</a>
+                      </td>
+                    </tr>
+                    <tr>
+                      <td valign="middle">
+                        <a href="/OpenGroupware/x/mail" class="skydockfont">Inbox</a>
+                      </td>
+                    </tr>
+                    <tr>
+                      <td valign="middle">
+                        <a href="/OpenGroupware/x/dock" class="skydockfont">Preferences</a>
+                      </td>
+                    </tr>
+                    <tr>
+                      <td valign="middle">
+                        <a href="/OpenGroupware/x/downloadBookmark" target="private_desktop" class="skydockfont">Home</a>
+                      </td>
+                    </tr>
+                    <tr>
+                      <td valign="middle">
+                        <a href="/OpenGroupware/x/downloadBookmark" target="public_desktop" class="skydockfont">Desktop</a>
+                      </td>
+                    </tr>
+                    <tr>
+                      <td valign="middle">
+                        <a href="/OpenGroupware/x/dock" class="skydockfont">Logout</a>
+                      </td>
+                    </tr>
+                  </table>
+                </td>
+                <td rsrc:background="box_right.gif">
+                  <img rsrc:src="box_right.gif"/>
+                </td>
+              </tr>
+              <tr>
+                <td>
+                  <img rsrc:src="box_botleft.gif"/>
+                </td>
+                <td rsrc:background="box_bottom.gif">
+                  <img rsrc:src="box_bottom.gif"/>
+                </td>
+                <td>
+                  <img rsrc:src="box_botright.gif"/>
+                </td>
+              </tr>
+            </table>
+          </span>
+        </td>
+        <td valign="top" width="100%">
+          <var:component-content/>
+        </td>
+      </tr>
+      <tr>
+        <td colspan="2">
+          <table cellpadding="0" cellspacing="0" border="0" width="100%">
+            <tr>
+              <td class="linecolor">
+                <img rsrc:src="line_left.gif"/>
+              </td>
+              <td class="linecolor" width="100%">
+                <img rsrc:src="line_stretch.gif"/>
+              </td>
+              <td class="linecolor">
+                <img rsrc:src="line_right.gif"/>
+              </td>
+            </tr>
+            <tr>
+              <td colspan="3"/>
+            </tr>
+          </table>
+          <table cellpadding="0" cellspacing="0" border="0" width="100%">
+            <tr>
+              <td valign="top" align="left">
+                <font class="defaultfont"><var:entity const:name="copy"/>
+      2000-2004 <a href="http://www.skyrix.com:80/knoppix/skyrix/" target="SKYRIX">SKYRIX Software AG</a>.
+      We welcome your
+      <a href="http://www.opengroupware.org/en/feedback.html" target="feedback">feedback</a>.
+        </font>
+              </td>
+              <td valign="top" align="right">
+                <font class="defaultfont">
+          No sessions required! ;-)
+        </font>
+              </td>
+            </tr>
+          </table>
+        </td>
+      </tr>
+    </table>
+  </body>
+</html>
diff --git a/SOGo/UI/Common/UIxTabItem.m b/SOGo/UI/Common/UIxTabItem.m
new file mode 100644 (file)
index 0000000..21046f9
--- /dev/null
@@ -0,0 +1,475 @@
+/*
+  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->label    = WOExtGetProperty(_config, @"label");
+
+    self->isScript = WOExtGetProperty(_config, @"isScript");
+    self->href     = WOExtGetProperty(_config, @"href");
+
+    self->icon     = WOExtGetProperty(_config, @"icon");
+    self->action   = WOExtGetProperty(_config, @"action");
+
+    self->tabStyle         = WOExtGetProperty(_config, @"tabStyle");
+    self->selectedTabStyle = WOExtGetProperty(_config, @"selectedTabStyle");
+
+    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->key      release];
+  [self->label    release];
+
+  [self->href   release];
+
+  [self->action   release];
+
+  [self->isScript release];
+  [self->template release];
+
+  [self->tabStyle release];
+  [self->selectedTabStyle release];
+
+  [self->icon     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]];
+    
+#if 0
+    result = [self->action valueInComponent:[_ctx component]];
+#endif
+
+    [_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];
+#if 0
+  info->uri      = [[_ctx componentActionURL] copy];
+#else
+  info->uri      = [[self->href stringValueInComponent:cmp] copy];
+#endif
+  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];
+  info->tabStyle         = [[self->tabStyle stringValueInComponent:cmp] copy];
+  info->selectedTabStyle = [[self->selectedTabStyle 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/SOGo/UI/Common/UIxTabView.h b/SOGo/UI/Common/UIxTabView.h
new file mode 100644 (file)
index 0000000..8224b44
--- /dev/null
@@ -0,0 +1,134 @@
+/*
+  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 *bodyStyle;
+  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 *label;
+
+  WOAssociation *href;
+  WOAssociation *isScript;
+
+  WOAssociation *action;
+  WOAssociation *icon;
+
+  /* config: */
+  WOAssociation *tabStyle;
+  WOAssociation *selectedTabStyle;
+
+  /* old 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/SOGo/UI/Common/UIxTabView.m b/SOGo/UI/Common/UIxTabView.m
new file mode 100644 (file)
index 0000000..ac635c3
--- /dev/null
@@ -0,0 +1,819 @@
+/*
+  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->bodyStyle          = WOExtGetProperty(_config, @"bodyStyle");
+    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");
+
+    self->template = RETAIN(_subs);
+  }
+  return self;
+}
+
+- (void)dealloc {
+  [self->selection release];
+
+  [self->headerStyle release];
+  [self->bodyStyle 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]];
+  NSLog(@"%s activeTabKey:%@", __PRETTY_FUNCTION__, activeTabKey);
+  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
+{
+  NSString    *headUri    = nil;
+  NSString    *label      = nil;
+  NSString    *scriptHref = nil;
+  NSString    *styleName  = nil;
+
+  WEClientCapabilities *ccaps;
+  WOComponent *comp;
+
+  ccaps = [[_ctx request] clientCapabilities];
+
+  comp = [_ctx component];
+  headUri = _info->uri;
+
+  if ((label = _info->label) == nil)
+    label = _info->key;
+  
+  if (_isActive) {
+    styleName = (_info->selectedTabStyle)
+      ? _info->selectedTabStyle
+      : [self->selectedTabStyle stringValueInComponent:comp];
+  }
+  else {
+    styleName = (_info->tabStyle)
+      ? _info->tabStyle
+      : [self->tabStyle stringValueInComponent:comp];
+  }
+  
+  [_response appendContentString:@"<td align='center' valign='middle'"];
+  
+  if (styleName) {
+      [_response appendContentString:@" class='"];
+      [_response appendContentHTMLAttributeValue:styleName];
+      [_response appendContentCharacter:'\''];
+  }
+
+  // click on td background
+  if ([ccaps isInternetExplorer] && [ccaps isJavaScriptBrowser]) {
+      [_response appendContentString:@" onclick=\"window.location.href='"];
+      [_response appendContentHTMLAttributeValue:headUri];
+      [_response appendContentString:@"'\""];
+  }
+  
+  [_response appendContentCharacter:'>'];
+
+  [_response appendContentString:@"<a href=\""];
+  
+  if (_doScript && (_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 ([label length] < 1)
+      label = _info->key;
+  [_response appendContentString:@"<nobr>"];
+  [_response appendContentHTMLString:label];
+  [_response appendContentString:@"</nobr>"];
+  
+  [_response appendContentString:@"</a>"];
+
+  [_response appendContentString:@"</td>"];
+
+#if 0
+  if (_doScript && (_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
+  }
+#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;
+  NSString  *styleName;
+  
+  doForm = NO;  /* generate form controls ? */
+  
+  [_response appendContentString:@"<tr><td colspan='2'>"];
+  
+  styleName = [self->headerStyle stringValueInComponent:[_ctx component]];
+  if(styleName) {
+      [_response appendContentString:
+          @"<table border='0' cellpadding='0' cellspacing='0' class='"];
+      [_response appendContentHTMLAttributeValue:styleName];
+      [_response appendContentString:@"'><tr>"];
+  }
+  else {
+      [_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
+{
+  NSString *styleName;
+  [_response appendContentString:@"  <tr"];
+    
+  styleName = [self->bodyStyle stringValueInComponent:[_ctx component]];
+  if(styleName) {
+    [_response appendContentString:@" class='"];
+    [_response appendContentHTMLAttributeValue:styleName];
+    [_response appendContentCharacter:'\''];
+  }
+  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;
+  NSString *styleName;
+
+  styleName = [self->bodyStyle stringValueInComponent:[_ctx component]];
+  ccaps = [[_ctx request] clientCapabilities];
+
+  /* put additional padding table into content ??? */
+  indentContent = [ccaps isFastTableBrowser] && ![ccaps isTextModeBrowser];
+  
+  [_response appendContentString:@"<tr"];
+  if(styleName) {
+    [_response appendContentString:@" class='"];
+    [_response appendContentHTMLAttributeValue:styleName];
+    [_response appendContentCharacter:'\''];
+  }
+  [_response appendContentString:@"><td colspan='2'"];
+  if (bgcolor) {
+    [_response appendContentString:@" bgcolor=\""];
+    [_response appendContentHTMLAttributeValue:bgcolor];
+    [_response appendContentCharacter:'\"'];
+  }
+  [_response appendContentCharacter:'>'];
+    
+  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];
+
+#if 0
+  /* header foot row */
+
+  [self _appendHeaderFootRowToResponse:_response inContext:_ctx
+        bgcolor:bgcolor
+        doScript:doScript
+        isLeftActive:isLeftActive];
+#endif
+
+  /* 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 */
diff --git a/SOGo/UI/Common/UIxWinClose.m b/SOGo/UI/Common/UIxWinClose.m
new file mode 100644 (file)
index 0000000..e8320e6
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+  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 UIxWinClose : WOComponent
+{
+
+}
+
+@end
+
+
+@implementation UIxWinClose
+
+@end
diff --git a/SOGo/UI/Common/UIxWinClose.wox b/SOGo/UI/Common/UIxWinClose.wox
new file mode 100644 (file)
index 0000000..35769e4
--- /dev/null
@@ -0,0 +1,6 @@
+<?xml version='1.0' standalone='yes'?>
+<a 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"
+   href="javascript:history.back()"><img border="0" alt="X" src="/ZideStore/so/ControlPanel/Products/CommonUI/Resources/closewindow.gif"/></a>
diff --git a/SOGo/UI/Common/Version b/SOGo/UI/Common/Version
new file mode 100644 (file)
index 0000000..d64ce5a
--- /dev/null
@@ -0,0 +1,5 @@
+# $Id: Version,v 1.1 2003/11/24 01:24:40 helge Exp $
+
+SUBMINOR_VERSION:=1
+
+# 1.1.0 requires NGObjWeb 4.2.202
diff --git a/SOGo/UI/Common/bundle-info.plist b/SOGo/UI/Common/bundle-info.plist
new file mode 100644 (file)
index 0000000..c7081c1
--- /dev/null
@@ -0,0 +1,40 @@
+{
+  "__cvs__" = "$Id: bundle-info.plist,v 1.1 2003/11/24 01:24:40 helge Exp $";
+
+  requires = {
+    bundleManagerVersion = 1;
+    classes = (
+      { name = NSObject;    }
+    );
+  };
+
+  provides = {
+    ZideStoreProducts = ( { name = CommonUIProduct; } );
+    
+    classes = (
+      { name = CommonUIProduct;       },
+      { name = UIxComponent;          },
+      { name = UIxPageFrame;          },
+      { name = UIxWinClose;           },
+      { name = UIxAppNavView;         },
+      { name = "UIxElemBuilder"; },
+      { name = "UIxTabView";          },
+      { name = "UIxTabItem";          },
+    );
+
+    WOComponents = (
+      { name = UIxPageFrame;  },
+      { name = UIxWinClose;   },
+      { name = UIxAppNavView; },
+    );
+    
+    WOxElemBuilder = (
+      { name = "UIxElemBuilder"; },
+    );
+
+    WODynamicElements = (
+      { name = "UIxTabView";          },
+      { name = "UIxTabItem";          },
+    );
+  };
+}
diff --git a/SOGo/UI/Common/calendar.css b/SOGo/UI/Common/calendar.css
new file mode 100644 (file)
index 0000000..34553bb
--- /dev/null
@@ -0,0 +1,189 @@
+.aptview_title {
+  font-size:        10pt;
+  font-family:      Arial, Helvetica, Verdana, Geneva, Tahoma, sans-serif;
+  color:            #000000;
+  font-weight:      bold;
+}
+
+.aptview_text {
+  font-size:        10pt;
+  font-family:      Arial, Helvetica, Verdana, Geneva, Tahoma, sans-serif;
+  color:            #000000;
+}
+
+.weekoverview_title {
+  font-size:        10pt;
+  font-family:      Arial, Helvetica, Verdana, Geneva, Tahoma, sans-serif;
+  letter-spacing:   0pt;
+  color:            #000000;
+  background-color: #d2d2cc;
+}
+
+.weekoverview_title a {
+  color:            #0033cc;
+  text-decoration: none;
+}
+
+.weekoverview_title_hilite {
+  font-size:        10pt;
+  font-family:      Arial, Helvetica, Verdana, Geneva, Tahoma, sans-serif;
+  letter-spacing:   0pt;
+  color:            #000000;
+  background-color: #d2d2cc;
+  font-weight:      bold;
+}
+
+.weekoverview_title_hilite a {
+  color:            #0033cc;
+  text-decoration: none;
+}
+
+.weekoverview_title_daylink {
+  font-size:        12pt;
+  color:            #0033cc;
+  font-weight:      bold;
+}
+
+.weekoverview_title_newlink {
+  font-size:        8pt;
+}
+
+.weekoverview_holidayinfo {
+  font-size:        8pt;
+  font-weight:      bold;
+}
+
+.weekoverview_content {
+  color:            #FFFFFF;
+  background-color: #e8e8e0;
+}
+
+.weekoverview_content a {
+  color:           #0000FF;
+  font-family:     Arial, Helvetica, Verdana, Geneva, Tahoma, sans-serif;
+  letter-spacing:  0pt;
+  text-decoration: none;
+}
+
+.weekoverview_content_hilite {
+  background-color: #fffff0;
+}
+
+.weekoverview_content_hilite a {
+  color:           #0000FF;
+  font-family:     Arial, Helvetica, Verdana, Geneva, Tahoma, sans-serif;
+  letter-spacing:  0pt;
+  text-decoration: none;
+}
+
+.monthoverview {
+  color:            #000000;
+  font-family:      Arial, Helvetica, Verdana, Geneva, Tahoma, sans-serif;
+  font-size:        10pt;
+  letter-spacing:   0pt;
+  padding:          2px;
+}
+
+.monthoverview a {
+  color:            #0033cc;
+  font-family:      Arial, Helvetica, Verdana, Geneva, Tahoma, sans-serif;
+  font-size:        7pt;
+  font-style:       normal;
+  font-weight:      normal;
+  letter-spacing:   0pt;
+  text-decoration:  none;
+}
+
+.monthoverview a:hover {
+  text-decoration:  underline;
+}
+
+.monthoverview_title {
+  background-color: #d2d2cc;
+  text-align:       center;
+}
+
+.monthoverview_week {
+  background-color: #d2d2cc;
+  width:            16pt;
+  text-align:       center;
+  vertical-align:   middle;
+}
+
+.monthoverview_week a {
+  color:            #000000;
+  font-size:        10pt;
+}
+
+.monthoverview_week_hilite {
+  background-color: #fffff0;
+  width:            16pt;
+  text-align:       center;
+  vertical-align:   middle;
+}
+
+.monthoverview_week_hilite a {
+  color:            #000000;
+  font-size:        10pt;
+}
+
+.monthoverview_content {
+  background-color: #e8e8e0;
+  font-size:        9pt;
+  height:           60;
+}
+
+.monthoverview_content a {
+  font-style:       italic;
+  font-weight:      bold;
+}
+
+.monthoverview_content td {
+  text-align:       let;
+  vertical-align:   top;
+}
+
+
+.monthoverview_content_hilite {
+  background-color: #fffff0;
+  font-size:        9pt;
+  height:           60;
+}
+
+.monthoverview_content_hilite a {
+  font-style:       italic;
+  font-weight:      bold;
+}
+
+.monthoverview_content_dimmed {
+  background-color: #d2d2cc;
+  font-size:        9pt;
+  height:           60;
+}
+
+.monthoverview_content_dimmed a {
+  font-style:       normal;
+  font-weight:      normal;
+}
+
+.monthoverview_day a {
+  color:            #000000;
+  font-family:      Arial, Helvetica, Verdana, Geneva, Tahoma, sans-serif;
+  font-size:        12pt;
+}
+
+.monthoverview_day_new a {
+  font-style:       normal;
+  font-weight:      normal;
+}
+
+.monthoverview_day_new a:hover {
+  font-style:       normal;
+  font-weight:      normal;
+  color:            #ff0000;
+}
+
+.monthoverview_content_link {
+  font-style:       normal;
+  font-weight:      normal;
+}
diff --git a/SOGo/UI/Common/common.h b/SOGo/UI/Common/common.h
new file mode 100644 (file)
index 0000000..ea759a9
--- /dev/null
@@ -0,0 +1,155 @@
+/*
+  Copyright (C) 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: common.h,v 1.1 2003/11/24 01:24:40 helge Exp $
+
+#import <Foundation/Foundation.h>
+
+#if LIB_FOUNDATION_LIBRARY
+#  include <Foundation/exceptions/GeneralExceptions.h>
+#elif NeXT_Foundation_LIBRARY || COCOA_Foundation_LIBRARY
+#  include <NGExtensions/NGObjectMacros.h>
+#  include <NGExtensions/NSString+Ext.h>
+#endif
+
+#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 = [propValue retain];
+        [(NSMutableDictionary *)_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/SOGo/UI/Common/images/OGoLogo.gif b/SOGo/UI/Common/images/OGoLogo.gif
new file mode 100755 (executable)
index 0000000..ea1b5f5
Binary files /dev/null and b/SOGo/UI/Common/images/OGoLogo.gif differ
diff --git a/SOGo/UI/Common/images/box_botleft.gif b/SOGo/UI/Common/images/box_botleft.gif
new file mode 100644 (file)
index 0000000..edaa190
Binary files /dev/null and b/SOGo/UI/Common/images/box_botleft.gif differ
diff --git a/SOGo/UI/Common/images/box_botright.gif b/SOGo/UI/Common/images/box_botright.gif
new file mode 100644 (file)
index 0000000..bb8be1b
Binary files /dev/null and b/SOGo/UI/Common/images/box_botright.gif differ
diff --git a/SOGo/UI/Common/images/box_bottom.gif b/SOGo/UI/Common/images/box_bottom.gif
new file mode 100644 (file)
index 0000000..c63a9cf
Binary files /dev/null and b/SOGo/UI/Common/images/box_bottom.gif differ
diff --git a/SOGo/UI/Common/images/box_left.gif b/SOGo/UI/Common/images/box_left.gif
new file mode 100644 (file)
index 0000000..260636d
Binary files /dev/null and b/SOGo/UI/Common/images/box_left.gif differ
diff --git a/SOGo/UI/Common/images/box_right.gif b/SOGo/UI/Common/images/box_right.gif
new file mode 100644 (file)
index 0000000..5315a06
Binary files /dev/null and b/SOGo/UI/Common/images/box_right.gif differ
diff --git a/SOGo/UI/Common/images/box_top.gif b/SOGo/UI/Common/images/box_top.gif
new file mode 100644 (file)
index 0000000..768bd4f
Binary files /dev/null and b/SOGo/UI/Common/images/box_top.gif differ
diff --git a/SOGo/UI/Common/images/box_topleft.gif b/SOGo/UI/Common/images/box_topleft.gif
new file mode 100644 (file)
index 0000000..0ede378
Binary files /dev/null and b/SOGo/UI/Common/images/box_topleft.gif differ
diff --git a/SOGo/UI/Common/images/box_topright.gif b/SOGo/UI/Common/images/box_topright.gif
new file mode 100644 (file)
index 0000000..5b3ca17
Binary files /dev/null and b/SOGo/UI/Common/images/box_topright.gif differ
diff --git a/SOGo/UI/Common/images/closewindow.gif b/SOGo/UI/Common/images/closewindow.gif
new file mode 100644 (file)
index 0000000..f4305d6
Binary files /dev/null and b/SOGo/UI/Common/images/closewindow.gif differ
diff --git a/SOGo/UI/Common/images/corner_right.gif b/SOGo/UI/Common/images/corner_right.gif
new file mode 100644 (file)
index 0000000..75b945d
Binary files /dev/null and b/SOGo/UI/Common/images/corner_right.gif differ
diff --git a/SOGo/UI/Common/images/line_left.gif b/SOGo/UI/Common/images/line_left.gif
new file mode 100644 (file)
index 0000000..19415f3
Binary files /dev/null and b/SOGo/UI/Common/images/line_left.gif differ
diff --git a/SOGo/UI/Common/images/line_right.gif b/SOGo/UI/Common/images/line_right.gif
new file mode 100644 (file)
index 0000000..504b5ce
Binary files /dev/null and b/SOGo/UI/Common/images/line_right.gif differ
diff --git a/SOGo/UI/Common/images/line_stretch.gif b/SOGo/UI/Common/images/line_stretch.gif
new file mode 100644 (file)
index 0000000..481e301
Binary files /dev/null and b/SOGo/UI/Common/images/line_stretch.gif differ
diff --git a/SOGo/UI/Common/images/menu_logo_top.gif b/SOGo/UI/Common/images/menu_logo_top.gif
new file mode 100644 (file)
index 0000000..ea1b5f5
Binary files /dev/null and b/SOGo/UI/Common/images/menu_logo_top.gif differ
diff --git a/SOGo/UI/Common/images/tab_.gif b/SOGo/UI/Common/images/tab_.gif
new file mode 100644 (file)
index 0000000..ad720a0
Binary files /dev/null and b/SOGo/UI/Common/images/tab_.gif differ
diff --git a/SOGo/UI/Common/images/tab_selected.gif b/SOGo/UI/Common/images/tab_selected.gif
new file mode 100644 (file)
index 0000000..2cbdea6
Binary files /dev/null and b/SOGo/UI/Common/images/tab_selected.gif differ
diff --git a/SOGo/UI/Common/product.plist b/SOGo/UI/Common/product.plist
new file mode 100644 (file)
index 0000000..1636c42
--- /dev/null
@@ -0,0 +1,47 @@
+{
+  requires = ( MAIN );
+
+  publicResources = (
+    calendar.css,
+    zidestoreui.css,
+    menu_logo_top.gif,
+    line_left.gif,
+    line_stretch.gif,
+    line_right.gif,
+    box_topleft.gif,
+    box_top.gif,
+    box_topright.gif,
+    box_left.gif,
+    box_right.gif,
+    box_botleft.gif,
+    box_bottom.gif,
+    box_botright.gif,
+    tab_selected.gif,
+    tab_.gif,
+    corner_right.gif,
+    closewindow.gif,
+    OGoLogo.gif
+  );
+  
+  factories = {
+  };
+
+  categories = {
+    SxFolder = {
+      methods = {
+        "app" = { 
+          protectedBy = "View";
+          pageName    = "UIxAppFrame"; 
+        };
+        "appheader" = { 
+          protectedBy = "View";
+          pageName    = "UIxAppHeader"; 
+        };
+        "appnavigation" = { 
+          protectedBy = "View";
+          pageName    = "UIxAppNavigation"; 
+        };
+      };
+    };
+  };
+}
diff --git a/SOGo/UI/Common/zidestoreui.css b/SOGo/UI/Common/zidestoreui.css
new file mode 100644 (file)
index 0000000..5d1e878
--- /dev/null
@@ -0,0 +1,199 @@
+/* ZideStore UI Stylesheet */
+
+/* common stuff */
+
+body {
+  color:            #000000;
+  font-family:      Arial, Helvetica, Verdana, Geneva, Tahoma, sans-serif;
+  font-size:        10pt;
+  background-color: #FFFFFF;
+  margin:           0px;
+  margin-top:       0px;
+  margin-bottom:    0px;
+  margin-left:      0px;
+  margin-right:     0px;
+}
+
+a:link {
+  color:       #0033CC;
+  font-family: Arial, Helvetica, Verdana, Geneva, Tahoma, sans-serif;
+  text-decoration: none;
+}
+a:visited {
+  color:       #660066;
+  font-family: Arial, Helvetica, Verdana, Geneva, Tahoma, sans-serif;
+  text-decoration: none;
+}
+a:hover {
+  color:       #FF0000;
+  font-family: Arial, Helvetica, Verdana, Geneva, Tahoma, sans-serif;
+  text-decoration: underline;
+}
+
+.linecolor {
+  background-color: #06348B;
+}
+
+font.defaultfont {
+  text-decoration:  none;
+  font-family:      Arial, Helvetica, Verdana, Geneva, Tahoma, sans-serif;
+  font-size:        8pt;
+  color:            #000000;
+}
+
+.window_label {
+  color:            #06348b;
+  font-family:      Arial, Helvetica, Verdana, Geneva, Tahoma, sans-serif;
+  font-size:        12pt;
+  font-weight:      bold;
+}
+
+
+/* tabs */
+
+.tab {
+  color:            #000000;
+  background-color: #e8e8e0;
+  font-size:        10pt;
+  text-decoration:  none;
+  width:            100px; 
+  height:           22px;
+  border-top:       1px solid #06348b;
+  border-right:     1px solid #06348b;
+}
+
+.tab a {
+  color:            #000000;
+  border:           none;
+  text-decoration:  none;
+}
+
+.tab_selected {
+  color:            #000000;
+  background-color: #f5f5e9;
+  font-size:        10pt;
+  text-decoration:  none;
+  font-weight:      bold;
+  width:            100px; 
+  height:           22px;
+  border-top:       1px solid #06348b;
+  border-right:     1px solid #06348b;
+}
+
+.tab_selected a {
+  color:            #000000;
+  border:           none;
+  text-decoration:  none;
+}
+
+.tabview_body {
+  background-color: #f5f5e9;
+}
+
+
+/* buttons */
+
+.button_auto_env {
+  height:           16px;
+  text-align:       center;
+  vertical-align:   middle;
+  padding:          0px 0px 0px 0px;
+  margin:           0px 0px 0px 0px;
+  overflow:         hidden;
+}
+
+.button_auto_env a {
+  text-decoration:  none;
+  color:            #000000;
+}
+
+.button_auto_env a:hover {
+  text-decoration:  underline;
+  color:            #ff0000;
+}
+
+.button_auto {
+  height:           20px;
+  border-style:     outset;
+  border-color:     #DDDDDD;
+  border-width:     2px;
+  color:            #000000;
+  background-color: #e8e8e0;
+  font-size:        8pt;
+  font-family:      Arial, Helvetica, Verdana, Geneva, Tahoma, sans-serif;
+  letter-spacing:   0pt;
+  text-decoration:  none;
+  text-color:       #000000;
+  text-align:       center;
+  vertical-align:   middle;
+  padding-left:     5px;
+  padding-right:    5px;
+  padding-top:      1px;
+  padding-bottom:   1px;
+  overflow:         hidden;
+}
+
+
+/* header */
+
+div#header {
+  margin-left:  5px;
+  margin-right: 5px;
+  padding:      0;
+  border-bottom: 1px solid #000000;
+}
+div#header img.headerlogo {
+  float:  right; 
+  width:  182px; 
+  height: 30px;
+}
+
+div#header div#headerhistory {
+  font-size:   11px;
+  color:       #000000;
+  margin:      0px;
+  padding-top: 18px;
+  height:      12px;
+}
+div#header a, div#header span {
+  margin:      0px;
+}
+div#header span#navtitle {
+  font-weight: bold;
+}
+div#header a:hover {
+  text-decoration: none;
+}
+
+/* the dock */
+
+a.skydockfont {
+  text-decoration:  none;
+  font-family:      Arial, Helvetica, Verdana, Geneva, Tahoma, sans-serif;
+  font-size:        8pt;
+  color:            #06348B;
+}
+font.skydockfont {
+  text-decoration:  none;
+  font-family:      Arial, Helvetica, Verdana, Geneva, Tahoma, sans-serif;
+  font-size:        8pt;
+  color:            #06348B;
+}
+font.skydockfont_inactiveMail {
+  text-decoration:  none;
+  font-family:      Arial, Helvetica, Verdana, Geneva, Tahoma, sans-serif;
+  font-size:        8pt;
+  color:            #CCCCCC;
+  font-weight:      bold;
+}
+font.skydockfont_newMail {
+  text-decoration:  none;
+  font-family:      Arial, Helvetica, Verdana, Geneva, Tahoma, sans-serif;
+  font-size:        8pt;
+  color:            #06348B;
+  font-weight:      bold;
+}
+table.skytextdocktable {
+  padding:        0px;
+  table-layout:   auto;
+}
diff --git a/SOGo/UI/GNUmakefile b/SOGo/UI/GNUmakefile
new file mode 100644 (file)
index 0000000..6885564
--- /dev/null
@@ -0,0 +1,9 @@
+# $Id$
+
+include $(GNUSTEP_MAKEFILES)/common.make
+
+SUBPROJECTS = \
+       Common          \
+       Scheduler       \
+
+include $(GNUSTEP_MAKEFILES)/aggregate.make
diff --git a/SOGo/UI/Scheduler/COPYING b/SOGo/UI/Scheduler/COPYING
new file mode 100644 (file)
index 0000000..161a3d1
--- /dev/null
@@ -0,0 +1,482 @@
+                 GNU LIBRARY GENERAL PUBLIC LICENSE
+                      Version 2, June 1991
+
+ Copyright (C) 1991 Free Software Foundation, Inc.
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the library GPL.  It is
+ numbered 2 because it goes with version 2 of the ordinary GPL.]
+
+                           Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+  This license, the Library General Public License, applies to some
+specially designated Free Software Foundation software, and to any
+other libraries whose authors decide to use it.  You can use it for
+your libraries, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if
+you distribute copies of the library, or if you modify it.
+
+  For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you.  You must make sure that they, too, receive or can get the source
+code.  If you link a program with the library, you must provide
+complete object files to the recipients so that they can relink them
+with the library, after making changes to the library and recompiling
+it.  And you must show them these terms so they know their rights.
+
+  Our method of protecting your rights has two steps: (1) copyright
+the library, and (2) offer you this license which gives you legal
+permission to copy, distribute and/or modify the library.
+
+  Also, for each distributor's protection, we want to make certain
+that everyone understands that there is no warranty for this free
+library.  If the library is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original
+version, so that any problems introduced by others will not reflect on
+the original authors' reputations.
+\f
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that companies distributing free
+software will individually obtain patent licenses, thus in effect
+transforming the program into proprietary software.  To prevent this,
+we have made it clear that any patent must be licensed for everyone's
+free use or not licensed at all.
+
+  Most GNU software, including some libraries, is covered by the ordinary
+GNU General Public License, which was designed for utility programs.  This
+license, the GNU Library General Public License, applies to certain
+designated libraries.  This license is quite different from the ordinary
+one; be sure to read it in full, and don't assume that anything in it is
+the same as in the ordinary license.
+
+  The reason we have a separate public license for some libraries is that
+they blur the distinction we usually make between modifying or adding to a
+program and simply using it.  Linking a program with a library, without
+changing the library, is in some sense simply using the library, and is
+analogous to running a utility program or application program.  However, in
+a textual and legal sense, the linked executable is a combined work, a
+derivative of the original library, and the ordinary General Public License
+treats it as such.
+
+  Because of this blurred distinction, using the ordinary General
+Public License for libraries did not effectively promote software
+sharing, because most developers did not use the libraries.  We
+concluded that weaker conditions might promote sharing better.
+
+  However, unrestricted linking of non-free programs would deprive the
+users of those programs of all benefit from the free status of the
+libraries themselves.  This Library General Public License is intended to
+permit developers of non-free programs to use free libraries, while
+preserving your freedom as a user of such programs to change the free
+libraries that are incorporated in them.  (We have not seen how to achieve
+this as regards changes in header files, but we have achieved it as regards
+changes in the actual functions of the Library.)  The hope is that this
+will lead to faster development of free libraries.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.  Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library".  The
+former contains code derived from the library, while the latter only
+works together with the library.
+
+  Note that it is possible for a library to be covered by the ordinary
+General Public License rather than by this special one.
+\f
+                 GNU LIBRARY GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License Agreement applies to any software library which
+contains a notice placed by the copyright holder or other authorized
+party saying it may be distributed under the terms of this Library
+General Public License (also called "this License").  Each licensee is
+addressed as "you".
+
+  A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+  The "Library", below, refers to any such software library or work
+which has been distributed under these terms.  A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language.  (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+  "Source code" for a work means the preferred form of the work for
+making modifications to it.  For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+  Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it).  Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+  
+  1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+  You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+\f
+  2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) The modified work must itself be a software library.
+
+    b) You must cause the files modified to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    c) You must cause the whole of the work to be licensed at no
+    charge to all third parties under the terms of this License.
+
+    d) If a facility in the modified Library refers to a function or a
+    table of data to be supplied by an application program that uses
+    the facility, other than as an argument passed when the facility
+    is invoked, then you must make a good faith effort to ensure that,
+    in the event an application does not supply such function or
+    table, the facility still operates, and performs whatever part of
+    its purpose remains meaningful.
+
+    (For example, a function in a library to compute square roots has
+    a purpose that is entirely well-defined independent of the
+    application.  Therefore, Subsection 2d requires that any
+    application-supplied function or table used by this function must
+    be optional: if the application does not supply it, the square
+    root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library.  To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License.  (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.)  Do not make any other change in
+these notices.
+\f
+  Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+  This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+  4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+  If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library".  Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+  However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library".  The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+  When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library.  The
+threshold for this to be true is not precisely defined by law.
+
+  If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work.  (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+  Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+\f
+  6. As an exception to the Sections above, you may also compile or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+  You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License.  You must supply a copy of this License.  If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License.  Also, you must do one
+of these things:
+
+    a) Accompany the work with the complete corresponding
+    machine-readable source code for the Library including whatever
+    changes were used in the work (which must be distributed under
+    Sections 1 and 2 above); and, if the work is an executable linked
+    with the Library, with the complete machine-readable "work that
+    uses the Library", as object code and/or source code, so that the
+    user can modify the Library and then relink to produce a modified
+    executable containing the modified Library.  (It is understood
+    that the user who changes the contents of definitions files in the
+    Library will not necessarily be able to recompile the application
+    to use the modified definitions.)
+
+    b) Accompany the work with a written offer, valid for at
+    least three years, to give the same user the materials
+    specified in Subsection 6a, above, for a charge no more
+    than the cost of performing this distribution.
+
+    c) If distribution of the work is made by offering access to copy
+    from a designated place, offer equivalent access to copy the above
+    specified materials from the same place.
+
+    d) Verify that the user has already received a copy of these
+    materials or that you have already sent this user a copy.
+
+  For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it.  However, as a special exception,
+the source code distributed need not include anything that is normally
+distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+  It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system.  Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+\f
+  7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+    a) Accompany the combined library with a copy of the same work
+    based on the Library, uncombined with any other library
+    facilities.  This must be distributed under the terms of the
+    Sections above.
+
+    b) Give prominent notice with the combined library of the fact
+    that part of it is a work based on the Library, and explaining
+    where to find the accompanying uncombined form of the same work.
+
+  8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License.  Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License.  However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+  9. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Library or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+  10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+\f
+  11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded.  In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+  13. The Free Software Foundation may publish revised and/or new
+versions of the Library General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation.  If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+\f
+  14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission.  For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this.  Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+                           NO WARRANTY
+
+  15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU.  SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+  16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+                    END OF TERMS AND CONDITIONS
+\f
+     Appendix: How to Apply These Terms to Your New Libraries
+
+  If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change.  You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms of the
+ordinary General Public License).
+
+  To apply these terms, attach the following notices to the library.  It is
+safest to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the library's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Library General Public
+    License as published by the Free Software Foundation; either
+    version 2 of the License, or (at your option) any later version.
+
+    This library 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
+    Library General Public License for more details.
+
+    You should have received a copy of the GNU Library General Public
+    License along with this library; if not, write to the Free
+    Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+    MA 02111-1307, USA
+
+Also add information on how to contact you by electronic and paper mail.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the library, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the
+  library `Frob' (a library for tweaking knobs) written by James Random Hacker.
+
+  <signature of Ty Coon>, 1 April 1990
+  Ty Coon, President of Vice
+
+That's all there is to it!
diff --git a/SOGo/UI/Scheduler/COPYRIGHT b/SOGo/UI/Scheduler/COPYRIGHT
new file mode 100644 (file)
index 0000000..1053b2a
--- /dev/null
@@ -0,0 +1,4 @@
+Copyright (C) 2004 SKYRIX Software AG
+
+
+Contact: info@skyrix.com
diff --git a/SOGo/UI/Scheduler/GNUmakefile b/SOGo/UI/Scheduler/GNUmakefile
new file mode 100644 (file)
index 0000000..40c6391
--- /dev/null
@@ -0,0 +1,66 @@
+# $Id: GNUmakefile,v 1.4 2004/06/04 16:15:23 znek Exp $
+
+include $(GNUSTEP_MAKEFILES)/common.make
+
+BUNDLE_NAME        = SchedulerUI
+BUNDLE_EXTENSION   = .zsp
+BUNDLE_INSTALL_DIR = $(GNUSTEP_USER_ROOT)/Library/ZideStore12
+
+SchedulerUI_PRINCIPAL_CLASS = SchedulerUIProduct
+
+SchedulerUI_OBJC_FILES = \
+       SchedulerUIProduct.m    \
+       UIxAppointmentFormatter.m \
+       UIxCalView.m            \
+       UIxCalWeekView.m        \
+       UIxCalMonthView.m       \
+       UIxAptTableView.m       \
+       \
+       UIxCalWeekOverview.m    \
+       UIxCalMonthOverview.m   \
+       UIxAppointmentView.m    \
+       UIxAppointmentEditor.m  \
+       UIxCalSelectTab.m \
+       UIxCalDateLabel.m \
+       UIxCalBackForthNavView.m \
+
+SchedulerUI_RESOURCE_FILES += \
+       Version                         \
+       product.plist                   \
+       \
+       UIxAptTableView.wox             \
+       UIxCalWeekOverview.wox          \
+       UIxCalMonthOverview.wox         \
+       UIxAppointmentView.wox          \
+       UIxAppointmentEditor.wox                \
+       UIxCalSelectTab.wox \
+       UIxCalDateLabel.wox \
+       UIxCalBackForthNavView.wox \
+       images/next_week.gif            \
+       images/previous_week.gif                                                \
+       images/icon_apt_chart.gif                                               \
+       images/icon_apt_overview.gif                            \
+       images/icon_apt_chart_inactive.gif              \
+       images/icon_apt_overview_inactive.gif \
+       images/icon_apt_column_view.gif                         \
+       images/icon_apt_list.gif                                                        \
+       images/icon_apt_list_inactive.gif                       \
+
+
+ifeq ($(FOUNDATION_LIB),apple)
+ZIDESTORE=$(GNUSTEP_USER_ROOT)/Library/Headers/ZideStore12
+else
+ZIDESTORE=$(GNUSTEP_USER_ROOT)/Headers/ZideStore12
+endif
+
+ADDITIONAL_INCLUDE_DIRS += \
+       -I. \
+       -I.. \
+       -I$(ZIDESTORE)/Frontend -I$(ZIDESTORE)/Backend \
+       -I$(ZIDESTORE) -I$(ZIDESTORE)/Common
+
+# make
+
+-include GNUmakefile.preamble
+include $(GNUSTEP_MAKEFILES)/bundle.make
+-include GNUmakefile.postamble
diff --git a/SOGo/UI/Scheduler/GNUmakefile.postamble b/SOGo/UI/Scheduler/GNUmakefile.postamble
new file mode 100644 (file)
index 0000000..3986bcc
--- /dev/null
@@ -0,0 +1,17 @@
+# $Id: GNUmakefile.postamble,v 1.1 2004/05/12 14:45:56 helge Exp $
+
+validate-wox:
+       xmllint --noout *.wox
+
+before-all :: validate-wox
+
+
+ifneq ($(GNUSTEP_BUILD_DIR),)
+after-all ::
+       @(cp bundle-info.plist \
+         $(GNUSTEP_BUILD_DIR)/$(BUNDLE_NAME)$(BUNDLE_EXTENSION))
+else
+after-all ::
+       @(cd $(BUNDLE_NAME)$(BUNDLE_EXTENSION);\
+         cp ../bundle-info.plist .)
+endif
diff --git a/SOGo/UI/Scheduler/GNUmakefile.preamble b/SOGo/UI/Scheduler/GNUmakefile.preamble
new file mode 100644 (file)
index 0000000..23c9438
--- /dev/null
@@ -0,0 +1,17 @@
+# $Id$
+
+ifneq ($(GNUSTEP_BUILD_DIR),)
+       RELBUILD_DIR_libZideStoreCommonUI = \
+               $(GNUSTEP_BUILD_DIR)/../Common/$(GNUSTEP_OBJ_DIR_NAME)
+else
+       RELBUILD_DIR_libZideStoreCommonUI = ../Common
+endif
+
+SchedulerUI_LIB_DIRS += -L$(RELBUILD_DIR_libZideStoreCommonUI)
+
+SchedulerUI_BUNDLE_LIBS += \
+       -lNGObjWeb -lNGScripting -lNGJavaScript -ljs \
+       -lNGMime -lNGStreams -lNGExtensions -lEOControl \
+       -lXmlRpc -lDOM -lSaxObjC \
+       -lSOGoLogic -lZideStoreCommonUI \
+       -lNGiCal
diff --git a/SOGo/UI/Scheduler/NOTES b/SOGo/UI/Scheduler/NOTES
new file mode 100644 (file)
index 0000000..35c83b1
--- /dev/null
@@ -0,0 +1,52 @@
+// $Id: NOTES,v 1.1 2003/11/24 01:24:40 helge Exp $
+
+Scheduler
+=========
+
+SOPE based interface for scheduler.
+
+Class Hierarchy
+===============
+
+  [WOComponent]
+    [SoComponent]
+      UIxAppointmentView
+      UIxCalView
+        UIxCalMonthView
+          UIxCalMonthOverview
+        UIxCalWeekView
+          UIxCalWeekOverview
+    UIxAptTableView
+  SchedulerUIProduct
+
+TBD:
+  UIxCalDayView
+    UIxCalDayOverview
+    UIxCalDayChart
+    UIxCalDayHChart
+  [UIxCalWeekView]
+    UIxCalWeekColumnView
+    UIxCalWeekChart
+    UIxCalWeekHChart
+  OGoYearOverview - should use aggressive caching in the long run
+
+  - editor page (which comes up in a new window)
+  - delete page
+  - print views
+
+Notes
+=====
+
+editor pages need to use JavaScript to trigger reloads in the parent window
+=> find out how to do that
+
+URLs
+====
+
+/zidestore/ControlPanel/                       => SoControlPanel
+/zidestore/ControlPanel/Products               => SoProductRegistry
+/zidestore/ControlPanel/Products/ZideStoreUI   => SoProduct
+/zidestore/ControlPanel/Products/ZideStoreUI/Resources/
+=> SoProductResourceManager
+/zidestore/ControlPanel/Products/ZideStoreUI/Resources/calendar.css
+=> resource
diff --git a/SOGo/UI/Scheduler/SchedulerUIProduct.m b/SOGo/UI/Scheduler/SchedulerUIProduct.m
new file mode 100644 (file)
index 0000000..7666ef0
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+  Copyright (C) 2000-2003 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: SchedulerUIProduct.m,v 1.1 2003/11/24 01:24:40 helge Exp $
+
+#import <Foundation/NSObject.h>
+
+@interface SchedulerUIProduct : NSObject
+{
+}
+
+@end
+
+#include "common.h"
+
+@implementation SchedulerUIProduct
+@end /* SchedulerUIProduct */
diff --git a/SOGo/UI/Scheduler/UIxAppointmentEditor.m b/SOGo/UI/Scheduler/UIxAppointmentEditor.m
new file mode 100644 (file)
index 0000000..5d1ef10
--- /dev/null
@@ -0,0 +1,277 @@
+/*
+  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 "common.h"
+#include <Common/UIxComponent.h>
+#include <SOGoLogic/SOGoAppointment.h>
+#include <NGiCal/NGiCal.h>
+
+
+/* TODO: CLEAN THIS MESS UP */
+
+
+@interface NSObject (AppointmentHack)
+- (BOOL)isAppointment;
+@end
+
+@implementation NSObject (AppointmentHack)
+- (BOOL)isAppointment {
+  return [self isKindOfClass:NSClassFromString(@"SxAppointment")];
+}
+@end
+
+@interface iCalPerson (Convenience)
+- (NSString *)rfc822Email;
+@end
+
+@implementation iCalPerson (Convenience)
+- (NSString *)rfc822Email {
+    NSString *_email = [self email];
+    NSRange colon = [_email rangeOfString:@":"];
+    if(colon.location != NSNotFound) {
+        return [_email substringFromIndex:colon.location + 1];
+    }
+    return _email;
+}
+@end
+
+@interface UIxAppointmentEditor : UIxComponent
+{
+    id appointment;
+    id participants;
+}
+
+- (SOGoAppointment *)appointment;
+- (NSString *)iCalStringTemplate;
+- (NSString *)iCalString;
+- (BOOL)isNewAppointment;
+
+@end
+
+@implementation UIxAppointmentEditor
+
+- (void)dealloc {
+    [self->appointment release];
+    [self->participants release];
+    [super dealloc];
+}
+
+
+/* accessors */
+
+
+- (NSString *)formattedAptStartTime {
+    NSCalendarDate *date;
+    
+    date = [[self appointment] startDate];
+    /* TODO: convert this into display timeZone! */
+    return [date descriptionWithCalendarFormat:@"%A, %Y-%m-%d %H:%M %Z"];
+}
+
+- (BOOL)isNewAppointment {
+    return ! [[self clientObject] isAppointment];
+}
+
+- (NSString *)iCalString {
+    if([self isNewAppointment]) {
+        return [self iCalStringTemplate];
+    }
+    else {
+        return [[self clientObject] valueForKey:@"iCalString"];
+    }
+}
+
+- (NSString *)iCalStringTemplate {
+    static NSString *iCalStringTemplate = \
+    @"BEGIN:VCALENDAR\nMETHOD:REQUEST\nPRODID:OpenGroupware.org ZideStore 1.2\n" \
+    @"VERSION:2.0\nBEGIN:VEVENT\nCLASS:PRIVATE\nSTATUS:CONFIRMED\n" \
+    @"DTSTART:%@\nDTEND:%@\n" \
+    @"TRANSP:OPAQUE\n" \
+    @"END:VEVENT\nEND:VCALENDAR";
+    NSCalendarDate *startDate, *endDate;
+    NSString *template;
+    
+    startDate = [self selectedDate];
+    endDate = [startDate dateByAddingYears:0 months:0 days:0
+                         hours:1 minutes:0 seconds:0];
+    
+    template = [NSString stringWithFormat:iCalStringTemplate,
+                                          [startDate icalString],
+                                          [endDate icalString]];
+    
+    return template;
+}
+
+
+/* backend */
+
+
+- (SOGoAppointment *)appointment {
+    if(self->appointment == nil) {
+        self->appointment = [[SOGoAppointment alloc]
+          initWithICalString:[self iCalString]];
+    }
+    return self->appointment;
+}
+
+- (id)participants {
+    if(self->participants == nil) {
+        NSArray *attendees;
+        NSMutableArray *emailAddresses;
+        unsigned i, count;
+
+        attendees = [self->appointment attendees];
+        count = [attendees count];
+        emailAddresses = [[NSMutableArray alloc] initWithCapacity:count];
+        for(i = 0; i < count; i++) {
+            NSString *email;
+            
+            email = [[attendees objectAtIndex:i] rfc822Email];
+            if(email)
+                [emailAddresses addObject:email];
+        }
+        self->participants = [[emailAddresses componentsJoinedByString:@"\n"]
+            retain];
+        [emailAddresses release];
+    }
+    return self->participants;
+}
+
+
+/* helper */
+
+- (NSString *)uriAsFormat {
+    NSString *uri, *qp;
+    NSRange r;
+
+    uri = [[[self context] request] uri];
+    
+    /* first: identify query parameters */
+    r = [uri rangeOfString:@"?" options:NSBackwardsSearch];
+    if (r.length > 0) {
+        uri = [uri substringToIndex:r.location];
+        qp = [uri substringFromIndex:r.location];
+    }
+    else {
+        qp = nil;
+    }
+    
+    /* next: strip trailing slash */
+    if([uri hasSuffix:@"/"])
+        uri = [uri substringToIndex:([uri length] - 1)];
+    r = [uri rangeOfString:@"/" options:NSBackwardsSearch];
+    
+    /* then: cut of last path component */
+    if(r.location == NSNotFound) { // no slash? are we at root?
+        uri = @"/";
+    }
+    else {
+        uri = [uri substringToIndex:(r.location + 1)];
+    }
+    /* next: append format token */
+    uri = [uri stringByAppendingString:@"%@"];
+    if(qp != nil)
+        uri = [uri stringByAppendingString:qp];
+    return uri;
+}
+
+
+/* save */
+
+
+- (id)saveAction {
+    SOGoAppointment *apt;
+    NSString *iCalString, *summary, *location, *nextMethod, *uri, *uriFormat;
+    NSCalendarDate *sd, *ed;
+    NSArray *ps;
+    unsigned i, count;
+    WOResponse *r;
+    WORequest *req;
+
+    req = [[self context] request];
+
+    /* get iCalString from hidden input */
+    iCalString = [req formValueForKey:@"ical"];
+    apt = [[SOGoAppointment alloc] initWithICalString:iCalString];
+
+    /* merge in form values */
+    sd = [NSCalendarDate dateWithString:[req formValueForKey:@"startDate"]
+                         calendarFormat:@"%Y-%m-%d %H:%M"];
+    [apt setStartDate:sd];
+    ed = [NSCalendarDate dateWithString:[req formValueForKey:@"endDate"]
+                         calendarFormat:@"%Y-%m-%d %H:%M"];
+    [apt setEndDate:ed];
+    summary = [req formValueForKey:@"summary"];
+    [apt setSummary:title];
+    location = [req formValueForKey:@"location"];
+    [apt setLocation:location];
+
+    [apt removeAllAttendees]; /* clean up */
+    ps = [[req formValueForKey:@"participants"]
+        componentsSeparatedByString:@"\n"];
+    count = [ps count];
+    for(i = 0; i < count; i++) {
+        NSString *email;
+        
+        email = [ps objectAtIndex:i];
+        if([email length] > 0) {
+            iCalPerson *p;
+            NSRange cnr;
+
+            p = [[iCalPerson alloc] init];
+            [p setEmail:[NSString stringWithFormat:@"mailto:%@", email]];
+            /* construct a fake CN */
+            cnr = [email rangeOfString:@"@"];
+            if(cnr.location != NSNotFound) {
+                [p setCn:[email substringToIndex:cnr.location]];
+            }
+            [apt addToAttendees:p];
+            [p release];
+        }
+    }
+
+    /* receive current representation for save operation */
+    iCalString = [apt iCalString];
+    [apt release];
+    
+
+    /* determine what's to do and where to go next */
+    if([self isNewAppointment]) {
+        nextMethod = @"duhduh";
+    }
+    else {
+        nextMethod = @"view";
+    }
+
+    NSLog(@"%s new iCalString:\n%@", __PRETTY_FUNCTION__, iCalString);
+
+    uriFormat = [self uriAsFormat];
+    uri = [NSString stringWithFormat:uriFormat, nextMethod];
+
+    r = [WOResponse responseWithRequest:req];
+    [r setStatus:302 /* moved */];
+    [r setHeader:uri forKey:@"location"];
+    return r;
+}
+
+@end
diff --git a/SOGo/UI/Scheduler/UIxAppointmentEditor.wox b/SOGo/UI/Scheduler/UIxAppointmentEditor.wox
new file mode 100644 (file)
index 0000000..ce2381a
--- /dev/null
@@ -0,0 +1,111 @@
+<?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:uix="OGo:uix"
+               className="UIxPageFrame"
+               title="name"
+>
+
+  <form href="save">
+  <table cellspacing="0" cellpadding="5" width="100%">
+  <tr>
+  <td>
+  <table cellpadding="0" cellspacing="0" width="100%">
+  <tr>
+  <td width="5"/>
+  <td class="window_label">Appointment Editor</td>
+  <td width="36" align="right" valign="center">
+  <var:component className="UIxWinClose" />
+  </td>
+  </tr>
+  </table>
+  </td>
+  </tr>
+
+  <tr>
+    <td>
+        <table border="0" cellpadding="2" width="100%" cellspacing="0" bgcolor="#e8e8e0">
+          <tr>
+            <td align="left" colspan="2">
+              <span class="aptview_title">Appointment on <var:string value="formattedAptStartTime" /></span>
+            </td>
+          </tr>
+          <tr valign="top">
+            <td align="right" width="15%">
+                <span class="aptview_text">Start time:</span>
+            </td>
+            <td align="left" bgcolor="#FFFFF0">
+                <span class="aptview_text">
+                  <input type="text" name="startDate" var:value="appointment.startDate" const:dateformat="%Y-%m-%d %H:%M" const:size="40" />
+                </span>
+            </td>
+          </tr>
+          <tr valign="top">
+            <td align="right" width="15%">
+                <span class="aptview_text">End time:</span>
+            </td>
+            <td align="left" bgcolor="#FFFFF0">
+                <span class="aptview_text">
+                  <input type="text" name="endDate" var:value="appointment.endDate" const:dateformat="%Y-%m-%d %H:%M" const:size="40" />
+                </span>
+            </td>
+          </tr>
+          <tr valign="top">
+            <td align="right" width="15%">
+                <span class="aptview_text">Title:</span>
+            </td>
+            <td align="left" bgcolor="#FFFFF0">
+                <span class="aptview_text">
+                  <input type="text" name="summary" var:value="appointment.summary" const:size="40" />
+                </span>
+            </td>
+          </tr>
+          <tr valign="top">
+            <td align="right" width="15%">
+                <span class="aptview_text">Location:</span>
+            </td>
+            <td align="left" bgcolor="#FFFFF0">
+                <span class="aptview_text">
+                  <input type="text" name="location" var:value="appointment.location" const:size="40"/>
+                </span>
+            </td>
+          </tr>
+        </table>
+    </td>
+  </tr>
+
+  <tr>
+    <td>
+        <table border="0" cellpadding="2" width="100%" cellspacing="0" bgcolor="#e8e8e0">
+          <tr>
+            <td align="left" colspan="2">
+              <span class="aptview_title">Search participants</span>
+            </td>
+          </tr>
+          <tr valign="top">
+            <td align="right" width="15%">
+                <span class="aptview_text">Participants:</span>
+            </td>
+            <td align="left" bgcolor="#FFFFF0">
+                <span class="aptview_text">
+                  <textarea name="participants" var:value="participants" cols="40" rows="5" />
+                </span>
+            </td>
+          </tr>
+        </table>
+    </td>
+  </tr>
+
+  <tr>
+    <td>
+        <input type="submit" value="Save" />
+        <input type="hidden" name="ical" var:value="iCalString" />
+    </td>
+  </tr>
+  </table>
+  </form>
+  <!-- -->
+  <hr />
+  clientObject: <var:string value="clientObject" />
+</var:component>
diff --git a/SOGo/UI/Scheduler/UIxAppointmentFormatter.h b/SOGo/UI/Scheduler/UIxAppointmentFormatter.h
new file mode 100644 (file)
index 0000000..4202e77
--- /dev/null
@@ -0,0 +1,120 @@
+/*
+  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 __UIxAppointmentFormatter_H__
+#define __UIxAppointmentFormatter_H__
+
+#import <Foundation/NSFormatter.h>
+
+/*
+  Formatter to format appointment-dicts to readable strings:
+
+  %[(dateFormat)]S
+             - startDate formatted with the dateFormat string
+             - if no dateFormat is defined, the default formats are used
+             - !!! dont forget the ()brakes !!!
+  %[(dateFormat)]E
+             - endDate formatted with the dateFormat string
+             - if no dateFormat is defined, the default formats are used
+             - !!! dont forget the ()brakes !!!
+
+  %[length]T - title with the specified length
+             - if title has more chars than length overLengthString is appended
+             - if no length is defined, no limit is set
+
+  %[max]P    - participants
+             - if more than max participants at appointment
+               moreParticipantsString is appended
+             - if no max defined no limit is set
+
+  %[length]L - location
+             - if location has more chars than length overLengthString is
+               appended
+             - if no length is defined, no limit is set
+
+  Example:
+  format: @"%S - %E, \n%T";
+
+ */
+
+@class NSCalendarDate;
+
+@interface UIxAppointmentFormatter : NSFormatter
+{
+@protected
+  NSString        *formatString;           // default: @"%S - %E, \n%T"
+  
+  NSString        *dateFormat;             // default: @"%H:%M"
+  NSString        *otherDayDateFormat;     // default: @"%H:%M(%m-%d)"
+  NSString        *otherYearDateFormat;    // default: @"%H:%M(%Y-%m-%d)"
+
+  NSString        *toLongString;           // default: @".."
+  NSString        *moreParticipantsString; // default: @"..."
+  NSString        *participantsSeparator;  // default: @", "
+
+  NSCalendarDate  *relationDate;           // if nil, dateFormat used as format
+  // to know whether its the same day, the same year or another year
+
+  BOOL            showFullNames; // try to show full names of participants
+}
+
+//init
+- (id)initWithFormat:(NSString *)_format;
++ (UIxAppointmentFormatter *)formatterWithFormat:(NSString *)_format;
++ (UIxAppointmentFormatter *)formatter;
+
+//accessors
+- (void)setFormat:(NSString *)_format;
+- (NSString *)format;
+
+- (void)setDateFormat:(NSString *)_format;
+- (NSString *)dateFormat;
+
+- (void)setOtherDayDateFormat:(NSString *)_format;
+- (NSString *)otherDayDateFormat;
+
+- (void)setOtherYearDateFormat:(NSString *)_format;
+- (NSString *)otherYearDateFormat;
+
+- (void)setToLongString:(NSString *)_toLong;
+- (NSString *)toLongString;
+
+- (void)setMoreParticipantsString:(NSString *)_more;
+- (NSString *)moreParticipantsString;
+
+- (void)setParticipantsSeparator:(NSString *)_sep;
+- (NSString *)participantsSeparator;
+
+- (void)setRelationDate:(NSCalendarDate *)_relation;
+- (NSCalendarDate *)relationDate;
+
+- (void)setShowFullNames:(BOOL)_flag;
+- (BOOL)showFullNames;
+
+// easy switches
+
+// this resets the date format
+- (void)switchToAMPMTimes:(BOOL)_showAMPM;
+
+@end
+
+#endif
diff --git a/SOGo/UI/Scheduler/UIxAppointmentFormatter.m b/SOGo/UI/Scheduler/UIxAppointmentFormatter.m
new file mode 100644 (file)
index 0000000..1380448
--- /dev/null
@@ -0,0 +1,454 @@
+/*
+  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 "UIxAppointmentFormatter.h"
+#import <Foundation/Foundation.h>
+#import <NGExtensions/NGExtensions.h>
+#import <EOControl/EOControl.h>
+
+@implementation UIxAppointmentFormatter
+
+- (id)init {
+  if ((self = [super init])) {
+    [self setFormat:@"%S - %E, \n%T"];
+    [self setDateFormat:@"%H:%M"];
+    [self setOtherDayDateFormat:@"%H:%M(%m-%d)"];
+    [self setOtherYearDateFormat:@"%H:%M(%Y-%m-%d)"];
+    [self setToLongString:@".."];
+    [self setMoreParticipantsString:@"..."];
+    [self setParticipantsSeparator:@", "];
+    [self setRelationDate:nil];
+    self->showFullNames = NO;
+  }
+  return self;
+}
+
+- (id)initWithFormat:(NSString *)_format {
+  if ((self = [self init])) {
+    [self setFormat:_format];
+  }
+  return self;
+}
+
++ (UIxAppointmentFormatter *)formatterWithFormat:(NSString *)_format {
+  return AUTORELEASE([(UIxAppointmentFormatter *)[UIxAppointmentFormatter alloc]
+                                                 initWithFormat:_format]);
+}
+
++ (UIxAppointmentFormatter *)formatter {
+  return AUTORELEASE([[UIxAppointmentFormatter alloc] init]);
+}
+
+#if !LIB_FOUNDATION_BOEHM_GC
+- (void)dealloc {
+  RELEASE(self->formatString);
+  RELEASE(self->dateFormat);
+  RELEASE(self->otherDayDateFormat);
+  RELEASE(self->otherYearDateFormat);
+  RELEASE(self->toLongString);
+  RELEASE(self->moreParticipantsString);
+  RELEASE(self->participantsSeparator);
+  RELEASE(self->relationDate);
+
+  [super dealloc];
+}
+#endif
+
+// accessors
+
+- (void)setFormat:(NSString *)_format {
+  ASSIGN(self->formatString,_format);
+}
+- (NSString *)format {
+  return self->formatString;
+}
+
+- (void)setDateFormat:(NSString *)_format {
+  ASSIGN(self->dateFormat,_format);
+}
+- (NSString *)dateFormat {
+  return self->dateFormat;
+}
+
+- (void)setOtherDayDateFormat:(NSString *)_format {
+  ASSIGN(self->otherDayDateFormat,_format);
+}
+- (NSString *)otherDayDateFormat {
+  return self->otherDayDateFormat;
+}
+
+- (void)setOtherYearDateFormat:(NSString *)_format {
+  ASSIGN(self->otherYearDateFormat,_format);
+}
+- (NSString *)otherYearDateFormat {
+  return self->otherYearDateFormat;
+}
+
+- (void)setToLongString:(NSString *)_toLong {
+  ASSIGN(self->toLongString,_toLong);
+}
+- (NSString *)toLongString {
+  return self->toLongString;
+}
+
+- (void)setMoreParticipantsString:(NSString *)_more {
+  ASSIGN(self->moreParticipantsString,_more);
+}
+- (NSString *)moreParticipantsString {
+  return self->moreParticipantsString;
+}
+
+- (void)setParticipantsSeparator:(NSString *)_sep {
+  ASSIGN(self->participantsSeparator,_sep);
+}
+- (NSString *)participantsSeparator {
+  return self->participantsSeparator;
+}
+
+- (void)setRelationDate:(NSCalendarDate *)_relation {
+  ASSIGN(self->relationDate,_relation);
+}
+- (NSCalendarDate *)relationDate {
+  return self->relationDate;
+}
+
+- (void)setShowFullNames:(BOOL)_flag {
+  self->showFullNames = _flag;
+}
+- (BOOL)showFullNames {
+  return self->showFullNames;
+}
+
+// easy switching
+- (void)switchToAMPMTimes:(BOOL)_showAMPM {
+  if (_showAMPM) {
+    [self setDateFormat:@"%I:%M %p"];
+    [self setOtherDayDateFormat:@"%I:%M %p(%m-%d)"];
+    [self setOtherYearDateFormat:@"%I:%M %p(%Y-%m-%d)"];
+  }
+  else {
+    [self setDateFormat:@"%H:%M"];
+    [self setOtherDayDateFormat:@"%H:%M(%m-%d)"];
+    [self setOtherYearDateFormat:@"%H:%M(%Y-%m-%d)"];
+  }
+}
+
+// formatting helpers
+
+- (NSString *)formatDate:(NSCalendarDate *)_date
+              withFormat:(NSString *)_format
+{
+  NSString *f;
+  NSCalendarDate *rel;
+
+  rel = self->relationDate;
+  
+  if (_format == nil) {
+    if (rel == nil) {
+      f = self->dateFormat;
+    }
+    else if ([_date isDateOnSameDay:rel]) {
+      f = self->dateFormat;
+    }
+    else if ([_date yearOfCommonEra] == [rel yearOfCommonEra]) {
+      f = self->otherDayDateFormat;
+    }
+    else {
+      f = self->otherYearDateFormat;
+    }
+  }
+  else {
+    f = _format;
+  }
+  return [_date descriptionWithCalendarFormat:f];
+}
+
+- (NSString *)formatStartDateFromApt:(id)_apt
+                          withFormat:(NSString *)_format
+{
+  return [self formatDate:[_apt valueForKey:@"startDate"]
+               withFormat:_format];
+}
+
+- (NSString *)formatEndDateFromApt:(id)_apt
+                        withFormat:(NSString *)_format
+{
+  return [self formatDate:[_apt valueForKey:@"endDate"]
+               withFormat:_format];
+}
+
+- (NSString *)stringForParticipant:(id)_part {
+  id label = nil;
+  
+  if ([[_part valueForKey:@"isTeam"] boolValue]) {
+    if ((label = [_part valueForKey:@"info"]) == nil)
+      label = [_part valueForKey:@"description"];
+  }
+  else if (self->showFullNames) {
+    label = [_part valueForKey:@"firstname"];
+    label = ([label length])
+      ? [label stringByAppendingFormat:@" %@", [_part valueForKey:@"name"]]
+      : [_part valueForKey:@"name"];
+  }
+  else if ([[_part valueForKey:@"isAccount"] boolValue]) {
+    label = [_part valueForKey:@"login"];
+  }
+  else {
+    if ((label = [_part valueForKey:@"name"]) == nil) {
+      if ((label = [_part valueForKey:@"info"]) == nil)
+        label = [_part valueForKey:@"description"];
+    }
+  }
+
+  if (![label isNotNull])
+    label = @"*";
+
+  return label;
+}
+
+- (NSString *)participantsForApt:(id)_apt
+                    withMaxCount:(NSString *)_cnt {
+  NSArray         *p;
+  int             max;
+  int             cnt;
+  NSMutableString *pString;
+
+  pString = [NSMutableString stringWithCapacity:255];
+
+  if (_cnt == nil) {
+    max = -1; // no limit
+  }
+  else {
+    max = [_cnt intValue];
+  }
+
+  p = [_apt valueForKey:@"participants"];
+
+  p = [p sortedArrayUsingKeyOrderArray:
+         [NSArray arrayWithObjects:
+                  [EOSortOrdering sortOrderingWithKey:@"isAccount"
+                                  selector:EOCompareAscending],
+                  [EOSortOrdering sortOrderingWithKey:@"login"
+                                  selector:EOCompareAscending],
+                  nil]];
+
+  max = ((max > [p count]) || (max == -1))
+    ? [p count]
+    : max;
+
+  for (cnt = 0; cnt < max; cnt++) {
+
+    if (cnt != 0)
+      [pString appendString:self->participantsSeparator];
+      
+    [pString appendString:
+             [self stringForParticipant:[p objectAtIndex:cnt]]];
+  }
+
+  if (max < [p count]) {
+    [pString appendString:self->moreParticipantsString];
+  }
+
+  return pString;
+}
+
+- (NSString *)titleForApt:(id)_apt withMaxLength:(NSString *)_length {
+  NSString    *t = nil;
+  int l;
+
+  l = (_length == nil)
+    ? -1
+    : [_length intValue];
+
+  t = [_apt valueForKey:@"title"];
+  if (!t) return @"*";
+
+  if (l > 1) {
+    if ([t length] > l) {
+      t = [t substringToIndex:(l - 2)];
+      t = [t stringByAppendingString:self->toLongString];
+    }
+  }
+  
+  if (l == 0)
+    t = @"*";
+  
+  return t;
+}
+
+- (NSString *)locationForApt:(id)_apt withMaxLength:(NSString *)_length {
+  NSString    *t = nil;
+  int l;
+
+  l = (_length == nil)
+    ? -1
+    : [_length intValue];
+
+  t = [_apt valueForKey:@"location"];
+  if (![t isNotNull] ||
+      [t length] == 0 ||
+      [t isEqualToString:@" "])
+    return @"";
+  
+  if (l > 1) {
+    if ([t length] > l) {
+      t = [t substringToIndex:(l - 2)];
+      t = [t stringByAppendingString:self->toLongString];
+    }
+  }
+  
+  if (l == 0)
+    t = @"";
+  
+  return t;
+}
+
+- (NSString *)resourcesForApt:(id)_apt withMaxLength:(NSString *)_length {
+  NSString    *t = nil;
+  int l;
+
+  l = (_length == nil)
+    ? -1
+    : [_length intValue];
+
+  t = [_apt valueForKey:@"resourceNames"];
+  if (![t isNotNull]  ||
+      [t length] == 0 ||
+      [t isEqualToString:@" "])
+    return @"";
+
+  if (l > 1) {
+    if ([t length] > l) {
+      t = [t substringToIndex:(l - 2)];
+      t = [t stringByAppendingString:self->toLongString];
+    }
+  }
+  
+  if (l == 0)
+    t = @"";
+  
+  return t;
+}
+
+// NSFormatter stuff
+
+- (NSString *)stringForObjectValue:(id)_obj {
+  NSMutableString *newString;
+  int             cnt;
+  int             length;
+  BOOL            replaceMode = NO;
+  NSString        *helper = nil;
+  NSCharacterSet  *digits;
+
+  newString = [NSMutableString stringWithCapacity:255];
+  length    = [self->formatString length];
+  digits    = [NSCharacterSet decimalDigitCharacterSet];
+
+  //  NSLog(@"Formatting with format: %@", self->formatString);
+
+  for (cnt = 0; cnt < length; cnt++) {
+    unichar c;
+    c = [self->formatString characterAtIndex:cnt];
+    //    NSLog(@"Character is: %c mode is: %@", c,
+    //          [NSNumber numberWithBool:replaceMode]);
+    if (replaceMode) {
+      if (c == 'S') {
+        [newString appendString:
+                   [self formatStartDateFromApt:_obj withFormat:helper]];
+        helper = nil;
+        replaceMode = NO;
+      }
+      else if (c == 'E') {
+        [newString appendString:
+                   [self formatEndDateFromApt:_obj withFormat:helper]];
+        helper = nil;
+        replaceMode = NO;
+      }
+      else if (c == 'P') {
+        [newString appendString:
+                   [self participantsForApt:_obj withMaxCount:helper]];
+        helper = nil;
+        replaceMode = NO;
+      }
+      else if (c == 'T') {
+        [newString appendString:
+                   [self titleForApt:_obj withMaxLength:helper]];
+        helper = nil;
+        replaceMode = NO;
+      }
+      else if (c == 'L') {
+        NSString *l;
+
+        l = [self locationForApt:_obj withMaxLength:helper];
+
+        if ([l length] > 0)
+          [newString appendString:l];
+        helper = nil;
+        replaceMode = NO;
+      }
+      else if (c == 'R') {
+        NSString *r;
+
+        r = [self resourcesForApt:_obj withMaxLength:helper];
+
+        if ([r length] > 0)
+          [newString appendString:r];
+        helper = nil;
+        replaceMode = NO;
+      }
+      else if (c == '(') {
+        int     end;
+        NSRange r = NSMakeRange(cnt,length-cnt);
+        
+        r = [self->formatString rangeOfString:@")"
+                 options:0 range:r];
+        
+        end = r.location - 1;
+        r = NSMakeRange(cnt+1, end-cnt-1);
+        
+        helper = [self->formatString substringWithRange:r];
+        cnt = end + 1;
+      }
+      else if ([digits characterIsMember:c]) {
+        helper = (helper == nil)
+          ? [NSString stringWithFormat:@"%c",c]
+          : [NSString stringWithFormat:@"%@%c", helper, c];
+      }
+      else {
+        NSLog(@"UNKNOWN FORMAT CHARACTER '%c'!!",c);
+        replaceMode = NO;
+        helper = nil;
+      }
+    } else {
+      if (c == '%') {
+        replaceMode = YES;
+      }
+      else {
+        [newString appendFormat:@"%c", c];
+      }
+    }
+  }
+  
+  return newString;
+}
+
+@end
diff --git a/SOGo/UI/Scheduler/UIxAppointmentView.h b/SOGo/UI/Scheduler/UIxAppointmentView.h
new file mode 100644 (file)
index 0000000..9038594
--- /dev/null
@@ -0,0 +1,26 @@
+// $Id$
+
+#ifndef __ZideStoreUI_UIxAppointmentView_H__
+#define __ZideStoreUI_UIxAppointmentView_H__
+
+#include <Common/UIxComponent.h>
+
+@interface UIxAppointmentView : UIxComponent
+{
+    NSString *tabSelection;
+    id appointment;
+    id attendee;
+}
+
+- (id)appointment;
+
+- (NSString *)attributesTabLink;
+- (NSString *)participantsTabLink;
+
+- (NSString *)completeHrefForMethod:(NSString *)_method
+              withParameter:(NSString *)_param
+              forKey:(NSString *)_key;
+
+@end
+
+#endif /* __ZideStoreUI_UIxAppointmentView_H__ */
diff --git a/SOGo/UI/Scheduler/UIxAppointmentView.m b/SOGo/UI/Scheduler/UIxAppointmentView.m
new file mode 100644 (file)
index 0000000..b05f908
--- /dev/null
@@ -0,0 +1,109 @@
+// $Id$
+
+#include "UIxAppointmentView.h"
+#include "common.h"
+#include <Backend/SxAptManager.h>
+#include <SOGoLogic/SOGoAppointment.h>
+
+
+@interface NSObject(UsedPrivates)
+- (SxAptManager *)aptManagerInContext:(id)_ctx;
+@end
+
+@implementation UIxAppointmentView
+
+- (void)dealloc {
+  [self->appointment release];
+  [self->attendee release];
+  [super dealloc];
+}
+
+
+/* accessors */
+
+
+- (NSString *)tabSelection {
+    NSString *selection;
+    
+    selection = [self queryParameterForKey:@"tab"];
+    if(! selection)
+        selection = @"attributes";
+    return selection;
+}
+
+- (void)setAttendee:(id)_attendee {
+    ASSIGN(self->attendee, _attendee);
+}
+- (id)attendee {
+    return self->attendee;
+}
+
+
+/* backend */
+
+
+- (SxAptManager *)aptManager {
+  return [[self clientObject] aptManagerInContext:[self context]];
+}
+
+- (SOGoAppointment *)appointment {
+    if(self->appointment == nil) {
+        NSString *iCalString;
+
+        iCalString = [[self clientObject] valueForKey:@"iCalString"];
+        self->appointment = [[SOGoAppointment alloc] initWithICalString:iCalString];
+    }
+    return self->appointment;
+}
+
+- (NSString *)formattedAptStartTime {
+    NSCalendarDate *date;
+    
+    date = [[self appointment] startDate];
+    /* TODO: convert this into display timeZone! */
+    return [date descriptionWithCalendarFormat:@"%A, %Y-%m-%d %H:%M %Z"];
+}
+
+- (NSString *)formattedAptEndTime {
+    NSCalendarDate *date;
+    
+    date = [[self appointment] endDate];
+    /* TODO: convert this into display timeZone! */
+    return [date descriptionWithCalendarFormat:@"%A, %Y-%m-%d %H:%M %Z"];
+}
+
+
+/* hrefs */
+
+
+- (NSString *)attributesTabLink {
+    return [self completeHrefForMethod:[self ownMethodName]
+                 withParameter:@"attributes"
+                 forKey:@"tab"];
+}
+
+- (NSString *)participantsTabLink {
+    return [self completeHrefForMethod:[self ownMethodName]
+                 withParameter:@"participants"
+                 forKey:@"tab"];
+}
+
+- (NSString *)debugTabLink {
+    return [self completeHrefForMethod:[self ownMethodName]
+                 withParameter:@"debug"
+                 forKey:@"tab"];
+}
+
+- (NSString *)completeHrefForMethod:(NSString *)_method
+              withParameter:(NSString *)_param
+              forKey:(NSString *)_key
+{
+    NSString *href;
+
+    [self setQueryParameter:_param forKey:_key];
+    href = [self completeHrefForMethod:[self ownMethodName]];
+    [self setQueryParameter:nil forKey:_key];
+    return href;
+}
+
+@end /* UIxAppointmentView */
diff --git a/SOGo/UI/Scheduler/UIxAppointmentView.wox b/SOGo/UI/Scheduler/UIxAppointmentView.wox
new file mode 100644 (file)
index 0000000..90dfd7b
--- /dev/null
@@ -0,0 +1,166 @@
+<?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:uix="OGo:uix"
+               className="UIxPageFrame"
+               title="name"
+>
+
+  <table cellspacing="0" cellpadding="5" width="100%">
+  <tr>
+  <td>
+  <table cellpadding="0" cellspacing="0" width="100%">
+  <tr>
+  <td width="5"/>
+  <td class="window_label">Appointment Viewer</td>
+  <td width="36" align="right" valign="center">
+  <var:component className="UIxWinClose" />
+  </td>
+  </tr>
+  </table>
+  </td>
+  </tr>
+
+  <tr>
+    <td>
+        <table border="0" cellpadding="2" width="100%" cellspacing="0">
+          <tr bgcolor="#e8e8e0">
+            <td align="left">
+              <span class="aptview_title"><var:string value="formattedAptStartTime" /></span>
+            </td>
+            <td align="right" >
+                <table border='0' cellpadding='0' cellspacing='1'>
+                    <tr>
+                        <td class="button_auto_env" nowrap="true" valign='middle' align='center'>
+                            <a class="button_auto"
+                               href="printview"
+                               var:queryDictionary="queryParameters"
+                               target="SOGoPrintView"
+                            >printview</a>
+                        </td>
+                        <td class="button_auto_env" nowrap="true" valign='middle' align='center'>
+                            <a class="button_auto"
+                               href="edit"
+                               var:queryDictionary="queryParameters"
+                            >edit</a>
+                        </td>
+                        <td class="button_auto_env" nowrap="true" valign='middle' align='center'>
+                            <a class="button_auto"
+                               href="delete"
+                               var:queryDictionary="queryParameters"
+                            >delete</a>
+                        </td>
+                    </tr>
+                </table>
+            </td>
+          </tr>
+        </table>
+    </td>
+  </tr>
+  <tr>
+    <td valign="top" width="100%">
+      <table width="100%" border="0" cellpadding="4" cellspacing="0">
+      <!-- general appointment info -->
+      <tr valign="top">
+        <td align="right" width="15%" bgcolor="#E8E8E0">
+            <span class="aptview_text">Title:</span>
+        </td>
+        <td align="left" bgcolor="#FFFFF0">
+            <span class="aptview_text">
+              <var:string value="appointment.summary" />
+            </span>
+        </td>
+      </tr>
+      <tr valign="top">
+        <td align="right" width="15%" bgcolor="#E8E8E0">
+          <span class="aptview_text">Location:</span>
+        </td>
+        <td align="left" bgcolor="#FFFFF0">
+          <span class="aptview_text">
+            <var:string value="appointment.location" />
+          </span>
+        </td>
+      </tr>
+      </table>
+   </td>
+  </tr>
+  <tr>
+    <td valign="top" width="100%">
+        <uix:tabview var:selection="tabSelection"
+                     const:tabStyle="tab"
+                     const:selectedTabStyle="tab_selected"
+                     const:bodyStyle="tabview_body"
+        >
+          <uix:tab const:key="attributes"
+                   const:label="attributes"
+                   var:href="attributesTabLink">
+              <table width="100%" border="0" cellpadding="4" cellspacing="0">
+              <tr valign="top">
+                <td align="right" width="15%" bgcolor="#E8E8E0">
+                    <span class="aptview_text">Start time:</span>
+                </td>
+                <td align="left" bgcolor="#FFFFF0">
+                    <span class="aptview_text">
+                      <var:string value="formattedAptStartTime" />
+                    </span>
+                </td>
+              </tr>
+              <tr valign="top">
+                <td align="right" width="15%" bgcolor="#E8E8E0">
+                  <span class="aptview_text">End time:</span>
+                </td>
+                <td align="left" bgcolor="#FFFFF0">
+                  <span class="aptview_text">
+                    <var:string value="formattedAptEndTime" />
+                  </span>
+                </td>
+              </tr>
+              </table>
+          </uix:tab>
+          <uix:tab const:key="participants"
+                   const:label="participants"
+                   var:href="participantsTabLink">
+              <table width="100%" border="0" cellpadding="4" cellspacing="0">
+              <tr valign="top">
+                <td align="left" bgcolor="#E8E8E0">
+                    <span class="aptview_title">Email</span>
+                </td>
+              </tr>
+              <var:foreach list="appointment.attendees" item="attendee">
+              <tr valign="top">
+                <td align="left" bgcolor="#FFFFF0">
+                  <span class="aptview_text">
+                    <var:string value="attendee.email" />
+                  </span>
+                </td>
+              </tr>
+              </var:foreach>
+              </table>
+          </uix:tab>
+          <uix:tab const:key="debug"
+                   const:label="DEBUG"
+                   var:href="debugTabLink">
+            OGo ZideStore Server - <var:string value="name"/>
+            <br />
+            Client: <var:string value="clientObject"/>
+            <br />
+            Group:      <var:string value="clientObject.group"/><br />
+            Deletable:  <var:string value="clientObject.isDeletionAllowed"/><br />
+            Generation: <var:string value="clientObject.zlGenerationCount"/><br />
+            MsgClass:   <var:string value="clientObject.outlookMessageClass"/><br />
+
+            <hr />
+            As iCal:<br />
+            <pre><var:string value="clientObject.iCalString"/></pre>
+
+            <hr />
+            As Mail:<br />
+            <pre><var:string value="clientObject.iCalMailString"/></pre>
+
+          </uix:tab>
+        </uix:tabview>
+    </td>
+  </tr>
+  </table>
+</var:component>
diff --git a/SOGo/UI/Scheduler/UIxAptTableView.m b/SOGo/UI/Scheduler/UIxAptTableView.m
new file mode 100644 (file)
index 0000000..420c4df
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+  Copyright (C) 2000-2003 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/SoComponent.h>
+
+@class NSArray, NSCalendarDate;
+
+@interface UIxAptTableView : SoComponent
+{
+  NSArray *appointments;
+  id      appointment;
+}
+
+/* accessors */
+
+- (NSArray *)appointments;
+- (id)appointment;
+
+@end
+
+#include "common.h"
+
+@implementation UIxAptTableView
+
+- (void)dealloc {
+  [self->appointment  release];
+  [self->appointments release];
+  [super dealloc];
+}
+
+/* accessors */
+
+- (void)setAppointments:(NSArray *)_apts {
+  ASSIGN(self->appointments, _apts);
+}
+- (NSArray *)appointments {
+  return self->appointments;
+}
+
+- (void)setAppointment:(id)_apt {
+  ASSIGN(self->appointment, _apt);
+}
+- (id)appointment {
+  return self->appointment;
+}
+
+- (NSString *)appointmentViewURL {
+  id pkey;
+  
+  if ((pkey = [[self appointment] valueForKey:@"dateId"]) == nil)
+    return nil;
+  
+  return [NSString stringWithFormat:@"%@/view", pkey];
+}
+
+@end /* UIxAptTableView */
diff --git a/SOGo/UI/Scheduler/UIxAptTableView.wox b/SOGo/UI/Scheduler/UIxAptTableView.wox
new file mode 100644 (file)
index 0000000..e270edf
--- /dev/null
@@ -0,0 +1,34 @@
+<?xml version='1.0' standalone='yes'?>
+<table
+  style="font-size: 11px;"
+  border="0" cellspacing="0" cellpadding="2"
+  xmlns="http://www.w3.org/1999/xhtml"
+  xmlns:var="http://www.skyrix.com/od/binding"
+  xmlns:const="http://www.skyrix.com/od/constant"
+>
+  <tr>
+    <th>ID</th>
+    <th>Title</th>
+    <th>Time</th>
+    <th>Version</th>
+    <th>Location</th>
+  </tr>
+  <var:foreach list="appointments" item="appointment">
+    <tr>
+      <td><var:string value="appointment.dateId"/></td>
+      <td>
+        <a var:href="appointmentViewURL"
+          ><var:string value="appointment.title"/></a>
+      </td>
+      <td>
+        <var:string value="appointment.startDate"
+                    const:dateformat="%Y-%m-%d %H:%M" />
+        -
+        <var:string value="appointment.endDate"
+                    const:dateformat="%Y-%m-%d %H:%M" />
+      </td>
+      <td><var:string value="appointment.objectVersion"/></td>
+      <td><var:string value="appointment.location"/></td>
+    </tr>
+  </var:foreach>
+</table>
diff --git a/SOGo/UI/Scheduler/UIxCalBackForthNavView.m b/SOGo/UI/Scheduler/UIxCalBackForthNavView.m
new file mode 100644 (file)
index 0000000..4194246
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+  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>
+
+/*
+    Associations:
+
+    methodName              -> maps to href
+    prevQueryParameters     -> queryDictionary
+    currentQueryParameters  -> queryDictionary
+    nextQueryParameters     -> queryDictionary
+    label                   -> user presentable name to display for "this"
+ */
+
+@interface UIxCalBackForthNavView : WOComponent
+{
+}
+
+@end
+
+
+@implementation UIxCalBackForthNavView
+
+- (BOOL)synchronizesVariablesWithBindings {
+    return NO;
+}
+
+@end
diff --git a/SOGo/UI/Scheduler/UIxCalBackForthNavView.wox b/SOGo/UI/Scheduler/UIxCalBackForthNavView.wox
new file mode 100644 (file)
index 0000000..7c86e8c
--- /dev/null
@@ -0,0 +1,20 @@
+<?xml version='1.0' standalone='yes'?>
+
+<table 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"
+       border="0"
+ >
+    <tr>
+        <td align="right" valign="middle">
+            <a var:href="^methodName" var:queryDictionary="^prevQueryParameters"><img rsrc:src="previous_week.gif" alt="previous" border="0"/></a>
+        </td>
+        <td align="right" valign="middle" class="button_auto_env">
+            <a var:href="^methodName" var:queryDictionary="^currentQueryParameters" class="button_auto"><var:string value="^label" escapeHTML="NO" /></a>
+        </td>
+        <td align="right" valign="middle">
+            <a var:href="^methodName" var:queryDictionary="^nextQueryParameters"><img rsrc:src="next_week.gif" alt="next" border="0"/></a>
+        </td>
+    </tr>
+</table>
\ No newline at end of file
diff --git a/SOGo/UI/Scheduler/UIxCalDateLabel.m b/SOGo/UI/Scheduler/UIxCalDateLabel.m
new file mode 100644 (file)
index 0000000..5e7fa48
--- /dev/null
@@ -0,0 +1,113 @@
+/*
+  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 UIxCalDateLabel : WOComponent
+{
+    NSString *selection;
+    NSCalendarDate *startDate;
+    NSCalendarDate *endDate;
+}
+
+- (NSString *)dayLabel;
+- (NSString *)weekLabel;
+- (NSString *)monthLabel;
+- (NSString *)yearLabel;
+
+@end
+
+
+@implementation UIxCalDateLabel
+
+- (void)dealloc {
+    [self->selection release];
+    [self->startDate release];
+    [self->endDate release];
+    [super dealloc];
+}
+
+- (void)setSelection:(NSString *)_selection {
+    ASSIGN(self->selection, _selection);
+}
+
+- (NSString *)selection {
+    return self->selection;
+}
+
+- (void)setStartDate:(NSCalendarDate *)_date {
+    ASSIGN(self->startDate, _date);
+}
+
+- (NSCalendarDate *)startDate {
+    return self->startDate;
+}
+
+- (void)setEndDate:(NSCalendarDate *)_date {
+    ASSIGN(self->endDate, _date);
+}
+
+- (NSCalendarDate *)endDate {
+    return self->endDate;
+}
+
+- (NSString *)label {
+    NSString *key = [self selection];
+    if([key isEqualToString:@"day"])
+        return [self dayLabel];
+    else if([key isEqualToString:@"week"])
+        return [self weekLabel];
+    else if([key isEqualToString:@"month"])
+        return [self monthLabel];
+    return [self yearLabel];
+}
+
+- (NSString *)dayLabel {
+    return [self->startDate descriptionWithCalendarFormat:@"%Y-%m-%d"];
+}
+
+- (NSString *)weekLabel {
+    NSString *label;
+    
+    label = [self->startDate descriptionWithCalendarFormat:@"%B %Y"];
+    if([self->startDate monthOfYear] != [self->endDate monthOfYear]) {
+        NSString *ext;
+        
+        ext = [self->endDate descriptionWithCalendarFormat:@"%B %Y"];
+        label = [NSString stringWithFormat:@"<nobr>%@ / %@</nobr>",
+                                            label,
+                                            ext];
+    }
+    return label;
+}
+
+- (NSString *)monthLabel {
+    return [self->startDate descriptionWithCalendarFormat:@"%B %Y"];
+}
+
+- (NSString *)yearLabel {
+    return [self->startDate descriptionWithCalendarFormat:@"%Y"];
+}
+
+@end
diff --git a/SOGo/UI/Scheduler/UIxCalDateLabel.wox b/SOGo/UI/Scheduler/UIxCalDateLabel.wox
new file mode 100644 (file)
index 0000000..4a0c93a
--- /dev/null
@@ -0,0 +1,8 @@
+<?xml version='1.0' standalone='yes'?>
+
+<span 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"
+      const:class="window_label"
+><var:string value="label" const:escapeHTML="NO" /></span>
\ No newline at end of file
diff --git a/SOGo/UI/Scheduler/UIxCalMonthOverview.m b/SOGo/UI/Scheduler/UIxCalMonthOverview.m
new file mode 100644 (file)
index 0000000..17526f6
--- /dev/null
@@ -0,0 +1,119 @@
+// $Id$
+
+#include "UIxCalMonthView.h"
+#include <NGExtensions/NGExtensions.h>
+
+
+@interface UIxCalMonthOverview : UIxCalMonthView
+{
+    int dayIndex;
+    int dayOfWeek;
+    int weekOfYear;
+    NSCalendarDate *currentWeekStart;
+}
+
+@end
+
+#include "common.h"
+
+@implementation UIxCalMonthOverview
+
+- (void)dealloc {
+    [self->currentWeekStart release];
+    [super dealloc];
+}
+
+- (void)setDayIndex:(int)_idx {
+    self->dayIndex = _idx;
+}
+
+- (int)dayIndex {
+    return self->dayIndex;
+}
+
+- (void)setDayOfWeek:(int)_day {
+    self->dayOfWeek = _day;
+}
+
+- (int)dayOfWeek {
+    return self->dayOfWeek;
+}
+
+- (void)setCurrentWeekStartDate:(NSCalendarDate *)_date {
+    ASSIGN(self->currentWeekStart, _date);
+}
+
+- (NSCalendarDate *)currentWeekStartDate {
+    return self->currentWeekStart;
+}
+
+- (void)setWeekOfYear:(int)_week {
+    NSCalendarDate *date;
+    
+    self->weekOfYear = _week;
+    if(_week == 52 || _week == 53)
+        date = [[self startDate] mondayOfWeek];
+    else
+        date = [self startDate];
+    date = [date mondayOfWeek:_week];
+    [self setCurrentWeekStartDate:date];
+}
+
+- (int)weekOfYear {
+    return self->weekOfYear;
+}
+
+- (int)year {
+    return [[self startDate] yearOfCommonEra];
+}
+
+- (int)month {
+    return [[self startDate] monthOfYear];
+}
+
+- (NSString *)localizedNameOfDayOfWeek {
+    // TODO: move this to some locale method
+    static char *dayNames[] = {
+        "Sunday",
+        "Monday",
+        "Tuesday",
+        "Wednesday",
+        "Thursday",
+        "Friday",
+        "Saturday"
+    };
+    return [[[NSString alloc] initWithCString:
+        dayNames[self->dayOfWeek]] autorelease];
+}
+
+- (NSDictionary *)currentWeekQueryParameters {
+    return [self queryParametersBySettingSelectedDate:self->currentWeekStart];
+}
+
+
+/* style sheet */
+
+
+- (NSString *)weekStyle {
+    if([self->currentWeekStart isDateInSameWeek:[NSCalendarDate date]])
+        return @"monthoverview_week_hilite";
+    return @"monthoverview_week";
+}
+
+- (NSString *)contentStyle {
+    if([self->currentDay isToday])
+        return @"monthoverview_content_hilite";
+    else if([self->currentDay monthOfYear] != [[self startDate] monthOfYear])
+        return @"monthoverview_content_dimmed";
+    return @"monthoverview_content";
+}
+
+
+/* appointments */
+
+
+- (NSArray *)appointments {
+  return [self fetchCoreInfos];
+}
+
+@end /* UIxCalMonthOverview */
diff --git a/SOGo/UI/Scheduler/UIxCalMonthOverview.wox b/SOGo/UI/Scheduler/UIxCalMonthOverview.wox
new file mode 100644 (file)
index 0000000..402e739
--- /dev/null
@@ -0,0 +1,165 @@
+<?xml version='1.0' standalone='yes'?>
+<var:component className="UIxPageFrame" 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"
+>
+
+  <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"><var:component className="UIxCalDateLabel" startDate="startDate" endDate="endDate" const:selection="month" /></td>
+  <td width="36" align="right" valign="center">
+  <var:component className="UIxWinClose" />
+  </td>
+  </tr>
+  </table>
+  </td>
+  </tr>
+
+  <tr>
+  <td id="skywinbodycell" class="wincontent">
+    <table border="0" cellpadding="0" cellspacing="0" width="100%">
+        <tr bgcolor="#e8e8e0">
+            <td align="left" valign="middle" width="80%">TODO: controls</td><!-- 99% -->
+            <td align="right">
+                <var:component className="UIxCalBackForthNavView"
+                               methodName="ownMethodName"
+                               prevQueryParameters="prevMonthQueryParameters"
+                               currentQueryParameters="todayQueryParameters"
+                               nextQueryParameters="nextMonthQueryParameters"
+                               const:label="this month"
+                />
+            </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="UIxCalSelectTab"
+                 const:selection="month"
+                 currentDate="selectedDate"
+  >
+        <table border="0" cellpadding="4" width="100%" cellspacing="2">
+          <tr>
+            <td align="right" bgcolor="#e8e8e0">
+                <table border='0' cellpadding='0' cellspacing='1'>
+                    <tr>
+                        <td class="button_auto_env" nowrap="true" valign='middle' align='center'>
+                            <a class="button_auto" href="monthprintview" var:queryDictionary="queryParameters" target="SOGoPrintView">printview</a>
+                        </td>
+                        <td class="button_auto_env" nowrap="true" valign='middle' align='center'>
+                            <a class="button_auto" href="proposal" var:queryDictionary="queryParameters">proposal</a>
+                        </td>
+                    </tr>
+                </table>
+            </td>
+          </tr>
+        </table>
+
+    <var:month-overview
+      list="appointments"
+      item="appointment"
+      currentDay="currentDay"
+      index="dayIndex"
+      year="year"
+      month="month"
+      const:startDateKey = "startDate"
+      const:endDateKey   = "endDate"
+
+      const:class="monthoverview"
+      contentStyle="contentStyle"
+      const:width="100%"
+    >
+      <var:month-info>
+        <var:if condition="hasHolidayInfo">
+            <var:string value="holidayInfo" const:class="monthoverview_holidayinfo" />
+        </var:if>
+        <var:foreach list="allDayApts" item="appointment">
+            <a var:href="appointmentViewURL"><var:string value="shortTextForApt" /></a>
+        </var:foreach>
+      </var:month-info>
+    <var:month-label const:orientation="top"
+                     dayOfWeek="dayOfWeek"
+                     const:class="monthoverview_title"
+    >
+        <var:string value="localizedNameOfDayOfWeek" />
+    </var:month-label>
+    <var:month-label const:orientation="left"
+                     weekOfYear="weekOfYear"
+                     class="weekStyle"
+    >
+        <a href="weekoverview"
+           var:queryDictionary="currentWeekQueryParameters"
+        ><var:string value="weekOfYear" /></a>
+    </var:month-label>
+    
+        <var:month-title class="contentStyle">
+            <span class="monthoverview_day">
+                <a href="dayoverview"
+                   var:queryDictionary="currentDayQueryParameters"
+                ><var:string value="currentDay.dayOfMonth" /></a>
+            </span>
+            <br />
+            <span class="monthoverview_day_new">
+                <a href="new"
+                   var:queryDictionary="currentDayQueryParameters"
+                >[new]</a>
+            </span>
+        </var:month-title>
+
+        <var:month>
+            <a var:href="appointmentViewURL"
+               class="monthoverview_content_link"
+               var:title="shortTextForApt"
+               var:queryDictionary="currentDayQueryParameters"
+            ><var:string value="shortTitleForApt" /></a>
+        </var:month>
+    </var:month-overview>
+  </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="" src="/ZideStore/so/ControlPanel/Products/CommonUI/Resources/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>
+
+<!--
+    <hr />
+    OGo ZideStore Server - <var:string value="name"/>
+    <br />
+    Client: <var:string value="clientObject"/>
+    <br />
+    Appointments: #<var:string value="appointments.count"/>
+    from <var:string value="startDate" />
+    to   <var:string value="endDate" />
+    <br />
+
+
+    <hr />
+
+    Appointments: 
+    <var:component className="UIxAptTableView" appointments="appointments"/>
+    -->
+    <!-- pre><var:string value="appointments" const:insertBR="YES"/></pre -->
+</var:component>
diff --git a/SOGo/UI/Scheduler/UIxCalMonthView.h b/SOGo/UI/Scheduler/UIxCalMonthView.h
new file mode 100644 (file)
index 0000000..5caf1d4
--- /dev/null
@@ -0,0 +1,23 @@
+// $Id$
+
+#ifndef __ZideStoreUI_UIxCalMonthView_H__
+#define __ZideStoreUI_UIxCalMonthView_H__
+
+#include "UIxCalView.h"
+
+/*
+  UIxCalMonthView
+  
+  Abstract superclass for views which display months.
+*/
+
+@interface UIxCalMonthView : UIxCalView
+{
+}
+
+- (NSDictionary *)prevMonthQueryParameters;
+- (NSDictionary *)nextMonthQueryParameters;
+
+@end
+
+#endif /* __ZideStoreUI_UIxCalMonthView_H__ */
diff --git a/SOGo/UI/Scheduler/UIxCalMonthView.m b/SOGo/UI/Scheduler/UIxCalMonthView.m
new file mode 100644 (file)
index 0000000..fa3a216
--- /dev/null
@@ -0,0 +1,49 @@
+// $Id$
+
+#include "UIxCalMonthView.h"
+#include "common.h"
+
+@implementation UIxCalMonthView
+
+- (NSCalendarDate *)startDate {
+  return [[super startDate] firstDayOfMonth];
+}
+
+- (NSCalendarDate *)endDate {
+  NSCalendarDate *startDate = [self startDate];
+  return [startDate dateByAddingYears:0
+                    months:0
+                    days:[startDate numberOfDaysInMonth]
+                    hours:0
+                    minutes:0
+                    seconds:0];
+}
+
+/* URLs */
+
+
+- (NSDictionary *)prevMonthQueryParameters {
+    NSCalendarDate *date;
+
+    date = [[self startDate] dateByAddingYears:0
+                             months:-1
+                             days:0
+                             hours:0
+                             minutes:0
+                             seconds:0];
+    return [self queryParametersBySettingSelectedDate:date];
+}
+
+- (NSDictionary *)nextMonthQueryParameters {
+    NSCalendarDate *date;
+    
+    date = [[self startDate] dateByAddingYears:0
+                             months:1
+                             days:0
+                             hours:0
+                             minutes:0
+                             seconds:0];
+    return [self queryParametersBySettingSelectedDate:date];
+}
+
+@end /* UIxCalMonthView */
diff --git a/SOGo/UI/Scheduler/UIxCalSelectTab.m b/SOGo/UI/Scheduler/UIxCalSelectTab.m
new file mode 100644 (file)
index 0000000..adacf04
--- /dev/null
@@ -0,0 +1,103 @@
+/*
+  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 <Common/UIxComponent.h>
+#include <NGObjWeb/NGObjWeb.h>
+#include <NGExtensions/NGExtensions.h>
+
+
+@interface UIxCalSelectTab : UIxComponent
+{
+    NSString *selection;
+    NSCalendarDate *currentDate;
+}
+
+@end
+
+
+@implementation UIxCalSelectTab
+
+- (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;
+}
+
+
+/* labels */
+
+
+- (NSString *)dayLabel {
+    return [self->currentDate descriptionWithCalendarFormat:@"%d"];
+}
+
+- (NSString *)weekLabel {
+    return [NSString stringWithFormat:@"Week %d", [self->currentDate weekOfYear]];
+}
+
+- (NSString *)monthLabel {
+    return [self->currentDate descriptionWithCalendarFormat:@"%B"];
+}
+
+- (NSString *)yearLabel {
+    return [self->currentDate descriptionWithCalendarFormat:@"%Y"];
+}
+
+
+/* hrefs */
+
+
+- (NSString *)daytabLink {
+    return [self completeHrefForMethod:@"dayoverview"];
+}
+
+- (NSString *)weektabLink {
+    return [self completeHrefForMethod:@"weekoverview"];
+}
+
+- (NSString *)monthtabLink {
+    return [self completeHrefForMethod:@"monthoverview"];
+}
+
+- (NSString *)yeartabLink {
+    return [self completeHrefForMethod:@"yearoverview"];
+}
+
+
+@end
diff --git a/SOGo/UI/Scheduler/UIxCalSelectTab.wox b/SOGo/UI/Scheduler/UIxCalSelectTab.wox
new file mode 100644 (file)
index 0000000..98ae502
--- /dev/null
@@ -0,0 +1,25 @@
+<?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"
+             var:selection="selection"
+             const:tabStyle="tab"
+             const:selectedTabStyle="tab_selected"
+             const:bodyStyle="tabview_body"
+>
+     <uix:tab const:key="day" var:label="dayLabel" var:href="daytabLink">
+     <var:component-content />
+     </uix:tab>
+     <uix:tab const:key="week" var:label="weekLabel" var:href="weektabLink">
+     <var:component-content />
+     </uix:tab>
+     <uix:tab const:key="month" var:label="monthLabel" var:href="monthtabLink">
+     <var:component-content />
+     </uix:tab>
+     <uix:tab const:key="year" var:label="yearLabel" var:href="yeartabLink">
+     <var:component-content />
+     </uix:tab>
+</uix:tabview>
diff --git a/SOGo/UI/Scheduler/UIxCalView.h b/SOGo/UI/Scheduler/UIxCalView.h
new file mode 100644 (file)
index 0000000..c9c10e6
--- /dev/null
@@ -0,0 +1,67 @@
+// $Id$
+
+#ifndef __ZideStoreUI_UIxCalView_H__
+#define __ZideStoreUI_UIxCalView_H__
+
+#include <Common/UIxComponent.h>
+
+@class NSArray, NSCalendarDate;
+@class SxAptManager, SxAptSetIdentifier;
+
+@interface UIxCalView : UIxComponent
+{
+  NSArray *appointments;
+  id      appointment;
+  NSCalendarDate *currentDay;
+}
+
+/* accessors */
+
+- (NSArray *)appointments;
+- (id)appointment;
+
+- (NSDictionary *)aptTypeDict;
+- (NSString *)aptTypeLabel;
+- (NSString *)aptTypeIcon;
+- (NSString *)shortTextForApt;
+- (NSString *)shortTitleForApt;
+
+/* related to current day */
+- (void)setCurrentDay:(NSCalendarDate *)_day;
+- (NSCalendarDate *)currentDay;
+- (NSString *)currentDayName;
+- (NSArray *)allDayApts;
+- (BOOL)hasDayInfo;
+- (BOOL)hasHoldidayInfo;
+
+    
+- (BOOL)showFullNames;
+- (BOOL)showAMPMDates;
+- (NSCalendarDate *)referenceDateForFormatter;
+    
+/* URLs */
+
+- (NSString *)appointmentViewURL;
+
+/* backend */
+
+- (SxAptManager *)aptManager;
+- (SxAptSetIdentifier *)aptSetID;
+
+/* fetching */
+
+- (NSCalendarDate *)startDate;
+- (NSCalendarDate *)endDate;
+- (NSArray *)fetchGIDs;
+- (NSArray *)fetchCoreInfos;
+
+/* date selection */
+- (NSDictionary *)todayQueryParameters;
+- (NSDictionary *)currentDayQueryParameters;
+- (NSDictionary *)queryParametersBySettingSelectedDate:(NSCalendarDate *)_date;
+- (void)setSelectedDateQueryParameter:(NSCalendarDate *)_newDate
+        inDictionary:(NSMutableDictionary *)_qp;
+
+@end
+
+#endif /* __ZideStoreUI_UIxCalView_H__ */
diff --git a/SOGo/UI/Scheduler/UIxCalView.m b/SOGo/UI/Scheduler/UIxCalView.m
new file mode 100644 (file)
index 0000000..ebd925f
--- /dev/null
@@ -0,0 +1,235 @@
+// $Id$
+
+#include "UIxCalView.h"
+#include "common.h"
+#include <Backend/SxAptManager.h>
+#include "UIxAppointmentFormatter.h"
+
+@interface NSObject(UsedPrivates)
+- (SxAptManager *)aptManagerInContext:(id)_ctx;
+@end
+
+@implementation UIxCalView
+
+- (void)dealloc {
+  [self->appointment  release];
+  [self->appointments release];
+  [self->currentDay release];
+  [super dealloc];
+}
+
+/* accessors */
+
+
+- (void)setAppointments:(NSArray *)_apts {
+  ASSIGN(self->appointments, _apts);
+}
+- (NSArray *)appointments {
+  return self->appointments;
+}
+
+- (void)setAppointment:(id)_apt {
+  ASSIGN(self->appointment, _apt);
+}
+- (id)appointment {
+  return self->appointment;
+}
+
+- (NSDictionary *)aptTypeDict {
+    return nil;
+}
+
+- (NSString *)aptTypeLabel {
+    return @"aptLabel";
+}
+
+- (NSString *)aptTypeIcon {
+    return @"";
+}
+
+- (NSString *)shortTextForApt {
+    UIxAppointmentFormatter *f;
+    
+    f = [UIxAppointmentFormatter formatterWithFormat:
+        @"%S - %E;\n%T;\n%L;\n%5P;\n%50R"];
+    [f setRelationDate:[self referenceDateForFormatter]];
+    [f setShowFullNames:[self showFullNames]];
+    if([self showAMPMDates])
+        [f switchToAMPMTimes:YES];
+    
+    return [NSString stringWithFormat:@"%@:\n%@",
+        [self aptTypeLabel],
+        [f stringForObjectValue:self->appointment]];
+}
+
+- (NSString *)shortTitleForApt {
+    NSString *title;
+    
+    title = [self->appointment valueForKey:@"title"];
+    if([title length] > 12) {
+        title = [NSString stringWithFormat:@"%@...",
+            [title substringToIndex:11]];
+    }
+    return title;
+}
+
+- (NSCalendarDate *)referenceDateForFormatter {
+    return [self selectedDate];
+}
+
+/* current day related */
+
+- (void)setCurrentDay:(NSCalendarDate *)_day {
+    ASSIGN(self->currentDay, _day);
+}
+- (NSCalendarDate *)currentDay {
+    return self->currentDay;
+}
+
+- (NSString *)currentDayName {
+    // TODO: this is slow, use locale dictionary to speed this up
+    return [self->currentDay descriptionWithCalendarFormat:@"%A"];
+}
+
+- (BOOL)hasDayInfo {
+    return [self hasHoldidayInfo] || ([[self allDayApts] count] != 0);
+}
+
+- (BOOL)hasHoldidayInfo {
+    return NO;
+}
+
+- (NSArray *)allDayApts {
+    return [NSArray array];
+}
+
+
+/* defaults */
+
+
+- (BOOL)showFullNames {
+    return YES;
+}
+
+- (BOOL)showAMPMDates {
+    return NO;
+}
+
+
+/* URLs */
+
+- (NSString *)appointmentViewURL {
+  id pkey;
+  
+  if ((pkey = [[self appointment] valueForKey:@"dateId"]) == nil)
+    return nil;
+  
+  return [NSString stringWithFormat:@"%@/view", pkey];
+}
+
+
+/* backend */
+
+- (SxAptManager *)aptManager {
+  return [[self clientObject] aptManagerInContext:[self context]];
+}
+- (SxAptSetIdentifier *)aptSetID {
+  return [[self clientObject] aptSetID];
+}
+
+/* resource URLs (TODO?) */
+
+- (NSString *)resourcePath {
+  return @"/ZideStore.woa/WebServerResources/";
+}
+
+- (NSString *)favIconPath {
+  return [[self resourcePath] stringByAppendingPathComponent:@"favicon.ico"];
+}
+- (NSString *)cssPath {
+  NSString *path;
+  
+  // TODO: there should be reusable functionality for that!
+  path = @"ControlPanel/Products/ZideStoreUI/Resources/zidestoreui.css";
+  return [[self context] urlWithRequestHandlerKey:@"so"
+                        path:path
+                        queryString:nil];
+}
+
+- (NSString *)calCSSPath {
+  NSString *path;
+  
+  // TODO: there should be reusable functionality for that!
+  path = @"ControlPanel/Products/ZideStoreUI/Resources/calendar.css";
+  return [[self context] urlWithRequestHandlerKey:@"so"
+                        path:path
+                        queryString:nil];
+}
+
+/* fetching */
+
+- (NSCalendarDate *)startDate {
+  return [self selectedDate];
+}
+- (NSCalendarDate *)endDate {
+  return [[self startDate] tomorrow];
+}
+
+- (NSArray *)fetchGIDs {
+  return [[self aptManager] gidsOfAppointmentSet:[self aptSetID]
+                            from:[self startDate] to:[self endDate]];
+}
+
+- (NSArray *)fetchCoreInfos {
+  NSArray *gids;
+  
+  if (self->appointments)
+    return self->appointments;
+  
+  [self logWithFormat:@"fetching (%@ => %@) ...", 
+         [self startDate], [self endDate]];
+  gids = [self fetchGIDs];
+  [self logWithFormat:@"  %i GIDs ...", [gids count]];
+  
+  self->appointments = 
+    [[[self aptManager] coreInfoOfAppointmentsWithGIDs:gids
+                        inSet:[self aptSetID]] retain];
+  
+  [self logWithFormat:@"fetched %i records.", [self->appointments count]];
+  return self->appointments;
+}
+
+
+/* date selection & conversion */
+
+
+- (NSDictionary *)todayQueryParameters {
+    NSCalendarDate *date;
+    
+    date = [NSCalendarDate date]; /* today */
+    return [self queryParametersBySettingSelectedDate:date];
+}
+
+- (NSDictionary *)currentDayQueryParameters {
+    return [self queryParametersBySettingSelectedDate:self->currentDay];
+}
+
+- (NSDictionary *)queryParametersBySettingSelectedDate:(NSCalendarDate *)_date {
+    NSMutableDictionary *qp;
+    
+    qp = [[self queryParameters] mutableCopy];
+    [self setSelectedDateQueryParameter:_date inDictionary:qp];
+    return [qp autorelease];
+}
+
+- (void)setSelectedDateQueryParameter:(NSCalendarDate *)_newDate
+        inDictionary:(NSMutableDictionary *)_qp;
+{
+    if(_newDate != nil)
+        [_qp setObject:[self dateStringForDate:_newDate]
+             forKey:@"day"];
+    else
+        [_qp removeObjectForKey:@"day"];
+}
+
+@end /* UIxCalView */
diff --git a/SOGo/UI/Scheduler/UIxCalWeekOverview.m b/SOGo/UI/Scheduler/UIxCalWeekOverview.m
new file mode 100644 (file)
index 0000000..f2d8caf
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+  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 "UIxCalWeekView.h"
+
+@interface UIxCalWeekOverview : UIxCalWeekView
+{
+    int dayIndex;
+}
+
+@end
+
+#include "common.h"
+#include <Backend/SxAptManager.h>
+
+
+@implementation UIxCalWeekOverview
+
+- (NSArray *)appointments {
+  return [self fetchCoreInfos];
+}
+
+- (void)setDayIndex:(char)_idx {
+    NSCalendarDate *d;
+    
+    if ((self->dayIndex == _idx) && (self->currentDay != nil))
+        return;
+    
+    self->dayIndex = _idx;
+    
+    if (_idx > 0) {
+        d = [[self startDate]
+               dateByAddingYears:0 months:0 days:_idx
+                           hours:0 minutes:0 seconds:0];
+    }
+    else
+        d = [self startDate];
+    
+    [self setCurrentDay:d];
+}
+
+- (int)dayIndex {
+    return self->dayIndex;
+}
+
+/* style sheet */
+
+- (NSString *)titleStyle {
+    if([self->currentDay isToday])
+        return @"weekoverview_title_hilite";
+    return @"weekoverview_title";
+}
+
+- (NSString *)contentStyle {
+    if([self->currentDay isToday])
+        return @"weekoverview_content_hilite";
+    return @"weekoverview_content";
+}
+
+@end /* UIxCalWeekOverview */
diff --git a/SOGo/UI/Scheduler/UIxCalWeekOverview.wox b/SOGo/UI/Scheduler/UIxCalWeekOverview.wox
new file mode 100644 (file)
index 0000000..7d590c2
--- /dev/null
@@ -0,0 +1,161 @@
+<?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="UIxPageFrame"
+               title="name">
+
+  <!-- $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"><var:component className="UIxCalDateLabel" startDate="startDate" endDate="endDate" const:selection="week" /></td>
+  <td width="36" align="right" valign="center">
+  <var:component className="UIxWinClose" />
+  </td>
+  </tr>
+  </table>
+  </td>
+  </tr>
+
+  <tr>
+  <td id="skywinbodycell" class="wincontent">
+    <table border="0" cellpadding="0" cellspacing="0" width="100%">
+    <tr bgcolor="#e8e8e0">
+    <td align="left" valign="middle" width="80%">TODO: controls</td><!-- 99% -->
+    <td align="right">
+    <var:component className="UIxCalBackForthNavView"
+                   methodName="ownMethodName"
+                   prevQueryParameters="prevWeekQueryParameters"
+                   currentQueryParameters="todayQueryParameters"
+                   nextQueryParameters="nextWeekQueryParameters"
+                   const:label="this week"
+    />
+    </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="UIxCalSelectTab" const:selection="week" currentDate="selectedDate">
+
+        <table border="0" cellpadding="4" width="100%" cellspacing="2">
+          <tr>
+            <td width="1%" align="left" valign="middle" bgcolor="#e8e8e0">
+              <table border='0' cellpadding='0' cellspacing='0'>
+               <tr>
+                  <td><img rsrc:src="icon_apt_overview_inactive.gif" title="Overview" alt="Overview" border="0" valign="top" /></td>
+                  <td><a href="weekchartview"><img rsrc:src="icon_apt_chart.gif" title="Chart" alt="Chart" border="0" valign="top" /></a></td>
+                  <td><a href="weeklistview"><img rsrc:src="icon_apt_list.gif" title="List" alt="List" border="0" valign="top" /></a></td>
+                  <td>
+                    <a href="weekcolumnview"><img rsrc:src="icon_apt_column_view.gif" title="Columns" alt="Columns" border="0" valign="top" /></a>
+                  </td>
+               </tr>
+              </table>
+            </td>
+          
+            <td align="right" bgcolor="#e8e8e0">
+                <table border='0' cellpadding='0' cellspacing='1'>
+                    <tr>
+                        <td class="button_auto_env" nowrap="true" valign='middle' align='center'>
+                            <a class="button_auto" href="weekprintview" var:queryDictionary="queryParameters" target="SOGoPrintView">printview</a>
+                        </td>
+                        <td class="button_auto_env" nowrap="true" valign='middle' align='center'>
+                            <a class="button_auto" href="proposal" var:queryDictionary="queryParameters">proposal</a>
+                        </td>
+                    </tr>
+                </table>
+            </td>
+          </tr>
+        </table>
+
+    <var:week-overview list="appointments"
+                       item="appointment"
+                       weekStart="startDate"
+                       dayIndex="dayIndex"
+                       const:startDateKey="startDate"
+                       const:endDateKey="endDate"
+                       const:titleStyle="weekoverview_title"
+                       contentStyle="contentStyle"
+    >
+        <var:week-title>
+            <table cellpadding="0"
+                   width="100%"
+                   border="0"
+                   cellspacing="0"
+                   var:class="titleStyle"
+            >
+                <tr>
+                    <td align="left" valign="top">
+                        <a href="dayoverview"
+                           var:queryDictionary="currentDayQueryParameters"
+                           class="weekoverview_title_daylink"
+                        ><var:string value="currentDay.dayOfMonth" /></a>
+                    </td>
+                    <td align="center" valign="top" width="97%">
+                    <var:string value="currentDayName" /><br />
+                    [<a href="new"
+                        var:queryDictionary="currentDayQueryParameters"
+                        class="weekoverview_title_newlink"
+                     >new</a>]
+                    </td>
+                </tr>
+            </table>
+        </var:week-title>
+        <var:if condition="hasDayInfo">
+            <var:week-info>
+                <var:if condition="hasHolidayInfo">
+                    <var:string value="holidayInfo" const:class="weekoverview_holidayinfo" />
+                </var:if>
+                <var:foreach list="allDayApts" item="appointment">
+                    <a var:href="appointmentViewURL"
+                       var:queryDictionary="currentDayQueryParameters"
+                    ><var:string value="shortTextForApt" /></a>
+                </var:foreach>
+            </var:week-info>
+        </var:if>
+      <var:week>
+          <a var:href="appointmentViewURL"><var:string value="appointment.title"/></a>
+      </var:week>
+  </var:week-overview>
+  </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="" src="/ZideStore/so/ControlPanel/Products/CommonUI/Resources/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>
+  <!--
+  <hr />
+  <var:string value="thisWeekQueryParameters" />
+  -->
+  <!--
+  <hr/>
+    
+    Appointments: 
+    <var:component className="UIxAptTableView" appointments="appointments"/>
+  -->
+    <!-- pre><var:string value="appointments" const:insertBR="YES"/></pre -->
+
+</var:component>
diff --git a/SOGo/UI/Scheduler/UIxCalWeekView.h b/SOGo/UI/Scheduler/UIxCalWeekView.h
new file mode 100644 (file)
index 0000000..f32b434
--- /dev/null
@@ -0,0 +1,19 @@
+// $Id$
+
+#ifndef __ZideStoreUI_UIxCalWeekView_H__
+#define __ZideStoreUI_UIxCalWeekView_H__
+
+#include "UIxCalView.h"
+
+@interface UIxCalWeekView : UIxCalView
+{
+}
+
+/* Query Parameters */
+
+- (NSDictionary *)prevWeekQueryParameters;
+- (NSDictionary *)nextWeekQueryParameters;
+    
+@end
+
+#endif /* __ZideStoreUI_UIxCalWeekView_H__ */
diff --git a/SOGo/UI/Scheduler/UIxCalWeekView.m b/SOGo/UI/Scheduler/UIxCalWeekView.m
new file mode 100644 (file)
index 0000000..5df1d2d
--- /dev/null
@@ -0,0 +1,35 @@
+// $Id$
+
+#include "UIxCalWeekView.h"
+#include "common.h"
+
+@implementation UIxCalWeekView
+
+- (NSCalendarDate *)startDate {
+  return [[super startDate] mondayOfWeek];
+}
+
+- (NSCalendarDate *)endDate {
+  return [[self startDate] dateByAddingYears:0 months:0 days:7
+                          hours:0 minutes:0 seconds:0];
+}
+
+/* URLs */
+
+- (NSDictionary *)prevWeekQueryParameters {
+    NSCalendarDate *date;
+
+    date = [[self startDate] dateByAddingYears:0 months:0 days:-7 
+                             hours:0 minutes:0 seconds:0];
+    return [self queryParametersBySettingSelectedDate:date];
+}
+
+- (NSDictionary *)nextWeekQueryParameters {
+    NSCalendarDate *date;
+    
+    date = [[self startDate] dateByAddingYears:0 months:0 days:7 
+                             hours:0 minutes:0 seconds:0];
+    return [self queryParametersBySettingSelectedDate:date];
+}
+
+@end /* UIxCalWeekView */
diff --git a/SOGo/UI/Scheduler/Version b/SOGo/UI/Scheduler/Version
new file mode 100644 (file)
index 0000000..d64ce5a
--- /dev/null
@@ -0,0 +1,5 @@
+# $Id: Version,v 1.1 2003/11/24 01:24:40 helge Exp $
+
+SUBMINOR_VERSION:=1
+
+# 1.1.0 requires NGObjWeb 4.2.202
diff --git a/SOGo/UI/Scheduler/bundle-info.plist b/SOGo/UI/Scheduler/bundle-info.plist
new file mode 100644 (file)
index 0000000..44a5c52
--- /dev/null
@@ -0,0 +1,20 @@
+{
+  "__cvs__" = "$Id: bundle-info.plist,v 1.1 2003/11/24 01:24:40 helge Exp $";
+
+  requires = {
+    bundleManagerVersion = 1;
+    classes = (
+      { name = NSObject;    }
+    );
+  };
+
+  provides = {
+    ZideStoreProducts = ( { name = SchedulerUIProduct; } );
+    
+    classes = (
+    );
+
+    WOComponents = (
+    );
+  };
+}
diff --git a/SOGo/UI/Scheduler/common.h b/SOGo/UI/Scheduler/common.h
new file mode 100644 (file)
index 0000000..093af0b
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+  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: common.h,v 1.1 2003/11/24 01:24:40 helge Exp $
+
+#import <Foundation/Foundation.h>
+
+#if LIB_FOUNDATION_LIBRARY
+#  include <Foundation/exceptions/GeneralExceptions.h>
+#elif NeXT_Foundation_LIBRARY || COCOA_Foundation_LIBRARY
+#  include <NGExtensions/NGObjectMacros.h>
+#  include <NGExtensions/NSString+Ext.h>
+#endif
+
+#include <NGExtensions/NGExtensions.h>
+#include <NGObjWeb/NGObjWeb.h>
+#include <NGObjWeb/SoObjects.h>
diff --git a/SOGo/UI/Scheduler/images/icon_apt_chart.gif b/SOGo/UI/Scheduler/images/icon_apt_chart.gif
new file mode 100644 (file)
index 0000000..ba0f740
Binary files /dev/null and b/SOGo/UI/Scheduler/images/icon_apt_chart.gif differ
diff --git a/SOGo/UI/Scheduler/images/icon_apt_chart_inactive.gif b/SOGo/UI/Scheduler/images/icon_apt_chart_inactive.gif
new file mode 100644 (file)
index 0000000..240f1e8
Binary files /dev/null and b/SOGo/UI/Scheduler/images/icon_apt_chart_inactive.gif differ
diff --git a/SOGo/UI/Scheduler/images/icon_apt_column_view.gif b/SOGo/UI/Scheduler/images/icon_apt_column_view.gif
new file mode 100644 (file)
index 0000000..4af2fa1
Binary files /dev/null and b/SOGo/UI/Scheduler/images/icon_apt_column_view.gif differ
diff --git a/SOGo/UI/Scheduler/images/icon_apt_list.gif b/SOGo/UI/Scheduler/images/icon_apt_list.gif
new file mode 100644 (file)
index 0000000..857db76
Binary files /dev/null and b/SOGo/UI/Scheduler/images/icon_apt_list.gif differ
diff --git a/SOGo/UI/Scheduler/images/icon_apt_list_inactive.gif b/SOGo/UI/Scheduler/images/icon_apt_list_inactive.gif
new file mode 100644 (file)
index 0000000..4e8debf
Binary files /dev/null and b/SOGo/UI/Scheduler/images/icon_apt_list_inactive.gif differ
diff --git a/SOGo/UI/Scheduler/images/icon_apt_overview.gif b/SOGo/UI/Scheduler/images/icon_apt_overview.gif
new file mode 100644 (file)
index 0000000..43ac796
Binary files /dev/null and b/SOGo/UI/Scheduler/images/icon_apt_overview.gif differ
diff --git a/SOGo/UI/Scheduler/images/icon_apt_overview_inactive.gif b/SOGo/UI/Scheduler/images/icon_apt_overview_inactive.gif
new file mode 100644 (file)
index 0000000..7736f48
Binary files /dev/null and b/SOGo/UI/Scheduler/images/icon_apt_overview_inactive.gif differ
diff --git a/SOGo/UI/Scheduler/images/next_week.gif b/SOGo/UI/Scheduler/images/next_week.gif
new file mode 100644 (file)
index 0000000..bacfdb0
Binary files /dev/null and b/SOGo/UI/Scheduler/images/next_week.gif differ
diff --git a/SOGo/UI/Scheduler/images/previous_week.gif b/SOGo/UI/Scheduler/images/previous_week.gif
new file mode 100644 (file)
index 0000000..5f1a0da
Binary files /dev/null and b/SOGo/UI/Scheduler/images/previous_week.gif differ
diff --git a/SOGo/UI/Scheduler/product.plist b/SOGo/UI/Scheduler/product.plist
new file mode 100644 (file)
index 0000000..680bd69
--- /dev/null
@@ -0,0 +1,71 @@
+{
+  requires = ( MAIN, CommonUI );
+
+  publicResources = (
+    previous_week.gif,
+    next_week.gif,
+    icon_apt_chart.gif,
+    icon_apt_overview.gif,
+    icon_apt_chart_inactive.gif,
+    icon_apt_overview_inactive.gif,
+    icon_apt_column_view.gif,
+    icon_apt_list.gif,
+    icon_apt_list_inactive.gif
+  );
+
+  factories = {
+  };
+
+  categories = {
+    SxAppointmentFolder = {
+      methods = {
+        "weekoverview" = { 
+          protectedBy = "View";
+          pageName    = "UIxCalWeekOverview"; 
+        };
+        "weekchartview" = { 
+          protectedBy = "View";
+          pageName    = "UIxCalWeekOverview"; 
+        };
+        "weeklistview" = { 
+          protectedBy = "View";
+          pageName    = "UIxCalWeekOverview"; 
+        };
+        "weekcolumnview" = { 
+          protectedBy = "View";
+          pageName    = "UIxCalWeekOverview"; 
+        };
+        "weekprintview" = { 
+          protectedBy = "View";
+          pageName    = "UIxCalWeekOverview"; 
+        };
+        "monthoverview" = { 
+          protectedBy = "View";
+          pageName    = "UIxCalMonthOverview"; 
+        };
+        "new" = { 
+          protectedBy = "View";
+          pageName    = "UIxAppointmentEditor"; 
+        };
+      };
+    };
+
+    SxAppointment = {
+      methods = {
+        "view" = { 
+          protectedBy = "View";
+          pageName    = "UIxAppointmentView"; 
+        };
+        "edit" = { 
+          protectedBy = "View";
+          pageName    = "UIxAppointmentEditor"; 
+        };
+        "save" = { 
+          protectedBy = "View";
+          pageName    = "UIxAppointmentEditor"; 
+          actionName  = "save";
+        };
+      };
+    };
+  };
+}