[Checkins] SVN: z3c.jsontree/trunk/ - implemented ITreeItems adapter which is responsible for list all items listed

Roger Ineichen roger at projekt01.ch
Fri Apr 11 06:32:39 EDT 2008


Log message for revision 85232:
  - implemented ITreeItems adapter which is responsible for list all items listed
    in tree
  - Added tests for the new feature
  - Update CHANGES.txt
  
  Note the API changed, we use a ITreeItems adapter which is now 
  responsible for list the childs for it's adapted context 

Changed:
  U   z3c.jsontree/trunk/CHANGES.txt
  U   z3c.jsontree/trunk/src/z3c/jsontree/base.py
  A   z3c.jsontree/trunk/src/z3c/jsontree/browser/tests/output/tree_3.txt
  U   z3c.jsontree/trunk/src/z3c/jsontree/browser/tests/test_view.py
  U   z3c.jsontree/trunk/src/z3c/jsontree/browser/tree.py
  U   z3c.jsontree/trunk/src/z3c/jsontree/browser/z3c.jsontree.css
  U   z3c.jsontree/trunk/src/z3c/jsontree/configure.zcml
  U   z3c.jsontree/trunk/src/z3c/jsontree/interfaces.py
  U   z3c.jsontree/trunk/src/z3c/jsontree/jsonrpc.py
  A   z3c.jsontree/trunk/src/z3c/jsontree/jsonrpc.zcml
  A   z3c.jsontree/trunk/src/z3c/jsontree/subitem.py
  U   z3c.jsontree/trunk/src/z3c/jsontree/tests.py

-=-
Modified: z3c.jsontree/trunk/CHANGES.txt
===================================================================
--- z3c.jsontree/trunk/CHANGES.txt	2008-04-11 10:09:06 UTC (rev 85231)
+++ z3c.jsontree/trunk/CHANGES.txt	2008-04-11 10:32:39 UTC (rev 85232)
@@ -5,4 +5,7 @@
 Version 0.5.0 (unreleased)
 -------------------------
 
+- implemented ITreeItems adapter which is responsible for list all items listed
+  in tree
+
 - Initial Release

Modified: z3c.jsontree/trunk/src/z3c/jsontree/base.py
===================================================================
--- z3c.jsontree/trunk/src/z3c/jsontree/base.py	2008-04-11 10:09:06 UTC (rev 85231)
+++ z3c.jsontree/trunk/src/z3c/jsontree/base.py	2008-04-11 10:32:39 UTC (rev 85232)
@@ -20,12 +20,9 @@
 import zope.interface
 import zope.component
 from zope.traversing import api
-from zope.security.interfaces import Unauthorized
-from zope.security.interfaces import Forbidden
 from zope.traversing.browser import absoluteURL
 from zope.traversing.namespace import getResource
 from zope.contentprovider.interfaces import IContentProvider
-from zope.app.container.interfaces import IReadContainer
 from zope.app.component import hooks
 
 from z3c.template.template import getPageTemplate
@@ -42,10 +39,54 @@
 from z3c.jsontree.interfaces import STATE_EXPANDED
 from z3c.jsontree.interfaces import STATE_COLLAPSED
 from z3c.jsontree.interfaces import STATE_STATIC
+from z3c.jsontree import subitem
 from z3c.jsontree import util
 
 
-class TreeBase(object):
+class IdGenerator(object):
+    """This mixin class generates Object Ids based on the the objects path.
+
+    Note: The objects must be traversable by it's path. You can implement a 
+    a custom path traverse concept in the getObjectByPath it you need to use
+    another traverse concept.
+
+    This ids must conform the w3c recommendation described in:
+    http://www.w3.org/TR/1999/REC-html401-19991224/types.html#type-name
+    """
+
+    def getId(self, item):
+        """Returns the DOM id for a given object.
+
+        Note: we encode the upper case letters because the Dom element id are 
+        not case sensitive in HTML. We prefix each upper case letter with ':'.
+        """
+        path = api.getPath(item)
+        newPath = u''
+        for letter in path:
+            if letter in string.uppercase:
+                newPath += ':' + letter
+            else:
+                newPath += letter
+
+        # we use a dot as a root representation, this avoids to get the same id
+        # for the ul and the first li tag
+        if newPath == '/':
+            newPath = '.'
+        # add additinal dot which separates the tree id and the path, is used
+        # for get the tree id out of the string in the javascript using
+        # ids = id.split("."); treeId = ids[0];
+        id = self.z3cJSONTreeId +'.'+ newPath
+        # convert '/' path separator to marker '::', because the path '/'' is  
+        # not allowed as DOM id. See also:
+        # http://www.w3.org/TR/1999/REC-html401-19991224/types.html#type-name
+        return id.replace('/', '::')
+
+    def id(self):
+        """Returns the DOM id for a given context."""
+        return self.getId(self.context)
+
+
+class TreeBase(subitem.SubItemMixin):
     """Tree iterator base implementation."""
 
     root = None
@@ -78,20 +119,6 @@
         self.context = context
         self.request = request
 
-    def getSubItems(self, item):
-        items = []
-        append = items.append
-        if IReadContainer.providedBy(item):
-            keys = list(item.keys())
-        else:
-            keys = []
-        for name in keys:
-            # Only include items we can traverse to
-            subItem = api.traverse(item, name, None)
-            if subItem is not None:
-                append(subItem)
-        return items
-
     def getIconURL(self, item, request, name='icon'):
         return util.getIconURL(item, request, name=name)
 
@@ -99,16 +126,6 @@
         root = self.getRoot()
         return util.getParentsFromContextToObject(self.context, root)
 
-    def hasSubItems(self, item):
-        res = False
-        if IReadContainer.providedBy(item):
-            try:
-                if len(item) > 0:
-                    res = True
-            except(Unauthorized, Forbidden):
-                pass
-        return res
-
     def update(self):
         """Returns HTML code for representing a <ul> tag tree with the 
         siblings and parents of an object.
@@ -120,6 +137,10 @@
         If we access the tree via a virtual host, the root is adjusted to
         the right root object.
 
+        The childTags get used in every implementation of this package. The
+        items in the childTags can get rendered with the python renderer which
+        uses inline code or with the template based renderer which is probably 
+        slower then the python renderer becaue of it's tal usage.
         """
         childTags = None
         stackItem = self.context
@@ -129,16 +150,14 @@
             tagList = []
             append = tagList.append
 
-            for subItem in self.getSubItems(item):
-                if self.hasSubItems(subItem):
-
+            for name, subItem, hasSubItems in self.getSubItems(item):
+                if hasSubItems:
                     if subItem == stackItem:
-                        append(self.renderUL(subItem, childTags))
+                        append(self.renderUL(name, subItem, childTags))
                     else:
-                        append(self.renderUL(subItem))
-
+                        append(self.renderUL(name, subItem))
                 else:
-                    append(self.renderLI(subItem))
+                    append(self.renderLI(name, subItem))
 
             childTags = ' '.join(tagList)
             stackItem = item
@@ -146,6 +165,88 @@
         self.childTags = childTags
 
 
