diff --git a/IPython/html/widgets/widget.py b/IPython/html/widgets/widget.py index 88b203e..a9618cc 100644 --- a/IPython/html/widgets/widget.py +++ b/IPython/html/widgets/widget.py @@ -93,6 +93,7 @@ class Widget(LoggingConfigurable): self._children = [] self._add_class = [0] self._remove_class = [0] + self._display_callbacks = [] super(Widget, self).__init__(**kwargs) # Register after init to allow default values to be specified @@ -278,6 +279,49 @@ class Widget(LoggingConfigurable): self.send_state(key='_remove_class') + def on_displayed(self, callback, remove=False): + """Register a callback to be called when the widget has been displayed + + callback: method handler + Can have a signature of: + - callback() + - callback(sender) + - callback(sender, view_name) + remove: bool + True if the callback should be unregistered.""" + if remove: + self._display_callbacks.remove(callback) + elif not callback in self._display_callbacks: + self._display_callbacks.append(callback) + + + def handle_displayed(self, view_name): + """Called when a view has been displayed for this widget instance + + view_name: unicode + Name of the view that was displayed.""" + for handler in self._display_callbacks: + if callable(handler): + argspec = inspect.getargspec(handler) + nargs = len(argspec[0]) + + # Bound methods have an additional 'self' argument + if isinstance(handler, types.MethodType): + nargs -= 1 + + # Call the callback + if nargs == 0: + handler() + elif nargs == 1: + handler(self) + elif nargs == 2: + handler(self, view_name) + else: + raise TypeError('Widget display callback must ' \ + 'accept 0-2 arguments, not %d.' % nargs) + + + # Support methods def _repr_widget_(self, view_name=None): """Function that is called when `IPython.display.display` is called on @@ -308,6 +352,7 @@ class Widget(LoggingConfigurable): "view_name": view_name, "parent": self.parent._comm.comm_id}) self._displayed = True + self.handle_displayed(view_name) # Now display children if any. for child in self._children: