[CMF-checkins] SVN: CMF/trunk/C merged yuppie-formlib branch:

Yvo Schubbe y.2006_ at wcm-solutions.de
Fri Nov 3 12:22:44 EST 2006


Log message for revision 71045:
  merged yuppie-formlib branch:
  - added some base classes and utilities for using zope.formlib in CMF
  - added formlib styles
  - replaced event views by formlib based forms
  - replaced link forms by formlib based forms
  - added EmailInputWidget

Changed:
  U   CMF/trunk/CHANGES.txt
  U   CMF/trunk/CMFCalendar/browser/configure.zcml
  U   CMF/trunk/CMFCalendar/browser/event.py
  D   CMF/trunk/CMFCalendar/browser/templates/event.pt
  D   CMF/trunk/CMFCalendar/browser/templates/event_edit.pt
  U   CMF/trunk/CMFCalendar/locales/cmf_calendar.pot
  U   CMF/trunk/CMFDefault/browser/configure.zcml
  A   CMF/trunk/CMFDefault/browser/favorite.py
  U   CMF/trunk/CMFDefault/browser/link.py
  D   CMF/trunk/CMFDefault/browser/templates/link_edit.pt
  U   CMF/trunk/CMFDefault/configure.zcml
  A   CMF/trunk/CMFDefault/formlib/
  U   CMF/trunk/CMFDefault/locales/cmf_default.pot
  U   CMF/trunk/CMFDefault/skins/zpt_generic/zpt_stylesheet.css

-=-
Modified: CMF/trunk/CHANGES.txt
===================================================================
--- CMF/trunk/CHANGES.txt	2006-11-03 17:18:51 UTC (rev 71044)
+++ CMF/trunk/CHANGES.txt	2006-11-03 17:22:43 UTC (rev 71045)
@@ -2,6 +2,11 @@
 
   New Features
 
+    - CMFDefault formlib: Added zope.formlib support.
+      This includes some CMF specific base classes and an 'EmailLine' field.
+
+    - browser views: Added some zope.formlib based forms.
+
     - CMFDefault utils: Added 'checkEmailAddress' function.
 
     - Added CMFCore.FSRestMethod:  ReST equivalent of FSSTXMethod.

Modified: CMF/trunk/CMFCalendar/browser/configure.zcml
===================================================================
--- CMF/trunk/CMFCalendar/browser/configure.zcml	2006-11-03 17:18:51 UTC (rev 71044)
+++ CMF/trunk/CMFCalendar/browser/configure.zcml	2006-11-03 17:22:43 UTC (rev 71045)
@@ -2,12 +2,18 @@
     xmlns="http://namespaces.zope.org/zope"
     xmlns:browser="http://namespaces.zope.org/browser">
 
+  <adapter factory=".event.EventSchemaAdapter"/>
+
+  <utility
+      component=".event.EventTypeVocabularyFactory"
+      name="AvailableEventTypes"
+      />
+
   <browser:page
       for="Products.CMFCalendar.interfaces.IEvent"
       layer="Products.CMFDefault.interfaces.ICMFDefaultSkin"
       name="view.html"
       class=".event.EventView"
-      template="templates/event.pt"
       permission="zope2.View"
       />
 
@@ -16,7 +22,6 @@
       layer="Products.CMFDefault.interfaces.ICMFDefaultSkin"
       name="edit.html"
       class=".event.EventEditView"
-      template="templates/event_edit.pt"
       permission="cmf.ModifyPortalContent"
       />
 

Modified: CMF/trunk/CMFCalendar/browser/event.py
===================================================================
--- CMF/trunk/CMFCalendar/browser/event.py	2006-11-03 17:18:51 UTC (rev 71044)
+++ CMF/trunk/CMFCalendar/browser/event.py	2006-11-03 17:22:43 UTC (rev 71045)
@@ -15,305 +15,161 @@
 $Id$
 """
 
-from DateTime.DateTime import DateTime
+from zope.app.form.browser import DatetimeI18nWidget
+from zope.app.schema.vocabulary import IVocabularyFactory
+from zope.component import adapts
+from zope.formlib import form
+from zope.interface import implements
+from zope.interface import Interface
+from zope.schema import Choice
+from zope.schema import Datetime
+from zope.schema import Field
+from zope.schema import Set
+from zope.schema import Tuple
+from zope.schema import Text
+from zope.schema import TextLine
+from zope.schema import URI
 
-from Products.CMFDefault.exceptions import ResourceLockedError
+from Products.CMFCore.utils import getToolByName
+from Products.CMFDefault.formlib.form import ContentEditFormBase
+from Products.CMFDefault.formlib.form import DisplayFormBase
+from Products.CMFDefault.formlib.schema import EmailLine
+from Products.CMFDefault.formlib.schema import ProxyFieldProperty
+from Products.CMFDefault.formlib.schema import SchemaAdapterBase
+from Products.CMFDefault.formlib.vocabulary import SimpleVocabulary
+
+from Products.CMFCalendar.interfaces import IMutableEvent
 from Products.CMFCalendar.utils import Message as _
 
-from Products.CMFDefault.browser.utils import decode
-from Products.CMFDefault.browser.utils import FormViewBase
-from Products.CMFDefault.browser.utils import memoize
-from Products.CMFDefault.browser.utils import ViewBase
 
+class EventTypeVocabulary(object):
 
-class EventView(ViewBase):
-
-    """View for IEvent.
+    """Vocabulary factory for available event types.
     """
 
-    # interface
+    implements(IVocabularyFactory)
 
-    @memoize
-    @decode
-    def contact_name(self):
-        return self.context.contact_name
+    def __call__(self, context):
+        context = getattr(context, 'context', context)
+        mdtool = getToolByName(context, 'portal_metadata')
+        items = [ (str(v), unicode(v), _(v))
+                  for v in mdtool.listAllowedSubjects(context) ]
+        return SimpleVocabulary.fromTitleItems(items)
 
-    @memoize
-    @decode
-    def location(self):
-        return self.context.location
+EventTypeVocabularyFactory = EventTypeVocabulary()
 
-    @memoize
-    @decode
-    def contact_email(self):
-        return self.context.contact_email
 
-    @memoize
-    @decode
-    def event_types(self):
-        return self.context.Subject()
+class IEventSchema(Interface):
 
