[Checkins] SVN: Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/ Added wizard and spreadsheet

Darryl Cousins darryl at darrylcousins.net.nz
Sun Jul 8 06:35:21 EDT 2007


Log message for revision 77608:
  Added wizard and spreadsheet

Changed:
  U   Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/browser/index.pt
  U   Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/configure.zcml
  U   Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/message/README.txt
  A   Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/message/message.txt
  U   Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/questionnaire/README.txt
  U   Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/questionnaire/questionnaire.py
  A   Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/questionnaire/questionnaire.txt
  A   Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/spreadsheet/
  A   Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/spreadsheet/README.txt
  A   Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/spreadsheet/__init__.py
  A   Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/spreadsheet/candidate.py
  A   Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/spreadsheet/spreadsheet.css
  A   Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/spreadsheet/spreadsheet.pt
  A   Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/spreadsheet/spreadsheet.py
  A   Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/spreadsheet/spreadsheet.txt
  U   Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/tests.py
  U   Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/widgets/README.txt
  U   Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/widgets/widgets.py
  A   Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/widgets/widgets.txt
  A   Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/wizard/
  A   Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/wizard/README.txt
  A   Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/wizard/__init__.py
  A   Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/wizard/images/
  A   Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/wizard/images/breadcrumb.jpg
  A   Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/wizard/images/breadcrumb_active.jpg
  A   Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/wizard/images/buttonLeftBG.gif
  A   Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/wizard/images/buttonRightBG.gif
  A   Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/wizard/step.pt
  A   Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/wizard/summary.pt
  A   Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/wizard/wizard.css
  A   Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/wizard/wizard.pt
  A   Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/wizard/wizard.py
  A   Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/wizard/wizard.txt

-=-
Modified: Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/browser/index.pt
===================================================================
--- Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/browser/index.pt	2007-07-08 07:53:54 UTC (rev 77607)
+++ Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/browser/index.pt	2007-07-08 10:35:18 UTC (rev 77608)
@@ -1,4 +1,4 @@
-<h1>Z3C form demos</h1>
+<h1>Z3C form demos (grokked)</h1>
 
 <div class="demo">
   <h4>Div based layout</h4>
@@ -25,5 +25,23 @@
     <a href="../++skin++marstableformdemo/questionnaireResults">Questionnaire</a>
   </div>
 
+  <h4>Advanced Demos</h4>
+  <div>
+    <a href="../++skin++marsformdemo/calculator.html">Calculator</a>
+  </div>
+  <div>
+    <a href="../++skin++marsformdemo/wizard.html">Wizard</a>
+  </div>
+  <div>
+    <a href="../++skin++marsformdemo/spreadsheet.html">Spreadsheet</a>
+  </div>
+  <div>
+    <a href="../++skin++marsformdemo/addressbook.html">Address Book</a>
+  </div>
+  <div>
+    <a href="../++skin++marsformdemo/showAllSQLHelloWorld.html">
+      SQL Hello World
+    </a>
+  </div>
 </div>
 

Modified: Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/configure.zcml
===================================================================
--- Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/configure.zcml	2007-07-08 07:53:54 UTC (rev 77607)
+++ Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/configure.zcml	2007-07-08 10:35:18 UTC (rev 77608)
@@ -15,9 +15,5 @@
     </resourceLibrary>
   </configure>
 
-  <adapter
-      factory=".widgets.widgets.getAllFields"
-      />
-
 </configure>
 

Modified: Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/message/README.txt
===================================================================
--- Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/message/README.txt	2007-07-08 07:53:54 UTC (rev 77607)
+++ Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/message/README.txt	2007-07-08 10:35:18 UTC (rev 77608)
@@ -5,87 +5,4 @@
 The "Hello World Message" demo is intended to demonstrate the most minimal
 setup required to get add, edit and display to work.
 
-To start, we need to open a browser and go to the demo applications overview
-screen:
-
-  >>> from mars.formdemo import testing
-  >>> from z3c.etestbrowser.testing import ExtendedTestBrowser
-  >>> user = ExtendedTestBrowser()
-  >>> user.handleErrors = False
-  >>> user.addHeader('Accept-Language', 'en')
-  >>> user.open('http://localhost:8080')
-  >>> skinURL = 'http://localhost:8080/++skin++marsformdemo'
-
-Since all demos are purely public, there is no need to log in. Let's now click
-on the "Hello World" link:
-
-  >>> user.open(skinURL + '/addHelloWorld')
-
-You are now represented with the message add form.
-
-If we submit the form by clicking on add, ...
-
-  >>> user.getControl('Add').click()
-
-... the same page returns telling us we have some errors:
-
-  >>> testing.printElement(user, "//div[@class='summary']")
-  <div class="summary">There were some errors.</div>
-
-This is because we forgot to enter the "Who" field, which is required:
-
-  >>> testing.printElement(user, "//ul[@class='errors']/li")
-  <li>
-     Who: <div class="error">Required input is missing.</div>
-  </li>
-
-Let's now fill out all the required fields and try to add the message again:
-
-  >>> user.getControl('Who').value = u'Stephan'
-  >>> user.getControl('When').value = u'7/1/07'
-  >>> user.getControl('Add').click()
-
-Once submitted, the message is now added to the database and the display view
-is shown:
-
-  >>> testing.printElement(user, "//h1")
-  <h1>
-    A cool Hello World from Stephan on 7/1/07 !
-  </h1>
-
-The message's edit form can be accessed by clicking on the "Edit Message"
-link:
-
-  >>> user.getLink('Edit Message').click()
-
-When immediately pressing "Apply", a message appears telling us that no data
-has been changed:
-
-  >>> user.getControl('Apply', index=0).click()
-  >>> testing.printElement(user, "//div[@class='summary']")
-  <div class="summary">No changes were applied.</div>
-
-Let's now change the name and submit the form:
-
-  >>> user.getControl('Who').value = u'Roger'
-  >>> user.getControl('Apply', index=0).click()
-
-The page now informs us that the data has been updated:
-
-  >>> testing.printElement(user, "//div[@class='summary']")
-  <div class="summary">Data successfully updated.</div>
-
-When pressing the "Apply and View" button, the changed data is stored and the
-user is also forwarded to the view page again:
-
-  >>> user.getControl('What').getControl('best').click()
-  >>> user.getControl('Apply and View').click()
-
-Of course, the view shows the latest data:
-
-  >>> testing.printElement(user, "//h1")
-  <h1>
-    A best Hello World from Roger on 7/1/07 !
-  </h1>
-
-
+The original doctest is ./message.py.

Added: Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/message/message.txt
===================================================================
--- Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/message/message.txt	                        (rev 0)
+++ Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/message/message.txt	2007-07-08 10:35:18 UTC (rev 77608)
@@ -0,0 +1,92 @@
+========================
+Hello World Message Demo
+========================
+
+The "Hello World Message" demo is intended to demonstrate the most minimal
+setup required to get add, edit and display to work.
+
+To start, we need to open a browser and go to the demo applications overview
+screen:
+
+  >>> from mars.formdemo import testing
+  >>> from z3c.etestbrowser.testing import ExtendedTestBrowser
+  >>> user = ExtendedTestBrowser()
+  >>> user.handleErrors = False
+  >>> user.addHeader('Accept-Language', 'en')
+  >>> user.open('http://localhost:8080')
+  >>> skinURL = 'http://localhost:8080/++skin++marsformdemo'
+
+Since all demos are purely public, there is no need to log in. Let's now click
+on the "Hello World" link:
+
+  >>> user.open(skinURL + '/addHelloWorld')
+
+You are now represented with the message add form.
+
+If we submit the form by clicking on add, ...
+
+  >>> user.getControl('Add').click()
+
+... the same page returns telling us we have some errors:
+
+  >>> testing.printElement(user, "//div[@class='summary']")
+  <div class="summary">There were some errors.</div>
+
+This is because we forgot to enter the "Who" field, which is required:
+
+  >>> testing.printElement(user, "//ul[@class='errors']/li")
+  <li>
+     Who: <div class="error">Required input is missing.</div>
+  </li>
+
+Let's now fill out all the required fields and try to add the message again:
+
+  >>> user.getControl('Who').value = u'Stephan'
+  >>> user.getControl('When').value = u'7/1/07'
+  >>> user.getControl('Add').click()
+
+Once submitted, the message is now added to the database and the display view
+is shown:
+
+  >>> testing.printElement(user, "//h1")
+  <h1>
+    A cool Hello World from Stephan on 7/1/07 !
+  </h1>
+
+The message's edit form can be accessed by clicking on the "Edit Message"
+link:
+
+  >>> user.getLink('Edit Message').click()
+
+When immediately pressing "Apply", a message appears telling us that no data
+has been changed:
+
+  >>> user.getControl('Apply', index=0).click()
+  >>> testing.printElement(user, "//div[@class='summary']")
+  <div class="summary">No changes were applied.</div>
+
+Let's now change the name and submit the form:
+
+  >>> user.getControl('Who').value = u'Roger'
+  >>> user.getControl('Apply', index=0).click()
+
+The page now informs us that the data has been updated:
+
+  >>> testing.printElement(user, "//div[@class='summary']")
+  <div class="summary">Data successfully updated.</div>
+
+When pressing the "Apply and View" button, the changed data is stored and the
+user is also forwarded to the view page again:
+
+  >>> user.getControl('What').getControl('best').click()
+  >>> user.getControl('Apply and View').click()
+
+Of course, the view shows the latest data:
+
+  >>> testing.printElement(user, "//h1")
+  <h1>
+    A best Hello World from Roger on 7/1/07 !
+  </h1>
+
+
+


