Show More
@@ -31,6 +31,7 b' var IPython = (function (IPython) {' | |||
|
31 | 31 | }; |
|
32 | 32 | |
|
33 | 33 | WidgetManager.prototype.init_kernel = function (kernel) { |
|
34 | // connect the kernel, and register message handlers | |
|
34 | 35 | this.kernel = kernel; |
|
35 | 36 | var msg_types = ['widget_create', 'widget_destroy', 'widget_update']; |
|
36 | 37 | for (var i = 0; i < msg_types.length; i++) { |
@@ -44,6 +45,20 b' var IPython = (function (IPython) {' | |||
|
44 | 45 | this.widget_types[widget_type] = constructor; |
|
45 | 46 | }; |
|
46 | 47 | |
|
48 | WidgetManager.prototype.register_widget = function (widget) { | |
|
49 | // Register a widget in the mapping | |
|
50 | this.widgets[widget.widget_id] = widget; | |
|
51 | widget.kernel = this.kernel; | |
|
52 | return widget.widget_id; | |
|
53 | }; | |
|
54 | ||
|
55 | WidgetManager.prototype.unregister_widget = function (widget_id) { | |
|
56 | // Remove a widget from the mapping | |
|
57 | delete this.widgets[widget_id]; | |
|
58 | }; | |
|
59 | ||
|
60 | // widget message handlers | |
|
61 | ||
|
47 | 62 | WidgetManager.prototype.widget_create = function (msg) { |
|
48 | 63 | var content = msg.content; |
|
49 | 64 | var constructor = this.widget_types[content.widget_type]; |
@@ -52,7 +67,10 b' var IPython = (function (IPython) {' | |||
|
52 | 67 | console.log("Available widget types are: ", this.widget_types); |
|
53 | 68 | return; |
|
54 | 69 | } |
|
55 |
var widget = new constructor( |
|
|
70 | var widget = new constructor(content.widget_id); | |
|
71 | this.register_widget(widget); | |
|
72 | widget.handle_create(content.data); | |
|
73 | ||
|
56 | 74 | this.widgets[content.widget_id] = widget; |
|
57 | 75 | }; |
|
58 | 76 | |
@@ -79,39 +97,48 b' var IPython = (function (IPython) {' | |||
|
79 | 97 | // Widget base class |
|
80 | 98 | //----------------------------------------------------------------------- |
|
81 | 99 | |
|
82 |
var Widget = function ( |
|
|
83 | this.kernel = kernel; | |
|
84 | if (!content) return; | |
|
85 | this.widget_id = content.widget_id; | |
|
86 | this.handle_create(content.data); | |
|
87 | }; | |
|
88 | ||
|
89 | Widget.prototype.handle_create = function (data) { | |
|
100 | var Widget = function (widget_id) { | |
|
101 | this.widget_id = widget_id; | |
|
102 | this.widget_type = 'widget'; | |
|
90 | 103 | }; |
|
91 | 104 | |
|
92 | Widget.prototype.handle_update = function (data) { | |
|
93 | }; | |
|
94 | ||
|
95 | Widget.prototype.handle_destroy = function (data) { | |
|
105 | // methods for sending messages | |
|
106 | Widget.prototype.create = function (data) { | |
|
107 | var content = { | |
|
108 | widget_id : this.widget_id, | |
|
109 | widget_type : this.widget_type, | |
|
110 | data : data || {}, | |
|
111 | }; | |
|
112 | this.kernel.send_shell_message("widget_create", content); | |
|
96 | 113 | }; |
|
97 | 114 | |
|
98 | 115 | Widget.prototype.update = function (data) { |
|
99 | 116 | var content = { |
|
100 | 117 | widget_id : this.widget_id, |
|
101 | data : data, | |
|
118 | data : data || {}, | |
|
102 | 119 | }; |
|
103 | 120 | this.kernel.send_shell_message("widget_update", content); |
|
104 | 121 | }; |
|
105 | 122 | |
|
106 | ||
|
107 | 123 | Widget.prototype.destroy = function (data) { |
|
108 | 124 | var content = { |
|
109 | 125 | widget_id : this.widget_id, |
|
110 | data : data, | |
|
126 | data : data || {}, | |
|
111 | 127 | }; |
|
112 | 128 | this.kernel.send_shell_message("widget_destroy", content); |
|
113 | 129 | }; |
|
114 | 130 | |
|
131 | // methods for handling incoming messages | |
|
132 | ||
|
133 | Widget.prototype.handle_create = function (data) { | |
|
134 | }; | |
|
135 | ||
|
136 | Widget.prototype.handle_update = function (data) { | |
|
137 | }; | |
|
138 | ||
|
139 | Widget.prototype.handle_destroy = function (data) { | |
|
140 | }; | |
|
141 | ||
|
115 | 142 | IPython.WidgetManager = WidgetManager; |
|
116 | 143 | IPython.Widget = Widget; |
|
117 | 144 |
@@ -11,11 +11,11 b'' | |||
|
11 | 11 | # Imports |
|
12 | 12 | #----------------------------------------------------------------------------- |
|
13 | 13 | |
|
14 | from weakref import ref | |
|
15 | ||
|
16 | 14 | from IPython.config import LoggingConfigurable |
|
17 | 15 | from IPython.core.prompts import LazyEvaluate |
|
18 | 16 | from IPython.core.getipython import get_ipython |
|
17 | ||
|
18 | from IPython.utils.importstring import import_item | |
|
19 | 19 | from IPython.utils.traitlets import Instance, Unicode, Dict, Any |
|
20 | 20 | |
|
21 | 21 | #----------------------------------------------------------------------------- |
@@ -30,6 +30,7 b' def lazy_keys(dikt):' | |||
|
30 | 30 | """ |
|
31 | 31 | return LazyEvaluate(lambda d: list(d.keys())) |
|
32 | 32 | |
|
33 | ||
|
33 | 34 | class WidgetManager(LoggingConfigurable): |
|
34 | 35 | """Manager for Widgets in the Kernel""" |
|
35 | 36 | |
@@ -46,25 +47,32 b' class WidgetManager(LoggingConfigurable):' | |||
|
46 | 47 | return self.shell.parent.session |
|
47 | 48 | |
|
48 | 49 | widgets = Dict() |
|
50 | widget_types = Dict() | |
|
49 | 51 | |
|
50 | 52 | # Public APIs |
|
51 | 53 | |
|
54 | def register_widget_type(self, widget_type, constructor): | |
|
55 | """Register a constructor for a given widget_type | |
|
56 | ||
|
57 | constructor can be a Widget class or an importstring for a Widget class. | |
|
58 | """ | |
|
59 | if isinstance(constructor, basestring): | |
|
60 | constructor = import_item(constructor) | |
|
61 | ||
|
62 | self.widget_types[widget_type] = constructor | |
|
63 | ||
|
52 | 64 | def register_widget(self, widget): |
|
53 | 65 | """Register a new widget""" |
|
54 |
|
|
|
66 | widget_id = widget.widget_id | |
|
55 | 67 | widget.shell = self.shell |
|
56 | 68 | widget.iopub_socket = self.iopub_socket |
|
57 | widget.create() | |
|
58 |
return |
|
|
69 | self.widgets[widget_id] = widget | |
|
70 | return widget_id | |
|
59 | 71 | |
|
60 | 72 | def unregister_widget(self, widget_id): |
|
61 | 73 | """Unregister a widget, and destroy its counterpart""" |
|
62 | 74 | # unlike get_widget, this should raise a KeyError |
|
63 |
widget |
|
|
64 | widget = widget_ref() | |
|
65 | if widget is None: | |
|
66 | # already destroyed, nothing to do | |
|
67 | return | |
|
75 | widget = self.widgets.pop(widget_id) | |
|
68 | 76 | widget.destroy() |
|
69 | 77 | |
|
70 | 78 | def get_widget(self, widget_id): |
@@ -80,16 +88,27 b' class WidgetManager(LoggingConfigurable):' | |||
|
80 | 88 | self.log.debug("Current widgets: %s", lazy_keys(self.widgets)) |
|
81 | 89 | return |
|
82 | 90 | # call, because we store weakrefs |
|
83 |
widget = self.widgets[widget_id] |
|
|
84 | if widget is None: | |
|
85 | self.log.error("Widget %s has been removed", widget_id) | |
|
86 | del self.widgets[widget_id] | |
|
87 | self.log.debug("Current widgets: %s", lazy_keys(self.widgets)) | |
|
88 | return | |
|
91 | widget = self.widgets[widget_id] | |
|
89 | 92 | return widget |
|
90 | 93 | |
|
91 | 94 | # Message handlers |
|
92 | 95 | |
|
96 | def widget_create(self, stream, ident, msg): | |
|
97 | """Handler for widget_update messages""" | |
|
98 | content = msg['content'] | |
|
99 | widget_id = content['widget_id'] | |
|
100 | widget_type = content['widget_type'] | |
|
101 | constructor = self.widget_types.get(widget_type, None) | |
|
102 | if constructor is None: | |
|
103 | self.log.error("No such widget_type registered: %s", widget_type) | |
|
104 | return | |
|
105 | widget = constructor(widget_id=widget_id, | |
|
106 | shell=self.shell, | |
|
107 | iopub_socket=self.iopub_socket, | |
|
108 | _create_data=content['data'], | |
|
109 | ) | |
|
110 | self.register_widget(widget) | |
|
111 | ||
|
93 | 112 | def widget_update(self, stream, ident, msg): |
|
94 | 113 | """Handler for widget_update messages""" |
|
95 | 114 | content = msg['content'] |
@@ -110,6 +129,6 b' class WidgetManager(LoggingConfigurable):' | |||
|
110 | 129 | return |
|
111 | 130 | widget.handle_destroy(content['data']) |
|
112 | 131 | del self.widgets[widget_id] |
|
113 | ||
|
132 | ||
|
114 | 133 | |
|
115 | 134 | __all__ = ['WidgetManager'] |
@@ -13,6 +13,7 b'' | |||
|
13 | 13 | |
|
14 | 14 | import uuid |
|
15 | 15 | |
|
16 | from IPython.core.getipython import get_ipython | |
|
16 | 17 | from IPython.config import LoggingConfigurable |
|
17 | 18 | from IPython.utils.traitlets import Instance, Unicode, Bytes, Bool, Dict, Any |
|
18 | 19 | |
@@ -47,6 +48,18 b' class Widget(LoggingConfigurable):' | |||
|
47 | 48 | def _widget_id_default(self): |
|
48 | 49 | return uuid.uuid4().hex |
|
49 | 50 | |
|
51 | primary = Bool(False, help="Am I the primary or secondary Widget?") | |
|
52 | ||
|
53 | def __init__(self, **kwargs): | |
|
54 | super(Widget, self).__init__(**kwargs) | |
|
55 | get_ipython().widget_manager.register_widget(self) | |
|
56 | if self.primary: | |
|
57 | # I am primary, create my peer | |
|
58 | self.create() | |
|
59 | else: | |
|
60 | # I am secondary, handle creation | |
|
61 | self.handle_create(self._create_data) | |
|
62 | ||
|
50 | 63 | def _publish_msg(self, msg_type, data=None, **keys): |
|
51 | 64 | """Helper for sending a widget message on IOPub""" |
|
52 | 65 | data = {} if data is None else data |
@@ -61,16 +74,20 b' class Widget(LoggingConfigurable):' | |||
|
61 | 74 | |
|
62 | 75 | # publishing messages |
|
63 | 76 | |
|
64 | def create(self): | |
|
77 | def create(self, data=None): | |
|
65 | 78 | """Create the frontend-side version of this widget""" |
|
66 | self._publish_msg('widget_create', self._create_data, widget_type = self.widget_type) | |
|
79 | if data is None: | |
|
80 | data = self._create_data | |
|
81 | self._publish_msg('widget_create', data, widget_type=self.widget_type) | |
|
67 | 82 | |
|
68 | def destroy(self): | |
|
83 | def destroy(self, data=None): | |
|
69 | 84 | """Destroy the frontend-side version of this widget""" |
|
70 | 85 | if self._destroyed: |
|
71 | 86 | # only destroy once |
|
72 | 87 | return |
|
73 | self._publish_msg('widget_destroy', self._destroy_data) | |
|
88 | if data is None: | |
|
89 | data = self._destroy_data | |
|
90 | self._publish_msg('widget_destroy', data) | |
|
74 | 91 | self._destroyed = True |
|
75 | 92 | |
|
76 | 93 | def update(self, data=None): |
@@ -79,6 +96,10 b' class Widget(LoggingConfigurable):' | |||
|
79 | 96 | |
|
80 | 97 | # handling of incoming messages |
|
81 | 98 | |
|
99 | def handle_create(self, data): | |
|
100 | """Handle a widget_create message""" | |
|
101 | self.log.debug("handle_create %s", data) | |
|
102 | ||
|
82 | 103 | def handle_destroy(self, data): |
|
83 | 104 | """Handle a widget_destroy message""" |
|
84 | 105 | self.log.debug("handle_destroy %s", data) |
@@ -168,7 +168,7 b' class Kernel(Configurable):' | |||
|
168 | 168 | for msg_type in msg_types: |
|
169 | 169 | self.shell_handlers[msg_type] = getattr(self, msg_type) |
|
170 | 170 | |
|
171 | widget_msg_types = [ 'widget_update', 'widget_destroy' ] | |
|
171 | widget_msg_types = [ 'widget_create', 'widget_update', 'widget_destroy' ] | |
|
172 | 172 | widget_manager = self.shell.widget_manager |
|
173 | 173 | for msg_type in widget_msg_types: |
|
174 | 174 | self.shell_handlers[msg_type] = getattr(widget_manager, msg_type) |
General Comments 0
You need to be logged in to leave comments.
Login now