[Checkins] SVN: z3c.tabular/trunk/ added initial implementation

Roger Ineichen roger at projekt01.ch
Sat Feb 21 23:10:57 EST 2009


Log message for revision 96979:
  added initial implementation

Changed:
  _U  z3c.tabular/trunk/
  A   z3c.tabular/trunk/AUTHOR.txt
  A   z3c.tabular/trunk/CHANGES.txt
  A   z3c.tabular/trunk/LICENSE.txt
  A   z3c.tabular/trunk/README.txt
  A   z3c.tabular/trunk/bootstrap.py
  A   z3c.tabular/trunk/buildout.cfg
  A   z3c.tabular/trunk/setup.py
  A   z3c.tabular/trunk/src/
  A   z3c.tabular/trunk/src/z3c/
  A   z3c.tabular/trunk/src/z3c/__init__.py
  A   z3c.tabular/trunk/src/z3c/tabular/
  A   z3c.tabular/trunk/src/z3c/tabular/README.txt
  A   z3c.tabular/trunk/src/z3c/tabular/__init__.py
  A   z3c.tabular/trunk/src/z3c/tabular/browser.zcml
  A   z3c.tabular/trunk/src/z3c/tabular/configure.zcml
  A   z3c.tabular/trunk/src/z3c/tabular/formtable.pt
  A   z3c.tabular/trunk/src/z3c/tabular/interfaces.py
  A   z3c.tabular/trunk/src/z3c/tabular/subformtable.pt
  A   z3c.tabular/trunk/src/z3c/tabular/table.pt
  A   z3c.tabular/trunk/src/z3c/tabular/table.py
  A   z3c.tabular/trunk/src/z3c/tabular/testing.py
  A   z3c.tabular/trunk/src/z3c/tabular/tests.py

-=-

Property changes on: z3c.tabular/trunk
___________________________________________________________________
Added: svn:ignore
   + .installed.cfg
bin
coverage
develop-eggs
parts


Added: z3c.tabular/trunk/AUTHOR.txt
===================================================================
--- z3c.tabular/trunk/AUTHOR.txt	                        (rev 0)
+++ z3c.tabular/trunk/AUTHOR.txt	2009-02-22 04:10:56 UTC (rev 96979)
@@ -0,0 +1 @@
+Roger Ineichen (roger <at> projekt01 <dot> ch)

Added: z3c.tabular/trunk/CHANGES.txt
===================================================================
--- z3c.tabular/trunk/CHANGES.txt	                        (rev 0)
+++ z3c.tabular/trunk/CHANGES.txt	2009-02-22 04:10:56 UTC (rev 96979)
@@ -0,0 +1,8 @@
+=======
+CHANGES
+=======
+
+0.5.0 (2009-02-22)
+------------------
+
+- Initial Release

Added: z3c.tabular/trunk/LICENSE.txt
===================================================================
--- z3c.tabular/trunk/LICENSE.txt	                        (rev 0)
+++ z3c.tabular/trunk/LICENSE.txt	2009-02-22 04:10:56 UTC (rev 96979)
@@ -0,0 +1,54 @@
+Zope Public License (ZPL) Version 2.1
+-------------------------------------
+
+A copyright notice accompanies this license document that
+identifies the copyright holders.
+
+This license has been certified as open source. It has also
+been designated as GPL compatible by the Free Software
+Foundation (FSF).
+
+Redistribution and use in source and binary forms, with or
+without modification, are permitted provided that the
+following conditions are met:
+
+1. Redistributions in source code must retain the
+   accompanying copyright notice, this list of conditions,
+   and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the accompanying
+   copyright notice, this list of conditions, and the
+   following disclaimer in the documentation and/or other
+   materials provided with the distribution.
+
+3. Names of the copyright holders must not be used to
+   endorse or promote products derived from this software
+   without prior written permission from the copyright
+   holders.
+
+4. The right to distribute this software or to use it for
+   any purpose does not give you the right to use
+   Servicemarks (sm) or Trademarks (tm) of the copyright
+   holders. Use of them is covered by separate agreement
+   with the copyright holders.
+
+5. If any files are modified, you must cause the modified
+   files to carry prominent notices stating that you changed
+   the files and the date of any change.
+
+Disclaimer
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS''
+  AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT
+  NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+  AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+  NO EVENT SHALL THE COPYRIGHT HOLDERS BE
+  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+  OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+  DAMAGE.