+class ProviderBase(object):
+    """Base class for tag element provider."""
+
+    template = getPageTemplate()
+
+    root = None
+    state = None
+    name = None
+    childTags = None
+    iconName = 'icon'
+
+    z3cJSONTreeId = JSON_TREE_ID
+    z3cJSONTreeName = JSON_TREE_ID
+    z3cJSONTreeClass = JSON_TREE_ID
+
+    viewName = JSON_TREE_VIEW_NAME
+
+    # LI tag CSS names
+    collapsedCSSName = JSON_LI_CSS_COLLAPSED
+    expandedCSSName = JSON_LI_CSS_EXPANDED
+    staticCSSName = JSON_LI_CSS_STATIC
+
+    # toggle icon names
+    collapsedIconName = JSON_TOGGLE_ICON_COLLAPSED
+    expandedIconNamen = JSON_TOGGLE_ICON_EXPANDED
+    staticIconName = JSON_TOGGLE_ICON_STATIC
+
+    def __init__(self, context, request, view):
+        self.context = context
+        self.request = request
+        self.view = view
+
+    @property
+    def className(self):
+        if self.state == STATE_COLLAPSED:
+            return self.collapsedCSSName
+        elif self.state == STATE_EXPANDED:
+            return self.expandedCSSName
+        else:
+            return self.staticCSSName
+
+    @property
+    def toggleIcon(self):
+        """Returns a toggle icon including settings for json url."""
+        if self.state == STATE_COLLAPSED:
+            iconName = self.collapsedIconName
+        elif self.state == STATE_EXPANDED:
+            iconName = self.expandedIconNamen
+        else:
+            iconName = self.staticIconName
+        icon = zope.component.getMultiAdapter((self.context, self.request), 
+            name=iconName)
+        resource = getResource(icon.context, icon.rname, self.request)
+        src = resource()
+        longDescURL = absoluteURL(self.context, self.request)
+        return ('<img src="%s" alt="toggle icon" width="%s" height="%s" ' 
+                'border="0" longDesc="%s" />' % (src, icon.width, 
+                   icon.height, longDescURL))
+
+    def icon(self):
+        """Returns a toggle icon including settings for json url."""
+        icon = zope.component.queryMultiAdapter((self.context, self.request), 
+            name=self.iconName)
+        if icon is not None:
+            resource = getResource(icon.context, icon.rname, self.request)
+            src = resource()
+            longDescURL = absoluteURL(self.context, self.request)
+            return ('<img src="%s" alt="toggle icon" width="%s" height="%s" ' 
+                    'border="0" />' % (src, icon.width, icon.height))
+        return u''
+
+    @property
+    def url(self):
+        return absoluteURL(self.context, self.request) +'/'+ self.viewName
+
+    def update(self):
+        pass
+
+    def render(self):
+        return self.template()
+
+
 class PythonRenderer(object):
     """Mixin class for template less tree generation.
     
@@ -184,8 +285,7 @@
                 'border="0" longDesc="%s" />' % (src, icon.width, 
                    icon.height, longDescURL))
 
-    def renderLI(self, item):
-        name = api.getName(item)
+    def renderLI(self, name, item):
         url = absoluteURL(item, self.request) +'/'+ self.viewName
         iconURL = self.getIconURL(item, self.request)
         id = self.getId(item)
@@ -200,9 +300,8 @@
         res += '</li>'
         return res
 
-    def renderUL(self, item, childTags=None):
+    def renderUL(self, name, item, childTags=None):
         """Renders <li> tag with already rendered child tags."""
-        name = api.getName(item)
         url = absoluteURL(item, self.request) +'/'+ self.viewName
         iconURL = self.getIconURL(item, self.request)
         id = self.getId(item)
@@ -281,15 +380,16 @@
     ulProviderName = 'ul'
     treeProviderName = 'tree'
 
-    def renderLI(self, item):
+    def renderLI(self, name, item):
         provider = zope.component.getMultiAdapter(
             (item, self.request, self), IContentProvider, 
             self.liProviderName)
+        provider.name = name
         provider.state = STATE_STATIC
         provider.update()
         return provider.render()
 
-    def renderUL(self, item, childTags=None):
+    def renderUL(self, name, item, childTags=None):
         """Renders <li> tag with already rendered child tags."""
         if item == self.context:
             state = STATE_COLLAPSED
@@ -302,6 +402,7 @@
         provider = zope.component.getMultiAdapter(
             (item, self.request, self), IContentProvider, 
             self.ulProviderName)
+        provider.name = name
         provider.childTags = childTags
         provider.state = state
         provider.update()
@@ -325,132 +426,3 @@
         provider.state = state
         provider.update()
         return provider.render()
-
-
-class IdGenerator(object):
-    """This mixin class generates Object Ids based on the the objects path.
-
-    Note: The objects must be traversable by it's path. You can implement a 
-    a custom path traverse concept in the getObjectByPath it you need to use
-    another traverse concept.
-
-    This ids must conform the w3c recommendation described in:
-    http://www.w3.org/TR/1999/REC-html401-19991224/types.html#type-name
-    """
-
-    def getId(self, item):
-        """Returns the DOM id for a given object.
-
-        Note: we encode the upper case letters because the Dom element id are 
-        not case sensitive in HTML. We prefix each upper case letter with ':'.
-        """
-        path = api.getPath(item)
-        newPath = u''
-        for letter in path:
-            if letter in string.uppercase:
-                newPath += ':' + letter
-            else:
-                newPath += letter
-
-        # we use a dot as a root representation, this avoids to get the same id
-        # for the ul and the first li tag
-        if newPath == '/':
-            newPath = '.'
-        # add additinal dot which separates the tree id and the path, is used
-        # for get the tree id out of the string in the javascript using
-        # ids = id.split("."); treeId = ids[0];
-        id = self.z3cJSONTreeId +'.'+ newPath
-        # convert '/' path separator to marker '::', because the path '/'' is  
-        # not allowed as DOM id. See also:
-        # http://www.w3.org/TR/1999/REC-html401-19991224/types.html#type-name
-        return id.replace('/', '::')
-
-    def id(self):
-        """Returns the DOM id for a given context."""
-        return self.getId(self.context)
-
-
-class ProviderBase(object):
-    """Base class for element provider."""
-
-    template = getPageTemplate()
-
-    root = None
-    state = None
-    childTags = None
-    iconName = 'icon'
-
-    z3cJSONTreeId = JSON_TREE_ID
-    z3cJSONTreeName = JSON_TREE_ID
-    z3cJSONTreeClass = JSON_TREE_ID
-
-    viewName = JSON_TREE_VIEW_NAME
-
-    # LI tag CSS names
-    collapsedCSSName = JSON_LI_CSS_COLLAPSED
-    expandedCSSName = JSON_LI_CSS_EXPANDED
-    staticCSSName = JSON_LI_CSS_STATIC
-
-    # toggle icon names
-    collapsedIconName = JSON_TOGGLE_ICON_COLLAPSED
-    expandedIconNamen = JSON_TOGGLE_ICON_EXPANDED
-    staticIconName = JSON_TOGGLE_ICON_STATIC
-
-    def __init__(self, context, request, view):
-        self.context = context
-        self.request = request
-        self.view = view
-
-    @property
-    def className(self):
-        if self.state == STATE_COLLAPSED:
-            return self.collapsedCSSName
-        elif self.state == STATE_EXPANDED:
-            return self.expandedCSSName
-        else:
-            return self.staticCSSName
-
-    @property
-    def toggleIcon(self):
-        """Returns a toggle icon including settings for json url."""
-        if self.state == STATE_COLLAPSED:
-            iconName = self.collapsedIconName
-        elif self.state == STATE_EXPANDED:
-            iconName = self.expandedIconNamen
-        else:
-            iconName = self.staticIconName
-        icon = zope.component.getMultiAdapter((self.context, self.request), 
-            name=iconName)
-        resource = getResource(icon.context, icon.rname, self.request)
-        src = resource()
-        longDescURL = absoluteURL(self.context, self.request)
-        return ('<img src="%s" alt="toggle icon" width="%s" height="%s" ' 
-                'border="0" longDesc="%s" />' % (src, icon.width, 
-                   icon.height, longDescURL))
-
-    def icon(self):
-        """Returns a toggle icon including settings for json url."""
-        icon = zope.component.queryMultiAdapter((self.context, self.request), 
-            name=self.iconName)
-        if icon is not None:
-            resource = getResource(icon.context, icon.rname, self.request)
-            src = resource()
-            longDescURL = absoluteURL(self.context, self.request)
-            return ('<img src="%s" alt="toggle icon" width="%s" height="%s" ' 
-                    'border="0" />' % (src, icon.width, icon.height))
-        return u''
-
-    @property
-    def name(self):
-        return api.getName(self.context) or u'[top]'
-
-    @property
-    def url(self):
-        return absoluteURL(self.context, self.request) +'/'+ self.viewName
-
-    def update(self):
-        pass
-
-    def render(self):
-        return self.template()
-

Added: z3c.jsontree/trunk/src/z3c/jsontree/browser/tests/output/tree_3.txt
===================================================================
--- z3c.jsontree/trunk/src/z3c/jsontree/browser/tests/output/tree_3.txt	                        (rev 0)
+++ z3c.jsontree/trunk/src/z3c/jsontree/browser/tests/output/tree_3.txt	2008-04-11 10:32:39 UTC (rev 85232)
@@ -0,0 +1 @@
+<ul class="z3cJSONTree" id="z3cJSONTree" name="z3cJSONTree"><li id="z3cJSONTree.." class="z3cJSONTreeExpanded"><img src="http://127.0.0.1/rootFolder/@@/zope-interface-Interface-z3cJSONTreeExpandedIcon.gif" alt="toggle icon" width="16" height="16" border="0" longDesc="http://127.0.0.1/rootFolder" /><a href="http://127.0.0.1/rootFolder/@@SelectedManagementView.html">[top]</a><ul><li id="z3cJSONTree.::folder1" class="z3cJSONTreeExpanded"><img src="http://127.0.0.1/rootFolder/@@/zope-interface-Interface-z3cJSONTreeExpandedIcon.gif" alt="toggle icon" width="16" height="16" border="0" longDesc="http://127.0.0.1/rootFolder/folder1" /><a href="http://127.0.0.1/rootFolder/folder1/@@SelectedManagementView.html">folder1</a><ul><li id="z3cJSONTree.::folder1::0" class="z3cJSONTreeStatic"><img src="http://127.0.0.1/rootFolder/@@/zope-interface-Interface-z3cJSONTreeStaticIcon.gif" alt="toggle icon" width="16" height="16" border="0" longDesc="http://127.0.0.1/rootFolder/folder1/0" /><a href="http://127.0.0.1/rootFolder/folder1/0/@@SelectedManagementView.html">0</a></li><li id="z3cJSONTree.::folder1::1" class="z3cJSONTreeStatic"><img src="http://127.0.0.1/rootFolder/@@/zope-interface-Interface-z3cJSONTreeStaticIcon.gif" alt="toggle icon" width="16" height="16" border="0" longDesc="http://127.0.0.1/rootFolder/folder1/1" /><a href="http://127.0.0.1/rootFolder/folder1/1/@@SelectedManagementView.html">1</a></li><li id="z3cJSONTree.::folder1::10" class="z3cJSONTreeStatic"><img src="http://127.0.0.1/rootFolder/@@/zope-interface-Interface-z3cJSONTreeStaticIcon.gif" alt="toggle icon" width="16" height="16" border="0" longDesc="http://127.0.0.1/rootFolder/folder1/10" /><a href="http://127.0.0.1/rootFolder/folder1/10/@@SelectedManagementView.html">10</a></li><li id="z3cJSONTree.::folder1::11" class="z3cJSONTreeStatic"><img src="http://127.0.0.1/rootFolder/@@/zope-interface-Interface-z3cJSONTreeStaticIcon.gif" alt="toggle icon" width="16" height="16" border="0" longDesc="http://127.0.0.1/rootFolder/folder1/11" /><a href="http://127.0.0.1/rootFolder/folder1/11/@@SelectedManagementView.html">11</a></li><li id="z3cJSONTree.::folder1::12" class="z3cJSONTreeStatic"><img src="http://127.0.0.1/rootFolder/@@/zope-interface-Interface-z3cJSONTreeStaticIcon.gif" alt="toggle icon" width="16" height="16" border="0" longDesc="http://127.0.0.1/rootFolder/folder1/12" /><a href="http://127.0.0.1/rootFolder/folder1/12/@@SelectedManagementView.html">12</a></li><li id="z3cJSONTree.::folder1::13" class="z3cJSONTreeStatic"><img src="http://127.0.0.1/rootFolder/@@/zope-interface-Interface-z3cJSONTreeStaticIcon.gif" alt="toggle icon" width="16" height="16" border="0" longDesc="http://127.0.0.1/rootFolder/folder1/13" /><a href="http://127.0.0.1/rootFolder/folder1/13/@@SelectedManagementView.html">13</a></li><li id="z3cJSONTree.::folder1::14" class="z3cJSONTreeStatic"><img src="http://127.0.0.1/rootFolder/@@/zope-interface-Interface-z3cJSONTreeStaticIcon.gif" alt="toggle icon" width="16" height="16" border="0" longDesc="http://127.0.0.1/rootFolder/folder1/14" /><a href="http://127.0.0.1/rootFolder/folder1/14/@@SelectedManagementView.html">14</a></li><li id="z3cJSONTree.::folder1::15" class="z3cJSONTreeStatic"><img src="http://127.0.0.1/rootFolder/@@/zope-interface-Interface-z3cJSONTreeStaticIcon.gif" alt="toggle icon" width="16" height="16" border="0" longDesc="http://127.0.0.1/rootFolder/folder1/15" /><a href="http://127.0.0.1/rootFolder/folder1/15/@@SelectedManagementView.html">15</a></li><li id="z3cJSONTree.::folder1::16" class="z3cJSONTreeStatic"><img src="http://127.0.0.1/rootFolder/@@/zope-interface-Interface-z3cJSONTreeStaticIcon.gif" alt="toggle icon" width="16" height="16" border="0" longDesc="http://127.0.0.1/rootFolder/folder1/16" /><a href="http://127.0.0.1/rootFolder/folder1/16/@@SelectedManagementView.html">16</a></li><li id="z3cJSONTree.::folder1::17" class="z3cJSONTreeStatic"><img src="http://127.0.0.1/rootFolder/@@/zope-interface-Interface-z3cJSONTreeStaticIcon.gif" alt="toggle icon" width="16" height="16" border="0" longDesc="http://127.0.0.1/rootFolder/folder1/17" /><a href="http://127.0.0.1/rootFolder/folder1/17/@@SelectedManagementView.html">17</a></li><li id="z3cJSONTree.::folder1::18" class="z3cJSONTreeStatic"><img src="http://127.0.0.1/rootFolder/@@/zope-interface-Interface-z3cJSONTreeStaticIcon.gif" alt="toggle icon" width="16" height="16" border="0" longDesc="http://127.0.0.1/rootFolder/folder1/18" /><a href="http://127.0.0.1/rootFolder/folder1/18/@@SelectedManagementView.html">18</a></li><li id="z3cJSONTree.::folder1::19" class="z3cJSONTreeStatic"><img src="http://127.0.0.1/rootFolder/@@/zope-interface-Interface-z3cJSONTreeStaticIcon.gif" alt="toggle icon" width="16" height="16" border="0" longDesc="http://127.0.0.1/rootFolder/folder1/19" /><a href="http://127.0.0.1/rootFolder/folder1/19/@@SelectedManagementView.html">19</a></li><li id="z3cJSONTree.::folder1::2" class="z3cJSONTreeStatic"><img src="http://127.0.0.1/rootFolder/@@/zope-interface-Interface-z3cJSONTreeStaticIcon.gif" alt="toggle icon" width="16" height="16" border="0" longDesc="http://127.0.0.1/rootFolder/folder1/2" /><a href="http://127.0.0.1/rootFolder/folder1/2/@@SelectedManagementView.html">2</a></li><li id="z3cJSONTree.::folder1::20" class="z3cJSONTreeStatic"><img src="http://127.0.0.1/rootFolder/@@/zope-interface-Interface-z3cJSONTreeStaticIcon.gif" alt="toggle icon" width="16" height="16" border="0" longDesc="http://127.0.0.1/rootFolder/folder1/20" /><a href="http://127.0.0.1/rootFolder/folder1/20/@@SelectedManagementView.html">20</a></li><li id="z3cJSONTree.::folder1::21" class="z3cJSONTreeStatic"><img src="http://127.0.0.1/rootFolder/@@/zope-interface-Interface-z3cJSONTreeStaticIcon.gif" alt="toggle icon" width="16" height="16" border="0" longDesc="http://127.0.0.1/rootFolder/folder1/21" /><a href="http://127.0.0.1/rootFolder/folder1/21/@@SelectedManagementView.html">21</a></li><li id="z3cJSONTree.::folder1::22" class="z3cJSONTreeStatic"><img src="http://127.0.0.1/rootFolder/@@/zope-interface-Interface-z3cJSONTreeStaticIcon.gif" alt="toggle icon" width="16" height="16" border="0" longDesc="http://127.0.0.1/rootFolder/folder1/22" /><a href="http://127.0.0.1/rootFolder/folder1/22/@@SelectedManagementView.html">22</a></li><li id="z3cJSONTree.::folder1::23" class="z3cJSONTreeStatic"><img src="http://127.0.0.1/rootFolder/@@/zope-interface-Interface-z3cJSONTreeStaticIcon.gif" alt="toggle icon" width="16" height="16" border="0" longDesc="http://127.0.0.1/rootFolder/folder1/23" /><a href="http://127.0.0.1/rootFolder/folder1/23/@@SelectedManagementView.html">23</a></li><li id="z3cJSONTree.::folder1::24" class="z3cJSONTreeStatic"><img src="http://127.0.0.1/rootFolder/@@/zope-interface-Interface-z3cJSONTreeStaticIcon.gif" alt="toggle icon" width="16" height="16" border="0" longDesc="http://127.0.0.1/rootFolder/folder1/24" /><a href="http://127.0.0.1/rootFolder/folder1/24/@@SelectedManagementView.html">24</a></li><li id="z3cJSONTree.::folder1::25" class="z3cJSONTreeStatic"><img src="http://127.0.0.1/rootFolder/@@/zope-interface-Interface-z3cJSONTreeStaticIcon.gif" alt="toggle icon" width="16" height="16" border="0" longDesc="http://127.0.0.1/rootFolder/folder1/25" /><a href="http://127.0.0.1/rootFolder/folder1/25/@@SelectedManagementView.html">25</a></li><li id="z3cJSONTree.::folder1::26" class="z3cJSONTreeStatic"><img src="http://127.0.0.1/rootFolder/@@/zope-interface-Interface-z3cJSONTreeStaticIcon.gif" alt="toggle icon" width="16" height="16" border="0" longDesc="http://127.0.0.1/rootFolder/folder1/26" /><a href="http://127.0.0.1/rootFolder/folder1/26/@@SelectedManagementView.html">26</a></li><li id="z3cJSONTree.::folder1::27" class="z3cJSONTreeStatic"><img src="http://127.0.0.1/rootFolder/@@/zope-interface-Interface-z3cJSONTreeStaticIcon.gif" alt="toggle icon" width="16" height="16" border="0" longDesc="http://127.0.0.1/rootFolder/folder1/27" /><a href="http://127.0.0.1/rootFolder/folder1/27/@@SelectedManagementView.html">27</a></li><li id="z3cJSONTree.::folder1::28" class="z3cJSONTreeStatic"><img src="http://127.0.0.1/rootFolder/@@/zope-interface-Interface-z3cJSONTreeStaticIcon.gif" alt="toggle icon" width="16" height="16" border="0" longDesc="http://127.0.0.1/rootFolder/folder1/28" /><a href="http://127.0.0.1/rootFolder/folder1/28/@@SelectedManagementView.html">28</a></li><li id="z3cJSONTree.::folder1::29" class="z3cJSONTreeStatic"><img src="http://127.0.0.1/rootFolder/@@/zope-interface-Interface-z3cJSONTreeStaticIcon.gif" alt="toggle icon" width="16" height="16" border="0" longDesc="http://127.0.0.1/rootFolder/folder1/29" /><a href="http://127.0.0.1/rootFolder/folder1/29/@@SelectedManagementView.html">29</a></li><li id="z3cJSONTree.::folder1::3" class="z3cJSONTreeStatic"><img src="http://127.0.0.1/rootFolder/@@/zope-interface-Interface-z3cJSONTreeStaticIcon.gif" alt="toggle icon" width="16" height="16" border="0" longDesc="http://127.0.0.1/rootFolder/folder1/3" /><a href="http://127.0.0.1/rootFolder/folder1/3/@@SelectedManagementView.html">3</a></li><li id="z3cJSONTree.::folder1::30" class="z3cJSONTreeStatic"><img src="http://127.0.0.1/rootFolder/@@/zope-interface-Interface-z3cJSONTreeStaticIcon.gif" alt="toggle icon" width="16" height="16" border="0" longDesc="http://127.0.0.1/rootFolder/folder1/30" /><a href="http://127.0.0.1/rootFolder/folder1/30/@@SelectedManagementView.html">30</a></li><li id="z3cJSONTree.::folder1::31" class="z3cJSONTreeStatic"><img src="http://127.0.0.1/rootFolder/@@/zope-interface-Interface-z3cJSONTreeStaticIcon.gif" alt="toggle icon" width="16" height="16" border="0" longDesc="http://127.0.0.1/rootFolder/folder1/31" /><a href="http://127.0.0.1/rootFolder/folder1/31/@@SelectedManagementView.html">31</a></li><li id="z3cJSONTree.::folder1::32" class="z3cJSONTreeStatic"><img src="http://127.0.0.1/rootFolder/@@/zope-interface-Interface-z3cJSONTreeStaticIcon.gif" alt="toggle icon" width="16" height="16" border="0" longDesc="http://127.0.0.1/rootFolder/folder1/32" /><a href="http://127.0.0.1/rootFolder/folder1/32/@@SelectedManagementView.html">32</a></li><li id="z3cJSONTree.::folder1::33" class="z3cJSONTreeStatic"><img src="http://127.0.0.1/rootFolder/@@/zope-interface-Interface-z3cJSONTreeStaticIcon.gif" alt="toggle icon" width="16" height="16" border="0" longDesc="http://127.0.0.1/rootFolder/folder1/33" /><a href="http://127.0.0.1/rootFolder/folder1/33/@@SelectedManagementView.html">33</a></li><li id="z3cJSONTree.::folder1::34" class="z3cJSONTreeStatic"><img src="http://127.0.0.1/rootFolder/@@/zope-interface-Interface-z3cJSONTreeStaticIcon.gif" alt="toggle icon" width="16" height="16" border="0" longDesc="http://127.0.0.1/rootFolder/folder1/34" /><a href="http://127.0.0.1/rootFolder/folder1/34/@@SelectedManagementView.html">34</a></li><li id="z3cJSONTree.::folder1::35" class="z3cJSONTreeStatic"><img src="http://127.0.0.1/rootFolder/@@/zope-interface-Interface-z3cJSONTreeStaticIcon.gif" alt="toggle icon" width="16" height="16" border="0" longDesc="http://127.0.0.1/rootFolder/folder1/35" /><a href="http://127.0.0.1/rootFolder/folder1/35/@@SelectedManagementView.html">35</a></li><li id="z3cJSONTree.::folder1::36" class="z3cJSONTreeStatic"><img src="http://127.0.0.1/rootFolder/@@/zope-interface-Interface-z3cJSONTreeStaticIcon.gif" alt="toggle icon" width="16" height="16" border="0" longDesc="http://127.0.0.1/rootFolder/folder1/36" /><a href="http://127.0.0.1/rootFolder/folder1/36/@@SelectedManagementView.html">36</a></li><li id="z3cJSONTree.::folder1::37" class="z3cJSONTreeStatic"><img src="http://127.0.0.1/rootFolder/@@/zope-interface-Interface-z3cJSONTreeStaticIcon.gif" alt="toggle icon" width="16" height="16" border="0" longDesc="http://127.0.0.1/rootFolder/folder1/37" /><a href="http://127.0.0.1/rootFolder/folder1/37/@@SelectedManagementView.html">37</a></li><li id="z3cJSONTree.::folder1::38" class="z3cJSONTreeStatic"><img src="http://127.0.0.1/rootFolder/@@/zope-interface-Interface-z3cJSONTreeStaticIcon.gif" alt="toggle icon" width="16" height="16" border="0" longDesc="http://127.0.0.1/rootFolder/folder1/38" /><a href="http://127.0.0.1/rootFolder/folder1/38/@@SelectedManagementView.html">38</a></li><li id="z3cJSONTree.::folder1::39" class="z3cJSONTreeStatic"><img src="http://127.0.0.1/rootFolder/@@/zope-interface-Interface-z3cJSONTreeStaticIcon.gif" alt="toggle icon" width="16" height="16" border="0" longDesc="http://127.0.0.1/rootFolder/folder1/39" /><a href="http://127.0.0.1/rootFolder/folder1/39/@@SelectedManagementView.html">39</a></li><li id="z3cJSONTree.::folder1::4" class="z3cJSONTreeStatic"><img src="http://127.0.0.1/rootFolder/@@/zope-interface-Interface-z3cJSONTreeStaticIcon.gif" alt="toggle icon" width="16" height="16" border="0" longDesc="http://127.0.0.1/rootFolder/folder1/4" /><a href="http://127.0.0.1/rootFolder/folder1/4/@@SelectedManagementView.html">4</a></li><li id="z3cJSONTree.::folder1::40" class="z3cJSONTreeStatic"><img src="http://127.0.0.1/rootFolder/@@/zope-interface-Interface-z3cJSONTreeStaticIcon.gif" alt="toggle icon" width="16" height="16" border="0" longDesc="http://127.0.0.1/rootFolder/folder1/40" /><a href="http://127.0.0.1/rootFolder/folder1/40/@@SelectedManagementView.html">40</a></li><li id="z3cJSONTree.::folder1::41" class="z3cJSONTreeStatic"><img src="http://127.0.0.1/rootFolder/@@/zope-interface-Interface-z3cJSONTreeStaticIcon.gif" alt="toggle icon" width="16" height="16" border="0" longDesc="http://127.0.0.1/rootFolder/folder1/41" /><a href="http://127.0.0.1/rootFolder/folder1/41/@@SelectedManagementView.html">41</a></li><li id="z3cJSONTree.::folder1::42" class="z3cJSONTreeStatic"><img src="http://127.0.0.1/rootFolder/@@/zope-interface-Interface-z3cJSONTreeStaticIcon.gif" alt="toggle icon" width="16" height="16" border="0" longDesc="http://127.0.0.1/rootFolder/folder1/42" /><a href="http://127.0.0.1/rootFolder/folder1/42/@@SelectedManagementView.html">42</a></li><li id="z3cJSONTree.::folder1::43" class="z3cJSONTreeStatic"><img src="http://127.0.0.1/rootFolder/@@/zope-interface-Interface-z3cJSONTreeStaticIcon.gif" alt="toggle icon" width="16" height="16" border="0" longDesc="http://127.0.0.1/rootFolder/folder1/43" /><a href="http://127.0.0.1/rootFolder/folder1/43/@@SelectedManagementView.html">43</a></li><li id="z3cJSONTree.::folder1::44" class="z3cJSONTreeStatic"><img src="http://127.0.0.1/rootFolder/@@/zope-interface-Interface-z3cJSONTreeStaticIcon.gif" alt="toggle icon" width="16" height="16" border="0" longDesc="http://127.0.0.1/rootFolder/folder1/44" /><a href="http://127.0.0.1/rootFolder/folder1/44/@@SelectedManagementView.html">44</a></li><li id="z3cJSONTree.::folder1::45" class="z3cJSONTreeStatic"><img src="http://127.0.0.1/rootFolder/@@/zope-interface-Interface-z3cJSONTreeStaticIcon.gif" alt="toggle icon" width="16" height="16" border="0" longDesc="http://127.0.0.1/rootFolder/folder1/45" /><a href="http://127.0.0.1/rootFolder/folder1/45/@@SelectedManagementView.html">45</a></li><li id="z3cJSONTree.::folder1::46" class="z3cJSONTreeStatic"><img src="http://127.0.0.1/rootFolder/@@/zope-interface-Interface-z3cJSONTreeStaticIcon.gif" alt="toggle icon" width="16" height="16" border="0" longDesc="http://127.0.0.1/rootFolder/folder1/46" /><a href="http://127.0.0.1/rootFolder/folder1/46/@@SelectedManagementView.html">46</a></li><li id="z3cJSONTree.::folder1::47" class="z3cJSONTreeStatic"><img src="http://127.0.0.1/rootFolder/@@/zope-interface-Interface-z3cJSONTreeStaticIcon.gif" alt="toggle icon" width="16" height="16" border="0" longDesc="http://127.0.0.1/rootFolder/folder1/47" /><a href="http://127.0.0.1/rootFolder/folder1/47/@@SelectedManagementView.html">47</a></li><li id="z3cJSONTree.::folder1::48" class="z3cJSONTreeStatic"><img src="http://127.0.0.1/rootFolder/@@/zope-interface-Interface-z3cJSONTreeStaticIcon.gif" alt="toggle icon" width="16" height="16" border="0" longDesc="http://127.0.0.1/rootFolder/folder1/48" /><a href="http://127.0.0.1/rootFolder/folder1/48/@@SelectedManagementView.html">48</a></li><li id="z3cJSONTree.::folder1::49" class="z3cJSONTreeStatic"><img src="http://127.0.0.1/rootFolder/@@/zope-interface-Interface-z3cJSONTreeStaticIcon.gif" alt="toggle icon" width="16" height="16" border="0" longDesc="http://127.0.0.1/rootFolder/folder1/49" /><a href="http://127.0.0.1/rootFolder/folder1/49/@@SelectedManagementView.html">49</a></li><li id="z3cJSONTree.::folder1::5" class="z3cJSONTreeStatic"><img src="http://127.0.0.1/rootFolder/@@/zope-interface-Interface-z3cJSONTreeStaticIcon.gif" alt="toggle icon" width="16" height="16" border="0" longDesc="http://127.0.0.1/rootFolder/folder1/5" /><a href="http://127.0.0.1/rootFolder/folder1/5/@@SelectedManagementView.html">5</a></li><li id="z3cJSONTree.::folder1::50" class="z3cJSONTreeStatic"><img src="http://127.0.0.1/rootFolder/@@/zope-interface-Interface-z3cJSONTreeStaticIcon.gif" alt="toggle icon" width="16" height="16" border="0" longDesc="http://127.0.0.1/rootFolder/folder1/50" /><a href="http://127.0.0.1/rootFolder/folder1/50/@@SelectedManagementView.html">50</a></li><li id="z3cJSONTree.::folder1::51" class="z3cJSONTreeStatic"><img src="http://127.0.0.1/rootFolder/@@/zope-interface-Interface-z3cJSONTreeStaticIcon.gif" alt="toggle icon" width="16" height="16" border="0" longDesc="http://127.0.0.1/rootFolder/folder1/51" /><a href="http://127.0.0.1/rootFolder/folder1/51/@@SelectedManagementView.html">51</a></li><li id="z3cJSONTree.::folder1::52" class="z3cJSONTreeStatic"><img src="http://127.0.0.1/rootFolder/@@/zope-interface-Interface-z3cJSONTreeStaticIcon.gif" alt="toggle icon" width="16" height="16" border="0" longDesc="http://127.0.0.1/rootFolder/folder1/52" /><a href="http://127.0.0.1/rootFolder/folder1/52/@@SelectedManagementView.html">52</a></li><li id="z3cJSONTree.::folder1" class="z3cJSONTreeStatic"><img src="http://127.0.0.1/rootFolder/@@/zope-interface-Interface-z3cJSONTreeStaticIcon.gif" alt="toggle icon" width="16" height="16" border="0" longDesc="http://127.0.0.1/rootFolder/folder1" /><a href="http://127.0.0.1/rootFolder/folder1/@@SelectedManagementView.html">[7 more items...]</a></li></ul></li><li id="z3cJSONTree.::folder2" class="z3cJSONTreeCollapsed"><img src="http://127.0.0.1/rootFolder/@@/zope-interface-Interface-z3cJSONTreeCollapsedIcon.gif" alt="toggle icon" width="16" height="16" border="0" longDesc="http://127.0.0.1/rootFolder/folder2" /><a href="http://127.0.0.1/rootFolder/folder2/@@SelectedManagementView.html">folder2</a></li><li id="z3cJSONTree.::папка3" class="z3cJSONTreeCollapsed"><img src="http://127.0.0.1/rootFolder/@@/zope-interface-Interface-z3cJSONTreeCollapsedIcon.gif" alt="toggle icon" width="16" height="16" border="0" longDesc="http://127.0.0.1/rootFolder/%D0%BF%D0%B0%D0%BF%D0%BA%D0%B03" /><a href="http://127.0.0.1/rootFolder/%D0%BF%D0%B0%D0%BF%D0%BA%D0%B03/@@SelectedManagementView.html">папка3</a></li></ul></li></ul>


Property changes on: z3c.jsontree/trunk/src/z3c/jsontree/browser/tests/output/tree_3.txt
___________________________________________________________________
Name: svn:eol-style
   + native

Modified: z3c.jsontree/trunk/src/z3c/jsontree/browser/tests/test_view.py
===================================================================
--- z3c.jsontree/trunk/src/z3c/jsontree/browser/tests/test_view.py	2008-04-11 10:09:06 UTC (rev 85231)
+++ z3c.jsontree/trunk/src/z3c/jsontree/browser/tests/test_view.py	2008-04-11 10:32:39 UTC (rev 85232)
@@ -25,6 +25,7 @@
 from zope.pagetemplate.tests.util import check_xml
 from zope.publisher.browser import TestRequest
 from zope.app.component import testing
+from zope.app.folder import Folder
 
 from z3c.testing import TestCase
 from z3c.jsontree.browser.tests import util
@@ -80,6 +81,19 @@
         ultree = view.tree
         check_xml(ultree, util.read_output('tree_2.txt'))
 
+    def test_simple_tree_view_3(self):
+        """This test includes cyrillic letters and maxItems."""
+        context = self.rootFolder['folder1']
+        for i in range(55):
+            context[str(i)] = Folder()
+        
+        subFolder = context['1']
+        request = TestRequest()
+        view = SimpleJSONTreeView(subFolder, request)
+        view.update()
+        ultree = view.tree
+        check_xml(ultree, util.read_output('tree_3.txt'))
+
     def test_generic_tree_view_1(self):
         context = self.rootFolder['folder1']
         request = TestRequest()
@@ -97,7 +111,20 @@
         ultree = view.tree
         check_xml(ultree, util.read_output('tree_2.txt'))
 
+    def test_generic_tree_view_3(self):
+        """This test includes cyrillic letters and maxItems."""
+        context = self.rootFolder['folder1']
+        for i in range(55):
+            context[str(i)] = Folder()
+        
+        subFolder = context['1']
+        request = TestRequest()
+        view = GenericJSONTreeView(subFolder, request)
+        view.update()
+        ultree = view.tree
+        check_xml(ultree, util.read_output('tree_3.txt'))
 
+
 def test_suite():
     return unittest.TestSuite((
         unittest.makeSuite(TestJSONTreeView),

Modified: z3c.jsontree/trunk/src/z3c/jsontree/browser/tree.py
===================================================================
--- z3c.jsontree/trunk/src/z3c/jsontree/browser/tree.py	2008-04-11 10:09:06 UTC (rev 85231)
+++ z3c.jsontree/trunk/src/z3c/jsontree/browser/tree.py	2008-04-11 10:32:39 UTC (rev 85232)
@@ -20,6 +20,7 @@
 import zope.interface
 import zope.component
 from zope.publisher.interfaces.browser import IBrowserRequest
+from zope.publisher.interfaces.http import IHTTPRequest
 from zope.viewlet.interfaces import IViewlet
 
 from z3c.jsontree import interfaces
@@ -55,7 +56,7 @@
     """LI tag content provider."""
 
     zope.interface.implements(interfaces.ILITagProvider)
-    zope.component.adapts(zope.interface.Interface, IBrowserRequest, 
+    zope.component.adapts(zope.interface.Interface, IHTTPRequest, 
         interfaces.ITemplateRenderer)
 
 
@@ -63,13 +64,15 @@
     """UL tag contet provider."""
 
     zope.interface.implements(interfaces.IULTagProvider)
-    zope.component.adapts(zope.interface.Interface, IBrowserRequest, 
+    zope.component.adapts(zope.interface.Interface, IHTTPRequest, 
         interfaces.ITemplateRenderer)
 
 
 class TreeProvider(base.ProviderBase, base.IdGenerator):
     """UL tag contet provider."""
 
+    name = u'[top]'
+
     zope.interface.implements(interfaces.ITreeProvider)
     zope.component.adapts(zope.interface.Interface, IBrowserRequest, 
         interfaces.ITemplateRenderer)

Modified: z3c.jsontree/trunk/src/z3c/jsontree/browser/z3c.jsontree.css
===================================================================
--- z3c.jsontree/trunk/src/z3c/jsontree/browser/z3c.jsontree.css	2008-04-11 10:09:06 UTC (rev 85231)
+++ z3c.jsontree/trunk/src/z3c/jsontree/browser/z3c.jsontree.css	2008-04-11 10:32:39 UTC (rev 85232)
@@ -1,4 +1,4 @@
-
+/*---[ z3c.jsontree styles ]-------------------------------------------------*/
 ul.z3cJSONTree {
     list-style-type: none;
     margin: 0px;

Modified: z3c.jsontree/trunk/src/z3c/jsontree/configure.zcml
===================================================================
--- z3c.jsontree/trunk/src/z3c/jsontree/configure.zcml	2008-04-11 10:09:06 UTC (rev 85231)
+++ z3c.jsontree/trunk/src/z3c/jsontree/configure.zcml	2008-04-11 10:32:39 UTC (rev 85232)
@@ -3,16 +3,31 @@
     xmlns:z3c="http://namespaces.zope.org/z3c"
     i18n_domain="z3c">
 
-  <!-- Note: this method only returns what the user has permission for
-       the permission check is done inside based on the different permission
-       the different items have -->
-  <z3c:jsonrpc
-      for="*"
-      class="z3c.jsontree.jsonrpc.JSONTreeItems"
-      permission="zope.Public"
-      methods="loadJSONTreeItems"
+  <adapter
+      for="zope.interface.Interface
+           zope.publisher.interfaces.browser.IBrowserRequest"
+      factory=".subitem.NoneTreeItems"
       />
 
+  <adapter
+      for="zope.app.container.interfaces.IReadContainer
+           zope.publisher.interfaces.browser.IBrowserRequest"
+      factory=".subitem.ContainerTreeItems"
+      />
+
+  <adapter
+      for="zope.interface.Interface
+           z3c.jsonrpc.interfaces.IJSONRPCRequest"
+      factory=".subitem.NoneTreeItems"
+      />
+
+  <adapter
+      for="zope.app.container.interfaces.IReadContainer
+           z3c.jsonrpc.interfaces.IJSONRPCRequest"
+      factory=".subitem.ContainerTreeItems"
+      />
+
+  <include file="jsonrpc.zcml" />
   <include package=".browser" />
 
 </configure>
\ No newline at end of file

Modified: z3c.jsontree/trunk/src/z3c/jsontree/interfaces.py
===================================================================
--- z3c.jsontree/trunk/src/z3c/jsontree/interfaces.py	2008-04-11 10:09:06 UTC (rev 85231)
+++ z3c.jsontree/trunk/src/z3c/jsontree/interfaces.py	2008-04-11 10:32:39 UTC (rev 85232)
@@ -36,6 +36,20 @@
 STATE_STATIC = 'static'
 
 
+class ITreeItems(zope.interface.Interface):
+    """Knows the items listed in tree for the given context."""
+
+    def __init__(context, provider):
+        """Adapts the context and the request.
+        
+        This allows to use different adapters for different layers on the same
+        context.
+        """
+
+    subItems = zope.interface.Attribute(
+        """List of (name, item, hasSubItems) tuple.""")
+
+
 class IElementProvider(IContentProvider):
 
     state = zope.interface.Attribute(
@@ -103,10 +117,10 @@
 class ITreeRenderer(zope.interface.Interface):
     """Knows how to render elements fo the tree items."""
 
-    def renderLI(item):
+    def renderLI(name, item):
         """Renders <LI> tags."""
 
-    def renderUL(item, childTags=None):
+    def renderUL(name, item, childTags=None):
         """Renders <li> tag including rendered child tags."""
 
     tree = zope.interface.Attribute(

Modified: z3c.jsontree/trunk/src/z3c/jsontree/jsonrpc.py
===================================================================
--- z3c.jsontree/trunk/src/z3c/jsontree/jsonrpc.py	2008-04-11 10:09:06 UTC (rev 85231)
+++ z3c.jsontree/trunk/src/z3c/jsontree/jsonrpc.py	2008-04-11 10:32:39 UTC (rev 85232)
@@ -16,61 +16,44 @@
 """
 __docformat__ = 'restructuredtext'
 
