diff --git a/IPython/html/widgets/widget.py b/IPython/html/widgets/widget.py index a822ffc..e2aa808 100644 --- a/IPython/html/widgets/widget.py +++ b/IPython/html/widgets/widget.py @@ -1,3 +1,17 @@ +"""Base Widget class. Allows user to create widgets in the backend that render +in the IPython notebook frontend. +""" +#----------------------------------------------------------------------------- +# Copyright (c) 2013, the IPython Development Team. +# +# Distributed under the terms of the Modified BSD License. +# +# The full license is in the file COPYING.txt, distributed with this software. +#----------------------------------------------------------------------------- + +#----------------------------------------------------------------------------- +# Imports +#----------------------------------------------------------------------------- from copy import copy from glob import glob import uuid @@ -11,6 +25,9 @@ from IPython.utils.traitlets import Unicode, Dict, List from IPython.display import Javascript, display from IPython.utils.py3compat import string_types +#----------------------------------------------------------------------------- +# Shared +#----------------------------------------------------------------------------- def init_widget_js(): path = os.path.split(os.path.abspath( __file__ ))[0] for filepath in glob(os.path.join(path, "*.py")): @@ -22,14 +39,19 @@ def init_widget_js(): display(Javascript(data='$.getScript("%s");' % js_path)) +#----------------------------------------------------------------------------- +# Classes +#----------------------------------------------------------------------------- class Widget(LoggingConfigurable): - ### Public declarations - target_name = Unicode('widget') - default_view_name = Unicode() + # Public declarations + target_name = Unicode('widget', help="""Name of the backbone model + registered in the frontend to create and sync this widget with.""") + default_view_name = Unicode(help="""Default view registered in the frontend + to use to represent the widget.""") - ### Private/protected declarations + # Private/protected declarations _keys = [] _property_lock = False _parent = None @@ -37,10 +59,22 @@ class Widget(LoggingConfigurable): _css = Dict() - ### Public constructor def __init__(self, parent=None, **kwargs): + """Public constructor + + Parameters + ---------- + parent : Widget instance (optional) + Widget that this widget instance is child of. When the widget is + displayed in the frontend, it's corresponding view will be made + child of the parent's view if the parent's view exists already. If + the parent's view is displayed, it will automatically display this + widget's default view as it's child. The default view can be set + via the default_view_name property. + """ super(Widget, self).__init__(**kwargs) + # Parent/child association self._children = [] if parent is not None: parent._children.append(self) @@ -52,14 +86,19 @@ class Widget(LoggingConfigurable): def __del__(self): + """Object disposal""" self.close() + def close(self): + """Close method. Closes the widget which closes the underlying comm. + When the comm is closed, all of the widget views are automatically + removed from the frontend.""" self.comm.close() del self.comm - ### Properties + # Properties def _get_parent(self): return self._parent parent = property(_get_parent) @@ -76,26 +115,10 @@ class Widget(LoggingConfigurable): return keys keys = property(_get_keys) - def _get_css(self, key, selector=""): - if selector in self._css and key in self._css[selector]: - return self._css[selector][key] - else: - return None - def _set_css(self, value, key, selector=""): - if selector not in self._css: - self._css[selector] = {} - - # Only update the property if it has changed. - if not (key in self._css[selector] and value in self._css[selector][key]): - self._css[selector][key] = value - self.send_state() # Send new state to client. - - css = property(_get_css, _set_css) - - ### Event handlers + # Event handlers def _handle_msg(self, msg): - + """Called when a msg is recieved from the frontend""" # Handle backbone sync methods CREATE, PATCH, and UPDATE sync_method = msg['content']['data']['sync_method'] sync_data = msg['content']['data']['sync_data'] @@ -103,6 +126,7 @@ class Widget(LoggingConfigurable): def _handle_recieve_state(self, sync_data): + """Called when a state is recieved from the frontend.""" self._property_lock = True try: @@ -115,6 +139,7 @@ class Widget(LoggingConfigurable): def _handle_property_changed(self, name, old, new): + """Called when a proeprty has been changed.""" if not self._property_lock and self.comm is not None: # TODO: Validate properties. # Send new state to frontend @@ -122,11 +147,84 @@ class Widget(LoggingConfigurable): def _handle_close(self): + """Called when the comm is closed by the frontend.""" self.comm = None - ### Public methods + # Public methods + def send_state(self, key=None): + """Sends the widget state, or a piece of it, to the frontend. + + Parameters + ---------- + key : unicode (optional) + A single property's name to sync with the frontend. + """ + state = {} + + # If a key is provided, just send the state of that key. + keys = [] + if key is None: + keys.extend(self.keys) + else: + keys.append(key) + for key in self.keys: + try: + state[key] = getattr(self, key) + except Exception as e: + pass # Eat errors, nom nom nom + self.comm.send({"method": "update", + "state": state}) + + + def get_css(self, key, selector=""): + """Get a CSS property of the widget views (shared among all of the + views) + + Parameters + ---------- + key: unicode + CSS key + selector: unicode (optional) + JQuery selector used when the CSS key/value was set. + """ + if selector in self._css and key in self._css[selector]: + return self._css[selector][key] + else: + return None + + + def set_css(self, key, value, selector=""): + """Set a CSS property of the widget views (shared among all of the + views) + + Parameters + ---------- + key: unicode + CSS key + value + CSS value + selector: unicode (optional) + JQuery selector to use to apply the CSS key/value. + """ + if selector not in self._css: + self._css[selector] = {} + + # Only update the property if it has changed. + if not (key in self._css[selector] and value in self._css[selector][key]): + self._css[selector][key] = value + self.send_state() # Send new state to client. + + + # Support methods def _repr_widget_(self, view_name=None): + """Function that is called when `IPython.display.display` is called on + the widget. + + Parameters + ---------- + view_name: unicode (optional) + View to display in the frontend. Overrides default_view_name.""" if not view_name: view_name = self.default_view_name @@ -151,21 +249,3 @@ class Widget(LoggingConfigurable): for child in self.children: child._repr_widget_() return None - - - def send_state(self, key=None): - state = {} - - # If a key is provided, just send the state of that key. - keys = [] - if key is None: - keys.extend(self.keys) - else: - keys.append(key) - for key in self.keys: - try: - state[key] = getattr(self, key) - except Exception as e: - pass # Eat errors, nom nom nom - self.comm.send({"method": "update", - "state": state}) diff --git a/IPython/html/widgets/widget_bool.py b/IPython/html/widgets/widget_bool.py index a9a0f2e..699dfaf 100644 --- a/IPython/html/widgets/widget_bool.py +++ b/IPython/html/widgets/widget_bool.py @@ -1,12 +1,31 @@ +"""BoolWidget class. + +Represents a boolean using a widget. +""" +#----------------------------------------------------------------------------- +# Copyright (c) 2013, the IPython Development Team. +# +# Distributed under the terms of the Modified BSD License. +# +# The full license is in the file COPYING.txt, distributed with this software. +#----------------------------------------------------------------------------- + +#----------------------------------------------------------------------------- +# Imports +#----------------------------------------------------------------------------- from widget import Widget from IPython.utils.traitlets import Unicode, Bool, List +#----------------------------------------------------------------------------- +# Classes +#----------------------------------------------------------------------------- class BoolWidget(Widget): target_name = Unicode('BoolWidgetModel') default_view_name = Unicode('CheckboxView') + + # Model Keys _keys = ['value', 'description', 'disabled'] - - value = Bool(False) - description = Unicode('') # Description of the boolean (label). - disabled = Bool(False) # Enable or disable user changes + value = Bool(False, help="Bool value") + description = Unicode('', help="Description of the boolean (label).") + disabled = Bool(False, help="Enable or disable user changes.") \ No newline at end of file diff --git a/IPython/html/widgets/widget_button.py b/IPython/html/widgets/widget_button.py index 749cb5a..14de721 100644 --- a/IPython/html/widgets/widget_button.py +++ b/IPython/html/widgets/widget_button.py @@ -1,22 +1,48 @@ +"""ButtonWidget class. + +Represents a button in the frontend using a widget. Allows user to listen for +click events on the button and trigger backend code when the clicks are fired. +""" +#----------------------------------------------------------------------------- +# Copyright (c) 2013, the IPython Development Team. +# +# Distributed under the terms of the Modified BSD License. +# +# The full license is in the file COPYING.txt, distributed with this software. +#----------------------------------------------------------------------------- + +#----------------------------------------------------------------------------- +# Imports +#----------------------------------------------------------------------------- import inspect import types from widget import Widget from IPython.utils.traitlets import Unicode, Bool, Int +#----------------------------------------------------------------------------- +# Classes +#----------------------------------------------------------------------------- class ButtonWidget(Widget): target_name = Unicode('ButtonWidgetModel') default_view_name = Unicode('ButtonView') + + # Keys _keys = ['clicks', 'description', 'disabled'] - - clicks = Int(0) - description = Unicode('') # Description of the button (label). - disabled = Bool(False) # Enable or disable user changes + clicks = Int(0, help="Number of times the button has been clicked.") + description = Unicode('', help="Description of the button (label).") + disabled = Bool(False, help="Enable or disable user changes.") _click_handlers = [] def on_click(self, callback, remove=False): + """Register a callback to execute when the button is clicked. + + Parameters + ---------- + remove : bool (optional) + Set to tru to remove the callback from the list of callbacks.""" if remove: self._click_handlers.remove(callback) else: @@ -24,6 +50,8 @@ class ButtonWidget(Widget): def _clicks_changed(self, name, old, new): + """Handles when the clicks property has been changed. Fires on_click + callbacks when appropriate.""" if new > old: for handler in self._click_handlers: if callable(handler): @@ -42,4 +70,3 @@ class ButtonWidget(Widget): else: raise TypeError('ButtonWidget click callback must ' \ 'accept 0 or 1 arguments.') - diff --git a/IPython/html/widgets/widget_container.py b/IPython/html/widgets/widget_container.py index 4ca7bce..8bacbb6 100644 --- a/IPython/html/widgets/widget_container.py +++ b/IPython/html/widgets/widget_container.py @@ -1,12 +1,31 @@ +"""ContainerWidget class. + +Represents a container that can be used to group other widgets. +""" +#----------------------------------------------------------------------------- +# Copyright (c) 2013, the IPython Development Team. +# +# Distributed under the terms of the Modified BSD License. +# +# The full license is in the file COPYING.txt, distributed with this software. +#----------------------------------------------------------------------------- + +#----------------------------------------------------------------------------- +# Imports +#----------------------------------------------------------------------------- from widget import Widget from IPython.utils.traitlets import Unicode, Bool +#----------------------------------------------------------------------------- +# Classes +#----------------------------------------------------------------------------- class ContainerWidget(Widget): target_name = Unicode('ContainerWidgetModel') default_view_name = Unicode('ContainerView') - _keys = ['_vbox', '_hbox', '_start', '_end', '_center'] - _trait_changing = False + # Keys, all private and managed by helper methods. Flexible box model + # classes... + _keys = ['_vbox', '_hbox', '_start', '_end', '_center'] _hbox = Bool(False) _vbox = Bool(False) _start = Bool(False) @@ -14,28 +33,68 @@ class ContainerWidget(Widget): _center = Bool(False) def hbox(self, enabled=True): + """Make this container an hbox. Automatically disables conflicting + features. + + Parameters + ---------- + enabled: bool (optional) + Enabled or disable the hbox feature of the container, defaults to + True.""" self._hbox = enabled if enabled: self._vbox = False def vbox(self, enabled=True): + """Make this container an vbox. Automatically disables conflicting + features. + + Parameters + ---------- + enabled: bool (optional) + Enabled or disable the vbox feature of the container, defaults to + True.""" self._vbox = enabled if enabled: self._hbox = False def start(self, enabled=True): + """Make the contents of this container align to the start of the axis. + Automatically disables conflicting alignments. + + Parameters + ---------- + enabled: bool (optional) + Enabled or disable the start alignment of the container, defaults to + True.""" self._start = enabled if enabled: self._end = False self._center = False def end(self, enabled=True): + """Make the contents of this container align to the end of the axis. + Automatically disables conflicting alignments. + + Parameters + ---------- + enabled: bool (optional) + Enabled or disable the end alignment of the container, defaults to + True.""" self._end = enabled if enabled: self._start = False self._center = False def center(self, enabled=True): + """Make the contents of this container align to the center of the axis. + Automatically disables conflicting alignments. + + Parameters + ---------- + enabled: bool (optional) + Enabled or disable the center alignment of the container, defaults to + True.""" self._center = enabled if enabled: self._start = False diff --git a/IPython/html/widgets/widget_float.py b/IPython/html/widgets/widget_float.py index 01b0a39..25619d1 100644 --- a/IPython/html/widgets/widget_float.py +++ b/IPython/html/widgets/widget_float.py @@ -1,10 +1,29 @@ +"""FloatWidget class. + +Represents an unbounded float using a widget. +""" +#----------------------------------------------------------------------------- +# Copyright (c) 2013, the IPython Development Team. +# +# Distributed under the terms of the Modified BSD License. +# +# The full license is in the file COPYING.txt, distributed with this software. +#----------------------------------------------------------------------------- + +#----------------------------------------------------------------------------- +# Imports +#----------------------------------------------------------------------------- from widget import Widget from IPython.utils.traitlets import Unicode, Float, Bool, List +#----------------------------------------------------------------------------- +# Classes +#----------------------------------------------------------------------------- class FloatWidget(Widget): target_name = Unicode('FloatWidgetModel') default_view_name = Unicode('FloatTextView') + + # Keys _keys = ['value', 'disabled'] - - value = Float(0.0) - disabled = Bool(False) # Enable or disable user changes + value = Float(0.0, help="Float value") + disabled = Bool(False, help="Enable or disable user changes") diff --git a/IPython/html/widgets/widget_float_range.py b/IPython/html/widgets/widget_float_range.py index df904ca..afb8fea 100644 --- a/IPython/html/widgets/widget_float_range.py +++ b/IPython/html/widgets/widget_float_range.py @@ -1,14 +1,33 @@ +"""FloatRangeWidget class. + +Represents a bounded float using a widget. +""" +#----------------------------------------------------------------------------- +# Copyright (c) 2013, the IPython Development Team. +# +# Distributed under the terms of the Modified BSD License. +# +# The full license is in the file COPYING.txt, distributed with this software. +#----------------------------------------------------------------------------- + +#----------------------------------------------------------------------------- +# Imports +#----------------------------------------------------------------------------- from widget import Widget from IPython.utils.traitlets import Unicode, Float, Bool, List +#----------------------------------------------------------------------------- +# Classes +#----------------------------------------------------------------------------- class FloatRangeWidget(Widget): target_name = Unicode('FloatRangeWidgetModel') default_view_name = Unicode('FloatSliderView') + + # Keys _keys = ['value', 'step', 'max', 'min', 'disabled', 'orientation'] - - value = Float(0.0) - max = Float(100.0) # Max value - min = Float(0.0) # Min value - disabled = Bool(False) # Enable or disable user changes - step = Float(0.1) # Minimum step that the value can take (ignored by some views) - orientation = Unicode(u'horizontal') # Vertical or horizontal (ignored by some views) + value = Float(0.0, help="Flaot value") + max = Float(100.0, help="Max value") + min = Float(0.0, help="Min value") + disabled = Bool(False, help="Enable or disable user changes") + step = Float(0.1, help="Minimum step that the value can take (ignored by some views)") + orientation = Unicode(u'horizontal', help="Vertical or horizontal (ignored by some views)") diff --git a/IPython/html/widgets/widget_int.py b/IPython/html/widgets/widget_int.py index 10aab8a..f2ba468 100644 --- a/IPython/html/widgets/widget_int.py +++ b/IPython/html/widgets/widget_int.py @@ -1,10 +1,29 @@ +"""IntWidget class. + +Represents an unbounded int using a widget. +""" +#----------------------------------------------------------------------------- +# Copyright (c) 2013, the IPython Development Team. +# +# Distributed under the terms of the Modified BSD License. +# +# The full license is in the file COPYING.txt, distributed with this software. +#----------------------------------------------------------------------------- + +#----------------------------------------------------------------------------- +# Imports +#----------------------------------------------------------------------------- from widget import Widget from IPython.utils.traitlets import Unicode, Int, Bool, List +#----------------------------------------------------------------------------- +# Classes +#----------------------------------------------------------------------------- class IntWidget(Widget): target_name = Unicode('IntWidgetModel') default_view_name = Unicode('IntTextView') - _keys = ['value', 'disabled'] - value = Int(0) - disabled = Bool(False) # Enable or disable user changes + # Keys + _keys = ['value', 'disabled'] + value = Int(0, help="Int value") + disabled = Bool(False, help="Enable or disable user changes") diff --git a/IPython/html/widgets/widget_int_range.py b/IPython/html/widgets/widget_int_range.py index 912567b..96557d9 100644 --- a/IPython/html/widgets/widget_int_range.py +++ b/IPython/html/widgets/widget_int_range.py @@ -1,14 +1,33 @@ +"""IntRangeWidget class. + +Represents a bounded int using a widget. +""" +#----------------------------------------------------------------------------- +# Copyright (c) 2013, the IPython Development Team. +# +# Distributed under the terms of the Modified BSD License. +# +# The full license is in the file COPYING.txt, distributed with this software. +#----------------------------------------------------------------------------- + +#----------------------------------------------------------------------------- +# Imports +#----------------------------------------------------------------------------- from widget import Widget from IPython.utils.traitlets import Unicode, Int, Bool, List +#----------------------------------------------------------------------------- +# Classes +#----------------------------------------------------------------------------- class IntRangeWidget(Widget): target_name = Unicode('IntRangeWidgetModel') default_view_name = Unicode('IntSliderView') - _keys = ['value', 'step', 'max', 'min', 'disabled', 'orientation'] - value = Int(0) - max = Int(100) # Max value - min = Int(0) # Min value - disabled = Bool(False) # Enable or disable user changes - step = Int(1) # Minimum step that the value can take (ignored by some views) - orientation = Unicode(u'horizontal') # Vertical or horizontal (ignored by some views) + # Keys + _keys = ['value', 'step', 'max', 'min', 'disabled', 'orientation'] + value = Int(0, help="Int value") + max = Int(100, help="Max value") + min = Int(0, help="Min value") + disabled = Bool(False, help="Enable or disable user changes") + step = Int(1, help="Minimum step that the value can take (ignored by some views)") + orientation = Unicode(u'horizontal', help="Vertical or horizontal (ignored by some views)") diff --git a/IPython/html/widgets/widget_selection.py b/IPython/html/widgets/widget_selection.py index 72e2553..b2210cf 100644 --- a/IPython/html/widgets/widget_selection.py +++ b/IPython/html/widgets/widget_selection.py @@ -1,12 +1,31 @@ +"""SelectionWidget class. + +Represents an enumeration using a widget. +""" +#----------------------------------------------------------------------------- +# Copyright (c) 2013, the IPython Development Team. +# +# Distributed under the terms of the Modified BSD License. +# +# The full license is in the file COPYING.txt, distributed with this software. +#----------------------------------------------------------------------------- + +#----------------------------------------------------------------------------- +# Imports +#----------------------------------------------------------------------------- from widget import Widget from IPython.utils.traitlets import Unicode, List, Bool +#----------------------------------------------------------------------------- +# SelectionWidget +#----------------------------------------------------------------------------- class SelectionWidget(Widget): target_name = Unicode('SelectionWidgetModel') default_view_name = Unicode('DropdownView') - _keys = ['value', 'values', 'disabled'] - value = Unicode() - values = List() # List of values the user can select - disabled = Bool(False) # Enable or disable user changes + # Keys + _keys = ['value', 'values', 'disabled'] + value = Unicode(help="Selected value") + values = List(help="List of values the user can select") + disabled = Bool(False, help="Enable or disable user changes") \ No newline at end of file diff --git a/IPython/html/widgets/widget_string.py b/IPython/html/widgets/widget_string.py index 96aa7a2..146da5f 100644 --- a/IPython/html/widgets/widget_string.py +++ b/IPython/html/widgets/widget_string.py @@ -1,11 +1,29 @@ +"""StringWidget class. + +Represents a unicode string using a widget. +""" +#----------------------------------------------------------------------------- +# Copyright (c) 2013, the IPython Development Team. +# +# Distributed under the terms of the Modified BSD License. +# +# The full license is in the file COPYING.txt, distributed with this software. +#----------------------------------------------------------------------------- + +#----------------------------------------------------------------------------- +# Imports +#----------------------------------------------------------------------------- from widget import Widget from IPython.utils.traitlets import Unicode, Bool, List +#----------------------------------------------------------------------------- +# Classes +#----------------------------------------------------------------------------- class StringWidget(Widget): target_name = Unicode('StringWidgetModel') default_view_name = Unicode('TextboxView') + + # Keys _keys = ['value', 'disabled'] - - value = Unicode() - disabled = Bool(False) # Enable or disable user changes - \ No newline at end of file + value = Unicode(help="String value") + disabled = Bool(False, help="Enable or disable user changes")