Property changes on: Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/message/message.txt
___________________________________________________________________
Name: svn:keywords
   + Date Author

Modified: Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/questionnaire/README.txt
===================================================================
--- Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/questionnaire/README.txt	2007-07-08 07:53:54 UTC (rev 77607)
+++ Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/questionnaire/README.txt	2007-07-08 10:35:18 UTC (rev 77608)
@@ -5,151 +5,4 @@
 The purpose of the questionnaire demo is demonstrate the concept of field
 groups and attribute value adapters for fields.
 
-To start, we need to open a browser and go to the demo applications overview
-screen:
-
-  >>> from z3c.formdemo import testing
-  >>> from z3c.etestbrowser.testing import ExtendedTestBrowser
-  >>> user = ExtendedTestBrowser()
-  >>> user.handleErrors = False
-  >>> user.addHeader('Accept-Language', 'en')
-  >>> skinURL = 'http://localhost:8080/++skin++marsformdemo'
-  >>> user.open('http://localhost:8080')
-
-Since all demos are purely public, there is no need to log in. Let's now click
-on the "All widgets" link:
-
-  >>> user.open(skinURL + '/questionnaireResults')
-
-The first screen you see is the questionnaire results screen.
-
-  >>> testing.printElement(user, "//h1")
-  <h1>Zope Developer Questionnaire Results</h1>
-
-Initially there are no questionnaires, so the screen contains little
-information. Let's first fill out a questionnaire by click on the link below
-the table.
-
-  >>> user.getLink('Fill out Questionnaire').click()
-
-The user is now presented with the questionnaire screen, which is organized
-into three groups. Let's fill out the questionnaire:
-
-  >>> user.getControl('Name').value = u'Stephan Richter'
-  >>> user.getControl('Age').value = u'27'
-
-  >>> user.getControl('yes', index=0).click()
-  >>> user.getControl('no', index=1).click()
-  >>> user.getControl('yes', index=2).click()
-  >>> user.getControl('no', index=3).click()
-
-  >>> user.getControl('yes', index=4).click()
-  >>> user.getControl('have you contributed').value = u'5'
-  >>> user.getControl('What is your Zope Id?').value = u'srichter'
-
-  >>> user.getControl('Submit Questionnaire').click()
-
-Once the questionnaire has been submitted, the user is returned to the results
-screen. Now the table has an entry:
-
-  >>> testing.printElement(user, "//table/tbody/tr[1]")
-  <tr class="odd"><td
-     class="sorted-on">
-      Stephan Richter
-    </td>
-    <td class="right">
-      27
-    </td>
-    <td class="right">
-      yes
-    </td>
-    <td class="right">
-      no
-    </td>
-    <td class="right">
-      yes
-    </td>
-    <td class="right">
-      no
-    </td>
-    <td class="right">
-      yes
-    </td>
-    <td class="right">
-      5
-    </td>
-    <td class="right">
-      srichter
-    </td>
-  </tr>
-
-Let's now fill out another questionnaire:
-
-  >>> user.getLink('Fill out Questionnaire').click()
-
-  >>> user.getControl('Name').value = u'Roger Ineichen'
-  >>> user.getControl('Age').value = u'39'
-
-  >>> user.getControl('yes', index=0).click()
-  >>> user.getControl('yes', index=1).click()
-  >>> user.getControl('yes', index=2).click()
-  >>> user.getControl('no', index=3).click()
-
-  >>> user.getControl('yes', index=4).click()
-  >>> user.getControl('have you contributed').value = u'4'
-  >>> user.getControl('What is your Zope Id?').value = u'projekt01'
-
-  >>> user.getControl('Submit Questionnaire').click()
-
-Now that we have two entries, we can use the table headers cells to sort
-them. By default they are sorted by name:
-
-  >>> testing.printElement(user, "//table/tbody/tr/td[1]/text()",
-  ...                      multiple=True, serialize=False)
-  Roger Ineichen
-  Stephan Richter
-
-Clicking on the "Name" table header cell, will leave the order, since the
-ordering must be initialized. The second time the order is reversed:
-
-  >>> user.getLink('Name').click()
-  >>> user.getLink('Name').click()
-
-  >>> testing.printElement(user, "//table/tbody/tr/td[1]/text()",
-  ...                      multiple=True, serialize=False)
-  Stephan Richter
-  Roger Ineichen
-
-Selecting another header will sort on it. Let's choose the age; clicking on it
-once sorts it in ascending order:
-
-  >>> user.getLink('Age').click()
-  >>> testing.printElement(user, "//table/tbody/tr/td[2]/text()",
-  ...                      multiple=True, serialize=False)
-  27
-  39
-
-Clicking it again, reverses the order:
-
-  >>> user.getLink('Age').click()
-  >>> testing.printElement(user, "//table/tbody/tr/td[2]/text()",
-  ...                      multiple=True, serialize=False)
-  39
-  27
-
-Finally, let's make sure that all headers are linked:
-
-  >>> user.getLink('Zope 2')
-  <Link text='Zope 2' url='...?sort-on=formdemo.questionnaire.zope2'>
-  >>> user.getLink('Plone')
-  <Link text='Plone' url='...?sort-on=formdemo.questionnaire.plone'>
-  >>> user.getLink('Zope 3')
-  <Link text='Zope 3' url='...?sort-on=formdemo.questionnaire.zope3'>
-  >>> user.getLink('Five')
-  <Link text='Five' url='...?sort-on=formdemo.questionnaire.five'>
-  >>> user.getLink('Contrib.')
-  <Link text='Contrib.' url='...?sort-on=formdemo.questionnaire.contributor'>
-  >>> user.getLink('Years')
-  <Link text='Years' url='...?sort-on=formdemo.questionnaire.years'>
-  >>> user.getLink('Zope Id')
-  <Link text='Zope Id' url='...?sort-on=formdemo.questionnaire.zopeId'>
+The original doctest is at ./questionnaire.txt.

Modified: Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/questionnaire/questionnaire.py
===================================================================
--- Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/questionnaire/questionnaire.py	2007-07-08 07:53:54 UTC (rev 77607)
+++ Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/questionnaire/questionnaire.py	2007-07-08 10:35:18 UTC (rev 77608)
@@ -122,7 +122,6 @@
                 if IQuestionnaire.providedBy(obj)]
 
     def update(self):
-        super(QuestionnaireResults, self).update()
 
         rows = []
         for questionnaire in self.getContent():