-from zope.traversing import api
-from zope.security.interfaces import Unauthorized
-from zope.security.interfaces import Forbidden
 from zope.traversing.browser import absoluteURL
-from zope.app.container.interfaces import IReadContainer
 
 from z3c.jsonrpc.publisher import MethodPublisher
 
 from z3c.jsontree.interfaces import JSON_TREE_ID
 from z3c.jsontree.interfaces import JSON_TREE_VIEW_NAME
 from z3c.jsontree import base
+from z3c.jsontree import subitem
 from z3c.jsontree import util
 
 
-class JSONTreeItems(MethodPublisher, base.IdGenerator):
+class NoneJSONTreeItems(MethodPublisher, base.IdGenerator):
+    """Returns no items.
+    
+    Default JSON adapter for all objects.
+    """
+
+    def loadJSONTreeItems(self, id):
+        """Returns child information for the object with the given path in a 
+        JSON format."""
+        return {'treeChilds': {'id':id, 'childs':[]}}
+
+
+class JSONTreeItems(subitem.SubItemMixin, MethodPublisher,
+    base.IdGenerator):
     """Returns the data of the childs from the path for the json tree.
     
     This is a simple implementation which uses the traversal concept.
     If you need to lookup items for other conponents then containers,
     e.g. for a widget, you need to implement your own child loader class.
+    
+    This is the default JSON adapter for IReadContainer.
     """
 
     viewName = JSON_TREE_VIEW_NAME
     z3cJSONTreeId = JSON_TREE_ID
     linkHandler = ''
 
