Author: rmarianski
Date: 2007-11-24 01:21:14 -0500 (Sat, 24 Nov 2007)
New Revision: 11238

Modified:
   
opencore/branches/viewlet_menuitems/opencore/browser/topnav/topnav_menuitem.py
   
opencore/branches/viewlet_menuitems/opencore/listen/browser/topnav_menuitem.py
   
opencore/branches/viewlet_menuitems/opencore/tasktracker/browser/topnav_menuitem.py
   
opencore/branches/viewlet_menuitems/opencore/wordpress/browser/topnav_menuitem.py
Log:
create mixins to share more code among various viewlets


Modified: 
opencore/branches/viewlet_menuitems/opencore/browser/topnav/topnav_menuitem.py
===================================================================
--- 
opencore/branches/viewlet_menuitems/opencore/browser/topnav/topnav_menuitem.py  
    2007-11-23 20:47:52 UTC (rev 11237)
+++ 
opencore/branches/viewlet_menuitems/opencore/browser/topnav/topnav_menuitem.py  
    2007-11-24 06:21:14 UTC (rev 11238)
@@ -1,4 +1,3 @@
-from zope.viewlet.viewlet import ViewletBase
 from Products.Five.browser.pagetemplatefile import ZopeTwoPageTemplateFile
 from Products.CMFCore.utils import getToolByName
 from opencore.interfaces import IMemberFolder
@@ -6,17 +5,47 @@
 from opencore.interfaces import IOpenPage
 from opencore.interfaces.adding import IAddProject
 from opencore.interfaces.adding import IAmAPeopleFolder
+from zope.interface import Interface
+from zope.viewlet.viewlet import ViewletBase
 
 class BaseMenuItem(ViewletBase):
     """Base class for topnav menu items."""
 
+    # these 3 viewlet attributes are what the template renders
     name = u''
     url = '#'
     css_class = None
 
     def update(self):
-        """subclasses can control setting state here"""
+        # check the context here to see if viewlet should be rendered
+        if not self.context_matches():
+            return self.no_render()
 
+        self.url = self.get_url()
+        if self.is_selected():
+            self.set_css_class()
+
+    def set_state(self):
+        """subclasses should set internal variables here for use later"""
+
+    def context_matches(self):
+        """subclasses should check here if they should be rendered"""
+
+    def get_url(self):
+        """subclasses should return the url attribute here
+           this represents the menu item's link"""
+
+    def is_selected(self):
+        """subclasses should check if the menu item should be rendered
+           selected"""
+
+    def set_css_class(self):
+        self.css_class = 'oc-topnav-selected'
+
+    def no_render(self):
+        # replace render method to return an empty string
+        self.render = lambda *args:''
+
     def __cmp__(self, rhs):
         #XXX this ideally would have happened
         # with a custom sorting viewlet manager
@@ -31,154 +60,155 @@
 
     render = ZopeTwoPageTemplateFile('topnav_menuitem.pt')
 
+# Here are some mixins for certain contexts that help reduce code
+
+class StartsWithMixin(object):
+    def is_selected(self):
+        return self.request.ACTUAL_URL.startswith(self.url)
+
+class ContextProvidedMixin(StartsWithMixin):
+    """Menu items must be in a particular context"""
+    should_be_provided = Interface
+    item_url = '#'
+
+    def set_state(self):
+        self.item = self._item_providing(self.should_be_provided)
+
+    def context_matches(self):
+        return self._item_providing(self.should_be_provided) is not None
+
+    def get_url(self):
+        item = self._item_providing(self.should_be_provided)
+        return '%s/%s' % (item.absolute_url(), self.item_url)
+
+class BaseProjectMenuItem(ContextProvidedMixin, BaseMenuItem):
+    should_be_provided = IProject
+
+class BaseMemberMenuItem(ContextProvidedMixin, BaseMenuItem):
+    should_be_provided = IMemberFolder
+
+class PortalContextMenuItem(BaseMenuItem):
+    folder_context = None
+
+    def context_matches(self):
+        # matching is handled by configuration here
+        return True
+
+    def get_url(self):
+        portal = getToolByName(self.context, 'portal_url').getPortalObject()
+        return getattr(portal, self.folder_context).absolute_url()
+
 # Member menu items
-class MemberWikiMenuItem(BaseMenuItem):
+class MemberWikiMenuItem(BaseMemberMenuItem):
     name = u'Wiki'
 
-    def update(self):
-        mem = self._item_providing(IMemberFolder)
-        if mem is None:
-            self.render = lambda *a:''
-            return
-        self.url = '%s/%s-home' % (mem.absolute_url(), mem.getId())
-        if IOpenPage.providedBy(self.context):
-            self.css_class = 'oc-topnav-selected'
+    def get_url(self):
+        mem = self._item_providing(self.should_be_provided)
+        return '%s/%s-home' % (mem.absolute_url(), mem.getId())
 