Added: Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/questionnaire/questionnaire.txt
===================================================================
--- Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/questionnaire/questionnaire.txt	                        (rev 0)
+++ Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/questionnaire/questionnaire.txt	2007-07-08 10:35:18 UTC (rev 77608)
@@ -0,0 +1,156 @@
+==================
+Questionnaire Demo
+==================
+
+The purpose of the questionnaire demo is demonstrate the concept of field
+groups and attribute value adapters for fields.
+
+To start, we need to open a browser and go to the demo applications overview
+screen:
+
+  >>> from z3c.formdemo import testing
+  >>> from z3c.etestbrowser.testing import ExtendedTestBrowser
+  >>> user = ExtendedTestBrowser()
+  >>> user.handleErrors = False
+  >>> user.addHeader('Accept-Language', 'en')
+  >>> skinURL = 'http://localhost:8080/++skin++marsformdemo'
+  >>> user.open('http://localhost:8080')
+
+Since all demos are purely public, there is no need to log in. Let's now click
+on the "All widgets" link:
+
+  >>> user.open(skinURL + '/questionnaireResults')
+
+The first screen you see is the questionnaire results screen.
+
+  >>> testing.printElement(user, "//h1")
+  <h1>Zope Developer Questionnaire Results</h1>
+
+Initially there are no questionnaires, so the screen contains little
+information. Let's first fill out a questionnaire by click on the link below
+the table.
+
+  >>> user.getLink('Fill out Questionnaire').click()
+
+The user is now presented with the questionnaire screen, which is organized
+into three groups. Let's fill out the questionnaire:
+
+  >>> user.getControl('Name').value = u'Stephan Richter'
+  >>> user.getControl('Age').value = u'27'
+
+  >>> user.getControl('yes', index=0).click()
+  >>> user.getControl('no', index=1).click()
+  >>> user.getControl('yes', index=2).click()
+  >>> user.getControl('no', index=3).click()
+
+  >>> user.getControl('yes', index=4).click()
+  >>> user.getControl('have you contributed').value = u'5'
+  >>> user.getControl('What is your Zope Id?').value = u'srichter'
+
+  >>> user.getControl('Submit Questionnaire').click()
+
+Once the questionnaire has been submitted, the user is returned to the results
+screen. Now the table has an entry:
+
+  >>> testing.printElement(user, "//table/tbody/tr[1]")
+  <tr class="odd"><td
+     class="sorted-on">
+      Stephan Richter
+    </td>
+    <td class="right">
+      27
+    </td>
+    <td class="right">
+      yes
+    </td>
+    <td class="right">
+      no
+    </td>
+    <td class="right">
+      yes
+    </td>
+    <td class="right">
+      no
+    </td>
+    <td class="right">
+      yes
+    </td>
+    <td class="right">
+      5
+    </td>
+    <td class="right">
+      srichter
+    </td>
+  </tr>
+
+Let's now fill out another questionnaire:
+
+  >>> user.getLink('Fill out Questionnaire').click()
+
+  >>> user.getControl('Name').value = u'Roger Ineichen'
+  >>> user.getControl('Age').value = u'39'
+
+  >>> user.getControl('yes', index=0).click()
+  >>> user.getControl('yes', index=1).click()
+  >>> user.getControl('yes', index=2).click()
+  >>> user.getControl('no', index=3).click()
+
+  >>> user.getControl('yes', index=4).click()
+  >>> user.getControl('have you contributed').value = u'4'
+  >>> user.getControl('What is your Zope Id?').value = u'projekt01'
+
+  >>> user.getControl('Submit Questionnaire').click()
+
+Now that we have two entries, we can use the table headers cells to sort
+them. By default they are sorted by name:
+
+  >>> testing.printElement(user, "//table/tbody/tr/td[1]/text()",
+  ...                      multiple=True, serialize=False)
+  Roger Ineichen
+  Stephan Richter
+
+Clicking on the "Name" table header cell, will leave the order, since the
+ordering must be initialized. The second time the order is reversed:
+
+  >>> user.getLink('Name').click()
+  >>> user.getLink('Name').click()
+
+  >>> testing.printElement(user, "//table/tbody/tr/td[1]/text()",
+  ...                      multiple=True, serialize=False)
+  Stephan Richter
+  Roger Ineichen
+
+Selecting another header will sort on it. Let's choose the age; clicking on it
+once sorts it in ascending order:
+
+  >>> user.getLink('Age').click()
+  >>> testing.printElement(user, "//table/tbody/tr/td[2]/text()",
+  ...                      multiple=True, serialize=False)
+  27
+  39
+
+Clicking it again, reverses the order:
+
+  >>> user.getLink('Age').click()
+  >>> testing.printElement(user, "//table/tbody/tr/td[2]/text()",
+  ...                      multiple=True, serialize=False)
+  39
+  27
+
+Finally, let's make sure that all headers are linked:
+
+  >>> user.getLink('Zope 2')
+  <Link text='Zope 2' url='...?sort-on=formdemo.questionnaire.zope2'>
+  >>> user.getLink('Plone')
+  <Link text='Plone' url='...?sort-on=formdemo.questionnaire.plone'>
+  >>> user.getLink('Zope 3')
+  <Link text='Zope 3' url='...?sort-on=formdemo.questionnaire.zope3'>
+  >>> user.getLink('Five')
+  <Link text='Five' url='...?sort-on=formdemo.questionnaire.five'>
+  >>> user.getLink('Contrib.')
+  <Link text='Contrib.' url='...?sort-on=formdemo.questionnaire.contributor'>
+  >>> user.getLink('Years')
+  <Link text='Years' url='...?sort-on=formdemo.questionnaire.years'>
+  >>> user.getLink('Zope Id')
+  <Link text='Zope Id' url='...?sort-on=formdemo.questionnaire.zopeId'>
+


Property changes on: Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/questionnaire/questionnaire.txt
___________________________________________________________________
Name: svn:keywords
   + Date Author

Added: Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/spreadsheet/README.txt
===================================================================
--- Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/spreadsheet/README.txt	                        (rev 0)
+++ Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/spreadsheet/README.txt	2007-07-08 10:35:18 UTC (rev 77608)
@@ -0,0 +1,8 @@
+================
+Spreadsheet Demo
+================
+
+The purpose of the spreadsheet demo is to demonstrate how the form framework
+can be combined with another framework, in our case the Zope Corp.'s tables.
+
+The original doctest is at ./spreadsheet.txt.


Property changes on: Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/spreadsheet/README.txt
___________________________________________________________________
Name: svn:keywords
   + Date Author

Added: Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/spreadsheet/__init__.py
===================================================================
--- Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/spreadsheet/__init__.py	                        (rev 0)
+++ Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/spreadsheet/__init__.py	2007-07-08 10:35:18 UTC (rev 77608)
@@ -0,0 +1 @@
+#


Property changes on: Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/spreadsheet/__init__.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/spreadsheet/candidate.py
===================================================================
--- Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/spreadsheet/candidate.py	                        (rev 0)
+++ Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/spreadsheet/candidate.py	2007-07-08 10:35:18 UTC (rev 77608)
@@ -0,0 +1,62 @@
+import zope.interface
+from zope.schema import fieldproperty
+from zope.viewlet.viewlet import CSSViewlet
+from zope.app.folder.interfaces import IFolder
+
+from z3c.form import field
+from z3c.formdemo.spreadsheet.content import ICandidate
+
+import grok
+
+import mars.layer
+import mars.viewlet
+import mars.template
+from mars.formdemo.layer import IDemoBrowserLayer
+from mars.formdemo.skin import skin
+from mars.formdemo.spreadsheet.spreadsheet import Spreadsheet
+
+mars.layer.layer(IDemoBrowserLayer)
+
+class Candidate(grok.Model):
+    zope.interface.implements(ICandidate)
+
+    lastName = fieldproperty.FieldProperty(ICandidate['lastName'])
+    firstName = fieldproperty.FieldProperty(ICandidate['firstName'])
+    rating = fieldproperty.FieldProperty(ICandidate['rating'])
+
+    def __init__(self, lastName, firstName, rating=None):
+        self.lastName = lastName
+        self.firstName = firstName
+        self.rating = rating
+
+class CandidateSpreadsheet(mars.view.PageletView, Spreadsheet):
+    grok.name('spreadsheet')
+    grok.context(IFolder)
+
+    sessionKey = 'mars.formdemo.spreadsheet.candidate'
+    rowFields = field.Fields(ICandidate)
+    columnWidths = (200, 200, 150)
+
+    def getContent(self):
+        return [obj for obj in self.context.values()
+                if ICandidate.providedBy(obj)]
+
+class CandidateSpreadsheetTemplate(mars.template.TemplateFactory):
+    grok.context(CandidateSpreadsheet)
+    grok.template('spreadsheet.pt')
+
+## CSS requirement
+class SpreadsheetStyle(mars.resource.ResourceFactory):
+    """File resource"""
+    grok.name('spreadsheet.css')
+    mars.resource.file('spreadsheet.css')
+
+SpreadsheetCSS = CSSViewlet('spreadsheet.css')
+class SpreadsheetCSSViewlet(mars.viewlet.SimpleViewlet, SpreadsheetCSS):
+    """css viewlet"""
+    weight = 1000
+    grok.name('spreadsheet.css')
+    grok.context(zope.interface.Interface)
+    mars.viewlet.view(CandidateSpreadsheet)
+    mars.viewlet.manager(skin.CSSManager)
+


Property changes on: Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/spreadsheet/candidate.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/spreadsheet/spreadsheet.css
===================================================================
--- Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/spreadsheet/spreadsheet.css	                        (rev 0)
+++ Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/spreadsheet/spreadsheet.css	2007-07-08 10:35:18 UTC (rev 77608)
@@ -0,0 +1,75 @@
+/* ----[ Layout ]----------------------------------------------------------- */
+
+h1 {
+  font-weight: bold;
+  margin-bottom: 10px;
+}
+
+/* ----[ Form ]------------------------------------------------------------ */
+
+input.textWidget {
+  width: 150px;
+  padding: 2px;
+  background: white;
+}
+
+select.selectWidget {
+  width: 130px;
+  padding: 2px;
+}
+
+input[type=submit] {
+  background: #D91813;
+  color: white;
+  border: 1px solid #8C100D;
+  font-weight: bold;
+}
+
+/* ----[ Table ]------------------------------------------------------------ */
+
+th {
+  background: #D91813;
+  color: white;
+  padding: 4px;
+}
+
+th a {
+  color: white;
+}
+
+th a:link {
+  color: white;
+}
+
+th a:hover {
+  color: white;
+}
+
+th a:visited {
+  color: white;
+}
+
+th.sorted-on {
+  background: #8C100D;
+}
+
+td {
+  padding: 3px;
+}
+
+td.sorted-on {
+  background: #DDD;
+}
+
+tr.even {
+  background: #EEE;
+}
+
+tr.even td.sorted-on {
+  background: #CCC;
+}
+
+tr.odd {
+  background: #F6F6F6;
+}
+

