##// END OF EJS Templates
Update widget_selection.py
jdavidheiser -
Show More
@@ -1,125 +1,126 b''
1 """SelectionWidget classes.
1 """SelectionWidget classes.
2
2
3 Represents an enumeration using a widget.
3 Represents an enumeration using a widget.
4 """
4 """
5 #-----------------------------------------------------------------------------
5 #-----------------------------------------------------------------------------
6 # Copyright (c) 2013, the IPython Development Team.
6 # Copyright (c) 2013, the IPython Development Team.
7 #
7 #
8 # Distributed under the terms of the Modified BSD License.
8 # Distributed under the terms of the Modified BSD License.
9 #
9 #
10 # The full license is in the file COPYING.txt, distributed with this software.
10 # The full license is in the file COPYING.txt, distributed with this software.
11 #-----------------------------------------------------------------------------
11 #-----------------------------------------------------------------------------
12
12
13 #-----------------------------------------------------------------------------
13 #-----------------------------------------------------------------------------
14 # Imports
14 # Imports
15 #-----------------------------------------------------------------------------
15 #-----------------------------------------------------------------------------
16
16
17 from collections import OrderedDict
17 from collections import OrderedDict
18 from threading import Lock
18 from threading import Lock
19
19
20 from .widget import DOMWidget
20 from .widget import DOMWidget
21 from IPython.utils.traitlets import Unicode, List, Bool, Any, Dict, TraitError
21 from IPython.utils.traitlets import Unicode, List, Bool, Any, Dict, TraitError
22 from IPython.utils.py3compat import unicode_type
22 from IPython.utils.py3compat import unicode_type
23
23
24 #-----------------------------------------------------------------------------
24 #-----------------------------------------------------------------------------
25 # SelectionWidget
25 # SelectionWidget
26 #-----------------------------------------------------------------------------
26 #-----------------------------------------------------------------------------
27 class _SelectionWidget(DOMWidget):
27 class _SelectionWidget(DOMWidget):
28 """Base class for Selection widgets
28 """Base class for Selection widgets
29
29
30 ``values`` can be specified as a list or dict. If given as a list,
30 ``values`` can be specified as a list or dict. If given as a list,
31 it will be transformed to a dict of the form ``{str(value):value}``.
31 it will be transformed to a dict of the form ``{str(value):value}``.
32 """
32 """
33
33
34 value = Any(help="Selected value")
34 value = Any(help="Selected value")
35 values = Dict(help="""Dictionary of {name: value} the user can select.
35 values = Dict(help="""Dictionary of {name: value} the user can select.
36
36
37 The keys of this dictionary are the strings that will be displayed in the UI,
37 The keys of this dictionary are the strings that will be displayed in the UI,
38 representing the actual Python choices.
38 representing the actual Python choices.
39
39
40 The keys of this dictionary are also available as value_names.
40 The keys of this dictionary are also available as value_names.
41 """)
41 """)
42 value_name = Unicode(help="The name of the selected value", sync=True)
42 value_name = Unicode(help="The name of the selected value", sync=True)
43 value_names = List(Unicode, help="""Read-only list of names for each value.
43 value_names = List(Unicode, help="""Read-only list of names for each value.
44
44
45 If values is specified as a list, this is the string representation of each element.
45 If values is specified as a list, this is the string representation of each element.
46 Otherwise, it is the keys of the values dictionary.
46 Otherwise, it is the keys of the values dictionary.
47
47
48 These strings are used to display the choices in the front-end.""", sync=True)
48 These strings are used to display the choices in the front-end.""", sync=True)
49 disabled = Bool(False, help="Enable or disable user changes", sync=True)
49 disabled = Bool(False, help="Enable or disable user changes", sync=True)
50 description = Unicode(help="Description of the value this widget represents", sync=True)
50 description = Unicode(help="Description of the value this widget represents", sync=True)
51
51
52
52
53 def __init__(self, *args, **kwargs):
53 def __init__(self, *args, **kwargs):
54 self.value_lock = Lock()
54 self.value_lock = Lock()
55 self._in_values_changed = False
55 self._in_values_changed = False
56 if 'values' in kwargs:
56 if 'values' in kwargs:
57 values = kwargs['values']
57 values = kwargs['values']
58 # convert list values to an dict of {str(v):v}
58 # convert list values to an dict of {str(v):v}
59 if isinstance(values, list):
59 if isinstance(values, list):
60 # preserve list order with an OrderedDict
60 # preserve list order with an OrderedDict
61 kwargs['values'] = OrderedDict((unicode_type(v), v) for v in values)
61 kwargs['values'] = OrderedDict((unicode_type(v), v) for v in values)
62 # python3.3 turned on hash randomization by default - this means that sometimes, randomly
62 # python3.3 turned on hash randomization by default - this means that sometimes, randomly
63 # we try to set value before setting values, due to dictionary ordering. To fix this, force
63 # we try to set value before setting values, due to dictionary ordering. To fix this, force
64 # the setting of self.values right now, before anything else runs
64 # the setting of self.values right now, before anything else runs
65 self.values = kwargs['values']
65 self.values = kwargs['values']
66 kwargs.pop('values')
66 DOMWidget.__init__(self, *args, **kwargs)
67 DOMWidget.__init__(self, *args, **kwargs)
67
68
68 def _values_changed(self, name, old, new):
69 def _values_changed(self, name, old, new):
69 """Handles when the values dict has been changed.
70 """Handles when the values dict has been changed.
70
71
71 Setting values implies setting value names from the keys of the dict.
72 Setting values implies setting value names from the keys of the dict.
72 """
73 """
73 self._in_values_changed = True
74 self._in_values_changed = True
74 try:
75 try:
75 self.value_names = list(new.keys())
76 self.value_names = list(new.keys())
76 finally:
77 finally:
77 self._in_values_changed = False
78 self._in_values_changed = False
78
79
79 # ensure that the chosen value is one of the choices
80 # ensure that the chosen value is one of the choices
80 if self.value not in new.values():
81 if self.value not in new.values():
81 self.value = next(iter(new.values()))
82 self.value = next(iter(new.values()))
82
83
83 def _value_names_changed(self, name, old, new):
84 def _value_names_changed(self, name, old, new):
84 if not self._in_values_changed:
85 if not self._in_values_changed:
85 raise TraitError("value_names is a read-only proxy to values.keys(). Use the values dict instead.")
86 raise TraitError("value_names is a read-only proxy to values.keys(). Use the values dict instead.")
86
87
87 def _value_changed(self, name, old, new):
88 def _value_changed(self, name, old, new):
88 """Called when value has been changed"""
89 """Called when value has been changed"""
89 if self.value_lock.acquire(False):
90 if self.value_lock.acquire(False):
90 try:
91 try:
91 # Reverse dictionary lookup for the value name
92 # Reverse dictionary lookup for the value name
92 for k,v in self.values.items():
93 for k,v in self.values.items():
93 if new == v:
94 if new == v:
94 # set the selected value name
95 # set the selected value name
95 self.value_name = k
96 self.value_name = k
96 return
97 return
97 # undo the change, and raise KeyError
98 # undo the change, and raise KeyError
98 self.value = old
99 self.value = old
99 raise KeyError(new)
100 raise KeyError(new)
100 finally:
101 finally:
101 self.value_lock.release()
102 self.value_lock.release()
102
103
103 def _value_name_changed(self, name, old, new):
104 def _value_name_changed(self, name, old, new):
104 """Called when the value name has been changed (typically by the frontend)."""
105 """Called when the value name has been changed (typically by the frontend)."""
105 if self.value_lock.acquire(False):
106 if self.value_lock.acquire(False):
106 try:
107 try:
107 self.value = self.values[new]
108 self.value = self.values[new]
108 finally:
109 finally:
109 self.value_lock.release()
110 self.value_lock.release()
110
111
111
112
112 class ToggleButtonsWidget(_SelectionWidget):
113 class ToggleButtonsWidget(_SelectionWidget):
113 _view_name = Unicode('ToggleButtonsView', sync=True)
114 _view_name = Unicode('ToggleButtonsView', sync=True)
114
115
115
116
116 class DropdownWidget(_SelectionWidget):
117 class DropdownWidget(_SelectionWidget):
117 _view_name = Unicode('DropdownView', sync=True)
118 _view_name = Unicode('DropdownView', sync=True)
118
119
119
120
120 class RadioButtonsWidget(_SelectionWidget):
121 class RadioButtonsWidget(_SelectionWidget):
121 _view_name = Unicode('RadioButtonsView', sync=True)
122 _view_name = Unicode('RadioButtonsView', sync=True)
122
123
123
124
124 class SelectWidget(_SelectionWidget):
125 class SelectWidget(_SelectionWidget):
125 _view_name = Unicode('SelectView', sync=True)
126 _view_name = Unicode('SelectView', sync=True)
General Comments 0
You need to be logged in to leave comments. Login now