-    @property
-    def subItems(self):
-        """Returns a list of items for the given context."""
-        items = []
-        keys = []
-        append = items.append
-        if IReadContainer.providedBy(self.context):
-            try:
-                keys = list(self.context.keys())
-            except(Unauthorized, Forbidden):
-                return items
-        for name in keys:
-            # Only include items we can traverse to
-            subItem = api.traverse(self.context, name, None)
-            if subItem is not None:
-                append(subItem)
-        return items
-
-    def hasSubItems(self, item):
-        """Returns a True or False if the sub item has subitems."""
-        res = False
-        if IReadContainer.providedBy(item):
-            try:
-                if len(item) > 0:
-                    res = True
-            except(Unauthorized, Forbidden):
-                pass
-        return res
-
     def getIconURL(self, item, request, name='icon'):
         return util.getIconURL(item, request, name=name)
 
@@ -81,9 +64,9 @@
         childs = []
         append = childs.append
 
-        for subItem in self.subItems:
+        for name, subItem, hasSubItems in self.getSubItems(self.context):
 
-            if self.hasSubItems(subItem):
+            if hasSubItems:
                 hasChilds = True
             else:
                 hasChilds = False
@@ -91,7 +74,7 @@
             info = {}
             url = absoluteURL(subItem, self.request)
             info['id'] = self.getId(subItem)
