[rhmessaging-commits] rhmessaging commits: r3456 - mgmt/trunk/wooly/python/wooly.

rhmessaging-commits at lists.jboss.org rhmessaging-commits at lists.jboss.org
Wed Jun 17 15:44:31 EDT 2009


Author: justi9
Date: 2009-06-17 15:44:31 -0400 (Wed, 17 Jun 2009)
New Revision: 3456

Modified:
   mgmt/trunk/wooly/python/wooly/demo.py
   mgmt/trunk/wooly/python/wooly/forms.py
   mgmt/trunk/wooly/python/wooly/forms.strings
   mgmt/trunk/wooly/python/wooly/pages.py
   mgmt/trunk/wooly/python/wooly/server.py
   mgmt/trunk/wooly/python/wooly/widgets.py
   mgmt/trunk/wooly/python/wooly/widgets.strings
Log:
 * Remove debug print, and return frame from pop_frame

 * Parameterize the html_class of WidgetSet

 * Use the new, changed debug facility in server

 * Add a form tab to wooly-demo

 * Include an errors attribute on all Form widgets, and use this to
   accumulate form input errors

 * Introduce SubmitForm, with the process_$mode regime and means of
   remembering how you navigated to it, and ButtonForm, for rendering
   any form with a set of buttons

 * Introduce a content pane, FormFieldSet, in lieu of welding the
   fields in directly as we did in FieldForm, and a new
   FieldSubmitForm for something similar to the old behavior

 * Introduce a 'check' pass on FormField, FormFieldSet, and
   FieldSubmitForm

 * Make FormErrors and FormFields aware of what form they are in

 * Revise the default form style


Modified: mgmt/trunk/wooly/python/wooly/demo.py
===================================================================
--- mgmt/trunk/wooly/python/wooly/demo.py	2009-06-17 19:33:19 UTC (rev 3455)
+++ mgmt/trunk/wooly/python/wooly/demo.py	2009-06-17 19:44:31 UTC (rev 3456)
@@ -7,6 +7,7 @@
 from wooly.server import WebServer
 from wooly.pages import HtmlPage
 from wooly.widgets import *
+from wooly.forms import *
 from wooly.resources import StringCatalog
 
 strings = StringCatalog(__file__)
@@ -86,6 +87,9 @@
         self.link_tab = LinkDemo(app, "link")
         tabs.add_tab(self.link_tab)
 
+        self.form_tab = FormDemo(app, "form")
+        tabs.add_tab(self.form_tab)
+
 class Introduction(Widget):
     def render_title(self, session):
         return "Introduction"
@@ -122,3 +126,113 @@
                 return "Hide that secret"
             else:
                 return "Show me a secret"