Added: Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/spreadsheet/spreadsheet.pt
===================================================================
--- Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/spreadsheet/spreadsheet.pt	                        (rev 0)
+++ Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/spreadsheet/spreadsheet.pt	2007-07-08 10:35:18 UTC (rev 77608)
@@ -0,0 +1,9 @@
+<h1>Spreadsheet Demo &ndash; Candidate Evaluations</h1>
+
+<div metal:use-macro="macro:form">
+  <div metal:fill-slot="info"
+       tal:replace="nothing" />
+  <div metal:fill-slot="main"
+       tal:replace="structure view/table" />
+</div>
+

Added: Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/spreadsheet/spreadsheet.py
===================================================================
--- Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/spreadsheet/spreadsheet.py	                        (rev 0)
+++ Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/spreadsheet/spreadsheet.py	2007-07-08 10:35:18 UTC (rev 77608)
@@ -0,0 +1,148 @@
+__docformat__ = "reStructuredText"
+import zope.interface
+from zope.app.session.interfaces import ISession
+from z3c.form import button, field, form, interfaces
+from z3c.formui import layout
+from zc.table import table, column
+
+from z3c.formdemo.browser import formatter
+from z3c.formdemo.spreadsheet import content
+
+
+class SpreadsheetDataColumn(column.SortingColumn):
+
+    def __init__(self, field):
+        super(SpreadsheetDataColumn, self).__init__(field.title, field.__name__)
+
+    def renderCell(self, item, formatter):
+        return item.widgets[self.name].render()
+
+    def getSortKey(self, item, formatter):
+        return item.widgets[self.name].value
+
+
+class SpreadsheetActionsColumn(column.Column):
+
+    def __init__(self):
+        super(SpreadsheetActionsColumn, self).__init__(
+            u'Actions', 'actions')
+
+    def renderCell(self, item, formatter):
+        return '\n'.join(
+            [action.render() for action in item.actions.values()] )
+
+
+class AddRow(form.AddForm):
+    form.extends(form.AddForm)
+    prefix = 'add.'
+
+    def __init__(self, spreadsheet):
+        super(AddRow, self).__init__(spreadsheet.context, spreadsheet.request)
+        self.fields = spreadsheet.rowFields
+        self.sessionKey = spreadsheet.sessionKey
+
+    def create(self, data):
+        return Candidate(**data)
+
+    def add(self, object):
+        count = 0
+        while 'candidate-%i' %count in self.context:
+            count += 1;
+        self._name = 'candidate-%i' %count
+        self.context[self._name] = object
+        return object
+
+    def update(self):
+        super(AddRow, self).update()
+        if self._finishedAdd:
+            # Purposefully do not deactivate add-mode, so that multiple
+            # candidates can be added at once.
+            self.request.response.redirect(self.request.getURL())
+
+    @button.buttonAndHandler(u'Cancel')
+    def handleCancel(self, action):
+        ISession(self.request)[self.sessionKey]['add'] = False
+        self.request.response.redirect(self.request.getURL())
+
+
+class EditRow(form.EditForm):
+
+    def __init__(self, spreadsheet, content):
+        super(EditRow, self).__init__(spreadsheet.context, spreadsheet.request)
+        self.fields = spreadsheet.rowFields
+        self.content = content
+        self.prefix = str(content.__name__) + '.'
+        self.sessionKey = spreadsheet.sessionKey
+
+    @property
+    def edit(self):
+        name = ISession(self.request)[self.sessionKey].get('edit')
+        return self.content.__name__ == name
+
+    def getContent(self):
+        return self.content
+
+    def updateWidgets(self):
+        self.widgets = zope.component.getMultiAdapter(
+            (self, self.request, self.getContent()), interfaces.IWidgets)
+        if not self.edit:
+            self.widgets.mode = interfaces.DISPLAY_MODE
+        self.widgets.update()
+
+    @button.buttonAndHandler(u'Edit', condition=lambda form: not form.edit)
+    def handleEdit(self, action):
+        ISession(self.request)[self.sessionKey]['edit'] = self.content.__name__
+        self.request.response.redirect(self.request.getURL())
+
+    @button.buttonAndHandler(u'Save', condition=lambda form: form.edit)
+    def handleSave(self, action):
+        self.handleApply(self, action)
+        if not self.widgets.errors:
+            ISession(self.request)[self.sessionKey]['edit'] = None
+            self.request.response.redirect(self.request.getURL())
+
+    @button.buttonAndHandler(u'Cancel', condition=lambda form: form.edit)
+    def handleCancel(self, action):
+        ISession(self.request)[self.sessionKey]['edit'] = None
+        self.request.response.redirect(self.request.getURL())
+
+
+class Spreadsheet(layout.FormLayoutSupport, form.Form):
+
+    sessionKey = 'z3c.formdemo.spreadsheet'
+    rowFields = None
+    columnWidths = None
+
+    @property
+    def add(self):
+        return ISession(self.request)[self.sessionKey].get('add', False)
+
+    @button.buttonAndHandler(u'Add', condition=lambda form: not form.add)
+    def handleAdd(self, action):
+        ISession(self.request)[self.sessionKey]['add'] = True
+        self.updateActions()
+
+    def update(self):
+        super(Spreadsheet, self).update()
+
+        rows = []
+        for candidate in self.getContent():
+            row = EditRow(self, candidate)
+            row.update()
+            rows.append(row)
+
+        if self.add:
+            row = AddRow(self)
+            row.update()
+            rows.append(row)
+
+        columns = [SpreadsheetDataColumn(field.field)
+                   for field in self.rowFields.values()]
+        columns.append(SpreadsheetActionsColumn())
+
+        self.table = formatter.SelectedItemFormatter(
+            self.context, self.request, rows,
+            prefix = self.sessionKey + '.', columns=columns,
+            sort_on=[('lastName', False)])
+        self.table.sortKey = 'formdemo.spreadsheet.sort-on'
+        self.table.widths = self.columnWidths + (100,)