-class MemberMenuItem(BaseMenuItem):
-    """Base class to allow easy creation of member menu items"""
-    item_url = '#'
+    def is_selected(self):
+        return IOpenPage.providedBy(self.context)
 
-    def update(self):
-        mem = self._item_providing(IMemberFolder)
-        if mem is None:
-            self.render = lambda *a:''
-            return
-        self.url = '%s/%s' % (mem.absolute_url(), self.item_url)
-        if self.request.ACTUAL_URL.startswith(self.url):
-            self.css_class = 'oc-topnav-selected'
-
-class ProfileMenuItem(MemberMenuItem):
+class ProfileMenuItem(BaseMemberMenuItem):
     name = u'Profile'
     item_url = 'profile'
 
-class AccountMenuItem(MemberMenuItem):
+class AccountMenuItem(BaseMemberMenuItem):
     name = u'Account'
     item_url = 'account'
 
 # Project menu items
-class ProjectWikiMenuItem(BaseMenuItem):
+class ProjectWikiMenuItem(BaseProjectMenuItem):
     name = u'Wiki'
 
-    def update(self):
-        proj = self._item_providing(IProject)
-        if proj is None:
-            self.render = lambda *a:''
-            return
-        self.url = '%s/project-home' % proj.absolute_url()
-        if IOpenPage.providedBy(self.context):
-            self.css_class = 'oc-topnav-selected'
+    def get_url(self):
+        item = self._item_providing(self.should_be_provided)
+        return '%s/project-home' % item.absolute_url()
 
-class ProjectMenuItem(BaseMenuItem):
-    """Base class to allow easy creation of project mneu items"""
-    item_url = '#'
+    def is_selected(self):
+        return IOpenPage.providedBy(self.context)
 
-    def update(self):
-        proj = self._item_providing(IProject)
-        if proj is None:
-            self.render = lambda *a:''
-            return
-        self.url = '%s/%s' % (proj.absolute_url(), self.item_url)
-        if self.request.ACTUAL_URL.startswith(self.url):
-            self.css_class = 'oc-topnav-selected'
-
-class TeamMenuItem(ProjectMenuItem):
+class TeamMenuItem(BaseProjectMenuItem):
     name = u'Team'
     item_url = 'team'
 
-class ManageTeamMenuItem(ProjectMenuItem):
+class ManageTeamMenuItem(BaseProjectMenuItem):
     name = u'Manage Team'
     item_url = 'manage-team'
 
-class ContentsMenuItem(ProjectMenuItem):
+class ContentsMenuItem(BaseProjectMenuItem):
     name = u'Contents'
     item_url = 'contents'
 
-class PreferencesMenuItem(ProjectMenuItem):
+class PreferencesMenuItem(BaseProjectMenuItem):
     name = u'Preferences'
     item_url = 'preferences'
 
-class JoinMenuItem(BaseMenuItem):
+class JoinMenuItem(BaseProjectMenuItem):
     name = u'Join Project'
+    item_url = 'request-membership'
 
-    def update(self):
+    def context_matches(self):
+        if not super(JoinMenuItem, self).context_matches():
+            return False
         proj = self._item_providing(IProject)
-        if proj is None:
-            self.render = lambda *a:''
-            return
         mstool = getToolByName(proj, 'portal_membership')
         if not mstool.isAnonymousUser():
             mem = mstool.getAuthenticatedMember()
             team = proj.getTeams()[0]
             filter_states = tuple(team.getActiveStates()) + ('pending',)
             if mem.getId() in team.getMemberIdsByStates(filter_states):
-                self.render = lambda *a:''
-                return
-        self.url = '%s/%s' % (proj.absolute_url(), 'request-membership')
+                return self.no_render()
+        return True
+
+    def is_selected(self):
+        return True
+
+    def set_css_class(self):
         if self.request.ACTUAL_URL == self.url:
             self.css_class = 'oc-topnav-selected'
         else:
             self.css_class = 'oc-topnav-join'
 
 # Search menu items
-class PeopleMenuItem(BaseMenuItem):
+class PeopleMenuItem(PortalContextMenuItem):
     name = u'People'
+    folder_context = 'people'
 
-    def update(self):
-        portal = getToolByName(self.context, 'portal_url').getPortalObject()
-        self.url = portal.people.absolute_url()
-        if IAmAPeopleFolder.providedBy(self.context):
-            self.css_class = 'oc-topnav-selected'
+    def is_selected(self):
+        return IAmAPeopleFolder.providedBy(self.context)
 
-class ProjectsMenuItem(BaseMenuItem):
+class ProjectsMenuItem(PortalContextMenuItem):
     name = u'Projects'