+
+class FormDemo(Widget):
+    def __init__(self, app, name):
+        super(FormDemo, self).__init__(app, name)
+
+        self.address_form = self.AddressForm(app, "address")
+        self.add_child(self.address_form)
+
+        self.three_form = self.ThreeForm(app, "threeform")
+        self.add_child(self.three_form)
+
+    def render_title(self, session):
+        return "Forms"
+
+    class AddressForm(FieldSubmitForm):
+        def __init__(self, app, name):
+            super(FormDemo.AddressForm, self).__init__(app, name)
+
+            self.name_ = self.Name(app, "first")
+            self.add_field(self.name_)
+
+            self.line_1 = self.Line1(app, "line1")
+            self.add_field(self.line_1)
+
+            self.line_2 = self.Line2(app, "line2")
+            self.add_field(self.line_2)
+
+        def render_title(self, session):
+            return "Enter your address"
+
+        class Name(StringField):
+            def render_title(self, session):
+                return "Name"
+
+        class Line1(StringField):
+            def render_title(self, session):
+                return "Address Line 1"
+
+        class Line2(StringField):
+            def render_title(self, session):
+                return "Address Line 2"
+
+    class ThreeForm(ModeSet, Frame):
+        def __init__(self, app, name):
+            super(FormDemo.ThreeForm, self).__init__(app, name)
+
+            self.one = self.One(app, "one")
+            self.add_mode(self.one)
+
+            self.two = self.Two(app, "two")
+            self.add_mode(self.two)
+
+            self.three = self.Three(app, "three")
+            self.add_mode(self.three)
+
+        class One(FieldSubmitForm):
+            def __init__(self, app, name):
+                super(FormDemo.ThreeForm.One, self).__init__(app, name)
+
+                field = self.OneField(app, "first")
+                self.add_field(field)
+
+            def process_cancel(self, session):
+                self.parent.three.show(session)
+
+            def process_submit(self, session):
+                self.parent.two.show(session)
+
+            def render_title(self, session):
+                return "Step 1"
+
+            class OneField(StringField):
+                def render_title(self, session):
+                    return "Alpha"
+
+        class Two(FieldSubmitForm):
+            def __init__(self, app, name):
+                super(FormDemo.ThreeForm.Two, self).__init__(app, name)
+
+                field = self.TwoField(app, "second")
+                self.add_field(field)
+
+            def process_cancel(self, session):
+                self.parent.one.show(session)
+
+            def process_submit(self, session):
+                self.parent.three.show(session)
+
+            def render_title(self, session):
+                return "Step 2"
+
+            class TwoField(StringField):
+                def render_title(self, session):
+                    return "Beta"
+
+        class Three(SubmitForm):
+            def __init__(self, app, name):
+                super(FormDemo.ThreeForm.Three, self).__init__(app, name)
+
+            def process_cancel(self, session):
+                self.parent.two.show(session)
+
+            def process_submit(self, session):
+                self.parent.one.show(session)
+
+            def render_title(self, session):
+                return "Step 3"
+
+            def render_content(self, session):
+                return "All done!"

Modified: mgmt/trunk/wooly/python/wooly/forms.py
===================================================================
--- mgmt/trunk/wooly/python/wooly/forms.py	2009-06-17 19:33:19 UTC (rev 3455)
+++ mgmt/trunk/wooly/python/wooly/forms.py	2009-06-17 19:44:31 UTC (rev 3456)
@@ -9,11 +9,18 @@
     def __init__(self, app, name):
         super(Form, self).__init__(app, name)
 
+        self.errors = ListAttribute(app, "errors")
+        self.add_attribute(self.errors)
+
         self.form_params = set()
 
         self.origin = Parameter(app, "origin")
         self.add_parameter(self.origin)
 
+    # XXX need a better name
+    def has_errors(self, session):
+        return len(self.errors.get(session))
+
     def get_origin(self, session):
         origin = self.origin.get(session)
 
@@ -66,41 +73,35 @@
                      % (name, value))
 
 class FormError(object):
-    def __init__(self, message=None):
+    def __init__(self, message=None, widget=None):
         self.message = message
+        self.widget = widget
 
     def get_message(self, session):
         return self.message
 
 class FormErrorSet(ItemSet):
-    def __init__(self, app, name):
-        super(FormErrorSet, self).__init__(app, name)
+    def init(self):
+        super(FormErrorSet, self).init()
 
-        self.__errors = self.Errors(app, "errors")
-        self.add_attribute(self.__errors)
+        for anc in self.ancestors:
+            if isinstance(anc, Form):
+                self.form = anc
 
-    def add(self, session, error):
-        assert isinstance(error, FormError)
+        self.test(self.form, "Not inside a form")
 
-        self.__errors.get(session).append(error)
-
-    def get(self, session):
-        return self.__errors.get(session)
-
     def get_items(self, session, *args):
-        return self.get(session)
+        return self.form.errors.get(session)
 
     def do_render(self, session, *args):
-        if self.get(session):
+        items = self.get_items(session, *args)
+
+        if items:
             return super(FormErrorSet, self).do_render(session, *args)
 
     def render_item_content(self, session, item):
         return item.get_message(session)
 
-    class Errors(Attribute):
-        def get_default(self, session):
-            return list()
-
 class FormInput(Widget):
     def __init__(self, app, name, param):
         super(FormInput, self).__init__(app, name)
@@ -114,8 +115,7 @@
     def init(self):
         super(FormInput, self).init()
 