Property changes on: Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/spreadsheet/spreadsheet.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/spreadsheet/spreadsheet.txt
===================================================================
--- Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/spreadsheet/spreadsheet.txt	                        (rev 0)
+++ Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/spreadsheet/spreadsheet.txt	2007-07-08 10:35:18 UTC (rev 77608)
@@ -0,0 +1,164 @@
+================
+Spreadsheet Demo
+================
+
+The purpose of the spreadsheet demo is to demonstrate how the form framework
+can be combined with another framework, in our case the Zope Corp.'s tables.
+
+To start, we need to open a browser and go to the demo applications overview
+screen:
+
+  >>> from z3c.formdemo import testing
+  >>> from z3c.etestbrowser.testing import ExtendedTestBrowser
+  >>> user = ExtendedTestBrowser()
+  >>> user.addHeader('Accept-Language', 'en')
+  >>> user.handleErrors = False
+  >>> skinURL = 'http://localhost:8080/++skin++marsformdemo'
+  >>> user.open('http://localhost:8080')
+
+Since all demos are purely public, there is no need to log in. Let's now click
+on the "Spreadsheet" link:
+
+  >>> user.open(skinURL + '/spreadsheet')
+
+There is only one screen for this demo. In it you see the candidate
+evaluations table:
+
+  >>> testing.printElement(user, "//h1")
+  <h1>Spreadsheet Demo ...</h1>
+
+Initially there are no evaluations, so the screen contains little
+information. Let's first fill out a few evaluations by clicking on the button
+below the table.
+
+  >>> user.getControl('Add').click()
+
+Once clicked, the button below the table disappears, and a new row is shown in
+the table allowing us to add another evaluation. So let's fill out information
+and add the evaluation:
+
+  >>> user.getControl(name='add.widgets.lastName').value = u'Richter'
+  >>> user.getControl(name='add.widgets.firstName').value = u'Stephan'
+  >>> user.getControl(name='add.widgets.rating:list').getControl('good').click()
+
+  >>> user.getControl('Add').click()
+
+When the page returns, we see a row with the entry of Stephan Richter, ...
+
+  >>> testing.printElement(user, "//table/tbody/tr[2]")
+  <tr class="even"><td class="sorted-on">
+      Richter
+    </td>
+    <td class="">
+      Stephan
+    </td>
+    <td class="">
+      good
+    </td>
+    <td class="">
+      <input type="submit" ... value="Edit" /></td>
+  </tr>
+
+... but also another add evaluation row. This is by design, so that the user
+can quickly record new entries. So let's add another:
+
+  >>> user.getControl(name='add.widgets.lastName').value = u'Ineichen'
+  >>> user.getControl(name='add.widgets.firstName').value = u'Roger'
+  >>> user.getControl(name='add.widgets.rating:list')\
+  ...     .getControl('excellent').click()
+
+  >>> user.getControl('Add').click()
+
+We are done now with adding new evaluations. Clicking on the "Cancel" button,
+removes the add line.
+
+  >>> user.getControl('Cancel').click()
+  >>> user.getControl(name='add.widgets.lastName')
+  Traceback (most recent call last):
+  ...
+  LookupError: name 'add.widgets.lastName'
+
+We can now edit an evaluation by clicking on the row's edit button:
+
+  >>> user.getControl('Edit', index=1).click()
+
+An edit form for this row appears now for Stephan. Let's change his rating to
+"average":
+
+  >>> user.getControl(name='candidate-0.widgets.rating:list')\
+  ...     .getControl('average').click()
+
+But hitting the "Cancel" button wil ignore the changes and simply return to
+diaplay the row:
+
+  >>> user.getControl('Cancel').click()
+  >>> testing.printElement(user, "//table/tbody/tr[2]/td[3]/text()",
+  ...                      serialize=False)
+  good
+
+Let's now edit the rating for real:
+
+  >>> user.getControl('Edit', index=1).click()
+  >>> user.getControl(name='candidate-0.widgets.rating:list')\
+  ...     .getControl('average').click()
+  >>> user.getControl('Save').click()
+
+Saving the changes also collapses the edit form back into a display form,
+saving the user from accessive button clicking. Of course, the data is
+properly stored.
+
+  >>> testing.printElement(user, "//table/tbody/tr[2]/td[3]/text()",
+  ...                      serialize=False)
+  average
+
+The real power of integrating the forms into ``zc.table`` is the automtic
+column sorting feature that comes with the table framework. By default they
+are sorted by last name:
+
+  >>> testing.printElement(user, "//table/tbody/tr/td[1]/text()",
+  ...                      multiple=True, serialize=False)
+  Ineichen
+  Richter
+
+Clicking on the "Last Name" table header cell, will leave the order, since the
+ordering must be initialized. The second time the order is reversed:
+
+  >>> user.getLink('Last Name').click()
+  >>> user.getLink('Last Name').click()
+
+  >>> testing.printElement(user, "//table/tbody/tr/td[1]/text()",
+  ...                      multiple=True, serialize=False)
+  Richter
+  Ineichen
+
+Selecting another header will sort on it. Let's choose the first name;
+clicking on it once sorts it in ascending order:
+
+  >>> user.getLink('First Name').click()
+  >>> testing.printElement(user, "//table/tbody/tr/td[2]/text()",
+  ...                      multiple=True, serialize=False)
+  Roger
+  Stephan
+
+Clicking it again, reverses the order:
+
+  >>> user.getLink('First Name').click()
+  >>> testing.printElement(user, "//table/tbody/tr/td[2]/text()",
+  ...                      multiple=True, serialize=False)
+  Stephan
+  Roger
+
+Except for the "Actions" column, all headers can be sorted on:
+
+  >>> user.getLink('Last Name')
+  <Link text='Last Name' url='...lastName'>
+  >>> user.getLink('First Name')
+  <Link text='First Name' url='...firstName'>
+  >>> user.getLink('Rating')
+  <Link text='Rating' url='...rating'>
+  >>> user.getLink('Actions')
+  Traceback (most recent call last):
+  ...
+  LinkNotFoundError
+
+


Property changes on: Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/spreadsheet/spreadsheet.txt
___________________________________________________________________
Name: svn:keywords
   + Date Author