-    @memoize
-    @decode
-    def contact_phone(self):
-        return self.context.contact_phone
-
-    @memoize
-    @decode
-    def event_url(self):
-        return self.context.event_url
-
-    @memoize
-    @decode
-    def start_date(self):
-        return DateTime(self.context.start()).Date()
-
-    @memoize
-    @decode
-    def start_time(self):
-        return DateTime(self.context.start()).Time()
-
-    @memoize
-    @decode
-    def stop_date(self):
-        return DateTime(self.context.end()).Date()
-
-    @memoize
-    @decode
-    def stop_time(self):
-        return DateTime(self.context.end()).Time()
-
-
-class EventEditView(FormViewBase):
-
-    """Edit view for IMutableEvent.
+    """Schema for event views.
     """
 
-    _BUTTONS = ({'id': 'change',
-                 'title': _(u'Change'),
-                 'transform': ('edit_control',),
-                 'redirect': ('portal_types', 'object/edit')},
-                {'id': 'change_and_view',
-                 'title': _(u'Change and View'),
-                 'transform': ('edit_control',),
-                 'redirect': ('portal_types', 'object/view')})
+    title = TextLine(
+        title=_(u'Title'),
+        required=False,
+        missing_value=u'',
+        max_length=100)
 
-    # interface
+    contact_name = TextLine(
+        title=_(u'Contact Name'),
+        required=False,
+        missing_value=u'',
+        max_length=100)
 
-    @memoize
-    @decode
-    def title(self):
-        title = self.request.form.get('title', None)
+    location = TextLine(
+        title=_(u'Location'),
+        required=False,
+        missing_value=u'',
+        max_length=100)
 
-        if title is None:
-            title = self.context.Title()
+    contact_email = EmailLine(
+        title=_(u'Contact Email'),
+        required=False)
 
-        return title
+    categories = Set(
+        title=_(u'Category'),
+        required=False,
+        missing_value=set(),
+        value_type=Choice(vocabulary="AvailableEventTypes"))
 
-    @memoize
-    @decode
-    def description(self):
-        description = self.request.form.get('description', None)
+    contact_phone = TextLine(
+        title=_(u'Contact Phone'),
+        required=False,
+        missing_value=u'',
+        max_length=100)
 
-        if description is None:
-            description = self.context.Description()
+    event_url = URI(
+        title=_(u'URL'),
+        required=False,
+        missing_value=u'',
+        max_length=100)
 
-        return description
+    start_date = Datetime(
+        title=_(u'From'),)
 
-    @memoize
-    @decode
-    def contact_name(self):
-        contact_name = self.request.form.get('contact_name', None)
+    stop_date = Datetime(
+        title=_(u'To'),)
 
-        if contact_name is None:
-            contact_name = self.context.contact_name
+    description = Text(
+        title=_(u'Description'),
+        required=False,
+        missing_value=u'')
 
-        return contact_name
 
-    @memoize
-    @decode
-    def location(self):
-        location = self.request.form.get('location', None)
+class EventSchemaAdapter(SchemaAdapterBase):
 
-        if location is None:
-            location = self.context.location
+    """Adapter for IMutableEvent.
+    """
 
-        return location
+    adapts(IMutableEvent)
+    implements(IEventSchema)
 
-    @memoize
-    @decode
-    def contact_email(self):
-        contact_email = self.request.form.get('contact_email', None)
+    title = ProxyFieldProperty(IEventSchema['title'], 'Title', 'setTitle')
+    contact_name = ProxyFieldProperty(IEventSchema['contact_name'])
+    location = ProxyFieldProperty(IEventSchema['location'])
+    contact_email = ProxyFieldProperty(IEventSchema['contact_email'])
+    categories = ProxyFieldProperty(IEventSchema['categories'],
+                                    'Subject', 'setSubject')
+    contact_phone = ProxyFieldProperty(IEventSchema['contact_phone'])
+    event_url = ProxyFieldProperty(IEventSchema['event_url'])
+    start_date = ProxyFieldProperty(IEventSchema['start_date'],
+                                    'start', 'setStartDate')
+    stop_date = ProxyFieldProperty(IEventSchema['stop_date'],
+                                   'end', 'setEndDate')
+    description = ProxyFieldProperty(IEventSchema['description'],
+                                     'Description', 'setDescription')
 
-        if contact_email is None:
-            contact_email = self.context.contact_email
 
-        return contact_email
+class EventViewMixin(object):
 
-    @memoize
-    @decode
-    def event_type(self):
-        event_type = self.request.form.get('event_type', None)
+    def setUpWidgets(self, ignore_request=False):
+        super(EventViewMixin,
+              self).setUpWidgets(ignore_request=ignore_request)
+        self.widgets['title'].split = True
+        self.widgets['contact_name'].split = True
+        self.widgets['location'].split = True
+        self.widgets['contact_email'].split = True
+        self.widgets['categories'].split = True
+        self.widgets['categories'].size = 4
+        self.widgets['contact_phone'].split = True
+        self.widgets['start_date'].split = True
+        self.widgets['stop_date'].split = True
+        self.widgets['description'].height = 5
 
-        if event_type is None:
-            event_type = self.context.Subject()
 
-        return event_type
+class EventView(EventViewMixin, DisplayFormBase):
 
-    @memoize
-    @decode
-    def contact_phone(self):
-        contact_phone = self.request.form.get('contact_phone', None)
+    """View for IEvent.
+    """
 
-        if contact_phone is None:
-            contact_phone = self.context.contact_phone
+    form_fields = form.FormFields(IEventSchema)
 
-        return contact_phone
 
-    @memoize
-    @decode
-    def event_url(self):
-        event_url = self.request.form.get('event_url', None)
+class EventEditView(EventViewMixin, ContentEditFormBase):
 
-        if event_url is None:
-            event_url = self.context.event_url
+    """Edit view for IMutableEvent.
+    """
 
-        return event_url
-
-    @memoize
-    @decode
-    def start_time(self):
-        start_string = self.request.form.get('start_time', None)
-
-        if start_string is None:
-            start_string = self.context.getStartTimeString().split()[0]
-
-        return start_string
-
-    @memoize
-    @decode
-    def startAMPM(self):
-        start_ampm = self.request.form.get('startAMPM', None)
-
-        if start_ampm is None:
-            time_strings = self.context.getStartTimeString().split()
-            start_ampm = (len(time_strings) == 2 and time_strings[1] or 'pm')
-
-        return start_ampm
-
-    @memoize
-    @decode
-    def stop_time(self):
-        stop_string = self.request.form.get('stop_time', None)
-
-        if stop_string is None:
-            stop_string = self.context.getStopTimeString().split()[0]
-
-        return stop_string
-
-    @memoize
-    @decode
-    def stopAMPM(self):
-        stop_ampm = self.request.form.get('stopAMPM', None)
-
-        if stop_ampm is None:
-            time_strings = self.context.getStopTimeString().split()
-            stop_ampm = (len(time_strings) == 2 and time_strings[1] or 'pm')
-
-        return stop_ampm
-
-    @memoize
-    @decode
-    def effectiveYear(self):
-        effective_year = self.request.form.get('effectiveYear', None)
-
-        if effective_year is None:
-            effective_year = self.context.getStartStrings()['year']
-
-        return effective_year
-
-    @memoize
-    @decode
-    def effectiveMo(self):
-        effective_month = self.request.form.get('effectiveMo', None)
-
-        if effective_month is None:
-            effective_month = self.context.getStartStrings()['month']
-
-        return effective_month
-
-    @memoize
-    @decode
-    def effectiveDay(self):
-        effective_day = self.request.form.get('effectiveDay', None)
-
-        if effective_day is None:
-            effective_day = self.context.getStartStrings()['day']
-
-        return effective_day
-
-    @memoize
-    @decode
-    def expirationYear(self):
-        expiration_year = self.request.form.get('expirationYear', None)
-
-        if expiration_year is None:
-            expiration_year = self.context.getEndStrings()['year']
-
-        return expiration_year
-
-    @memoize
-    @decode
-    def expirationMo(self):
-        expiration_month = self.request.form.get('expirationMo', None)
-
-        if expiration_month is None:
-            expiration_month = self.context.getEndStrings()['month']
-
-        return expiration_month
-
-    @memoize
-    @decode
-    def expirationDay(self):
-        expiration_day = self.request.form.get('expirationDay', None)
-
-        if expiration_day is None:
-            expiration_day = self.context.getEndStrings()['day']
-
-        return expiration_day
-
-    # controllers
-
-    def edit_control( self
-                    , title=None
-                    , description=None
-                    , event_type=None
-                    , effectiveDay=None
-                    , effectiveMo=None
-                    , effectiveYear=None
-                    , expirationDay=None
-                    , expirationMo=None
-                    , expirationYear=None
-                    , start_time=None
-                    , startAMPM=None
-                    , stop_time=None
-                    , stopAMPM=None
-                    , location=None
-                    , contact_name=None
-                    , contact_email=None
-                    , contact_phone=None
-                    , event_url=None
-                    , **kw
-                    ):
-
-        try:
-            self.context.edit( title, description, event_type, effectiveDay
-                             , effectiveMo, effectiveYear, expirationDay
-                             , expirationMo, expirationYear, start_time
-                             , startAMPM, stop_time, stopAMPM, location
-                             , contact_name, contact_email, contact_phone
-                             , event_url)
-            return True, _(u'Event changed.')
-        except ResourceLockedError, errmsg:
-            return False, errmsg
-
+    form_fields = form.FormFields(IEventSchema)
+    form_fields['start_date'].custom_widget = DatetimeI18nWidget
+    form_fields['stop_date'].custom_widget = DatetimeI18nWidget

Deleted: CMF/trunk/CMFCalendar/browser/templates/event.pt
===================================================================
--- CMF/trunk/CMFCalendar/browser/templates/event.pt	2006-11-03 17:18:51 UTC (rev 71044)
+++ CMF/trunk/CMFCalendar/browser/templates/event.pt	2006-11-03 17:22:43 UTC (rev 71045)
@@ -1,74 +0,0 @@
-<html metal:use-macro="context/@@standard_macros/page">
-<head>
-
-<metal:slot fill-slot="style_slot">
-<tal:span tal:replace="structure context/getBaseTag" />
-</metal:slot>
-
-</head>
-<body>
-
-<metal:slot metal:fill-slot="body" i18n:domain="cmf_calendar">
-
-<table class="Event" border="0" cellpadding="5" width="100%" cellspacing="3">
- <tr>
-  <th width="10%" i18n:translate="">Event Name</th>
-  <td nowrap="nowrap" tal:content="view/title">Title</td>
-  <th width="10%" i18n:translate="">Contact Name</th>
-  <td nowrap="nowrap" tal:content="view/contact_name">contact_name</td>
- </tr>
- <tr>
-  <th width="10%" i18n:translate="">Location</th>
-  <td nowrap="nowrap" tal:content="view/location">location</td>
-  <th width="10%" i18n:translate="">Contact Email</th>
-  <td nowrap="nowrap" tal:condition="view/contact_email">
-   <a tal:attributes="href string:mailto:${view/contact_email}"
-      tal:content="view/contact_email"
-      href="mailto:contact_email">contact_email</a></td>
- </tr>
- <tr>
-  <th width="10%" i18n:translate="">Event type</th>
-  <td valign="top" nowrap="nowrap"><tal:loop
-      tal:repeat="event_type view/event_types"><tal:span
-       tal:content="event_type" i18n:translate="" /> </tal:loop></td>
-  <th width="10%" i18n:translate="">Contact Phone</th>
-  <td nowrap="nowrap" tal:content="view/contact_phone">contact_phone</td>
- </tr>
- <tr tal:condition="view/event_url">
-  <th width="10%" i18n:translate="">Event URL</th>
-  <td colspan="3" nowrap="nowrap"><a href="event_url"
-     tal:attributes="href view/event_url"
-     tal:content="view/event_url">event_url</a></td>
- </tr>
- <tr>
-  <td colspan="4"><hr /></td>
- </tr>
- <tr>
-  <th width="10%" i18n:translate="">Start Date</th>
-  <td tal:content="view/start_date">start</td>
-  <th width="10%" i18n:translate="">Stop Date</th>
-  <td tal:content="view/stop_date">end</td>
- </tr>
- <tr>
-  <th width="10%" i18n:translate="">Start Time</th>
-  <td tal:content="view/start_time">start</td>
-  <th width="10%" i18n:translate="">Stop Time</th>
-  <td tal:content="view/stop_time">end</td>
- </tr>
- <tr>
-  <td colspan="4"><hr /></td>
- </tr>
- <tr>
-  <th width="10%" i18n:translate="">Description</th>
-  <td colspan="3" valign="top" nowrap="nowrap"
-     tal:content="view/description">Description</td>
- </tr>
- <tr>
-  <td colspan="4">&nbsp;</td>
- </tr>
-</table>
-
-</metal:slot>
-
-</body>
-</html>

Deleted: CMF/trunk/CMFCalendar/browser/templates/event_edit.pt
===================================================================
--- CMF/trunk/CMFCalendar/browser/templates/event_edit.pt	2006-11-03 17:18:51 UTC (rev 71044)
+++ CMF/trunk/CMFCalendar/browser/templates/event_edit.pt	2006-11-03 17:22:43 UTC (rev 71045)
@@ -1,175 +0,0 @@
-<html metal:use-macro="context/@@standard_macros/page">
-<body>
-
-<metal:slot metal:fill-slot="body" i18n:domain="cmf_calendar">
-<h1 i18n:translate="">Edit: <tal:span
-    tal:content="view/title" i18n:name="obj_title">Title</tal:span></h1>
-
-<form action="event_edit_form" method="post"
-      tal:attributes="action view/form_action">
-<table class="FormLayout">
- <tr>
-  <th i18n:translate="">Event Name</th>
-  <td>
-   <input type="text"
-      name="title" maxlength="100" size="35" value="Title"
-      tal:attributes="value view/title" />
-  </td>
-  <th i18n:translate="">Contact Name</th>
-  <td>
-   <input type="text"
-      name="contact_name" maxlength="100" size="35" value="contact_name"
-      tal:attributes="value view/contact_name" />
-  </td>
- </tr>
- <tr>
-  <th i18n:translate="">Location</th>
-  <td>
-   <input type="text"
-      name="location" maxlength="100" size="35" value="location"
-      tal:attributes="value view/location" />
-  </td>
-  <th i18n:translate="">Contact Email</th>
-  <td>
-   <input type="text"
-      name="contact_email" maxlength="100" size="35" value="contact_email"
-      tal:attributes="value view/contact_email" />
-  </td>
- </tr>
- <tr>
-  <th i18n:translate="">Event type</th>
-  <td>
-   <select name="event_type:list" multiple="multiple">
-    <option tal:replace="nothing">Event Type 1</option>
-    <option tal:replace="nothing">Event Type 2</option>
-    <option tal:replace="nothing">...</option>
-    <option value="subj"
-       tal:repeat="subj python: context.portal_metadata.listAllowedSubjects(context)"
-       tal:attributes="value subj;
-                       selected python: subj in view.event_type()"
-       tal:content="subj" i18n:translate="">Event Type N</option>
-   </select>
-  </td>
-  <th i18n:translate="">Contact Phone</th>
-  <td>
-   <input type="text" name="contact_phone" maxlength="100" size="35"
-      value="contact_phone" id="cb_contact_phone"
-      tal:attributes="value view/contact_phone" />
-  </td>
- </tr>
- <tr>
-  <th i18n:translate="">Event URL</th>
-  <td colspan="3">
-   <input type="text" name="event_url" size="55" maxlength="100"
-      value="event_url"
-      tal:attributes="value view/event_url" />
-  </td>
- </tr>
- <tr>
-  <th i18n:translate="">Start Date</th>
-  <td>
-   <select name="effectiveYear">
-    <option value=""
-       tal:repeat="year context/buildYears"
-       tal:attributes="value year;
-                       selected python: year == view.effectiveYear()"
-       tal:content="year">Year</option>
-   </select>
-   &nbsp;
-   <select name="effectiveMo">
-    <option value=""
-       tal:repeat="month context/buildMonths"
-       tal:attributes="value month;
-                       selected python: month == view.effectiveMo()"
-       tal:content="month">Month</option>
-   </select>
-   &nbsp;
-   <select name="effectiveDay">
-    <option value=""
-       tal:repeat="day context/buildDays"
-       tal:attributes="value day;
-                       selected python: day == view.effectiveDay()"
-       tal:content="day">Day</option>
-   </select>
-  </td>
-  <th i18n:translate="">Stop Date</th>
-  <td>
-   <select name="expirationYear">
-    <option value=""
-       tal:repeat="year context/buildYears"
-       tal:attributes="value year;
-                       selected python: year == view.expirationYear()"
-       tal:content="year">Day</option>
-   </select>
-   &nbsp;
-   <select name="expirationMo">
-    <option value=""
-       tal:repeat="month context/buildMonths"
-       tal:attributes="value month;
-                       selected python: month == view.expirationMo()"
-       tal:content="month">Month</option>
-   </select>
-   &nbsp;
-   <select name="expirationDay">
-    <option value=""
-       tal:repeat="day context/buildDays"
-       tal:attributes="value day;
-                       selected python: day == view.expirationDay()"
-       tal:content="day">Day</option>
-   </select>
-  </td>
- </tr>
- <tr>
-  <th i18n:translate="">Start Time</th>
-  <td>
-   <select name="start_time">
-    <option value=""
-       tal:repeat="bt context/buildTimes"
-       tal:attributes="value bt; selected python: bt == view.start_time()"
-       tal:content="bt">start time</option>
-   </select>
-   &nbsp;
-   <input type="radio" name="startAMPM" value="am" id="cb_start_am"
-      tal:attributes="checked python: view.startAMPM() == 'am'" />
-   <label for="cb_start_am" i18n:translate="">am</label>
-   <input type="radio" name="startAMPM" value="pm" id="cb_start_pm"
-      tal:attributes="checked python: view.startAMPM() == 'pm'" />
-   <label for="cb_start_pm" i18n:translate="">pm</label>
-  </td>
-  <th i18n:translate="">Stop Time</th>
-  <td>
-   <select name="stop_time">
-   <option value=""
-      tal:repeat="bt context/buildTimes"
-      tal:attributes="value bt; selected python: bt == view.stop_time()"
-      tal:content="bt">end time</option>
-   </select>
-   &nbsp;
-   <input type="radio" name="stopAMPM" value="am" id="cb_stop_am"
-      tal:attributes="checked python: view.stopAMPM() == 'am'" />
-   <label for="cb_stop_am" i18n:translate="">am</label>
-   <input type="radio" name="stopAMPM" value="pm" id="cb_stop_pm"
-      tal:attributes="checked python: view.stopAMPM() == 'pm'" />
-   <label for="cb_stop_pm" i18n:translate="">pm</label>
-  </td>
- </tr>
- <tr>
-  <th i18n:translate="">Description</th>
-  <td class="TextField" colspan="3">
-   <textarea name="description:text" rows="5" cols="70" wrap="soft"
-      tal:content="view/description"></textarea>
-  </td>
- </tr>
- <tr>
-  <td>&nbsp;</td>
-  <td colspan="3">
-   <metal:macro metal:use-macro="context/@@form_widget/buttons" />
-  </td>
- </tr>
-</table>
-</form>
-
-</metal:slot>
-
-</body>
-</html>

Modified: CMF/trunk/CMFCalendar/locales/cmf_calendar.pot
===================================================================
--- CMF/trunk/CMFCalendar/locales/cmf_calendar.pot	2006-11-03 17:18:51 UTC (rev 71044)
+++ CMF/trunk/CMFCalendar/locales/cmf_calendar.pot	2006-11-03 17:22:43 UTC (rev 71045)
@@ -12,175 +12,166 @@
 ##############################################################################
 msgid ""
 msgstr ""
-"Project-Id-Version: CMF 2.0\n"
+"Project-Id-Version: CMF 2.1\n"
 "POT-Creation-Date: $Date$\n"
 "Language-Team: CMF Developers <zope-cmf at zope.org>\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 
-#: CMFCalendar/browser/event.py:316
-#: CMFCalendar/skins/zpt_calendar/event_edit_control.py:11
-msgid "Event changed."
+#: CMFCalendar/browser/event.py:102
+msgid "URL"
 msgstr ""
 
-#: CMFCalendar/browser/event.py:93
-#: CMFCalendar/skins/zpt_calendar/event_edit_form.py:50
-msgid "Change"
+#: CMFCalendar/browser/event.py:108
+msgid "From"
 msgstr ""
 
-#: CMFCalendar/browser/event.py:97
-#: CMFCalendar/skins/zpt_calendar/event_edit_form.py:51
-msgid "Change and View"
+#: CMFCalendar/browser/event.py:111
+msgid "To"
 msgstr ""
 
-#: CMFCalendar/browser/templates/calendar_widgets.pt:13
-#: CMFCalendar/skins/zpt_calendar/calendarBox.pt:12
-msgid "CMF Calendar"
+#: CMFCalendar/browser/event.py:114
+#: CMFCalendar/skins/zpt_calendar/event_edit_template.pt:160
+#: CMFCalendar/skins/zpt_calendar/event_view_template.pt:61
+msgid "Description"
 msgstr ""
 
-#: CMFCalendar/browser/templates/calendar_widgets.pt:29
-#: CMFCalendar/browser/templates/calendar_widgets.pt:42
-#: CMFCalendar/browser/templates/event.pt:32
-#: CMFCalendar/browser/templates/event_edit.pt:46
-#: CMFCalendar/skins/zpt_calendar/calendarBox.pt:28
-#: CMFCalendar/skins/zpt_calendar/calendarBox.pt:41
-#: CMFCalendar/skins/zpt_calendar/event_edit_template.pt:49
-#: CMFCalendar/skins/zpt_calendar/event_view_template.pt:31
-msgid "${DYNAMIC_CONTENT}"
+#: CMFCalendar/browser/event.py:68
+msgid "Title"
 msgstr ""
 
-#: CMFCalendar/browser/templates/event.pt:15
-#: CMFCalendar/browser/templates/event_edit.pt:12
-#: CMFCalendar/skins/zpt_calendar/event_edit_template.pt:15
-#: CMFCalendar/skins/zpt_calendar/event_view_template.pt:14
-msgid "Event Name"
-msgstr ""
-
-#: CMFCalendar/browser/templates/event.pt:17
-#: CMFCalendar/browser/templates/event_edit.pt:18
+#: CMFCalendar/browser/event.py:74
 #: CMFCalendar/skins/zpt_calendar/event_edit_template.pt:21
 #: CMFCalendar/skins/zpt_calendar/event_view_template.pt:16
 msgid "Contact Name"
 msgstr ""
 
-#: CMFCalendar/browser/templates/event.pt:21
-#: CMFCalendar/browser/templates/event_edit.pt:26
+#: CMFCalendar/browser/event.py:80
 #: CMFCalendar/skins/zpt_calendar/event_edit_template.pt:29
 #: CMFCalendar/skins/zpt_calendar/event_view_template.pt:20
 msgid "Location"
 msgstr ""
 
-#: CMFCalendar/browser/templates/event.pt:23
-#: CMFCalendar/browser/templates/event_edit.pt:32
+#: CMFCalendar/browser/event.py:86
 #: CMFCalendar/skins/zpt_calendar/event_edit_template.pt:35
 #: CMFCalendar/skins/zpt_calendar/event_view_template.pt:22
 msgid "Contact Email"
 msgstr ""
 
-#: CMFCalendar/browser/templates/event.pt:30
-#: CMFCalendar/browser/templates/event_edit.pt:40
-#: CMFCalendar/skins/zpt_calendar/event_edit_template.pt:43
-#: CMFCalendar/skins/zpt_calendar/event_view_template.pt:29
-msgid "Event type"
+#: CMFCalendar/browser/event.py:90
+msgid "Category"
 msgstr ""
 
-#: CMFCalendar/browser/templates/event.pt:34
-#: CMFCalendar/browser/templates/event_edit.pt:53
+#: CMFCalendar/browser/event.py:96
 #: CMFCalendar/skins/zpt_calendar/event_edit_template.pt:56
 #: CMFCalendar/skins/zpt_calendar/event_view_template.pt:33
 msgid "Contact Phone"
 msgstr ""
 
-#: CMFCalendar/browser/templates/event.pt:38
-#: CMFCalendar/browser/templates/event_edit.pt:61
-#: CMFCalendar/skins/zpt_calendar/event_edit_template.pt:64
-#: CMFCalendar/skins/zpt_calendar/event_view_template.pt:37
-msgid "Event URL"
+#: CMFCalendar/browser/templates/calendar_widgets.pt:13
+#: CMFCalendar/skins/zpt_calendar/calendarBox.pt:12
+msgid "CMF Calendar"
 msgstr ""
 
-#: CMFCalendar/browser/templates/event.pt:47
-#: CMFCalendar/browser/templates/event_edit.pt:69
-#: CMFCalendar/skins/zpt_calendar/event_edit_template.pt:72
-#: CMFCalendar/skins/zpt_calendar/event_view_template.pt:46
-msgid "Start Date"
+#: CMFCalendar/browser/templates/calendar_widgets.pt:29
+#: CMFCalendar/browser/templates/calendar_widgets.pt:42
+#: CMFCalendar/skins/zpt_calendar/calendarBox.pt:28
+#: CMFCalendar/skins/zpt_calendar/calendarBox.pt:41
+#: CMFCalendar/skins/zpt_calendar/event_edit_template.pt:49
+#: CMFCalendar/skins/zpt_calendar/event_view_template.pt:31
+msgid "${DYNAMIC_CONTENT}"
 msgstr ""
 
-#: CMFCalendar/browser/templates/event.pt:49
-#: CMFCalendar/browser/templates/event_edit.pt:95
-#: CMFCalendar/skins/zpt_calendar/event_edit_template.pt:98
-#: CMFCalendar/skins/zpt_calendar/event_view_template.pt:48
-msgid "Stop Date"
+#: CMFCalendar/profiles/default/types/Event.xml:5
+msgid "Event"
 msgstr ""
 
-#: CMFCalendar/browser/templates/event.pt:53
-#: CMFCalendar/browser/templates/event_edit.pt:123
-#: CMFCalendar/skins/zpt_calendar/event_edit_template.pt:126
-#: CMFCalendar/skins/zpt_calendar/event_view_template.pt:52
-msgid "Start Time"
+#: CMFCalendar/profiles/default/types/Event.xml:6
+msgid "Events are objects for use in Calendar topical queries on the catalog."
 msgstr ""
 
-#: CMFCalendar/browser/templates/event.pt:55
-#: CMFCalendar/browser/templates/event_edit.pt:139
-#: CMFCalendar/skins/zpt_calendar/event_edit_template.pt:142
-#: CMFCalendar/skins/zpt_calendar/event_view_template.pt:54
-msgid "Stop Time"
+#: CMFCalendar/setuphandlers.py:42
+msgid "Appointment"
 msgstr ""
 
-#: CMFCalendar/browser/templates/event.pt:62
-#: CMFCalendar/browser/templates/event_edit.pt:157
-#: CMFCalendar/skins/zpt_calendar/event_edit_template.pt:160
-#: CMFCalendar/skins/zpt_calendar/event_view_template.pt:61
-msgid "Description"
+#: CMFCalendar/setuphandlers.py:43
+msgid "Convention"
 msgstr ""
 
-#: CMFCalendar/browser/templates/event_edit.pt:134
-#: CMFCalendar/browser/templates/event_edit.pt:150
+#: CMFCalendar/setuphandlers.py:44
+msgid "Meeting"
+msgstr ""
+
+#: CMFCalendar/setuphandlers.py:45
+msgid "Social Event"
+msgstr ""
+
+#: CMFCalendar/setuphandlers.py:46
+msgid "Work"
+msgstr ""
+
+#: CMFCalendar/skins/zpt_calendar/event_edit_control.py:11
+msgid "Event changed."
+msgstr ""
+
+#: CMFCalendar/skins/zpt_calendar/event_edit_form.py:50
+msgid "Change"
+msgstr ""
+
+#: CMFCalendar/skins/zpt_calendar/event_edit_form.py:51
+msgid "Change and View"
+msgstr ""
+
+#: CMFCalendar/skins/zpt_calendar/event_edit_template.pt:126
+#: CMFCalendar/skins/zpt_calendar/event_view_template.pt:52
+msgid "Start Time"
+msgstr ""
+
 #: CMFCalendar/skins/zpt_calendar/event_edit_template.pt:137
 #: CMFCalendar/skins/zpt_calendar/event_edit_template.pt:153
 msgid "am"
 msgstr ""
 
-#: CMFCalendar/browser/templates/event_edit.pt:137
-#: CMFCalendar/browser/templates/event_edit.pt:153
 #: CMFCalendar/skins/zpt_calendar/event_edit_template.pt:140
 #: CMFCalendar/skins/zpt_calendar/event_edit_template.pt:156
 msgid "pm"
 msgstr ""
 
-#: CMFCalendar/browser/templates/event_edit.pt:5
-#: CMFCalendar/skins/zpt_calendar/event_edit_template.pt:5
-msgid "Edit: ${obj_title}"
+#: CMFCalendar/skins/zpt_calendar/event_edit_template.pt:142
+#: CMFCalendar/skins/zpt_calendar/event_view_template.pt:54
+msgid "Stop Time"
 msgstr ""
 
-#: CMFCalendar/profiles/default/types/Event.xml:5
-msgid "Event"
+#: CMFCalendar/skins/zpt_calendar/event_edit_template.pt:15
+#: CMFCalendar/skins/zpt_calendar/event_view_template.pt:14
+msgid "Event Name"
 msgstr ""
 
-#: CMFCalendar/profiles/default/types/Event.xml:6
-msgid "Events are objects for use in Calendar topical queries on the catalog."
+#: CMFCalendar/skins/zpt_calendar/event_edit_template.pt:43
+#: CMFCalendar/skins/zpt_calendar/event_view_template.pt:29
+msgid "Event type"
 msgstr ""
 
-#: CMFCalendar/setuphandlers.py:42
-msgid "Appointment"
+#: CMFCalendar/skins/zpt_calendar/event_edit_template.pt:5
+msgid "Edit: ${obj_title}"
 msgstr ""
 
-#: CMFCalendar/setuphandlers.py:43
-msgid "Convention"
+#: CMFCalendar/skins/zpt_calendar/event_edit_template.pt:64
+#: CMFCalendar/skins/zpt_calendar/event_view_template.pt:37
+msgid "Event URL"
 msgstr ""
 
-#: CMFCalendar/setuphandlers.py:44
-msgid "Meeting"
+#: CMFCalendar/skins/zpt_calendar/event_edit_template.pt:72
+#: CMFCalendar/skins/zpt_calendar/event_view_template.pt:46
+msgid "Start Date"
 msgstr ""
 
-#: CMFCalendar/setuphandlers.py:45
-msgid "Social Event"
+#: CMFCalendar/skins/zpt_calendar/event_edit_template.pt:98
+#: CMFCalendar/skins/zpt_calendar/event_view_template.pt:48
+msgid "Stop Date"
 msgstr ""
 
-#: CMFCalendar/setuphandlers.py:46
-msgid "Work"
-msgstr ""
-
 msgid "Su"
 msgstr ""
 

Modified: CMF/trunk/CMFDefault/browser/configure.zcml
===================================================================
--- CMF/trunk/CMFDefault/browser/configure.zcml	2006-11-03 17:18:51 UTC (rev 71044)
+++ CMF/trunk/CMFDefault/browser/configure.zcml	2006-11-03 17:22:43 UTC (rev 71045)
@@ -65,6 +65,8 @@
       permission="cmf.ModifyPortalContent"
       />
 
+  <adapter factory=".link.LinkSchemaAdapter"/>
+
   <browser:page
       for="..interfaces.ILink"
       layer="..interfaces.ICMFDefaultSkin"
@@ -79,11 +81,20 @@
       layer="..interfaces.ICMFDefaultSkin"
       name="edit.html"
       class=".link.LinkEditView"
-      template="templates/link_edit.pt"
       permission="cmf.ModifyPortalContent"
       />
 
+  <adapter factory=".favorite.FavoriteSchemaAdapter"/>
+
   <browser:page
+      for="..interfaces.IMutableFavorite"
+      layer="..interfaces.ICMFDefaultSkin"
+      name="edit.html"
+      class=".favorite.FavoriteEditView"
+      permission="cmf.ModifyPortalContent"
+      />
+
+  <browser:page
       for="*"
       layer="..interfaces.ICMFDefaultSkin"
       name="form_widget"

Copied: CMF/trunk/CMFDefault/browser/favorite.py (from rev 71039, CMF/branches/yuppie-formlib/CMFDefault/browser/favorite.py)

Modified: CMF/trunk/CMFDefault/browser/link.py
===================================================================
--- CMF/trunk/CMFDefault/browser/link.py	2006-11-03 17:18:51 UTC (rev 71044)
+++ CMF/trunk/CMFDefault/browser/link.py	2006-11-03 17:22:43 UTC (rev 71045)
@@ -15,15 +15,49 @@
 $Id$
 """
 
