##// END OF EJS Templates
make js / Python widgets symmetrical...
MinRK -
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(this.kernel, content);
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 (kernel, content) {
83 this.kernel = kernel;
84 if (!content) return;
85 this.widget_id = content.widget_id;
86 this.handle_create(content.data);
100 var Widget = function (widget_id) {
101 this.widget_id = widget_id;
102 this.widget_type = 'widget';
87 103 };
88 104
89 Widget.prototype.handle_create = function (data) {
90 };
91
92 Widget.prototype.handle_update = 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 || {},
93 111 };
94
95 Widget.prototype.handle_destroy = function (data) {
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 self.widgets[widget.widget_id] = ref(widget)
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 widget.widget_id
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_ref = self.widgets.pop(widget_id)
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']
@@ -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