Back to index

plone3  3.1.7
widgets.py
Go to the documentation of this file.
00001 from zope.app.form.browser import MultiSelectWidget
00002 from zope.app.form.browser import DropdownWidget
00003 from zope.app.form.browser.widget import renderElement
00004 from zope.component import getMultiAdapter
00005 from zope.component import queryMultiAdapter
00006 from zope.schema.interfaces import ITitledTokenizedTerm
00007 from zope.schema.vocabulary import SimpleTerm
00008 from zope.schema.vocabulary import SimpleVocabulary
00009 
00010 from Products.CMFCore.utils import getToolByName
00011 from Products.CMFPlone import PloneMessageFactory as _
00012 from plone.app.form.widgets import MultiCheckBoxWidget
00013 
00014 WEEKDAYS = (('Monday', 0),
00015             ('Tuesday', 1),
00016             ('Wednesday', 2),
00017             ('Thursday', 3),
00018             ('Friday', 4),
00019             ('Saturday', 5),
00020             ('Sunday', 6))
00021 
00022 
00023 class DropdownChoiceWidget(DropdownWidget):
00024     """ """
00025 
00026     def __init__(self, field, request):
00027         """Initialize the widget."""
00028         super(DropdownChoiceWidget, self).__init__(field,
00029             field.vocabulary, request)
00030 
00031 
00032 class MultiCheckBoxVocabularyWidget(MultiCheckBoxWidget):
00033     """ """
00034 
00035     def __init__(self, field, request):
00036         """Initialize the widget."""
00037         super(MultiCheckBoxVocabularyWidget, self).__init__(field,
00038             field.value_type.vocabulary, request)
00039 
00040 
00041 class MultiCheckBoxColumnsWidget(MultiCheckBoxWidget):
00042     """ """
00043 
00044     how_many_columns = 2   # two by default
00045 
00046     def __init__(self, field, request):
00047         """Initialize the widget."""
00048         super(MultiCheckBoxColumnsWidget, self).__init__(field,
00049             field.value_type.vocabulary, request)
00050 
00051     def renderItemsWithValues(self, values):
00052         """Render the list of possible values, with those found in
00053         `values` being marked as selected.
00054 
00055         This code is mostly taken from from zope.app.form.browser.itemswidgets
00056         import ItemsEditWidgetBase licensed under the ZPL 2.1.
00057         """
00058 
00059         cssClass = self.cssClass
00060 
00061         # multiple items with the same value are not allowed from a
00062         # vocabulary, so that need not be considered here
00063         rendered_items = []
00064         count = 0
00065 
00066         # XXX remove the inline styles!
00067         rendered_items.append('<div style="float:left; margin-right: 2em;">')
00068 
00069         # Handle case of missing value
00070         missing = self._toFormValue(self.context.missing_value)
00071 
00072         if self._displayItemForMissingValue and not self.context.required:
00073             if missing in values:
00074                 render = self.renderSelectedItem
00075             else:
00076                 render = self.renderItem
00077 
00078             missing_item = render(count,
00079                 self.translate(self._messageNoValue),
00080                 missing,
00081                 self.name,
00082                 cssClass)
00083             rendered_items.append(missing_item)
00084             count += 1
00085 
00086         length = len(self.vocabulary)
00087         cc = self.how_many_columns
00088         breaks = [ length % cc == 0 and length / cc or length / cc + 1 ]
00089         for b in range(2, cc):
00090             breaks.append(breaks[0] * b)
00091 
00092         # Render normal values
00093         for term in self.vocabulary:
00094             item_text = self.textForValue(term)
00095 
00096             if term.value in values:
00097                 render = self.renderSelectedItem
00098             else:
00099                 render = self.renderItem
00100 
00101             rendered_item = render(count,
00102                 item_text,
00103                 term.token,
00104                 self.name,
00105                 cssClass)
00106 
00107             rendered_items.append(rendered_item)
00108             count += 1
00109 
00110             if count in breaks:
00111                 rendered_items.append('</div><div style="float:left; '
00112                                       'margin-right: 2em;">')
00113 
00114         rendered_items.append('</div><div style="clear:both">&nbsp;</div>')
00115 
00116         return rendered_items
00117 
00118 
00119 class MultiCheckBoxThreeColumnWidget(MultiCheckBoxColumnsWidget):
00120     """ """
00121     how_many_columns = 3
00122 
00123 
00124 class LanguageTableWidget(MultiCheckBoxWidget):
00125     """ """
00126 
00127     _joinButtonToMessageTemplate = u"""<tr class="%s">
00128 <td>%s</td><td>%s</td><td>%s</td>
00129 </tr>"""
00130 
00131     _table_start_template = u"""
00132 <table summary="%s"
00133        class="listing"
00134        id="lang-selection"
00135        style="display: block; height: 20em; width: 50em; overflow: auto;">
00136     <thead>
00137         <tr>
00138             <th class="nosort">%s</th>
00139             <th>%s</th>
00140             <th>%s</th>
00141         </tr>
00142     </thead>
00143     <tbody>
00144     """
00145 
00146     _table_end_template = u"""</tbody></table>"""
00147 
00148     def associateLabelWithInputControl(self):
00149         return None
00150     
00151     def __init__(self, field, request):
00152         """Initialize the widget."""
00153         super(LanguageTableWidget, self).__init__(field,
00154             field.value_type.vocabulary, request)
00155         # TODO: This is a bit hairy, but seems to work fine.
00156         context = self.context.context.context
00157         portal_state = queryMultiAdapter((context, request),
00158                                          name=u'plone_portal_state')
00159         self.languages = portal_state.locale().displayNames.languages
00160         self.territories = portal_state.locale().displayNames.territories
00161 
00162     def renderValue(self, value):
00163         return ''.join(self.renderItems(value))
00164 
00165     def renderItemsWithValues(self, values):
00166         """Render the list of possible values, with those found in
00167         `values` being marked as selected.
00168 
00169         This code is mostly taken from from zope.app.form.browser.itemswidgets
00170         import ItemsEditWidgetBase licensed under the ZPL 2.1.
00171         """
00172 
00173         cssClass = self.cssClass
00174 
00175         # multiple items with the same value are not allowed from a
00176         # vocabulary, so that need not be considered here
00177         rendered_items = []
00178         count = 0
00179 
00180         rendered_items.append(self._table_start_template % (
00181             self.translate(_(u'heading_allowed_languages',
00182                              default=u'Allowed languages')),
00183             self.translate(_(u'heading_language_allowed',
00184                              default=u'Allowed?')),
00185             self.translate(_(u'heading_language',
00186                              default=u'Language')),
00187             self.translate(_(u'heading_language_code',
00188                              default=u'Code'))
00189             ))
00190 
00191         # Handle case of missing value
00192         missing = self._toFormValue(self.context.missing_value)
00193 
00194         if self._displayItemForMissingValue and not self.context.required:
00195             if missing in values:
00196                 render = self.renderSelectedItem
00197             else:
00198                 render = self.renderItem
00199 
00200             missing_item = render(count,
00201                 self.translate(self._messageNoValue),
00202                 missing,
00203                 self.name,
00204                 cssClass)
00205             rendered_items.append(missing_item)
00206             count += 1
00207 
00208         # Render normal values
00209         vocabulary = [(self.textForValue(term), term) for
00210                       term in self.vocabulary]
00211 
00212         # Sort by translated name, this is lame and needs proper collation
00213         # support, but we don't have that yet.
00214         vocabulary.sort()
00215 
00216         for item_text, term in vocabulary:
00217             if term.value in values:
00218                 render = self.renderSelectedItem
00219             else:
00220                 render = self.renderItem
00221 
00222             css = count % 2 and cssClass + 'even' or cssClass + 'odd'
00223             rendered_item = render(count,
00224                 item_text,
00225                 term.token,
00226                 self.name,
00227                 css)
00228 
00229             rendered_items.append(rendered_item)
00230             count += 1
00231 
00232         rendered_items.append(self._table_end_template)
00233 
00234         return rendered_items
00235 
00236     def renderItem(self, index, text, value, name, cssClass):
00237         id = '%s.%s' % (name, index)
00238         elem = renderElement('input',
00239                              type="checkbox",
00240                              cssClass=cssClass,
00241                              name=name,
00242                              id=id,
00243                              value=value)
00244         return self._joinButtonToMessageTemplate % (cssClass, elem, text, value)
00245     
00246     def renderSelectedItem(self, index, text, value, name, cssClass):
00247         id = '%s.%s' % (name, index)
00248         elem = renderElement('input',
00249                              type="checkbox",
00250                              cssClass=cssClass,
00251                              name=name,
00252                              id=id,
00253                              value=value,
00254                              checked="checked")
00255         return self._joinButtonToMessageTemplate % (cssClass, elem, text, value)
00256 
00257     def textForValue(self, term):
00258         """Extract a string from the `term`.
00259 
00260         The `term` must be a vocabulary tokenized term.
00261         """
00262         if ITitledTokenizedTerm.providedBy(term):
00263             if '-' in term.value:
00264                 code, territory = term.value.split('-')
00265                 territory = territory.upper()
00266                 result = self.languages.get(code, None)
00267                 # If we don't have a translation for the language, return the
00268                 # English one and don't bother with the country name
00269                 if result is None or result == code:
00270                     return term.title
00271                 territory = self.territories.get(territory, territory)
00272                 result = "%s (%s)" % (result, territory)
00273             else:
00274                 result = self.languages.get(term.value, None)
00275                 # If we don't have a translation for the language, return the
00276                 # default English text, rather than the language code
00277                 if result is None or result == term.value:
00278                     return term.title
00279             return result
00280         return term.token
00281 
00282 
00283 class MultiSelectTupleWidget(MultiSelectWidget):
00284     """Provide a selection list for the tuple to be selected."""
00285 
00286     def _toFieldValue(self, input):
00287         value = super(MultiSelectWidget, self)._toFieldValue(input)
00288         if isinstance(value, list):
00289             value = tuple(value)
00290         return value
00291 
00292 
00293 def WeekdayWidget(field, request):
00294     """A widget for the selection of weekdays."""
00295     weekdays = WEEKDAYS
00296     locale = None
00297     context = getattr(field, 'context', None)
00298     if context is not None:
00299         context = getattr(context, 'context', None)
00300         if context is not None:
00301             portal_state = getMultiAdapter((context, request),
00302                                            name=u'plone_portal_state')
00303             locale = portal_state.locale()
00304     if locale is not None:
00305         # We probably shouldn't assume a gregorian calendar here, but the rest
00306         # of our stack doesn't support anything else anyways for now.
00307         gregorian = locale.dates.calendars.get('gregorian')
00308         weekdays = tuple(zip(gregorian.getDayNames(), range(0, 8)))
00309 
00310     terms = [SimpleTerm(item[1], title=item[0]) for item in weekdays]
00311     return DropdownWidget(field, SimpleVocabulary(terms), request)
00312 
00313 
00314 class AllowedTypesWidget(MultiCheckBoxWidget):
00315     """ A widget for activating and deactivating mimetypes with special
00316         considerations for types
00317         whose transformation is not installed locally.
00318 
00319         a format can have the following states:
00320 
00321          1. active (i.e. selected and deselectable)
00322          2. inactive (i.e. not selected but selectable)
00323          3. deactivated (i.e. not selected and not selectable)
00324          4. default (i.e. selected and not deselectable)
00325 
00326         TODO:
00327          * computation of state for each format
00328          * rendering of those states
00329     """
00330 
00331     def __init__(self, field, request):
00332         """Initialize the widget."""
00333         super(AllowedTypesWidget, self).__init__(field,
00334             field.value_type.vocabulary, request)
00335