Source code for traitsui.editors.tuple_editor
# (C) Copyright 2004-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!
""" Defines the tuple editor factory for all traits user interface toolkits.
"""
from traits.api import (
BaseTuple,
Bool,
HasTraits,
List,
Str,
Int,
Any,
TraitType,
)
from traits.trait_base import SequenceTypes
from traitsui.editor import Editor
from traitsui.editor_factory import EditorFactory
from traitsui.group import Group
from traitsui.item import Item
from traitsui.view import View
[docs]class TupleEditor(EditorFactory):
"""Editor factory for tuple editors."""
# -------------------------------------------------------------------------
# Trait definitions:
# -------------------------------------------------------------------------
#: Trait definitions for each tuple field
types = Any()
#: Labels for each of the tuple fields
labels = List(Str)
#: Editors for each of the tuple fields:
editors = List(EditorFactory)
#: Number of tuple fields or rows
cols = Int(1)
#: Is user input set on every keystroke? This is applied to every field
#: of the tuple, provided the field does not already have an 'auto_set'
#: metadata or an editor defined.
auto_set = Bool(True)
#: Is user input set when the Enter key is pressed? This is applied to
#: every field of the tuple, provided the field does not already have an
#: 'enter_set' metadata or an editor defined.
enter_set = Bool(False)
[docs]class SimpleEditor(Editor):
"""Simple style of editor for tuples.
The editor displays an editor for each of the fields in the tuple, based on
the type of each field.
"""
[docs] def init(self, parent):
"""Finishes initializing the editor by creating the underlying toolkit
widget.
"""
self._ts = ts = TupleStructure(self)
self._ui = ui = ts.view.ui(ts, parent, kind="subpanel").trait_set(
parent=self.ui
)
self.control = ui.control
self.set_tooltip()
[docs] def update_editor(self):
"""Updates the editor when the object trait changes external to the
editor.
"""
ts = self._ts
for i, value in enumerate(self.value):
setattr(ts, "f%d" % i, value)
[docs] def get_error_control(self):
"""Returns the editor's control for indicating error status."""
return self._ui.get_error_controls()
[docs]class TupleStructure(HasTraits):
"""Creates a view containing items for each field in a tuple."""
# -------------------------------------------------------------------------
# Trait definitions:
# -------------------------------------------------------------------------
#: Editor this structure is linked to
editor = Any()
#: The constructed View for the tuple
view = Any()
#: Number of tuple fields
fields = Int()
def __init__(self, editor):
"""Initializes the object."""
super().__init__(editor=editor)
factory = editor.factory
types = factory.types
labels = factory.labels
editors = factory.editors
cols = factory.cols
# Get the tuple we are mirroring:
object = editor.value
# For each tuple field, add a trait with the appropriate trait
# definition and default value:
content = []
self.fields = len(object)
len_labels = len(labels)
len_editors = len(editors)
if types is None:
type = editor.value_trait.handler
if isinstance(type, BaseTuple):
types = type.types
if not isinstance(types, SequenceTypes):
types = [types]
len_types = len(types)
if len_types == 0:
types = [Any]
len_types = 1
for i, value in enumerate(object):
type = types[i % len_types]
auto_set = enter_set = None
if isinstance(type, TraitType):
auto_set = type.auto_set
enter_set = type.enter_set
if auto_set is None:
auto_set = editor.factory.auto_set
if enter_set is None:
enter_set = editor.factory.enter_set
label = ""
if i < len_labels:
label = labels[i]
field_editor = None
if i < len_editors:
field_editor = editors[i]
name = "f%d" % i
self.add_trait(
name,
type(
value,
event="field",
auto_set=auto_set,
enter_set=enter_set,
),
)
item = Item(name=name, label=label, editor=field_editor)
if cols <= 1:
content.append(item)
else:
if (i % cols) == 0:
group = Group(orientation="horizontal")
content.append(group)
group.content.append(item)
self.view = View(Group(show_labels=(len_labels != 0), *content))
def _field_changed(self, name, old, new):
"""Updates the underlying tuple when any field changes value."""
index = int(name[1:])
value = self.editor.value
if new != value[index]:
self.editor.value = tuple(
[getattr(self, "f%d" % i) for i in range(self.fields)]
)
# This alias is deprecated and will be removed in TraitsUI 8.
ToolkitEditorFactory = TupleEditor