-from Products.CMFDefault.exceptions import ResourceLockedError
+import urlparse
+
+from zope.app.form.browser import BytesWidget
+from zope.component import adapts
+from zope.formlib import form
+from zope.interface import implements
+from zope.interface import Interface
+from zope.schema import BytesLine
+from zope.schema import TextLine
+
+from Products.CMFDefault.formlib.form import ContentEditFormBase
+from Products.CMFDefault.formlib.schema import ProxyFieldProperty
+from Products.CMFDefault.formlib.schema import SchemaAdapterBase
+from Products.CMFDefault.interfaces import IMutableLink
 from Products.CMFDefault.utils import Message as _
 
 from utils import decode
-from utils import FormViewBase
 from utils import memoize
 from utils import ViewBase
 
 
+class ILinkSchema(Interface):
+
+    title = TextLine(
+        title=_(u'Title'),
+        description=_(u'Title'),
+        readonly=True)
+
+    remote_url = BytesLine(
+        title=_(u'URL'),
+        required=False,
+        missing_value=u'')
+
+
+class LinkSchemaAdapter(SchemaAdapterBase):
+
+    adapts(IMutableLink)
+    implements(ILinkSchema)
+
+    title = ProxyFieldProperty(ILinkSchema['title'], 'Title')
+    remote_url = ProxyFieldProperty(ILinkSchema['remote_url'])
+
+
 class LinkView(ViewBase):
 
     """View for ILink.
@@ -37,36 +71,36 @@
         return self.context.getRemoteUrl()
 
 
-class LinkEditView(FormViewBase):
+class LinkURIWidget(BytesWidget):
 
-    """Edit view for IMutableLink.
+    """Custom widget for remote_url.
     """
 
