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