-            info['content'] = api.getName(subItem)
+            info['content'] = name
             info['url'] = url +'/'+ self.viewName
             info['iconURL'] = util.getIconURL(subItem, self.request)
             info['linkHandler'] = self.linkHandler

Added: z3c.jsontree/trunk/src/z3c/jsontree/jsonrpc.zcml
===================================================================
--- z3c.jsontree/trunk/src/z3c/jsontree/jsonrpc.zcml	                        (rev 0)
+++ z3c.jsontree/trunk/src/z3c/jsontree/jsonrpc.zcml	2008-04-11 10:32:39 UTC (rev 85232)
@@ -0,0 +1,23 @@
+<configure 
+    xmlns="http://namespaces.zope.org/zope"
+    xmlns:z3c="http://namespaces.zope.org/z3c"
+    i18n_domain="z3c">
+
+  <!-- Note: this method only returns what the user has permission for
+       the permission check is done inside based on the different permission
+       the different items have -->
+  <z3c:jsonrpc
+      for="*"
+      class="z3c.jsontree.jsonrpc.NoneJSONTreeItems"
+      permission="zope.Public"
+      methods="loadJSONTreeItems"
+      />
+
+  <z3c:jsonrpc
+      for="zope.app.container.interfaces.IReadContainer"
+      class="z3c.jsontree.jsonrpc.JSONTreeItems"
+      permission="zope.Public"
+      methods="loadJSONTreeItems"
+      />
+
+</configure>
\ No newline at end of file