-    _BUTTONS = ({'id': 'change',
-                 'title': _(u'Change'),
-                 'transform': ('edit_control',),
-                 'redirect': ('portal_types', 'object/edit')},
-                {'id': 'change_and_view',
-                 'title': _(u'Change and View'),
-                 'transform': ('edit_control',),
-                 'redirect': ('portal_types', 'object/view')})
+    def _toFieldValue(self, input):
+        value = super(LinkURIWidget, self)._toFieldValue(input)
+        if not value:
+            return value
+        tokens = urlparse.urlparse(value, 'http')
+        if tokens[0] == 'http':
+            if tokens[1]:
+                # We have a nethost. All is well.
+                return urlparse.urlunparse(tokens)
+            elif tokens[2:] == ('', '', '', ''):
+                # Empty URL
+                return u''
+            else:
+                # Relative URL, keep it that way, without http:
+                tokens = ('', '') + tokens[2:]
+                return urlparse.urlunparse(tokens)
+        else:
+            # Other scheme, keep original
+            return urlparse.urlunparse(tokens)
 
-    # interface
 
-    @memoize
-    @decode
-    def remote_url(self):
-        return self.request.form.get('remote_url', self.context.remote_url)
+class LinkEditView(ContentEditFormBase):
 
-    # controllers
+    """Edit view for IMutableLink.
+    """
 