Added: z3c.tabular/trunk/README.txt
===================================================================
--- z3c.tabular/trunk/README.txt	                        (rev 0)
+++ z3c.tabular/trunk/README.txt	2009-02-22 04:10:56 UTC (rev 96979)
@@ -0,0 +1,2 @@
+This package provides a table implementation including form support for Zope3 
+based on z3c.form and z3c.table.

Added: z3c.tabular/trunk/bootstrap.py
===================================================================
--- z3c.tabular/trunk/bootstrap.py	                        (rev 0)
+++ z3c.tabular/trunk/bootstrap.py	2009-02-22 04:10:56 UTC (rev 96979)
@@ -0,0 +1,52 @@
+##############################################################################
+#
+# Copyright (c) 2008 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.
+#
+##############################################################################
+"""Bootstrap a buildout-based project
+
+Simply run this script in a directory containing a buildout.cfg.
+The script accepts buildout command-line options, so you can
+use the -c option to specify an alternate configuration file.
+
+$Id:$
+"""
+
+import os, shutil, sys, tempfile, urllib2
+
+tmpeggs = tempfile.mkdtemp()
+
+ez = {}
+exec urllib2.urlopen('http://peak.telecommunity.com/dist/ez_setup.py'
+                     ).read() in ez
+ez['use_setuptools'](to_dir=tmpeggs, download_delay=0)
+
+import pkg_resources
+
+cmd = 'from setuptools.command.easy_install import main; main()'
+if sys.platform == 'win32':
+    cmd = '"%s"' % cmd # work around spawn lamosity on windows
+
+ws = pkg_resources.working_set
+assert os.spawnle(
+    os.P_WAIT, sys.executable, sys.executable,
+    '-c', cmd, '-mqNxd', tmpeggs, 'zc.buildout',
+    dict(os.environ,
+         PYTHONPATH=
+         ws.find(pkg_resources.Requirement.parse('setuptools')).location
+         ),
+    ) == 0
+
+ws.add_entry(tmpeggs)
+ws.require('zc.buildout')
+import zc.buildout.buildout
+zc.buildout.buildout.main(sys.argv[1:] + ['bootstrap'])
+shutil.rmtree(tmpeggs)

Added: z3c.tabular/trunk/buildout.cfg
===================================================================
--- z3c.tabular/trunk/buildout.cfg	                        (rev 0)
+++ z3c.tabular/trunk/buildout.cfg	2009-02-22 04:10:56 UTC (rev 96979)
@@ -0,0 +1,27 @@
+[buildout]
+develop = .
+parts = test checker coverage-test coverage-report
+
+
+[test]
+recipe = zc.recipe.testrunner
+eggs = z3c.tabular [test]
+defaults = ['--tests-pattern', '^f?tests$', '-v']
+
+
+[checker]
+recipe = lovely.recipe:importchecker
+path = src/z3c/tabular
+
+
+[coverage-test]
+recipe = zc.recipe.testrunner
+eggs = z3c.tabular [test]
+defaults = ['--coverage', '../../coverage']
+
+
+[coverage-report]
+recipe = zc.recipe.egg
+eggs = z3c.coverage
+scripts = coverage=coverage-report
+arguments = ('coverage', 'coverage/report')