-        if self.param is None:
-            raise Exception("Parameter not set for %s" % self)
+        self.test(self.param, "Parameter not set")
 
         assert isinstance(self.param, Parameter)
 
@@ -123,11 +123,10 @@
             if isinstance(anc, Form):
                 self.form = anc
 
-        if self.form:
-            self.form.form_params.add(self.param)
-        else:
-            print "Warning: FormInput '%s' not inside a form" % self
+        self.test(self.form, "Not inside a form")
 
+        self.form.form_params.add(self.param)
+
     def get(self, session):
         return self.param.get(session)
 
@@ -246,7 +245,7 @@
     def __init__(self, app, name):
         super(FormButton, self).__init__(app, name, None)
 
-        self.param = BooleanParameter(app, "param")
+        self.param = BooleanParameter(app, "invoked")
         self.add_parameter(self.param)
 
     def do_process(self, session, *args):
@@ -296,13 +295,23 @@
     def __init__(self, app, name):
         super(FormField, self).__init__(app, name)
 
-        self.__errors = FormErrorSet(app, "errors")
-        self.add_child(self.__errors)
-
         self.css_class = "field"
+        self.form = None
 
+    def init(self):
+        super(FormField, self).init()
+
+        for anc in self.ancestors:
+            if isinstance(anc, Form):
+                self.form = anc
+
+        self.test(self.form, "Not inside a form")
+
+    def check(self, session):
+        pass
+
     def validate(self, session):
-        errors = self.__errors.get(session)
+        errors = self.form.errors.get(session)
 
         self.do_validate(session, errors)
 
@@ -311,12 +320,48 @@
     def do_validate(self, session, errors):
         pass
 
-    def render_field_help(self, session, *args):
+    def render_help(self, session, *args):
         pass
 
     def render_form_field_class(self, session, *args):
         return self.css_class
 
+class FormFieldSet(Widget):
+    def __init__(self, app, name):
+        super(FormFieldSet, self).__init__(app, name)
+
+        self.fields = list()
+
+    def add_field(self, field):
+        assert isinstance(field, FormField)
+
+        self.fields.append(field)
+        self.add_child(field)
+
+    def check(self, session):
+        for field in self.fields:
+            field.check(session)
+
+    # XXX get rid of this
+    def validate(self, session):
+        errors = list()
+
+        for field in self.fields:
+            errors.extend(field.validate(session))
+
+        return errors
+
+    def render_message(self, session, *args):
+        pass
+
+    def render_fields(self, session, *args):
+        writer = Writer()
+
+        for field in self.fields:
+            writer.write(field.render(session))
+
+        return writer.to_string()
+
 class ScalarField(FormField):
     def __init__(self, app, name, input):
         super(ScalarField, self).__init__(app, name)
@@ -444,16 +489,28 @@
 
 class ButtonForm(Form):
     def __init__(self, app, name):
-        super(ButtonForm. self).__init__(app, name)
+        super(ButtonForm, self).__init__(app, name)
 
+        self.error_display = FormErrorSet(app, "errors")
+        self.add_child(self.error_display)
+
+        self.content = None
+
         self.buttons = list()
 
     def add_button(self, button):
-        assert type(button) is FormButton
+        assert isinstance(button, FormButton)
 
         self.buttons.append(button)
         self.add_child(button)
 
+    def render_errors(self, session, *args):
+        if self.errors.get(session):
+            return self.error_display.render(session, *args)
+
+    def render_content(self, session, *args):
+        return self.content.render(session, *args)
+
     def render_buttons(self, session, *args):
         writer = Writer()
 
@@ -462,30 +519,87 @@
 
         return writer.to_string()
 
-class FieldForm(Form):
+class SubmitForm(ButtonForm):
     def __init__(self, app, name):
-        super(FieldForm, self).__init__(app, name)
+        super(SubmitForm, self).__init__(app, name)
 
-        self.fields = list()
+        self.return_url = Parameter(app, "return")
+        self.add_parameter(self.return_url)
 