-    def edit_control(self, remote_url, **kw):
-        context = self.context
-        if remote_url != context.remote_url:
-            try:
-                context.edit(remote_url=remote_url)
-                return True, _(u'Link changed.')
-            except ResourceLockedError, errmsg:
-                return False, errmsg
-        else:
-            return False, _(u'Nothing to change.')
+    form_fields = form.FormFields(ILinkSchema)
+    form_fields['remote_url'].custom_widget = LinkURIWidget

Deleted: CMF/trunk/CMFDefault/browser/templates/link_edit.pt
===================================================================
--- CMF/trunk/CMFDefault/browser/templates/link_edit.pt	2006-11-03 17:18:51 UTC (rev 71044)
+++ CMF/trunk/CMFDefault/browser/templates/link_edit.pt	2006-11-03 17:22:43 UTC (rev 71045)
@@ -1,33 +0,0 @@
-<html metal:use-macro="context/@@standard_macros/page">
-<body>
-
-<metal:slot metal:fill-slot="body" i18n:domain="cmf_default">
-<h1 i18n:translate="">Edit: <tal:span
-    tal:content="view/title" i18n:name="obj_title">Title</tal:span></h1>
-
-<form action="link_edit_form" method="post"
-   tal:attributes="action view/form_action">
-<table class="FormLayout">
- <tr>
-  <th i18n:translate="">Title</th>
-  <td tal:content="view/title">Title</td>
- </tr>
- <tr>
-  <th i18n:translate="">URL</th>
-  <td>
-   <input type="text" name="remote_url" value=""
-          tal:attributes="value view/remote_url" />
-  </td>
- </tr>
- <tr>
-  <td>&nbsp;</td>
-  <td>
-   <metal:macro metal:use-macro="context/@@form_widget/buttons" />
-  </td>
- </tr>
-</table>
-</form>
-</metal:slot>
-
-</body>
-</html>

