Repository URL to install this package:
Version:
7.4.4 ▾
|
# (C) Copyright 2005-2022 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!
""" Classes to provide a switcher. """
import wx
from wx.lib.scrolledpanel import ScrolledPanel as wxScrolledPanel
from traits.api import HasTraits, Int
class SwitcherModel(HasTraits):
""" Base class for switcher models. """
# The index of the selected 'page'.
selected = Int(-1)
def __init__(self):
""" Creates a new switcher model. """
# The items to display in the switcher control.
self.items = [] # (str label, object value)
return
# ------------------------------------------------------------------------
# 'SwitcherModel' interface.
# ------------------------------------------------------------------------
def create_page(self, parent, index):
""" Creates a page for the switcher panel. """
raise NotImplementedError()
class SwitcherControl(wx.Panel):
""" The default switcher control (a combo box). """
def __init__(self, parent, id, model, label=None, **kw):
""" Creates a new switcher control. """
# Base-class constructor.
wx.Panel.__init__(self, parent, id, **kw)
# The switcher model that we are a controller for.
self.model = model
# The optional label.
self.label = label
# Create the widget!
self._create_widget(model, label)
# Listen for when the selected item in the model is changed.
model.observe(self._on_selected_changed, "selected")
return
# ------------------------------------------------------------------------
# Trait event handlers.
# ------------------------------------------------------------------------
def _on_selected_changed(self, event):
""" Called when the selected item in the model is changed. """
selected = event.new
self.combo.SetSelection(selected)
return
# ------------------------------------------------------------------------
# wx event handlers.
# ------------------------------------------------------------------------
def _on_combobox(self, event):
""" Called when the combo box selection is changed. """
combo = event.GetEventObject()
# Update the model.
self.model.selected = combo.GetSelection()
return
# ------------------------------------------------------------------------
# Private interface.
# ------------------------------------------------------------------------
def _create_widget(self, model, label):
""" Creates the widget."""
self.sizer = sizer = wx.BoxSizer(wx.VERTICAL)
self.SetSizer(sizer)
self.SetAutoLayout(True)
# Switcher combo.
sizer.Add(self._combo(self, model, label), 1, wx.EXPAND)
# Resize the panel to match the sizer's minimal size.
sizer.Fit(self)
def _combo(self, parent, model, label):
""" Creates the switcher combo. """
sizer = wx.BoxSizer(wx.HORIZONTAL)
# Label.
if label is not None:
text = wx.StaticText(parent, -1, label)
sizer.Add(text, 0, wx.ALIGN_CENTER | wx.ALL, 5)
# Combo.
self.combo = combo = wx.ComboBox(
parent, -1, style=wx.CB_DROPDOWN | wx.CB_READONLY
)
sizer.Add(combo, 1, wx.EXPAND | wx.ALIGN_CENTER | wx.ALL, 5)
# Ask the model for the available options.
items = model.items
if len(items) > 0:
for name, data in model.items:
combo.Append(name, data)
# Listen for changes to the selected item.
self.Bind(wx.EVT_COMBOBOX, self._on_combobox, id=combo.GetId())
# If the model's selected variable has been set ...
if model.selected != -1:
combo.SetSelection(model.selected)
return sizer
class SwitcherPanel(wxScrolledPanel):
""" The default switcher panel. """
def __init__(self, parent, id, model, label=None, cache=True, **kw):
# Base-class constructor.
wxScrolledPanel.__init__(self, parent, id, **kw)
self.SetupScrolling()
# The switcher model that we are a panel for.
self.model = model
# Should we cache pages as we create them?
self.cache = cache
# The page cache (if caching was requested).
self._page_cache = {}
# The currently displayed page.
self.current = None
# Create the widget!
self._create_widget(model, label)
return
# ------------------------------------------------------------------------
# 'SwitcherPanel' interface.
# ------------------------------------------------------------------------
def show_page(self, index):
""" Shows the page at the specified index. """
self._show_page(index)
return
# ------------------------------------------------------------------------
# Private interface.
# ------------------------------------------------------------------------
def _create_widget(self, model, label):
""" Creates the widget. """
self.sizer = sizer = wx.BoxSizer(wx.VERTICAL)
self.SetSizer(sizer)
self.SetAutoLayout(True)
# Nothing to add here as we add the panel contents lazily!
pass
# Resize the panel to match the sizer's minimal size.
sizer.Fit(self)
def _show_page(self, index):
""" Shows the page at the specified index. """
# If a page is already displayed then hide it.
if self.current is not None:
self.current.Show(False)
self.sizer.Remove(self.current)
# Is the page in the cache?
page = self._page_cache.get(index)
if not self.cache or page is None:
# If not then ask our panel factory to create it.
page = self.model.create_page(self, index)
# Add it to the cache!
self._page_cache[index] = page
# Display the page.
self.sizer.Add(page, 15, wx.EXPAND, 5)
page.Show(True)
self.current = page
# Force a new layout of the sizer's children but KEEPING the current
# dimension.
self.sizer.Layout()
class Switcher(wx.Panel):
""" A switcher. """
def __init__(self, parent, id, model, label=None, **kw):
""" Create a new switcher. """
# Base-class constructor.
wx.Panel.__init__(self, parent, id, **kw)
# The model that we are a switcher for.
self.model = model
# Create the widget!
self._create_widget(model, label)
return
# ------------------------------------------------------------------------
# Private interface.
# ------------------------------------------------------------------------
def _create_widget(self, model, label):
""" Creates the widget. """
self.sizer = sizer = wx.BoxSizer(wx.VERTICAL)
self.SetSizer(sizer)
self.SetAutoLayout(True)
# Switcher control.
self.control = control = SwitcherControl(self, -1, model, label)
sizer.Add(control, 0, wx.EXPAND)
# Switcher panel.
self.panel = panel = SwitcherPanel(self, -1, model, label)
sizer.Add(panel, 1, wx.EXPAND)
# Resize the panel to match the sizer's minimal size.
sizer.Fit(self)
return