Source code for pyface.wizard.chained_wizard_controller
# (C) Copyright 2005-2023 Enthought, Inc., Austin, TX
# All rights reserved.
#
# This software is provided without warranty under the terms of the BSD
# license included in LICENSE.txt and may be redistributed only under
# the conditions described in the aforementioned license. The license
# is also available online at http://www.enthought.com/licenses/BSD.txt
#
# Thanks for using Enthought open source!
""" A wizard controller that can be chained with others. """
from traits.api import Instance, observe
from .i_wizard_controller import IWizardController
from .wizard_controller import WizardController
[docs]class ChainedWizardController(WizardController):
""" A wizard controller that can be chained with others. """
# 'ChainedWizardController' interface ---------------------------------#
# The next chained wizard controller.
next_controller = Instance(IWizardController)
# ------------------------------------------------------------------------
# 'IWizardController' interface.
# ------------------------------------------------------------------------
[docs] def get_next_page(self, page):
""" Returns the next page. """
next_page = None
if page in self._pages:
if page is not self._pages[-1]:
index = self._pages.index(page)
next_page = self._pages[index + 1]
else:
if self.next_controller is not None:
next_page = self.next_controller.get_first_page()
else:
if self.next_controller is not None:
next_page = self.next_controller.get_next_page(page)
return next_page
[docs] def get_previous_page(self, page):
""" Returns the previous page. """
if page in self._pages:
index = self._pages.index(page)
previous_page = self._pages[index - 1]
else:
if self.next_controller is not None:
if self.next_controller.is_first_page(page):
previous_page = self._pages[-1]
else:
previous_page = self.next_controller.get_previous_page(
page
)
else:
previous_page = None
return previous_page
[docs] def is_first_page(self, page):
""" Is the page the first page? """
return page is self._pages[0]
[docs] def is_last_page(self, page):
""" Is the page the last page? """
if page in self._pages:
# If page is not this controller's last page, then it cannot be
# *the* last page.
if page is not self._pages[-1]:
is_last = False
# Otherwise, it is *the* last page if this controller has no next
# controller or the next controller has no pages.
else:
if self.next_controller is None:
is_last = True
else:
is_last = self.next_controller.is_last_page(page)
else:
if self.next_controller is not None:
is_last = self.next_controller.is_last_page(page)
elif len(self._pages) > 0:
is_last = False
else:
is_last = True
return is_last
[docs] def dispose_pages(self):
""" Dispose the wizard's pages. """
for page in self._pages:
page.dispose_page()
if self.next_controller is not None:
self.next_controller.dispose_pages()
return
# ------------------------------------------------------------------------
# 'ChainedWizardController' interface.
# ------------------------------------------------------------------------
def _get_pages(self):
""" Returns the pages in the wizard. """
pages = self._pages[:]
if self.next_controller is not None:
pages.extend(self.next_controller.pages)
return pages
def _set_pages(self, pages):
""" Sets the pages in the wizard. """
self._pages = pages
return
# ------------------------------------------------------------------------
# Private interface.
# ------------------------------------------------------------------------
def _update(self):
""" Checks the completion status of the controller. """
# The entire wizard is complete when ALL pages are complete.
for page in self._pages:
if not page.complete:
self.complete = False
break
else:
if self.next_controller is not None:
# fixme: This is a abstraction leak point, since _update is not
# part of the wizard_controller interface!
self.next_controller._update()
self.complete = self.next_controller.complete
else:
self.complete = True
return
# Trait event handlers -------------------------------------------------
# Static ----
@observe("current_page")
def _reset_observers_on_current_page_and_update(self, event):
""" Called when the current page is changed. """
old, new = event.old, event.new
if old is not None:
old.observe(
self._on_page_complete, "complete", remove=True
)
if new is not None:
new.observe(self._on_page_complete, "complete")
if self.next_controller is not None:
self.next_controller.current_page = new
self._update()
@observe("next_controller")
def _reset_observers_on_next_controller_and_update(self, event):
""" Called when the next controller is changed. """
old, new = event.old, event.new
if old is not None:
old.observe(
self._on_controller_complete, "complete", remove=True
)
if new is not None:
new.observe(self._on_controller_complete, "complete")
self._update()
return
# Dynamic ----
def _on_controller_complete(self, event):
""" Called when the next controller's complete state changes. """
self._update()
def _on_page_complete(self, event):
""" Called when the current page is complete. """
self._update()
return