##// END OF EJS Templates
move DeprecatedClass to widgets, where it's used...
Min RK -
Show More
@@ -0,0 +1,22 b''
1 """Decorator for warning about deprecated widget classes"""
2
3 # Copyright (c) IPython Development Team.
4 # Distributed under the terms of the Modified BSD License.
5
6 from warnings import warn
7
8
9 def DeprecatedClass(base, class_name):
10 """Warn about a deprecated class on instantiation"""
11 # Hook the init method of the base class.
12 def init_hook(self, *pargs, **kwargs):
13 base.__init__(self, *pargs, **kwargs)
14
15 # Warn once per class.
16 if base not in DeprecatedClass._warned_classes:
17 DeprecatedClass._warned_classes.append(base)
18 warn('"{}" is deprecated, please use "{}" instead.'.format(
19 class_name, base.__name__))
20 return type(class_name, (base,), {'__init__': init_hook})
21
22 DeprecatedClass._warned_classes = []
@@ -1,89 +1,80 b''
1 """Bool class.
1 """Bool class.
2
2
3 Represents a boolean using a widget.
3 Represents a boolean using a widget.
4 """
4 """
5 #-----------------------------------------------------------------------------
5
6 # Copyright (c) 2013, the IPython Development Team.
6 # Copyright (c) IPython Development Team.
7 #
8 # Distributed under the terms of the Modified BSD License.
7 # Distributed under the terms of the Modified BSD License.
9 #
10 # The full license is in the file COPYING.txt, distributed with this software.
11 #-----------------------------------------------------------------------------
12
8
13 #-----------------------------------------------------------------------------
14 # Imports
15 #-----------------------------------------------------------------------------
16 from .widget import DOMWidget, register
9 from .widget import DOMWidget, register
17 from IPython.utils.traitlets import Unicode, Bool, CaselessStrEnum
10 from IPython.utils.traitlets import Unicode, Bool, CaselessStrEnum
18 from IPython.utils.warn import DeprecatedClass
11 from .deprecated import DeprecatedClass
12
19
13
20 #-----------------------------------------------------------------------------
21 # Classes
22 #-----------------------------------------------------------------------------
23 class _Bool(DOMWidget):
14 class _Bool(DOMWidget):
24 """A base class for creating widgets that represent booleans."""
15 """A base class for creating widgets that represent booleans."""
25 value = Bool(False, help="Bool value", sync=True)
16 value = Bool(False, help="Bool value", sync=True)
26 description = Unicode('', help="Description of the boolean (label).", sync=True)
17 description = Unicode('', help="Description of the boolean (label).", sync=True)
27 disabled = Bool(False, help="Enable or disable user changes.", sync=True)
18 disabled = Bool(False, help="Enable or disable user changes.", sync=True)
28
19
29 def __init__(self, value=None, **kwargs):
20 def __init__(self, value=None, **kwargs):
30 if value is not None:
21 if value is not None:
31 kwargs['value'] = value
22 kwargs['value'] = value
32 super(_Bool, self).__init__(**kwargs)
23 super(_Bool, self).__init__(**kwargs)
33
24
34 @register('IPython.Checkbox')
25 @register('IPython.Checkbox')
35 class Checkbox(_Bool):
26 class Checkbox(_Bool):
36 """Displays a boolean `value` in the form of a checkbox.
27 """Displays a boolean `value` in the form of a checkbox.
37
28
38 Parameters
29 Parameters
39 ----------
30 ----------
40 value : {True,False}
31 value : {True,False}
41 value of the checkbox: True-checked, False-unchecked
32 value of the checkbox: True-checked, False-unchecked
42 description : str
33 description : str
43 description displayed next to the checkbox
34 description displayed next to the checkbox
44 """
35 """
45 _view_name = Unicode('CheckboxView', sync=True)
36 _view_name = Unicode('CheckboxView', sync=True)
46
37
47
38
48 @register('IPython.ToggleButton')
39 @register('IPython.ToggleButton')
49 class ToggleButton(_Bool):
40 class ToggleButton(_Bool):
50 """Displays a boolean `value` in the form of a toggle button.
41 """Displays a boolean `value` in the form of a toggle button.
51
42
52 Parameters
43 Parameters
53 ----------
44 ----------
54 value : {True,False}
45 value : {True,False}
55 value of the toggle button: True-pressed, False-unpressed
46 value of the toggle button: True-pressed, False-unpressed
56 description : str
47 description : str
57 description displayed next to the button
48 description displayed next to the button
58 tooltip: str
49 tooltip: str
59 tooltip caption of the toggle button
50 tooltip caption of the toggle button
60 icon: str
51 icon: str
61 font-awesome icon name
52 font-awesome icon name
62 """
53 """
63 _view_name = Unicode('ToggleButtonView', sync=True)
54 _view_name = Unicode('ToggleButtonView', sync=True)
64 tooltip = Unicode(help="Tooltip caption of the toggle button.", sync=True)
55 tooltip = Unicode(help="Tooltip caption of the toggle button.", sync=True)
65 icon = Unicode('', help= "Font-awesome icon.", sync=True)
56 icon = Unicode('', help= "Font-awesome icon.", sync=True)
66
57
67 button_style = CaselessStrEnum(
58 button_style = CaselessStrEnum(
68 values=['primary', 'success', 'info', 'warning', 'danger', ''],
59 values=['primary', 'success', 'info', 'warning', 'danger', ''],
69 default_value='', allow_none=True, sync=True, help="""Use a
60 default_value='', allow_none=True, sync=True, help="""Use a
70 predefined styling for the button.""")
61 predefined styling for the button.""")
71
62
72
63
73 @register('IPython.Valid')
64 @register('IPython.Valid')
74 class Valid(_Bool):
65 class Valid(_Bool):
75
66
76 """Displays a boolean `value` in the form of a green check (True / valid)
67 """Displays a boolean `value` in the form of a green check (True / valid)
77 or a red cross (False / invalid).
68 or a red cross (False / invalid).
78
69
79 Parameters
70 Parameters
80 ----------
71 ----------
81 value: {True,False}
72 value: {True,False}
82 value of the Valid widget
73 value of the Valid widget
83 """
74 """
84 readout = Unicode(help="Message displayed when the value is False", sync=True)
75 readout = Unicode(help="Message displayed when the value is False", sync=True)
85 _view_name = Unicode('ValidView', sync=True)
76 _view_name = Unicode('ValidView', sync=True)
86
77
87 # Remove in IPython 4.0
78 # Remove in IPython 4.0
88 CheckboxWidget = DeprecatedClass(Checkbox, 'CheckboxWidget')
79 CheckboxWidget = DeprecatedClass(Checkbox, 'CheckboxWidget')
89 ToggleButtonWidget = DeprecatedClass(ToggleButton, 'ToggleButtonWidget')
80 ToggleButtonWidget = DeprecatedClass(ToggleButton, 'ToggleButtonWidget')
@@ -1,107 +1,107 b''
1 """Box class.
1 """Box class.
2
2
3 Represents a container that can be used to group other widgets.
3 Represents a container that can be used to group other widgets.
4 """
4 """
5
5
6 # Copyright (c) IPython Development Team.
6 # Copyright (c) IPython Development Team.
7 # Distributed under the terms of the Modified BSD License.
7 # Distributed under the terms of the Modified BSD License.
8
8
9 from .widget import DOMWidget, Widget, register
9 from .widget import DOMWidget, Widget, register
10 from IPython.utils.traitlets import Unicode, Tuple, TraitError, Int, CaselessStrEnum
10 from IPython.utils.traitlets import Unicode, Tuple, TraitError, Int, CaselessStrEnum
11 from IPython.utils.warn import DeprecatedClass
11 from .deprecated import DeprecatedClass
12
12
13 def _widget_to_json(x):
13 def _widget_to_json(x):
14 if isinstance(x, dict):
14 if isinstance(x, dict):
15 return {k: _widget_to_json(v) for k, v in x.items()}
15 return {k: _widget_to_json(v) for k, v in x.items()}
16 elif isinstance(x, (list, tuple)):
16 elif isinstance(x, (list, tuple)):
17 return [_widget_to_json(v) for v in x]
17 return [_widget_to_json(v) for v in x]
18 elif isinstance(x, Widget):
18 elif isinstance(x, Widget):
19 return "IPY_MODEL_" + x.model_id
19 return "IPY_MODEL_" + x.model_id
20 else:
20 else:
21 return x
21 return x
22
22
23 def _json_to_widget(x):
23 def _json_to_widget(x):
24 if isinstance(x, dict):
24 if isinstance(x, dict):
25 return {k: _json_to_widget(v) for k, v in x.items()}
25 return {k: _json_to_widget(v) for k, v in x.items()}
26 elif isinstance(x, (list, tuple)):
26 elif isinstance(x, (list, tuple)):
27 return [_json_to_widget(v) for v in x]
27 return [_json_to_widget(v) for v in x]
28 elif isinstance(x, string_types) and x.startswith('IPY_MODEL_') and x[10:] in Widget.widgets:
28 elif isinstance(x, string_types) and x.startswith('IPY_MODEL_') and x[10:] in Widget.widgets:
29 return Widget.widgets[x[10:]]
29 return Widget.widgets[x[10:]]
30 else:
30 else:
31 return x
31 return x
32
32
33 widget_serialization = {
33 widget_serialization = {
34 'from_json': _json_to_widget,
34 'from_json': _json_to_widget,
35 'to_json': _widget_to_json
35 'to_json': _widget_to_json
36 }
36 }
37
37
38
38
39 @register('IPython.Box')
39 @register('IPython.Box')
40 class Box(DOMWidget):
40 class Box(DOMWidget):
41 """Displays multiple widgets in a group."""
41 """Displays multiple widgets in a group."""
42 _model_name = Unicode('BoxModel', sync=True)
42 _model_name = Unicode('BoxModel', sync=True)
43 _view_name = Unicode('BoxView', sync=True)
43 _view_name = Unicode('BoxView', sync=True)
44
44
45 # Child widgets in the container.
45 # Child widgets in the container.
46 # Using a tuple here to force reassignment to update the list.
46 # Using a tuple here to force reassignment to update the list.
47 # When a proper notifying-list trait exists, that is what should be used here.
47 # When a proper notifying-list trait exists, that is what should be used here.
48 children = Tuple(sync=True, **widget_serialization)
48 children = Tuple(sync=True, **widget_serialization)
49
49
50 _overflow_values = ['visible', 'hidden', 'scroll', 'auto', 'initial', 'inherit', '']
50 _overflow_values = ['visible', 'hidden', 'scroll', 'auto', 'initial', 'inherit', '']
51 overflow_x = CaselessStrEnum(
51 overflow_x = CaselessStrEnum(
52 values=_overflow_values,
52 values=_overflow_values,
53 default_value='', sync=True, help="""Specifies what
53 default_value='', sync=True, help="""Specifies what
54 happens to content that is too large for the rendered region.""")
54 happens to content that is too large for the rendered region.""")
55 overflow_y = CaselessStrEnum(
55 overflow_y = CaselessStrEnum(
56 values=_overflow_values,
56 values=_overflow_values,
57 default_value='', sync=True, help="""Specifies what
57 default_value='', sync=True, help="""Specifies what
58 happens to content that is too large for the rendered region.""")
58 happens to content that is too large for the rendered region.""")
59
59
60 box_style = CaselessStrEnum(
60 box_style = CaselessStrEnum(
61 values=['success', 'info', 'warning', 'danger', ''],
61 values=['success', 'info', 'warning', 'danger', ''],
62 default_value='', allow_none=True, sync=True, help="""Use a
62 default_value='', allow_none=True, sync=True, help="""Use a
63 predefined styling for the box.""")
63 predefined styling for the box.""")
64
64
65 def __init__(self, children = (), **kwargs):
65 def __init__(self, children = (), **kwargs):
66 kwargs['children'] = children
66 kwargs['children'] = children
67 super(Box, self).__init__(**kwargs)
67 super(Box, self).__init__(**kwargs)
68 self.on_displayed(Box._fire_children_displayed)
68 self.on_displayed(Box._fire_children_displayed)
69
69
70 def _fire_children_displayed(self):
70 def _fire_children_displayed(self):
71 for child in self.children:
71 for child in self.children:
72 child._handle_displayed()
72 child._handle_displayed()
73
73
74
74
75 @register('IPython.FlexBox')
75 @register('IPython.FlexBox')
76 class FlexBox(Box):
76 class FlexBox(Box):
77 """Displays multiple widgets using the flexible box model."""
77 """Displays multiple widgets using the flexible box model."""
78 _view_name = Unicode('FlexBoxView', sync=True)
78 _view_name = Unicode('FlexBoxView', sync=True)
79 orientation = CaselessStrEnum(values=['vertical', 'horizontal'], default_value='vertical', sync=True)
79 orientation = CaselessStrEnum(values=['vertical', 'horizontal'], default_value='vertical', sync=True)
80 flex = Int(0, sync=True, help="""Specify the flexible-ness of the model.""")
80 flex = Int(0, sync=True, help="""Specify the flexible-ness of the model.""")
81 def _flex_changed(self, name, old, new):
81 def _flex_changed(self, name, old, new):
82 new = min(max(0, new), 2)
82 new = min(max(0, new), 2)
83 if self.flex != new:
83 if self.flex != new:
84 self.flex = new
84 self.flex = new
85
85
86 _locations = ['start', 'center', 'end', 'baseline', 'stretch']
86 _locations = ['start', 'center', 'end', 'baseline', 'stretch']
87 pack = CaselessStrEnum(
87 pack = CaselessStrEnum(
88 values=_locations,
88 values=_locations,
89 default_value='start', sync=True)
89 default_value='start', sync=True)
90 align = CaselessStrEnum(
90 align = CaselessStrEnum(
91 values=_locations,
91 values=_locations,
92 default_value='start', sync=True)
92 default_value='start', sync=True)
93
93
94
94
95 def VBox(*pargs, **kwargs):
95 def VBox(*pargs, **kwargs):
96 """Displays multiple widgets vertically using the flexible box model."""
96 """Displays multiple widgets vertically using the flexible box model."""
97 kwargs['orientation'] = 'vertical'
97 kwargs['orientation'] = 'vertical'
98 return FlexBox(*pargs, **kwargs)
98 return FlexBox(*pargs, **kwargs)
99
99
100 def HBox(*pargs, **kwargs):
100 def HBox(*pargs, **kwargs):
101 """Displays multiple widgets horizontally using the flexible box model."""
101 """Displays multiple widgets horizontally using the flexible box model."""
102 kwargs['orientation'] = 'horizontal'
102 kwargs['orientation'] = 'horizontal'
103 return FlexBox(*pargs, **kwargs)
103 return FlexBox(*pargs, **kwargs)
104
104
105
105
106 # Remove in IPython 4.0
106 # Remove in IPython 4.0
107 ContainerWidget = DeprecatedClass(Box, 'ContainerWidget')
107 ContainerWidget = DeprecatedClass(Box, 'ContainerWidget')
@@ -1,82 +1,73 b''
1 """Button class.
1 """Button class.
2
2
3 Represents a button in the frontend using a widget. Allows user to listen for
3 Represents a button in the frontend using a widget. Allows user to listen for
4 click events on the button and trigger backend code when the clicks are fired.
4 click events on the button and trigger backend code when the clicks are fired.
5 """
5 """
6 #-----------------------------------------------------------------------------
6
7 # Copyright (c) 2013, the IPython Development Team.
7 # Copyright (c) IPython Development Team.
8 #
9 # Distributed under the terms of the Modified BSD License.
8 # Distributed under the terms of the Modified BSD License.
10 #
11 # The full license is in the file COPYING.txt, distributed with this software.
12 #-----------------------------------------------------------------------------
13
9
14 #-----------------------------------------------------------------------------
15 # Imports
16 #-----------------------------------------------------------------------------
17 from .widget import DOMWidget, CallbackDispatcher, register
10 from .widget import DOMWidget, CallbackDispatcher, register
18 from IPython.utils.traitlets import Unicode, Bool, CaselessStrEnum
11 from IPython.utils.traitlets import Unicode, Bool, CaselessStrEnum
19 from IPython.utils.warn import DeprecatedClass
12 from .deprecated import DeprecatedClass
13
20
14
21 #-----------------------------------------------------------------------------
22 # Classes
23 #-----------------------------------------------------------------------------
24 @register('IPython.Button')
15 @register('IPython.Button')
25 class Button(DOMWidget):
16 class Button(DOMWidget):
26 """Button widget.
17 """Button widget.
27 This widget has an `on_click` method that allows you to listen for the
18 This widget has an `on_click` method that allows you to listen for the
28 user clicking on the button. The click event itself is stateless.
19 user clicking on the button. The click event itself is stateless.
29
20
30 Parameters
21 Parameters
31 ----------
22 ----------
32 description : str
23 description : str
33 description displayed next to the button
24 description displayed next to the button
34 tooltip: str
25 tooltip: str
35 tooltip caption of the toggle button
26 tooltip caption of the toggle button
36 icon: str
27 icon: str
37 font-awesome icon name
28 font-awesome icon name
38 """
29 """
39 _view_name = Unicode('ButtonView', sync=True)
30 _view_name = Unicode('ButtonView', sync=True)
40
31
41 # Keys
32 # Keys
42 description = Unicode('', help="Button label.", sync=True)
33 description = Unicode('', help="Button label.", sync=True)
43 tooltip = Unicode(help="Tooltip caption of the button.", sync=True)
34 tooltip = Unicode(help="Tooltip caption of the button.", sync=True)
44 disabled = Bool(False, help="Enable or disable user changes.", sync=True)
35 disabled = Bool(False, help="Enable or disable user changes.", sync=True)
45 icon = Unicode('', help= "Font-awesome icon.", sync=True)
36 icon = Unicode('', help= "Font-awesome icon.", sync=True)
46
37
47 button_style = CaselessStrEnum(
38 button_style = CaselessStrEnum(
48 values=['primary', 'success', 'info', 'warning', 'danger', ''],
39 values=['primary', 'success', 'info', 'warning', 'danger', ''],
49 default_value='', allow_none=True, sync=True, help="""Use a
40 default_value='', allow_none=True, sync=True, help="""Use a
50 predefined styling for the button.""")
41 predefined styling for the button.""")
51
42
52 def __init__(self, **kwargs):
43 def __init__(self, **kwargs):
53 """Constructor"""
44 """Constructor"""
54 super(Button, self).__init__(**kwargs)
45 super(Button, self).__init__(**kwargs)
55 self._click_handlers = CallbackDispatcher()
46 self._click_handlers = CallbackDispatcher()
56 self.on_msg(self._handle_button_msg)
47 self.on_msg(self._handle_button_msg)
57
48
58 def on_click(self, callback, remove=False):
49 def on_click(self, callback, remove=False):
59 """Register a callback to execute when the button is clicked.
50 """Register a callback to execute when the button is clicked.
60
51
61 The callback will be called with one argument,
52 The callback will be called with one argument,
62 the clicked button widget instance.
53 the clicked button widget instance.
63
54
64 Parameters
55 Parameters
65 ----------
56 ----------
66 remove : bool (optional)
57 remove : bool (optional)
67 Set to true to remove the callback from the list of callbacks."""
58 Set to true to remove the callback from the list of callbacks."""
68 self._click_handlers.register_callback(callback, remove=remove)
59 self._click_handlers.register_callback(callback, remove=remove)
69
60
70 def _handle_button_msg(self, _, content, buffers):
61 def _handle_button_msg(self, _, content, buffers):
71 """Handle a msg from the front-end.
62 """Handle a msg from the front-end.
72
63
73 Parameters
64 Parameters
74 ----------
65 ----------
75 content: dict
66 content: dict
76 Content of the msg."""
67 Content of the msg."""
77 if content.get('event', '') == 'click':
68 if content.get('event', '') == 'click':
78 self._click_handlers(self)
69 self._click_handlers(self)
79
70
80
71
81 # Remove in IPython 4.0
72 # Remove in IPython 4.0
82 ButtonWidget = DeprecatedClass(Button, 'ButtonWidget')
73 ButtonWidget = DeprecatedClass(Button, 'ButtonWidget')
@@ -1,296 +1,287 b''
1 """Float class.
1 """Float class.
2
2
3 Represents an unbounded float using a widget.
3 Represents an unbounded float using a widget.
4 """
4 """
5 #-----------------------------------------------------------------------------
5
6 # Copyright (c) 2013, the IPython Development Team.
6 # Copyright (c) IPython Development Team.
7 #
8 # Distributed under the terms of the Modified BSD License.
7 # Distributed under the terms of the Modified BSD License.
9 #
10 # The full license is in the file COPYING.txt, distributed with this software.
11 #-----------------------------------------------------------------------------
12
8
13 #-----------------------------------------------------------------------------
14 # Imports
15 #-----------------------------------------------------------------------------
16 from .widget import DOMWidget, register
9 from .widget import DOMWidget, register
17 from .trait_types import Color
10 from .trait_types import Color
18 from IPython.utils.traitlets import (Unicode, CFloat, Bool, CaselessStrEnum,
11 from IPython.utils.traitlets import (Unicode, CFloat, Bool, CaselessStrEnum,
19 Tuple, TraitError)
12 Tuple, TraitError)
20 from IPython.utils.warn import DeprecatedClass
13 from .deprecated import DeprecatedClass
14
21
15
22 #-----------------------------------------------------------------------------
23 # Classes
24 #-----------------------------------------------------------------------------
25 class _Float(DOMWidget):
16 class _Float(DOMWidget):
26 value = CFloat(0.0, help="Float value", sync=True)
17 value = CFloat(0.0, help="Float value", sync=True)
27 disabled = Bool(False, help="Enable or disable user changes", sync=True)
18 disabled = Bool(False, help="Enable or disable user changes", sync=True)
28 description = Unicode(help="Description of the value this widget represents", sync=True)
19 description = Unicode(help="Description of the value this widget represents", sync=True)
29
20
30 def __init__(self, value=None, **kwargs):
21 def __init__(self, value=None, **kwargs):
31 if value is not None:
22 if value is not None:
32 kwargs['value'] = value
23 kwargs['value'] = value
33 super(_Float, self).__init__(**kwargs)
24 super(_Float, self).__init__(**kwargs)
34
25
35
26
36 class _BoundedFloat(_Float):
27 class _BoundedFloat(_Float):
37 max = CFloat(100.0, help="Max value", sync=True)
28 max = CFloat(100.0, help="Max value", sync=True)
38 min = CFloat(0.0, help="Min value", sync=True)
29 min = CFloat(0.0, help="Min value", sync=True)
39 step = CFloat(0.1, help="Minimum step to increment the value (ignored by some views)", sync=True)
30 step = CFloat(0.1, help="Minimum step to increment the value (ignored by some views)", sync=True)
40
31
41 def __init__(self, *pargs, **kwargs):
32 def __init__(self, *pargs, **kwargs):
42 """Constructor"""
33 """Constructor"""
43 super(_BoundedFloat, self).__init__(*pargs, **kwargs)
34 super(_BoundedFloat, self).__init__(*pargs, **kwargs)
44
35
45 def _value_validate(self, value, trait):
36 def _value_validate(self, value, trait):
46 """Cap and floor value"""
37 """Cap and floor value"""
47 if self.min > value or self.max < value:
38 if self.min > value or self.max < value:
48 value = min(max(value, self.min), self.max)
39 value = min(max(value, self.min), self.max)
49 return value
40 return value
50
41
51 def _min_validate(self, min, trait):
42 def _min_validate(self, min, trait):
52 """Enforce min <= value <= max"""
43 """Enforce min <= value <= max"""
53 if min > self.max:
44 if min > self.max:
54 raise TraitError("Setting min > max")
45 raise TraitError("Setting min > max")
55 if min > self.value:
46 if min > self.value:
56 self.value = min
47 self.value = min
57 return min
48 return min
58
49
59 def _max_validate(self, max, trait):
50 def _max_validate(self, max, trait):
60 """Enforce min <= value <= max"""
51 """Enforce min <= value <= max"""
61 if max < self.min:
52 if max < self.min:
62 raise TraitError("setting max < min")
53 raise TraitError("setting max < min")
63 if max < self.value:
54 if max < self.value:
64 self.value = max
55 self.value = max
65 return max
56 return max
66
57
67
58
68 @register('IPython.FloatText')
59 @register('IPython.FloatText')
69 class FloatText(_Float):
60 class FloatText(_Float):
70 """ Displays a float value within a textbox. For a textbox in
61 """ Displays a float value within a textbox. For a textbox in
71 which the value must be within a specific range, use BoundedFloatText.
62 which the value must be within a specific range, use BoundedFloatText.
72
63
73 Parameters
64 Parameters
74 ----------
65 ----------
75 value : float
66 value : float
76 value displayed
67 value displayed
77 description : str
68 description : str
78 description displayed next to the text box
69 description displayed next to the text box
79 color : str Unicode color code (eg. '#C13535'), optional
70 color : str Unicode color code (eg. '#C13535'), optional
80 color of the value displayed
71 color of the value displayed
81 """
72 """
82 _view_name = Unicode('FloatTextView', sync=True)
73 _view_name = Unicode('FloatTextView', sync=True)
83
74
84
75
85 @register('IPython.BoundedFloatText')
76 @register('IPython.BoundedFloatText')
86 class BoundedFloatText(_BoundedFloat):
77 class BoundedFloatText(_BoundedFloat):
87 """ Displays a float value within a textbox. Value must be within the range specified.
78 """ Displays a float value within a textbox. Value must be within the range specified.
88 For a textbox in which the value doesn't need to be within a specific range, use FloatText.
79 For a textbox in which the value doesn't need to be within a specific range, use FloatText.
89
80
90 Parameters
81 Parameters
91 ----------
82 ----------
92 value : float
83 value : float
93 value displayed
84 value displayed
94 min : float
85 min : float
95 minimal value of the range of possible values displayed
86 minimal value of the range of possible values displayed
96 max : float
87 max : float
97 maximal value of the range of possible values displayed
88 maximal value of the range of possible values displayed
98 description : str
89 description : str
99 description displayed next to the textbox
90 description displayed next to the textbox
100 color : str Unicode color code (eg. '#C13535'), optional
91 color : str Unicode color code (eg. '#C13535'), optional
101 color of the value displayed
92 color of the value displayed
102 """
93 """
103 _view_name = Unicode('FloatTextView', sync=True)
94 _view_name = Unicode('FloatTextView', sync=True)
104
95
105
96
106 @register('IPython.FloatSlider')
97 @register('IPython.FloatSlider')
107 class FloatSlider(_BoundedFloat):
98 class FloatSlider(_BoundedFloat):
108 """ Slider/trackbar of floating values with the specified range.
99 """ Slider/trackbar of floating values with the specified range.
109
100
110 Parameters
101 Parameters
111 ----------
102 ----------
112 value : float
103 value : float
113 position of the slider
104 position of the slider
114 min : float
105 min : float
115 minimal position of the slider
106 minimal position of the slider
116 max : float
107 max : float
117 maximal position of the slider
108 maximal position of the slider
118 step : float
109 step : float
119 step of the trackbar
110 step of the trackbar
120 description : str
111 description : str
121 name of the slider
112 name of the slider
122 orientation : {'vertical', 'horizontal}, optional
113 orientation : {'vertical', 'horizontal}, optional
123 default is horizontal
114 default is horizontal
124 readout : {True, False}, optional
115 readout : {True, False}, optional
125 default is True, display the current value of the slider next to it
116 default is True, display the current value of the slider next to it
126 slider_color : str Unicode color code (eg. '#C13535'), optional
117 slider_color : str Unicode color code (eg. '#C13535'), optional
127 color of the slider
118 color of the slider
128 color : str Unicode color code (eg. '#C13535'), optional
119 color : str Unicode color code (eg. '#C13535'), optional
129 color of the value displayed (if readout == True)
120 color of the value displayed (if readout == True)
130 """
121 """
131 _view_name = Unicode('FloatSliderView', sync=True)
122 _view_name = Unicode('FloatSliderView', sync=True)
132 orientation = CaselessStrEnum(values=['horizontal', 'vertical'],
123 orientation = CaselessStrEnum(values=['horizontal', 'vertical'],
133 default_value='horizontal', help="Vertical or horizontal.", sync=True)
124 default_value='horizontal', help="Vertical or horizontal.", sync=True)
134 _range = Bool(False, help="Display a range selector", sync=True)
125 _range = Bool(False, help="Display a range selector", sync=True)
135 readout = Bool(True, help="Display the current value of the slider next to it.", sync=True)
126 readout = Bool(True, help="Display the current value of the slider next to it.", sync=True)
136 slider_color = Color(None, allow_none=True, sync=True)
127 slider_color = Color(None, allow_none=True, sync=True)
137
128
138
129
139 @register('IPython.FloatProgress')
130 @register('IPython.FloatProgress')
140 class FloatProgress(_BoundedFloat):
131 class FloatProgress(_BoundedFloat):
141 """ Displays a progress bar.
132 """ Displays a progress bar.
142
133
143 Parameters
134 Parameters
144 -----------
135 -----------
145 value : float
136 value : float
146 position within the range of the progress bar
137 position within the range of the progress bar
147 min : float
138 min : float
148 minimal position of the slider
139 minimal position of the slider
149 max : float
140 max : float
150 maximal position of the slider
141 maximal position of the slider
151 step : float
142 step : float
152 step of the progress bar
143 step of the progress bar
153 description : str
144 description : str
154 name of the progress bar
145 name of the progress bar
155 bar_style: {'success', 'info', 'warning', 'danger', ''}, optional
146 bar_style: {'success', 'info', 'warning', 'danger', ''}, optional
156 color of the progress bar, default is '' (blue)
147 color of the progress bar, default is '' (blue)
157 colors are: 'success'-green, 'info'-light blue, 'warning'-orange, 'danger'-red
148 colors are: 'success'-green, 'info'-light blue, 'warning'-orange, 'danger'-red
158 """
149 """
159 _view_name = Unicode('ProgressView', sync=True)
150 _view_name = Unicode('ProgressView', sync=True)
160
151
161 bar_style = CaselessStrEnum(
152 bar_style = CaselessStrEnum(
162 values=['success', 'info', 'warning', 'danger', ''],
153 values=['success', 'info', 'warning', 'danger', ''],
163 default_value='', allow_none=True, sync=True, help="""Use a
154 default_value='', allow_none=True, sync=True, help="""Use a
164 predefined styling for the progess bar.""")
155 predefined styling for the progess bar.""")
165
156
166 class _FloatRange(_Float):
157 class _FloatRange(_Float):
167 value = Tuple(CFloat, CFloat, default_value=(0.0, 1.0), help="Tuple of (lower, upper) bounds", sync=True)
158 value = Tuple(CFloat, CFloat, default_value=(0.0, 1.0), help="Tuple of (lower, upper) bounds", sync=True)
168 lower = CFloat(0.0, help="Lower bound", sync=False)
159 lower = CFloat(0.0, help="Lower bound", sync=False)
169 upper = CFloat(1.0, help="Upper bound", sync=False)
160 upper = CFloat(1.0, help="Upper bound", sync=False)
170
161
171 def __init__(self, *pargs, **kwargs):
162 def __init__(self, *pargs, **kwargs):
172 value_given = 'value' in kwargs
163 value_given = 'value' in kwargs
173 lower_given = 'lower' in kwargs
164 lower_given = 'lower' in kwargs
174 upper_given = 'upper' in kwargs
165 upper_given = 'upper' in kwargs
175 if value_given and (lower_given or upper_given):
166 if value_given and (lower_given or upper_given):
176 raise ValueError("Cannot specify both 'value' and 'lower'/'upper' for range widget")
167 raise ValueError("Cannot specify both 'value' and 'lower'/'upper' for range widget")
177 if lower_given != upper_given:
168 if lower_given != upper_given:
178 raise ValueError("Must specify both 'lower' and 'upper' for range widget")
169 raise ValueError("Must specify both 'lower' and 'upper' for range widget")
179
170
180 DOMWidget.__init__(self, *pargs, **kwargs)
171 DOMWidget.__init__(self, *pargs, **kwargs)
181
172
182 # ensure the traits match, preferring whichever (if any) was given in kwargs
173 # ensure the traits match, preferring whichever (if any) was given in kwargs
183 if value_given:
174 if value_given:
184 self.lower, self.upper = self.value
175 self.lower, self.upper = self.value
185 else:
176 else:
186 self.value = (self.lower, self.upper)
177 self.value = (self.lower, self.upper)
187
178
188 self.on_trait_change(self._validate, ['value', 'upper', 'lower'])
179 self.on_trait_change(self._validate, ['value', 'upper', 'lower'])
189
180
190 def _validate(self, name, old, new):
181 def _validate(self, name, old, new):
191 if name == 'value':
182 if name == 'value':
192 self.lower, self.upper = min(new), max(new)
183 self.lower, self.upper = min(new), max(new)
193 elif name == 'lower':
184 elif name == 'lower':
194 self.value = (new, self.value[1])
185 self.value = (new, self.value[1])
195 elif name == 'upper':
186 elif name == 'upper':
196 self.value = (self.value[0], new)
187 self.value = (self.value[0], new)
197
188
198 class _BoundedFloatRange(_FloatRange):
189 class _BoundedFloatRange(_FloatRange):
199 step = CFloat(1.0, help="Minimum step that the value can take (ignored by some views)", sync=True)
190 step = CFloat(1.0, help="Minimum step that the value can take (ignored by some views)", sync=True)
200 max = CFloat(100.0, help="Max value", sync=True)
191 max = CFloat(100.0, help="Max value", sync=True)
201 min = CFloat(0.0, help="Min value", sync=True)
192 min = CFloat(0.0, help="Min value", sync=True)
202
193
203 def __init__(self, *pargs, **kwargs):
194 def __init__(self, *pargs, **kwargs):
204 any_value_given = 'value' in kwargs or 'upper' in kwargs or 'lower' in kwargs
195 any_value_given = 'value' in kwargs or 'upper' in kwargs or 'lower' in kwargs
205 _FloatRange.__init__(self, *pargs, **kwargs)
196 _FloatRange.__init__(self, *pargs, **kwargs)
206
197
207 # ensure a minimal amount of sanity
198 # ensure a minimal amount of sanity
208 if self.min > self.max:
199 if self.min > self.max:
209 raise ValueError("min must be <= max")
200 raise ValueError("min must be <= max")
210
201
211 if any_value_given:
202 if any_value_given:
212 # if a value was given, clamp it within (min, max)
203 # if a value was given, clamp it within (min, max)
213 self._validate("value", None, self.value)
204 self._validate("value", None, self.value)
214 else:
205 else:
215 # otherwise, set it to 25-75% to avoid the handles overlapping
206 # otherwise, set it to 25-75% to avoid the handles overlapping
216 self.value = (0.75*self.min + 0.25*self.max,
207 self.value = (0.75*self.min + 0.25*self.max,
217 0.25*self.min + 0.75*self.max)
208 0.25*self.min + 0.75*self.max)
218 # callback already set for 'value', 'lower', 'upper'
209 # callback already set for 'value', 'lower', 'upper'
219 self.on_trait_change(self._validate, ['min', 'max'])
210 self.on_trait_change(self._validate, ['min', 'max'])
220
211
221
212
222 def _validate(self, name, old, new):
213 def _validate(self, name, old, new):
223 if name == "min":
214 if name == "min":
224 if new > self.max:
215 if new > self.max:
225 raise ValueError("setting min > max")
216 raise ValueError("setting min > max")
226 self.min = new
217 self.min = new
227 elif name == "max":
218 elif name == "max":
228 if new < self.min:
219 if new < self.min:
229 raise ValueError("setting max < min")
220 raise ValueError("setting max < min")
230 self.max = new
221 self.max = new
231
222
232 low, high = self.value
223 low, high = self.value
233 if name == "value":
224 if name == "value":
234 low, high = min(new), max(new)
225 low, high = min(new), max(new)
235 elif name == "upper":
226 elif name == "upper":
236 if new < self.lower:
227 if new < self.lower:
237 raise ValueError("setting upper < lower")
228 raise ValueError("setting upper < lower")
238 high = new
229 high = new
239 elif name == "lower":
230 elif name == "lower":
240 if new > self.upper:
231 if new > self.upper:
241 raise ValueError("setting lower > upper")
232 raise ValueError("setting lower > upper")
242 low = new
233 low = new
243
234
244 low = max(self.min, min(low, self.max))
235 low = max(self.min, min(low, self.max))
245 high = min(self.max, max(high, self.min))
236 high = min(self.max, max(high, self.min))
246
237
247 # determine the order in which we should update the
238 # determine the order in which we should update the
248 # lower, upper traits to avoid a temporary inverted overlap
239 # lower, upper traits to avoid a temporary inverted overlap
249 lower_first = high < self.lower
240 lower_first = high < self.lower
250
241
251 self.value = (low, high)
242 self.value = (low, high)
252 if lower_first:
243 if lower_first:
253 self.lower = low
244 self.lower = low
254 self.upper = high
245 self.upper = high
255 else:
246 else:
256 self.upper = high
247 self.upper = high
257 self.lower = low
248 self.lower = low
258
249
259
250
260 @register('IPython.FloatRangeSlider')
251 @register('IPython.FloatRangeSlider')
261 class FloatRangeSlider(_BoundedFloatRange):
252 class FloatRangeSlider(_BoundedFloatRange):
262 """ Slider/trackbar for displaying a floating value range (within the specified range of values).
253 """ Slider/trackbar for displaying a floating value range (within the specified range of values).
263
254
264 Parameters
255 Parameters
265 ----------
256 ----------
266 value : float tuple
257 value : float tuple
267 range of the slider displayed
258 range of the slider displayed
268 min : float
259 min : float
269 minimal position of the slider
260 minimal position of the slider
270 max : float
261 max : float
271 maximal position of the slider
262 maximal position of the slider
272 step : float
263 step : float
273 step of the trackbar
264 step of the trackbar
274 description : str
265 description : str
275 name of the slider
266 name of the slider
276 orientation : {'vertical', 'horizontal}, optional
267 orientation : {'vertical', 'horizontal}, optional
277 default is horizontal
268 default is horizontal
278 readout : {True, False}, optional
269 readout : {True, False}, optional
279 default is True, display the current value of the slider next to it
270 default is True, display the current value of the slider next to it
280 slider_color : str Unicode color code (eg. '#C13535'), optional
271 slider_color : str Unicode color code (eg. '#C13535'), optional
281 color of the slider
272 color of the slider
282 color : str Unicode color code (eg. '#C13535'), optional
273 color : str Unicode color code (eg. '#C13535'), optional
283 color of the value displayed (if readout == True)
274 color of the value displayed (if readout == True)
284 """
275 """
285 _view_name = Unicode('FloatSliderView', sync=True)
276 _view_name = Unicode('FloatSliderView', sync=True)
286 orientation = CaselessStrEnum(values=['horizontal', 'vertical'],
277 orientation = CaselessStrEnum(values=['horizontal', 'vertical'],
287 default_value='horizontal', help="Vertical or horizontal.", sync=True)
278 default_value='horizontal', help="Vertical or horizontal.", sync=True)
288 _range = Bool(True, help="Display a range selector", sync=True)
279 _range = Bool(True, help="Display a range selector", sync=True)
289 readout = Bool(True, help="Display the current value of the slider next to it.", sync=True)
280 readout = Bool(True, help="Display the current value of the slider next to it.", sync=True)
290 slider_color = Color(None, allow_none=True, sync=True)
281 slider_color = Color(None, allow_none=True, sync=True)
291
282
292 # Remove in IPython 4.0
283 # Remove in IPython 4.0
293 FloatTextWidget = DeprecatedClass(FloatText, 'FloatTextWidget')
284 FloatTextWidget = DeprecatedClass(FloatText, 'FloatTextWidget')
294 BoundedFloatTextWidget = DeprecatedClass(BoundedFloatText, 'BoundedFloatTextWidget')
285 BoundedFloatTextWidget = DeprecatedClass(BoundedFloatText, 'BoundedFloatTextWidget')
295 FloatSliderWidget = DeprecatedClass(FloatSlider, 'FloatSliderWidget')
286 FloatSliderWidget = DeprecatedClass(FloatSlider, 'FloatSliderWidget')
296 FloatProgressWidget = DeprecatedClass(FloatProgress, 'FloatProgressWidget')
287 FloatProgressWidget = DeprecatedClass(FloatProgress, 'FloatProgressWidget')
@@ -1,47 +1,37 b''
1 """Image class.
1 """Image class.
2
2
3 Represents an image in the frontend using a widget.
3 Represents an image in the frontend using a widget.
4 """
4 """
5 #-----------------------------------------------------------------------------
5
6 # Copyright (c) 2013, the IPython Development Team.
6 # Copyright (c) IPython Development Team.
7 #
8 # Distributed under the terms of the Modified BSD License.
7 # Distributed under the terms of the Modified BSD License.
9 #
10 # The full license is in the file COPYING.txt, distributed with this software.
11 #-----------------------------------------------------------------------------
12
8
13 #-----------------------------------------------------------------------------
14 # Imports
15 #-----------------------------------------------------------------------------
16 import base64
9 import base64
17
10
18 from .widget import DOMWidget, register
11 from .widget import DOMWidget, register
19 from IPython.utils.traitlets import Unicode, CUnicode, Bytes
12 from IPython.utils.traitlets import Unicode, CUnicode, Bytes
20 from IPython.utils.warn import DeprecatedClass
13 from .deprecated import DeprecatedClass
21
14
22 #-----------------------------------------------------------------------------
23 # Classes
24 #-----------------------------------------------------------------------------
25 @register('IPython.Image')
15 @register('IPython.Image')
26 class Image(DOMWidget):
16 class Image(DOMWidget):
27 """Displays an image as a widget.
17 """Displays an image as a widget.
28
18
29 The `value` of this widget accepts a byte string. The byte string is the raw
19 The `value` of this widget accepts a byte string. The byte string is the raw
30 image data that you want the browser to display. You can explicitly define
20 image data that you want the browser to display. You can explicitly define
31 the format of the byte string using the `format` trait (which defaults to
21 the format of the byte string using the `format` trait (which defaults to
32 "png")."""
22 "png")."""
33 _view_name = Unicode('ImageView', sync=True)
23 _view_name = Unicode('ImageView', sync=True)
34
24
35 # Define the custom state properties to sync with the front-end
25 # Define the custom state properties to sync with the front-end
36 format = Unicode('png', sync=True)
26 format = Unicode('png', sync=True)
37 width = CUnicode(sync=True)
27 width = CUnicode(sync=True)
38 height = CUnicode(sync=True)
28 height = CUnicode(sync=True)
39 _b64value = Unicode(sync=True)
29 _b64value = Unicode(sync=True)
40
30
41 value = Bytes()
31 value = Bytes()
42 def _value_changed(self, name, old, new):
32 def _value_changed(self, name, old, new):
43 self._b64value = base64.b64encode(new)
33 self._b64value = base64.b64encode(new)
44
34
45
35
46 # Remove in IPython 4.0
36 # Remove in IPython 4.0
47 ImageWidget = DeprecatedClass(Image, 'ImageWidget')
37 ImageWidget = DeprecatedClass(Image, 'ImageWidget')
@@ -1,207 +1,198 b''
1 """Int class.
1 """Int class.
2
2
3 Represents an unbounded int using a widget.
3 Represents an unbounded int using a widget.
4 """
4 """
5 #-----------------------------------------------------------------------------
5
6 # Copyright (c) 2013, the IPython Development Team.
6 # Copyright (c) IPython Development Team.
7 #
8 # Distributed under the terms of the Modified BSD License.
7 # Distributed under the terms of the Modified BSD License.
9 #
10 # The full license is in the file COPYING.txt, distributed with this software.
11 #-----------------------------------------------------------------------------
12
8
13 #-----------------------------------------------------------------------------
14 # Imports
15 #-----------------------------------------------------------------------------
16 from .widget import DOMWidget, register
9 from .widget import DOMWidget, register
17 from .trait_types import Color
10 from .trait_types import Color
18 from IPython.utils.traitlets import (Unicode, CInt, Bool, CaselessStrEnum,
11 from IPython.utils.traitlets import (Unicode, CInt, Bool, CaselessStrEnum,
19 Tuple, TraitError)
12 Tuple, TraitError)
20 from IPython.utils.warn import DeprecatedClass
13 from .deprecated import DeprecatedClass
14
21
15
22 #-----------------------------------------------------------------------------
23 # Classes
24 #-----------------------------------------------------------------------------
25 class _Int(DOMWidget):
16 class _Int(DOMWidget):
26 """Base class used to create widgets that represent an int."""
17 """Base class used to create widgets that represent an int."""
27 value = CInt(0, help="Int value", sync=True)
18 value = CInt(0, help="Int value", sync=True)
28 disabled = Bool(False, help="Enable or disable user changes", sync=True)
19 disabled = Bool(False, help="Enable or disable user changes", sync=True)
29 description = Unicode(help="Description of the value this widget represents", sync=True)
20 description = Unicode(help="Description of the value this widget represents", sync=True)
30
21
31 def __init__(self, value=None, **kwargs):
22 def __init__(self, value=None, **kwargs):
32 if value is not None:
23 if value is not None:
33 kwargs['value'] = value
24 kwargs['value'] = value
34 super(_Int, self).__init__(**kwargs)
25 super(_Int, self).__init__(**kwargs)
35
26
36
27
37 class _BoundedInt(_Int):
28 class _BoundedInt(_Int):
38 """Base class used to create widgets that represent a int that is bounded
29 """Base class used to create widgets that represent a int that is bounded
39 by a minium and maximum."""
30 by a minium and maximum."""
40 step = CInt(1, help="Minimum step to increment the value (ignored by some views)", sync=True)
31 step = CInt(1, help="Minimum step to increment the value (ignored by some views)", sync=True)
41 max = CInt(100, help="Max value", sync=True)
32 max = CInt(100, help="Max value", sync=True)
42 min = CInt(0, help="Min value", sync=True)
33 min = CInt(0, help="Min value", sync=True)
43
34
44 def __init__(self, *pargs, **kwargs):
35 def __init__(self, *pargs, **kwargs):
45 """Constructor"""
36 """Constructor"""
46 super(_BoundedInt, self).__init__(*pargs, **kwargs)
37 super(_BoundedInt, self).__init__(*pargs, **kwargs)
47
38
48 def _value_validate(self, value, trait):
39 def _value_validate(self, value, trait):
49 """Cap and floor value"""
40 """Cap and floor value"""
50 if self.min > value or self.max < value:
41 if self.min > value or self.max < value:
51 value = min(max(value, self.min), self.max)
42 value = min(max(value, self.min), self.max)
52 return value
43 return value
53
44
54 def _min_validate(self, min, trait):
45 def _min_validate(self, min, trait):
55 """Enforce min <= value <= max"""
46 """Enforce min <= value <= max"""
56 if min > self.max:
47 if min > self.max:
57 raise TraitError("Setting min > max")
48 raise TraitError("Setting min > max")
58 if min > self.value:
49 if min > self.value:
59 self.value = min
50 self.value = min
60 return min
51 return min
61
52
62 def _max_validate(self, max, trait):
53 def _max_validate(self, max, trait):
63 """Enforce min <= value <= max"""
54 """Enforce min <= value <= max"""
64 if max < self.min:
55 if max < self.min:
65 raise TraitError("setting max < min")
56 raise TraitError("setting max < min")
66 if max < self.value:
57 if max < self.value:
67 self.value = max
58 self.value = max
68 return max
59 return max
69
60
70 @register('IPython.IntText')
61 @register('IPython.IntText')
71 class IntText(_Int):
62 class IntText(_Int):
72 """Textbox widget that represents a int."""
63 """Textbox widget that represents a int."""
73 _view_name = Unicode('IntTextView', sync=True)
64 _view_name = Unicode('IntTextView', sync=True)
74
65
75
66
76 @register('IPython.BoundedIntText')
67 @register('IPython.BoundedIntText')
77 class BoundedIntText(_BoundedInt):
68 class BoundedIntText(_BoundedInt):
78 """Textbox widget that represents a int bounded by a minimum and maximum value."""
69 """Textbox widget that represents a int bounded by a minimum and maximum value."""
79 _view_name = Unicode('IntTextView', sync=True)
70 _view_name = Unicode('IntTextView', sync=True)
80
71
81
72
82 @register('IPython.IntSlider')
73 @register('IPython.IntSlider')
83 class IntSlider(_BoundedInt):
74 class IntSlider(_BoundedInt):
84 """Slider widget that represents a int bounded by a minimum and maximum value."""
75 """Slider widget that represents a int bounded by a minimum and maximum value."""
85 _view_name = Unicode('IntSliderView', sync=True)
76 _view_name = Unicode('IntSliderView', sync=True)
86 orientation = CaselessStrEnum(values=['horizontal', 'vertical'],
77 orientation = CaselessStrEnum(values=['horizontal', 'vertical'],
87 default_value='horizontal', help="Vertical or horizontal.", sync=True)
78 default_value='horizontal', help="Vertical or horizontal.", sync=True)
88 _range = Bool(False, help="Display a range selector", sync=True)
79 _range = Bool(False, help="Display a range selector", sync=True)
89 readout = Bool(True, help="Display the current value of the slider next to it.", sync=True)
80 readout = Bool(True, help="Display the current value of the slider next to it.", sync=True)
90 slider_color = Color(None, allow_none=True, sync=True)
81 slider_color = Color(None, allow_none=True, sync=True)
91
82
92
83
93 @register('IPython.IntProgress')
84 @register('IPython.IntProgress')
94 class IntProgress(_BoundedInt):
85 class IntProgress(_BoundedInt):
95 """Progress bar that represents a int bounded by a minimum and maximum value."""
86 """Progress bar that represents a int bounded by a minimum and maximum value."""
96 _view_name = Unicode('ProgressView', sync=True)
87 _view_name = Unicode('ProgressView', sync=True)
97
88
98 bar_style = CaselessStrEnum(
89 bar_style = CaselessStrEnum(
99 values=['success', 'info', 'warning', 'danger', ''],
90 values=['success', 'info', 'warning', 'danger', ''],
100 default_value='', allow_none=True, sync=True, help="""Use a
91 default_value='', allow_none=True, sync=True, help="""Use a
101 predefined styling for the progess bar.""")
92 predefined styling for the progess bar.""")
102
93
103 class _IntRange(_Int):
94 class _IntRange(_Int):
104 value = Tuple(CInt, CInt, default_value=(0, 1), help="Tuple of (lower, upper) bounds", sync=True)
95 value = Tuple(CInt, CInt, default_value=(0, 1), help="Tuple of (lower, upper) bounds", sync=True)
105 lower = CInt(0, help="Lower bound", sync=False)
96 lower = CInt(0, help="Lower bound", sync=False)
106 upper = CInt(1, help="Upper bound", sync=False)
97 upper = CInt(1, help="Upper bound", sync=False)
107
98
108 def __init__(self, *pargs, **kwargs):
99 def __init__(self, *pargs, **kwargs):
109 value_given = 'value' in kwargs
100 value_given = 'value' in kwargs
110 lower_given = 'lower' in kwargs
101 lower_given = 'lower' in kwargs
111 upper_given = 'upper' in kwargs
102 upper_given = 'upper' in kwargs
112 if value_given and (lower_given or upper_given):
103 if value_given and (lower_given or upper_given):
113 raise ValueError("Cannot specify both 'value' and 'lower'/'upper' for range widget")
104 raise ValueError("Cannot specify both 'value' and 'lower'/'upper' for range widget")
114 if lower_given != upper_given:
105 if lower_given != upper_given:
115 raise ValueError("Must specify both 'lower' and 'upper' for range widget")
106 raise ValueError("Must specify both 'lower' and 'upper' for range widget")
116
107
117 super(_IntRange, self).__init__(*pargs, **kwargs)
108 super(_IntRange, self).__init__(*pargs, **kwargs)
118
109
119 # ensure the traits match, preferring whichever (if any) was given in kwargs
110 # ensure the traits match, preferring whichever (if any) was given in kwargs
120 if value_given:
111 if value_given:
121 self.lower, self.upper = self.value
112 self.lower, self.upper = self.value
122 else:
113 else:
123 self.value = (self.lower, self.upper)
114 self.value = (self.lower, self.upper)
124
115
125 self.on_trait_change(self._validate, ['value', 'upper', 'lower'])
116 self.on_trait_change(self._validate, ['value', 'upper', 'lower'])
126
117
127 def _validate(self, name, old, new):
118 def _validate(self, name, old, new):
128 if name == 'value':
119 if name == 'value':
129 self.lower, self.upper = min(new), max(new)
120 self.lower, self.upper = min(new), max(new)
130 elif name == 'lower':
121 elif name == 'lower':
131 self.value = (new, self.value[1])
122 self.value = (new, self.value[1])
132 elif name == 'upper':
123 elif name == 'upper':
133 self.value = (self.value[0], new)
124 self.value = (self.value[0], new)
134
125
135 class _BoundedIntRange(_IntRange):
126 class _BoundedIntRange(_IntRange):
136 step = CInt(1, help="Minimum step that the value can take (ignored by some views)", sync=True)
127 step = CInt(1, help="Minimum step that the value can take (ignored by some views)", sync=True)
137 max = CInt(100, help="Max value", sync=True)
128 max = CInt(100, help="Max value", sync=True)
138 min = CInt(0, help="Min value", sync=True)
129 min = CInt(0, help="Min value", sync=True)
139
130
140 def __init__(self, *pargs, **kwargs):
131 def __init__(self, *pargs, **kwargs):
141 any_value_given = 'value' in kwargs or 'upper' in kwargs or 'lower' in kwargs
132 any_value_given = 'value' in kwargs or 'upper' in kwargs or 'lower' in kwargs
142 _IntRange.__init__(self, *pargs, **kwargs)
133 _IntRange.__init__(self, *pargs, **kwargs)
143
134
144 # ensure a minimal amount of sanity
135 # ensure a minimal amount of sanity
145 if self.min > self.max:
136 if self.min > self.max:
146 raise ValueError("min must be <= max")
137 raise ValueError("min must be <= max")
147
138
148 if any_value_given:
139 if any_value_given:
149 # if a value was given, clamp it within (min, max)
140 # if a value was given, clamp it within (min, max)
150 self._validate("value", None, self.value)
141 self._validate("value", None, self.value)
151 else:
142 else:
152 # otherwise, set it to 25-75% to avoid the handles overlapping
143 # otherwise, set it to 25-75% to avoid the handles overlapping
153 self.value = (0.75*self.min + 0.25*self.max,
144 self.value = (0.75*self.min + 0.25*self.max,
154 0.25*self.min + 0.75*self.max)
145 0.25*self.min + 0.75*self.max)
155 # callback already set for 'value', 'lower', 'upper'
146 # callback already set for 'value', 'lower', 'upper'
156 self.on_trait_change(self._validate, ['min', 'max'])
147 self.on_trait_change(self._validate, ['min', 'max'])
157
148
158 def _validate(self, name, old, new):
149 def _validate(self, name, old, new):
159 if name == "min":
150 if name == "min":
160 if new > self.max:
151 if new > self.max:
161 raise ValueError("setting min > max")
152 raise ValueError("setting min > max")
162 elif name == "max":
153 elif name == "max":
163 if new < self.min:
154 if new < self.min:
164 raise ValueError("setting max < min")
155 raise ValueError("setting max < min")
165
156
166 low, high = self.value
157 low, high = self.value
167 if name == "value":
158 if name == "value":
168 low, high = min(new), max(new)
159 low, high = min(new), max(new)
169 elif name == "upper":
160 elif name == "upper":
170 if new < self.lower:
161 if new < self.lower:
171 raise ValueError("setting upper < lower")
162 raise ValueError("setting upper < lower")
172 high = new
163 high = new
173 elif name == "lower":
164 elif name == "lower":
174 if new > self.upper:
165 if new > self.upper:
175 raise ValueError("setting lower > upper")
166 raise ValueError("setting lower > upper")
176 low = new
167 low = new
177
168
178 low = max(self.min, min(low, self.max))
169 low = max(self.min, min(low, self.max))
179 high = min(self.max, max(high, self.min))
170 high = min(self.max, max(high, self.min))
180
171
181 # determine the order in which we should update the
172 # determine the order in which we should update the
182 # lower, upper traits to avoid a temporary inverted overlap
173 # lower, upper traits to avoid a temporary inverted overlap
183 lower_first = high < self.lower
174 lower_first = high < self.lower
184
175
185 self.value = (low, high)
176 self.value = (low, high)
186 if lower_first:
177 if lower_first:
187 self.lower = low
178 self.lower = low
188 self.upper = high
179 self.upper = high
189 else:
180 else:
190 self.upper = high
181 self.upper = high
191 self.lower = low
182 self.lower = low
192
183
193 @register('IPython.IntRangeSlider')
184 @register('IPython.IntRangeSlider')
194 class IntRangeSlider(_BoundedIntRange):
185 class IntRangeSlider(_BoundedIntRange):
195 """Slider widget that represents a pair of ints between a minimum and maximum value."""
186 """Slider widget that represents a pair of ints between a minimum and maximum value."""
196 _view_name = Unicode('IntSliderView', sync=True)
187 _view_name = Unicode('IntSliderView', sync=True)
197 orientation = CaselessStrEnum(values=['horizontal', 'vertical'],
188 orientation = CaselessStrEnum(values=['horizontal', 'vertical'],
198 default_value='horizontal', help="Vertical or horizontal.", sync=True)
189 default_value='horizontal', help="Vertical or horizontal.", sync=True)
199 _range = Bool(True, help="Display a range selector", sync=True)
190 _range = Bool(True, help="Display a range selector", sync=True)
200 readout = Bool(True, help="Display the current value of the slider next to it.", sync=True)
191 readout = Bool(True, help="Display the current value of the slider next to it.", sync=True)
201 slider_color = Color(None, allow_none=True, sync=True)
192 slider_color = Color(None, allow_none=True, sync=True)
202
193
203 # Remove in IPython 4.0
194 # Remove in IPython 4.0
204 IntTextWidget = DeprecatedClass(IntText, 'IntTextWidget')
195 IntTextWidget = DeprecatedClass(IntText, 'IntTextWidget')
205 BoundedIntTextWidget = DeprecatedClass(BoundedIntText, 'BoundedIntTextWidget')
196 BoundedIntTextWidget = DeprecatedClass(BoundedIntText, 'BoundedIntTextWidget')
206 IntSliderWidget = DeprecatedClass(IntSlider, 'IntSliderWidget')
197 IntSliderWidget = DeprecatedClass(IntSlider, 'IntSliderWidget')
207 IntProgressWidget = DeprecatedClass(IntProgress, 'IntProgressWidget')
198 IntProgressWidget = DeprecatedClass(IntProgress, 'IntProgressWidget')
@@ -1,248 +1,238 b''
1 """Selection classes.
1 """Selection classes.
2
2
3 Represents an enumeration using a widget.
3 Represents an enumeration using a widget.
4 """
4 """
5 #-----------------------------------------------------------------------------
6 # Copyright (c) 2013, the IPython Development Team.
7 #
8 # Distributed under the terms of the Modified BSD License.
9 #
10 # The full license is in the file COPYING.txt, distributed with this software.
11 #-----------------------------------------------------------------------------
12
5
13 #-----------------------------------------------------------------------------
6 # Copyright (c) IPython Development Team.
14 # Imports
7 # Distributed under the terms of the Modified BSD License.
15 #-----------------------------------------------------------------------------
16
8
17 from collections import OrderedDict
9 from collections import OrderedDict
18 from threading import Lock
10 from threading import Lock
19
11
20 from .widget import DOMWidget, register
12 from .widget import DOMWidget, register
21 from IPython.utils.traitlets import (
13 from IPython.utils.traitlets import (
22 Unicode, Bool, Any, Dict, TraitError, CaselessStrEnum, Tuple, List
14 Unicode, Bool, Any, Dict, TraitError, CaselessStrEnum, Tuple, List
23 )
15 )
24 from IPython.utils.py3compat import unicode_type
16 from IPython.utils.py3compat import unicode_type
25 from IPython.utils.warn import DeprecatedClass
17 from .deprecated import DeprecatedClass
18
26
19
27 #-----------------------------------------------------------------------------
28 # SelectionWidget
29 #-----------------------------------------------------------------------------
30 class _Selection(DOMWidget):
20 class _Selection(DOMWidget):
31 """Base class for Selection widgets
21 """Base class for Selection widgets
32
22
33 ``options`` can be specified as a list or dict. If given as a list,
23 ``options`` can be specified as a list or dict. If given as a list,
34 it will be transformed to a dict of the form ``{str(value):value}``.
24 it will be transformed to a dict of the form ``{str(value):value}``.
35
25
36 When programmatically setting the value, a reverse lookup is performed
26 When programmatically setting the value, a reverse lookup is performed
37 among the options to set the value of ``selected_label`` accordingly. The
27 among the options to set the value of ``selected_label`` accordingly. The
38 reverse lookup uses the equality operator by default, but an other
28 reverse lookup uses the equality operator by default, but an other
39 predicate may be provided via the ``equals`` argument. For example, when
29 predicate may be provided via the ``equals`` argument. For example, when
40 dealing with numpy arrays, one may set equals=np.array_equal.
30 dealing with numpy arrays, one may set equals=np.array_equal.
41 """
31 """
42
32
43 value = Any(help="Selected value")
33 value = Any(help="Selected value")
44 selected_label = Unicode(help="The label of the selected value", sync=True)
34 selected_label = Unicode(help="The label of the selected value", sync=True)
45 options = Any(help="""List of (key, value) tuples or dict of values that the
35 options = Any(help="""List of (key, value) tuples or dict of values that the
46 user can select.
36 user can select.
47
37
48 The keys of this list are the strings that will be displayed in the UI,
38 The keys of this list are the strings that will be displayed in the UI,
49 representing the actual Python choices.
39 representing the actual Python choices.
50
40
51 The keys of this list are also available as _options_labels.
41 The keys of this list are also available as _options_labels.
52 """)
42 """)
53
43
54 _options_dict = Dict()
44 _options_dict = Dict()
55 _options_labels = Tuple(sync=True)
45 _options_labels = Tuple(sync=True)
56 _options_values = Tuple()
46 _options_values = Tuple()
57
47
58 disabled = Bool(False, help="Enable or disable user changes", sync=True)
48 disabled = Bool(False, help="Enable or disable user changes", sync=True)
59 description = Unicode(help="Description of the value this widget represents", sync=True)
49 description = Unicode(help="Description of the value this widget represents", sync=True)
60
50
61 def __init__(self, *args, **kwargs):
51 def __init__(self, *args, **kwargs):
62 self.value_lock = Lock()
52 self.value_lock = Lock()
63 self.options_lock = Lock()
53 self.options_lock = Lock()
64 self.equals = kwargs.pop('equals', lambda x, y: x == y)
54 self.equals = kwargs.pop('equals', lambda x, y: x == y)
65 self.on_trait_change(self._options_readonly_changed, ['_options_dict', '_options_labels', '_options_values', '_options'])
55 self.on_trait_change(self._options_readonly_changed, ['_options_dict', '_options_labels', '_options_values', '_options'])
66 if 'options' in kwargs:
56 if 'options' in kwargs:
67 self.options = kwargs.pop('options')
57 self.options = kwargs.pop('options')
68 DOMWidget.__init__(self, *args, **kwargs)
58 DOMWidget.__init__(self, *args, **kwargs)
69 self._value_in_options()
59 self._value_in_options()
70
60
71 def _make_options(self, x):
61 def _make_options(self, x):
72 # If x is a dict, convert it to list format.
62 # If x is a dict, convert it to list format.
73 if isinstance(x, (OrderedDict, dict)):
63 if isinstance(x, (OrderedDict, dict)):
74 return [(k, v) for k, v in x.items()]
64 return [(k, v) for k, v in x.items()]
75
65
76 # Make sure x is a list or tuple.
66 # Make sure x is a list or tuple.
77 if not isinstance(x, (list, tuple)):
67 if not isinstance(x, (list, tuple)):
78 raise ValueError('x')
68 raise ValueError('x')
79
69
80 # If x is an ordinary list, use the option values as names.
70 # If x is an ordinary list, use the option values as names.
81 for y in x:
71 for y in x:
82 if not isinstance(y, (list, tuple)) or len(y) < 2:
72 if not isinstance(y, (list, tuple)) or len(y) < 2:
83 return [(i, i) for i in x]
73 return [(i, i) for i in x]
84
74
85 # Value is already in the correct format.
75 # Value is already in the correct format.
86 return x
76 return x
87
77
88 def _options_changed(self, name, old, new):
78 def _options_changed(self, name, old, new):
89 """Handles when the options tuple has been changed.
79 """Handles when the options tuple has been changed.
90
80
91 Setting options implies setting option labels from the keys of the dict.
81 Setting options implies setting option labels from the keys of the dict.
92 """
82 """
93 if self.options_lock.acquire(False):
83 if self.options_lock.acquire(False):
94 try:
84 try:
95 self.options = new
85 self.options = new
96
86
97 options = self._make_options(new)
87 options = self._make_options(new)
98 self._options_dict = {i[0]: i[1] for i in options}
88 self._options_dict = {i[0]: i[1] for i in options}
99 self._options_labels = [i[0] for i in options]
89 self._options_labels = [i[0] for i in options]
100 self._options_values = [i[1] for i in options]
90 self._options_values = [i[1] for i in options]
101 self._value_in_options()
91 self._value_in_options()
102 finally:
92 finally:
103 self.options_lock.release()
93 self.options_lock.release()
104
94
105 def _value_in_options(self):
95 def _value_in_options(self):
106 # ensure that the chosen value is one of the choices
96 # ensure that the chosen value is one of the choices
107
97
108 if self._options_values:
98 if self._options_values:
109 if self.value not in self._options_values:
99 if self.value not in self._options_values:
110 self.value = next(iter(self._options_values))
100 self.value = next(iter(self._options_values))
111
101
112 def _options_readonly_changed(self, name, old, new):
102 def _options_readonly_changed(self, name, old, new):
113 if not self.options_lock.locked():
103 if not self.options_lock.locked():
114 raise TraitError("`.%s` is a read-only trait. Use the `.options` tuple instead." % name)
104 raise TraitError("`.%s` is a read-only trait. Use the `.options` tuple instead." % name)
115
105
116 def _value_changed(self, name, old, new):
106 def _value_changed(self, name, old, new):
117 """Called when value has been changed"""
107 """Called when value has been changed"""
118 if self.value_lock.acquire(False):
108 if self.value_lock.acquire(False):
119 try:
109 try:
120 # Reverse dictionary lookup for the value name
110 # Reverse dictionary lookup for the value name
121 for k, v in self._options_dict.items():
111 for k, v in self._options_dict.items():
122 if self.equals(new, v):
112 if self.equals(new, v):
123 # set the selected value name
113 # set the selected value name
124 self.selected_label = k
114 self.selected_label = k
125 return
115 return
126 # undo the change, and raise KeyError
116 # undo the change, and raise KeyError
127 self.value = old
117 self.value = old
128 raise KeyError(new)
118 raise KeyError(new)
129 finally:
119 finally:
130 self.value_lock.release()
120 self.value_lock.release()
131
121
132 def _selected_label_changed(self, name, old, new):
122 def _selected_label_changed(self, name, old, new):
133 """Called when the value name has been changed (typically by the frontend)."""
123 """Called when the value name has been changed (typically by the frontend)."""
134 if self.value_lock.acquire(False):
124 if self.value_lock.acquire(False):
135 try:
125 try:
136 self.value = self._options_dict[new]
126 self.value = self._options_dict[new]
137 finally:
127 finally:
138 self.value_lock.release()
128 self.value_lock.release()
139
129
140
130
141 class _MultipleSelection(_Selection):
131 class _MultipleSelection(_Selection):
142 """Base class for MultipleSelection widgets.
132 """Base class for MultipleSelection widgets.
143
133
144 As with ``_Selection``, ``options`` can be specified as a list or dict. If
134 As with ``_Selection``, ``options`` can be specified as a list or dict. If
145 given as a list, it will be transformed to a dict of the form
135 given as a list, it will be transformed to a dict of the form
146 ``{str(value): value}``.
136 ``{str(value): value}``.
147
137
148 Despite their names, ``value`` (and ``selected_label``) will be tuples, even
138 Despite their names, ``value`` (and ``selected_label``) will be tuples, even
149 if only a single option is selected.
139 if only a single option is selected.
150 """
140 """
151
141
152 value = Tuple(help="Selected values")
142 value = Tuple(help="Selected values")
153 selected_labels = Tuple(help="The labels of the selected options",
143 selected_labels = Tuple(help="The labels of the selected options",
154 sync=True)
144 sync=True)
155
145
156 @property
146 @property
157 def selected_label(self):
147 def selected_label(self):
158 raise AttributeError(
148 raise AttributeError(
159 "Does not support selected_label, use selected_labels")
149 "Does not support selected_label, use selected_labels")
160
150
161 def _value_in_options(self):
151 def _value_in_options(self):
162 # ensure that the chosen value is one of the choices
152 # ensure that the chosen value is one of the choices
163 if self.options:
153 if self.options:
164 old_value = self.value or []
154 old_value = self.value or []
165 new_value = []
155 new_value = []
166 for value in old_value:
156 for value in old_value:
167 if value in self._options_dict.values():
157 if value in self._options_dict.values():
168 new_value.append(value)
158 new_value.append(value)
169 if new_value:
159 if new_value:
170 self.value = new_value
160 self.value = new_value
171 else:
161 else:
172 self.value = [next(iter(self._options_dict.values()))]
162 self.value = [next(iter(self._options_dict.values()))]
173
163
174 def _value_changed(self, name, old, new):
164 def _value_changed(self, name, old, new):
175 """Called when value has been changed"""
165 """Called when value has been changed"""
176 if self.value_lock.acquire(False):
166 if self.value_lock.acquire(False):
177 try:
167 try:
178 self.selected_labels = [
168 self.selected_labels = [
179 self._options_labels[self._options_values.index(v)]
169 self._options_labels[self._options_values.index(v)]
180 for v in new
170 for v in new
181 ]
171 ]
182 except:
172 except:
183 self.value = old
173 self.value = old
184 raise KeyError(new)
174 raise KeyError(new)
185 finally:
175 finally:
186 self.value_lock.release()
176 self.value_lock.release()
187
177
188 def _selected_labels_changed(self, name, old, new):
178 def _selected_labels_changed(self, name, old, new):
189 """Called when the selected label has been changed (typically by the
179 """Called when the selected label has been changed (typically by the
190 frontend)."""
180 frontend)."""
191 if self.value_lock.acquire(False):
181 if self.value_lock.acquire(False):
192 try:
182 try:
193 self.value = [self._options_dict[name] for name in new]
183 self.value = [self._options_dict[name] for name in new]
194 finally:
184 finally:
195 self.value_lock.release()
185 self.value_lock.release()
196
186
197
187
198 @register('IPython.ToggleButtons')
188 @register('IPython.ToggleButtons')
199 class ToggleButtons(_Selection):
189 class ToggleButtons(_Selection):
200 """Group of toggle buttons that represent an enumeration. Only one toggle
190 """Group of toggle buttons that represent an enumeration. Only one toggle
201 button can be toggled at any point in time."""
191 button can be toggled at any point in time."""
202 _view_name = Unicode('ToggleButtonsView', sync=True)
192 _view_name = Unicode('ToggleButtonsView', sync=True)
203 tooltips = List(Unicode(), sync=True)
193 tooltips = List(Unicode(), sync=True)
204 icons = List(Unicode(), sync=True)
194 icons = List(Unicode(), sync=True)
205
195
206 button_style = CaselessStrEnum(
196 button_style = CaselessStrEnum(
207 values=['primary', 'success', 'info', 'warning', 'danger', ''],
197 values=['primary', 'success', 'info', 'warning', 'danger', ''],
208 default_value='', allow_none=True, sync=True, help="""Use a
198 default_value='', allow_none=True, sync=True, help="""Use a
209 predefined styling for the buttons.""")
199 predefined styling for the buttons.""")
210
200
211 @register('IPython.Dropdown')
201 @register('IPython.Dropdown')
212 class Dropdown(_Selection):
202 class Dropdown(_Selection):
213 """Allows you to select a single item from a dropdown."""
203 """Allows you to select a single item from a dropdown."""
214 _view_name = Unicode('DropdownView', sync=True)
204 _view_name = Unicode('DropdownView', sync=True)
215
205
216 button_style = CaselessStrEnum(
206 button_style = CaselessStrEnum(
217 values=['primary', 'success', 'info', 'warning', 'danger', ''],
207 values=['primary', 'success', 'info', 'warning', 'danger', ''],
218 default_value='', allow_none=True, sync=True, help="""Use a
208 default_value='', allow_none=True, sync=True, help="""Use a
219 predefined styling for the buttons.""")
209 predefined styling for the buttons.""")
220
210
221 @register('IPython.RadioButtons')
211 @register('IPython.RadioButtons')
222 class RadioButtons(_Selection):
212 class RadioButtons(_Selection):
223 """Group of radio buttons that represent an enumeration. Only one radio
213 """Group of radio buttons that represent an enumeration. Only one radio
224 button can be toggled at any point in time."""
214 button can be toggled at any point in time."""
225 _view_name = Unicode('RadioButtonsView', sync=True)
215 _view_name = Unicode('RadioButtonsView', sync=True)
226
216
227
217
228
218
229 @register('IPython.Select')
219 @register('IPython.Select')
230 class Select(_Selection):
220 class Select(_Selection):
231 """Listbox that only allows one item to be selected at any given time."""
221 """Listbox that only allows one item to be selected at any given time."""
232 _view_name = Unicode('SelectView', sync=True)
222 _view_name = Unicode('SelectView', sync=True)
233
223
234
224
235 @register('IPython.SelectMultiple')
225 @register('IPython.SelectMultiple')
236 class SelectMultiple(_MultipleSelection):
226 class SelectMultiple(_MultipleSelection):
237 """Listbox that allows many items to be selected at any given time.
227 """Listbox that allows many items to be selected at any given time.
238 Despite their names, inherited from ``_Selection``, the currently chosen
228 Despite their names, inherited from ``_Selection``, the currently chosen
239 option values, ``value``, or their labels, ``selected_labels`` must both be
229 option values, ``value``, or their labels, ``selected_labels`` must both be
240 updated with a list-like object."""
230 updated with a list-like object."""
241 _view_name = Unicode('SelectMultipleView', sync=True)
231 _view_name = Unicode('SelectMultipleView', sync=True)
242
232
243
233
244 # Remove in IPython 4.0
234 # Remove in IPython 4.0
245 ToggleButtonsWidget = DeprecatedClass(ToggleButtons, 'ToggleButtonsWidget')
235 ToggleButtonsWidget = DeprecatedClass(ToggleButtons, 'ToggleButtonsWidget')
246 DropdownWidget = DeprecatedClass(Dropdown, 'DropdownWidget')
236 DropdownWidget = DeprecatedClass(Dropdown, 'DropdownWidget')
247 RadioButtonsWidget = DeprecatedClass(RadioButtons, 'RadioButtonsWidget')
237 RadioButtonsWidget = DeprecatedClass(RadioButtons, 'RadioButtonsWidget')
248 SelectWidget = DeprecatedClass(Select, 'SelectWidget')
238 SelectWidget = DeprecatedClass(Select, 'SelectWidget')
@@ -1,68 +1,58 b''
1 """SelectionContainer class.
1 """SelectionContainer class.
2
2
3 Represents a multipage container that can be used to group other widgets into
3 Represents a multipage container that can be used to group other widgets into
4 pages.
4 pages.
5 """
5 """
6 #-----------------------------------------------------------------------------
6
7 # Copyright (c) 2013, the IPython Development Team.
7 # Copyright (c) IPython Development Team.
8 #
9 # Distributed under the terms of the Modified BSD License.
8 # Distributed under the terms of the Modified BSD License.
10 #
11 # The full license is in the file COPYING.txt, distributed with this software.
12 #-----------------------------------------------------------------------------
13
9
14 #-----------------------------------------------------------------------------
15 # Imports
16 #-----------------------------------------------------------------------------
17 from .widget_box import Box, register
10 from .widget_box import Box, register
18 from IPython.utils.traitlets import Unicode, Dict, CInt
11 from IPython.utils.traitlets import Unicode, Dict, CInt
19 from IPython.utils.warn import DeprecatedClass
12 from .deprecated import DeprecatedClass
20
13
21 #-----------------------------------------------------------------------------
22 # Classes
23 #-----------------------------------------------------------------------------
24 class _SelectionContainer(Box):
14 class _SelectionContainer(Box):
25 """Base class used to display multiple child widgets."""
15 """Base class used to display multiple child widgets."""
26 _titles = Dict(help="Titles of the pages", sync=True)
16 _titles = Dict(help="Titles of the pages", sync=True)
27 selected_index = CInt(0, sync=True)
17 selected_index = CInt(0, sync=True)
28
18
29 # Public methods
19 # Public methods
30 def set_title(self, index, title):
20 def set_title(self, index, title):
31 """Sets the title of a container page.
21 """Sets the title of a container page.
32
22
33 Parameters
23 Parameters
34 ----------
24 ----------
35 index : int
25 index : int
36 Index of the container page
26 Index of the container page
37 title : unicode
27 title : unicode
38 New title"""
28 New title"""
39 self._titles[index] = title
29 self._titles[index] = title
40 self.send_state('_titles')
30 self.send_state('_titles')
41
31
42 def get_title(self, index):
32 def get_title(self, index):
43 """Gets the title of a container pages.
33 """Gets the title of a container pages.
44
34
45 Parameters
35 Parameters
46 ----------
36 ----------
47 index : int
37 index : int
48 Index of the container page"""
38 Index of the container page"""
49 if index in self._titles:
39 if index in self._titles:
50 return self._titles[index]
40 return self._titles[index]
51 else:
41 else:
52 return None
42 return None
53
43
54 @register('IPython.Accordion')
44 @register('IPython.Accordion')
55 class Accordion(_SelectionContainer):
45 class Accordion(_SelectionContainer):
56 """Displays children each on a separate accordion page."""
46 """Displays children each on a separate accordion page."""
57 _view_name = Unicode('AccordionView', sync=True)
47 _view_name = Unicode('AccordionView', sync=True)
58
48
59
49
60 @register('IPython.Tab')
50 @register('IPython.Tab')
61 class Tab(_SelectionContainer):
51 class Tab(_SelectionContainer):
62 """Displays children each on a separate accordion tab."""
52 """Displays children each on a separate accordion tab."""
63 _view_name = Unicode('TabView', sync=True)
53 _view_name = Unicode('TabView', sync=True)
64
54
65
55
66 # Remove in IPython 4.0
56 # Remove in IPython 4.0
67 AccordionWidget = DeprecatedClass(Accordion, 'AccordionWidget')
57 AccordionWidget = DeprecatedClass(Accordion, 'AccordionWidget')
68 TabWidget = DeprecatedClass(Tab, 'TabWidget')
58 TabWidget = DeprecatedClass(Tab, 'TabWidget')
@@ -1,95 +1,86 b''
1 """String class.
1 """String class.
2
2
3 Represents a unicode string using a widget.
3 Represents a unicode string using a widget.
4 """
4 """
5 #-----------------------------------------------------------------------------
5
6 # Copyright (c) 2013, the IPython Development Team.
6 # Copyright (c) IPython Development Team.
7 #
8 # Distributed under the terms of the Modified BSD License.
7 # Distributed under the terms of the Modified BSD License.
9 #
10 # The full license is in the file COPYING.txt, distributed with this software.
11 #-----------------------------------------------------------------------------
12
8
13 #-----------------------------------------------------------------------------
14 # Imports
15 #-----------------------------------------------------------------------------
16 from .widget import DOMWidget, CallbackDispatcher, register
9 from .widget import DOMWidget, CallbackDispatcher, register
17 from IPython.utils.traitlets import Unicode, Bool
10 from IPython.utils.traitlets import Unicode, Bool
18 from IPython.utils.warn import DeprecatedClass
11 from .deprecated import DeprecatedClass
12
19
13
20 #-----------------------------------------------------------------------------
21 # Classes
22 #-----------------------------------------------------------------------------
23 class _String(DOMWidget):
14 class _String(DOMWidget):
24 """Base class used to create widgets that represent a string."""
15 """Base class used to create widgets that represent a string."""
25 value = Unicode(help="String value", sync=True)
16 value = Unicode(help="String value", sync=True)
26 disabled = Bool(False, help="Enable or disable user changes", sync=True)
17 disabled = Bool(False, help="Enable or disable user changes", sync=True)
27 description = Unicode(help="Description of the value this widget represents", sync=True)
18 description = Unicode(help="Description of the value this widget represents", sync=True)
28 placeholder = Unicode("", help="Placeholder text to display when nothing has been typed", sync=True)
19 placeholder = Unicode("", help="Placeholder text to display when nothing has been typed", sync=True)
29
20
30 def __init__(self, value=None, **kwargs):
21 def __init__(self, value=None, **kwargs):
31 if value is not None:
22 if value is not None:
32 kwargs['value'] = value
23 kwargs['value'] = value
33 super(_String, self).__init__(**kwargs)
24 super(_String, self).__init__(**kwargs)
34
25
35 @register('IPython.HTML')
26 @register('IPython.HTML')
36 class HTML(_String):
27 class HTML(_String):
37 """Renders the string `value` as HTML."""
28 """Renders the string `value` as HTML."""
38 _view_name = Unicode('HTMLView', sync=True)
29 _view_name = Unicode('HTMLView', sync=True)
39
30
40
31
41 @register('IPython.Latex')
32 @register('IPython.Latex')
42 class Latex(_String):
33 class Latex(_String):
43 """Renders math inside the string `value` as Latex (requires $ $ or $$ $$
34 """Renders math inside the string `value` as Latex (requires $ $ or $$ $$
44 and similar latex tags)."""
35 and similar latex tags)."""
45 _view_name = Unicode('LatexView', sync=True)
36 _view_name = Unicode('LatexView', sync=True)
46
37
47
38
48 @register('IPython.Textarea')
39 @register('IPython.Textarea')
49 class Textarea(_String):
40 class Textarea(_String):
50 """Multiline text area widget."""
41 """Multiline text area widget."""
51 _view_name = Unicode('TextareaView', sync=True)
42 _view_name = Unicode('TextareaView', sync=True)
52
43
53 def scroll_to_bottom(self):
44 def scroll_to_bottom(self):
54 self.send({"method": "scroll_to_bottom"})
45 self.send({"method": "scroll_to_bottom"})
55
46
56
47
57 @register('IPython.Text')
48 @register('IPython.Text')
58 class Text(_String):
49 class Text(_String):
59 """Single line textbox widget."""
50 """Single line textbox widget."""
60 _view_name = Unicode('TextView', sync=True)
51 _view_name = Unicode('TextView', sync=True)
61
52
62 def __init__(self, *args, **kwargs):
53 def __init__(self, *args, **kwargs):
63 super(Text, self).__init__(*args, **kwargs)
54 super(Text, self).__init__(*args, **kwargs)
64 self._submission_callbacks = CallbackDispatcher()
55 self._submission_callbacks = CallbackDispatcher()
65 self.on_msg(self._handle_string_msg)
56 self.on_msg(self._handle_string_msg)
66
57
67 def _handle_string_msg(self, _, content):
58 def _handle_string_msg(self, _, content):
68 """Handle a msg from the front-end.
59 """Handle a msg from the front-end.
69
60
70 Parameters
61 Parameters
71 ----------
62 ----------
72 content: dict
63 content: dict
73 Content of the msg."""
64 Content of the msg."""
74 if content.get('event', '') == 'submit':
65 if content.get('event', '') == 'submit':
75 self._submission_callbacks(self)
66 self._submission_callbacks(self)
76
67
77 def on_submit(self, callback, remove=False):
68 def on_submit(self, callback, remove=False):
78 """(Un)Register a callback to handle text submission.
69 """(Un)Register a callback to handle text submission.
79
70
80 Triggered when the user clicks enter.
71 Triggered when the user clicks enter.
81
72
82 Parameters
73 Parameters
83 ----------
74 ----------
84 callback: callable
75 callback: callable
85 Will be called with exactly one argument: the Widget instance
76 Will be called with exactly one argument: the Widget instance
86 remove: bool (optional)
77 remove: bool (optional)
87 Whether to unregister the callback"""
78 Whether to unregister the callback"""
88 self._submission_callbacks.register_callback(callback, remove=remove)
79 self._submission_callbacks.register_callback(callback, remove=remove)
89
80
90
81
91 # Remove in IPython 4.0
82 # Remove in IPython 4.0
92 HTMLWidget = DeprecatedClass(HTML, 'HTMLWidget')
83 HTMLWidget = DeprecatedClass(HTML, 'HTMLWidget')
93 LatexWidget = DeprecatedClass(Latex, 'LatexWidget')
84 LatexWidget = DeprecatedClass(Latex, 'LatexWidget')
94 TextareaWidget = DeprecatedClass(Textarea, 'TextareaWidget')
85 TextareaWidget = DeprecatedClass(Textarea, 'TextareaWidget')
95 TextWidget = DeprecatedClass(Text, 'TextWidget')
86 TextWidget = DeprecatedClass(Text, 'TextWidget')
@@ -1,81 +1,57 b''
1 # encoding: utf-8
1 # encoding: utf-8
2 """
2 """
3 Utilities for warnings. Shoudn't we just use the built in warnings module.
3 Utilities for warnings. Shoudn't we just use the built in warnings module.
4 """
4 """
5
5
6 #-----------------------------------------------------------------------------
6 # Copyright (c) IPython Development Team.
7 # Copyright (C) 2008-2011 The IPython Development Team
7 # Distributed under the terms of the Modified BSD License.
8 #
8
9 # Distributed under the terms of the BSD License. The full license is in
10 # the file COPYING, distributed as part of this software.
11 #-----------------------------------------------------------------------------
12
13 #-----------------------------------------------------------------------------
14 # Imports
15 #-----------------------------------------------------------------------------
16 from __future__ import print_function
9 from __future__ import print_function
17
10
18 import sys
11 import sys
19 import warnings
20
12
21 from IPython.utils import io
13 from IPython.utils import io
22
14
23 #-----------------------------------------------------------------------------
24 # Code
25 #-----------------------------------------------------------------------------
26
15
27 def warn(msg,level=2,exit_val=1):
16 def warn(msg,level=2,exit_val=1):
28 """Standard warning printer. Gives formatting consistency.
17 """Standard warning printer. Gives formatting consistency.
29
18
30 Output is sent to io.stderr (sys.stderr by default).
19 Output is sent to io.stderr (sys.stderr by default).
31
20
32 Options:
21 Options:
33
22
34 -level(2): allows finer control:
23 -level(2): allows finer control:
35 0 -> Do nothing, dummy function.
24 0 -> Do nothing, dummy function.
36 1 -> Print message.
25 1 -> Print message.
37 2 -> Print 'WARNING:' + message. (Default level).
26 2 -> Print 'WARNING:' + message. (Default level).
38 3 -> Print 'ERROR:' + message.
27 3 -> Print 'ERROR:' + message.
39 4 -> Print 'FATAL ERROR:' + message and trigger a sys.exit(exit_val).
28 4 -> Print 'FATAL ERROR:' + message and trigger a sys.exit(exit_val).
40
29
41 -exit_val (1): exit value returned by sys.exit() for a level 4
30 -exit_val (1): exit value returned by sys.exit() for a level 4
42 warning. Ignored for all other levels."""
31 warning. Ignored for all other levels."""
43
32
44 if level>0:
33 if level>0:
45 header = ['','','WARNING: ','ERROR: ','FATAL ERROR: ']
34 header = ['','','WARNING: ','ERROR: ','FATAL ERROR: ']
46 print(header[level], msg, sep='', file=io.stderr)
35 print(header[level], msg, sep='', file=io.stderr)
47 if level == 4:
36 if level == 4:
48 print('Exiting.\n', file=io.stderr)
37 print('Exiting.\n', file=io.stderr)
49 sys.exit(exit_val)
38 sys.exit(exit_val)
50
39
51
40
52 def info(msg):
41 def info(msg):
53 """Equivalent to warn(msg,level=1)."""
42 """Equivalent to warn(msg,level=1)."""
54
43
55 warn(msg,level=1)
44 warn(msg,level=1)
56
45
57
46
58 def error(msg):
47 def error(msg):
59 """Equivalent to warn(msg,level=3)."""
48 """Equivalent to warn(msg,level=3)."""
60
49
61 warn(msg,level=3)
50 warn(msg,level=3)
62
51
63
52
64 def fatal(msg,exit_val=1):
53 def fatal(msg,exit_val=1):
65 """Equivalent to warn(msg,exit_val=exit_val,level=4)."""
54 """Equivalent to warn(msg,exit_val=exit_val,level=4)."""
66
55
67 warn(msg,exit_val=exit_val,level=4)
56 warn(msg,exit_val=exit_val,level=4)
68
57
69
70 def DeprecatedClass(base, class_name):
71 # Hook the init method of the base class.
72 def init_hook(self, *pargs, **kwargs):
73 base.__init__(self, *pargs, **kwargs)
74
75 # Warn once per class.
76 if base not in DeprecatedClass._warned_classes:
77 DeprecatedClass._warned_classes.append(base)
78 warn('"{}" is deprecated, please use "{}" instead.'.format(
79 class_name, base.__name__))
80 return type(class_name, (base,), {'__init__': init_hook})
81 DeprecatedClass._warned_classes = []
General Comments 0
You need to be logged in to leave comments. Login now