Added: z3c.tabular/trunk/setup.py
===================================================================
--- z3c.tabular/trunk/setup.py	                        (rev 0)
+++ z3c.tabular/trunk/setup.py	2009-02-22 04:10:56 UTC (rev 96979)
@@ -0,0 +1,70 @@
+##############################################################################
+#
+# 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:$
+"""
+
+import os
+from setuptools import setup, find_packages
+
+def read(*rnames):
+    return open(os.path.join(os.path.dirname(__file__), *rnames)).read()
+
+setup (
+    name='z3c.tabular',
+    version='0.5.0',
+    author = "Roger Ineichen and the Zope Community",
+    author_email = "zope3-dev at zope.org",
+    description = "Table with form support based on z3c.form and z3c.table for Zope3",
+    long_description=(
+        read('README.txt')
+        + '\n\n' +
+        read('CHANGES.txt')
+        ),
+    license = "ZPL 2.1",
+    keywords = "zope3 z3c tabular data form table contents",
+    classifiers = [
+        'Development Status :: 4 - Beta',
+        'Environment :: Web Environment',
+        'Intended Audience :: Developers',
+        'License :: OSI Approved :: Zope Public License',
+        'Programming Language :: Python',
+        'Natural Language :: English',
+        'Operating System :: OS Independent',
+        'Topic :: Internet :: WWW/HTTP',
+        'Framework :: Zope3'],
+    url = 'http://cheeseshop.python.org/pypi/z3c.tabular',
+    packages = find_packages('src'),
+    include_package_data = True,
+    package_dir = {'':'src'},
+    namespace_packages = ['z3c'],
+    extras_require = dict(
+        test = [
+            'z3c.table',
+            'z3c.testing',
+            'zope.publisher',
+            'zope.testing',
+            ],
+        ),
+    install_requires = [
+        'setuptools',
+        'z3c.form',
+        'z3c.formui',
+        'z3c.table',
+        'z3c.template',
+        'zope.i18nmessageid',
+        'zope.interface',
+        ],
+    zip_safe = False,
+)


Property changes on: z3c.tabular/trunk/src
___________________________________________________________________
Added: svn:ignore
   + z3c.tabular.egg-info


Added: z3c.tabular/trunk/src/z3c/__init__.py
===================================================================
--- z3c.tabular/trunk/src/z3c/__init__.py	                        (rev 0)
+++ z3c.tabular/trunk/src/z3c/__init__.py	2009-02-22 04:10:56 UTC (rev 96979)
@@ -0,0 +1,7 @@
+try:
+    # Declare this a namespace package if pkg_resources is available.
+    import pkg_resources
+    pkg_resources.declare_namespace('z3c')
+except ImportError:
+    pass
+

Added: z3c.tabular/trunk/src/z3c/tabular/README.txt
===================================================================
--- z3c.tabular/trunk/src/z3c/tabular/README.txt	                        (rev 0)
+++ z3c.tabular/trunk/src/z3c/tabular/README.txt	2009-02-22 04:10:56 UTC (rev 96979)
@@ -0,0 +1,288 @@
+==========
+Form Table
+==========
+
+The goal of this package is to offer a modular table rendering library which 
+includes built in support for update forms. This will allow us to adapt items
+rendered as table row items to forms. This could prevent to use traversable
+exposed forms for such items. But this is just one of the benefits. See more
+below.
+
+
+Form support
+------------
+
+We need to setup the form defaults first:
+
+  >>> from z3c.form.testing import setupFormDefaults
+  >>> setupFormDefaults()
+
+And load the formui confguration, which will make sure that all macros get 
+registered correctly.
+
+  >>> from zope.configuration import xmlconfig
+  >>> import zope.component
+  >>> import zope.viewlet
+  >>> import zope.app.component
+  >>> import zope.app.publisher.browser
+  >>> import z3c.macro
+  >>> import z3c.template
+  >>> import z3c.formui
+  >>> xmlconfig.XMLConfig('meta.zcml', zope.component)()
+  >>> xmlconfig.XMLConfig('meta.zcml', zope.viewlet)()
+  >>> xmlconfig.XMLConfig('meta.zcml', zope.app.component)()
+  >>> xmlconfig.XMLConfig('meta.zcml', zope.app.publisher.browser)()
+  >>> xmlconfig.XMLConfig('meta.zcml', z3c.macro)()
+  >>> xmlconfig.XMLConfig('meta.zcml', z3c.template)()
+  >>> xmlconfig.XMLConfig('configure.zcml', z3c.formui)()
+
+And load the z3c.tabular configure.zcml:
+
+  >>> import z3c.tabular
+  >>> xmlconfig.XMLConfig('configure.zcml', z3c.tabular)()
+
+
+Sample data setup
+-----------------
+
+Let's create a sample container which we can use as our iterable context:
+
+  >>> from zope.app.container import btree
+  >>> class Container(btree.BTreeContainer):
+  ...     """Sample container."""
+  ...     __name__ = u'container'
+  >>> container = Container()
+
+and set a parent for the container:
+
+  >>> root['container'] = container
+
+and create a sample content object which we use as container item:
+
+  >>> import zope.interface
+  >>> import zope.schema
+  >>> class IContent(zope.interface.Interface):
+  ...     """Content interface."""
+  ...  
+  ...     title = zope.schema.TextLine(title=u'Title')
+  ...     number = zope.schema.Int(title=u'Number')
+
+  >>> class Content(object):
+  ...     """Sample content."""
+  ...     zope.interface.implements(IContent)
+  ...     def __init__(self, title, number):
+  ...         self.__name__ = title.lower()
+  ...         self.title = title
+  ...         self.number = number
+
+Now setup some items:
+
+  >>> container[u'first'] = Content('First', 1)
+  >>> container[u'second'] = Content('Second', 2)
+  >>> container[u'third'] = Content('Third', 3)
+
+
+FormTable setup
+---------------
+
+The ``FormTable`` offers a sub form setup for rendering items within a form.
+Let's first define a form for our used items:
+
+
+  >>> from z3c.form import form
+  >>> from z3c.form import field
+  >>> class ContentEditForm(form.EditForm):
+  ...     fields = field.Fields(IContent)
+
+Now we can define our ``FormTable`` including the SelectedItemColumn:
+
+  >>> from z3c.table import column
+  >>> import z3c.tabular.table
+  >>> class ContentFormTable(z3c.tabular.table.SubFormTable):
+  ... 
+  ...     subFormClass = ContentEditForm
+  ... 
+  ...     def setUpColumns(self):
+  ...         return [
+  ...             column.addColumn(self, column.SelectedItemColumn,
+  ...                              u'selectedItem', weight=1),
+  ...             ]
+
+And support the div form layer for our request:
+
+  >>> from z3c.formui.interfaces import IDivFormLayer
+  >>> from zope.interface import alsoProvides
+  >>> from z3c.form.testing import TestRequest
+  >>> request = TestRequest()
+  >>> alsoProvides(request, IDivFormLayer)
+
+Now we can render our table. As you can see the ``SelectedItemColumn`` renders 
+a link which knows hot to select the item:
+
+  >>> contentSubFormTable = ContentFormTable(container, request)
+  >>> contentSubFormTable.__name__ = 'view.html'
+  >>> contentSubFormTable.update()
+  >>> print contentSubFormTable.render()
+  <form action="http://127.0.0.1" method="post"
+        enctype="multipart/form-data" class="edit-form"
+        name="subFormTable" id="subFormTable">
+    <div class="viewspace">
+        <div class="required-info">
+           <span class="required">*</span>
+           &ndash; required
+        </div>
+      <div>
+      <table width="100%" border="0" cellspacing="0" cellpadding="0">
+        <tr>
+          <td valign="top">
+            <div>
+              <table class="contents">
+    <thead>
+      <tr>
+        <th>Name</th>
+      </tr>
+    </thead>
+    <tbody>
+      <tr class="even">
+        <td><a href="http://127.0.0.1/container/view.html?subFormTable-selectedItem-0-selectedItems=first">first</a></td>
+      </tr>
+      <tr class="odd">
+        <td><a href="http://127.0.0.1/container/view.html?subFormTable-selectedItem-0-selectedItems=second">second</a></td>
+      </tr>
+      <tr class="even">
+        <td><a href="http://127.0.0.1/container/view.html?subFormTable-selectedItem-0-selectedItems=third">third</a></td>
+      </tr>
+    </tbody>
+  </table>
+            </div>
+          </td>
+          <td valign="top">
+          </td>
+        </tr>
+      </table>
+    </div>
+    </div>
+    <div>
+      <div class="buttons">
+        <input type="submit" id="subFormTable-buttons-delete"
+         name="subFormTable.buttons.delete"
+         class="submit-widget button-field" value="Delete" />
+        <input type="submit" id="subFormTable-buttons-edit"
+         name="subFormTable.buttons.edit"
+         class="submit-widget button-field" value="Edit" />
+        <input type="submit" id="subFormTable-buttons-cancel"
+         name="subFormTable.buttons.cancel"
+         class="submit-widget button-field" value="Cancel" />
+      </div>
+    </div>
+  </form>
+
+Now we are ready to select an item by click on the link. We simlate this by 
+set the relevant data in the request:
+
+  >>> selectRequest = TestRequest(form={
+  ...     'subFormTable-selectedItem-0-selectedItems': 'second'})
+  >>> alsoProvides(selectRequest, IDivFormLayer)
+  >>> selectedItemTable = ContentFormTable(container, selectRequest)
+  >>> selectedItemTable.__name__ = 'view.html'
+  >>> selectedItemTable.update()
+  >>> print selectedItemTable.render()
+  <form action="http://127.0.0.1" method="post"
+        enctype="multipart/form-data" class="edit-form"
+        name="subFormTable" id="subFormTable">
+    <div class="viewspace">
+        <div class="required-info">
+           <span class="required">*</span>
+           &ndash; required
+        </div>
+      <div>
+      <table width="100%" border="0" cellspacing="0" cellpadding="0">
+        <tr>
+          <td valign="top">
+            <div>
+              <table class="contents">
+    <thead>
+      <tr>
+        <th>Name</th>
+      </tr>
+    </thead>
+    <tbody>
+      <tr class="even">
+        <td><a href="http://127.0.0.1/container/view.html?subFormTable-selectedItem-0-selectedItems=first">first</a></td>
+      </tr>
+      <tr class="selected odd">
+        <td><a href="http://127.0.0.1/container/view.html?subFormTable-selectedItem-0-selectedItems=second">second</a></td>
+      </tr>
+      <tr class="even">
+        <td><a href="http://127.0.0.1/container/view.html?subFormTable-selectedItem-0-selectedItems=third">third</a></td>
+      </tr>
+    </tbody>
+  </table>
+            </div>
+          </td>
+          <td valign="top">
+            <div class="tableForm">
+              <form action="http://127.0.0.1" method="post"
+        enctype="multipart/form-data" class="edit-form"
+        name="form" id="form">
+    <div class="viewspace">
+        <div class="required-info">
+           <span class="required">*</span>
+           &ndash; required
+        </div>
+      <div>
+            <div id="form-widgets-title-row" class="row">
+                <div class="label">
+                  <label for="form-widgets-title">
+                    <span>Title</span>
+                    <span class="required">*</span>
+                  </label>
+                </div>
+                <div class="widget"><input type="text" id="form-widgets-title"
+         name="form.widgets.title"
+         class="text-widget required textline-field"
+         value="Second" />
+  </div>
+            </div>
+            <div id="form-widgets-number-row" class="row">
+                <div class="label">
+                  <label for="form-widgets-number">
+                    <span>Number</span>
+                    <span class="required">*</span>
+                  </label>
+                </div>
+                <div class="widget"><input type="text" id="form-widgets-number"
+         name="form.widgets.number"
+         class="text-widget required int-field" value="2" />
+  </div>
+            </div>
+      </div>
+    </div>
+    <div>
+      <div class="buttons">
+        <input type="submit" id="form-buttons-apply"
+         name="form.buttons.apply"
+         class="submit-widget button-field" value="Apply" />
+      </div>
+    </div>
+  </form>
+            </div>
+          </td>
+        </tr>
+      </table>
+    </div>
+    </div>
+    <div>
+      <div class="buttons">
+        <input type="submit" id="subFormTable-buttons-delete"
+         name="subFormTable.buttons.delete"
+         class="submit-widget button-field" value="Delete" />
+        <input type="submit" id="subFormTable-buttons-edit"
+         name="subFormTable.buttons.edit"
+         class="submit-widget button-field" value="Edit" />
+        <input type="submit" id="subFormTable-buttons-cancel"
+         name="subFormTable.buttons.cancel"
+         class="submit-widget button-field" value="Cancel" />
+      </div>
+    </div>
+  </form>

Added: z3c.tabular/trunk/src/z3c/tabular/__init__.py
===================================================================
--- z3c.tabular/trunk/src/z3c/tabular/__init__.py	                        (rev 0)
+++ z3c.tabular/trunk/src/z3c/tabular/__init__.py	2009-02-22 04:10:56 UTC (rev 96979)
@@ -0,0 +1 @@
+# make a package

Added: z3c.tabular/trunk/src/z3c/tabular/browser.zcml
===================================================================
--- z3c.tabular/trunk/src/z3c/tabular/browser.zcml	                        (rev 0)
+++ z3c.tabular/trunk/src/z3c/tabular/browser.zcml	2009-02-22 04:10:56 UTC (rev 96979)
@@ -0,0 +1,25 @@
+<configure
+    xmlns:zope="http://namespaces.zope.org/zope"
+    xmlns="http://namespaces.zope.org/browser"
+    xmlns:z3c="http://namespaces.zope.org/z3c"
+    i18n_domain="z3c">
+
+  <z3c:template
+      template="table.pt"
+      for=".interfaces.ITemplateTable"
+      layer="zope.publisher.interfaces.browser.IBrowserRequest"
+      />
+
+  <z3c:template
+      template="formtable.pt"
+      for=".interfaces.IFormTable"
+      layer="zope.publisher.interfaces.browser.IBrowserRequest"
+      />
+
+  <z3c:template
+      template="subformtable.pt"
+      for=".interfaces.ISubFormTable"
+      layer="zope.publisher.interfaces.browser.IBrowserRequest"
+      />
+
+</configure>

Added: z3c.tabular/trunk/src/z3c/tabular/configure.zcml
===================================================================
--- z3c.tabular/trunk/src/z3c/tabular/configure.zcml	                        (rev 0)
+++ z3c.tabular/trunk/src/z3c/tabular/configure.zcml	2009-02-22 04:10:56 UTC (rev 96979)
@@ -0,0 +1,7 @@
+<configure
+    xmlns="http://namespaces.zope.org/zope"
+    i18n_domain="z3c">
+
+  <include file="browser.zcml" />
+
+</configure>

Added: z3c.tabular/trunk/src/z3c/tabular/formtable.pt
===================================================================
--- z3c.tabular/trunk/src/z3c/tabular/formtable.pt	                        (rev 0)
+++ z3c.tabular/trunk/src/z3c/tabular/formtable.pt	2009-02-22 04:10:56 UTC (rev 96979)
@@ -0,0 +1,18 @@
+<div metal:use-macro="macro:form">
+  <div metal:fill-slot="main"
+       tal:define="batch view/renderBatch">
+    <div class="tabluarTable">
+      <tal:block replace="structure view/renderTable">
+        table
+      </tal:block>
+    </div>
+    <div class="batch" tal:condition="batch">
+      <tal:block replace="structure batch">
+        table
+      </tal:block>
+    </div>
+    <div class="tabluarForm">
+      <div metal:use-macro="macro:widget-rows" />
+    </div>
+  </div>
+</div>

Added: z3c.tabular/trunk/src/z3c/tabular/interfaces.py
===================================================================
--- z3c.tabular/trunk/src/z3c/tabular/interfaces.py	                        (rev 0)
+++ z3c.tabular/trunk/src/z3c/tabular/interfaces.py	2009-02-22 04:10:56 UTC (rev 96979)
@@ -0,0 +1,35 @@
+##############################################################################
+#
+# 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 z3c.table.interfaces
+
+
+class ITemplateTable(z3c.table.interfaces.ITable):
+    """Template aware table."""
+
+
+class IFormTable(ITemplateTable):
+    """Table including a form setup."""
+
+
+class IDeleteFormTable(IFormTable):
+    """Delete button aware table including a form setup."""
+
+
+class ISubFormTable(IDeleteFormTable):
+    """Table including a sub form for one selected item."""

Added: z3c.tabular/trunk/src/z3c/tabular/subformtable.pt
===================================================================
--- z3c.tabular/trunk/src/z3c/tabular/subformtable.pt	                        (rev 0)
+++ z3c.tabular/trunk/src/z3c/tabular/subformtable.pt	2009-02-22 04:10:56 UTC (rev 96979)
@@ -0,0 +1,29 @@
+<div metal:use-macro="macro:form">
+  <div metal:fill-slot="main">
+    <table width="100%" border="0" cellspacing="0" cellpadding="0">
+      <tr>
+        <td valign="top"
+            tal:define="batch view/renderBatch">
+          <div>
+            <tal:block replace="structure view/renderTable">
+              table
+            </tal:block>
+          </div>
+          <div class="batch" tal:condition="batch">
+            <tal:block replace="structure batch">
+              table
+            </tal:block>
+          </div>
+        </td>
+        <td valign="top"
+            tal:define="subForm nocall:view/subForm">
+          <div class="tableForm" tal:condition="nocall:subForm">
+            <tal:block replace="structure subForm/render">
+              form
+            </tal:block>
+          </div>
+        </td>
+      </tr>
+    </table>
+  </div>
+</div>

Added: z3c.tabular/trunk/src/z3c/tabular/table.pt
===================================================================
--- z3c.tabular/trunk/src/z3c/tabular/table.pt	                        (rev 0)
+++ z3c.tabular/trunk/src/z3c/tabular/table.pt	2009-02-22 04:10:56 UTC (rev 96979)
@@ -0,0 +1,15 @@
+<div metal:use-macro="macro:form">
+  <div metal:fill-slot="main"
+       tal:define="batch view/renderBatch">
+    <div class="tabluarTable">
+      <tal:block replace="structure view/renderTable">
+        table
+      </tal:block>
+    </div>
+    <div class="batch" tal:condition="batch">
+      <tal:block replace="structure batch">
+        table
+      </tal:block>
+    </div>
+  </div>
+</div>

Added: z3c.tabular/trunk/src/z3c/tabular/table.py
===================================================================
--- z3c.tabular/trunk/src/z3c/tabular/table.py	                        (rev 0)
+++ z3c.tabular/trunk/src/z3c/tabular/table.py	2009-02-22 04:10:56 UTC (rev 96979)
@@ -0,0 +1,258 @@
+##############################################################################
+#
+# 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 transaction
+import zope.interface
+import zope.i18nmessageid
+
+from z3c.form import button
+from z3c.form import field
+from z3c.formui import form
+from z3c.table import table
+from z3c.template.template import getPageTemplate
+
+from z3c.tabular import interfaces
+
+_ = zope.i18nmessageid.MessageFactory('z3c')
+
+
+# conditions
+def hasContent(form):
+    return form.hasContent
+
+
+def canCancel(form):
+    return form.supportsCancel
+
+
+def canDelete(form):
+    return form.supportsDelete
+
+
+# simple template rendering aware table base class
+class TemplateTable(table.Table):
+    """Template aware teble."""
+
+    zope.interface.implements(interfaces.ITemplateTable)
+
+    template = getPageTemplate()
+
+    def render(self):
+        """Render the template."""
+        return self.template()
+
+
+# simple form aware table base class
+class TableBase(TemplateTable):
+    """Generic table class with form action support used as form mixin base.
+    
+    This table base class allows you to mixin custom forms as base.
+    """
+
+    prefix = 'formTable'
+
+    # internal defaults
+    actions = None
+    hasContent = False
+    nextURL = None
+    selectedItems = []
+    ignoreContext = False
+
+    # table defaults
+    cssClasses = {'table': 'contents'}
+    cssClassEven = u'even'
+    cssClassOdd = u'odd'
+    cssClassSelected = u'selected'
+    
+    batchSize = 25
+    startBatchingAt = 25
+    
+    # customize this part
+    allowCancel = True
+
+    def update(self):
+        # 1. setup widgets
+        self.updateWidgets()
+        # 2. setup search values, generate rows, setup headers and columns
+        super(TableBase, self).update()
+        # 3. setup conditions
+        self.setupConditions()
+        # 4. setup form part
+        self.updateActions()
+        if self.actions is not None:
+            self.actions.execute()
+
+    def setupConditions(self):
+        self.hasContent = bool(self.rows)
+        if self.allowCancel:
+            self.supportsCancel = self.hasContent
+
+    def updateAfterActionExecution(self):
+        """Update table data if subform changes soemthing."""
+        # first update table data which probably changed
+        super(TableBase, self).update()
+        # second setup conditions
+        self.setupConditions()
+        # third update action which we have probably different conditions for
+        self.updateActions()
+
+    @button.buttonAndHandler(_('Cancel'), name='cancel', condition=canCancel)
+    def handleCancel(self, action):
+        self.nextURL = self.request.getURL()
+
+    def render(self):
+        """Render the template."""
+        if self.nextURL is not None:
+            self.request.response.redirect(self.nextURL)
+            return ""
+        return self.template()
+
+
+class FormTable(TableBase, form.Form):
+    """Generic table class with form action support based on IForm."""
+
+    zope.interface.implements(interfaces.IFormTable)
+
+    template = getPageTemplate()
+
+
+class DeleteFormTable(FormTable):
+    """Table class with form action support based on IForm."""
+
+    zope.interface.implements(interfaces.IDeleteFormTable)
+
+    prefix = 'deleteFormTable'
+
+    # internal defaults
+    supportsCancel = False
+    supportsDelete = False
+
+    deleteErrorMessage = _('Could not delete the selected items')
+    deleteNoItemsMessage = _('No items selected for delete')
+    deleteSuccessMessage = _('Data successfully deleted')
+    
+    # customize this part
+    allowCancel = True
+    allowDelete = True
+
+    def executeDelete(self, item):
+        raise NotImplementedError('Subclass must implement executeDelete')
+
+    def setupConditions(self):
+        self.hasContent = bool(self.rows)
+        if self.allowCancel:
+            self.supportsCancel = self.hasContent
+        if self.allowDelete:
+            self.supportsDelete = self.hasContent
+
+    def doDelete(self, action):
+        if not len(self.selectedItems):
+            self.status = self.deleteNoItemsMessage
+            return
+        try:
+            for item in self.selectedItems:
+                self.executeDelete(item)
+            # update the table rows before we start with rendering
+            self.updateAfterActionExecution()
+            if self.status is None:
+                # probably execute delete or updateAfterAction already set a 
+                # status
+                self.status = self.deleteSuccessMessage
+        except KeyError:
+            self.status = self.deleteErrorMessage
+            transaction.doom()
+
+    @button.buttonAndHandler(_('Delete'), name='delete', condition=canDelete)
+    def handleDelete(self, action):
+        self.doDelete(action)
+
+
+# form table including a sub form
+class SubFormTable(DeleteFormTable):
+    """Form table including a sub form based on IForm."""
+
+    zope.interface.implements(interfaces.ISubFormTable)
+
+    buttons = DeleteFormTable.buttons.copy()
+    handlers = DeleteFormTable.handlers.copy()
+
+    prefix = 'subFormTable'
+
+    # internal defaults
+    subForm = None
+
+    # error messages
+    subFormNoItemMessage = _('No item selected for edit')
+    subFormToManyItemsMessage = _('Only one item could be selected for edit')
+    subFormNotFoundMessage = _('No edit form found for selected item')
+    
+    # customize this part
+    # use subFormClass or use subFormName. If you set both it will end in 
+    # using subFormClass. See updateSubForm for details.
+    subFormClass = None
+    subFormName = u''
+
+    def update(self):
+        # 1. setup widgets
+        super(SubFormTable, self).update()
+        # 2. setup form after we set probably a selectedItem
+        self.updateSubForm()
+
+    @property
+    def selectedItem(self):
+        if len(self.selectedItems) == 0:
+            return None
+        if len(self.selectedItems) > 1:
+            self.status = self.subFormToManyItemsMessage
+            return None
+        return self.selectedItems[0]
+
+    def setUpSubForm(self, selectedItem):
+        if self.subFormClass is not None:
+            return self.subFormClass(selectedItem, self.request)
+        elif self.subFormName is not None:
+            return zope.component.queryMultiAdapter((selectedItem,
+                self.request), name=self.subFormName)
+
+    def updateSubForm(self):
+        selectedItem = self.selectedItem
+        if selectedItem is None:
+            return
+        # set table as parent
+        self.subForm = self.setUpSubForm(selectedItem)
+        if self.subForm is None:
+            self.status = self.subFormNotFoundMessage
+            return
+        self.subForm.__parent__ = self
+        # udpate edit form
+        self.subForm.update()
+
+    def doSubForm(self, action):
+        if self.subForm is None:
+            return
+        # set ignore request and update again
+        self.subForm.ignoreRequest = True
+        self.subForm.update()
+
+    @button.buttonAndHandler(u'Edit')
+    def handleSubForm(self, action):
+        self.doSubForm(action)
+
+    @button.buttonAndHandler(_('Cancel'), name='cancel', condition=canCancel)
+    def handleCancel(self, action):
+        self.nextURL = self.request.getURL()

Added: z3c.tabular/trunk/src/z3c/tabular/testing.py
===================================================================
--- z3c.tabular/trunk/src/z3c/tabular/testing.py	                        (rev 0)
+++ z3c.tabular/trunk/src/z3c/tabular/testing.py	2009-02-22 04:10:56 UTC (rev 96979)
@@ -0,0 +1,40 @@
+##############################################################################
+#
+# 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"
+
+from zope.app.pagetemplate import metaconfigure
+from zope.app.testing import setup
+
+import z3c.macro.tales
+import z3c.table.testing
+
+
+###############################################################################
+#
+# testing setup
+#
+###############################################################################
+
+def setUp(test):
+    test.globs = {'root': setup.placefulSetUp(True)}
+
+    metaconfigure.registerType('macro', z3c.macro.tales.MacroExpression)
+    z3c.table.testing.setUpAdapters()
+
+
+def tearDown(test):
+    setup.placefulTearDown()

Added: z3c.tabular/trunk/src/z3c/tabular/tests.py
===================================================================
--- z3c.tabular/trunk/src/z3c/tabular/tests.py	                        (rev 0)
+++ z3c.tabular/trunk/src/z3c/tabular/tests.py	2009-02-22 04:10:56 UTC (rev 96979)
@@ -0,0 +1,63 @@
+##############################################################################
+#
+# 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 unittest
+from zope.testing import doctest
+from zope.publisher.browser import TestRequest
+
+import z3c.testing
+import z3c.table.testing
+from z3c.tabular import interfaces
+from z3c.tabular import table
+from z3c.tabular import testing
+
+
+class FakeContainer(object):
+    def values(self):
+        pass
+
+
+# table
+class TestFormTable(z3c.testing.InterfaceBaseTest):
+
+    def setUp(test):
+        z3c.table.testing.setUpAdapters()
+
+    def getTestInterface(self):
+        return interfaces.IFormTable
+
+    def getTestClass(self):
+        return table.FormTable
+
+    def getTestPos(self):
+        return (FakeContainer(), TestRequest())
+
+
+
+def test_suite():
+    return unittest.TestSuite((
+        doctest.DocFileSuite('README.txt',
+            setUp=testing.setUp, tearDown=testing.tearDown,
+            optionflags=doctest.NORMALIZE_WHITESPACE|doctest.ELLIPSIS,
+            ),
+        unittest.makeSuite(TestFormTable),
+        ))
+
+
+if __name__ == '__main__':
+    unittest.main(defaultTest='test_suite')



More information about the Checkins mailing list