Modified: Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/tests.py
===================================================================
--- Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/tests.py	2007-07-08 07:53:54 UTC (rev 77607)
+++ Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/tests.py	2007-07-08 10:35:18 UTC (rev 77608)
@@ -10,9 +10,11 @@
 def test_suite():
     suites = []
     for docpath in (
-                    ('message', 'README.txt'),
-                    ('questionnaire', 'README.txt'),
-                    ('widgets', 'README.txt'),
+                    #('message', 'message.txt'),
+                    #('questionnaire', 'questionnaire.txt'),
+                    #('widgets', 'widgets.txt'),
+                    #('spreadsheet', 'spreadsheet.txt'),
+                    ('wizard', 'wizard.txt'),
                     ):
         suite = functional.FunctionalDocFileSuite(
             os.path.join(*docpath),

Modified: Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/widgets/README.txt
===================================================================
--- Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/widgets/README.txt	2007-07-08 07:53:54 UTC (rev 77607)
+++ Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/widgets/README.txt	2007-07-08 10:35:18 UTC (rev 77608)
@@ -5,128 +5,5 @@
 The purpose of the widgets demo is demonstrate that there exists a widget for
 each standard field type and how it works.
 
-To start, we need to open a browser and go to the demo applications overview
-screen:
+The original doctest is at ./widgets.txt.
 
-  >>> from z3c.formdemo import testing
-  >>> from z3c.etestbrowser.testing import ExtendedTestBrowser
-  >>> user = ExtendedTestBrowser()
-  >>> user.addHeader('Accept-Language', 'en')
-  >>> user.handleErrors = False
-  >>> skinURL = 'http://localhost:8080/++skin++marsformdemo'
-
-Since all demos are purely public, there is no need to log in. Let's now click
-on the "All widgets" link:
-
-  >>> user.open(skinURL + '/widgets')
-
-You are now in the widgets form. Let's now fill out all forms an submit the
-form:
-
-  >>> import cStringIO
-
-  >>> def addSelection(browser, name, value, selected=True):
-  ...     form = browser.mech_browser.forms().next()
-  ...     form.new_control(
-  ...         'select', name, attrs={'__select': {'name': name, 'size': '5'}})
-  ...     form.new_control(
-  ...         'select', name,
-  ...         attrs={'__select': {'name': name, 'size': '5'},
-  ...                'selected': 'selected', 'value': value})
-
-  >>> user.getControl('ASCII', index=0).value += u' Add on.'
-  >>> user.getControl('ASCII Line').value += u' Add on.'
-  >>> user.getControl('no', index=0).click() # Boolean
-  >>> user.getControl('Bytes', index=0).add_file(
-  ...     cStringIO.StringIO('File contents'), 'text/plain', 'test.txt')
-  >>> user.getControl('Bytes Line').value += u' Add on.'
-  >>> user.getControl('Choice', index=0).getControl('Two').click()
-  >>> user.getControl('Choice (Not Required)').getControl('Two').click()
-  >>> user.getControl('Choice (Explicit Prompt)').getControl('Two').click()
-  >>> user.getControl('Date', index=0).value = u'7/1/07'
-  >>> user.getControl('Date/Time').value = u'7/1/07 12:15 AM'
-  >>> user.getControl('Decimal').value = u'12439.986'
-  >>> user.getControl('Dotted Name').value += u'demo'
-  >>> user.getControl('Float').value += u'12439.986'
-  >>> user.getControl('Frozen Set').getControl('One').click()
-  >>> user.getControl('Id').value += u'demo'
-  >>> user.getControl('Integer').value = u'12439'
-  >>> addSelection(user, 'form.widgets.listField', u'1')
-  >>> user.getControl('Password').value = u'pwd'
-  >>> user.getControl('Set', index=1).getControl('One').click()
-  >>> user.getControl('Source Text').value += u' Add on.'
-  >>> user.getControl('Text', index=1).value += u' Add on.'
-  >>> user.getControl('Text Line').value += u' Add on.'
-  >>> user.getControl('Time', index=1).value = u'12:15 AM'
-  >>> user.getControl('Time Delta').value = u'4 days, 1:00:00'
-  >>> addSelection(user, 'form.widgets.tupleField', u'1')
-  >>> user.getControl('URI').value += u'/Documentation'
-  >>> user.getControl(name='form.widgets.hiddenField').value += u' Add on.'
-
-  >>> user.getControl('Apply').click()
-
-Once submitted, the same form returns with a data changed method:
-
-  >>> from z3c.formdemo import testing
-  >>> testing.printElement(user, "//div[@class='summary']")
-  <div class="summary">Data successfully updated.</div>
-
-Let's now ensure that the data has been truly uploaded:
-
-  >>> from z3c.formdemo.widgets import interfaces
-  >>> fields = interfaces.IAllFields(getRootFolder())
-
-  >>> fields.asciiField
-  'This is\n ASCII. Add on.'
-  >>> fields.asciiLineField
-  'An ASCII line. Add on.'
-  >>> fields.boolField
-  False
-  >>> fields.bytesField
-  'File contents'
-  >>> fields.bytesLineField
-  'A Bytes line. Add on.'
-  >>> fields.choiceField
-  2
-  >>> fields.optionalChoiceField
-  2
-  >>> fields.promptChoiceField
-  2
-  >>> fields.dateField
-  datetime.date(2007, 7, 1)
-  >>> fields.datetimeField
-  datetime.datetime(2007, 7, 1, 0, 15)
-  >>> fields.decimalField
-  Decimal("12439.986")
-  >>> fields.dottedNameField
-  'z3c.formdemo'
-  >>> fields.floatField
-  12.811999999999999
-  >>> fields.frozenSetField
-  frozenset([3])
-  >>> fields.idField
-  'z3c.formdemo'
-  >>> fields.intField
-  12439
-  >>> fields.listField
-  [1]
-  >>> fields.passwordField
-  u'pwd'
-  >>> fields.setField
-  set([3])
-  >>> fields.sourceTextField
-  u'<source /> Add on.'
-  >>> fields.textField
-  u'Some\n Text. Add on.'
-  >>> fields.textLineField
-  u'Some Text line. Add on.'
-  >>> fields.timeField
-  datetime.time(0, 15)
-  >>> fields.timedeltaField
-  datetime.timedelta(4, 3600)
-  >>> fields.tupleField
-  (1,)
-  >>> fields.uriField
-  'http://zope.org/Documentation'
-  >>> fields.hiddenField
-  u'Some Hidden Text. Add on.'

Modified: Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/widgets/widgets.py
===================================================================
--- Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/widgets/widgets.py	2007-07-08 07:53:54 UTC (rev 77607)
+++ Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/widgets/widgets.py	2007-07-08 10:35:18 UTC (rev 77608)
@@ -63,10 +63,14 @@
     hiddenField = fieldproperty.FieldProperty(IAllFields['hiddenField'])
 
 # register the AllField class as a annotation adapter
-getAllFields = zope.annotation.factory(AllFields)
-# TODO fix me
+zope.component.provideAdapter(zope.annotation.factory(AllFields))
+
+#  fix me: this adapter factory fails because although the annotation factory
+# returns a `bound` method, when the factory is registered in the grokker it
+# appears as an `unbound` method and therefore fails when it is called
+# Is this something happening in martian????
 #class GetAllFields(mars.adapter.AdapterFactory):
-#    mars.adapter.factory(getAllFields)
+#    mars.adapter.factory(zope.annotation.factory(AllFields))
 
 class AllFieldsForm(mars.view.PageletView, form.EditForm):
     """A form showing all fields."""

Added: Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/widgets/widgets.txt
===================================================================
--- Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/widgets/widgets.txt	                        (rev 0)
+++ Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/widgets/widgets.txt	2007-07-08 10:35:18 UTC (rev 77608)
@@ -0,0 +1,133 @@
+============
+Widgets Demo
+============
+
+The purpose of the widgets demo is demonstrate that there exists a widget for
+each standard field type and how it works.
+
+To start, we need to open a browser and go to the demo applications overview
+screen:
+
+  >>> from z3c.formdemo import testing
+  >>> from z3c.etestbrowser.testing import ExtendedTestBrowser
+  >>> user = ExtendedTestBrowser()
+  >>> user.addHeader('Accept-Language', 'en')
+  >>> user.handleErrors = False
+  >>> skinURL = 'http://localhost:8080/++skin++marsformdemo'
+
+Since all demos are purely public, there is no need to log in. Let's now click
+on the "All widgets" link:
+
+  >>> user.open(skinURL + '/widgets')
+
+You are now in the widgets form. Let's now fill out all forms an submit the
+form:
+
+  >>> import cStringIO
+
+  >>> def addSelection(browser, name, value, selected=True):
+  ...     form = browser.mech_browser.forms().next()
+  ...     form.new_control(
+  ...         'select', name, attrs={'__select': {'name': name, 'size': '5'}})
+  ...     form.new_control(
+  ...         'select', name,
+  ...         attrs={'__select': {'name': name, 'size': '5'},
+  ...                'selected': 'selected', 'value': value})
+
+  >>> user.getControl('ASCII', index=0).value += u' Add on.'
+  >>> user.getControl('ASCII Line').value += u' Add on.'
+  >>> user.getControl('no', index=0).click() # Boolean
+  >>> user.getControl('Bytes', index=0).add_file(
+  ...     cStringIO.StringIO('File contents'), 'text/plain', 'test.txt')
+  >>> user.getControl('Bytes Line').value += u' Add on.'
+  >>> user.getControl('Choice', index=0).getControl('Two').click()
+  >>> user.getControl('Choice (Not Required)').getControl('Two').click()
+  >>> user.getControl('Choice (Explicit Prompt)').getControl('Two').click()
+  >>> user.getControl('Date', index=0).value = u'7/1/07'
+  >>> user.getControl('Date/Time').value = u'7/1/07 12:15 AM'
+  >>> user.getControl('Decimal').value = u'12439.986'
+  >>> user.getControl('Dotted Name').value += u'demo'
+  >>> user.getControl('Float').value += u'12439.986'
+  >>> user.getControl('Frozen Set').getControl('One').click()
+  >>> user.getControl('Id').value += u'demo'
+  >>> user.getControl('Integer').value = u'12439'
+  >>> addSelection(user, 'form.widgets.listField', u'1')
+  >>> user.getControl('Password').value = u'pwd'
+  >>> user.getControl('Set', index=1).getControl('One').click()
+  >>> user.getControl('Source Text').value += u' Add on.'
+  >>> user.getControl('Text', index=1).value += u' Add on.'
+  >>> user.getControl('Text Line').value += u' Add on.'
+  >>> user.getControl('Time', index=1).value = u'12:15 AM'
+  >>> user.getControl('Time Delta').value = u'4 days, 1:00:00'
+  >>> addSelection(user, 'form.widgets.tupleField', u'1')
+  >>> user.getControl('URI').value += u'/Documentation'
+  >>> user.getControl(name='form.widgets.hiddenField').value += u' Add on.'
+
+  >>> user.getControl('Apply').click()
+
+Once submitted, the same form returns with a data changed method:
+
+  >>> from z3c.formdemo import testing
+  >>> testing.printElement(user, "//div[@class='summary']")
+  <div class="summary">Data successfully updated.</div>
+
+Let's now ensure that the data has been truly uploaded:
+
+  >>> from z3c.formdemo.widgets import interfaces
+  >>> fields = interfaces.IAllFields(getRootFolder())
+
+  >>> fields.asciiField
+  'This is\n ASCII. Add on.'
+  >>> fields.asciiLineField
+  'An ASCII line. Add on.'
+  >>> fields.boolField
+  False
+  >>> fields.bytesField
+  'File contents'
+  >>> fields.bytesLineField
+  'A Bytes line. Add on.'
+  >>> fields.choiceField
+  2
+  >>> fields.optionalChoiceField
+  2
+  >>> fields.promptChoiceField
+  2
+  >>> fields.dateField
+  datetime.date(2007, 7, 1)
+  >>> fields.datetimeField
+  datetime.datetime(2007, 7, 1, 0, 15)
+  >>> fields.decimalField
+  Decimal("12439.986")
+  >>> fields.dottedNameField
+  'z3c.formdemo'
+  >>> fields.floatField
+  12.811999999999999
+  >>> fields.frozenSetField
+  frozenset([3])
+  >>> fields.idField
+  'z3c.formdemo'
+  >>> fields.intField
+  12439
+  >>> fields.listField
+  [1]
+  >>> fields.passwordField
+  u'pwd'
+  >>> fields.setField
+  set([3])
+  >>> fields.sourceTextField
+  u'<source /> Add on.'
+  >>> fields.textField
+  u'Some\n Text. Add on.'
+  >>> fields.textLineField
+  u'Some Text line. Add on.'
+  >>> fields.timeField
+  datetime.time(0, 15)
+  >>> fields.timedeltaField
+  datetime.timedelta(4, 3600)
+  >>> fields.tupleField
+  (1,)
+  >>> fields.uriField
+  'http://zope.org/Documentation'
+  >>> fields.hiddenField
+  u'Some Hidden Text. Add on.'
+


Property changes on: Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/widgets/widgets.txt
___________________________________________________________________
Name: svn:keywords
   + Date Author

Added: Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/wizard/README.txt
===================================================================
--- Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/wizard/README.txt	                        (rev 0)
+++ Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/wizard/README.txt	2007-07-08 10:35:18 UTC (rev 77608)
@@ -0,0 +1,10 @@
+===========
+Wizard Demo
+===========
+
+The purpose of the wizard demo is demonstrate the construction of a typical UI
+wizard, effectively splitting one form into multiple pages. None of the data
+is permanently stored until the wizard is submitted.
+
+The original doctest is at ./widgets.txt.
+


Property changes on: Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/wizard/README.txt
___________________________________________________________________
Name: svn:keywords
   + Date Author

Added: Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/wizard/__init__.py
===================================================================
--- Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/wizard/__init__.py	                        (rev 0)
+++ Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/wizard/__init__.py	2007-07-08 10:35:18 UTC (rev 77608)
@@ -0,0 +1 @@
+#


Property changes on: Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/wizard/__init__.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/wizard/images/breadcrumb.jpg
===================================================================
(Binary files differ)


Property changes on: Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/wizard/images/breadcrumb.jpg
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/wizard/images/breadcrumb_active.jpg
===================================================================
(Binary files differ)


Property changes on: Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/wizard/images/breadcrumb_active.jpg
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/wizard/images/buttonLeftBG.gif
===================================================================
(Binary files differ)


Property changes on: Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/wizard/images/buttonLeftBG.gif
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/wizard/images/buttonRightBG.gif
===================================================================
(Binary files differ)


Property changes on: Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/wizard/images/buttonRightBG.gif
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/wizard/step.pt
===================================================================
--- Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/wizard/step.pt	                        (rev 0)
+++ Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/wizard/step.pt	2007-07-08 10:35:18 UTC (rev 77608)
@@ -0,0 +1 @@
+<div metal:use-macro="macro:widget-rows" />

Added: Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/wizard/summary.pt
===================================================================
--- Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/wizard/summary.pt	                        (rev 0)
+++ Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/wizard/summary.pt	2007-07-08 10:35:18 UTC (rev 77608)
@@ -0,0 +1,19 @@
+<h1>Person Summary</h1>
+
+<h2>Basic Information</h2>
+<div metal:use-macro="macro:widget-rows" />
+
+<h2>Father</h2>
+<div tal:define="view nocall:view/father">
+  <div metal:use-macro="macro:widget-rows" />
+</div>
+
+<h2>Mother</h2>
+<div tal:define="view nocall:view/mother">
+  <div metal:use-macro="macro:widget-rows" />
+</div>
+
+<h2>Employer</h2>
+<div tal:define="view nocall:view/employer">
+  <div metal:use-macro="macro:widget-rows" />
+</div>

Added: Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/wizard/wizard.css
===================================================================
--- Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/wizard/wizard.css	                        (rev 0)
+++ Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/wizard/wizard.css	2007-07-08 10:35:18 UTC (rev 77608)
@@ -0,0 +1,115 @@
+/* zrt-replace: "images/" tal"string:${context/++resource++WizardImages}/" */
+
+/* [ layout ]--------------------------------------------------------------- */
+
+body {
+  background: #EEE;
+}
+
+div.wizard {
+  width: 600px;
+  font-family: Verdana, Arial, sans-serif;
+  background: white;
+  padding: 20px;
+}
+
+div.header {
+  background-color: #F9CA0B;
+  margin: 0;
+  padding: 10px;
+}
+
+div.header h1 {
+  font-weight: bold;
+  margin: 0;
+  padding: 0;
+}
+
+/* [ breadcrumbs ]---------------------------------------------------------- */
+
+table.breadcrumbs {
+  margin: 10px 0;
+  width: 100%;
+}
+
+table.breadcrumbs td div {
+  height: 25px;
+  width: 25px;
+  background-repeat: no-repeat;
+  background-position: center center;
+  margin-left: auto;
+  margin-right: auto;
+  font-weight: bold;
+  padding-top: 3px;
+  padding-left: 9px;
+}
+
+table.breadcrumbs td.active div {
+  background-image: url("images/breadcrumb_active.jpg");
+  color: #F9CA0B;
+}
+
+table.breadcrumbs td.inactive div {
+  background-image: url("images/breadcrumb.jpg");
+  color: white;
+}
+
+table.breadcrumbs td.inactive a {
+  color: inherit;
+}
+
+/* [ step ]----------------------------------------------------------------- */
+
+fieldset.step {
+  border: 1px solid #F9CA0B;
+  margin: 0;
+  padding: 10px 10px 5px 10px;
+}
+
+fieldset.step legend {
+  border: 1px solid #F9CA0B;
+  padding: 3px 7px;
+  font-size: 12px;
+  font-variant: small-caps;
+}
+
+
+/* [ buttons ]-------------------------------------------------------------- */
+
+div.buttons {
+  height: 15px;
+  margin: 10px 0px 0px 0px;
+  padding: 0;
+}
+
+span.forward {
+  float: right;
+}
+
+span.forward input[type="submit"] {
+    cursor: pointer;
+    border: 0;
+    color: #000000;
+    background-color: #F9CA0B;
+    background-image: url("images/buttonRightBG.gif");
+    background-repeat: no-repeat;
+    background-position: right;
+    border: 1px solid #A28204;
+    padding: 1px 15px 1px 2px;
+}
+
+span.back {
+  float: left;
+}
+
+span.back input[type="submit"] {
+    cursor: pointer;
+    border: 0;
+    color: #000000;
+    background-color: #F9CA0B;
+    background-image: url("images/buttonLeftBG.gif");
+    background-repeat: no-repeat;
+    background-position: left;
+    border: 1px solid #A28204;
+    padding: 1px 2px 1px 15px;
+}

Added: Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/wizard/wizard.pt
===================================================================
--- Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/wizard/wizard.pt	                        (rev 0)
+++ Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/wizard/wizard.pt	2007-07-08 10:35:18 UTC (rev 77608)
@@ -0,0 +1,46 @@
+<div class="wizard">
+  <div class="header">
+    <h1 tal:content="view/title">Wizard</h1>
+  </div>
+  <table class="breadcrumbs"><tr>
+    <td tal:repeat="info view/stepsInfo"
+        tal:attributes="class info/class">
+      <div>
+        <span
+           tal:condition="info/active"
+           tal:content="info/number" />
+        <a href=""
+           tal:condition="not:info/active"
+           tal:attributes="href string:${request/URL}?step=${info/name}"
+           tal:content="info/number" />
+      </div>
+    </td>
+  </tr></table>
+  <div metal:use-macro="macro:form">
+    <div metal:fill-slot="info"
+         tal:replace="nothing" />
+    <fieldset class="step"
+              metal:fill-slot="main">
+      <legend tal:content="view/step/label">Label</legend>
+      <div class="status" tal:condition="view/step/status">
+        <div class="summary" tal:content="view/step/status">
+          Form status summary
+        </div>
+      </div>
+      <div tal:content="structure view/step/render" />
+      <div metal:use-macro="macro:form-required-info" />
+    </fieldset>
+    <div class="buttons" metal:fill-slot="buttons">
+      <span class="back">
+        <input tal:repeat="action view/actions/backActions"
+             tal:replace="structure action/render"
+             />
+      </span>
+      <span class="forward">
+        <input tal:repeat="action view/actions/forwardActions"
+             tal:replace="structure action/render"
+             />
+      </span>
+    </div>
+  </div>
+</div>

Added: Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/wizard/wizard.py
===================================================================
--- Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/wizard/wizard.py	                        (rev 0)
+++ Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/wizard/wizard.py	2007-07-08 10:35:18 UTC (rev 77608)
@@ -0,0 +1,119 @@
+__docformat__ = "reStructuredText"
+
+import zope.interface
+from zope.viewlet.viewlet import CSSViewlet
+from zope.app.folder.interfaces import IFolder
+from zope.app.session.interfaces import ISession
+
+from z3c.form import form, field, button
+from z3c.formui import layout
+from z3c.formdemo.wizard import interfaces, browser, content
+from z3c.formdemo.wizard.wizard import Wizard
+
+
+import grok
+
+import mars.view
+import mars.viewlet
+import mars.layer
+from mars.formdemo.layer import IDemoBrowserLayer
+from mars.formdemo.skin import skin
+
+mars.layer.layer(IDemoBrowserLayer)
+
+class PersonWizard(mars.view.PageletView, Wizard):
+    grok.name('wizard')
+    grok.context(IFolder)
+    form.extends(Wizard)
+
+    title = u'Wizard Demo - Person Demographics'
+    sessionKey = 'z3c.formdemo.wizard.person'
+
+    steps = [
+        ('personalInfo', browser.PersonalInfoStep),
+        ('address', browser.AddressStep),
+        ('father', browser.FatherStep),
+        ('mother', browser.MotherStep),
+        ('employer', browser.EmployerStep)]
+
+    def finish(self):
+        self.request.response.redirect('summary')
+
+    def getContent(self):
+        session = ISession(self.request)[self.sessionKey]
+        obj = session.get('content')
+        if obj is None:
+            obj = session['content'] = content.Person()
+        return obj
+
+    @button.buttonAndHandler(
+        u'Clear', condition=lambda form: form.isFirstStep(),
+        provides=(interfaces.IBackButton,))
+    def handleClear(self, action):
+        session = ISession(self.request)[self.sessionKey]
+        del session['content']
+        self.request.response.redirect(
+            self.request.getURL() + '?step=' + self.steps[0][0])
+
+class PersonSummary(mars.view.FormView, layout.FormLayoutSupport, form.DisplayForm):
+    grok.name('summary')
+    grok.context(zope.interface.Interface)
+
+    fields = field.Fields(interfaces.IPersonalInfo).select(*browser.infoSelection)
+
+    def getContent(self):
+        session = ISession(self.request)[PersonWizard.sessionKey]
+        return session.get('content')
+
+    def update(self):
+        content = self.getContent()
+        self.father = form.DisplayForm(content.father, self.request)
+        self.father.fields = field.Fields(interfaces.IPersonalInfo).select(
+            *browser.infoSelection)
+        self.father.update()
+
+        self.mother = form.DisplayForm(content.mother, self.request)
+        self.mother.fields = field.Fields(interfaces.IPersonalInfo).select(
+            *browser.infoSelection)
+        self.mother.update()
+
+        self.employer = form.DisplayForm(content.employer, self.request)
+        self.employer.fields = field.Fields(interfaces.IEmployerInfo).select(
+            'name', 'street', 'city', 'zip')
+        self.employer.update()
+
+        super(PersonSummary, self).update()
+
+class PersonSummaryTemplate(mars.template.TemplateFactory):
+    grok.context(PersonSummary)
+    grok.template('summary.pt')
+
+
+class WizardImages(mars.resource.ResourceDirectoryFactory):
+    """image resource directory (++resource++img)"""
+    grok.name('WizardImages')
+    mars.resource.directory('images')
+
+
+## CSS requirement
+class WizardStyle(mars.resource.ResourceFactory):
+    """File resource"""
+    grok.name('wizard.css')
+    mars.resource.file('wizard.css')
+
+WizardCSS= CSSViewlet('wizard.css')
+class WizardCSSViewlet(mars.viewlet.SimpleViewlet, WizardCSS):
+    """css viewlet"""
+    grok.name('wizard.css')
+    grok.context(zope.interface.Interface)
+    mars.viewlet.view(Wizard)
+    mars.viewlet.manager(skin.CSSManager)
+
+class WizardTemplate(mars.template.TemplateFactory):
+    grok.context(Wizard)
+    grok.template('wizard.pt')
+
+class StepTemplate(mars.template.TemplateFactory):
+    grok.context(interfaces.IStep)
+    grok.template('step.pt')
+


Property changes on: Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/wizard/wizard.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/wizard/wizard.txt
===================================================================
--- Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/wizard/wizard.txt	                        (rev 0)
+++ Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/wizard/wizard.txt	2007-07-08 10:35:18 UTC (rev 77608)
@@ -0,0 +1,188 @@
+===========
+Wizard Demo
+===========
+
+The purpose of the wizard demo is demonstrate the construction of a typical UI
+wizard, effectively splitting one form into multiple pages. None of the data
+is permanently stored until the wizard is submitted.
+
+To start, we need to open a browser and go to the demo applications overview
+screen:
+
+  >>> from z3c.formdemo import testing
+  >>> from z3c.etestbrowser.testing import ExtendedTestBrowser
+  >>> user = ExtendedTestBrowser()
+  >>> user.addHeader('Accept-Language', 'en')
+  >>> user.handleErrors = False
+  >>> skinURL = 'http://localhost:8080/++skin++marsformdemo'
+
+Since all demos are purely public, there is no need to log in. Let's now click
+on the "Wizard" link:
+
+  >>> user.open(skinURL + '/wizard')
+  >>> user.open('http://localhost:8080/wizard')
+
+You are now seeing the first step of the wizard, which asks for personal
+information:
+
+  >>> testing.printElement(user, "//h1")
+  <h1>Wizard Demo - Person Demographics</h1>
+
+  >>> testing.printElement(user, "//legend")
+  <legend>Personal Information</legend>
+
+Let's fill out the form and save the data:
+
+  >>> user.getControl('First Name').value = 'Stephan'
+  >>> user.getControl('Last Name').value = 'Richter'
+
+  >>> user.getControl('Phone').value = '+1 555 276-3761'
+  >>> user.getControl('Email').value = 'stephan.richter_(at)_gmail.com'
+
+  >>> user.getControl('Save').click()
+
+Rhe "Save" button causes the form to be submitted, but not to proceed to the
+next step. A message that the data has been successfully saved in shown:
+
+  >>> testing.printElement(user, "//div[@class='summary']")
+  <div class="summary">Data successfully updated.</div>
+
+Pressing the "Clear" button (which only appears on the first step) will clear
+out the data of all steps:
+
+  >>> user.getControl('Clear').click()
+
+  >>> user.getControl('First Name').value
+  ''
+  >>> user.getControl('Last Name').value
+  ''
+  >>> user.getControl('Phone').value
+  ''
+  >>> user.getControl('Email').value
+  ''
+
+So let's now fill out the form and click the next button this time.
+
+  >>> user.getControl('First Name').value = 'Stephan'
+
+  >>> user.getControl('Phone').value = '+1 555 276-3761'
+  >>> user.getControl('Email').value = 'stephan.richter_(at)_gmail.com'
+
+  >>> user.getControl('Next').click()
+
+But we forgot the last name, which means the form does nto successfully submit
+and an error message is shown. So we are still at step 1:
+
+  >>> testing.printElement(user, "//legend")
+  <legend>Personal Information</legend>
+
+Filling in the missing required field will allow the action to be successful:
+
+  >>> user.getControl('Last Name').value = 'Richter'
+  >>> user.getControl('Next').click()
+
+You are now forwarded to the second step:
+
+  >>> testing.printElement(user, "//legend")
+  <legend>Address</legend>
+
+The "Next" button does not only forward the user to the second step, but also
+stores the data. Clicking on "Previous" will bring us back to the first
+screen. But let's first fill out step 2, since the "Previous" button also
+stores the data of the current step:
+
+  >>> user.getControl('Street').value = '110 Main Street'
+  >>> user.getControl('Zip').value = '01754'
+
+  >>> user.getControl('Previous').click()
+
+But forgetting a required field does not get you to the previous step.
+
+  >>> testing.printElement(user, "//legend")
+  <legend>Address</legend>
+
+Filling out all information causes the action to be successful:
+
+  >>> user.getControl('City').value = 'Maynard'
+  >>> user.getControl('Previous').click()
+
+So back at step 1, we can see that all the personal information is there.
+
+  >>> user.getControl('First Name').value
+  'Stephan'
+  >>> user.getControl('Last Name').value
+  'Richter'
+  >>> user.getControl('Phone').value
+  '+1 555 276-3761'
+  >>> user.getControl('Email').value
+  'stephan.richter_(at)_gmail.com'
+
+You can also navigate through the wizard by clicking on the step number on the
+top, so let's go to step 2 by clicking on that link:
+
+  >>> user.getLink('2').click()
+  >>> testing.printElement(user, "//legend")
+  <legend>Address</legend>
+
+Note that no data is saved, when using this link. We also notice that all the
+data fields are filled out:
+
+  >>> user.getControl('Street').value
+  '110 Main Street'
+  >>> user.getControl('Zip').value
+  '01754'
+  >>> user.getControl('City').value
+  'Maynard'
+
+Let's now go to the third and forth step, filling them out.
+
+  >>> user.getControl('Next').click()
+
+  >>> user.getControl('First Name').value = 'Wolfgang'
+  >>> user.getControl('Last Name').value = 'Richter'
+  >>> user.getControl('Phone').value = '+49 33 1271568'
+  >>> user.getControl('Email').value = 'wrichter at telekom.de'
+  >>> user.getControl('Street').value = u'Dorfstraße 12'.encode('utf-8')
+  >>> user.getControl('Zip').value = '01945'
+  >>> user.getControl('City').value = 'Tetta'
+
+  >>> user.getControl('Next').click()
+
+  >>> user.getControl('First Name').value = 'Marion'
+  >>> user.getControl('Last Name').value = 'Richter'
+  >>> user.getControl('Phone').value = '+49 33 1271568'
+  >>> user.getControl('Street').value = u'Dorfstraße 12'.encode('utf-8')
+  >>> user.getControl('Zip').value = '01945'
+  >>> user.getControl('City').value = 'Tettau'
+
+  >>> user.getControl('Next').click()
+
+We are now at the final screen. As you will notice, initially there is no
+button that allows submitting the wizard:
+
+  >>> user.getControl('Finish')
+  Traceback (most recent call last):
+  ...
+  LookupError: label 'Finish'
+
+This is because not all required fields have been filled out. Filling out the
+last step and saving it, ...
+
+  >>> user.getControl('Name').value = 'Myself'
+  >>> user.getControl('Street').value = '110 Main Street'
+  >>> user.getControl('Zip').value = '01754'
+  >>> user.getControl('City').value = 'Maynard'
+
+  >>> user.getControl('Save').click()
+
+... will allow the "Finish" button to show:
+
+  >>> user.getControl('Finish')
+  <SubmitControl name='form.buttons.finish' type='submit'>
+
+Clicking it, brings us to the final summary screen:
+
+  >>> user.getControl('Finish').click()
+  >>> user.url
+  'http://localhost:8080/summary'
+


Property changes on: Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/wizard/wizard.txt
___________________________________________________________________
Name: svn:keywords
   + Date Author



More information about the Checkins mailing list