##// END OF EJS Templates
Add selector button to dashboard
Add selector button to dashboard

File last commit:

r20287:e8dddcc1
r20313:cf7912ff
Show More
widget_selection.py
238 lines | 8.9 KiB | text/x-python | PythonLexer
Jonathan Frederic
Renamed *Widget to *,...
r17598 """Selection classes.
Jonathan Frederic
Cleaned up Python widget code.
r14283
Represents an enumeration using a widget.
"""
#-----------------------------------------------------------------------------
# Copyright (c) 2013, the IPython Development Team.
#
# Distributed under the terms of the Modified BSD License.
#
# The full license is in the file COPYING.txt, distributed with this software.
#-----------------------------------------------------------------------------
#-----------------------------------------------------------------------------
# Imports
#-----------------------------------------------------------------------------
MinRK
Make `SelectionWidget.values` a dict...
r15024
from collections import OrderedDict
Jonathan Frederic
Support multiple types in selection widget.
r14698 from threading import Lock
Sylvain Corlay
registering core widgets
r18531 from .widget import DOMWidget, register
Thomas Kluyver
Import Tuple traitlet for Selection widget
r19060 from IPython.utils.traitlets import (
Unicode, Bool, Any, Dict, TraitError, CaselessStrEnum, Tuple
)
MinRK
Make `SelectionWidget.values` a dict...
r15024 from IPython.utils.py3compat import unicode_type
Jonathan Frederic
Renamed *Widget to *,...
r17598 from IPython.utils.warn import DeprecatedClass
Jonathan Frederic
Add selection widget
r14242
Jonathan Frederic
Cleaned up Python widget code.
r14283 #-----------------------------------------------------------------------------
# SelectionWidget
#-----------------------------------------------------------------------------
Jonathan Frederic
Renamed *Widget to *,...
r17598 class _Selection(DOMWidget):
MinRK
Make `SelectionWidget.values` a dict...
r15024 """Base class for Selection widgets
Nicholas Bollweg
squashing the whitespace changes
r20287 ``options`` can be specified as a list or dict. If given as a list,
MinRK
Make `SelectionWidget.values` a dict...
r15024 it will be transformed to a dict of the form ``{str(value):value}``.
"""
value = Any(help="Selected value")
Nicholas Bollweg
squashing the whitespace changes
r20287 selected_label = Unicode(help="The label of the selected value", sync=True)
options = Any(help="""List of (key, value) tuples or dict of values that the
Jonathan Frederic
Don't magically convert values to a list of tuples.
r19134 user can select.
MinRK
Make `SelectionWidget.values` a dict...
r15024
Jonathan Frederic
Something
r19058 The keys of this list are the strings that will be displayed in the UI,
MinRK
Make `SelectionWidget.values` a dict...
r15024 representing the actual Python choices.
Nicholas Bollweg
squashing the whitespace changes
r20287 The keys of this list are also available as _options_labels.
MinRK
Make `SelectionWidget.values` a dict...
r15024 """)
Jonathan Frederic
Something
r19058
Nicholas Bollweg
squashing the whitespace changes
r20287 _options_dict = Dict()
_options_labels = Tuple(sync=True)
_options_values = Tuple()
Jonathan Frederic
Something
r19058
Jonathan Frederic
sync=True isntead of a keys list
r14588 disabled = Bool(False, help="Enable or disable user changes", sync=True)
description = Unicode(help="Description of the value this widget represents", sync=True)
Jonathan Frederic
Something
r19058
MinRK
Make `SelectionWidget.values` a dict...
r15024 def __init__(self, *args, **kwargs):
Jonathan Frederic
Support multiple types in selection widget.
r14698 self.value_lock = Lock()
Nicholas Bollweg
squashing the whitespace changes
r20287 self.options_lock = Lock()
self.on_trait_change(self._options_readonly_changed, ['_options_dict', '_options_labels', '_options_values', '_options'])
if 'options' in kwargs:
self.options = kwargs.pop('options')
MinRK
Make `SelectionWidget.values` a dict...
r15024 DOMWidget.__init__(self, *args, **kwargs)
Nicholas Bollweg
squashing the whitespace changes
r20287 self._value_in_options()
MinRK
Make `SelectionWidget.values` a dict...
r15024
Nicholas Bollweg
squashing the whitespace changes
r20287 def _make_options(self, x):
Jonathan Frederic
Something
r19058 # If x is a dict, convert it to list format.
if isinstance(x, (OrderedDict, dict)):
return [(k, v) for k, v in x.items()]
# Make sure x is a list or tuple.
if not isinstance(x, (list, tuple)):
raise ValueError('x')
Nicholas Bollweg
squashing the whitespace changes
r20287 # If x is an ordinary list, use the option values as names.
Jonathan Frederic
Something
r19058 for y in x:
if not isinstance(y, (list, tuple)) or len(y) < 2:
return [(i, i) for i in x]
# Value is already in the correct format.
return x
Nicholas Bollweg
squashing the whitespace changes
r20287 def _options_changed(self, name, old, new):
"""Handles when the options tuple has been changed.
Jonathan Frederic
Support multiple types in selection widget.
r14698
Nicholas Bollweg
squashing the whitespace changes
r20287 Setting options implies setting option labels from the keys of the dict.
"""
if self.options_lock.acquire(False):
Jonathan Frederic
Something
r19058 try:
Nicholas Bollweg
squashing the whitespace changes
r20287 self.options = new
Jonathan Frederic
Typo fix
r19157
Nicholas Bollweg
squashing the whitespace changes
r20287 options = self._make_options(new)
self._options_dict = {i[0]: i[1] for i in options}
self._options_labels = [i[0] for i in options]
self._options_values = [i[1] for i in options]
self._value_in_options()
Jonathan Frederic
Make selection widget respect order.
r19059 finally:
Nicholas Bollweg
squashing the whitespace changes
r20287 self.options_lock.release()
Jonathan Frederic
Something
r19058
Nicholas Bollweg
squashing the whitespace changes
r20287 def _value_in_options(self):
MinRK
don't allow empty selection in selection widgets...
r15046 # ensure that the chosen value is one of the choices
MinRK
Make `SelectionWidget.values` a dict...
r15024
Nicholas Bollweg
squashing the whitespace changes
r20287 if self._options_values:
if self.value not in self._options_values:
self.value = next(iter(self._options_values))
Jonathan Frederic
Support multiple types in selection widget.
r14698
Nicholas Bollweg
squashing the whitespace changes
r20287 def _options_readonly_changed(self, name, old, new):
if not self.options_lock.locked():
raise TraitError("`.%s` is a read-only trait. Use the `.options` tuple instead." % name)
Jonathan Frederic
Support multiple types in selection widget.
r14698 def _value_changed(self, name, old, new):
"""Called when value has been changed"""
if self.value_lock.acquire(False):
try:
MinRK
don't allow empty selection in selection widgets...
r15046 # Reverse dictionary lookup for the value name
Nicholas Bollweg
squashing the whitespace changes
r20287 for k, v in self._options_dict.items():
MinRK
Make `SelectionWidget.values` a dict...
r15024 if new == v:
# set the selected value name
Nicholas Bollweg
squashing the whitespace changes
r20287 self.selected_label = k
MinRK
Make `SelectionWidget.values` a dict...
r15024 return
MinRK
undo failed changes...
r15401 # undo the change, and raise KeyError
self.value = old
MinRK
don't allow empty selection in selection widgets...
r15046 raise KeyError(new)
Jonathan Frederic
Support multiple types in selection widget.
r14698 finally:
self.value_lock.release()
Nicholas Bollweg
squashing the whitespace changes
r20287 def _selected_label_changed(self, name, old, new):
MinRK
Make `SelectionWidget.values` a dict...
r15024 """Called when the value name has been changed (typically by the frontend)."""
Jonathan Frederic
Support multiple types in selection widget.
r14698 if self.value_lock.acquire(False):
try:
Nicholas Bollweg
squashing the whitespace changes
r20287 self.value = self._options_dict[new]
finally:
self.value_lock.release()
class _MultipleSelection(_Selection):
"""Base class for MultipleSelection widgets.
As with ``_Selection``, ``options`` can be specified as a list or dict. If
given as a list, it will be transformed to a dict of the form
``{str(value): value}``.
Despite their names, ``value`` (and ``selected_label``) will be tuples, even
if only a single option is selected.
"""
value = Tuple(help="Selected values")
selected_labels = Tuple(help="The labels of the selected options",
sync=True)
@property
def selected_label(self):
raise AttributeError(
"Does not support selected_label, use selected_labels")
def _value_in_options(self):
# ensure that the chosen value is one of the choices
if self.options:
old_value = self.value or []
new_value = []
for value in old_value:
if value in self._options_dict.values():
new_value.append(value)
if new_value:
self.value = new_value
else:
self.value = [next(iter(self._options_dict.values()))]
def _value_changed(self, name, old, new):
"""Called when value has been changed"""
if self.value_lock.acquire(False):
try:
self.selected_labels = [
self._options_labels[self._options_values.index(v)]
for v in new
]
except:
self.value = old
raise KeyError(new)
finally:
self.value_lock.release()
def _selected_labels_changed(self, name, old, new):
"""Called when the selected label has been changed (typically by the
frontend)."""
if self.value_lock.acquire(False):
try:
self.value = [self._options_dict[name] for name in new]
Jonathan Frederic
Support multiple types in selection widget.
r14698 finally:
self.value_lock.release()
Jonathan Frederic
1-to-1 widget / view mapping
r14592
Sylvain Corlay
jupyter -> IPython
r18533 @register('IPython.ToggleButtons')
Jonathan Frederic
Renamed *Widget to *,...
r17598 class ToggleButtons(_Selection):
Jonathan Frederic
Added some doc strings on the widgets....
r17602 """Group of toggle buttons that represent an enumeration. Only one toggle
button can be toggled at any point in time."""
Jonathan Frederic
s/view_name/_view_name
r14701 _view_name = Unicode('ToggleButtonsView', sync=True)
Jonathan Frederic
Create base widget classes
r14670
Jonathan Frederic
Added Bootstrap specific classes,...
r17728 button_style = CaselessStrEnum(
values=['primary', 'success', 'info', 'warning', 'danger', ''],
default_value='', allow_none=True, sync=True, help="""Use a
predefined styling for the buttons.""")
Sylvain Corlay
jupyter -> IPython
r18533 @register('IPython.Dropdown')
Jonathan Frederic
Renamed *Widget to *,...
r17598 class Dropdown(_Selection):
Jonathan Frederic
Added some doc strings on the widgets....
r17602 """Allows you to select a single item from a dropdown."""
Jonathan Frederic
s/view_name/_view_name
r14701 _view_name = Unicode('DropdownView', sync=True)
Jonathan Frederic
1-to-1 widget / view mapping
r14592
Jonathan Frederic
Added bootstrap3 progress bar classes
r17729 button_style = CaselessStrEnum(
values=['primary', 'success', 'info', 'warning', 'danger', ''],
default_value='', allow_none=True, sync=True, help="""Use a
predefined styling for the buttons.""")
Sylvain Corlay
jupyter -> IPython
r18533 @register('IPython.RadioButtons')
Jonathan Frederic
Renamed *Widget to *,...
r17598 class RadioButtons(_Selection):
Jonathan Frederic
Added some doc strings on the widgets....
r17602 """Group of radio buttons that represent an enumeration. Only one radio
button can be toggled at any point in time."""
Jonathan Frederic
s/view_name/_view_name
r14701 _view_name = Unicode('RadioButtonsView', sync=True)
Jonathan Frederic
1-to-1 widget / view mapping
r14592
Sylvain Corlay
registering core widgets
r18531
Sylvain Corlay
jupyter -> IPython
r18533 @register('IPython.Select')
Jonathan Frederic
Renamed *Widget to *,...
r17598 class Select(_Selection):
Jonathan Frederic
Added some doc strings on the widgets....
r17602 """Listbox that only allows one item to be selected at any given time."""
Jonathan Frederic
Renamed widgets......
r14834 _view_name = Unicode('SelectView', sync=True)
Jonathan Frederic
Renamed *Widget to *,...
r17598
Jonathan Frederic
Added some doc strings on the widgets....
r17602
Nicholas Bollweg
squashing the whitespace changes
r20287 @register('IPython.SelectMultiple')
class SelectMultiple(_MultipleSelection):
"""Listbox that allows many items to be selected at any given time.
Despite their names, inherited from ``_Selection``, the currently chosen
option values, ``value``, or their labels, ``selected_labels`` must both be
updated with a list-like object."""
_view_name = Unicode('SelectMultipleView', sync=True)
Jonathan Frederic
Added some doc strings on the widgets....
r17602 # Remove in IPython 4.0
Jonathan Frederic
Renamed *Widget to *,...
r17598 ToggleButtonsWidget = DeprecatedClass(ToggleButtons, 'ToggleButtonsWidget')
DropdownWidget = DeprecatedClass(Dropdown, 'DropdownWidget')
RadioButtonsWidget = DeprecatedClass(RadioButtons, 'RadioButtonsWidget')
SelectWidget = DeprecatedClass(Select, 'SelectWidget')