"""Graphical interactors.
This module provides five types of interactors:
- :class:`GButton`: A clickable button.
- :class:`GCheckBox`: A checkable box.
- :class:`GSlider`: A slider between numeric values.
- :class:`GChooser`: A list of selectable items.
- :class:`GTextField`: A single-line string entry.
"""
import campy.graphics.gobjects as gobjects
import campy.private.platform as _platform
from campy.graphics.gevents import *
[docs]class GInteractor(gobjects.GObject):
"""Superclass of all graphical interactors.
In most applications, interactors will be added to one region in a
:class:`GWindow`, but interactors can also be placed in specific positions
in a :class:`GCompound` (or the :class:`GWindow`'s default top
:class:`GCompound`) just like any other :class:`GObject`.
"""
def __init__(self, command=''):
"""Initialize a :class:`GInteractor` with a command.
The command is accessible as part of any :class:`GActionEvents` that
this interactor generates.
:param command: The action command for this interactor.
"""
# TODO(sredmond): Consider stripping the concept of "action commands"
# entirely, since it violates "There should be one way to do things."
super().__init__()
self._command = command
@property
def command(self):
"""Get or set the action command for this interactor."""
return self._command
@command.setter
def command(self, command):
self._command = command
_platform.Platform().ginteractor_set_action_command(self, action_command)
# TODO(sredmond): Provide a general mechanism for setting an interactor's size.
# TODO(sredmond): Provide a general mechanism to get the location and bounds
# of an interactor.
[docs]class GCheckBox(GInteractor):
"""An onscreen check box.
Clicking once on the check box selects it; clicking again removes the
selection.
Clicking on the box generates a GActionEvent.
"""
def __init__(self, label):
"""
Creates a GCheckBox with the specified label.
In contrast to the GButton constructor, this constructor does not set an
action command.
:param str label: A label for this GCheckBox.
"""
super().__init__()
self.label = label
_platform.Platform().gcheckbox_constructor(self, label)
@property
def selected(self):
"""Get or set whether the checkbox is selected.
:param bool state: Whether the checkbox is selected.
"""
return _platform.Platform().gcheckbox_is_selected(self)
@selected.setter
def selected(self, state):
return _platform.Platform().gcheckbox_set_selected(self, state)
def __str__(self):
return 'GCheckBox("{}")'.format(self.label)
[docs]class GSlider(GInteractor):
"""An onscreen slider.
Dragging
"""
def __init__(self, min_value=0, max_value=100, starting_value=50):
"""Create a horizontal GSlider.
The client can specify a minimum value, maximum value, and starting
value.
:param int min_value: The minimum value of this GSlider.
:param int max_value: The maximum value of this GSlider. Should be >=
min_value, but this is not currently enforced.
:param int starting_value: The starting value of this GSlider. Should be
between min_value and max_value. If not, is set to min_value.
"""
super().__init__()
self.min_value = min_value
self.max_value = max_value
# TODO(sredmond): Error check that max_value >= min_value.
if not min_value <= starting_value <= max_value:
starting_value = min_value
_platform.Platform().gslider_constructor(self, min_value, max_value, starting_value)
@property
def value(self):
"""Get or set the current value of the GSlider.
:param int value: The value of the GSlider.
"""
return _platform.Platform().gslider_get_value(self)
@value.setter
def value(self, new_value):
_platform.Platform().gslider_set_value(self, value)
def __str__(self):
return "GSlider(value={}, min={}, max={})".format(self.value, self.min_value, self.max_value)
[docs]class GTextField(GInteractor):
"""An onscreen text field for entering short text strings.
Hitting RETURN in a text field generates a :class:`GActionEvent`.
"""
def __init__(self, width=10):
"""Create a text field with a maximum width.
A :class:`GActionEvent` is generated whenever the user presses the
RETURN key while this interactor has focus.
:param width: The maximum number of characters this field can hold.
"""
super().__init__(self)
self._width = width
_platform.Platform().gtextfield_constructor(self)
@property
def text(self):
"""Get or set the contents of this :class:`GTextField`."""
return _platform.Platform().gtextfield_get_text(self)
@text.setter
def text(self, content):
_platform.Platform().gtextfield_set_text(self, content)
def __str__(self):
return "GTextField(text={}, width={})".format(self.text, self.width)
[docs]class GChooser(GInteractor):
"""A list of selectable items.
You can construct a :class:`GChooser` with an ordered collection of items,
or :meth:`add` and :meth:`remove` items after construction::
size_chooser = GChooser('Small', 'Medium', 'Large')
size_chooser.add_item('X-Large')
size_chooser.remove_item('Medium')
To get the selected item::
size_chooser = GChooser('Small', 'Medium', 'Large')
selected = size_chooser.selected_item
"""
def __init__(self, *items):
"""Create a :class:`GChooser`, optionally with some items.
These items are supplied as extra positional arguments::
size_chooser = GChooser('Small', 'Medium', 'Large')
To construct a :class:`GChooser` from a collection of elements, unpack
the elements into the constructor::
options = ('Small', 'Medium', 'Large')
size_chooser = GChooser(*options)
A :class:`GActionEvent` is generated each time the user selects an item.
"""
super().__init__(self)
self._items = list(items)
_platform.Platform().gchooser_constructor(self)
[docs] def add_item(self, item):
"""Add a new option to this :class:`GChooser`.
:param item: The new item to add to this :class:`GChooser`.
"""
self._items.append(item)
_platform.Platform().gchooser_add_item(self, item)
[docs] def remove_item(self, item):
"""Remove an option from this :class:`GChooser`.
:param item: The item to remove from this :class:`GChooser`.
:return: Whether the item was removed.
"""
try:
self._items.remove(item)
_platform.Platform().gchooser_remove_item(self, item)
return True
except ValueError:
return False
@property
def selected_item(self):
"""Get or set the currently selected item of this :class:`GChooser`.
Setting the selected item to something not in this :class:`GChooser`'s
list of items results in no change.
"""
return _platform.Platform().gchooser_get_selected_item(self)
@selected_item.setter
def selected_item(self, item):
if item not in self._items:
return
_platform.Platform().gchooser_set_selected_item(self, item)
def __str__(self):
return "GChooser(items={})".format(self._items)