-    def add_field(self, field):
-        assert isinstance(field, FormField)
+        self.cancel = self.Cancel(app, "cancel")
+        self.cancel.set_tab_index(201)
+        self.add_button(self.cancel)
 
-        self.fields.append(field)
-        self.add_child(field)
+        self.submit = self.Submit(app, "submit")
+        self.submit.set_tab_index(200)
+        self.add_button(self.submit)
 
-    def validate(self, session):
-        errors = list()
+    def submit(self, session):
+        self.submit.set(session, True)
 
-        for field in self.fields:
-            errors.extend(field.validate(session))
+    def cancel(self, session):
+        self.cancel.set(session, True)
 
-        return errors
+    def check(self, session):
+        pass
 
-    def render_fields(self, session, *args):
-        writer = Writer()
+    def do_process(self, session):
+        if self.cancel.get(session):
+            self.cancel.set(session, False)
 
-        for field in self.fields:
-            writer.write(field.render(session))
+            self.process_cancel(session)
+        elif self.submit.get(session):
+            self.submit.set(session, False)
 
-        return writer.to_string()
+            self.process_submit(session)
+        else:
+            self.process_display(session)
+
+    # XXX get rid of this?
+    def process_return(self, session):
+        url = self.return_url.get(session)
+        self.page.set_redirect_url(session, url)
+
+    def process_cancel(self, session):
+        self.process_return(session)
+
+    def process_submit(self, session):
+        pass
+
+    def process_display(self, session):
+        pass
+
+    def render_cancel_content(self, session):
+        return "Cancel"
+
+    def render_submit_content(self, session):
+        return "Submit"
+
+    class Cancel(FormButton):
+        def render_class(self, session, *args):
+            return "cancel"
+
+        def render_content(self, session):
+            return self.parent.render_cancel_content(session)
+
+    class Submit(FormButton):
+        def render_class(self, session):
+            return "submit"
+
+        def render_content(self, session):
+            return self.parent.render_submit_content(session)
+
+class FieldSubmitForm(SubmitForm):
+    def __init__(self, app, name):
+        super(FieldSubmitForm, self).__init__(app, name)
+
+        self.content = FormFieldSet(app, "fields")
+        self.add_child(self.content)
+
+    def add_field(self, field):
+        self.content.add_field(field)
+
+    def check(self, session):
+        super(FieldSubmitForm, self).check(session)
+
+        self.content.check(session)

Modified: mgmt/trunk/wooly/python/wooly/forms.strings
===================================================================
--- mgmt/trunk/wooly/python/wooly/forms.strings	2009-06-17 19:33:19 UTC (rev 3455)
+++ mgmt/trunk/wooly/python/wooly/forms.strings	2009-06-17 19:44:31 UTC (rev 3456)
@@ -1,12 +1,40 @@
 [FormErrorSet.css]