Modified: CMF/trunk/CMFDefault/configure.zcml
===================================================================
--- CMF/trunk/CMFDefault/configure.zcml	2006-11-03 17:18:51 UTC (rev 71044)
+++ CMF/trunk/CMFDefault/configure.zcml	2006-11-03 17:22:43 UTC (rev 71045)
@@ -5,6 +5,8 @@
 
   <include package=".browser"/>
 
+  <include package=".formlib"/>
+
   <include file="content.zcml"/>
 
   <include file="profiles.zcml"/>

Copied: CMF/trunk/CMFDefault/formlib (from rev 71039, CMF/branches/yuppie-formlib/CMFDefault/formlib)

Modified: CMF/trunk/CMFDefault/locales/cmf_default.pot
===================================================================
--- CMF/trunk/CMFDefault/locales/cmf_default.pot	2006-11-03 17:18:51 UTC (rev 71044)
+++ CMF/trunk/CMFDefault/locales/cmf_default.pot	2006-11-03 17:22:43 UTC (rev 71045)
@@ -12,7 +12,7 @@
 ##############################################################################
 msgid ""
 msgstr ""
-"Project-Id-Version: CMF 2.0\n"
+"Project-Id-Version: CMF 2.1\n"
 "POT-Creation-Date: $Date$\n"
 "Language-Team: CMF Developers <zope-cmf at zope.org>\n"
 "MIME-Version: 1.0\n"
@@ -20,7 +20,7 @@
 "Content-Transfer-Encoding: 8bit\n"
 
 #: CMFCore/RegistrationTool.py:144
-#: CMFDefault/RegistrationTool.py:96
+#: CMFDefault/RegistrationTool.py:94
 msgid "The login name you selected is already in use or is not valid. Please choose another."
 msgstr ""
 
@@ -30,7 +30,7 @@
 msgstr ""
 
 #: CMFCore/WorkflowTool.py:241
-# Default: ""
+#. Default: ""
 msgid "No workflow provides the '${action_id}' action."
 msgstr ""
 
@@ -40,12 +40,12 @@
 msgstr ""
 
 #: CMFCore/WorkflowTool.py:277
-# Default: ""
+#. Default: ""
 msgid "No workflow provides '${name}' information."
 msgstr ""
 
 #: CMFCore/WorkflowTool.py:292
-# Default: ""
+#. Default: ""
 msgid "Could not get info: ${name}"
 msgstr ""
 
@@ -53,42 +53,42 @@
 msgid "Intervening changes from elsewhere detected. Please refetch the document and reapply your changes. (You may be able to recover your version using the browser 'back' button, but will have to apply them to a freshly fetched copy.)"
 msgstr ""
 
-#: CMFDefault/RegistrationTool.py:101
-msgid "You must enter an email address."
-msgstr ""
-
-#: CMFDefault/RegistrationTool.py:106
-#: CMFDefault/RegistrationTool.py:115
-#: CMFDefault/RegistrationTool.py:121
+#: CMFDefault/RegistrationTool.py:104
+#: CMFDefault/RegistrationTool.py:113
+#: CMFDefault/RegistrationTool.py:119
 msgid "You must enter a valid email address."
 msgstr ""
 
-#: CMFDefault/RegistrationTool.py:135
-#: CMFDefault/RegistrationTool.py:164
+#: CMFDefault/RegistrationTool.py:133
+#: CMFDefault/RegistrationTool.py:162
 msgid "The username you entered could not be found."
 msgstr ""
 
-#: CMFDefault/RegistrationTool.py:51
-# Default: ""
+#: CMFDefault/RegistrationTool.py:49
+#. Default: ""
 msgid "No email address is registered for member: ${member_id}"
 msgstr ""
 
-#: CMFDefault/RegistrationTool.py:70
+#: CMFDefault/RegistrationTool.py:68
 msgid "You must enter a password."
 msgstr ""
 
-#: CMFDefault/RegistrationTool.py:73
+#: CMFDefault/RegistrationTool.py:71
 msgid "Your password must contain at least 5 characters."
 msgstr ""
 
-#: CMFDefault/RegistrationTool.py:76
+#: CMFDefault/RegistrationTool.py:74
 msgid "Your password and confirmation did not match. Please try again."
 msgstr ""
 
-#: CMFDefault/RegistrationTool.py:93
+#: CMFDefault/RegistrationTool.py:91
 msgid "You must enter a valid name."
 msgstr ""
 
+#: CMFDefault/RegistrationTool.py:99
+msgid "You must enter an email address."
+msgstr ""
+
 #: CMFDefault/browser/document.py:107
 #: CMFDefault/skins/zpt_content/document_edit_control.py:10
 msgid "Document changed."
@@ -99,9 +99,9 @@
 #: CMFDefault/browser/folder.py:374
 #: CMFDefault/browser/folder.py:389
 #: CMFDefault/browser/folder.py:404
-#: CMFDefault/browser/link.py:74
 #: CMFDefault/browser/metadata.py:63
 #: CMFDefault/browser/newsitem.py:53
+#: CMFDefault/formlib/form.py:144
 #: CMFDefault/skins/zpt_content/document_edit_control.py:14
 #: CMFDefault/skins/zpt_content/folder_edit_control.py:9
 #: CMFDefault/skins/zpt_content/link_edit_control.py:13
@@ -116,9 +116,9 @@
 msgstr ""
 
 #: CMFDefault/browser/document.py:49
-#: CMFDefault/browser/link.py:48
 #: CMFDefault/browser/metadata.py:34
 #: CMFDefault/browser/metadata.py:72
+#: CMFDefault/formlib/form.py:100
 #: CMFDefault/skins/zpt_content/document_edit_form.py:34
 #: CMFDefault/skins/zpt_content/file_edit_form.py:25
 #: CMFDefault/skins/zpt_content/folder_edit_form.py:24
