From 71954f3fe5ecb6e42f1e66a4511f1a39f1fc4d35 Mon Sep 17 00:00:00 2001 From: Helmut Merz Date: Fri, 23 Dec 2011 14:13:28 +0100 Subject: [PATCH 1/2] make keytable field and widget fully operable --- composer/schema/grid/field.py | 13 +++++++++++++ composer/schema/grid/grid_macros.pt | 19 +++++++++++++++---- composer/schema/grid/interfaces.py | 2 ++ 3 files changed, 30 insertions(+), 4 deletions(-) diff --git a/composer/schema/grid/field.py b/composer/schema/grid/field.py index d67f33a..e5c8152 100644 --- a/composer/schema/grid/field.py +++ b/composer/schema/grid/field.py @@ -126,6 +126,9 @@ class GridFieldInstance(ListFieldInstance): class RecordsFieldInstance(GridFieldInstance): + def getRenderer(self, name): + return grid_macros.macros[name] + def marshall(self, value): result = [] for row in value or []: @@ -156,6 +159,16 @@ class KeyTableFieldInstance(RecordsFieldInstance): def dataNames(self): return [f.name for f in self.columnTypes[1:]] + def display(self, value): + headers = [fi.context.title for fi in self.columnFieldInstances] + rows = [] + for k, v in value.items(): + row = [k] + for idx, fi in enumerate(self.columnFieldInstances[1:]): + row.append(fi.display(v[idx])) + rows.append(row) + return dict(headers=headers, rows=rows) + def marshall(self, value): result = [] if not value: diff --git a/composer/schema/grid/grid_macros.pt b/composer/schema/grid/grid_macros.pt index 903be12..751e627 100755 --- a/composer/schema/grid/grid_macros.pt +++ b/composer/schema/grid/grid_macros.pt @@ -39,16 +39,14 @@ - @@ -92,5 +90,18 @@ + +
Column Title
+ + + + +
Column Title
+ + + diff --git a/composer/schema/grid/interfaces.py b/composer/schema/grid/interfaces.py index f6ca57a..b653d42 100644 --- a/composer/schema/grid/interfaces.py +++ b/composer/schema/grid/interfaces.py @@ -55,5 +55,7 @@ class KeyTable(Grid): FieldType('keytable', 'keytable', u'A dictionary of records or rows the first ' u'column of which represents the key.', + displayRenderer='display_records', + inputRenderer='input_records', instanceName='keytable',)) From 117d8b194cbd6fe37794c4d94d7a99d6b3aac237 Mon Sep 17 00:00:00 2001 From: Helmut Merz Date: Tue, 27 Dec 2011 20:10:20 +0100 Subject: [PATCH 2/2] backport changes from BlueBream version, e.g. for dynamic retrieving renderer; provide context and request for field instance in order to work with vocabularies depending on context --- composer/schema/field.py | 24 +++++++++++++++++------- composer/schema/grid/field.py | 2 ++ composer/schema/instance.py | 3 ++- composer/schema/interfaces.py | 12 +++++++++--- 4 files changed, 30 insertions(+), 11 deletions(-) diff --git a/composer/schema/field.py b/composer/schema/field.py index 3509b7b..dc89e92 100644 --- a/composer/schema/field.py +++ b/composer/schema/field.py @@ -18,8 +18,6 @@ """ Schema fields and related classes. - -$Id$ """ from datetime import datetime @@ -32,7 +30,7 @@ from zope.component import adapts from zope import component from zope.i18n.format import DateTimeParseError from zope.i18n.locales import locales -from zope.schema.interfaces import IVocabularyFactory +from zope.schema.interfaces import IVocabularyFactory, IContextSourceBinder from zope.tales.engine import Engine from zope.tales.tales import Context @@ -139,8 +137,15 @@ class Field(Component): return terms voc = voc.splitlines() return [dict(token=t, title=t) for t in voc if t.strip()] - else: - return [dict(token=t.token, title=t.title or t.value) for t in voc] + elif IContextSourceBinder.providedBy(voc): + source = voc(context) + terms = component.queryMultiAdapter((source, request), ITerms) + if terms is not None: + termsList = [terms.getTerm(value) for value in source] + return [dict(token=t.token, title=t.title) for t in termsList] + else: + return None + return [dict(token=t.token, title=t.title or t.value) for t in voc] def getVocabularyTerms(self, name, context, request): if context is None or request is None: @@ -157,12 +162,14 @@ class Field(Component): def getFieldTypeInfo(self): return self.fieldTypeInfo or fieldTypes.getTerm(self.fieldType) - def getFieldInstance(self, clientInstance=None): + def getFieldInstance(self, clientInstance=None, context=None, request=None): instanceName = self.instance_name or self.getFieldTypeInfo().instanceName fi = component.queryAdapter(self, IFieldInstance, name=instanceName) if fi is None: fi = component.getAdapter(self, IFieldInstance, name='') fi.clientInstance = clientInstance + fi.clientContext = context + fi.request = request return fi def getContextProperties(self): @@ -216,6 +223,9 @@ class FieldInstance(object): self.errors.append(error) self.severity = max(error.severity, self.severity) + def getRenderer(self, name): + return None + class NumberFieldInstance(FieldInstance): @@ -385,7 +395,7 @@ class CheckBoxesFieldInstance(ListFieldInstance): class DropdownFieldInstance(FieldInstance): def display(self, value): - items = self.context.getVocabularyItems() + items = self.context.getVocabularyItems(self.clientContext, self.request) for item in items: if item['token'] == value: return item['title'] diff --git a/composer/schema/grid/field.py b/composer/schema/grid/field.py index e5c8152..b2eefc9 100644 --- a/composer/schema/grid/field.py +++ b/composer/schema/grid/field.py @@ -162,6 +162,8 @@ class KeyTableFieldInstance(RecordsFieldInstance): def display(self, value): headers = [fi.context.title for fi in self.columnFieldInstances] rows = [] + if value is None: + value = {} for k, v in value.items(): row = [k] for idx, fi in enumerate(self.columnFieldInstances[1:]): diff --git a/composer/schema/instance.py b/composer/schema/instance.py index 682898f..1c5ffbf 100644 --- a/composer/schema/instance.py +++ b/composer/schema/instance.py @@ -52,7 +52,8 @@ class Instance(BaseInstance): if not f.storeData: # a dummy field, e.g. a spacer continue - fi = f.getFieldInstance(self) + fi = f.getFieldInstance(self, context=kw.get('context'), + request=kw.get('request')) name = f.name value = getattr(self.context, name) or fi.default if mode in ('view', 'preview'): diff --git a/composer/schema/interfaces.py b/composer/schema/interfaces.py index 6ed3551..9e3f809 100644 --- a/composer/schema/interfaces.py +++ b/composer/schema/interfaces.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2010 Helmut Merz helmutm@cy55.de +# Copyright (c) 2011 Helmut Merz helmutm@cy55.de # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -18,8 +18,6 @@ """ Schemas and Fields. - -$Id$ """ from zope import schema @@ -278,6 +276,14 @@ class IFieldInstance(Interface): allow for checking more than one data element. """ + def getRenderer(name): + """ Return the renderer object (e.g. a ZPT macro) for this field + with the name given. + + May return None in which case the calling application should + use a default renderer. + """ + class IFormState(Interface): """ Represents the state of all fields when editing.