Repository URL to install this package:
|
Version:
7.2.1 ▾
|
# (C) Copyright 2004-2021 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!
""" Defines the base class for wxPython editors.
"""
import wx
from traits.api import HasTraits, Int, Instance, Str, Callable
# CIRCULAR IMPORT FIXME:
# We are importing from the source instead of from the api in order to
# avoid circular imports. The 'toolkit.py' file imports from 'helper' which in
# turns imports from this file. Therefore, trying to import
# 'traitsui.wx' (which imports the toolkit) will lead to importing
# all of the editor factories declared in traitsui.api. In addition,# some of the editor factories have a Color trait defined, and this will lead
# to an import of the wx 'toolkit' causing a circular import problem.
# Another solution could be to move the GroupEditor object from helper to this
# file.
from traitsui.editor import Editor as UIEditor
from .constants import WindowColor, OKColor, ErrorColor
class Editor(UIEditor):
""" Base class for wxPython editors for Traits-based UIs.
"""
# -------------------------------------------------------------------------
# Trait definitions:
# -------------------------------------------------------------------------
#: Style for embedding control in a sizer:
layout_style = Int(wx.EXPAND)
#: The maximum extra padding that should be allowed around the editor:
border_size = Int(4)
def _control_changed(self, control):
""" Handles the **control** trait being set.
"""
if control is not None:
control._editor = self
def set_focus(self):
""" Assigns focus to the editor's underlying toolkit widget.
"""
if self.control is not None:
self.control.SetFocus()
def update_editor(self):
""" Updates the editor when the object trait changes externally to the
editor.
"""
new_value = self.str_value
if self.control.GetValue() != new_value:
self.control.SetValue(new_value)
def error(self, excp):
""" Handles an error that occurs while setting the object's trait value.
"""
dlg = wx.MessageDialog(
self.control,
str(excp),
self.description + " value error",
wx.OK | wx.ICON_INFORMATION,
)
dlg.ShowModal()
dlg.Destroy()
def set_tooltip_text(self, control, text):
""" Sets the tooltip for a specified control.
"""
control.SetToolTip(text)
def _enabled_changed(self, enabled):
""" Handles the **enabled** state of the editor being changed.
"""
control = self.control
if control is not None:
control.Enable(enabled)
control.Refresh()
if self.label_control is not None:
self.label_control.Enable(enabled)
self.label_control.Refresh()
def _visible_changed(self, visible):
""" Handles the **visible** state of the editor being changed.
"""
control = self.control
parent = control.GetParent()
# Handle the case where the item whose visibility has changed is a
# notebook page:
sizer = parent.GetSizer()
from pyface.dock.api import DockSizer
if isinstance(sizer, DockSizer):
dock_controls = sizer.GetContents().get_controls(False)
for dock_control in dock_controls:
if dock_control.control is control:
dock_control.visible = visible
sizer.Layout()
# Handle a normal item:
else:
if self.label_control is not None:
self.label_control.Show(visible)
control.Show(visible)
# If only control.Layout() is called there are certain cases where
# the newly visible items are sized incorrectly (see ticket 1797)
if parent is None:
control.Layout()
else:
parent.Layout()
def get_error_control(self):
""" Returns the editor's control for indicating error status.
"""
return self.control
def in_error_state(self):
""" Returns whether or not the editor is in an error state.
"""
return False
def set_error_state(self, state=None, control=None):
""" Sets the editor's current error state.
"""
if state is None:
state = self.invalid
state = state or self.in_error_state()
if control is None:
control = self.get_error_control() or []
if not isinstance(control, list):
control = [control]
for item in control:
if state:
color = ErrorColor
if getattr(item, "_ok_color", None) is None:
item._ok_color = item.GetBackgroundColour()
else:
color = getattr(item, "_ok_color", None)
if color is None:
color = OKColor
if isinstance(item, wx.Panel):
color = WindowColor
item.SetBackgroundColour(color)
item.Refresh()
def _invalid_changed(self, state):
""" Handles the editor's invalid state changing.
"""
self.set_error_state()
class EditorWithList(Editor):
""" Editor for an object that contains a list.
"""
# -------------------------------------------------------------------------
# Trait definitions:
# -------------------------------------------------------------------------
#: Object containing the list being monitored
list_object = Instance(HasTraits)
#: Name of the monitored trait
list_name = Str()
#: Function used to evaluate the current list object value:
list_value = Callable()
def init(self, parent):
""" Initializes the object.
"""
factory = self.factory
name = factory.name
if name != "":
self.list_object, self.list_name, self.list_value = self.parse_extended_name(
name
)
else:
self.list_object, self.list_name = factory, "values"
self.list_value = lambda: factory.values
self.list_object.on_trait_change(
self._list_updated, self.list_name + "[]", dispatch="ui"
)
self._list_updated()
def dispose(self):
""" Disconnects the listeners set up by the constructor.
"""
self.list_object.on_trait_change(
self._list_updated, self.list_name + "[]", remove=True
)
super().dispose()
def _list_updated(self):
""" Handles the monitored trait being updated.
"""
self.list_updated(self.list_value())
def list_updated(self, values):
""" Handles the monitored list being updated.
"""
raise NotImplementedError
class EditorFromView(Editor):
""" An editor generated from a View object.
"""
def init(self, parent):
""" Initializes the object.
"""
self._ui = ui = self.init_ui(parent)
if ui.history is None:
ui.history = self.ui.history
self.control = ui.control
def init_ui(self, parent):
""" Creates and returns the traits UI defined by this editor.
(Must be overridden by a subclass).
"""
raise NotImplementedError
def update_editor(self):
""" Updates the editor when the object trait changes externally to the
editor.
"""
# Normally nothing needs to be done here, since it should all be handled
# by the editor's internally created traits UI:
pass
def dispose(self):
""" Disposes of the editor.
"""
self._ui.dispose()
super().dispose()