From f1615d1bef48724d5ed1c405453e490b01866f5a Mon Sep 17 00:00:00 2001 From: Stephan Richter Date: Wed, 30 May 2007 17:13:58 +0000 Subject: [PATCH] Implemented request by David Pratt to show completion conditioning on the finish button. --- src/z3c/formdemo/wizard/interfaces.py | 18 +++++++++++++ src/z3c/formdemo/wizard/wizard.py | 39 +++++++++++++++++++++++++-- 2 files changed, 55 insertions(+), 2 deletions(-) diff --git a/src/z3c/formdemo/wizard/interfaces.py b/src/z3c/formdemo/wizard/interfaces.py index d9890a7..f3e1c03 100644 --- a/src/z3c/formdemo/wizard/interfaces.py +++ b/src/z3c/formdemo/wizard/interfaces.py @@ -35,6 +35,24 @@ class IForwardButton(interfaces.IButton): class IStep(zope.interface.Interface): """An interface marking a step sub-form.""" + def isComplete(): + """Determines whether a step is complete.""" + +class IWizard(zope.interface.Interface): + """An interface marking the controlling wizard form.""" + + def isComplete(): + """Determines whether the wizard is complete.""" + + def getCurrentStep(): + """Return the current step as an instance.""" + + def isFirstStep(): + """Determine whether the current step is the first one.""" + + def isLastStep(): + """Determine whether the current step is the last one.""" + # ----[ Content Interfaces ]-------------------------------------------------- diff --git a/src/z3c/formdemo/wizard/wizard.py b/src/z3c/formdemo/wizard/wizard.py index 561f247..5d9f650 100644 --- a/src/z3c/formdemo/wizard/wizard.py +++ b/src/z3c/formdemo/wizard/wizard.py @@ -16,12 +16,13 @@ $Id$ """ __docformat__ = "reStructuredText" +import zope.component import zope.interface from zope.app.session.interfaces import ISession from zope.viewlet.viewlet import CSSViewlet from z3c.form import button, field, form, subform -from z3c.form.interfaces import IWidgets +from z3c.form.interfaces import IWidgets, IDataManager from z3c.formui import layout from z3c.formdemo.wizard import interfaces @@ -48,7 +49,7 @@ class IWizardButtons(zope.interface.Interface): finish = button.Button( title=u'Finish', - condition=lambda form: form.isLastStep()) + condition=lambda form: form.isLastStep() and form.isComplete()) zope.interface.alsoProvides( finish, (interfaces.ISaveButton, interfaces.IForwardButton)) @@ -58,6 +59,22 @@ class Step(subform.EditSubForm): name = None label = None + def isComplete(self): + """See interfaces.IStep + + This implementation checks that all required fields have been filled + out. + """ + content = self.getContent() + for field in self.fields.values(): + if not field.field.required: + continue + dm = zope.component.getMultiAdapter( + (content, field.field), IDataManager) + if dm.get() is field.field.missing_value: + return False + return True + @button.handler(interfaces.ISaveButton) def handleAllButtons(self, action): self.handleApply(self, action) @@ -77,6 +94,7 @@ def forwardActions(self): class Wizard(layout.FormLayoutSupport, form.Form): + zope.interface.implements(interfaces.IWizard) sessionKey = 'z3c.formdemo.wizard' buttons = button.Buttons(IWizardButtons) @@ -85,7 +103,15 @@ class Wizard(layout.FormLayoutSupport, form.Form): steps = None step = None + def isComplete(self): + for name, StepClass in self.steps: + step = StepClass(self.getContent(), self.request, self) + if not step.isComplete(): + return False + return True + def getCurrentStep(self): + """See interfaces.IWizard""" session = ISession(self.request)[self.sessionKey] if 'step' in self.request: name = self.request['step'] @@ -99,9 +125,11 @@ def getCurrentStep(self): return inst def isFirstStep(self): + """See interfaces.IWizard""" return isinstance(self.step, self.steps[0][1]) def isLastStep(self): + """See interfaces.IWizard""" return isinstance(self.step, self.steps[-1][1]) @property @@ -151,6 +179,13 @@ def handleNext(self, action): self.request.response.redirect(url) + @button.handler(IWizardButtons['save']) + def handleSave(self, action): + # Saving can change the conditions for the finish button, so we need + # to reconstruct the button actions, since we do not redirect. + self.updateActions() + + @button.handler(IWizardButtons['finish']) def handleFinish(self, action): session = ISession(self.request)[self.sessionKey]