diff -r 000000000000 -r 7a0b409fd4b8 src/pyams_form/interfaces/form.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/pyams_form/interfaces/form.py Thu Feb 19 10:55:46 2015 +0100 @@ -0,0 +1,425 @@ +# +# Copyright (c) 2008-2015 Thierry Florac +# All Rights Reserved. +# +# This software is subject to the provisions of the Zope Public License, +# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. +# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED +# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS +# FOR A PARTICULAR PURPOSE. +# +from pyams_template.template import template_config + +__docformat__ = 'restructuredtext' + +# import standard library + +# import interfaces +from pyams_viewlet.interfaces import IViewletManager +from pyramid.interfaces import IView +from z3c.form.interfaces import INPUT_MODE, ISubForm, IWidget, IFormLayer as IBaseFormLayer, ISubmitWidget +from zope.interface.interfaces import IObjectEvent, ObjectEvent +from zope.lifecycleevent.interfaces import IObjectCreatedEvent, IObjectModifiedEvent + +# import packages +from pyams_form.schema import ResetButton, CloseButton +from z3c.form import button +from zope.interface import implementer, Interface, Attribute +from zope.lifecycleevent import ObjectCreatedEvent, ObjectModifiedEvent +from zope.schema import TextLine, List, Object, Bool, Choice, Dict + +from pyams_form import _ + + +# +# Form interfaces +# + +class IFormLayer(IBaseFormLayer): + """Base PyAMS form layer""" + + +class IBaseForm(IView): + """Base form interface""" + + +@template_config(template='../templates/form.pt', layer=IFormLayer) +class IForm(IBaseForm): + """Default form interface""" + + skin = TextLine(title="Skin name", + default="PyAMS default skin", + required=False) + + edit_permission = TextLine(title="Required edit permission", + required=False, + default='manage') + + def get_skin(self): + """Get skin associated with this form""" + + title = TextLine(title="Form title") + + legend = TextLine(title="Form legend", + required=False) + + css_class = TextLine(title="CSS class", + default='ams-form form-horizontal') + + icon_css_class = TextLine(title="Legend CSS class", + required=False) + + autocomplete = Choice(title="Auto-complete", + values=('on', 'off'), + default='on') + + warn_on_change = Choice(title="Warn on unsaved change?", + values=('default', True, False), + default='default') + + label_css_class = TextLine(title="Labels CSS class", + required=False, + default='control-label col-md-3') + + input_css_class = TextLine(title="Inputs CSS class", + required=False, + default='col-md-9') + + display_hints_on_widgets = Bool(title="Display hints on input widgets?", + required=True, + default=False) + + handle_upload = Bool(title="Handle uploads in form?", + description="Set to true when form handle uploads to get progress bar", + required=True, + default=False) + + callbacks = Dict(title="Widgets validation callbacks", + key_type=TextLine(), + value_type=TextLine(), + required=False) + + subforms = List(title="Sub-forms", + value_type=Object(schema=ISubForm), + required=False, + readonly=True) + + subforms_legend = TextLine(title="Sub-forms legend", + required=False) + + tabforms = List(title="Tab-forms", + value_type=Object(schema=ISubForm), + required=False, + readonly=True) + + is_dialog = Attribute("Check to know if current form is in a modal dialog") + + def get_form_action(self): + """Get form action URL""" + + def get_widget_callback(self, widget): + """Get submit callback associated with a given widget""" + + def update_content(self, object, data): + """Update given object with form data""" + + def get_submit_output(self, writer, changes): + """Get submit output""" + + +class IAJAXForm(Interface): + """AJAX form attributes""" + + ajax_handler = TextLine(title="AJAX handler", + description="Name of a JSON view handling AJAX requests", + required=False) + + form_options = Dict(title="AJAX data options", + required=False) + + form_target = TextLine(title="Form submit target", + description="Form content target for HTML and text content types", + required=False, + default='#content') + + ajax_callback = TextLine(title="AJAX submit callback", + description="Name of a custom form submit callback", + required=False) + + def get_form_options(self): + """Get form options in JSON format""" + + def get_ajax_handler(self): + """Get absolute URL of AJAX handler""" + + def get_ajax_errors(self): + """Get AJAX errors""" + + def get_ajax_output(self, changes): + """Get AJAX POST output""" + + +class IFormWidgetsGroup(Interface): + """Form widgets group interface""" + + id = TextLine(title="Group ID", + required=False) + + widgets = List(title="Group's widgets list", + value_type=Object(schema=IWidget)) + + legend = TextLine(title="Group legend", + required=False) + + help = TextLine(title="Group help", + required=False) + + css_class = TextLine(title="CSS class", + required=False, + readonly=True) + + switch = Bool(title="Switchable group?", + required=True, + default=False) + + checkbox_switch = Bool(title="Group switched via checkbox?", + required=True, + default=False) + + checkbox_field = TextLine(title="Field name matching switch checkbox?", + required=False) + + checkbox_widget = Object(schema=IWidget, + required=False, + readonly=True) + + hide_if_empty = Bool(title="Hide group if empty?", + description="""If 'Yes', a switchable group containing only """ + """widgets with default values is hidden""", + required=True, + default=False) + + visible = Attribute("Visible group?") + + visible_widgets = Attribute("Visible widgets") + + switchable = Attribute("Switchable group?") + + switcher_state = Attribute("Switcher state") + + checker_state = Attribute("Checker state") + + +class IGroupsBasedForm(IBaseForm): + """Groups based form""" + + groups = List(title="Form widgets groups", + value_type=Object(IFormWidgetsGroup)) + + def add_group(self, group): + """Add given group to form groups""" + + +class IViewletsBasedForm(IBaseForm): + """Viewlets based form""" + + providers = List(title="List of content providers names included in this form", + value_type=TextLine(), + required=True) + + +class IInnerSubForm(ISubForm): + """Inner sub-form interface""" + + +class IInnerTabForm(ISubForm): + """Inner tab-form interface""" + + +class IViewletSubForm(ISubForm): + """Inner viewlet form interface""" + + legend = Attribute("Sub-form legend") + + switchable = Attribute("Can the sub-form be hidden ?") + + visible = Attribute("Is the sub-form initially visible ?") + + callbacks = Dict(title="Widgets callbacks", + key_type=TextLine(), + value_type=TextLine()) + + def get_widget_callback(self, widget): + """Get submit callback associated with a given widget""" + + +class ICustomExtractSubForm(ISubForm): + """SubForm interface with custom extract method""" + + def extract(self): + """Custom data and errors extraction method""" + + +class ICustomUpdateSubForm(ISubForm): + """SubForm interface with custom update method""" + + def update_content(self, object, data): + """Custom content update method""" + + +class ISearchForm(Interface): + """Default search form interface""" + + def get_search_results(self): + """Get search results""" + + +# +# Form viewlets +# + +class IFormViewletsManager(IViewletManager): + """Base forms viewlets manager interface""" + + +class IFormPrefixViewletsManager(IFormViewletsManager): + """Form prefix viewlets manager interface""" + + +class IWidgetsPrefixViewletsManager(IFormViewletsManager): + """Form widgets prefix viewlets manager interface""" + + +class IWidgetsSuffixViewletsManager(IFormViewletsManager): + """Form widgets suffix viewlets manager interface""" + + +class IFormSuffixViewletsManager(IFormViewletsManager): + """Form suffix viewlets manager interface""" + + +# +# Form buttons +# + +def check_submit_button(form): + """Check form and widgets mode before displaying submit button""" + if form.mode != INPUT_MODE: + return False + for widget in form.widgets.values(): + if widget.mode == INPUT_MODE: + return True + if IForm.providedBy(form): + for subform in form.subforms: + for widget in subform.widgets.values(): + if widget.mode == INPUT_MODE: + return True + + +class IAddFormButtons(Interface): + """Default add form buttons""" + + reset = ResetButton(name='reset', title=_("Reset")) + add = button.Button(name='add', title=_("Add"), condition=check_submit_button) + + +class IModalAddFormButtons(Interface): + """Modal add form buttons""" + + close = CloseButton(name='close', title=_("Close")) + add = button.Button(name='add', title=_("Add"), condition=check_submit_button) + + +class IEditFormButtons(Interface): + """Default edit form buttons""" + + reset = ResetButton(name='reset', title=_("Reset")) + submit = button.Button(name='submit', title=_("Submit"), condition=check_submit_button) + + +class IModalEditFormButtons(Interface): + """Modal edit form buttons""" + + close = CloseButton(name='close', title=_("Close")) + submit = button.Button(name='submit', title=_("Submit"), condition=check_submit_button) + + +class IModalDisplayFormButtons(Interface): + """Modal display form buttons""" + + close = CloseButton(name='close', title=_("Close")) + + +# +# Inner form interface +# + +@template_config(template='../templates/inner-form.pt', layer=IFormLayer) +class IInnerForm(Interface): + """Inner form marker interface""" + + +@template_config(template='../templates/widget-form.pt', layer=IFormLayer) +class IWidgetForm(Interface): + """Widget form marker interface""" + + widget_icon_class = TextLine(title="Widget icon class", + default="fa fa-edit") + + +# +# Form buttons widgets +# + +class IResetWidget(ISubmitWidget): + """Reset button widget interface""" + + +class ICloseWidget(ISubmitWidget): + """Close button widget interface""" + + +# +# Form events +# + +class IFormCreatedEvent(IObjectEvent): + """Form created event interface""" + + +@implementer(IFormCreatedEvent) +class FormCreatedEvent(ObjectEvent): + """Form created event""" + + +class IViewObjectEvent(IObjectEvent): + """View object event interface""" + + view = Attribute("View in which event was fired") + + +class IFormObjectCreatedEvent(IObjectCreatedEvent, IViewObjectEvent): + """Event fired after final object creation""" + + +@implementer(IFormObjectCreatedEvent) +class FormObjectCreatedEvent(ObjectCreatedEvent): + """Form object created event""" + + def __init__(self, object, view): + self.object = object + self.view = view + + +class IFormObjectModifiedEvent(IObjectModifiedEvent, IViewObjectEvent): + """Event fired after object modification""" + + +@implementer(IFormObjectModifiedEvent) +class FormObjectModifiedEvent(ObjectModifiedEvent): + """Form object modified event""" + + def __init__(self, object, view, *descriptions): + ObjectModifiedEvent.__init__(self, object, *descriptions) + self.view = view