src/pyams_i18n/widget/__init__.py
changeset 2 a44a73ee12f9
child 4 a80dffc48eb6
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/pyams_i18n/widget/__init__.py	Fri Mar 20 17:28:43 2015 +0100
@@ -0,0 +1,152 @@
+#
+# Copyright (c) 2008-2015 Thierry Florac <tflorac AT ulthar.net>
+# 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.
+#
+from pyramid.decorator import reify
+
+__docformat__ = 'restructuredtext'
+
+
+# import standard library
+
+# import interfaces
+from pyams_form.interfaces.form import IFormLayer
+from pyams_i18n.interfaces import II18nManager, INegotiator
+from pyams_i18n.interfaces.schema import II18nField, II18nTextLineField, II18nTextField, II18nFileField
+from pyams_i18n.interfaces.widget import II18nWidget, II18nTextLineWidget, II18nTextWidget, II18nFileWidget
+from z3c.form.interfaces import IDataConverter, IFieldWidget, NO_VALUE
+
+# import packages
+from pyams_form.widget import widgettemplate_config
+from pyams_utils.adapter import adapter_config
+from pyams_utils.registry import query_utility
+from pyams_utils.traversing import get_parent
+from z3c.form.browser.widget import HTMLInputWidget
+from z3c.form.converter import BaseDataConverter
+from z3c.form.util import expandPrefix
+from z3c.form.widget import Widget, FieldWidget
+from zope.interface import implementer_only
+
+
+@adapter_config(context=(II18nField, II18nWidget), provides=IDataConverter)
+class I18nDataConverter(BaseDataConverter):
+    """I18n base data converter"""
+
+    def __init__(self, field, widget):
+        super(I18nDataConverter, self).__init__(field, widget)
+
+    def toWidgetValue(self, value):
+        # I18n widget is using a dict where each key is a lang
+        # and each value is matching widget value
+        result = {}
+        registry = self.widget.request.registry
+        for lang, val in value.items():
+            converter = registry.queryMultiAdapter((self.field.value_type, self.widget.get_widget(lang)),
+                                                   IDataConverter)
+            if converter is not None:
+                result[lang] = converter.toWidgetValue(val)
+        return result
+
+    def toFieldValue(self, value):
+        # I18n widget is using a dict where each key is a lang
+        # and each value is matching widget value
+        result = {}
+        registry = self.widget.request.registry
+        for lang in self.widget.langs:
+            converter = registry.queryMultiAdapter((self.field.value_type, self.widget.get_widget(lang)),
+                                                   IDataConverter)
+            if converter is not None:
+                result[lang] = converter.toFieldValue(self.widget.get_value(lang))
+        return result
+
+
+@widgettemplate_config(mode='input', template='templates/i18n-input.pt', widget=II18nWidget, layer=IFormLayer)
+@widgettemplate_config(mode='display', template='templates/i18n-input.pt', widget=II18nWidget, layer=IFormLayer)
+@implementer_only(II18nWidget)
+class I18nWidget(HTMLInputWidget, Widget):
+    """I18n base widget"""
+
+    @reify
+    def langs(self):
+        langs = []
+        negotiator = query_utility(INegotiator)
+        if negotiator is not None:
+            langs.append(negotiator.server_language)
+        manager = get_parent(self.context, II18nManager)
+        if manager is not None:
+            langs.extend(sorted(filter(lambda x: x not in langs, manager.languages)))
+        elif negotiator is not None:
+            langs.extend(sorted(filter(lambda x: x not in langs, negotiator.offered_languages)))
+        else:
+            langs.append('en')
+        return langs
+
+    def update(self):
+        self.widgets = {}
+        for lang in self.langs:
+            widget = self.request.registry.queryMultiAdapter((self.field.value_type, self.request), IFieldWidget)
+            if widget is not None:
+                prefix = expandPrefix(self.form.prefix) + expandPrefix(self.form.widgets.prefix) + expandPrefix(lang)
+                name = self.field.value_type.__name__ = self.field.__name__
+                widget.name = prefix + name
+                widget.id = widget.name.replace('.', '-')
+                widget.form = self.form
+                widget.field = self.field.value_type
+                widget.context = self.context
+                widget.ignoreContext = self.ignoreContext
+                widget.ignoreRequest = self.ignoreRequest
+                widget.lang = lang
+                widget.update()
+            self.widgets[lang] = widget
+        super(I18nWidget, self).update()
+
+    def extract(self, default=NO_VALUE):
+        result = {}
+        [result.setdefault(lang, self.widgets[lang].extract(default)) for lang in self.widgets.keys()]
+        return result
+    
+    def get_widget(self, lang):
+        return self.widgets.get(lang)
+
+    def get_value(self, lang):
+        return self.get_widget(lang).value
+
+
+@implementer_only(II18nTextLineWidget)
+class I18nTextLineWidget(I18nWidget):
+    """I18n text line widget"""
+
+
+@adapter_config(context=(II18nTextLineField, IFormLayer), provides=IFieldWidget)
+def I18nTextLineFieldWidget(field, request):
+    """I18n text line field widget factory"""
+    return FieldWidget(field, I18nTextLineWidget(request))
+
+
+@implementer_only(II18nTextWidget)
+class I18nTextWidget(I18nWidget):
+    """I18n text widget"""
+
+
+@adapter_config(context=(II18nTextField, IFormLayer), provides=IFieldWidget)
+def I18nTextFieldWidget(field, request):
+    """I18n text field widget factory"""
+    return FieldWidget(field, I18nTextWidget(request))
+
+
+@implementer_only(II18nFileWidget)
+class I18nFileWidget(I18nWidget):
+    """I18n file widget"""
+
+
+@adapter_config(context=(II18nFileField, IFormLayer), provides=IFieldWidget)
+def I18nFileFieldWidget(field, request):
+    """I18n file field widget factory"""
+    return FieldWidget(field, I18nFileWidget(request))