Property changes on: z3c.jsontree/trunk/src/z3c/jsontree/jsonrpc.zcml
___________________________________________________________________
Name: svn:eol-style
   + native

Added: z3c.jsontree/trunk/src/z3c/jsontree/subitem.py
===================================================================
--- z3c.jsontree/trunk/src/z3c/jsontree/subitem.py	                        (rev 0)
+++ z3c.jsontree/trunk/src/z3c/jsontree/subitem.py	2008-04-11 10:32:39 UTC (rev 85232)
@@ -0,0 +1,115 @@
+##############################################################################
+#
+# Copyright (c) 2008 Zope Foundation 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.
+#
+##############################################################################
+"""
+$Id:$
+"""
+__docformat__ = 'restructuredtext'
+
+import zope.interface
+import zope.component
+import zope.i18nmessageid
+import zope.i18n
+from zope.security.interfaces import Unauthorized
+from zope.security.interfaces import Forbidden
+from zope.traversing import api
+from zope.app.container.interfaces import IReadContainer
+
+from z3c.jsontree import interfaces
+
+_ = zope.i18nmessageid.MessageFactory('z3c')
+
+
+class SubItemMixin(object):
+    """Base class for sub item lookup."""
+
+    def getSubItems(self, item):
+        """Delegate call to ITreeItems adapter."""
+        adapter = zope.component.getMultiAdapter((item, self.request),
+            interfaces.ITreeItems)
+        return adapter.subItems
+
+
+class TreeItemsMixin(object):
+    """Base class for ITreeItems adapter."""
+
+    zope.interface.implements(interfaces.ITreeItems)
+
+    def __init__(self, context, request):
+        self.context = context
+        self.request = request
+
+
+class NoneTreeItems(TreeItemsMixin):
+    """Returns no items.
+    
+    Default tree item adapter for all objects.
+    """
+
+    @property
+    def subItems(self):
+        return []
+
+
+class ContainerTreeItems(TreeItemsMixin):
+    """Knows the items listed in tree for the given context.
+    
+    This is the default tree item adapter for IReadContainer.
+    """
+
+    maxItems = 50
+
+    def _hasSubItems(self, item):
+        """This method allows us to decide if a sub item has items from the 
+        point of view of the context."""
+        res = False
+        if IReadContainer.providedBy(item):
+            try:
+                if len(item) > 0:
+                    res = True
+            except(Unauthorized, Forbidden):
+                pass
+        return res
+
+    @property
+    def subItems(self):
+        """Collect all tree items for the given context."""
+        items = []
+        keys = []
+        append = items.append
+        if IReadContainer.providedBy(self.context):
+            try:
+                keys = list(self.context.keys())
+            except(Unauthorized, Forbidden):
+                return items
+        else:
+            return items
+        counter = 1
+        for name in keys:
+            # Only include items we can traverse to
+            subItem = api.traverse(self.context, name, None)
+            if subItem is not None:
+                append((api.getName(subItem), subItem,
+                    self._hasSubItems(subItem)))
+            counter += 1
+            if counter == self.maxItems:
+                # add context which should support a item listing view with 
+                # batch
+                lenght = len(keys) - self.maxItems
+                default = '[%s more items...]' % lenght
+                name = zope.i18n.translate(
+                    _('[${lenght} more items...]', mapping={'lenght':lenght}),
+                    context=self.request, default=default)
+                append((name, self.context, False))
+                break
+        return items