@@ -134,9 +134,9 @@
 msgstr ""
 
 #: CMFDefault/browser/document.py:54
-#: CMFDefault/browser/link.py:52
 #: CMFDefault/browser/metadata.py:38
 #: CMFDefault/browser/metadata.py:80
+#: CMFDefault/formlib/form.py:106
 #: CMFDefault/skins/zpt_content/document_edit_form.py:35
 #: CMFDefault/skins/zpt_content/file_edit_form.py:26
 #: CMFDefault/skins/zpt_content/folder_edit_form.py:25
@@ -148,6 +148,39 @@
 msgid "Change and View"
 msgstr ""
 
+#: CMFDefault/browser/favorite.py:39
+#: CMFDefault/browser/favorite.py:40
+#: CMFDefault/browser/link.py:42
+#: CMFDefault/browser/link.py:43
+#: CMFDefault/browser/templates/document_edit.pt:13
+#: CMFDefault/browser/templates/metadata_edit.pt:34
+#: CMFDefault/browser/templates/metadata_minimal_edit.pt:12
+#: CMFDefault/browser/templates/newsitem_edit.pt:12
+#: CMFDefault/skins/zpt_content/document_edit_template.pt:16
+#: CMFDefault/skins/zpt_content/file_edit_template.pt:15
+#: CMFDefault/skins/zpt_content/folder_edit_template.pt:15
+#: CMFDefault/skins/zpt_content/image_edit_template.pt:15
+#: CMFDefault/skins/zpt_content/link_edit_template.pt:15
+#: CMFDefault/skins/zpt_content/metadata_edit_template.pt:37
+#: CMFDefault/skins/zpt_content/newsitem_edit_template.pt:15
+#: CMFDefault/skins/zpt_generic/metadata_help.pt:11
+#: CMFDefault/skins/zpt_generic/review.pt:24
+#: CMFDefault/skins/zpt_generic/search_form_template.pt:48
+#: CMFDefault/skins/zpt_generic/search_results_template.pt:15
+#: CMFTopic/skins/zpt_topic/topic_edit_template.pt:15
+msgid "Title"
+msgstr ""
+
+#: CMFDefault/browser/favorite.py:44
+#: CMFDefault/browser/link.py:47
+#: CMFDefault/skins/zpt_content/link_edit_template.pt:19
+msgid "URL"
+msgstr ""
+
+#: CMFDefault/browser/favorite.py:45
+msgid "URL relative to the site root."
+msgstr ""
+
 #: CMFDefault/browser/folder.py:193
 #: CMFDefault/skins/zpt_generic/folder_contents.py:113
 #: CMFDefault/skins/zpt_generic/metadata_help.pt:110
@@ -338,11 +371,6 @@
 msgid "Delete"
 msgstr ""
 
-#: CMFDefault/browser/link.py:70
-#: CMFDefault/skins/zpt_content/link_edit_control.py:9
-msgid "Link changed."
-msgstr ""
-
 #: CMFDefault/browser/metadata.py:61
 #: CMFDefault/browser/metadata.py:207
 #: CMFDefault/skins/zpt_content/folder_edit_control.py:7
@@ -371,69 +399,11 @@
 msgid "There are no items matching your specified criteria."
 msgstr ""
 
-#: CMFDefault/browser/templates/batch_widgets.pt:7
-#: CMFDefault/browser/templates/batch_widgets.pt:19
-#: CMFDefault/browser/templates/batch_widgets.pt:19
-#: CMFDefault/browser/templates/batch_widgets.pt:30
-#: CMFDefault/browser/templates/folder_contents.pt:42
-#: CMFDefault/browser/templates/form_widgets.pt:13
-#: CMFDefault/skins/zpt_content/content_status_history.pt:25
-#: CMFDefault/skins/zpt_content/content_status_history.pt:32
-#: CMFDefault/skins/zpt_content/transition_form.pt:26
-#: CMFDefault/skins/zpt_content/transition_form.pt:56
-#: CMFDefault/skins/zpt_generic/batch_widgets.pt:14
-#: CMFDefault/skins/zpt_generic/batch_widgets.pt:34
-#: CMFDefault/skins/zpt_generic/batch_widgets.pt:34
-#: CMFDefault/skins/zpt_generic/batch_widgets.pt:45
-#: CMFDefault/skins/zpt_generic/folder_contents_template.pt:46
-#: CMFDefault/skins/zpt_generic/folder_factories_template.pt:21
-#: CMFDefault/skins/zpt_generic/folder_factories_template.pt:26
-#: CMFDefault/skins/zpt_generic/folder_filter_form.pt:51
-#: CMFDefault/skins/zpt_generic/folder_rename_template.pt:17
-#: CMFDefault/skins/zpt_generic/form_widgets.pt:22
-#: CMFDefault/skins/zpt_generic/index_html_utils.html:32
-#: CMFDefault/skins/zpt_generic/index_html_utils.html:32
-#: CMFDefault/skins/zpt_generic/index_html_utils.html:70
-#: CMFDefault/skins/zpt_generic/index_html_utils.html:70
-#: CMFDefault/skins/zpt_generic/index_html_utils.html:106
-#: CMFDefault/skins/zpt_generic/index_html_utils.html:106
-#: CMFDefault/skins/zpt_generic/join_template.pt:5
-#: CMFDefault/skins/zpt_generic/main_template.pt:71
-#: CMFDefault/skins/zpt_generic/main_template.pt:118
-#: CMFDefault/skins/zpt_generic/main_template.pt:157
-#: CMFDefault/skins/zpt_generic/main_template.pt:175
-#: CMFDefault/skins/zpt_generic/main_template.pt:201
-#: CMFDefault/skins/zpt_generic/main_template.pt:207
-#: CMFDefault/skins/zpt_generic/main_template.pt:221
-#: CMFDefault/skins/zpt_generic/main_template.pt:235
-#: CMFDefault/skins/zpt_generic/main_template.pt:269
-#: CMFDefault/skins/zpt_generic/review.pt:55
-#: CMFDefault/skins/zpt_generic/roster.pt:43
-#: CMFDefault/skins/zpt_generic/search_results_template.pt:35
-#: CMFDefault/skins/zpt_generic/synPropertiesForm_template.pt:66
+#: CMFDefault/browser/templates/batch_widgets.pt:41
+#: CMFDefault/browser/templates/batch_widgets.pt:47
 msgid "${DYNAMIC_CONTENT}"
 msgstr ""
 
-#: CMFDefault/browser/templates/document_edit.pt:13
-#: CMFDefault/browser/templates/link_edit.pt:12
-#: CMFDefault/browser/templates/metadata_edit.pt:34
-#: CMFDefault/browser/templates/metadata_minimal_edit.pt:12
-#: CMFDefault/browser/templates/newsitem_edit.pt:12
-#: CMFDefault/skins/zpt_content/document_edit_template.pt:16
-#: CMFDefault/skins/zpt_content/file_edit_template.pt:15
-#: CMFDefault/skins/zpt_content/folder_edit_template.pt:15
-#: CMFDefault/skins/zpt_content/image_edit_template.pt:15
-#: CMFDefault/skins/zpt_content/link_edit_template.pt:15
-#: CMFDefault/skins/zpt_content/metadata_edit_template.pt:37
-#: CMFDefault/skins/zpt_content/newsitem_edit_template.pt:15
-#: CMFDefault/skins/zpt_generic/metadata_help.pt:11
-#: CMFDefault/skins/zpt_generic/review.pt:24
-#: CMFDefault/skins/zpt_generic/search_form_template.pt:48
-#: CMFDefault/skins/zpt_generic/search_results_template.pt:15
-#: CMFTopic/skins/zpt_topic/topic_edit_template.pt:15
-msgid "Title"
-msgstr ""
-
 #: CMFDefault/browser/templates/document_edit.pt:17
 #: CMFDefault/browser/templates/metadata_edit.pt:41
 #: CMFDefault/browser/templates/metadata_minimal_edit.pt:19
@@ -485,7 +455,6 @@
 msgstr ""
 
 #: CMFDefault/browser/templates/document_edit.pt:5
-#: CMFDefault/browser/templates/link_edit.pt:5
 #: CMFDefault/browser/templates/metadata_minimal_edit.pt:5
 #: CMFDefault/browser/templates/newsitem_edit.pt:5
 #: CMFDefault/skins/zpt_content/document_edit_template.pt:5