-ul.errors {
-  color: red;
+div.FormErrorSet {
+  margin: 1em auto;
+  border: none;
+  -moz-border-radius: 0.5em;
+  -webkit-border-radius: 0.5em;
+  padding: 1em;
+  width: 36em;
+  background-color: #fbb;
   font-weight: bold;
 }
 
+div.FormErrorSet > p {
+  margin: 0;
+}
+
+div.FormErrorSet > p > img {
+  vertical-align: -75%;
+  margin: 0 0.5em 0 0;
+}
+
+div.FormErrorSet > ul {
+  list-style: disc;
+  margin: 0 0 0 36px;
+  padding: 0.66em 2em;
+}
+
 [FormErrorSet.html]
-<ul class="errors">{items}</ul>
+<div class="FormErrorSet">
+  <p>
+    <img src="resource?name=warning-36.png"/>
+    Input errors
+  </p>
 
+  <ul>{items}</ul>
+</div>
+
 [FormErrorSet.item_html]
 <li>{item_content}</li>
 
@@ -70,60 +98,62 @@
 [OptionInputSet.item_html]
 <option value="{item_value}" {item_selected_attr}>{item_content}</option>
 
-[FormField.css]
-div.field {
-  padding: 0;
-  margin: 0;
+[FormField.html]
+<tr>
+  <th>
+    <div class="title">{title}</div>
+    <div class="help">{help}</div>
+  </th>
+  <td>{inputs}</td>
+</tr>
+
+[FormFieldSet.css]
+table.FormFieldSet {
+    width: 100%;
+    border-collapse: collapse;
 }
 
-div.field div.title {
-  font-weight: bold;
-  font-size: 0.9em;
-  float: left;
-  margin: 0 1em 1em 0;
+table.FormFieldSet > tbody > tr {
+    padding: 2em;
+    border-top: 1px dotted #ccc;
 }
-div.field div.field_help {
-	font-size: 0.9em;
-	color: #222;
+
+table.FormFieldSet > tbody > tr > th,
+table.FormFieldSet > tbody > tr > td {
+    padding: 0.5em 0;
+    border-top: 1px dotted #ccc;
+    margin: 0.25em 0;
 }
 
-div.field div.inputs {
-  margin: 0 0 1em 1em;
+table.FormFieldSet > tbody > tr:first-child > th {
+    border-top: hidden;
+    width: 25%;
 }
-div.field div.clear_left {
-	clear: left;
+
+table.FormFieldSet > tbody > tr:first-child > td {
+    border-top: hidden;
+    width: 75%;
 }
 
-/* optional styles for displaying a FormField */
-div.compact {
-	padding: 0;
-	margin: 0;
+table.FormFieldSet > tbody > tr > th {
+    width: 25%;
+    text-align: left;
+    vertical-align: top;
 }
-div.compact div.title {
-	float: left;
-	margin: 0;
-	width: 6em;
+
+table.FormFieldSet > tbody > tr > th > div.title {
+    font-weight: bold;
+    font-size: 0.9em;
 }
-div.compact div.field_help {
-	font-size: 0.9em;
-	color: #222;
+
+table.FormFieldSet > tbody > tr > td {
+    width: 75%;
 }
-div.compact div.inputs {
-	margin-left: 1em;
-}
-div.compact.first {
-	margin-top: 1em;
-}
-div.compact.last {
-	margin-bottom: 1em;
-}
 
-[FormField.html]
-<div class="{form_field_class}">
-  <div class="title">{title}</div> <div class="field_help">{field_help}</div><div class="clear_left"></div>
-  {errors}
-  <div class="inputs">{inputs}</div><div style="clear:left;"><!-- --></div>
-</div>
+[FormFieldSet.html]
+<table class="FormFieldSet">
+  <tbody>{fields}</tbody>
+</table>
 
 [RadioFieldOption.html]
 <div>
@@ -138,3 +168,54 @@
          tabindex="{tab_index}" {checked_attr} {disabled_attr}/>
   <label for="{id}">{title}</label>
 </div>
+
+[ButtonForm.css]
+form.ButtonForm {
+    background-color: #fafafa;
+    border: 2px solid #fff;
+    -moz-border-radius: 0.5em;
+    -webkit-border-radius: 0.5em;
+}
+
+form.ButtonForm > div.title {
+    font-weight: bold;
+    font-size: 1.1em;
+    background-color: #e7e7f7;
+    padding: 0.5em 0.75em;
+    margin-bottom: 0.5em;
+    -moz-border-radius: 0.35em 0.35em 0 0;
+    -webkit-border-radius: 0.35em 0.35em 0 0;
+}
+
+form.ButtonForm > div.content {
+    margin: 0.5em 1em;
+}
+
+form.ButtonForm > div.buttons {
+    text-align: right;
+    background-color: #e7e7f7;
+    padding: 0.5em;
+    margin-top: 0.5em;
+    -moz-border-radius: 0 0 0.35em 0.35em;
+    -webkit-border-radius: 0 0 0.35em 0.35em;
+}
+
+form.ButtonForm > div.buttons > button {
+    margin: 0 0 0 0.5em;
+}
+
+[ButtonForm.html]
+<form id="{id}" class="ButtonForm" method="post" action="?">
+  <div class="title">{title}</div>
+  <div class="content">
+    {errors}
+    {content}
+  </div>
+  <div class="buttons">{buttons}</div>
+  <div>{hidden_inputs}</div>
+</form>
+<script type="text/javascript">
+//<![CDATA[
+  wooly.doc().elembyid("{id}").node.elements[0].focus();
+//]]>
+</script>

Modified: mgmt/trunk/wooly/python/wooly/pages.py
===================================================================
--- mgmt/trunk/wooly/python/wooly/pages.py	2009-06-17 19:33:19 UTC (rev 3455)
+++ mgmt/trunk/wooly/python/wooly/pages.py	2009-06-17 19:44:31 UTC (rev 3456)
@@ -39,8 +39,8 @@
 
     def pop_frame(self, session):
         frame = self.get_frame(session)
-        #print "Popping current frame", frame
         self.set_frame(session, frame.frame)
+        return frame
 
     def set_default_frame(self, frame):
         self.page_frame.default = frame

Modified: mgmt/trunk/wooly/python/wooly/server.py
===================================================================
--- mgmt/trunk/wooly/python/wooly/server.py	2009-06-17 19:33:19 UTC (rev 3455)
+++ mgmt/trunk/wooly/python/wooly/server.py	2009-06-17 19:44:31 UTC (rev 3456)
@@ -181,13 +181,12 @@
 
         writer = Writer()
         writer.write("APPLICATION ERROR\n")
-        writer.write("\n----- python trace -----\n")
-        print_exc(None, writer)
 
         if session.debug:
-            writer.write("\n----- process trace -----\n")
-            session.debug.print_process_calls(writer)
-            writer.write("\n----- render trace -----\n")
-            session.debug.print_render_calls(writer)
+            writer.write("\n----- wooly -----\n\n")
+            session.debug.write(writer)
 
+        writer.write("\n----- python -----\n\n")
+        print_exc(None, writer)
+
         return writer.to_string()

Modified: mgmt/trunk/wooly/python/wooly/widgets.py
===================================================================
--- mgmt/trunk/wooly/python/wooly/widgets.py	2009-06-17 19:33:19 UTC (rev 3455)
+++ mgmt/trunk/wooly/python/wooly/widgets.py	2009-06-17 19:44:31 UTC (rev 3456)
@@ -164,6 +164,8 @@
     def __init__(self, app, name):
         super(ItemSet, self).__init__(app, name)
 
+        self.html_class = ItemSet.__name__
+
         self.items = Attribute(app, "items")
         self.add_attribute(self.items)
 

Modified: mgmt/trunk/wooly/python/wooly/widgets.strings
===================================================================
--- mgmt/trunk/wooly/python/wooly/widgets.strings	2009-06-17 19:33:19 UTC (rev 3455)
+++ mgmt/trunk/wooly/python/wooly/widgets.strings	2009-06-17 19:44:31 UTC (rev 3456)
@@ -51,7 +51,7 @@
 <li><a href="{tab_href}" {tab_class}>{tab_content}</a></li>
 
 [WidgetSet.html]
-<ul class="{class}">{widgets}</ul>
+<ul id="{id}" class="{class}">{widgets}</ul>
 
 [WidgetSet.widget_html]
 <li>{widget}</li>
@@ -74,7 +74,7 @@
 <a href="{href}" class="Toggle {state}">{content}</a>
 
 [ItemSet.html]
-<ul class="ItemSet">{items}</ul>
+<ul id="{id}" class="{class}">{items}</ul>
 
 [ItemSet.item_html]
 <li>{item_content}</li>
@@ -180,16 +180,20 @@
 <tr><th>{title}</th><td>{value}</td></tr>
 
 [ActionSet.css]
-ul.ActionSet li {
+ul.ActionSet {
+    list-style-type: none;
+    padding: 0;
+    margin: 0;
 }
 
 ul.ActionSet a:before, ul.ActionSet span:before {
-  content: "\00BB \0020";
-  font-weight: bold;
-  color: #dc9f2e;
+    content: "\00BB \0020";
+    font-weight: bold;
+    color: #dc9f2e;
 }
+
 ul.ActionSet span {
-	color: #666;
+    color: #666;
 }
 
 [ActionSet.html]




More information about the rhmessaging-commits mailing list