Property changes on: z3c.jsontree/trunk/src/z3c/jsontree/subitem.py
___________________________________________________________________
Name: svn:eol-style
   + native

Modified: z3c.jsontree/trunk/src/z3c/jsontree/tests.py
===================================================================
--- z3c.jsontree/trunk/src/z3c/jsontree/tests.py	2008-04-11 10:09:06 UTC (rev 85231)
+++ z3c.jsontree/trunk/src/z3c/jsontree/tests.py	2008-04-11 10:32:39 UTC (rev 85232)
@@ -22,14 +22,18 @@
 import zope.component
 from zope.testing import doctest
 from zope.publisher.browser import TestRequest
+from zope.publisher.interfaces.browser import IBrowserRequest
+from zope.app.container.interfaces import IReadContainer
 from zope.app.testing import setup
 
 import z3c.testing
 import z3c.jsonrpc.testing
+from z3c.jsonrpc.interfaces import IJSONRPCRequest
 from z3c.jsontree import browser
 from z3c.template.zcml import TemplateFactory
 from z3c.template.interfaces import IContentTemplate
 from z3c.jsontree import interfaces
+from z3c.jsontree import subitem
 from z3c.jsontree.browser import tree
 
 
@@ -65,29 +69,45 @@
         return self
 
 
+def setUpAdapters():
+    # register icon resource
+    zope.component.provideAdapter(ResourceStub,
+        name='z3cJSONTreeCollapsedIcon')
+    zope.component.provideAdapter(ResourceStub,
+        name='z3cJSONTreeExpandedIcon')
+    zope.component.provideAdapter(ResourceStub,
+        name='z3cJSONTreeStaticIcon')
+
+    # register icon
+    zope.component.provideAdapter(IconStub('z3cJSONTreeCollapsedIcon'),
+        (zope.interface.Interface, zope.interface.Interface),
+        provides=zope.interface.Interface, name='z3cJSONTreeCollapsedIcon')
+    zope.component.provideAdapter(IconStub('z3cJSONTreeExpandedIcon'),
+        (zope.interface.Interface, zope.interface.Interface),
+        provides=zope.interface.Interface, name='z3cJSONTreeExpandedIcon')
+    zope.component.provideAdapter(IconStub('z3cJSONTreeStaticIcon'),
+        (zope.interface.Interface, zope.interface.Interface),
+        provides=zope.interface.Interface, name='z3cJSONTreeStaticIcon')
+
+    # setup adapters
+    zope.component.provideAdapter(subitem.NoneTreeItems,
+        (zope.interface.Interface, IBrowserRequest))
+    zope.component.provideAdapter(subitem.ContainerTreeItems,
+        (IReadContainer, IBrowserRequest))
+    zope.component.provideAdapter(subitem.NoneTreeItems,
+        (zope.interface.Interface, IJSONRPCRequest))
+    zope.component.provideAdapter(subitem.ContainerTreeItems,
+        (IReadContainer, IJSONRPCRequest))
+
+
 class TestSimpleJSONTree(z3c.testing.InterfaceBaseTest):
 
     def setUp(test):
         setup.placefulSetUp(True)
