[Checkins] SVN: CMF/branches/2.0/C - CMFCalendar: Added experimental Zope 3-style browser views.

Jens Vagelpohl jens at dataflake.org
Mon Apr 3 16:37:39 EDT 2006


Log message for revision 66356:
  - CMFCalendar: Added experimental Zope 3-style browser views.
    The views are disabled by default. See README.txt of the browser
    sub-package for further information.
  
    XXX Note XXX
    One nasty I felt I had to do was add some calendar-related helpers 
    to CMFDefault.browser.utils.ViewBase. This is due to the nature of
    the calendar month view widget that shows everywhere when CMFCalendar
    is enabled. Better ideas welcome!
  
  

Changed:
  U   CMF/branches/2.0/CHANGES.txt
  U   CMF/branches/2.0/CMFCalendar/CalendarTool.py
  U   CMF/branches/2.0/CMFCalendar/Event.py
  U   CMF/branches/2.0/CMFCalendar/__init__.py
  A   CMF/branches/2.0/CMFCalendar/browser/
  A   CMF/branches/2.0/CMFCalendar/browser/README.txt
  A   CMF/branches/2.0/CMFCalendar/browser/TODO.txt
  A   CMF/branches/2.0/CMFCalendar/browser/__init__.py
  A   CMF/branches/2.0/CMFCalendar/browser/calendar.py
  A   CMF/branches/2.0/CMFCalendar/browser/configure.zcml
  A   CMF/branches/2.0/CMFCalendar/browser/event.py
  A   CMF/branches/2.0/CMFCalendar/browser/templates/
  A   CMF/branches/2.0/CMFCalendar/browser/templates/calendar_day.pt
  A   CMF/branches/2.0/CMFCalendar/browser/templates/calendar_widgets.pt
  A   CMF/branches/2.0/CMFCalendar/browser/templates/event.pt
  A   CMF/branches/2.0/CMFCalendar/browser/templates/event_edit.pt
  A   CMF/branches/2.0/CMFCalendar/configure.zcml
  A   CMF/branches/2.0/CMFCalendar/interfaces/
  A   CMF/branches/2.0/CMFCalendar/interfaces/Event.py
  A   CMF/branches/2.0/CMFCalendar/interfaces/__init__.py
  A   CMF/branches/2.0/CMFCalendar/interfaces/_content.py
  A   CMF/branches/2.0/CMFCalendar/interfaces/_tools.py
  A   CMF/branches/2.0/CMFCalendar/interfaces/portal_calendar.py
  A   CMF/branches/2.0/CMFCalendar/profiles/views_support/
  A   CMF/branches/2.0/CMFCalendar/profiles/views_support/types/
  A   CMF/branches/2.0/CMFCalendar/profiles/views_support/types/Event.xml
  U   CMF/branches/2.0/CMFCalendar/tests/test_Calendar.py
  U   CMF/branches/2.0/CMFCalendar/tests/test_Event.py
  U   CMF/branches/2.0/CMFDefault/browser/utils.py

-=-
Modified: CMF/branches/2.0/CHANGES.txt
===================================================================
--- CMF/branches/2.0/CHANGES.txt	2006-04-03 17:49:47 UTC (rev 66355)
+++ CMF/branches/2.0/CHANGES.txt	2006-04-03 20:37:37 UTC (rev 66356)
@@ -1,5 +1,11 @@
 CMF 2.0.0 (unreleased)
 
+  New Features
+
+    - CMFCalendar: Added experimental Zope 3-style browser views.
+      The views are disabled by default. See README.txt of the browser
+      sub-package for further information.
+
   Bug Fixes
 
     - IndexableObjectWrapper: Fixed list of provided interfaces.

Modified: CMF/branches/2.0/CMFCalendar/CalendarTool.py
===================================================================
--- CMF/branches/2.0/CMFCalendar/CalendarTool.py	2006-04-03 17:49:47 UTC (rev 66355)
+++ CMF/branches/2.0/CMFCalendar/CalendarTool.py	2006-04-03 20:37:37 UTC (rev 66356)
@@ -22,10 +22,13 @@
 from DateTime import DateTime
 from Globals import InitializeClass
 from OFS.SimpleItem import SimpleItem
+from zope.interface import implements
 from Products.PageTemplates.PageTemplateFile import PageTemplateFile
 
 from Products.CMFCore.utils import UniqueObject
 
+from interfaces import ICalendarTool
+from interfaces.portal_calendar import portal_calendar as z2ICalendarTool
 from permissions import ManagePortal
 
 class CalendarTool (UniqueObject, SimpleItem):
@@ -34,6 +37,9 @@
     meta_type= 'CMF Calendar Tool'
     security = ClassSecurityInfo()
 
+    implements(ICalendarTool)
+    __implements__ = (z2ICalendarTool,)
+
     calendar_types = ('Event',)
     calendar_states = ('published',)
     use_session = ''

Modified: CMF/branches/2.0/CMFCalendar/Event.py
===================================================================
--- CMF/branches/2.0/CMFCalendar/Event.py	2006-04-03 17:49:47 UTC (rev 66355)
+++ CMF/branches/2.0/CMFCalendar/Event.py	2006-04-03 20:37:37 UTC (rev 66356)
@@ -19,6 +19,7 @@
 from DateTime import DateTime
 from Globals import InitializeClass
 import transaction
+from zope.interface import implements
 
 from Products.CMFCore.PortalContent import PortalContent
 from Products.CMFCore.utils import contributorsplitter
@@ -31,40 +32,47 @@
 from Products.CMFDefault.utils import parseHeadersBody
 from Products.CMFDefault.utils import SimpleHTMLParser
 
+from Products.GenericSetup.interfaces import IDAVAware
+
 from exceptions import ResourceLockedError
+from interfaces import IEvent
+from interfaces import IMutableEvent
+from interfaces.Event import IEvent as z2IEvent
+from interfaces.Event import IMutableEvent as z2IMutableEvent
 from permissions import ChangeEvents
 from permissions import ModifyPortalContent
 from permissions import View
 
 
-def addEvent(self
-             , id
-             , title=''
-             , description=''
-             , effective_date = None 
-             , expiration_date = None 
-             , start_date = None 
-             , end_date = None
-             , location=''
-             , contact_name=''
-             , contact_email=''
-             , contact_phone=''
-             , event_url=''
-             , REQUEST=None):
+def addEvent( self
+            , id
+            , title=''
+            , description=''
+            , effective_date = None 
+            , expiration_date = None 
+            , start_date = None 
+            , end_date = None
+            , location=''
+            , contact_name=''
+            , contact_email=''
+            , contact_phone=''
+            , event_url=''
+            , REQUEST=None
+            ):
     """Create an empty event.
     """