+    folder_context = 'projects'
 
-    def update(self):
-        portal = getToolByName(self.context, 'portal_url').getPortalObject()
-        self.url = portal.projects.absolute_url()
-        if (IAddProject.providedBy(self.context)
-            and not self.request.ACTUAL_URL.endswith('/create')):
-            self.css_class = 'oc-topnav-selected'
+    def is_selected(self):
+        return (IAddProject.providedBy(self.context)
+                and not self.request.ACTUAL_URL.endswith('/create'))
 
-class StartProjectMenuItem(BaseMenuItem):
+class StartProjectMenuItem(StartsWithMixin, BaseMenuItem):
     name = u'Start A Project'
 
-    def update(self):
+    def context_matches(self):
+        return True
+
+    def get_url(self):
         portal = getToolByName(self.context, 'portal_url').getPortalObject()
-        self.url = '%s/%s' % (portal.projects.absolute_url(), 'create')
-        if self.request.ACTUAL_URL == self.url:
-            self.css_class = 'oc-topnav-selected'
+        return '%s/%s' % (portal.projects.absolute_url(), 'create')
 
-
 # Featurelets need to only provide
 # name
 # supp_must_provide - installed marker interface
-# flet_url - portion of url after project url
-class BaseFeatureletMenuItem(BaseMenuItem):
+# item_url - portion of url after project url
+class BaseFeatureletMenuItem(BaseProjectMenuItem):
     """Base class to allow easy creation of featurelet menu items"""
 
-    supporter = IProject
-    supp_must_provide = None
-    flet_url = '#'
+    supp_must_provide = Interface
 
-    def update(self):
-        proj = self._item_providing(self.supporter)
-        if proj is None:
-            self.render = lambda *a:''
-            return
+    def context_matches(self):
+        if not super(BaseFeatureletMenuItem, self).context_matches():
+            return False
+        proj = self._item_providing(IProject)
         if not self.supp_must_provide.providedBy(proj):
-            self.render = lambda *a:''
-            return
-
-        self.url = '%s/%s' % (proj.absolute_url(), self.flet_url)
-        if self.request.ACTUAL_URL.startswith(self.url):
-            self.css_class = 'oc-topnav-selected'
+            return self.no_render()
+        return True

Modified: 
opencore/branches/viewlet_menuitems/opencore/listen/browser/topnav_menuitem.py
===================================================================
--- 
opencore/branches/viewlet_menuitems/opencore/listen/browser/topnav_menuitem.py  
    2007-11-23 20:47:52 UTC (rev 11237)
+++ 
opencore/branches/viewlet_menuitems/opencore/listen/browser/topnav_menuitem.py  
    2007-11-24 06:21:14 UTC (rev 11238)
@@ -4,4 +4,4 @@
 class ListenMenuItem(BaseFeatureletMenuItem):
     name = u'Mailing Lists'
     supp_must_provide = IListenFeatureletInstalled
-    flet_url = 'lists'
+    item_url = 'lists'

Modified: 
opencore/branches/viewlet_menuitems/opencore/tasktracker/browser/topnav_menuitem.py
===================================================================
--- 
opencore/branches/viewlet_menuitems/opencore/tasktracker/browser/topnav_menuitem.py
 2007-11-23 20:47:52 UTC (rev 11237)
+++ 
opencore/branches/viewlet_menuitems/opencore/tasktracker/browser/topnav_menuitem.py
 2007-11-24 06:21:14 UTC (rev 11238)
@@ -4,4 +4,4 @@
 class TasktrackerMenuItem(BaseFeatureletMenuItem):
     name = u'Task tracker'
     supp_must_provide = ITaskTrackerFeatureletInstalled
-    flet_url = 'tasks'
+    item_url = 'tasks'

Modified: 
opencore/branches/viewlet_menuitems/opencore/wordpress/browser/topnav_menuitem.py
===================================================================
--- 
opencore/branches/viewlet_menuitems/opencore/wordpress/browser/topnav_menuitem.py
   2007-11-23 20:47:52 UTC (rev 11237)
+++ 
opencore/branches/viewlet_menuitems/opencore/wordpress/browser/topnav_menuitem.py
   2007-11-24 06:21:14 UTC (rev 11238)
@@ -4,4 +4,4 @@
 class WordpressMenuItem(BaseFeatureletMenuItem):
     name = u'Blog'
     supp_must_provide = IWordPressFeatureletInstalled
-    flet_url = 'blog'
+    item_url = 'blog'



--
Archive: 
http://www.openplans.org/projects/opencore/lists/openplans-svn/archive/2007/11/1195885288457
To unsubscribe send an email with subject unsubscribe to [EMAIL PROTECTED]  
Please contact [EMAIL PROTECTED] for questions.

Reply via email to