-        # register icon resource
-        zope.component.provideAdapter(ResourceStub,
-            name='z3cJSONTreeCollapsedIcon')
-        zope.component.provideAdapter(ResourceStub,
-            name='z3cJSONTreeExpandedIcon')
-        zope.component.provideAdapter(ResourceStub,
-            name='z3cJSONTreeStaticIcon')
+        
+        # setup adapters
+        setUpAdapters()
 
-        # register icon
-        zope.component.provideAdapter(IconStub('z3cJSONTreeCollapsedIcon'),
-            (zope.interface.Interface, zope.interface.Interface),
-            provides=zope.interface.Interface, name='z3cJSONTreeCollapsedIcon')
-        zope.component.provideAdapter(IconStub('z3cJSONTreeExpandedIcon'),
-            (zope.interface.Interface, zope.interface.Interface),
-            provides=zope.interface.Interface, name='z3cJSONTreeExpandedIcon')
-        zope.component.provideAdapter(IconStub('z3cJSONTreeStaticIcon'),
-            (zope.interface.Interface, zope.interface.Interface),
-            provides=zope.interface.Interface, name='z3cJSONTreeStaticIcon')
-
     def tearDown(test):
         setup.placefulTearDown()
 
@@ -105,25 +125,10 @@
 
     def setUp(test):
         setup.placefulSetUp(True)
-        # register icon resource
-        zope.component.provideAdapter(ResourceStub,
-            name='z3cJSONTreeCollapsedIcon')
-        zope.component.provideAdapter(ResourceStub,
-            name='z3cJSONTreeExpandedIcon')
-        zope.component.provideAdapter(ResourceStub,
-            name='z3cJSONTreeStaticIcon')
+        
+        # setup adapters
+        setUpAdapters()
 
-        # register icon
-        zope.component.provideAdapter(IconStub('z3cJSONTreeCollapsedIcon'),
-            (zope.interface.Interface, zope.interface.Interface),
-            provides=zope.interface.Interface, name='z3cJSONTreeCollapsedIcon')
-        zope.component.provideAdapter(IconStub('z3cJSONTreeExpandedIcon'),
-            (zope.interface.Interface, zope.interface.Interface),
-            provides=zope.interface.Interface, name='z3cJSONTreeExpandedIcon')
-        zope.component.provideAdapter(IconStub('z3cJSONTreeStaticIcon'),
-            (zope.interface.Interface, zope.interface.Interface),
-            provides=zope.interface.Interface, name='z3cJSONTreeStaticIcon')
-
         # register tree content provider
         zope.component.provideAdapter(tree.TreeProvider, name='tree')
         zope.component.provideAdapter(tree.ULTagProvider, name='ul')
@@ -149,11 +154,15 @@
         return (None, TestRequest())
 
 
+def setUp(test):
+    # setup adapters
+    setUpAdapters()
+    
+
 def test_suite():
     return unittest.TestSuite((
         z3c.jsonrpc.testing.FunctionalDocFileSuite('README.txt',
-            setUp=z3c.jsonrpc.testing.setUp,
-            tearDown=z3c.jsonrpc.testing.tearDown,
+            setUp=setUp,
             optionflags=doctest.NORMALIZE_WHITESPACE|doctest.ELLIPSIS,
             ),
         unittest.makeSuite(TestSimpleJSONTree),



More information about the Checkins mailing list