@@ -548,11 +517,6 @@
 msgid "Link: ${link}"
 msgstr ""
 
-#: CMFDefault/browser/templates/link_edit.pt:16
-#: CMFDefault/skins/zpt_content/link_edit_template.pt:19
-msgid "URL"
-msgstr ""
-
 #: CMFDefault/browser/templates/metadata_edit.pt:101
 #: CMFDefault/skins/zpt_content/metadata_edit_template.pt:104
 #: CMFDefault/skins/zpt_generic/metadata_help.pt:199
@@ -638,38 +602,53 @@
 msgid "Body"
 msgstr ""
 
-#: CMFDefault/browser/utils.py:274
+#: CMFDefault/browser/utils.py:273
 msgid "Previous item"
 msgstr ""
 
-#: CMFDefault/browser/utils.py:276
-# Default: ""
+#: CMFDefault/browser/utils.py:275
+#. Default: ""
 msgid "Previous ${count} items"
 msgstr ""
 
-#: CMFDefault/browser/utils.py:288
+#: CMFDefault/browser/utils.py:287
 msgid "Next item"
 msgstr ""
 
-#: CMFDefault/browser/utils.py:290
-# Default: ""
+#: CMFDefault/browser/utils.py:289
+#. Default: ""
 msgid "Next ${count} items"
 msgstr ""
 
-#: CMFDefault/browser/utils.py:301
+#: CMFDefault/browser/utils.py:300
 #: CMFDefault/skins/zpt_generic/search.py:47
 msgid "item"
 msgstr ""
 
-#: CMFDefault/browser/utils.py:301
+#: CMFDefault/browser/utils.py:300
 #: CMFDefault/skins/zpt_generic/search.py:47
 msgid "items"
 msgstr ""
 
 #: CMFDefault/exceptions.py:68
+#: CMFDefault/formlib/widgets.py:41
 msgid "Invalid email address."
 msgstr ""
 
+#: CMFDefault/formlib/form.py:123
+#. Default: ""
+msgid "Edit ${obj_type}"
+msgstr ""
+
+#: CMFDefault/formlib/form.py:127
+msgid "This resource is locked via webDAV."
+msgstr ""
+
+#: CMFDefault/formlib/form.py:141
+#. Default: ""
+msgid "${obj_type} changed."
+msgstr ""
+
 #: CMFDefault/profiles/default/actions.xml:10
 #: CMFDefault/skins/zpt_generic/login_form.pt:44
 msgid "Login"
@@ -1016,6 +995,10 @@
 msgid "Upload image"
 msgstr ""
 
+#: CMFDefault/skins/zpt_content/link_edit_control.py:9
+msgid "Link changed."
+msgstr ""
+
 #: CMFDefault/skins/zpt_content/transition_form.pt:11
 msgid "Transition of ${objectid}."
 msgstr ""
@@ -1124,20 +1107,15 @@
 msgid "Please select a content type."
 msgstr ""
 
+#: CMFDefault/skins/zpt_generic/batch_widgets.pt:70
+#: CMFDefault/skins/zpt_generic/batch_widgets.pt:81
+msgid "${DYNAMIC_CONTENT} ${count} ${DYNAMIC_CONTENT}"
+msgstr ""
+
 #: CMFDefault/skins/zpt_generic/breadcrumbs.py:13
 msgid "root"
 msgstr ""
 
-#: CMFDefault/skins/zpt_generic/content_byline.pt:14
-#: CMFDefault/skins/zpt_generic/recent_news_template.pt:29
-msgid "and"
-msgstr ""
-
-#: CMFDefault/skins/zpt_generic/content_byline.pt:22
-#: CMFDefault/skins/zpt_generic/recent_news_template.pt:32
-msgid "unknown"
-msgstr ""
-
 #: CMFDefault/skins/zpt_generic/content_byline.pt:23
 msgid "Last modified"
 msgstr ""
@@ -1599,7 +1577,7 @@
 msgstr ""
 
 #: CMFDefault/skins/zpt_generic/password_email.py:18
-# Default: ""
+#. Default: ""
 msgid "${portal_title}: Membership reminder"
 msgstr ""
 
@@ -1768,7 +1746,7 @@
 msgstr ""
 
 #: CMFDefault/skins/zpt_generic/registered_email.py:31
-# Default: ""
+#. Default: ""
 msgid "${portal_title}: Your Membership Information"
 msgstr ""
 
@@ -2027,6 +2005,18 @@
 msgid "Max Syndicated Items"
 msgstr ""
 
+#: CMFDefault/skins/zpt_generic/talkback_tree.pt:26
+msgid "and"
+msgstr ""
+
+#: CMFDefault/skins/zpt_generic/talkback_tree.pt:29
+msgid "unknown"
+msgstr ""
+
+#: CMFDefault/skins/zpt_generic/talkback_tree.pt:32
+msgid "delete reply"
+msgstr ""
+
 #: CMFDefault/skins/zpt_generic/undo_form.pt:107
 msgid "There are no transactions that can be undone."
 msgstr ""
@@ -2072,17 +2062,17 @@
 msgstr ""
 
 #: CMFDefault/utils.py:329
-# Default: ""
+#. Default: ""
 msgid "JavaScript event '${attribute}' not allowed."
 msgstr ""
 
 #: CMFDefault/utils.py:334
-# Default: ""
+#. Default: ""
 msgid "JavaScript URI '${value}' not allowed."
 msgstr ""
 
 #: CMFDefault/utils.py:347
-# Default: ""
+#. Default: ""
 msgid "Dynamic tag '${tag}' not allowed."
 msgstr ""
 
@@ -2119,12 +2109,12 @@
 msgstr ""
 
 #: DCWorkflow/DCWorkflow.py:285
-# Default: ""
+#. Default: ""
 msgid "Transition '${action_id}' is not triggered by a user action."
 msgstr ""
 
 #: DCWorkflow/DCWorkflow.py:468
-# Default: ""
+#. Default: ""
 msgid "Destination state undefined: ${state_id}"
 msgstr ""
 

Modified: CMF/trunk/CMFDefault/skins/zpt_generic/zpt_stylesheet.css
===================================================================
--- CMF/trunk/CMFDefault/skins/zpt_generic/zpt_stylesheet.css	2006-11-03 17:18:51 UTC (rev 71044)
+++ CMF/trunk/CMFDefault/skins/zpt_generic/zpt_stylesheet.css	2006-11-03 17:22:43 UTC (rev 71045)
@@ -437,3 +437,38 @@
 .FormButtons {
     margin-top: 8pt;
 }
+
+.form            { width: 720px; background-color: #efef8f; }
+.widgets         { width: 720px; float: left; }
+.widget          { width: 720px; float: left; margin-top: 6px;
+                   min-height: 30px; height: auto !important; height: 30px;
+                   font-family: sans-serif; font-size: 90%;
+                   background-color: #efefef; }
+.widget.split    { width: 360px; }
+.widget label    { width: 108px; float: left; padding: 0 4px;
+                   min-height: 17px; height: auto !important; height: 17px;
+                   text-align: right; font-size: 80%; font-weight: bold; }
+.widget .field   { width: 604px; float: left;
+                   font-family: inherit; font-size: inherit; }
+.widget.split .field { width: 244px; }
+.widget .data    { width: 600px; padding: 0 2px;
+                   min-height: 30px; height: auto !important; height: 30px;
+                   background-color: #ffffff; }
+.widget.split .data { width: 240px; }
+.widget input.textType, .widget select, .widget textarea {
+                   width: 596px; margin: 0 -2px; padding: 0 2px;
+                   font-family: inherit; font-size: inherit; }
+.widget select   { padding: 0 }
+.widget input.textType {
+                   min-height: 30px; height: auto !important; height: 24px; }
+.widget.split input.textType { width: 236px; }
+.widget.split select { width: 244px; }
+.widget ul       { margin: 0 0 0 10px; padding: 0 0 0 10px;
+                   list-style-type: disc; }
+.widget .error   { display: block;
+                   font-size: 80%; font-weight: bold; color: red; }
+.errors          { font-family: sans-serif;
+                   font-size: 72%; font-weight: bold; color: red; }
+.clear           { clear: both; padding-top: 6px; }
+.buttons         { min-width: 604px; margin: 0 0 0 116px; }
+.button          { margin-bottom: 6px; }



More information about the CMF-checkins mailing list