-    event = Event(id
-                  , title
-                  , description
-                  , effective_date
-                  , expiration_date
-                  , start_date
-                  , end_date
-                  , location
-                  , contact_name
-                  , contact_email
-                  , contact_phone
-                  , event_url
+    event = Event( id
+                 , title
+                 , description
+                 , effective_date
+                 , expiration_date
+                 , start_date
+                 , end_date
+                 , location
+                 , contact_name
+                 , contact_email
+                 , contact_phone
+                 , event_url
                  )
     self._setObject(id, event)
 
@@ -95,23 +103,26 @@
     security = ClassSecurityInfo()
     security.declareObjectProtected(View)
 
-    __implements__ = ( PortalContent.__implements__
+    implements(IMutableEvent, IEvent, IDAVAware)
+    __implements__ = ( z2IMutableEvent
+                     , z2IEvent
+                     , PortalContent.__implements__
                      , DefaultDublinCoreImpl.__implements__
                      )
 
-    def __init__(self
-                 , id
-                 , title=''
-                 , description=''
-                 , effective_date = None 
-                 , expiration_date = None 
-                 , start_date = None
-                 , end_date = None
-                 , location=''
-                 , contact_name=''
-                 , contact_email=''
-                 , contact_phone=''
-                 , event_url=''
+    def __init__( self
+                , id
+                , title=''
+                , description=''
+                , effective_date = None 
+                , expiration_date = None 
+                , start_date = None
+                , end_date = None
+                , location=''
+                , contact_name=''
+                , contact_email=''
+                , contact_phone=''
+                , event_url=''
                 ):
         DefaultDublinCoreImpl.__init__(self)
         self.id=id
@@ -147,36 +158,40 @@
 
     security.declarePublic('getEndStrings')
     def getEndStrings(self):
+        """ Returns a mapping with string representations for the end time
+
+        o keys are 'day', 'month' and 'year'
         """
-        """
         return _dateStrings(self.end())
 
     security.declarePublic('getStartStrings')
     def getStartStrings(self):
+        """ Returns a mapping with string representations for the start time
+
+        o keys are 'day', 'month' and 'year'
         """
-        """
         return _dateStrings(self.start())
 
     security.declareProtected(ChangeEvents, 'edit')
-    def edit(self
-             , title=None
-             , description=None
-             , eventType=None
-             , effectiveDay=None
-             , effectiveMo=None
-             , effectiveYear=None
-             , expirationDay=None
-             , expirationMo=None
-             , expirationYear=None
-             , start_time=None
-             , startAMPM=None
-             , stop_time=None
-             , stopAMPM=None
-             , location=None
-             , contact_name=None
-             , contact_email=None
-             , contact_phone=None
-             , event_url=None
+    def edit( self
+            , title=None
+            , description=None
+            , eventType=None
+            , effectiveDay=None
+            , effectiveMo=None
+            , effectiveYear=None
+            , expirationDay=None
+            , expirationMo=None
+            , expirationYear=None
+            , start_time=None
+            , startAMPM=None
+            , stop_time=None
+            , stopAMPM=None
+            , location=None
+            , contact_name=None
+            , contact_email=None
+            , contact_phone=None
+            , event_url=None
             ):
         """\
         """
@@ -262,46 +277,40 @@
 
     security.declareProtected(ChangeEvents, 'setStartDate')
     def setStartDate(self, start):
+        """ Setting the event start date when the event is scheduled to begin.
         """
-        Setting the event start date, when the event is scheduled to begin.
-        """
         self.start_date = self._datify(start)
 
     security.declareProtected(ChangeEvents, 'setEndDate')
     def setEndDate(self, end):
+        """ Setting the event end date, when the event ends.
         """
-        Setting the event end date, when the event ends.
-        """
         self.end_date = self._datify(end)
 
     security.declarePublic('start')
     def start(self):
+        """ Return our start time as a DateTime object
         """
-            Return our start time as a string.
-        """
         date = getattr( self, 'start_date', None )
         return date is None and self.created() or date
 
     security.declarePublic('end')
     def end(self):
+        """ Return our end time as a DateTime object
         """
-            Return our stop time as a string.
-        """
         date = getattr( self, 'end_date', None )
         return date is None and self.start() or date    
 
     security.declarePublic('getStartTimeString')
     def getStartTimeString( self ):
+        """ Return our start time as a string.
         """
-            Return our start time as a string.
-        """
         return self.start().AMPMMinutes() 
 
     security.declarePublic('getStopTimeString')
     def getStopTimeString( self ):
+        """ Return our stop time as a string.
         """
-            Return our stop time as a string.
-        """
         return self.end().AMPMMinutes() 
 
     security.declarePrivate('handleText')
@@ -324,6 +333,13 @@
 
     security.declareProtected(ModifyPortalContent, 'setMetadata')
     def setMetadata(self, headers):
+        """ Set an Event's metadata
+
+        o headers is a mapping containing keys corresponding to
+        Dublin Core metadata fields
+        o Only those attributes that are passed in with the mapping are
+        manipulated
+        """
         headers['Format'] = self.Format()
         new_subject = keywordsplitter(headers)
         headers['Subject'] = new_subject or self.Subject()
@@ -346,7 +362,8 @@
 
     security.declarePublic( 'getMetadataHeaders' )
     def getMetadataHeaders(self):
-        """Return RFC-822-style header spec."""
+        """ Return metadata attributes in RFC-822-style header spec.
+        """
         hdrlist = DefaultDublinCoreImpl.getMetadataHeaders(self)
         hdrlist.append( ('StartDate', self.start().strftime("%Y-%m-%d %H:%M:%S") ) )
         hdrlist.append( ('EndDate',  self.end().strftime("%Y-%m-%d %H:%M:%S") ) )

Modified: CMF/branches/2.0/CMFCalendar/__init__.py
===================================================================
--- CMF/branches/2.0/CMFCalendar/__init__.py	2006-04-03 17:49:47 UTC (rev 66355)
+++ CMF/branches/2.0/CMFCalendar/__init__.py	2006-04-03 20:37:37 UTC (rev 66356)
@@ -64,3 +64,12 @@
                                      EXTENSION,
                                      for_=ISiteRoot,
                                     )
+
+    profile_registry.registerProfile('views_support',
+                                     'Experimental CMFCalendar Browser Views',
+                                     'Hooks up the browser views.',
+                                     'profiles/views_support',
+                                     'CMFCalendar',
+                                     EXTENSION,
+                                     for_=ISiteRoot,
+                                    )

Added: CMF/branches/2.0/CMFCalendar/browser/README.txt
===================================================================
--- CMF/branches/2.0/CMFCalendar/browser/README.txt	2006-04-03 17:49:47 UTC (rev 66355)
+++ CMF/branches/2.0/CMFCalendar/browser/README.txt	2006-04-03 20:37:37 UTC (rev 66356)
@@ -0,0 +1,17 @@
+Experimental Browser Views
+
+  This sub-package provides Zope 3-style browser views for the CMFCalendar
+  IEvent interface. These views are not used by the default profile.
+
+  The content of this sub-package is experimental and might be refactored
+  without further notice. Documentation and unittests are still missing but
+  the views should work just as well as the corresponding skin methods.
+
+  See TODO.txt for a detailed list of converted skin methods.
+
+  Using the Browser Views
+
+    In an un-customized CMFDefault site you will notice no difference because
+    the browser views are just different in implementation, not in look and
+    feel. But the browser view machinery bypasses the CMF skin machinery, so
+    you will notice that TTW customizations no longer have any effect.


Property changes on: CMF/branches/2.0/CMFCalendar/browser/README.txt
___________________________________________________________________
Name: svn:eol-style
   + native

Added: CMF/branches/2.0/CMFCalendar/browser/TODO.txt
===================================================================
--- CMF/branches/2.0/CMFCalendar/browser/TODO.txt	2006-04-03 17:49:47 UTC (rev 66355)
+++ CMF/branches/2.0/CMFCalendar/browser/TODO.txt	2006-04-03 20:37:37 UTC (rev 66356)
@@ -0,0 +1,29 @@
+Converting skins to views:
+
+  [x] @@calendar_day.html:
+
+      [x] calendar_day_view.py -> CalendarView.dayInfo
+      [x] calendar_day_view_template.pt -> templates/calendar_day.pt
+      [x] getEndAsString.py -> CalendarView.getEndAsString
+      [x] getStartAsString.py -> CalendarView.getStartAsString
+      [x] getNextDayLink.py -> CalendarView.getNextDayLink
+      [x] getPreviousDayLink.py -> CalendarView.getPreviousDayLink
+
+  [x] @@calendar_widget:
+
+      [x] calendarBox.pt -> templates/calendar_widgets.pt
+      [x] getDaysClass.py -> ViewBase.getDaysClass
+      [x] getMonthAndYear.py -> ViewBase.getMonthAndYear
+      [x] getNextMonthLink.py -> ViewBase.getNextMonthLink
+      [x] getPreviousMonthLink.py -> ViewBase.getPreviousMonthLink
+
+  [x] IEvent @@view.html:
+
+      [x] event_view.py -> EventView
+      [x] event_view_template.pt -> templates/event.pt
+
+  [x] IMutableEvent @@edit.html:
+
+      [x] event_edit_form.py -> EventEditView
+      [x] event_edit_template.pt -> templates/event_edit.pt
+      [x] event_edit_control.py -> EventEditView.edit_control


Property changes on: CMF/branches/2.0/CMFCalendar/browser/TODO.txt
___________________________________________________________________
Name: svn:eol-style
   + native

Added: CMF/branches/2.0/CMFCalendar/browser/__init__.py
===================================================================
--- CMF/branches/2.0/CMFCalendar/browser/__init__.py	2006-04-03 17:49:47 UTC (rev 66355)
+++ CMF/branches/2.0/CMFCalendar/browser/__init__.py	2006-04-03 20:37:37 UTC (rev 66356)
@@ -0,0 +1,16 @@
+##############################################################################
+#
+# Copyright (c) 2006 Zope Corporation and Contributors. All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""CMFCalendar browser views.
+
+$Id$
+"""


Property changes on: CMF/branches/2.0/CMFCalendar/browser/__init__.py
___________________________________________________________________
Name: svn:keywords
   + Id
Name: svn:eol-style
   + native

Added: CMF/branches/2.0/CMFCalendar/browser/calendar.py
===================================================================
--- CMF/branches/2.0/CMFCalendar/browser/calendar.py	2006-04-03 17:49:47 UTC (rev 66355)
+++ CMF/branches/2.0/CMFCalendar/browser/calendar.py	2006-04-03 20:37:37 UTC (rev 66356)
@@ -0,0 +1,101 @@
+##############################################################################
+#
+# Copyright (c) 2006 Zope Corporation and Contributors. All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""Browser views for the portal calendar.
+
+$Id$
+"""
+
+import urlparse
+
+from DateTime.DateTime import DateTime
+
+from Products.CMFDefault.exceptions import ResourceLockedError
+from Products.CMFDefault.utils import Message as _
+
+from Products.CMFDefault.browser.utils import decode
+from Products.CMFDefault.browser.utils import memoize
+from Products.CMFDefault.browser.utils import ViewBase
+
+
+class CalendarView(ViewBase):
+
+    """ Helper class for calendar-related templates
+    """
+
+    @memoize
+    @decode
+    def dayInfo(self):
+        """ Event info for a specific day
+        """
+        info = {}
+        caltool = self._getTool('portal_calendar')
+        view_url = self._getViewURL()
+        date_string = self.request.get('date',DateTime().aCommon()[:12])
+        thisDay = DateTime(date_string)
+
+        info['previous_url'] = '%s?date=%s' % (view_url, (thisDay-1).Date())
+        info['date'] = thisDay.aCommon()[:12]
+        info['next_url'] =  '%s?date=%s' % (view_url, (thisDay+1).Date())
+        
+        items = [ {'title': item.Title,
+                   'url': item.getURL(),
+                   'start': self.getStartAsString(thisDay, item),
+                   'stop': self.getEndAsString(thisDay, item)}
+                  for item in caltool.getEventsForThisDay(thisDay) ]
+        
+        info['listItemInfos'] = tuple(items)
+        
+        return info
+
+    @memoize
+    @decode
+    def getStartAsString(self, day, event):
+        """ Retrieve formatted start string
+        """
+        first_date = DateTime(day.Date()+" 00:00:00")
+        
+        if event.start < first_date:
+            return event.start.aCommon()[:12]
+        else:
+            return event.start.TimeMinutes()
+
+    @memoize
+    @decode
+    def getEndAsString(self, day, event):
+        """ Retrieve formatted end string
+        """
+        last_date = DateTime(day.Date()+" 23:59:59")
+        
+        if event.end > last_date:
+            return event.end.aCommon()[:12]
+        else:
+            return event.end.TimeMinutes()
+
+    @memoize
+    @decode
+    def getNextDayLink(self, base_url, day):
+        """ Return URL for the next day link
+        """
+        day += 1
+        
+        return '%s?date=%s' % (base_url, day.Date())
+
+    @memoize
+    @decode
+    def getPreviousDayLink(self, base_url, day):
+        """ Return URL for the previous day link
+        """
+        day -= 1
+        
+        return '%s?date=%s' % (base_url, day.Date())
+


Property changes on: CMF/branches/2.0/CMFCalendar/browser/calendar.py
___________________________________________________________________
Name: svn:keywords
   + Id
Name: svn:eol-style
   + native

Added: CMF/branches/2.0/CMFCalendar/browser/configure.zcml
===================================================================
--- CMF/branches/2.0/CMFCalendar/browser/configure.zcml	2006-04-03 17:49:47 UTC (rev 66355)
+++ CMF/branches/2.0/CMFCalendar/browser/configure.zcml	2006-04-03 20:37:37 UTC (rev 66356)
@@ -0,0 +1,42 @@
+<configure
+    xmlns="http://namespaces.zope.org/zope"
+    xmlns:browser="http://namespaces.zope.org/browser"
+    xmlns:five="http://namespaces.zope.org/five">
+
+  <browser:page
+      for="Products.CMFCalendar.interfaces.IEvent"
+      name="view.html"
+      class=".event.EventView"
+      template="templates/event.pt"
+      permission="zope2.View"
+      layer="cmf"
+      />
+
+  <browser:page
+      for="Products.CMFCalendar.interfaces.IMutableEvent"
+      name="edit.html"
+      class=".event.EventEditView"
+      template="templates/event_edit.pt"
+      permission="cmf.ModifyPortalContent"
+      layer="cmf"
+      />
+
+  <browser:page
+      for="*"
+      name="calendar_day.html"
+      class=".calendar.CalendarView"
+      template="templates/calendar_day.pt"
+      permission="zope2.View"
+      layer="cmf"
+      />
+
+  <browser:page
+      for="*"
+      name="calendar_widget"
+      class=".calendar.CalendarView"
+      template="templates/calendar_widgets.pt"
+      permission="zope2.View"
+      layer="cmf"
+      />
+
+</configure>


Property changes on: CMF/branches/2.0/CMFCalendar/browser/configure.zcml
___________________________________________________________________
Name: svn:eol-style
   + native

Added: CMF/branches/2.0/CMFCalendar/browser/event.py
===================================================================
--- CMF/branches/2.0/CMFCalendar/browser/event.py	2006-04-03 17:49:47 UTC (rev 66355)
+++ CMF/branches/2.0/CMFCalendar/browser/event.py	2006-04-03 20:37:37 UTC (rev 66356)
@@ -0,0 +1,242 @@
+##############################################################################
+#
+# Copyright (c) 2006 Zope Corporation and Contributors. All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""Browser views for events.
+
+$Id$
+"""
+
+from DateTime.DateTime import DateTime
+
+from Products.CMFDefault.exceptions import ResourceLockedError
+from Products.CMFDefault.utils import Message as _
+
+from Products.CMFDefault.browser.utils import decode
+from Products.CMFDefault.browser.utils import FormViewBase
+from Products.CMFDefault.browser.utils import memoize
+from Products.CMFDefault.browser.utils import ViewBase
+
+
+class EventView(ViewBase):
+
+    """View for IEvent.
+    """
+
+    # interface
+
+    @memoize
+    @decode
+    def contact_name(self):
+        return self.context.contact_name
+
+    @memoize
+    @decode
+    def location(self):
+        return self.context.location
+
+    @memoize
+    @decode
+    def contact_email(self):
+        return self.context.contact_email
+
+    @memoize
+    @decode
+    def event_types(self):
+        return self.context.Subject()
+
+    @memoize
+    @decode
+    def contact_phone(self):
+        return self.context.contact_phone
+
+    @memoize
+    @decode
+    def event_url(self):
+        return self.context.event_url
+
+    @memoize
+    @decode
+    def start_date(self):
+        return DateTime(self.context.start()).Date()
+
+    @memoize
+    @decode
+    def start_time(self):
+        return DateTime(self.context.start()).Time()
+
+    @memoize
+    @decode
+    def stop_date(self):
+        return DateTime(self.context.end()).Date()
+
+    @memoize
+    @decode
+    def stop_time(self):
+        return DateTime(self.context.end()).Time()
+
+
+class EventEditView(FormViewBase):
+
+    """Edit view for IMutableEvent.
+    """
+
+    _BUTTONS = ({'id': 'change',
+                 'title': _(u'Change'),
+                 'transform': ('edit_control',),
+                 'redirect': ('portal_types', 'object/edit')},
+                {'id': 'change_and_view',
+                 'title': _(u'Change and View'),
+                 'transform': ('edit_control',),
+                 'redirect': ('portal_types', 'object/view')})
+
+    # interface
+
+    @memoize
+    @decode
+    def title(self):
+        return self.request.form.get('title', self.context.Title())
+
+    @memoize
+    @decode
+    def description(self):
+        return self.request.form.get('description', self.context.Description())
+
+    @memoize
+    @decode
+    def contact_name(self):
+        return self.request.form.get('contact_name', self.context.contact_name)
+
+    @memoize
+    @decode
+    def location(self):
+        return self.request.form.get('location', self.context.location)
+
+    @memoize
+    @decode
+    def contact_email(self):
+        return self.request.form.get( 'contact_email'
+                                    , self.context.contact_email
+                                    )
+
+    @memoize
+    @decode
+    def event_type(self):
+        return self.request.form.get('event_type', self.context.Subject())
+
+    @memoize
+    @decode
+    def contact_phone(self):
+        return self.request.form.get( 'contact_phone'
+                                    , self.context.contact_phone
+                                    )
+
+    @memoize
+    @decode
+    def event_url(self):
+        return self.request.form.get('event_url', self.context.event_url)
+
+    @memoize
+    @decode
+    def start_time(self):
+        time_strings = self.context.getStartTimeString().split()
+        return self.request.form.get('start_time', time_strings[0])
+
+    @memoize
+    @decode
+    def startAMPM(self):
+        time_strings = self.context.getStartTimeString().split()
+        AMPM = (len(time_strings) == 2 and time_strings[1] or 'pm')
+        return self.request.form.get('startAMPM', AMPM)
+
+    @memoize
+    @decode
+    def stop_time(self):
+        time_strings = self.context.getStopTimeString().split()
+        return self.request.form.get('stop_time', time_strings[0])
+
+    @memoize
+    @decode
+    def stopAMPM(self):
+        time_strings = self.context.getStopTimeString().split()
+        AMPM = (len(time_strings) == 2 and time_strings[1] or 'pm')
+        return self.request.form.get('stopAMPM', AMPM)
+
+    @memoize
+    @decode
+    def effectiveYear(self):
+        date_strings = self.context.getStartStrings()
+        return self.request.form.get('effectiveYear', date_strings['year'])
+
+    @memoize
+    @decode
+    def effectiveMo(self):
+        date_strings = self.context.getStartStrings()
+        return self.request.form.get('effectiveMo', date_strings['month'])
+
+    @memoize
+    @decode
+    def effectiveDay(self):
+        date_strings = self.context.getStartStrings()
+        return self.request.form.get('effectiveDay', date_strings['day'])
+
+    @memoize
+    @decode
+    def expirationYear(self):
+        date_strings = self.context.getEndStrings()
+        return self.request.form.get('expirationYear', date_strings['year'])
+
+    @memoize
+    @decode
+    def expirationMo(self):
+        date_strings = self.context.getEndStrings()
+        return self.request.form.get('expirationMo', date_strings['month'])
+
+    @memoize
+    @decode
+    def expirationDay(self):
+        date_strings = self.context.getEndStrings()
+        return self.request.form.get('expirationDay', date_strings['day'])
+
+    # controllers
+
+    def edit_control( self
+                    , title=None
+                    , description=None
+                    , event_type=None
+                    , effectiveDay=None
+                    , effectiveMo=None
+                    , effectiveYear=None
+                    , expirationDay=None
+                    , expirationMo=None
+                    , expirationYear=None
+                    , start_time=None
+                    , startAMPM=None
+                    , stop_time=None
+                    , stopAMPM=None
+                    , location=None
+                    , contact_name=None
+                    , contact_email=None
+                    , contact_phone=None
+                    , event_url=None
+                    , **kw
+                    ):
+
+        try:
+            self.context.edit( title, description, event_type, effectiveDay
+                             , effectiveMo, effectiveYear, expirationDay
+                             , expirationMo, expirationYear, start_time
+                             , startAMPM, stop_time, stopAMPM, location
+                             , contact_name, contact_email, contact_phone
+                             , event_url)
+            return True, _(u'Event changed.')
+        except ResourceLockedError, errmsg:
+            return False, errmsg


Property changes on: CMF/branches/2.0/CMFCalendar/browser/event.py
___________________________________________________________________
Name: svn:keywords
   + Id
Name: svn:eol-style
   + native

Added: CMF/branches/2.0/CMFCalendar/browser/templates/calendar_day.pt
===================================================================
--- CMF/branches/2.0/CMFCalendar/browser/templates/calendar_day.pt	2006-04-03 17:49:47 UTC (rev 66355)
+++ CMF/branches/2.0/CMFCalendar/browser/templates/calendar_day.pt	2006-04-03 20:37:37 UTC (rev 66356)
@@ -0,0 +1,46 @@
+<html metal:use-macro="context/@@standard_macros/page">
+<head>
+
+<metal:slot fill-slot="style_slot">
+<tal:span tal:replace="structure context/getBaseTag" />
+</metal:slot>
+
+</head>
+<body>
+
+<metal:slot metal:fill-slot="body">
+
+<div class="dayViewBox" metal:define-macro="dayViewBox">
+<table class="dayView" cellpadding="0" cellspacing="0" border="0"
+       tal:define="day_info view/dayInfo">
+ <tr>
+  <th>
+   <a href="#" tal:attributes="href day_info/previous_url">&laquo;</a>
+  </th>
+  <th colspan="3" nowrap="nowrap" tal:content="day_info/date">Date Heading</th>
+  <th>
+   <a href="#" tal:attributes="href day_info/next_url">&raquo;</a>
+  </th>
+ </tr>
+ <tal:loop tal:repeat="item_info day_info/listItemInfos">
+ <tr>
+  <td class="heading" colspan="5" nowrap="nowrap">
+   <a href="#" tal:attributes="href item_info/url"
+      tal:content="item_info/title">event title</a>
+  </td>
+ </tr>
+ <tr>
+  <td class="startDate" colspan="2" nowrap="nowrap"
+     tal:content="item_info/start">Event Start</td>
+  <td nowrap="nowrap"> -- </td>
+  <td class="endDate" colspan="2" nowrap="nowrap"
+     tal:content="item_info/stop">Event End</td>
+ </tr>
+ </tal:loop>
+</table>
+</div>
+
+</metal:slot>
+
+</body>
+</html>


Property changes on: CMF/branches/2.0/CMFCalendar/browser/templates/calendar_day.pt
___________________________________________________________________
Name: svn:eol-style
   + native

Added: CMF/branches/2.0/CMFCalendar/browser/templates/calendar_widgets.pt
===================================================================
--- CMF/branches/2.0/CMFCalendar/browser/templates/calendar_widgets.pt	2006-04-03 17:49:47 UTC (rev 66355)
+++ CMF/branches/2.0/CMFCalendar/browser/templates/calendar_widgets.pt	2006-04-03 20:37:37 UTC (rev 66356)
@@ -0,0 +1,68 @@
+<html metal:use-macro="context/@@standard_macros/page">
+<body>
+
+<metal:slot metal:fill-slot="body" i18n:domain="cmf_calendar">
+ <div metal:define-macro="calendarBox"
+     class="CalendarBox"
+     tal:define="yearmonth view/getMonthAndYear;
+                 year python:yearmonth[0];
+                 month python:yearmonth[1];
+                 weeks python:context.portal_calendar.getEventsForCalendar(month=month, year=year);">
+
+    <div metal:define-slot="title" class="CalendarTitle"
+       i18n:translate="">CMF Calendar</div>
+
+    <!-- The calendar, rendered as a table -->
+    <table cellspacing="0" cellpadding="0" border="1">
+    <tr><td>
+
+    <table cellpadding="2" cellspacing="0" border="0" class="calendar">
+
+        <!-- The headers. The month with links either side -->
+        <tr>
+         <th>
+          <a href="#" class="CalendarArrow"
+             tal:attributes="href python:view.getPreviousMonthLink(request.URL0, month, year)">&laquo;</a>
+         </th>
+         <th colspan="5" tal:define="date python:context.ZopeTime(int(year), int(month), 1)">
+          <tal:span tal:content="python:date.strftime('%B').capitalize()"
+             i18n:translate="">January</tal:span
+         > <tal:span tal:content="python:date.year()">2000</tal:span>
+         </th>
+         <th>
+          <a href="#" class="CalendarArrow"
+             tal:attributes="href python:view.getNextMonthLink(request.URL0, month, year)">&raquo;</a>
+         </th>
+        </tr>
+
+        <!-- The week days across the top -->
+        <tr tal:define="weekdays context/portal_calendar/getDays">
+         <tal:loop tal:repeat="weekday weekdays"
+        ><td class="weekdays" tal:content="weekday" i18n:translate="">
+          Su
+         </td></tal:loop>
+        </tr>
+
+        <!-- The actual days with in the weeks -->
+        <tr tal:repeat="week weeks">
+         <tal:loop tal:repeat="day week"
+        ><td class="event"
+            tal:define="daynumber day/day;
+                        datestring python:'%d/%0.2d/%0.2d' % (year, month, daynumber);"
+            tal:attributes="class python:view.getDaysClass(daynumber, month, year, day['event'])">
+          <a href
+             tal:omit-tag="not: day/event"
+             tal:attributes="href string:${portal_url}/@@calendar_day.html?date=${datestring}"
+             tal:content="python:daynumber or default"> &nbsp;</a>
+         </td></tal:loop>
+        </tr>
+
+    </table>
+    </td></tr>
+    </table>
+
+ </div>
+</metal:slot>
+
+</body>
+</html>


Property changes on: CMF/branches/2.0/CMFCalendar/browser/templates/calendar_widgets.pt
___________________________________________________________________
Name: svn:eol-style
   + native

Added: CMF/branches/2.0/CMFCalendar/browser/templates/event.pt
===================================================================
--- CMF/branches/2.0/CMFCalendar/browser/templates/event.pt	2006-04-03 17:49:47 UTC (rev 66355)
+++ CMF/branches/2.0/CMFCalendar/browser/templates/event.pt	2006-04-03 20:37:37 UTC (rev 66356)
@@ -0,0 +1,74 @@
+<html metal:use-macro="context/@@standard_macros/page">
+<head>
+
+<metal:slot fill-slot="style_slot">
+<tal:span tal:replace="structure context/getBaseTag" />
+</metal:slot>
+
+</head>
+<body>
+
+<metal:slot metal:fill-slot="body">
+
+<table class="Event" border="0" cellpadding="5" width="100%" cellspacing="3">
+ <tr>
+  <th width="10%" i18n:translate="">Event Name</th>
+  <td nowrap="nowrap" tal:content="view/title">Title</td>
+  <th width="10%" i18n:translate="">Contact Name</th>
+  <td nowrap="nowrap" tal:content="view/contact_name">contact_name</td>
+ </tr>
+ <tr>
+  <th width="10%" i18n:translate="">Location</th>
+  <td nowrap="nowrap" tal:content="view/location">location</td>
+  <th width="10%" i18n:translate="">Contact Email</th>
+  <td nowrap="nowrap" tal:condition="view/contact_email">
+   <a tal:attributes="href string:mailto:${view/contact_email}"
+      tal:content="view/contact_email"
+      href="mailto:contact_email">contact_email</a></td>
+ </tr>
+ <tr>
+  <th width="10%" i18n:translate="">Event type</th>
+  <td valign="top" nowrap="nowrap"><tal:loop
+      tal:repeat="event_type view/event_types"><tal:span
+       tal:content="event_type" i18n:translate="" /> </tal:loop></td>
+  <th width="10%" i18n:translate="">Contact Phone</th>
+  <td nowrap="nowrap" tal:content="view/contact_phone">contact_phone</td>
+ </tr>
+ <tr tal:condition="view/event_url">
+  <th width="10%" i18n:translate="">Event URL</th>
+  <td colspan="3" nowrap="nowrap"><a href="event_url"
+     tal:attributes="href view/event_url"
+     tal:content="view/event_url">event_url</a></td>
+ </tr>
+ <tr>
+  <td colspan="4"><hr /></td>
+ </tr>
+ <tr>
+  <th width="10%" i18n:translate="">Start Date</th>
+  <td tal:content="view/start_date">start</td>
+  <th width="10%" i18n:translate="">Stop Date</th>
+  <td tal:content="view/stop_date">end</td>
+ </tr>
+ <tr>
+  <th width="10%" i18n:translate="">Start Time</th>
+  <td tal:content="view/start_time">start</td>
+  <th width="10%" i18n:translate="">Stop Time</th>
+  <td tal:content="view/stop_time">end</td>
+ </tr>
+ <tr>
+  <td colspan="4"><hr /></td>
+ </tr>
+ <tr>
+  <th width="10%" i18n:translate="">Description</th>
+  <td colspan="3" valign="top" nowrap="nowrap"
+     tal:content="view/description">Description</td>
+ </tr>
+ <tr>
+  <td colspan="4">&nbsp;</td>
+ </tr>
+</table>
+
+</metal:slot>
+
+</body>
+</html>


Property changes on: CMF/branches/2.0/CMFCalendar/browser/templates/event.pt
___________________________________________________________________
Name: svn:eol-style
   + native

Added: CMF/branches/2.0/CMFCalendar/browser/templates/event_edit.pt
===================================================================
--- CMF/branches/2.0/CMFCalendar/browser/templates/event_edit.pt	2006-04-03 17:49:47 UTC (rev 66355)
+++ CMF/branches/2.0/CMFCalendar/browser/templates/event_edit.pt	2006-04-03 20:37:37 UTC (rev 66356)
@@ -0,0 +1,178 @@
+<html metal:use-macro="context/@@standard_macros/page">
+<body>
+
+<metal:slot metal:fill-slot="body" i18n:domain="cmf_calendar">
+<h1 i18n:translate="">Edit: <tal:span
+    tal:content="view/title" i18n:name="obj_title">Title</tal:span></h1>
+
+<div class="Desktop">
+
+<form action="event_edit_form" method="post"
+      tal:attributes="action view/form_action">
+<table class="FormLayout">
+ <tr>
+  <th i18n:translate="">Event Name</th>
+  <td>
+   <input type="text"
+      name="title" maxlength="100" size="35" value="Title"
+      tal:attributes="value view/title" />
+  </td>
+  <th i18n:translate="">Contact Name</th>
+  <td>
+   <input type="text"
+      name="contact_name" maxlength="100" size="35" value="contact_name"
+      tal:attributes="value view/contact_name" />
+  </td>
+ </tr>
+ <tr>
+  <th i18n:translate="">Location</th>
+  <td>
+   <input type="text"
+      name="location" maxlength="100" size="35" value="location"
+      tal:attributes="value view/location" />
+  </td>
+  <th i18n:translate="">Contact Email</th>
+  <td>
+   <input type="text"
+      name="contact_email" maxlength="100" size="35" value="contact_email"
+      tal:attributes="value view/contact_email" />
+  </td>
+ </tr>
+ <tr>
+  <th i18n:translate="">Event type</th>
+  <td>
+   <select name="event_type:list" multiple="multiple">
+    <option tal:replace="nothing">Event Type 1</option>
+    <option tal:replace="nothing">Event Type 2</option>
+    <option tal:replace="nothing">...</option>
+    <option value="subj"
+       tal:repeat="subj python: context.portal_metadata.listAllowedSubjects(context)"
+       tal:attributes="value subj;
+                       selected python: subj in view.event_type()"
+       tal:content="subj" i18n:translate="">Event Type N</option>
+   </select>
+  </td>
+  <th i18n:translate="">Contact Phone</th>
+  <td>
+   <input type="text" name="contact_phone" maxlength="100" size="35"
+      value="contact_phone" id="cb_contact_phone"
+      tal:attributes="value view/contact_phone" />
+  </td>
+ </tr>
+ <tr>
+  <th i18n:translate="">Event URL</th>
+  <td colspan="3">
+   <input type="text" name="event_url" size="55" maxlength="100"
+      value="event_url"
+      tal:attributes="value view/event_url" />
+  </td>
+ </tr>
+ <tr>
+  <th i18n:translate="">Start Date</th>
+  <td>
+   <select name="effectiveYear">
+    <option value=""
+       tal:repeat="year context/buildYears"
+       tal:attributes="value year;
+                       selected python: year == view.effectiveYear()"
+       tal:content="year">Year</option>
+   </select>
+   &nbsp;
+   <select name="effectiveMo">
+    <option value=""
+       tal:repeat="month context/buildMonths"
+       tal:attributes="value month;
+                       selected python: month == view.effectiveMo()"
+       tal:content="month">Month</option>
+   </select>
+   &nbsp;
+   <select name="effectiveDay">
+    <option value=""
+       tal:repeat="day context/buildDays"
+       tal:attributes="value day;
+                       selected python: day == view.effectiveDay()"
+       tal:content="day">Day</option>
+   </select>
+  </td>
+  <th i18n:translate="">Stop Date</th>
+  <td>
+   <select name="expirationYear">
+    <option value=""
+       tal:repeat="year context/buildYears"
+       tal:attributes="value year;
+                       selected python: year == view.expirationYear()"
+       tal:content="year">Day</option>
+   </select>
+   &nbsp;
+   <select name="expirationMo">
+    <option value=""
+       tal:repeat="month context/buildMonths"
+       tal:attributes="value month;
+                       selected python: month == view.expirationMo()"
+       tal:content="month">Month</option>
+   </select>
+   &nbsp;
+   <select name="expirationDay">
+    <option value=""
+       tal:repeat="day context/buildDays"
+       tal:attributes="value day;
+                       selected python: day == view.expirationDay()"
+       tal:content="day">Day</option>
+   </select>
+  </td>
+ </tr>
+ <tr>
+  <th i18n:translate="">Start Time</th>
+  <td>
+   <select name="start_time">
+    <option value=""
+       tal:repeat="bt context/buildTimes"
+       tal:attributes="value bt; selected python: bt == view.start_time()"
+       tal:content="bt">start time</option>
+   </select>
+   &nbsp;
+   <input type="radio" name="startAMPM" value="am" id="cb_start_am"
+      tal:attributes="checked python: view.startAMPM() == 'am'" />
+   <label for="cb_start_am" i18n:translate="">am</label>
+   <input type="radio" name="startAMPM" value="pm" id="cb_start_pm"
+      tal:attributes="checked python: view.startAMPM() == 'pm'" />
+   <label for="cb_start_pm" i18n:translate="">pm</label>
+  </td>
+  <th i18n:translate="">Stop Time</th>
+  <td>
+   <select name="stop_time">
+   <option value=""
+      tal:repeat="bt context/buildTimes"
+      tal:attributes="value bt; selected python: bt == view.stop_time()"
+      tal:content="bt">end time</option>
+   </select>
+   &nbsp;
+   <input type="radio" name="stopAMPM" value="am" id="cb_stop_am"
+      tal:attributes="checked python: view.stopAMPM() == 'am'" />
+   <label for="cb_stop_am" i18n:translate="">am</label>
+   <input type="radio" name="stopAMPM" value="pm" id="cb_stop_pm"
+      tal:attributes="checked python: view.stopAMPM() == 'pm'" />
+   <label for="cb_stop_pm" i18n:translate="">pm</label>
+  </td>
+ </tr>
+ <tr>
+  <th i18n:translate="">Description</th>
+  <td class="TextField" colspan="3">
+   <textarea name="description:text" rows="5" cols="70" wrap="soft"
+      tal:content="view/description"></textarea>
+  </td>
+ </tr>
+ <tr>
+  <td>&nbsp;</td>
+  <td colspan="3">
+   <metal:macro metal:use-macro="context/@@form_widget/buttons" />
+  </td>
+ </tr>
+</table>
+</form>
+
+</div>
+</metal:slot>
+
+</body>
+</html>


Property changes on: CMF/branches/2.0/CMFCalendar/browser/templates/event_edit.pt
___________________________________________________________________
Name: svn:eol-style
   + native

Added: CMF/branches/2.0/CMFCalendar/configure.zcml
===================================================================
--- CMF/branches/2.0/CMFCalendar/configure.zcml	2006-04-03 17:49:47 UTC (rev 66355)
+++ CMF/branches/2.0/CMFCalendar/configure.zcml	2006-04-03 20:37:37 UTC (rev 66356)
@@ -0,0 +1,9 @@
+<configure
+    xmlns="http://namespaces.zope.org/zope">
+
+  <!-- Load CMFDefault.skin first, we use the layer named "cmf" it defines -->
+  <include package="Products.CMFDefault.skin"/>
+
+  <include package=".browser"/>
+
+</configure>


Property changes on: CMF/branches/2.0/CMFCalendar/configure.zcml
___________________________________________________________________
Name: svn:eol-style
   + native

Added: CMF/branches/2.0/CMFCalendar/interfaces/Event.py
===================================================================
--- CMF/branches/2.0/CMFCalendar/interfaces/Event.py	2006-04-03 17:49:47 UTC (rev 66355)
+++ CMF/branches/2.0/CMFCalendar/interfaces/Event.py	2006-04-03 20:37:37 UTC (rev 66356)
@@ -0,0 +1,21 @@
+##############################################################################
+#
+# Copyright (c) 2006 Zope Corporation and Contributors. All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+""" Event content type interfaces.
+
+$Id$
+"""
+
+# BBB: module will be removed in CMF 2.2
+#      zope2 interfaces created on runtime:
+#      - IEvent      
+#      - IMutableEvent


Property changes on: CMF/branches/2.0/CMFCalendar/interfaces/Event.py
___________________________________________________________________
Name: svn:keywords
   + Id
Name: svn:eol-style
   + native

Added: CMF/branches/2.0/CMFCalendar/interfaces/__init__.py
===================================================================
--- CMF/branches/2.0/CMFCalendar/interfaces/__init__.py	2006-04-03 17:49:47 UTC (rev 66355)
+++ CMF/branches/2.0/CMFCalendar/interfaces/__init__.py	2006-04-03 20:37:37 UTC (rev 66356)
@@ -0,0 +1,31 @@
+##############################################################################
+#
+# Copyright (c) 2006 Zope Corporation and Contributors. All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+""" CMFCalendar.interfaces package.
+
+$Id$
+"""
+
+from _content import *
+from _tools import *
+
+# BBB: will be removed in CMF 2.2
+#      create zope2 interfaces
+from Interface.bridge import createZope3Bridge
+import Event
+import portal_calendar
+
+createZope3Bridge(IEvent, Event, 'IEvent')
+createZope3Bridge(IMutableEvent, Event, 'IMutableEvent')
+createZope3Bridge(ICalendarTool, portal_calendar, 'portal_calendar')
+
+del createZope3Bridge


Property changes on: CMF/branches/2.0/CMFCalendar/interfaces/__init__.py
___________________________________________________________________
Name: svn:keywords
   + Id
Name: svn:eol-style
   + native

Added: CMF/branches/2.0/CMFCalendar/interfaces/_content.py
===================================================================
--- CMF/branches/2.0/CMFCalendar/interfaces/_content.py	2006-04-03 17:49:47 UTC (rev 66355)
+++ CMF/branches/2.0/CMFCalendar/interfaces/_content.py	2006-04-03 20:37:37 UTC (rev 66356)
@@ -0,0 +1,103 @@
+##############################################################################
+#
+# Copyright (c) 2005 Zope Corporation and Contributors. All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+""" CMFCalendar content interfaces.
+
+$Id$
+"""
+
+from zope.interface import Interface
+from zope.interface import Attribute
+
+
+class IEvent(Interface):
+
+    """ IEvent models an event.
+    """
+
+    def getEndStrings():
+        """ Returns a mapping with string representations for the end time
+
+        o keys are 'day', 'month' and 'year'
+        """
+
+    def getStartStrings():
+        """ Returns a mapping with string representations for the start time
+
+        o keys are 'day', 'month' and 'year'
+        """
+
+    def start():
+        """ Return our start time as a DateTime object
+        """
+
+    def end():
+        """ Return our end time as a DateTime object
+        """
+
+    def getStartTimeString():
+        """ Return our start time as a string.
+        """
+
+    def getStopTimeString():
+        """ Return our stop time as a string.
+        """
+
+    def getMetadataHeaders():
+        """ Return metadata attributes in RFC-822-style header spec.
+        """
+
+class IMutableEvent(IEvent):
+
+    """ Updatable form of IEvent.
+    """
+    def edit( title=None
+            , description=None
+            , eventType=None
+            , effectiveDay=None
+            , effectiveMo=None
+            , effectiveYear=None
+            , expirationDay=None
+            , expirationMo=None
+            , expirationYear=None
+            , start_time=None
+            , startAMPM=None
+            , stop_time=None
+            , stopAMPM=None
+            , location=None
+            , contact_name=None
+            , contact_email=None
+            , contact_phone=None
+            , event_url=None
+            ):
+        """ Update the event.
+
+        o Only arguments that have a value are manipulated.
+        """  
+
+    def setStartDate(start):
+        """ Setting the event start date when the event is scheduled to begin.
+        """
+
+    def setEndDate(end):
+        """ Setting the event end date, when the event ends.
+        """
+
+    def setMetadata(headers):
+        """ Set an Event's metadata
+
+        o headers is a mapping containing keys corresponding to
+        Dublin Core metadata fields
+        o Only those attributes that are passed in with the mapping are
+        manipulated
+        """
+


Property changes on: CMF/branches/2.0/CMFCalendar/interfaces/_content.py
___________________________________________________________________
Name: svn:keywords
   + Id
Name: svn:eol-style
   + native

Added: CMF/branches/2.0/CMFCalendar/interfaces/_tools.py
===================================================================
--- CMF/branches/2.0/CMFCalendar/interfaces/_tools.py	2006-04-03 17:49:47 UTC (rev 66355)
+++ CMF/branches/2.0/CMFCalendar/interfaces/_tools.py	2006-04-03 20:37:37 UTC (rev 66356)
@@ -0,0 +1,25 @@
+##############################################################################
+#
+# Copyright (c) 2006 Zope Corporation and Contributors. All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+""" CMFColendar tool interfaces.
+
+$Id$
+"""
+
+from zope.interface import Interface
+from zope.interface import Attribute
+
+
+class ICalendarTool(Interface):
+
+    """ Declare product-specific APIs for the CMFCalendar tools.
+    """


Property changes on: CMF/branches/2.0/CMFCalendar/interfaces/_tools.py
___________________________________________________________________
Name: svn:keywords
   + Id
Name: svn:eol-style
   + native

Added: CMF/branches/2.0/CMFCalendar/interfaces/portal_calendar.py
===================================================================
--- CMF/branches/2.0/CMFCalendar/interfaces/portal_calendar.py	2006-04-03 17:49:47 UTC (rev 66355)
+++ CMF/branches/2.0/CMFCalendar/interfaces/portal_calendar.py	2006-04-03 20:37:37 UTC (rev 66356)
@@ -0,0 +1,20 @@
+##############################################################################
+#
+# Copyright (c) 2006 Zope Corporation and Contributors. All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+""" Calendar tool interface
+
+$Id$
+"""
+
+# BBB: module will be removed in CMF 2.2
+#      zope2 interfaces created on runtime:
+#      - portal_calendar


Property changes on: CMF/branches/2.0/CMFCalendar/interfaces/portal_calendar.py
___________________________________________________________________
Name: svn:keywords
   + Id
Name: svn:eol-style
   + native

Added: CMF/branches/2.0/CMFCalendar/profiles/views_support/types/Event.xml
===================================================================
--- CMF/branches/2.0/CMFCalendar/profiles/views_support/types/Event.xml	2006-04-03 17:49:47 UTC (rev 66355)
+++ CMF/branches/2.0/CMFCalendar/profiles/views_support/types/Event.xml	2006-04-03 20:37:37 UTC (rev 66356)
@@ -0,0 +1,7 @@
+<?xml version="1.0"?>
+<object name="Event">
+ <alias from="(Default)" to="@@view.html"/>
+ <alias from="event_edit_form" to="@@edit.html"/>
+ <alias from="event_view" to="@@view.html"/>
+ <alias from="view" to="@@view.html"/>
+</object>


Property changes on: CMF/branches/2.0/CMFCalendar/profiles/views_support/types/Event.xml
___________________________________________________________________
Name: svn:eol-style
   + native

Modified: CMF/branches/2.0/CMFCalendar/tests/test_Calendar.py
===================================================================
--- CMF/branches/2.0/CMFCalendar/tests/test_Calendar.py	2006-04-03 17:49:47 UTC (rev 66355)
+++ CMF/branches/2.0/CMFCalendar/tests/test_Calendar.py	2006-04-03 20:37:37 UTC (rev 66356)
@@ -40,6 +40,21 @@
 
         return CalendarTool(*args, **kw)
 
+    def test_z2interfaces(self):
+        from Interface.Verify import verifyClass
+        from Products.CMFCalendar.interfaces.portal_calendar \
+                import portal_calendar as ICalendarTool
+        from Products.CMFCalendar.CalendarTool import CalendarTool
+
+        verifyClass(ICalendarTool, CalendarTool)
+
+    def test_z3interfaces(self):
+        from zope.interface.verify import verifyClass
+        from Products.CMFCalendar.interfaces import ICalendarTool
+        from Products.CMFCalendar.CalendarTool import CalendarTool
+
+        verifyClass(ICalendarTool, CalendarTool)
+
     def test_new(self):
         ctool = self._makeOne()
         self.assertEqual( ctool.getId(), 'portal_calendar' )
@@ -113,20 +128,34 @@
             params=(obj, Site.REQUEST)
         obj(*params)
 
-    def test_sessions(self):
+    def test_sessions_skinsview(self):
         self.Tool.edit_configuration(show_types=['Event'], use_session="True")
 
         self._testURL('/CalendarTest/calendarBox', ())
 
         self.failUnless(self.app.REQUEST.SESSION.get('calendar_year',None))
 
-    def test_noSessions(self):
+    def test_sessions_fiveview(self):
+        self.Tool.edit_configuration(show_types=['Event'], use_session="True")
+
+        self._testURL('/CalendarTest/@@calendar_widget', ())
+
+        self.failUnless(self.app.REQUEST.SESSION.get('calendar_year',None))
+
+    def test_noSessions_skinsview(self):
         self.Tool.edit_configuration(show_types=['Event'], use_session="")
 
         self._testURL('/CalendarTest/calendarBox', ())
 
         self.failIf(self.app.REQUEST.SESSION.get('calendar_year',None))
 
+    def test_noSessions_fiveview(self):
+        self.Tool.edit_configuration(show_types=['Event'], use_session="")
+
+        self._testURL('/CalendarTest/@@calendar_widget', ())
+
+        self.failIf(self.app.REQUEST.SESSION.get('calendar_year',None))
+
     def test_simpleCalendarRendering(self):
         data = [
                 [

Modified: CMF/branches/2.0/CMFCalendar/tests/test_Event.py
===================================================================
--- CMF/branches/2.0/CMFCalendar/tests/test_Event.py	2006-04-03 17:49:47 UTC (rev 66355)
+++ CMF/branches/2.0/CMFCalendar/tests/test_Event.py	2006-04-03 20:37:37 UTC (rev 66356)
@@ -43,12 +43,16 @@
         from Products.CMFCore.interfaces.Dynamic \
                 import DynamicType as IDynamicType
         from Products.CMFCalendar.Event import Event
+        from Products.CMFCalendar.interfaces.Event import IEvent
+        from Products.CMFCalendar.interfaces.Event import IMutableEvent
 
         verifyClass(ICatalogableDublinCore, Event)
         verifyClass(IContentish, Event)
         verifyClass(IDublinCore, Event)
         verifyClass(IDynamicType, Event)
         verifyClass(IMutableDublinCore, Event)
+        verifyClass(IEvent, Event)
+        verifyClass(IMutableEvent, Event)
 
     def test_z3interfaces(self):
         from zope.interface.verify import verifyClass
@@ -58,12 +62,16 @@
         from Products.CMFCore.interfaces import IDublinCore
         from Products.CMFCore.interfaces import IDynamicType
         from Products.CMFCore.interfaces import IMutableDublinCore
+        from Products.CMFCalendar.interfaces import IEvent
+        from Products.CMFCalendar.interfaces import IMutableEvent
 
         verifyClass(ICatalogableDublinCore, Event)
         verifyClass(IContentish, Event)
         verifyClass(IDublinCore, Event)
         verifyClass(IDynamicType, Event)
         verifyClass(IMutableDublinCore, Event)
+        verifyClass(IEvent, Event)
+        verifyClass(IMutableEvent, Event)
 
     def test_new(self):
         event = self._makeOne('test')

Modified: CMF/branches/2.0/CMFDefault/browser/utils.py
===================================================================
--- CMF/branches/2.0/CMFDefault/browser/utils.py	2006-04-03 17:49:47 UTC (rev 66355)
+++ CMF/branches/2.0/CMFDefault/browser/utils.py	2006-04-03 20:37:37 UTC (rev 66356)
@@ -15,10 +15,14 @@
 $Id$
 """
 
+from AccessControl.SecurityInfo import ClassSecurityInfo
+from DateTime.DateTime import DateTime
+from Globals import InitializeClass
 from Products.PythonScripts.standard import thousands_commas
 from ZTUtils import Batch
 from ZTUtils import make_query
 
+from Products.CMFCore.permissions import View
 from Products.CMFCore.utils import getToolByName
 from Products.CMFDefault.utils import html_marshal
 from Products.CMFDefault.utils import Message as _
@@ -44,6 +48,14 @@
 
 class ViewBase:
 
+    # The following allows to traverse the view/class and reach
+    # macros defined in page templates, e.g. in a use-macro.
+    security = ClassSecurityInfo()
+    def _macros(self):
+        return self.index.macros
+    security.declareProtected(View, 'macros')
+    macros = property(_macros, None, None)
+
     # helpers
 
     @memoize
@@ -82,6 +94,96 @@
         return self.context.Description()
 
 
+    # Calendar widgets helpers
+    # When CMFCalendar is enabled, the month calendar widget shows up
+    # everywhere - that's why these methods are currently here.
+
+    @memoize
+    @decode
+    def getMonthAndYear(self):
+        """ Retrieve month/year tuple
+        """
+        current = DateTime()
+        
+        year = None
+        month = None
+        use_session = self._getTool('portal_calendar').getUseSession()
+        
+        # First priority goes to the data in the request
+        year  = self.request.get('year',  None)
+        month = self.request.get('month', None)
+        session = None
+        
+        # Next get the data from the SESSION
+        if use_session == "True":
+            session = self.request.get('SESSION', None)
+            if session:
+                if not year:   year  = session.get('calendar_year',  None)
+                if not month:  month = session.get('calendar_month', None)
+        
+        # Last resort to Today
+        if not year:   year  = current.year()
+        if not month:  month = current.month()
+        
+        # Then store the results in the session for next time
+        if session:
+            session.set('calendar_year',  year)
+            session.set('calendar_month', month)
+        
+        # Finally return the results
+        return (year, month) 
+
+    @memoize
+    @decode
+    def getNextMonthLink(self, base_url, month, year):
+        """ Return URL for the next month link
+        """
+        calendar_tool = self._getTool('portal_calendar')
+        nextMonthTime = calendar_tool.getNextMonth(month, year)
+        
+        x = '%s?month:int=%d&year:int=%d' % ( base_url
+                                            , nextMonthTime.month()
+                                            , nextMonthTime.year()
+                                            )
+        
+        return x
+
+    @memoize
+    @decode
+    def getPreviousMonthLink(self, base_url, month, year):
+        """ Return URL for the previous month link
+        """
+        calendar_tool = self._getTool('portal_calendar')
+        prevMonthTime = calendar_tool.getPreviousMonth(month, year)
+        
+        x = '%s?month:int=%d&year:int=%d' % ( base_url
+                                            , prevMonthTime.month()
+                                            , prevMonthTime.year()
+                                            )
+        
+        return x
+
+    @memoize
+    def getDaysClass(self, day, month, year, event=None):
+        """ Determine the CSS class to use for the given day
+        """
+        current = DateTime()
+        
+        if ( current.year()==year and 
+             current.month()==month and 
+             current.day()==int(day) ):
+            if event:
+                return "todayevent"
+            else:
+                return "todaynoevent"
+        
+        if event:
+            return "event"
+        else:
+            return ""
+
+InitializeClass(ViewBase)
+
 class FormViewBase(ViewBase):
 
     # helpers



More information about the Checkins mailing list