Configurable Container Views
Configurable Container Views
Status
Authors
Stefan Martin (s.martin@iwm-kmrc.de), Uwe Oestermeier (u.oestermeier@iwm-kmrc.de)
Problem/Proposal
Currently the standard container view in zope.app.container.browser (contents.pt /contents.py) is too limited in it's usability for the user and reusability for the programmer:
- All columns and commands are hard coded. - The find function is very simple (only for ids) and the view of results to small (only ids). - A user can neither sort the items nor show or hide columns.
Therefore a programmer is forced to write special container views for special containers always from scratch.
We propose to reimplement the containerview with configurable and reusable parts:
- Sets of columns (fields)
- Find/filter functions with options (e.g. incluce/exclude items of subcontainers, involved fields)
- New sort functions (sort by fields, grouped)
- Large sets of items should be displayed in batches and not drawn-out
The components should be reusable by the programmer. Standard components should be:
- Sets of columns (fields)
- Commands for selections of objects like rename, cut, copy, paste and delete
- Commands for single objects like add and edit
- Sort functions for subset of standard columns
The composition of these components should be specified in ZCML statements
and schema definitions. The grid should be automatically generated like
displayschema, addform and editform.
Goals
Define a set of schemes, classes and menus that replace the hard coded columns and commands in a reusable way. The composition of these components should be configurable, especially
- the applicability to special types of container and content items: all schema fields, sort criteria, and filter should be defined for specified interfaces or classes.
- the order of appearance, i.e. the order of columns and commands should correspond to the order in schemes and ZCML statements or an explicit position statement.
- the allowed types of interaction: each command for sets of selected contained objects should be ruled by permissions.
- the implementations: the display and edit widgets, the sort and filter functions should be substituable by other implementations.
The resulting containerviews should also offer more options for the user. Container items should be sortable, individual columns should be hideable, large sets of items should be displayed in batches and not drawn-out.
Proposed Solution
Our solution includes the definition of new directives for the composition of container views. The display, adding, and editing mechanisms are borrowed from the existing form machinery.
New configuration directives
The definition of the new directives might look as follows:
<meta:complexDirective
name="grid"
<meta:subdirective
name="gridColumn"
/>
<meta:subdirective
name="gridFilter"
/>
</meta:complexDirective>
The subdirective gridColumn is used to define one slot for the display, editing, and adding of contained item types.
Schema generated rows
If we consider each row as a sequence of schema fields the widgets for
each cell can be displayed like a schemadisplay, edited like an
editform and added like an addform.
Example
The current content view could be configured as follows:
<browser:grid
for="zope.app.container.interfaces.IReadContainer"
permission="zope.ManageContent"
menu="grid_write"
title="Content"
name="content.html"
max_rows=25>
<browser:gridColumn
title=u"Name"
for="zope.app.location.interfaces.ILocation"
field="__name__"
/>
<browser:gridColumn
title=u"Title"
for="zope.app.dublincore.interfaces.IZopeDublinCore"
field="title"
/>
...
<browser:gridColumn
title=u"Size"
for="zope.app.size.interfaces.ISized"
field="sizeForDisplay"
/>
</browser:grid>
The GridView? provides the access to the specified column interfaces and fields. The basic code (without events and error handling) is quite simple:
class GridView(BrowserView):
"""Simple grid-view base class.
"""
# setData and getData methods for container items.
def getData(self, item) :
data = {}
for key, interface in self.columns.items() :
adapter = interface(item, None)
if adapter is not None :
data[key] = getattr(adapter, key)
def setData(self, data):
for key, interface in self.columns.items() :
if key in data :
adapter = interface(item, None)
if adapter is not None :
setattr(adapter, key, data[key])
return "Updated"
# Commands for selections of container items.
def rename(self):
def cut(self):
...
Since the command buttons at the bottom of the container view act like a menu we use the existing ZCML statements:
<browser:menu
id="grid_write"
title="Menu for managing contents of a container"
/>
<browser:menuItems
menu="grid_write"
for="zope.app.container.interfaces.IReadContainer">
<browser:menuItem
action="Rename.html"
title="Rename"
description="Rename selected items"
permission="zope.ManageContent"
/>
<browser:menuItem
action="Cut.html"
title="Cut"
description="Delete selected items and copy to the clipboard"
permission="zope.ManageContent"
/>
...
</browser:menuItems>
<browser:pages
for="zope.app.container.interfaces.IReadContainer"
permission="zope.ManageContent"
class=".GridView">
<browser:page
name="Rename.html"
template="rename.pt"
/>
<brower:page
name="Cut.html"
action="cut"
...
</browser:pages>
Risks
No risks anticipated.
... --benji_york, 2005/09/29 09:00 EST reply
I'll be releasing some code today that does most of what this proposal wants for any collection of objects, not just container views.
