##// END OF EJS Templates
Merge master
Gordon Ball -
r17698:0a458d02 merge
parent child Browse files
Show More
@@ -0,0 +1,43 b''
1
2 //
3 // Tests for the Session object
4 //
5
6 casper.notebook_test(function () {
7 this.evaluate(function () {
8 var kernel = IPython.notebook.session.kernel;
9 IPython._channels = [
10 kernel.shell_channel,
11 kernel.iopub_channel,
12 kernel.stdin_channel
13 ];
14 IPython.notebook.session.delete();
15 });
16
17 this.waitFor(function () {
18 return this.evaluate(function(){
19 for (var i=0; i < IPython._channels.length; i++) {
20 var ws = IPython._channels[i];
21 if (ws.readyState !== ws.CLOSED) {
22 return false;
23 }
24 }
25 return true;
26 });
27 });
28
29 this.then(function () {
30 var states = this.evaluate(function() {
31 var states = [];
32 for (var i = 0; i < IPython._channels.length; i++) {
33 states.push(IPython._channels[i].readyState);
34 }
35 return states;
36 });
37
38 for (var i = 0; i < states.length; i++) {
39 this.test.assertEquals(states[i], WebSocket.CLOSED,
40 "Session.delete closes websockets[" + i + "]");
41 }
42 });
43 });
@@ -0,0 +1,73 b''
1 """Box class.
2
3 Represents a container that can be used to group other widgets.
4 """
5
6 # Copyright (c) IPython Development Team.
7 # Distributed under the terms of the Modified BSD License.
8
9 from .widget import DOMWidget
10 from IPython.utils.traitlets import Unicode, Tuple, TraitError, Int, CaselessStrEnum
11 from IPython.utils.warn import DeprecatedClass
12
13 class Box(DOMWidget):
14 """Displays multiple widgets in a group."""
15 _view_name = Unicode('BoxView', sync=True)
16
17 # Child widgets in the container.
18 # Using a tuple here to force reassignment to update the list.
19 # When a proper notifying-list trait exists, that is what should be used here.
20 children = Tuple(sync=True, allow_none=False)
21
22 def __init__(self, children = (), **kwargs):
23 kwargs['children'] = children
24 super(Box, self).__init__(**kwargs)
25 self.on_displayed(Box._fire_children_displayed)
26
27 def _fire_children_displayed(self):
28 for child in self.children:
29 child._handle_displayed()
30
31
32 class Popup(Box):
33 """Displays multiple widgets in an in page popup div."""
34 _view_name = Unicode('PopupView', sync=True)
35
36 description = Unicode(sync=True)
37 button_text = Unicode(sync=True)
38
39
40 class FlexBox(Box):
41 """Displays multiple widgets using the flexible box model."""
42 _view_name = Unicode('FlexBoxView', sync=True)
43 orientation = CaselessStrEnum(values=['vertical', 'horizontal'], default_value='vertical', sync=True)
44 flex = Int(0, sync=True, help="""Specify the flexible-ness of the model.""")
45 def _flex_changed(self, name, old, new):
46 new = min(max(0, new), 2)
47 if self.flex != new:
48 self.flex = new
49
50 _locations = ['start', 'center', 'end', 'baseline', 'stretch']
51 pack = CaselessStrEnum(
52 values=_locations,
53 default_value='start', allow_none=False, sync=True)
54 align = CaselessStrEnum(
55 values=_locations,
56 default_value='start', allow_none=False, sync=True)
57
58
59 def VBox(*pargs, **kwargs):
60 """Displays multiple widgets vertically using the flexible box model."""
61 kwargs['orientation'] = 'vertical'
62 return FlexBox(*pargs, **kwargs)
63
64 def HBox(*pargs, **kwargs):
65 """Displays multiple widgets horizontally using the flexible box model."""
66 kwargs['orientation'] = 'horizontal'
67 return FlexBox(*pargs, **kwargs)
68
69
70 # Remove in IPython 4.0
71 ContainerWidget = DeprecatedClass(Box, 'ContainerWidget')
72 PopupWidget = DeprecatedClass(Popup, 'PopupWidget')
73
@@ -0,0 +1,6 b''
1 * The widget classes have been renamed from `*Widget` to `*`. The old names are
2 still functional, but are deprecated. i.e. `IntSliderWidget` has been renamed
3 to `IntSlider`.
4 * The ContainerWidget was renamed to Box and no longer defaults as a flexible
5 box in the web browser. A new FlexBox widget was added, which allows you to
6 use the flexible box model.
@@ -84,6 +84,9 b' class KernelActionHandler(IPythonHandler):'
84
84
85 class ZMQChannelHandler(AuthenticatedZMQStreamHandler):
85 class ZMQChannelHandler(AuthenticatedZMQStreamHandler):
86
86
87 def __repr__(self):
88 return "%s(%s)" % (self.__class__.__name__, getattr(self, 'kernel_id', 'uninitialized'))
89
87 def create_stream(self):
90 def create_stream(self):
88 km = self.kernel_manager
91 km = self.kernel_manager
89 meth = getattr(km, 'connect_%s' % self.channel)
92 meth = getattr(km, 'connect_%s' % self.channel)
@@ -145,6 +148,12 b' class ZMQChannelHandler(AuthenticatedZMQStreamHandler):'
145 self.zmq_stream.on_recv(self._on_zmq_reply)
148 self.zmq_stream.on_recv(self._on_zmq_reply)
146
149
147 def on_message(self, msg):
150 def on_message(self, msg):
151 if self.zmq_stream is None:
152 return
153 elif self.zmq_stream.closed():
154 self.log.info("%s closed, closing websocket.", self)
155 self.close()
156 return
148 msg = json.loads(msg)
157 msg = json.loads(msg)
149 self.session.send(self.zmq_stream, msg)
158 self.session.send(self.zmq_stream, msg)
150
159
@@ -184,6 +184,30 b' Browsers not listed, including Safari, are supported via the styling under the'
184 justify-content: center;
184 justify-content: center;
185 }
185 }
186
186
187 .hbox.baseline,
188 .vbox.baseline,
189 .baseline {
190 /* Old browsers */
191 -webkit-box-pack: baseline;
192 -moz-box-pack: baseline;
193 box-pack: baseline;
194
195 /* Modern browsers */
196 justify-content: baseline;
197 }
198
199 .hbox.stretch,
200 .vbox.stretch,
201 .stretch {
202 /* Old browsers */
203 -webkit-box-pack: stretch;
204 -moz-box-pack: stretch;
205 box-pack: stretch;
206
207 /* Modern browsers */
208 justify-content: stretch;
209 }
210
187 .hbox.align-start,
211 .hbox.align-start,
188 .vbox.align-start,
212 .vbox.align-start,
189 .align-start {
213 .align-start {
@@ -219,3 +243,27 b' Browsers not listed, including Safari, are supported via the styling under the'
219 /* Modern browsers */
243 /* Modern browsers */
220 align-items: center;
244 align-items: center;
221 }
245 }
246
247 .hbox.align-baseline,
248 .vbox.align-baseline,
249 .align-baseline {
250 /* Old browsers */
251 -webkit-box-align: baseline;
252 -moz-box-align: baseline;
253 box-align: baseline;
254
255 /* Modern browsers */
256 align-items: baseline;
257 }
258
259 .hbox.align-stretch,
260 .vbox.align-stretch,
261 .align-stretch {
262 /* Old browsers */
263 -webkit-box-align: stretch;
264 -moz-box-align: stretch;
265 box-align: stretch;
266
267 /* Modern browsers */
268 align-items: stretch;
269 }
@@ -54,9 +54,19 b' define(['
54 return;
54 return;
55 }
55 }
56 var ks = this.kernelspecs[kernel_name];
56 var ks = this.kernelspecs[kernel_name];
57 try {
58 this.notebook.start_session(kernel_name);
59 } catch (e) {
60 if (e.name === 'SessionAlreadyStarting') {
61 console.log("Cannot change kernel while waiting for pending session start.");
62 } else {
63 // unhandled error
64 throw e;
65 }
66 // only trigger spec_changed if change was successful
67 return;
68 }
57 this.events.trigger('spec_changed.Kernel', ks);
69 this.events.trigger('spec_changed.Kernel', ks);
58 this.notebook.session.delete();
59 this.notebook.start_session(kernel_name);
60 };
70 };
61
71
62 KernelSelector.prototype.bind_events = function() {
72 KernelSelector.prototype.bind_events = function() {
@@ -157,12 +157,13 b' define(['
157 }
157 }
158 });
158 });
159 this.element.find('#kill_and_exit').click(function () {
159 this.element.find('#kill_and_exit').click(function () {
160 that.notebook.session.delete();
160 var close_window = function () {
161 setTimeout(function(){
162 // allow closing of new tabs in Chromium, impossible in FF
161 // allow closing of new tabs in Chromium, impossible in FF
163 window.open('', '_self', '');
162 window.open('', '_self', '');
164 window.close();
163 window.close();
165 }, 500);
164 };
165 // finish with close on success or failure
166 that.notebook.session.delete(close_window, close_window);
166 });
167 });
167 // Edit
168 // Edit
168 this.element.find('#cut_cell').click(function () {
169 this.element.find('#cut_cell').click(function () {
@@ -62,6 +62,7 b' define(['
62 this.save_widget = options.save_widget;
62 this.save_widget = options.save_widget;
63 this.tooltip = new tooltip.Tooltip(this.events);
63 this.tooltip = new tooltip.Tooltip(this.events);
64 this.ws_url = options.ws_url;
64 this.ws_url = options.ws_url;
65 this._session_starting = false;
65 // default_kernel_name is a temporary measure while we implement proper
66 // default_kernel_name is a temporary measure while we implement proper
66 // kernel selection and delayed start. Do not rely on it.
67 // kernel selection and delayed start. Do not rely on it.
67 this.default_kernel_name = 'python';
68 this.default_kernel_name = 'python';
@@ -1525,9 +1526,38 b' define(['
1525 * @method start_session
1526 * @method start_session
1526 */
1527 */
1527 Notebook.prototype.start_session = function (kernel_name) {
1528 Notebook.prototype.start_session = function (kernel_name) {
1529 var that = this;
1528 if (kernel_name === undefined) {
1530 if (kernel_name === undefined) {
1529 kernel_name = this.default_kernel_name;
1531 kernel_name = this.default_kernel_name;
1530 }
1532 }
1533 if (this._session_starting) {
1534 throw new session.SessionAlreadyStarting();
1535 }
1536 this._session_starting = true;
1537
1538 if (this.session !== null) {
1539 var s = this.session;
1540 this.session = null;
1541 // need to start the new session in a callback after delete,
1542 // because javascript does not guarantee the ordering of AJAX requests (?!)
1543 s.delete(function () {
1544 // on successful delete, start new session
1545 that._session_starting = false;
1546 that.start_session(kernel_name);
1547 }, function (jqXHR, status, error) {
1548 // log the failed delete, but still create a new session
1549 // 404 just means it was already deleted by someone else,
1550 // but other errors are possible.
1551 utils.log_ajax_error(jqXHR, status, error);
1552 that._session_starting = false;
1553 that.start_session(kernel_name);
1554 }
1555 );
1556 return;
1557 }
1558
1559
1560
1531 this.session = new session.Session({
1561 this.session = new session.Session({
1532 base_url: this.base_url,
1562 base_url: this.base_url,
1533 ws_url: this.ws_url,
1563 ws_url: this.ws_url,
@@ -1539,7 +1569,10 b' define(['
1539 kernel_name: kernel_name,
1569 kernel_name: kernel_name,
1540 notebook: this});
1570 notebook: this});
1541
1571
1542 this.session.start($.proxy(this._session_started, this));
1572 this.session.start(
1573 $.proxy(this._session_started, this),
1574 $.proxy(this._session_start_failed, this)
1575 );
1543 };
1576 };
1544
1577
1545
1578
@@ -1548,7 +1581,8 b' define(['
1548 * comm manager to the widget manager
1581 * comm manager to the widget manager
1549 *
1582 *
1550 */
1583 */
1551 Notebook.prototype._session_started = function(){
1584 Notebook.prototype._session_started = function (){
1585 this._session_starting = false;
1552 this.kernel = this.session.kernel;
1586 this.kernel = this.session.kernel;
1553 var ncells = this.ncells();
1587 var ncells = this.ncells();
1554 for (var i=0; i<ncells; i++) {
1588 for (var i=0; i<ncells; i++) {
@@ -1558,7 +1592,11 b' define(['
1558 }
1592 }
1559 }
1593 }
1560 };
1594 };
1561
1595 Notebook.prototype._session_start_failed = function (jqxhr, status, error){
1596 this._session_starting = false;
1597 utils.log_ajax_error(jqxhr, status, error);
1598 };
1599
1562 /**
1600 /**
1563 * Prompt the user to restart the IPython kernel.
1601 * Prompt the user to restart the IPython kernel.
1564 *
1602 *
@@ -109,6 +109,12 b' define(['
109 knw.set_message("Restarting kernel", 2000);
109 knw.set_message("Restarting kernel", 2000);
110 });
110 });
111
111
112 this.events.on('status_dead.Kernel',function () {
113 that.save_widget.update_document_title();
114 knw.danger("Dead kernel");
115 $kernel_ind_icon.attr('class','kernel_dead_icon').attr('title','Kernel Dead');
116 });
117
112 this.events.on('status_interrupting.Kernel',function () {
118 this.events.on('status_interrupting.Kernel',function () {
113 knw.set_message("Interrupting kernel", 2000);
119 knw.set_message("Interrupting kernel", 2000);
114 });
120 });
@@ -118,6 +124,8 b' define(['
118 $kernel_ind_icon.attr('class','kernel_busy_icon').attr('title','Kernel Busy');
124 $kernel_ind_icon.attr('class','kernel_busy_icon').attr('title','Kernel Busy');
119
125
120 this.events.on('status_started.Kernel', function (evt, data) {
126 this.events.on('status_started.Kernel', function (evt, data) {
127 knw.info("Websockets Connected", 500);
128 that.events.trigger('status_busy.Kernel');
121 data.kernel.kernel_info(function () {
129 data.kernel.kernel_info(function () {
122 that.events.trigger('status_idle.Kernel');
130 that.events.trigger('status_idle.Kernel');
123 });
131 });
@@ -153,8 +161,13 b' define(['
153 var ws_url = data.ws_url;
161 var ws_url = data.ws_url;
154 var early = data.early;
162 var early = data.early;
155 var msg;
163 var msg;
164
165 $kernel_ind_icon
166 .attr('class', 'kernel_disconnected_icon')
167 .attr('title', 'No Connection to Kernel');
168
156 if (!early) {
169 if (!early) {
157 knw.set_message('Reconnecting WebSockets', 1000);
170 knw.warning('Reconnecting');
158 setTimeout(function () {
171 setTimeout(function () {
159 kernel.start_channels();
172 kernel.start_channels();
160 }, 5000);
173 }, 5000);
@@ -173,7 +186,7 b' define(['
173 "OK": {},
186 "OK": {},
174 "Reconnect": {
187 "Reconnect": {
175 click: function () {
188 click: function () {
176 knw.set_message('Reconnecting WebSockets', 1000);
189 knw.warning('Reconnecting');
177 setTimeout(function () {
190 setTimeout(function () {
178 kernel.start_channels();
191 kernel.start_channels();
179 }, 5000);
192 }, 5000);
@@ -43,4 +43,12 b''
43 .icon(@fa-var-circle);
43 .icon(@fa-var-circle);
44 }
44 }
45
45
46 .kernel_dead_icon:before {
47 .icon(@fa-var-bomb);
48 }
49
50 .kernel_disconnected_icon:before {
51 .icon(@fa-var-chain-broken);
52 }
53
46
54
@@ -179,10 +179,18 b' define(['
179 that._websocket_closed(ws_host_url, false);
179 that._websocket_closed(ws_host_url, false);
180 }
180 }
181 };
181 };
182 var ws_error = function(evt){
183 if (already_called_onclose){
184 return;
185 }
186 already_called_onclose = true;
187 that._websocket_closed(ws_host_url, false);
188 };
182 var channels = [this.shell_channel, this.iopub_channel, this.stdin_channel];
189 var channels = [this.shell_channel, this.iopub_channel, this.stdin_channel];
183 for (var i=0; i < channels.length; i++) {
190 for (var i=0; i < channels.length; i++) {
184 channels[i].onopen = $.proxy(this._ws_opened, this);
191 channels[i].onopen = $.proxy(this._ws_opened, this);
185 channels[i].onclose = ws_closed_early;
192 channels[i].onclose = ws_closed_early;
193 channels[i].onerror = ws_error;
186 }
194 }
187 // switch from early-close to late-close message after 1s
195 // switch from early-close to late-close message after 1s
188 setTimeout(function() {
196 setTimeout(function() {
@@ -211,7 +219,7 b' define(['
211 var channels = [this.shell_channel, this.iopub_channel, this.stdin_channel];
219 var channels = [this.shell_channel, this.iopub_channel, this.stdin_channel];
212 for (var i=0; i < channels.length; i++) {
220 for (var i=0; i < channels.length; i++) {
213 // if any channel is not ready, don't trigger event.
221 // if any channel is not ready, don't trigger event.
214 if ( !channels[i].readyState ) return;
222 if ( channels[i].readyState == WebSocket.OPEN ) return;
215 }
223 }
216 // all events ready, trigger started event.
224 // all events ready, trigger started event.
217 this.events.trigger('status_started.Kernel', {kernel: this});
225 this.events.trigger('status_started.Kernel', {kernel: this});
@@ -385,15 +393,17 b' define(['
385 };
393 };
386
394
387
395
388 Kernel.prototype.kill = function () {
396 Kernel.prototype.kill = function (success, error) {
389 if (this.running) {
397 if (this.running) {
390 this.running = false;
398 this.running = false;
391 var settings = {
399 var settings = {
392 cache : false,
400 cache : false,
393 type : "DELETE",
401 type : "DELETE",
394 error : utils.log_ajax_error,
402 success : success,
403 error : error || utils.log_ajax_error,
395 };
404 };
396 $.ajax(utils.url_join_encode(this.kernel_url), settings);
405 $.ajax(utils.url_join_encode(this.kernel_url), settings);
406 this.stop_channels();
397 }
407 }
398 };
408 };
399
409
@@ -21,7 +21,7 b' define(['
21 this.ws_url = options.ws_url;
21 this.ws_url = options.ws_url;
22 };
22 };
23
23
24 Session.prototype.start = function(callback) {
24 Session.prototype.start = function (success, error) {
25 var that = this;
25 var that = this;
26 var model = {
26 var model = {
27 notebook : {
27 notebook : {
@@ -40,11 +40,17 b' define(['
40 dataType : "json",
40 dataType : "json",
41 success : function (data, status, xhr) {
41 success : function (data, status, xhr) {
42 that._handle_start_success(data);
42 that._handle_start_success(data);
43 if (callback) {
43 if (success) {
44 callback(data, status, xhr);
44 success(data, status, xhr);
45 }
45 }
46 },
46 },
47 error : utils.log_ajax_error,
47 error : function (xhr, status, err) {
48 that._handle_start_failure(xhr, status, err);
49 if (error !== undefined) {
50 error(xhr, status, err);
51 }
52 utils.log_ajax_error(xhr, status, err);
53 }
48 };
54 };
49 var url = utils.url_join_encode(this.base_url, 'api/sessions');
55 var url = utils.url_join_encode(this.base_url, 'api/sessions');
50 $.ajax(url, settings);
56 $.ajax(url, settings);
@@ -71,15 +77,19 b' define(['
71 $.ajax(url, settings);
77 $.ajax(url, settings);
72 };
78 };
73
79
74 Session.prototype.delete = function() {
80 Session.prototype.delete = function (success, error) {
75 var settings = {
81 var settings = {
76 processData : false,
82 processData : false,
77 cache : false,
83 cache : false,
78 type : "DELETE",
84 type : "DELETE",
79 dataType : "json",
85 dataType : "json",
80 error : utils.log_ajax_error,
86 success : success,
87 error : error || utils.log_ajax_error,
81 };
88 };
82 this.kernel.running = false;
89 if (this.kernel) {
90 this.kernel.running = false;
91 this.kernel.stop_channels();
92 }
83 var url = utils.url_join_encode(this.base_url, 'api/sessions', this.id);
93 var url = utils.url_join_encode(this.base_url, 'api/sessions', this.id);
84 $.ajax(url, settings);
94 $.ajax(url, settings);
85 };
95 };
@@ -99,6 +109,11 b' define(['
99 this.kernel = new kernel.Kernel(kernel_service_url, this.ws_url, this.notebook, this.kernel_name);
109 this.kernel = new kernel.Kernel(kernel_service_url, this.ws_url, this.notebook, this.kernel_name);
100 this.kernel._kernel_started(data.kernel);
110 this.kernel._kernel_started(data.kernel);
101 };
111 };
112
113 Session.prototype._handle_start_failure = function (xhr, status, error) {
114 this.events.trigger('start_failed.Session', [this, xhr, status, error]);
115 this.events.trigger('status_dead.Kernel');
116 };
102
117
103 /**
118 /**
104 * Prompt the user to restart the IPython kernel.
119 * Prompt the user to restart the IPython kernel.
@@ -118,8 +133,18 b' define(['
118 this.kernel.kill();
133 this.kernel.kill();
119 };
134 };
120
135
136 var SessionAlreadyStarting = function (message) {
137 this.name = "SessionAlreadyStarting";
138 this.message = (message || "");
139 };
140
141 SessionAlreadyStarting.prototype = Error.prototype;
142
121 // For backwards compatability.
143 // For backwards compatability.
122 IPython.Session = Session;
144 IPython.Session = Session;
123
145
124 return {'Session': Session};
146 return {
147 Session: Session,
148 SessionAlreadyStarting: SessionAlreadyStarting,
149 };
125 });
150 });
@@ -1501,7 +1501,7 b' div.cell.text_cell.rendered {'
1501 box-pack: start;
1501 box-pack: start;
1502 /* Modern browsers */
1502 /* Modern browsers */
1503 justify-content: flex-start;
1503 justify-content: flex-start;
1504 /* ContainerWidget */
1504 /* Box */
1505 box-sizing: border-box;
1505 box-sizing: border-box;
1506 -moz-box-sizing: border-box;
1506 -moz-box-sizing: border-box;
1507 -webkit-box-sizing: border-box;
1507 -webkit-box-sizing: border-box;
@@ -1532,7 +1532,7 b' div.cell.text_cell.rendered {'
1532 box-pack: start;
1532 box-pack: start;
1533 /* Modern browsers */
1533 /* Modern browsers */
1534 justify-content: flex-start;
1534 justify-content: flex-start;
1535 /* ContainerWidget */
1535 /* Box */
1536 box-sizing: border-box;
1536 box-sizing: border-box;
1537 -moz-box-sizing: border-box;
1537 -moz-box-sizing: border-box;
1538 -webkit-box-sizing: border-box;
1538 -webkit-box-sizing: border-box;
@@ -1584,7 +1584,7 b' div.cell.text_cell.rendered {'
1584 box-pack: start;
1584 box-pack: start;
1585 /* Modern browsers */
1585 /* Modern browsers */
1586 justify-content: flex-start;
1586 justify-content: flex-start;
1587 /* ContainerWidget */
1587 /* Box */
1588 box-sizing: border-box;
1588 box-sizing: border-box;
1589 -moz-box-sizing: border-box;
1589 -moz-box-sizing: border-box;
1590 -webkit-box-sizing: border-box;
1590 -webkit-box-sizing: border-box;
@@ -1639,7 +1639,7 b' div.cell.text_cell.rendered {'
1639 box-pack: start;
1639 box-pack: start;
1640 /* Modern browsers */
1640 /* Modern browsers */
1641 justify-content: flex-start;
1641 justify-content: flex-start;
1642 /* ContainerWidget */
1642 /* Box */
1643 box-sizing: border-box;
1643 box-sizing: border-box;
1644 -moz-box-sizing: border-box;
1644 -moz-box-sizing: border-box;
1645 -webkit-box-sizing: border-box;
1645 -webkit-box-sizing: border-box;
@@ -1691,7 +1691,7 b' div.cell.text_cell.rendered {'
1691 box-pack: start;
1691 box-pack: start;
1692 /* Modern browsers */
1692 /* Modern browsers */
1693 justify-content: flex-start;
1693 justify-content: flex-start;
1694 /* ContainerWidget */
1694 /* Box */
1695 box-sizing: border-box;
1695 box-sizing: border-box;
1696 -moz-box-sizing: border-box;
1696 -moz-box-sizing: border-box;
1697 -webkit-box-sizing: border-box;
1697 -webkit-box-sizing: border-box;
@@ -1724,7 +1724,7 b' div.cell.text_cell.rendered {'
1724 width: 30px;
1724 width: 30px;
1725 }
1725 }
1726 .widget-modal {
1726 .widget-modal {
1727 /* ContainerWidget - ModalView */
1727 /* Box - ModalView */
1728 overflow: hidden;
1728 overflow: hidden;
1729 position: absolute !important;
1729 position: absolute !important;
1730 top: 0px;
1730 top: 0px;
@@ -1732,11 +1732,11 b' div.cell.text_cell.rendered {'
1732 margin-left: 0px !important;
1732 margin-left: 0px !important;
1733 }
1733 }
1734 .widget-modal-body {
1734 .widget-modal-body {
1735 /* ContainerWidget - ModalView Body */
1735 /* Box - ModalView Body */
1736 max-height: none !important;
1736 max-height: none !important;
1737 }
1737 }
1738 .widget-container {
1738 .widget-box {
1739 /* ContainerWidget */
1739 /* Box */
1740 box-sizing: border-box;
1740 box-sizing: border-box;
1741 -moz-box-sizing: border-box;
1741 -moz-box-sizing: border-box;
1742 -webkit-box-sizing: border-box;
1742 -webkit-box-sizing: border-box;
@@ -9273,7 +9273,7 b' div.cell.text_cell.rendered {'
9273 box-pack: start;
9273 box-pack: start;
9274 /* Modern browsers */
9274 /* Modern browsers */
9275 justify-content: flex-start;
9275 justify-content: flex-start;
9276 /* ContainerWidget */
9276 /* Box */
9277 box-sizing: border-box;
9277 box-sizing: border-box;
9278 -moz-box-sizing: border-box;
9278 -moz-box-sizing: border-box;
9279 -webkit-box-sizing: border-box;
9279 -webkit-box-sizing: border-box;
@@ -9304,7 +9304,7 b' div.cell.text_cell.rendered {'
9304 box-pack: start;
9304 box-pack: start;
9305 /* Modern browsers */
9305 /* Modern browsers */
9306 justify-content: flex-start;
9306 justify-content: flex-start;
9307 /* ContainerWidget */
9307 /* Box */
9308 box-sizing: border-box;
9308 box-sizing: border-box;
9309 -moz-box-sizing: border-box;
9309 -moz-box-sizing: border-box;
9310 -webkit-box-sizing: border-box;
9310 -webkit-box-sizing: border-box;
@@ -9356,7 +9356,7 b' div.cell.text_cell.rendered {'
9356 box-pack: start;
9356 box-pack: start;
9357 /* Modern browsers */
9357 /* Modern browsers */
9358 justify-content: flex-start;
9358 justify-content: flex-start;
9359 /* ContainerWidget */
9359 /* Box */
9360 box-sizing: border-box;
9360 box-sizing: border-box;
9361 -moz-box-sizing: border-box;
9361 -moz-box-sizing: border-box;
9362 -webkit-box-sizing: border-box;
9362 -webkit-box-sizing: border-box;
@@ -9411,7 +9411,7 b' div.cell.text_cell.rendered {'
9411 box-pack: start;
9411 box-pack: start;
9412 /* Modern browsers */
9412 /* Modern browsers */
9413 justify-content: flex-start;
9413 justify-content: flex-start;
9414 /* ContainerWidget */
9414 /* Box */
9415 box-sizing: border-box;
9415 box-sizing: border-box;
9416 -moz-box-sizing: border-box;
9416 -moz-box-sizing: border-box;
9417 -webkit-box-sizing: border-box;
9417 -webkit-box-sizing: border-box;
@@ -9463,7 +9463,7 b' div.cell.text_cell.rendered {'
9463 box-pack: start;
9463 box-pack: start;
9464 /* Modern browsers */
9464 /* Modern browsers */
9465 justify-content: flex-start;
9465 justify-content: flex-start;
9466 /* ContainerWidget */
9466 /* Box */
9467 box-sizing: border-box;
9467 box-sizing: border-box;
9468 -moz-box-sizing: border-box;
9468 -moz-box-sizing: border-box;
9469 -webkit-box-sizing: border-box;
9469 -webkit-box-sizing: border-box;
@@ -9496,7 +9496,7 b' div.cell.text_cell.rendered {'
9496 width: 30px;
9496 width: 30px;
9497 }
9497 }
9498 .widget-modal {
9498 .widget-modal {
9499 /* ContainerWidget - ModalView */
9499 /* Box - ModalView */
9500 overflow: hidden;
9500 overflow: hidden;
9501 position: absolute !important;
9501 position: absolute !important;
9502 top: 0px;
9502 top: 0px;
@@ -9504,11 +9504,11 b' div.cell.text_cell.rendered {'
9504 margin-left: 0px !important;
9504 margin-left: 0px !important;
9505 }
9505 }
9506 .widget-modal-body {
9506 .widget-modal-body {
9507 /* ContainerWidget - ModalView Body */
9507 /* Box - ModalView Body */
9508 max-height: none !important;
9508 max-height: none !important;
9509 }
9509 }
9510 .widget-container {
9510 .widget-box {
9511 /* ContainerWidget */
9511 /* Box */
9512 box-sizing: border-box;
9512 box-sizing: border-box;
9513 -moz-box-sizing: border-box;
9513 -moz-box-sizing: border-box;
9514 -webkit-box-sizing: border-box;
9514 -webkit-box-sizing: border-box;
@@ -10006,6 +10006,38 b' ul#help_menu li a i {'
10006 .kernel_busy_icon:before.pull-right {
10006 .kernel_busy_icon:before.pull-right {
10007 margin-left: .3em;
10007 margin-left: .3em;
10008 }
10008 }
10009 .kernel_dead_icon:before {
10010 display: inline-block;
10011 font-family: FontAwesome;
10012 font-style: normal;
10013 font-weight: normal;
10014 line-height: 1;
10015 -webkit-font-smoothing: antialiased;
10016 -moz-osx-font-smoothing: grayscale;
10017 content: "\f1e2";
10018 }
10019 .kernel_dead_icon:before.pull-left {
10020 margin-right: .3em;
10021 }
10022 .kernel_dead_icon:before.pull-right {
10023 margin-left: .3em;
10024 }
10025 .kernel_disconnected_icon:before {
10026 display: inline-block;
10027 font-family: FontAwesome;
10028 font-style: normal;
10029 font-weight: normal;
10030 line-height: 1;
10031 -webkit-font-smoothing: antialiased;
10032 -moz-osx-font-smoothing: grayscale;
10033 content: "\f127";
10034 }
10035 .kernel_disconnected_icon:before.pull-left {
10036 margin-right: .3em;
10037 }
10038 .kernel_disconnected_icon:before.pull-right {
10039 margin-left: .3em;
10040 }
10009 .notification_widget {
10041 .notification_widget {
10010 color: #777777;
10042 color: #777777;
10011 padding: 1px 12px;
10043 padding: 1px 12px;
@@ -5,7 +5,7 b' define(['
5 "widgets/js/manager",
5 "widgets/js/manager",
6 "widgets/js/widget_bool",
6 "widgets/js/widget_bool",
7 "widgets/js/widget_button",
7 "widgets/js/widget_button",
8 "widgets/js/widget_container",
8 "widgets/js/widget_box",
9 "widgets/js/widget_float",
9 "widgets/js/widget_float",
10 "widgets/js/widget_image",
10 "widgets/js/widget_image",
11 "widgets/js/widget_int",
11 "widgets/js/widget_int",
@@ -7,11 +7,10 b' define(['
7 "bootstrap",
7 "bootstrap",
8 ], function(widget, $){
8 ], function(widget, $){
9
9
10 var ContainerView = widget.DOMWidgetView.extend({
10 var BoxView = widget.DOMWidgetView.extend({
11 initialize: function(){
11 initialize: function(){
12 // Public constructor
12 // Public constructor
13 ContainerView.__super__.initialize.apply(this, arguments);
13 BoxView.__super__.initialize.apply(this, arguments);
14 this.update_children([], this.model.get('children'));
15 this.model.on('change:children', function(model, value) {
14 this.model.on('change:children', function(model, value) {
16 this.update_children(model.previous('children'), value);
15 this.update_children(model.previous('children'), value);
17 }, this);
16 }, this);
@@ -19,7 +18,9 b' define(['
19
18
20 render: function(){
19 render: function(){
21 // Called when view is rendered.
20 // Called when view is rendered.
22 this.$el.addClass('widget-container').addClass('vbox');
21 this.$box = this.$el;
22 this.$box.addClass('widget-box');
23 this.update_children([], this.model.get('children'));
23 },
24 },
24
25
25 update_children: function(old_list, new_list) {
26 update_children: function(old_list, new_list) {
@@ -37,7 +38,7 b' define(['
37 add_child_model: function(model) {
38 add_child_model: function(model) {
38 // Called when a model is added to the children list.
39 // Called when a model is added to the children list.
39 var view = this.create_child_view(model);
40 var view = this.create_child_view(model);
40 this.$el.append(view.$el);
41 this.$box.append(view.$el);
41
42
42 // Trigger the displayed event of the child view.
43 // Trigger the displayed event of the child view.
43 this.after_displayed(function() {
44 this.after_displayed(function() {
@@ -45,9 +46,54 b' define(['
45 });
46 });
46 },
47 },
47 });
48 });
48
49
49
50 var PopupView = widget.DOMWidgetView.extend({
50
51 var FlexBoxView = BoxView.extend({
52 render: function(){
53 FlexBoxView.__super__.render.apply(this);
54 this.model.on('change:orientation', this.update_orientation, this);
55 this.model.on('change:flex', this._flex_changed, this);
56 this.model.on('change:pack', this._pack_changed, this);
57 this.model.on('change:align', this._align_changed, this);
58 this._flex_changed();
59 this._pack_changed();
60 this._align_changed();
61 this.update_orientation();
62 },
63
64 update_orientation: function(){
65 var orientation = this.model.get("orientation");
66 if (orientation == "vertical") {
67 this.$box.removeClass("hbox").addClass("vbox");
68 } else {
69 this.$box.removeClass("vbox").addClass("hbox");
70 }
71 },
72
73 _flex_changed: function(){
74 if (this.model.previous('flex')) {
75 this.$box.removeClass('box-flex' + this.model.previous('flex'));
76 }
77 this.$box.addClass('box-flex' + this.model.get('flex'));
78 },
79
80 _pack_changed: function(){
81 if (this.model.previous('pack')) {
82 this.$box.removeClass(this.model.previous('pack'));
83 }
84 this.$box.addClass(this.model.get('pack'));
85 },
86
87 _align_changed: function(){
88 if (this.model.previous('align')) {
89 this.$box.removeClass('align-' + this.model.previous('align'));
90 }
91 this.$box.addClass('align-' + this.model.get('align'));
92 },
93 });
94
95 var PopupView = BoxView.extend({
96
51 render: function(){
97 render: function(){
52 // Called when view is rendered.
98 // Called when view is rendered.
53 var that = this;
99 var that = this;
@@ -130,11 +176,11 b' define(['
130 this.$title = $('<div />')
176 this.$title = $('<div />')
131 .addClass('widget-modal-title')
177 .addClass('widget-modal-title')
132 .html("&nbsp;")
178 .html("&nbsp;")
133 .appendTo(this.$title_bar);
179 .appendTo(this.$title_bar);
134 this.$body = $('<div />')
180 this.$box = $('<div />')
135 .addClass('modal-body')
181 .addClass('modal-body')
136 .addClass('widget-modal-body')
182 .addClass('widget-modal-body')
137 .addClass('widget-container')
183 .addClass('widget-box')
138 .addClass('vbox')
184 .addClass('vbox')
139 .appendTo(this.$window);
185 .appendTo(this.$window);
140
186
@@ -149,7 +195,7 b' define(['
149 this.$window.draggable({handle: '.popover-title', snap: '#notebook, .modal', snapMode: 'both'});
195 this.$window.draggable({handle: '.popover-title', snap: '#notebook, .modal', snapMode: 'both'});
150 this.$window.resizable();
196 this.$window.resizable();
151 this.$window.on('resize', function(){
197 this.$window.on('resize', function(){
152 that.$body.outerHeight(that.$window.innerHeight() - that.$title_bar.outerHeight());
198 that.$box.outerHeight(that.$window.innerHeight() - that.$title_bar.outerHeight());
153 });
199 });
154
200
155 this._shown_once = false;
201 this._shown_once = false;
@@ -203,29 +249,6 b' define(['
203 this.$window.css('z-index', max_zindex);
249 this.$window.css('z-index', max_zindex);
204 },
250 },
205
251
206 update_children: function(old_list, new_list) {
207 // Called when the children list is modified.
208 this.do_diff(old_list, new_list,
209 $.proxy(this.remove_child_model, this),
210 $.proxy(this.add_child_model, this));
211 },
212
213 remove_child_model: function(model) {
214 // Called when a child is removed from children list.
215 this.pop_child_view(model).remove();
216 },
217
218 add_child_model: function(model) {
219 // Called when a child is added to children list.
220 var view = this.create_child_view(model);
221 this.$body.append(view.$el);
222
223 // Trigger the displayed event of the child view.
224 this.after_displayed(function() {
225 view.trigger('displayed');
226 });
227 },
228
229 update: function(){
252 update: function(){
230 // Update the contents of this view
253 // Update the contents of this view
231 //
254 //
@@ -277,7 +300,8 b' define(['
277 });
300 });
278
301
279 return {
302 return {
280 'ContainerView': ContainerView,
303 'BoxView': BoxView,
281 'PopupView': PopupView,
304 'PopupView': PopupView,
305 'FlexBoxView': FlexBoxView,
282 };
306 };
283 });
307 });
@@ -226,7 +226,7 b''
226 margin : 5px;
226 margin : 5px;
227
227
228 .start();
228 .start();
229 .widget-container();
229 .widget-box();
230 }
230 }
231
231
232 .widget-hbox {
232 .widget-hbox {
@@ -258,7 +258,7 b''
258 }
258 }
259
259
260 .widget-modal {
260 .widget-modal {
261 /* ContainerWidget - ModalView */
261 /* Box - ModalView */
262 overflow : hidden;
262 overflow : hidden;
263 position : absolute !important;
263 position : absolute !important;
264 top : 0px;
264 top : 0px;
@@ -267,12 +267,12 b''
267 }
267 }
268
268
269 .widget-modal-body {
269 .widget-modal-body {
270 /* ContainerWidget - ModalView Body */
270 /* Box - ModalView Body */
271 max-height: none !important;
271 max-height: none !important;
272 }
272 }
273
273
274 .widget-container {
274 .widget-box {
275 /* ContainerWidget */
275 /* Box */
276 .border-box-sizing();
276 .border-box-sizing();
277 .align-start();
277 .align-start();
278 }
278 }
@@ -1,12 +1,12 b''
1
1
2 //
2 //
3 // Miscellaneous javascript tests
3 // Kernel tests
4 //
4 //
5 casper.notebook_test(function () {
5 casper.notebook_test(function () {
6 this.evaluate(function () {
6 this.evaluate(function () {
7 IPython.notebook.kernel.kernel_info(
7 IPython.notebook.kernel.kernel_info(
8 function(msg){
8 function(msg){
9 IPython._kernel_info_response = msg;
9 IPython._kernel_info_response = msg;
10 })
10 })
11 });
11 });
12
12
@@ -24,5 +24,41 b' casper.notebook_test(function () {'
24 this.test.assertTrue( kernel_info_response.msg_type === 'kernel_info_reply', 'Kernel info request return kernel_info_reply');
24 this.test.assertTrue( kernel_info_response.msg_type === 'kernel_info_reply', 'Kernel info request return kernel_info_reply');
25 this.test.assertTrue( kernel_info_response.content !== undefined, 'Kernel_info_reply is not undefined');
25 this.test.assertTrue( kernel_info_response.content !== undefined, 'Kernel_info_reply is not undefined');
26 });
26 });
27
27
28 this.thenEvaluate(function () {
29 var kernel = IPython.notebook.session.kernel;
30 IPython._channels = [
31 kernel.shell_channel,
32 kernel.iopub_channel,
33 kernel.stdin_channel
34 ];
35 kernel.kill();
36 });
37
38 this.waitFor(function () {
39 return this.evaluate(function(){
40 for (var i=0; i < IPython._channels.length; i++) {
41 var ws = IPython._channels[i];
42 if (ws.readyState !== ws.CLOSED) {
43 return false;
44 }
45 }
46 return true;
47 });
48 });
49
50 this.then(function () {
51 var states = this.evaluate(function() {
52 var states = [];
53 for (var i = 0; i < IPython._channels.length; i++) {
54 states.push(IPython._channels[i].readyState);
55 }
56 return states;
57 });
58
59 for (var i = 0; i < states.length; i++) {
60 this.test.assertEquals(states[i], WebSocket.CLOSED,
61 "Kernel.kill closes websockets[" + i + "]");
62 }
63 });
28 });
64 });
@@ -147,7 +147,7 b' casper.notebook_test(function () {'
147 var textbox = {};
147 var textbox = {};
148 throttle_index = this.append_cell(
148 throttle_index = this.append_cell(
149 'import time\n' +
149 'import time\n' +
150 'textbox = widgets.TextWidget()\n' +
150 'textbox = widgets.Text()\n' +
151 'display(textbox)\n' +
151 'display(textbox)\n' +
152 'textbox.add_class("my-throttle-textbox", selector="input")\n' +
152 'textbox.add_class("my-throttle-textbox", selector="input")\n' +
153 'def handle_change(name, old, new):\n' +
153 'def handle_change(name, old, new):\n' +
@@ -7,8 +7,8 b' casper.notebook_test(function () {'
7 this.execute_cell_then(index);
7 this.execute_cell_then(index);
8
8
9 var bool_index = this.append_cell(
9 var bool_index = this.append_cell(
10 'bool_widgets = [widgets.CheckboxWidget(description="Title", value=True),\n' +
10 'bool_widgets = [widgets.Checkbox(description="Title", value=True),\n' +
11 ' widgets.ToggleButtonWidget(description="Title", value=True)]\n' +
11 ' widgets.ToggleButton(description="Title", value=True)]\n' +
12 'display(bool_widgets[0])\n' +
12 'display(bool_widgets[0])\n' +
13 'display(bool_widgets[1])\n' +
13 'display(bool_widgets[1])\n' +
14 'print("Success")');
14 'print("Success")');
@@ -7,8 +7,8 b' casper.notebook_test(function () {'
7 this.execute_cell_then(index);
7 this.execute_cell_then(index);
8
8
9 var container_index = this.append_cell(
9 var container_index = this.append_cell(
10 'container = widgets.ContainerWidget()\n' +
10 'container = widgets.Box()\n' +
11 'button = widgets.ButtonWidget()\n'+
11 'button = widgets.Button()\n'+
12 'container.children = [button]\n'+
12 'container.children = [button]\n'+
13 'display(container)\n'+
13 'display(container)\n'+
14 'container.add_class("my-test-class")\n'+
14 'container.add_class("my-test-class")\n'+
@@ -23,7 +23,7 b' casper.notebook_test(function () {'
23 'Widget subarea exists.');
23 'Widget subarea exists.');
24
24
25 this.test.assert(this.cell_element_exists(index,
25 this.test.assert(this.cell_element_exists(index,
26 '.widget-area .widget-subarea .widget-container'),
26 '.widget-area .widget-subarea .widget-box'),
27 'Widget container exists.');
27 'Widget container exists.');
28
28
29 this.test.assert(this.cell_element_exists(index,
29 this.test.assert(this.cell_element_exists(index,
@@ -70,7 +70,7 b' casper.notebook_test(function () {'
70 'Display container child executed with correct output.');
70 'Display container child executed with correct output.');
71
71
72 this.test.assert(! this.cell_element_exists(index,
72 this.test.assert(! this.cell_element_exists(index,
73 '.widget-area .widget-subarea .widget-container'),
73 '.widget-area .widget-subarea .widget-box'),
74 'Parent container not displayed.');
74 'Parent container not displayed.');
75
75
76 this.test.assert(this.cell_element_exists(index,
76 this.test.assert(this.cell_element_exists(index,
@@ -7,7 +7,7 b' casper.notebook_test(function () {'
7 this.execute_cell_then(index);
7 this.execute_cell_then(index);
8
8
9 var button_index = this.append_cell(
9 var button_index = this.append_cell(
10 'button = widgets.ButtonWidget(description="Title")\n' +
10 'button = widgets.Button(description="Title")\n' +
11 'display(button)\n' +
11 'display(button)\n' +
12 'print("Success")\n' +
12 'print("Success")\n' +
13 'def handle_click(sender):\n' +
13 'def handle_click(sender):\n' +
@@ -9,7 +9,7 b' casper.notebook_test(function () {'
9 var float_text = {};
9 var float_text = {};
10 float_text.query = '.widget-area .widget-subarea .widget-hbox-single .my-second-float-text';
10 float_text.query = '.widget-area .widget-subarea .widget-hbox-single .my-second-float-text';
11 float_text.index = this.append_cell(
11 float_text.index = this.append_cell(
12 'float_widget = widgets.FloatTextWidget()\n' +
12 'float_widget = widgets.FloatText()\n' +
13 'display(float_widget)\n' +
13 'display(float_widget)\n' +
14 'float_widget.add_class("my-second-float-text", selector="input")\n' +
14 'float_widget.add_class("my-second-float-text", selector="input")\n' +
15 'print(float_widget.model_id)\n');
15 'print(float_widget.model_id)\n');
@@ -59,8 +59,8 b' casper.notebook_test(function () {'
59 var slider = {};
59 var slider = {};
60 slider.query = '.widget-area .widget-subarea .widget-hbox-single .slider';
60 slider.query = '.widget-area .widget-subarea .widget-hbox-single .slider';
61 slider.index = this.append_cell(
61 slider.index = this.append_cell(
62 'floatrange = [widgets.BoundedFloatTextWidget(), \n' +
62 'floatrange = [widgets.BoundedFloatText(), \n' +
63 ' widgets.FloatSliderWidget()]\n' +
63 ' widgets.FloatSlider()]\n' +
64 '[display(floatrange[i]) for i in range(2)]\n' +
64 '[display(floatrange[i]) for i in range(2)]\n' +
65 'print("Success")\n');
65 'print("Success")\n');
66 this.execute_cell_then(slider.index, function(index){
66 this.execute_cell_then(slider.index, function(index){
@@ -18,7 +18,7 b' casper.notebook_test(function () {'
18 var image_index = this.append_cell(
18 var image_index = this.append_cell(
19 'import base64\n' +
19 'import base64\n' +
20 'data = base64.b64decode("' + test_jpg + '")\n' +
20 'data = base64.b64decode("' + test_jpg + '")\n' +
21 'image = widgets.ImageWidget()\n' +
21 'image = widgets.Image()\n' +
22 'image.format = "jpeg"\n' +
22 'image.format = "jpeg"\n' +
23 'image.value = data\n' +
23 'image.value = data\n' +
24 'image.width = "50px"\n' +
24 'image.width = "50px"\n' +
@@ -9,7 +9,7 b' casper.notebook_test(function () {'
9 var int_text = {};
9 var int_text = {};
10 int_text.query = '.widget-area .widget-subarea .widget-hbox-single .my-second-int-text';
10 int_text.query = '.widget-area .widget-subarea .widget-hbox-single .my-second-int-text';
11 int_text.index = this.append_cell(
11 int_text.index = this.append_cell(
12 'int_widget = widgets.IntTextWidget()\n' +
12 'int_widget = widgets.IntText()\n' +
13 'display(int_widget)\n' +
13 'display(int_widget)\n' +
14 'int_widget.add_class("my-second-int-text", selector="input")\n' +
14 'int_widget.add_class("my-second-int-text", selector="input")\n' +
15 'print(int_widget.model_id)\n');
15 'print(int_widget.model_id)\n');
@@ -44,10 +44,10 b' casper.notebook_test(function () {'
44 //values=["' + selection_values + '"[i] for i in range(4)]
44 //values=["' + selection_values + '"[i] for i in range(4)]
45 selection_index = this.append_cell(
45 selection_index = this.append_cell(
46 'values=["' + selection_values + '"[i] for i in range(4)]\n' +
46 'values=["' + selection_values + '"[i] for i in range(4)]\n' +
47 'selection = [widgets.DropdownWidget(values=values),\n' +
47 'selection = [widgets.Dropdown(values=values),\n' +
48 ' widgets.ToggleButtonsWidget(values=values),\n' +
48 ' widgets.ToggleButtons(values=values),\n' +
49 ' widgets.RadioButtonsWidget(values=values),\n' +
49 ' widgets.RadioButtons(values=values),\n' +
50 ' widgets.SelectWidget(values=values)]\n' +
50 ' widgets.Select(values=values)]\n' +
51 '[display(selection[i]) for i in range(4)]\n' +
51 '[display(selection[i]) for i in range(4)]\n' +
52 'for widget in selection:\n' +
52 'for widget in selection:\n' +
53 ' def handle_change(name,old,new):\n' +
53 ' def handle_change(name,old,new):\n' +
@@ -9,10 +9,10 b' casper.notebook_test(function () {'
9 // Test tab view
9 // Test tab view
10 var multicontainer1_query = '.widget-area .widget-subarea div div.nav-tabs';
10 var multicontainer1_query = '.widget-area .widget-subarea div div.nav-tabs';
11 var multicontainer1_index = this.append_cell(
11 var multicontainer1_index = this.append_cell(
12 'multicontainer = widgets.TabWidget()\n' +
12 'multicontainer = widgets.Tab()\n' +
13 'page1 = widgets.TextWidget()\n' +
13 'page1 = widgets.Text()\n' +
14 'page2 = widgets.TextWidget()\n' +
14 'page2 = widgets.Text()\n' +
15 'page3 = widgets.TextWidget()\n' +
15 'page3 = widgets.Text()\n' +
16 'multicontainer.children = [page1, page2, page3]\n' +
16 'multicontainer.children = [page1, page2, page3]\n' +
17 'display(multicontainer)\n' +
17 'display(multicontainer)\n' +
18 'multicontainer.selected_index = 0\n' +
18 'multicontainer.selected_index = 0\n' +
@@ -64,10 +64,10 b' casper.notebook_test(function () {'
64 // Test accordion view
64 // Test accordion view
65 var multicontainer2_query = '.widget-area .widget-subarea .panel-group';
65 var multicontainer2_query = '.widget-area .widget-subarea .panel-group';
66 var multicontainer2_index = this.append_cell(
66 var multicontainer2_index = this.append_cell(
67 'multicontainer = widgets.AccordionWidget()\n' +
67 'multicontainer = widgets.Accordion()\n' +
68 'page1 = widgets.TextWidget()\n' +
68 'page1 = widgets.Text()\n' +
69 'page2 = widgets.TextWidget()\n' +
69 'page2 = widgets.Text()\n' +
70 'page3 = widgets.TextWidget()\n' +
70 'page3 = widgets.Text()\n' +
71 'multicontainer.children = [page1, page2, page3]\n' +
71 'multicontainer.children = [page1, page2, page3]\n' +
72 'multicontainer.set_title(2, "good")\n' +
72 'multicontainer.set_title(2, "good")\n' +
73 'display(multicontainer)\n' +
73 'display(multicontainer)\n' +
@@ -7,10 +7,10 b' casper.notebook_test(function () {'
7 this.execute_cell_then(index);
7 this.execute_cell_then(index);
8
8
9 var string_index = this.append_cell(
9 var string_index = this.append_cell(
10 'string_widget = [widgets.TextWidget(value = "xyz", placeholder = "abc"),\n' +
10 'string_widget = [widgets.Text(value = "xyz", placeholder = "abc"),\n' +
11 ' widgets.TextareaWidget(value = "xyz", placeholder = "def"),\n' +
11 ' widgets.Textarea(value = "xyz", placeholder = "def"),\n' +
12 ' widgets.HTMLWidget(value = "xyz"),\n' +
12 ' widgets.HTML(value = "xyz"),\n' +
13 ' widgets.LatexWidget(value = "$\\\\LaTeX{}$")]\n' +
13 ' widgets.Latex(value = "$\\\\LaTeX{}$")]\n' +
14 '[display(widget) for widget in string_widget]\n'+
14 '[display(widget) for widget in string_widget]\n'+
15 'print("Success")');
15 'print("Success")');
16 this.execute_cell_then(string_index, function(index){
16 this.execute_cell_then(string_index, function(index){
@@ -1,12 +1,23 b''
1 from .widget import Widget, DOMWidget, CallbackDispatcher
1 from .widget import Widget, DOMWidget, CallbackDispatcher
2
2
3 from .widget_bool import Checkbox, ToggleButton
4 from .widget_button import Button
5 from .widget_box import Box, Popup, FlexBox, HBox, VBox
6 from .widget_float import FloatText, BoundedFloatText, FloatSlider, FloatProgress, FloatRangeSlider
7 from .widget_image import Image
8 from .widget_int import IntText, BoundedIntText, IntSlider, IntProgress, IntRangeSlider
9 from .widget_selection import RadioButtons, ToggleButtons, Dropdown, Select
10 from .widget_selectioncontainer import Tab, Accordion
11 from .widget_string import HTML, Latex, Text, Textarea
12 from .interaction import interact, interactive, fixed
13
14 # Deprecated classes
3 from .widget_bool import CheckboxWidget, ToggleButtonWidget
15 from .widget_bool import CheckboxWidget, ToggleButtonWidget
4 from .widget_button import ButtonWidget
16 from .widget_button import ButtonWidget
5 from .widget_container import ContainerWidget, PopupWidget
17 from .widget_box import ContainerWidget, PopupWidget
6 from .widget_float import FloatTextWidget, BoundedFloatTextWidget, FloatSliderWidget, FloatProgressWidget, FloatRangeSliderWidget
18 from .widget_float import FloatTextWidget, BoundedFloatTextWidget, FloatSliderWidget, FloatProgressWidget
7 from .widget_image import ImageWidget
19 from .widget_image import ImageWidget
8 from .widget_int import IntTextWidget, BoundedIntTextWidget, IntSliderWidget, IntProgressWidget, IntRangeSliderWidget
20 from .widget_int import IntTextWidget, BoundedIntTextWidget, IntSliderWidget, IntProgressWidget
9 from .widget_selection import RadioButtonsWidget, ToggleButtonsWidget, DropdownWidget, SelectWidget
21 from .widget_selection import RadioButtonsWidget, ToggleButtonsWidget, DropdownWidget, SelectWidget
10 from .widget_selectioncontainer import TabWidget, AccordionWidget
22 from .widget_selectioncontainer import TabWidget, AccordionWidget
11 from .widget_string import HTMLWidget, LatexWidget, TextWidget, TextareaWidget
23 from .widget_string import HTMLWidget, LatexWidget, TextWidget, TextareaWidget
12 from .interaction import interact, interactive, fixed
@@ -21,9 +21,9 b' except ImportError:'
21 from inspect import getcallargs
21 from inspect import getcallargs
22
22
23 from IPython.core.getipython import get_ipython
23 from IPython.core.getipython import get_ipython
24 from IPython.html.widgets import (Widget, TextWidget,
24 from IPython.html.widgets import (Widget, Text,
25 FloatSliderWidget, IntSliderWidget, CheckboxWidget, DropdownWidget,
25 FloatSlider, IntSlider, Checkbox, Dropdown,
26 ContainerWidget, DOMWidget)
26 Box, DOMWidget)
27 from IPython.display import display, clear_output
27 from IPython.display import display, clear_output
28 from IPython.utils.py3compat import string_types, unicode_type
28 from IPython.utils.py3compat import string_types, unicode_type
29 from IPython.utils.traitlets import HasTraits, Any, Unicode
29 from IPython.utils.traitlets import HasTraits, Any, Unicode
@@ -70,17 +70,17 b' def _get_min_max_value(min, max, value=None, step=None):'
70 def _widget_abbrev_single_value(o):
70 def _widget_abbrev_single_value(o):
71 """Make widgets from single values, which can be used as parameter defaults."""
71 """Make widgets from single values, which can be used as parameter defaults."""
72 if isinstance(o, string_types):
72 if isinstance(o, string_types):
73 return TextWidget(value=unicode_type(o))
73 return Text(value=unicode_type(o))
74 elif isinstance(o, dict):
74 elif isinstance(o, dict):
75 return DropdownWidget(values=o)
75 return Dropdown(values=o)
76 elif isinstance(o, bool):
76 elif isinstance(o, bool):
77 return CheckboxWidget(value=o)
77 return Checkbox(value=o)
78 elif isinstance(o, float):
78 elif isinstance(o, float):
79 min, max, value = _get_min_max_value(None, None, o)
79 min, max, value = _get_min_max_value(None, None, o)
80 return FloatSliderWidget(value=o, min=min, max=max)
80 return FloatSlider(value=o, min=min, max=max)
81 elif isinstance(o, int):
81 elif isinstance(o, int):
82 min, max, value = _get_min_max_value(None, None, o)
82 min, max, value = _get_min_max_value(None, None, o)
83 return IntSliderWidget(value=o, min=min, max=max)
83 return IntSlider(value=o, min=min, max=max)
84 else:
84 else:
85 return None
85 return None
86
86
@@ -89,13 +89,13 b' def _widget_abbrev(o):'
89 float_or_int = (float, int)
89 float_or_int = (float, int)
90 if isinstance(o, (list, tuple)):
90 if isinstance(o, (list, tuple)):
91 if o and all(isinstance(x, string_types) for x in o):
91 if o and all(isinstance(x, string_types) for x in o):
92 return DropdownWidget(values=[unicode_type(k) for k in o])
92 return Dropdown(values=[unicode_type(k) for k in o])
93 elif _matches(o, (float_or_int, float_or_int)):
93 elif _matches(o, (float_or_int, float_or_int)):
94 min, max, value = _get_min_max_value(o[0], o[1])
94 min, max, value = _get_min_max_value(o[0], o[1])
95 if all(isinstance(_, int) for _ in o):
95 if all(isinstance(_, int) for _ in o):
96 cls = IntSliderWidget
96 cls = IntSlider
97 else:
97 else:
98 cls = FloatSliderWidget
98 cls = FloatSlider
99 return cls(value=value, min=min, max=max)
99 return cls(value=value, min=min, max=max)
100 elif _matches(o, (float_or_int, float_or_int, float_or_int)):
100 elif _matches(o, (float_or_int, float_or_int, float_or_int)):
101 step = o[2]
101 step = o[2]
@@ -103,9 +103,9 b' def _widget_abbrev(o):'
103 raise ValueError("step must be >= 0, not %r" % step)
103 raise ValueError("step must be >= 0, not %r" % step)
104 min, max, value = _get_min_max_value(o[0], o[1], step=step)
104 min, max, value = _get_min_max_value(o[0], o[1], step=step)
105 if all(isinstance(_, int) for _ in o):
105 if all(isinstance(_, int) for _ in o):
106 cls = IntSliderWidget
106 cls = IntSlider
107 else:
107 else:
108 cls = FloatSliderWidget
108 cls = FloatSlider
109 return cls(value=value, min=min, max=max, step=step)
109 return cls(value=value, min=min, max=max, step=step)
110 else:
110 else:
111 return _widget_abbrev_single_value(o)
111 return _widget_abbrev_single_value(o)
@@ -176,7 +176,7 b' def interactive(__interact_f, **kwargs):'
176 f = __interact_f
176 f = __interact_f
177 co = kwargs.pop('clear_output', True)
177 co = kwargs.pop('clear_output', True)
178 kwargs_widgets = []
178 kwargs_widgets = []
179 container = ContainerWidget()
179 container = Box()
180 container.result = None
180 container.result = None
181 container.args = []
181 container.args = []
182 container.kwargs = dict()
182 container.kwargs = dict()
@@ -92,7 +92,7 b' def test_single_value_string():'
92 c = interactive(f, a=a)
92 c = interactive(f, a=a)
93 w = c.children[0]
93 w = c.children[0]
94 check_widget(w,
94 check_widget(w,
95 cls=widgets.TextWidget,
95 cls=widgets.Text,
96 description='a',
96 description='a',
97 value=a,
97 value=a,
98 )
98 )
@@ -102,7 +102,7 b' def test_single_value_bool():'
102 c = interactive(f, a=a)
102 c = interactive(f, a=a)
103 w = c.children[0]
103 w = c.children[0]
104 check_widget(w,
104 check_widget(w,
105 cls=widgets.CheckboxWidget,
105 cls=widgets.Checkbox,
106 description='a',
106 description='a',
107 value=a,
107 value=a,
108 )
108 )
@@ -115,7 +115,7 b' def test_single_value_dict():'
115 c = interactive(f, d=d)
115 c = interactive(f, d=d)
116 w = c.children[0]
116 w = c.children[0]
117 check_widget(w,
117 check_widget(w,
118 cls=widgets.DropdownWidget,
118 cls=widgets.Dropdown,
119 description='d',
119 description='d',
120 values=d,
120 values=d,
121 value=next(iter(d.values())),
121 value=next(iter(d.values())),
@@ -126,7 +126,7 b' def test_single_value_float():'
126 c = interactive(f, a=a)
126 c = interactive(f, a=a)
127 w = c.children[0]
127 w = c.children[0]
128 check_widget(w,
128 check_widget(w,
129 cls=widgets.FloatSliderWidget,
129 cls=widgets.FloatSlider,
130 description='a',
130 description='a',
131 value=a,
131 value=a,
132 min= -a if a > 0 else 3*a,
132 min= -a if a > 0 else 3*a,
@@ -141,7 +141,7 b' def test_single_value_int():'
141 nt.assert_equal(len(c.children), 1)
141 nt.assert_equal(len(c.children), 1)
142 w = c.children[0]
142 w = c.children[0]
143 check_widget(w,
143 check_widget(w,
144 cls=widgets.IntSliderWidget,
144 cls=widgets.IntSlider,
145 description='a',
145 description='a',
146 value=a,
146 value=a,
147 min= -a if a > 0 else 3*a,
147 min= -a if a > 0 else 3*a,
@@ -159,7 +159,7 b' def test_list_tuple_2_int():'
159 c = interactive(f, tup=(min, max), lis=[min, max])
159 c = interactive(f, tup=(min, max), lis=[min, max])
160 nt.assert_equal(len(c.children), 2)
160 nt.assert_equal(len(c.children), 2)
161 d = dict(
161 d = dict(
162 cls=widgets.IntSliderWidget,
162 cls=widgets.IntSlider,
163 min=min,
163 min=min,
164 max=max,
164 max=max,
165 step=1,
165 step=1,
@@ -176,7 +176,7 b' def test_list_tuple_3_int():'
176 c = interactive(f, tup=(min, max, step), lis=[min, max, step])
176 c = interactive(f, tup=(min, max, step), lis=[min, max, step])
177 nt.assert_equal(len(c.children), 2)
177 nt.assert_equal(len(c.children), 2)
178 d = dict(
178 d = dict(
179 cls=widgets.IntSliderWidget,
179 cls=widgets.IntSlider,
180 min=min,
180 min=min,
181 max=max,
181 max=max,
182 step=step,
182 step=step,
@@ -193,7 +193,7 b' def test_list_tuple_2_float():'
193 c = interactive(f, tup=(min, max), lis=[min, max])
193 c = interactive(f, tup=(min, max), lis=[min, max])
194 nt.assert_equal(len(c.children), 2)
194 nt.assert_equal(len(c.children), 2)
195 d = dict(
195 d = dict(
196 cls=widgets.FloatSliderWidget,
196 cls=widgets.FloatSlider,
197 min=min,
197 min=min,
198 max=max,
198 max=max,
199 step=.1,
199 step=.1,
@@ -212,7 +212,7 b' def test_list_tuple_3_float():'
212 c = interactive(f, tup=(min, max, step), lis=[min, max, step])
212 c = interactive(f, tup=(min, max, step), lis=[min, max, step])
213 nt.assert_equal(len(c.children), 2)
213 nt.assert_equal(len(c.children), 2)
214 d = dict(
214 d = dict(
215 cls=widgets.FloatSliderWidget,
215 cls=widgets.FloatSlider,
216 min=min,
216 min=min,
217 max=max,
217 max=max,
218 step=step,
218 step=step,
@@ -227,7 +227,7 b' def test_list_tuple_str():'
227 c = interactive(f, tup=tuple(values), lis=list(values))
227 c = interactive(f, tup=tuple(values), lis=list(values))
228 nt.assert_equal(len(c.children), 2)
228 nt.assert_equal(len(c.children), 2)
229 d = dict(
229 d = dict(
230 cls=widgets.DropdownWidget,
230 cls=widgets.Dropdown,
231 value=first,
231 value=first,
232 values=dvalues
232 values=dvalues
233 )
233 )
@@ -253,15 +253,15 b' def test_defaults():'
253 c = interactive(f)
253 c = interactive(f)
254 check_widgets(c,
254 check_widgets(c,
255 n=dict(
255 n=dict(
256 cls=widgets.IntSliderWidget,
256 cls=widgets.IntSlider,
257 value=10,
257 value=10,
258 ),
258 ),
259 f=dict(
259 f=dict(
260 cls=widgets.FloatSliderWidget,
260 cls=widgets.FloatSlider,
261 value=4.5,
261 value=4.5,
262 ),
262 ),
263 g=dict(
263 g=dict(
264 cls=widgets.IntSliderWidget,
264 cls=widgets.IntSlider,
265 value=1,
265 value=1,
266 ),
266 ),
267 )
267 )
@@ -274,24 +274,24 b' def test_default_values():'
274 c = interactive(f)
274 c = interactive(f)
275 check_widgets(c,
275 check_widgets(c,
276 n=dict(
276 n=dict(
277 cls=widgets.IntSliderWidget,
277 cls=widgets.IntSlider,
278 value=10,
278 value=10,
279 ),
279 ),
280 f=dict(
280 f=dict(
281 cls=widgets.FloatSliderWidget,
281 cls=widgets.FloatSlider,
282 value=4.5,
282 value=4.5,
283 ),
283 ),
284 g=dict(
284 g=dict(
285 cls=widgets.IntSliderWidget,
285 cls=widgets.IntSlider,
286 value=5,
286 value=5,
287 ),
287 ),
288 h=dict(
288 h=dict(
289 cls=widgets.DropdownWidget,
289 cls=widgets.Dropdown,
290 values={'a': 1, 'b': 2},
290 values={'a': 1, 'b': 2},
291 value=2
291 value=2
292 ),
292 ),
293 j=dict(
293 j=dict(
294 cls=widgets.DropdownWidget,
294 cls=widgets.Dropdown,
295 values={'hi':'hi', 'there':'there'},
295 values={'hi':'hi', 'there':'there'},
296 value='there'
296 value='there'
297 ),
297 ),
@@ -305,34 +305,34 b' def test_default_out_of_bounds():'
305 c = interactive(f)
305 c = interactive(f)
306 check_widgets(c,
306 check_widgets(c,
307 f=dict(
307 f=dict(
308 cls=widgets.FloatSliderWidget,
308 cls=widgets.FloatSlider,
309 value=5.,
309 value=5.,
310 ),
310 ),
311 h=dict(
311 h=dict(
312 cls=widgets.DropdownWidget,
312 cls=widgets.Dropdown,
313 values={'a': 1},
313 values={'a': 1},
314 value=1,
314 value=1,
315 ),
315 ),
316 j=dict(
316 j=dict(
317 cls=widgets.DropdownWidget,
317 cls=widgets.Dropdown,
318 values={'hi':'hi', 'there':'there'},
318 values={'hi':'hi', 'there':'there'},
319 value='hi',
319 value='hi',
320 ),
320 ),
321 )
321 )
322
322
323 def test_annotations():
323 def test_annotations():
324 @annotate(n=10, f=widgets.FloatTextWidget())
324 @annotate(n=10, f=widgets.FloatText())
325 def f(n, f):
325 def f(n, f):
326 pass
326 pass
327
327
328 c = interactive(f)
328 c = interactive(f)
329 check_widgets(c,
329 check_widgets(c,
330 n=dict(
330 n=dict(
331 cls=widgets.IntSliderWidget,
331 cls=widgets.IntSlider,
332 value=10,
332 value=10,
333 ),
333 ),
334 f=dict(
334 f=dict(
335 cls=widgets.FloatTextWidget,
335 cls=widgets.FloatText,
336 ),
336 ),
337 )
337 )
338
338
@@ -344,11 +344,11 b' def test_priority():'
344 c = interactive(f, kwarg='kwarg')
344 c = interactive(f, kwarg='kwarg')
345 check_widgets(c,
345 check_widgets(c,
346 kwarg=dict(
346 kwarg=dict(
347 cls=widgets.TextWidget,
347 cls=widgets.Text,
348 value='kwarg',
348 value='kwarg',
349 ),
349 ),
350 annotate=dict(
350 annotate=dict(
351 cls=widgets.TextWidget,
351 cls=widgets.Text,
352 value='annotate',
352 value='annotate',
353 ),
353 ),
354 )
354 )
@@ -362,7 +362,7 b' def test_decorator_kwarg():'
362 nt.assert_equal(len(displayed), 1)
362 nt.assert_equal(len(displayed), 1)
363 w = displayed[0].children[0]
363 w = displayed[0].children[0]
364 check_widget(w,
364 check_widget(w,
365 cls=widgets.IntSliderWidget,
365 cls=widgets.IntSlider,
366 value=5,
366 value=5,
367 )
367 )
368
368
@@ -375,7 +375,7 b' def test_decorator_no_call():'
375 nt.assert_equal(len(displayed), 1)
375 nt.assert_equal(len(displayed), 1)
376 w = displayed[0].children[0]
376 w = displayed[0].children[0]
377 check_widget(w,
377 check_widget(w,
378 cls=widgets.TextWidget,
378 cls=widgets.Text,
379 value='default',
379 value='default',
380 )
380 )
381
381
@@ -388,7 +388,7 b' def test_call_interact():'
388 nt.assert_equal(len(displayed), 1)
388 nt.assert_equal(len(displayed), 1)
389 w = displayed[0].children[0]
389 w = displayed[0].children[0]
390 check_widget(w,
390 check_widget(w,
391 cls=widgets.TextWidget,
391 cls=widgets.Text,
392 value='default',
392 value='default',
393 )
393 )
394
394
@@ -401,7 +401,7 b' def test_call_interact_kwargs():'
401 nt.assert_equal(len(displayed), 1)
401 nt.assert_equal(len(displayed), 1)
402 w = displayed[0].children[0]
402 w = displayed[0].children[0]
403 check_widget(w,
403 check_widget(w,
404 cls=widgets.IntSliderWidget,
404 cls=widgets.IntSlider,
405 value=10,
405 value=10,
406 )
406 )
407
407
@@ -417,7 +417,7 b' def test_call_decorated_on_trait_change():'
417 nt.assert_equal(len(displayed), 1)
417 nt.assert_equal(len(displayed), 1)
418 w = displayed[0].children[0]
418 w = displayed[0].children[0]
419 check_widget(w,
419 check_widget(w,
420 cls=widgets.TextWidget,
420 cls=widgets.Text,
421 value='default',
421 value='default',
422 )
422 )
423 # test calling the function directly
423 # test calling the function directly
@@ -441,7 +441,7 b' def test_call_decorated_kwargs_on_trait_change():'
441 nt.assert_equal(len(displayed), 1)
441 nt.assert_equal(len(displayed), 1)
442 w = displayed[0].children[0]
442 w = displayed[0].children[0]
443 check_widget(w,
443 check_widget(w,
444 cls=widgets.TextWidget,
444 cls=widgets.Text,
445 value='kwarg',
445 value='kwarg',
446 )
446 )
447 # test calling the function directly
447 # test calling the function directly
@@ -458,7 +458,7 b' def test_fixed():'
458 nt.assert_equal(len(c.children), 1)
458 nt.assert_equal(len(c.children), 1)
459 w = c.children[0]
459 w = c.children[0]
460 check_widget(w,
460 check_widget(w,
461 cls=widgets.TextWidget,
461 cls=widgets.Text,
462 value='text',
462 value='text',
463 description='b',
463 description='b',
464 )
464 )
@@ -467,22 +467,22 b' def test_default_description():'
467 c = interactive(f, b='text')
467 c = interactive(f, b='text')
468 w = c.children[0]
468 w = c.children[0]
469 check_widget(w,
469 check_widget(w,
470 cls=widgets.TextWidget,
470 cls=widgets.Text,
471 value='text',
471 value='text',
472 description='b',
472 description='b',
473 )
473 )
474
474
475 def test_custom_description():
475 def test_custom_description():
476 c = interactive(f, b=widgets.TextWidget(value='text', description='foo'))
476 c = interactive(f, b=widgets.Text(value='text', description='foo'))
477 w = c.children[0]
477 w = c.children[0]
478 check_widget(w,
478 check_widget(w,
479 cls=widgets.TextWidget,
479 cls=widgets.Text,
480 value='text',
480 value='text',
481 description='foo',
481 description='foo',
482 )
482 )
483
483
484 def test_int_range_logic():
484 def test_int_range_logic():
485 irsw = widgets.IntRangeSliderWidget
485 irsw = widgets.IntRangeSlider
486 w = irsw(value=(2, 4), min=0, max=6)
486 w = irsw(value=(2, 4), min=0, max=6)
487 check_widget(w, cls=irsw, value=(2, 4), min=0, max=6)
487 check_widget(w, cls=irsw, value=(2, 4), min=0, max=6)
488 w.value = (4, 2)
488 w.value = (4, 2)
@@ -537,7 +537,7 b' def test_int_range_logic():'
537
537
538
538
539 def test_float_range_logic():
539 def test_float_range_logic():
540 frsw = widgets.FloatRangeSliderWidget
540 frsw = widgets.FloatRangeSlider
541 w = frsw(value=(.2, .4), min=0., max=.6)
541 w = frsw(value=(.2, .4), min=0., max=.6)
542 check_widget(w, cls=frsw, value=(.2, .4), min=0., max=.6)
542 check_widget(w, cls=frsw, value=(.2, .4), min=0., max=.6)
543 w.value = (.4, .2)
543 w.value = (.4, .2)
@@ -588,4 +588,4 b' def test_float_range_logic():'
588 with nt.assert_raises(ValueError):
588 with nt.assert_raises(ValueError):
589 frsw(value=(2, 4), lower=3, upper=3)
589 frsw(value=(2, 4), lower=3, upper=3)
590 with nt.assert_raises(ValueError):
590 with nt.assert_raises(ValueError):
591 frsw(min=.2, max=.1) No newline at end of file
591 frsw(min=.2, max=.1)
@@ -1,4 +1,4 b''
1 """BoolWidget class.
1 """Bool class.
2
2
3 Represents a boolean using a widget.
3 Represents a boolean using a widget.
4 """
4 """
@@ -15,20 +15,29 b' Represents a boolean using a widget.'
15 #-----------------------------------------------------------------------------
15 #-----------------------------------------------------------------------------
16 from .widget import DOMWidget
16 from .widget import DOMWidget
17 from IPython.utils.traitlets import Unicode, Bool
17 from IPython.utils.traitlets import Unicode, Bool
18 from IPython.utils.warn import DeprecatedClass
18
19
19 #-----------------------------------------------------------------------------
20 #-----------------------------------------------------------------------------
20 # Classes
21 # Classes
21 #-----------------------------------------------------------------------------
22 #-----------------------------------------------------------------------------
22 class _BoolWidget(DOMWidget):
23 class _Bool(DOMWidget):
24 """A base class for creating widgets that represent booleans."""
23 value = Bool(False, help="Bool value", sync=True)
25 value = Bool(False, help="Bool value", sync=True)
24 description = Unicode('', help="Description of the boolean (label).", sync=True)
26 description = Unicode('', help="Description of the boolean (label).", sync=True)
25 disabled = Bool(False, help="Enable or disable user changes.", sync=True)
27 disabled = Bool(False, help="Enable or disable user changes.", sync=True)
26
28
27
29
28 class CheckboxWidget(_BoolWidget):
30 class Checkbox(_Bool):
31 """Displays a boolean `value`."""
29 _view_name = Unicode('CheckboxView', sync=True)
32 _view_name = Unicode('CheckboxView', sync=True)
30
33
31
34
32 class ToggleButtonWidget(_BoolWidget):
35 class ToggleButton(_Bool):
33 _view_name = Unicode('ToggleButtonView', sync=True)
36 """Displays a boolean `value`."""
34
37
38 _view_name = Unicode('ToggleButtonView', sync=True)
39
40
41 # Remove in IPython 4.0
42 CheckboxWidget = DeprecatedClass(Checkbox, 'CheckboxWidget')
43 ToggleButtonWidget = DeprecatedClass(ToggleButton, 'ToggleButtonWidget')
@@ -1,4 +1,4 b''
1 """ButtonWidget 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.
@@ -16,11 +16,16 b' click events on the button and trigger backend code when the clicks are fired.'
16 #-----------------------------------------------------------------------------
16 #-----------------------------------------------------------------------------
17 from .widget import DOMWidget, CallbackDispatcher
17 from .widget import DOMWidget, CallbackDispatcher
18 from IPython.utils.traitlets import Unicode, Bool
18 from IPython.utils.traitlets import Unicode, Bool
19 from IPython.utils.warn import DeprecatedClass
19
20
20 #-----------------------------------------------------------------------------
21 #-----------------------------------------------------------------------------
21 # Classes
22 # Classes
22 #-----------------------------------------------------------------------------
23 #-----------------------------------------------------------------------------
23 class ButtonWidget(DOMWidget):
24 class Button(DOMWidget):
25 """Button widget.
26
27 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."""
24 _view_name = Unicode('ButtonView', sync=True)
29 _view_name = Unicode('ButtonView', sync=True)
25
30
26 # Keys
31 # Keys
@@ -29,7 +34,7 b' class ButtonWidget(DOMWidget):'
29
34
30 def __init__(self, **kwargs):
35 def __init__(self, **kwargs):
31 """Constructor"""
36 """Constructor"""
32 super(ButtonWidget, self).__init__(**kwargs)
37 super(Button, self).__init__(**kwargs)
33 self._click_handlers = CallbackDispatcher()
38 self._click_handlers = CallbackDispatcher()
34 self.on_msg(self._handle_button_msg)
39 self.on_msg(self._handle_button_msg)
35
40
@@ -54,3 +59,7 b' class ButtonWidget(DOMWidget):'
54 Content of the msg."""
59 Content of the msg."""
55 if content.get('event', '') == 'click':
60 if content.get('event', '') == 'click':
56 self._click_handlers(self)
61 self._click_handlers(self)
62
63
64 # Remove in IPython 4.0
65 ButtonWidget = DeprecatedClass(Button, 'ButtonWidget')
@@ -1,4 +1,4 b''
1 """FloatWidget class.
1 """Float class.
2
2
3 Represents an unbounded float using a widget.
3 Represents an unbounded float using a widget.
4 """
4 """
@@ -15,17 +15,18 b' Represents an unbounded float using a widget.'
15 #-----------------------------------------------------------------------------
15 #-----------------------------------------------------------------------------
16 from .widget import DOMWidget
16 from .widget import DOMWidget
17 from IPython.utils.traitlets import Unicode, CFloat, Bool, Enum, Tuple
17 from IPython.utils.traitlets import Unicode, CFloat, Bool, Enum, Tuple
18 from IPython.utils.warn import DeprecatedClass
18
19
19 #-----------------------------------------------------------------------------
20 #-----------------------------------------------------------------------------
20 # Classes
21 # Classes
21 #-----------------------------------------------------------------------------
22 #-----------------------------------------------------------------------------
22 class _FloatWidget(DOMWidget):
23 class _Float(DOMWidget):
23 value = CFloat(0.0, help="Float value", sync=True)
24 value = CFloat(0.0, help="Float value", sync=True)
24 disabled = Bool(False, help="Enable or disable user changes", sync=True)
25 disabled = Bool(False, help="Enable or disable user changes", sync=True)
25 description = Unicode(help="Description of the value this widget represents", sync=True)
26 description = Unicode(help="Description of the value this widget represents", sync=True)
26
27
27
28
28 class _BoundedFloatWidget(_FloatWidget):
29 class _BoundedFloat(_Float):
29 max = CFloat(100.0, help="Max value", sync=True)
30 max = CFloat(100.0, help="Max value", sync=True)
30 min = CFloat(0.0, help="Min value", sync=True)
31 min = CFloat(0.0, help="Min value", sync=True)
31 step = CFloat(0.1, help="Minimum step that the value can take (ignored by some views)", sync=True)
32 step = CFloat(0.1, help="Minimum step that the value can take (ignored by some views)", sync=True)
@@ -42,26 +43,26 b' class _BoundedFloatWidget(_FloatWidget):'
42 self.value = min(max(new, self.min), self.max)
43 self.value = min(max(new, self.min), self.max)
43
44
44
45
45 class FloatTextWidget(_FloatWidget):
46 class FloatText(_Float):
46 _view_name = Unicode('FloatTextView', sync=True)
47 _view_name = Unicode('FloatTextView', sync=True)
47
48
48
49
49 class BoundedFloatTextWidget(_BoundedFloatWidget):
50 class BoundedFloatText(_BoundedFloat):
50 _view_name = Unicode('FloatTextView', sync=True)
51 _view_name = Unicode('FloatTextView', sync=True)
51
52
52
53
53 class FloatSliderWidget(_BoundedFloatWidget):
54 class FloatSlider(_BoundedFloat):
54 _view_name = Unicode('FloatSliderView', sync=True)
55 _view_name = Unicode('FloatSliderView', sync=True)
55 orientation = Enum([u'horizontal', u'vertical'], u'horizontal',
56 orientation = Enum([u'horizontal', u'vertical'], u'horizontal',
56 help="Vertical or horizontal.", sync=True)
57 help="Vertical or horizontal.", sync=True)
57 range = Bool(False, help="Display a range selector", sync=True)
58 range = Bool(False, help="Display a range selector", sync=True)
58 readout = Bool(True, help="Display the current value of the slider next to it.", sync=True)
59 readout = Bool(True, help="Display the current value of the slider next to it.", sync=True)
59
60
60
61
61 class FloatProgressWidget(_BoundedFloatWidget):
62 class FloatProgress(_BoundedFloat):
62 _view_name = Unicode('ProgressView', sync=True)
63 _view_name = Unicode('ProgressView', sync=True)
63
64
64 class _FloatRangeWidget(_FloatWidget):
65 class _FloatRange(_Float):
65 value = Tuple(CFloat, CFloat, default_value=(0.0, 1.0), help="Tuple of (lower, upper) bounds", sync=True)
66 value = Tuple(CFloat, CFloat, default_value=(0.0, 1.0), help="Tuple of (lower, upper) bounds", sync=True)
66 lower = CFloat(0.0, help="Lower bound", sync=False)
67 lower = CFloat(0.0, help="Lower bound", sync=False)
67 upper = CFloat(1.0, help="Upper bound", sync=False)
68 upper = CFloat(1.0, help="Upper bound", sync=False)
@@ -90,14 +91,14 b' class _FloatRangeWidget(_FloatWidget):'
90 elif name == 'upper':
91 elif name == 'upper':
91 self.value = (self.value[0], new)
92 self.value = (self.value[0], new)
92
93
93 class _BoundedFloatRangeWidget(_FloatRangeWidget):
94 class _BoundedFloatRange(_FloatRange):
94 step = CFloat(1.0, help="Minimum step that the value can take (ignored by some views)", sync=True)
95 step = CFloat(1.0, help="Minimum step that the value can take (ignored by some views)", sync=True)
95 max = CFloat(100.0, help="Max value", sync=True)
96 max = CFloat(100.0, help="Max value", sync=True)
96 min = CFloat(0.0, help="Min value", sync=True)
97 min = CFloat(0.0, help="Min value", sync=True)
97
98
98 def __init__(self, *pargs, **kwargs):
99 def __init__(self, *pargs, **kwargs):
99 any_value_given = 'value' in kwargs or 'upper' in kwargs or 'lower' in kwargs
100 any_value_given = 'value' in kwargs or 'upper' in kwargs or 'lower' in kwargs
100 _FloatRangeWidget.__init__(self, *pargs, **kwargs)
101 _FloatRange.__init__(self, *pargs, **kwargs)
101
102
102 # ensure a minimal amount of sanity
103 # ensure a minimal amount of sanity
103 if self.min > self.max:
104 if self.min > self.max:
@@ -156,9 +157,15 b' class _BoundedFloatRangeWidget(_FloatRangeWidget):'
156 self.lower = low
157 self.lower = low
157
158
158
159
159 class FloatRangeSliderWidget(_BoundedFloatRangeWidget):
160 class FloatRangeSlider(_BoundedFloatRange):
160 _view_name = Unicode('FloatSliderView', sync=True)
161 _view_name = Unicode('FloatSliderView', sync=True)
161 orientation = Enum([u'horizontal', u'vertical'], u'horizontal',
162 orientation = Enum([u'horizontal', u'vertical'], u'horizontal',
162 help="Vertical or horizontal.", sync=True)
163 help="Vertical or horizontal.", sync=True)
163 range = Bool(True, help="Display a range selector", sync=True)
164 range = Bool(True, help="Display a range selector", sync=True)
164 readout = Bool(True, help="Display the current value of the slider next to it.", sync=True)
165 readout = Bool(True, help="Display the current value of the slider next to it.", sync=True)
166
167 # Remove in IPython 4.0
168 FloatTextWidget = DeprecatedClass(FloatText, 'FloatTextWidget')
169 BoundedFloatTextWidget = DeprecatedClass(BoundedFloatText, 'BoundedFloatTextWidget')
170 FloatSliderWidget = DeprecatedClass(FloatSlider, 'FloatSliderWidget')
171 FloatProgressWidget = DeprecatedClass(FloatProgress, 'FloatProgressWidget')
@@ -1,4 +1,4 b''
1 """ImageWidget 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 """
@@ -17,11 +17,18 b' import base64'
17
17
18 from .widget import DOMWidget
18 from .widget import DOMWidget
19 from IPython.utils.traitlets import Unicode, CUnicode, Bytes
19 from IPython.utils.traitlets import Unicode, CUnicode, Bytes
20 from IPython.utils.warn import DeprecatedClass
20
21
21 #-----------------------------------------------------------------------------
22 #-----------------------------------------------------------------------------
22 # Classes
23 # Classes
23 #-----------------------------------------------------------------------------
24 #-----------------------------------------------------------------------------
24 class ImageWidget(DOMWidget):
25 class Image(DOMWidget):
26 """Displays an image as a widget.
27
28 The `value` of this widget accepts a byte string. The byte string is the raw
29 image data that you want the browser to display. You can explicitly define
30 the format of the byte string using the `format` trait (which defaults to
31 "png")."""
25 _view_name = Unicode('ImageView', sync=True)
32 _view_name = Unicode('ImageView', sync=True)
26
33
27 # Define the custom state properties to sync with the front-end
34 # Define the custom state properties to sync with the front-end
@@ -33,3 +40,7 b' class ImageWidget(DOMWidget):'
33 value = Bytes()
40 value = Bytes()
34 def _value_changed(self, name, old, new):
41 def _value_changed(self, name, old, new):
35 self._b64value = base64.b64encode(new)
42 self._b64value = base64.b64encode(new)
43
44
45 # Remove in IPython 4.0
46 ImageWidget = DeprecatedClass(Image, 'ImageWidget')
@@ -1,4 +1,4 b''
1 """IntWidget class.
1 """Int class.
2
2
3 Represents an unbounded int using a widget.
3 Represents an unbounded int using a widget.
4 """
4 """
@@ -15,17 +15,21 b' Represents an unbounded int using a widget.'
15 #-----------------------------------------------------------------------------
15 #-----------------------------------------------------------------------------
16 from .widget import DOMWidget
16 from .widget import DOMWidget
17 from IPython.utils.traitlets import Unicode, CInt, Bool, Enum, Tuple
17 from IPython.utils.traitlets import Unicode, CInt, Bool, Enum, Tuple
18 from IPython.utils.warn import DeprecatedClass
18
19
19 #-----------------------------------------------------------------------------
20 #-----------------------------------------------------------------------------
20 # Classes
21 # Classes
21 #-----------------------------------------------------------------------------
22 #-----------------------------------------------------------------------------
22 class _IntWidget(DOMWidget):
23 class _Int(DOMWidget):
23 value = CInt(0, help="Int value", sync=True)
24 """Base class used to create widgets that represent an int."""
25 value = CInt(0, help="Int value", sync=True)
24 disabled = Bool(False, help="Enable or disable user changes", sync=True)
26 disabled = Bool(False, help="Enable or disable user changes", sync=True)
25 description = Unicode(help="Description of the value this widget represents", sync=True)
27 description = Unicode(help="Description of the value this widget represents", sync=True)
26
28
27
29
28 class _BoundedIntWidget(_IntWidget):
30 class _BoundedInt(_Int):
31 """Base class used to create widgets that represent a int that is bounded
32 by a minium and maximum."""
29 step = CInt(1, help="Minimum step that the value can take (ignored by some views)", sync=True)
33 step = CInt(1, help="Minimum step that the value can take (ignored by some views)", sync=True)
30 max = CInt(100, help="Max value", sync=True)
34 max = CInt(100, help="Max value", sync=True)
31 min = CInt(0, help="Min value", sync=True)
35 min = CInt(0, help="Min value", sync=True)
@@ -41,26 +45,30 b' class _BoundedIntWidget(_IntWidget):'
41 self.value = min(max(new, self.min), self.max)
45 self.value = min(max(new, self.min), self.max)
42
46
43
47
44 class IntTextWidget(_IntWidget):
48 class IntText(_Int):
49 """Textbox widget that represents a int."""
45 _view_name = Unicode('IntTextView', sync=True)
50 _view_name = Unicode('IntTextView', sync=True)
46
51
47
52
48 class BoundedIntTextWidget(_BoundedIntWidget):
53 class BoundedIntText(_BoundedInt):
54 """Textbox widget that represents a int bounded by a minimum and maximum value."""
49 _view_name = Unicode('IntTextView', sync=True)
55 _view_name = Unicode('IntTextView', sync=True)
50
56
51
57
52 class IntSliderWidget(_BoundedIntWidget):
58 class IntSlider(_BoundedInt):
59 """Slider widget that represents a int bounded by a minimum and maximum value."""
53 _view_name = Unicode('IntSliderView', sync=True)
60 _view_name = Unicode('IntSliderView', sync=True)
54 orientation = Enum([u'horizontal', u'vertical'], u'horizontal',
61 orientation = Enum([u'horizontal', u'vertical'], u'horizontal',
55 help="Vertical or horizontal.", sync=True)
62 help="Vertical or horizontal.", sync=True)
56 range = Bool(False, help="Display a range selector", sync=True)
63 range = Bool(False, help="Display a range selector", sync=True)
57 readout = Bool(True, help="Display the current value of the slider next to it.", sync=True)
64 readout = Bool(True, help="Display the current value of the slider next to it.", sync=True)
58
65
59
66
60 class IntProgressWidget(_BoundedIntWidget):
67 class IntProgress(_BoundedInt):
68 """Progress bar that represents a int bounded by a minimum and maximum value."""
61 _view_name = Unicode('ProgressView', sync=True)
69 _view_name = Unicode('ProgressView', sync=True)
62
70
63 class _IntRangeWidget(_IntWidget):
71 class _IntRange(_Int):
64 value = Tuple(CInt, CInt, default_value=(0, 1), help="Tuple of (lower, upper) bounds", sync=True)
72 value = Tuple(CInt, CInt, default_value=(0, 1), help="Tuple of (lower, upper) bounds", sync=True)
65 lower = CInt(0, help="Lower bound", sync=False)
73 lower = CInt(0, help="Lower bound", sync=False)
66 upper = CInt(1, help="Upper bound", sync=False)
74 upper = CInt(1, help="Upper bound", sync=False)
@@ -89,14 +97,14 b' class _IntRangeWidget(_IntWidget):'
89 elif name == 'upper':
97 elif name == 'upper':
90 self.value = (self.value[0], new)
98 self.value = (self.value[0], new)
91
99
92 class _BoundedIntRangeWidget(_IntRangeWidget):
100 class _BoundedIntRange(_IntRange):
93 step = CInt(1, help="Minimum step that the value can take (ignored by some views)", sync=True)
101 step = CInt(1, help="Minimum step that the value can take (ignored by some views)", sync=True)
94 max = CInt(100, help="Max value", sync=True)
102 max = CInt(100, help="Max value", sync=True)
95 min = CInt(0, help="Min value", sync=True)
103 min = CInt(0, help="Min value", sync=True)
96
104
97 def __init__(self, *pargs, **kwargs):
105 def __init__(self, *pargs, **kwargs):
98 any_value_given = 'value' in kwargs or 'upper' in kwargs or 'lower' in kwargs
106 any_value_given = 'value' in kwargs or 'upper' in kwargs or 'lower' in kwargs
99 _IntRangeWidget.__init__(self, *pargs, **kwargs)
107 _IntRange.__init__(self, *pargs, **kwargs)
100
108
101 # ensure a minimal amount of sanity
109 # ensure a minimal amount of sanity
102 if self.min > self.max:
110 if self.min > self.max:
@@ -153,9 +161,15 b' class _BoundedIntRangeWidget(_IntRangeWidget):'
153 self.upper = high
161 self.upper = high
154 self.lower = low
162 self.lower = low
155
163
156 class IntRangeSliderWidget(_BoundedIntRangeWidget):
164 class IntRangeSlider(_BoundedIntRange):
157 _view_name = Unicode('IntSliderView', sync=True)
165 _view_name = Unicode('IntSliderView', sync=True)
158 orientation = Enum([u'horizontal', u'vertical'], u'horizontal',
166 orientation = Enum([u'horizontal', u'vertical'], u'horizontal',
159 help="Vertical or horizontal.", sync=True)
167 help="Vertical or horizontal.", sync=True)
160 range = Bool(True, help="Display a range selector", sync=True)
168 range = Bool(True, help="Display a range selector", sync=True)
161 readout = Bool(True, help="Display the current value of the slider next to it.", sync=True)
169 readout = Bool(True, help="Display the current value of the slider next to it.", sync=True)
170
171 # Remove in IPython 4.0
172 IntTextWidget = DeprecatedClass(IntText, 'IntTextWidget')
173 BoundedIntTextWidget = DeprecatedClass(BoundedIntText, 'BoundedIntTextWidget')
174 IntSliderWidget = DeprecatedClass(IntSlider, 'IntSliderWidget')
175 IntProgressWidget = DeprecatedClass(IntProgress, 'IntProgressWidget')
@@ -1,4 +1,4 b''
1 """SelectionWidget classes.
1 """Selection classes.
2
2
3 Represents an enumeration using a widget.
3 Represents an enumeration using a widget.
4 """
4 """
@@ -20,11 +20,12 b' from threading import Lock'
20 from .widget import DOMWidget
20 from .widget import DOMWidget
21 from IPython.utils.traitlets import Unicode, List, Bool, Any, Dict, TraitError
21 from IPython.utils.traitlets import Unicode, List, Bool, Any, Dict, TraitError
22 from IPython.utils.py3compat import unicode_type
22 from IPython.utils.py3compat import unicode_type
23 from IPython.utils.warn import DeprecatedClass
23
24
24 #-----------------------------------------------------------------------------
25 #-----------------------------------------------------------------------------
25 # SelectionWidget
26 # SelectionWidget
26 #-----------------------------------------------------------------------------
27 #-----------------------------------------------------------------------------
27 class _SelectionWidget(DOMWidget):
28 class _Selection(DOMWidget):
28 """Base class for Selection widgets
29 """Base class for Selection widgets
29
30
30 ``values`` can be specified as a list or dict. If given as a list,
31 ``values`` can be specified as a list or dict. If given as a list,
@@ -109,17 +110,30 b' class _SelectionWidget(DOMWidget):'
109 self.value_lock.release()
110 self.value_lock.release()
110
111
111
112
112 class ToggleButtonsWidget(_SelectionWidget):
113 class ToggleButtons(_Selection):
114 """Group of toggle buttons that represent an enumeration. Only one toggle
115 button can be toggled at any point in time."""
113 _view_name = Unicode('ToggleButtonsView', sync=True)
116 _view_name = Unicode('ToggleButtonsView', sync=True)
114
117
115
118
116 class DropdownWidget(_SelectionWidget):
119 class Dropdown(_Selection):
120 """Allows you to select a single item from a dropdown."""
117 _view_name = Unicode('DropdownView', sync=True)
121 _view_name = Unicode('DropdownView', sync=True)
118
122
119
123
120 class RadioButtonsWidget(_SelectionWidget):
124 class RadioButtons(_Selection):
125 """Group of radio buttons that represent an enumeration. Only one radio
126 button can be toggled at any point in time."""
121 _view_name = Unicode('RadioButtonsView', sync=True)
127 _view_name = Unicode('RadioButtonsView', sync=True)
122
128
123
129
124 class SelectWidget(_SelectionWidget):
130 class Select(_Selection):
131 """Listbox that only allows one item to be selected at any given time."""
125 _view_name = Unicode('SelectView', sync=True)
132 _view_name = Unicode('SelectView', sync=True)
133
134
135 # Remove in IPython 4.0
136 ToggleButtonsWidget = DeprecatedClass(ToggleButtons, 'ToggleButtonsWidget')
137 DropdownWidget = DeprecatedClass(Dropdown, 'DropdownWidget')
138 RadioButtonsWidget = DeprecatedClass(RadioButtons, 'RadioButtonsWidget')
139 SelectWidget = DeprecatedClass(Select, 'SelectWidget')
@@ -1,4 +1,4 b''
1 """SelectionContainerWidget 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.
@@ -14,13 +14,15 b' pages.'
14 #-----------------------------------------------------------------------------
14 #-----------------------------------------------------------------------------
15 # Imports
15 # Imports
16 #-----------------------------------------------------------------------------
16 #-----------------------------------------------------------------------------
17 from .widget_container import ContainerWidget
17 from .widget_box import Box
18 from IPython.utils.traitlets import Unicode, Dict, CInt
18 from IPython.utils.traitlets import Unicode, Dict, CInt
19 from IPython.utils.warn import DeprecatedClass
19
20
20 #-----------------------------------------------------------------------------
21 #-----------------------------------------------------------------------------
21 # Classes
22 # Classes
22 #-----------------------------------------------------------------------------
23 #-----------------------------------------------------------------------------
23 class _SelectionContainerWidget(ContainerWidget):
24 class _SelectionContainer(Box):
25 """Base class used to display multiple child widgets."""
24 _titles = Dict(help="Titles of the pages", sync=True)
26 _titles = Dict(help="Titles of the pages", sync=True)
25 selected_index = CInt(0, sync=True)
27 selected_index = CInt(0, sync=True)
26
28
@@ -50,9 +52,16 b' class _SelectionContainerWidget(ContainerWidget):'
50 return None
52 return None
51
53
52
54
53 class AccordionWidget(_SelectionContainerWidget):
55 class Accordion(_SelectionContainer):
56 """Displays children each on a separate accordion page."""
54 _view_name = Unicode('AccordionView', sync=True)
57 _view_name = Unicode('AccordionView', sync=True)
55
58
56
59
57 class TabWidget(_SelectionContainerWidget):
60 class Tab(_SelectionContainer):
61 """Displays children each on a separate accordion tab."""
58 _view_name = Unicode('TabView', sync=True)
62 _view_name = Unicode('TabView', sync=True)
63
64
65 # Remove in IPython 4.0
66 AccordionWidget = DeprecatedClass(Accordion, 'AccordionWidget')
67 TabWidget = DeprecatedClass(Tab, 'TabWidget')
@@ -1,4 +1,4 b''
1 """StringWidget class.
1 """String class.
2
2
3 Represents a unicode string using a widget.
3 Represents a unicode string using a widget.
4 """
4 """
@@ -15,37 +15,44 b' Represents a unicode string using a widget.'
15 #-----------------------------------------------------------------------------
15 #-----------------------------------------------------------------------------
16 from .widget import DOMWidget, CallbackDispatcher
16 from .widget import DOMWidget, CallbackDispatcher
17 from IPython.utils.traitlets import Unicode, Bool
17 from IPython.utils.traitlets import Unicode, Bool
18 from IPython.utils.warn import DeprecatedClass
18
19
19 #-----------------------------------------------------------------------------
20 #-----------------------------------------------------------------------------
20 # Classes
21 # Classes
21 #-----------------------------------------------------------------------------
22 #-----------------------------------------------------------------------------
22 class _StringWidget(DOMWidget):
23 class _String(DOMWidget):
24 """Base class used to create widgets that represent a string."""
23 value = Unicode(help="String value", sync=True)
25 value = Unicode(help="String value", sync=True)
24 disabled = Bool(False, help="Enable or disable user changes", sync=True)
26 disabled = Bool(False, help="Enable or disable user changes", sync=True)
25 description = Unicode(help="Description of the value this widget represents", sync=True)
27 description = Unicode(help="Description of the value this widget represents", sync=True)
26 placeholder = Unicode("", help="Placeholder text to display when nothing has been typed", sync=True)
28 placeholder = Unicode("", help="Placeholder text to display when nothing has been typed", sync=True)
27
29
28
30
29 class HTMLWidget(_StringWidget):
31 class HTML(_String):
32 """Renders the string `value` as HTML."""
30 _view_name = Unicode('HTMLView', sync=True)
33 _view_name = Unicode('HTMLView', sync=True)
31
34
32
35
33 class LatexWidget(_StringWidget):
36 class Latex(_String):
37 """Renders math inside the string `value` as Latex (requires $ $ or $$ $$
38 and similar latex tags)."""
34 _view_name = Unicode('LatexView', sync=True)
39 _view_name = Unicode('LatexView', sync=True)
35
40
36
41
37 class TextareaWidget(_StringWidget):
42 class Textarea(_String):
43 """Multiline text area widget."""
38 _view_name = Unicode('TextareaView', sync=True)
44 _view_name = Unicode('TextareaView', sync=True)
39
45
40 def scroll_to_bottom(self):
46 def scroll_to_bottom(self):
41 self.send({"method": "scroll_to_bottom"})
47 self.send({"method": "scroll_to_bottom"})
42
48
43
49
44 class TextWidget(_StringWidget):
50 class Text(_String):
51 """Single line textbox widget."""
45 _view_name = Unicode('TextView', sync=True)
52 _view_name = Unicode('TextView', sync=True)
46
53
47 def __init__(self, **kwargs):
54 def __init__(self, **kwargs):
48 super(TextWidget, self).__init__(**kwargs)
55 super(Text, self).__init__(**kwargs)
49 self._submission_callbacks = CallbackDispatcher()
56 self._submission_callbacks = CallbackDispatcher()
50 self.on_msg(self._handle_string_msg)
57 self.on_msg(self._handle_string_msg)
51
58
@@ -71,3 +78,10 b' class TextWidget(_StringWidget):'
71 remove: bool (optional)
78 remove: bool (optional)
72 Whether to unregister the callback"""
79 Whether to unregister the callback"""
73 self._submission_callbacks.register_callback(callback, remove=remove)
80 self._submission_callbacks.register_callback(callback, remove=remove)
81
82
83 # Remove in IPython 4.0
84 HTMLWidget = DeprecatedClass(HTML, 'HTMLWidget')
85 LatexWidget = DeprecatedClass(Latex, 'LatexWidget')
86 TextareaWidget = DeprecatedClass(Textarea, 'TextareaWidget')
87 TextWidget = DeprecatedClass(Text, 'TextWidget')
@@ -8,7 +8,7 b' pjoin = os.path.join'
8
8
9 from IPython.utils.path import get_ipython_dir
9 from IPython.utils.path import get_ipython_dir
10 from IPython.utils.py3compat import PY3
10 from IPython.utils.py3compat import PY3
11 from IPython.utils.traitlets import HasTraits, List, Unicode, Dict
11 from IPython.utils.traitlets import HasTraits, List, Unicode, Dict, Any
12
12
13 if os.name == 'nt':
13 if os.name == 'nt':
14 programdata = os.environ.get('PROGRAMDATA', None)
14 programdata = os.environ.get('PROGRAMDATA', None)
@@ -36,18 +36,12 b' class KernelSpec(HasTraits):'
36 argv = List()
36 argv = List()
37 display_name = Unicode()
37 display_name = Unicode()
38 language = Unicode()
38 language = Unicode()
39 codemirror_mode = None
39 codemirror_mode = Any() # can be unicode or dict
40 env = Dict()
40 env = Dict()
41
42 resource_dir = Unicode()
41 resource_dir = Unicode()
43
42
44 def __init__(self, resource_dir, argv, display_name, language,
43 def _codemirror_mode_default(self):
45 codemirror_mode=None):
44 return self.language
46 super(KernelSpec, self).__init__(resource_dir=resource_dir, argv=argv,
47 display_name=display_name, language=language,
48 codemirror_mode=codemirror_mode)
49 if not self.codemirror_mode:
50 self.codemirror_mode = self.language
51
45
52 @classmethod
46 @classmethod
53 def from_resource_dir(cls, resource_dir):
47 def from_resource_dir(cls, resource_dir):
@@ -61,3 +61,18 b' def getoutput(cmd):'
61 myError = reg.StandardError
61 myError = reg.StandardError
62 error = myError.ReadToEnd()
62 error = myError.ReadToEnd()
63 return output
63 return output
64
65 def check_pid(pid):
66 """
67 Check if a process with the given PID (pid) exists
68 """
69 try:
70 System.Diagnostics.Process.GetProcessById(pid)
71 # process with given pid is running
72 return True
73 except System.InvalidOperationException:
74 # process wasn't started by this object (but is running)
75 return True
76 except System.ArgumentException:
77 # process with given pid isn't running
78 return False
@@ -23,7 +23,7 b' import sys'
23 if sys.platform == 'win32':
23 if sys.platform == 'win32':
24 from ._process_win32 import _find_cmd, system, getoutput, arg_split, check_pid
24 from ._process_win32 import _find_cmd, system, getoutput, arg_split, check_pid
25 elif sys.platform == 'cli':
25 elif sys.platform == 'cli':
26 from ._process_cli import _find_cmd, system, getoutput, arg_split
26 from ._process_cli import _find_cmd, system, getoutput, arg_split, check_pid
27 else:
27 else:
28 from ._process_posix import _find_cmd, system, getoutput, arg_split, check_pid
28 from ._process_posix import _find_cmd, system, getoutput, arg_split, check_pid
29
29
@@ -406,6 +406,13 b' class TestHasTraits(TestCase):'
406 a = A()
406 a = A()
407 self.assertEqual(a.trait_metadata('i','config_key'), 'MY_VALUE')
407 self.assertEqual(a.trait_metadata('i','config_key'), 'MY_VALUE')
408
408
409 def test_trait_metadata_default(self):
410 class A(HasTraits):
411 i = Int()
412 a = A()
413 self.assertEqual(a.trait_metadata('i', 'config_key'), None)
414 self.assertEqual(a.trait_metadata('i', 'config_key', 'default'), 'default')
415
409 def test_traits(self):
416 def test_traits(self):
410 class A(HasTraits):
417 class A(HasTraits):
411 i = Int
418 i = Int
@@ -458,8 +458,8 b' class TraitType(object):'
458 % (self.name, self.info(), repr_type(value))
458 % (self.name, self.info(), repr_type(value))
459 raise TraitError(e)
459 raise TraitError(e)
460
460
461 def get_metadata(self, key):
461 def get_metadata(self, key, default=None):
462 return getattr(self, '_metadata', {}).get(key, None)
462 return getattr(self, '_metadata', {}).get(key, default)
463
463
464 def set_metadata(self, key, value):
464 def set_metadata(self, key, value):
465 getattr(self, '_metadata', {})[key] = value
465 getattr(self, '_metadata', {})[key] = value
@@ -728,7 +728,7 b' class HasTraits(py3compat.with_metaclass(MetaHasTraits, object)):'
728
728
729 return result
729 return result
730
730
731 def trait_metadata(self, traitname, key):
731 def trait_metadata(self, traitname, key, default=None):
732 """Get metadata values for trait by key."""
732 """Get metadata values for trait by key."""
733 try:
733 try:
734 trait = getattr(self.__class__, traitname)
734 trait = getattr(self.__class__, traitname)
@@ -736,7 +736,7 b' class HasTraits(py3compat.with_metaclass(MetaHasTraits, object)):'
736 raise TraitError("Class %s does not have a trait named %s" %
736 raise TraitError("Class %s does not have a trait named %s" %
737 (self.__class__.__name__, traitname))
737 (self.__class__.__name__, traitname))
738 else:
738 else:
739 return trait.get_metadata(key)
739 return trait.get_metadata(key, default)
740
740
741 #-----------------------------------------------------------------------------
741 #-----------------------------------------------------------------------------
742 # Actual TraitTypes implementations/subclasses
742 # Actual TraitTypes implementations/subclasses
@@ -16,6 +16,7 b" Utilities for warnings. Shoudn't we just use the built in warnings module."
16 from __future__ import print_function
16 from __future__ import print_function
17
17
18 import sys
18 import sys
19 import warnings
19
20
20 from IPython.utils import io
21 from IPython.utils import io
21
22
@@ -65,3 +66,16 b' def fatal(msg,exit_val=1):'
65
66
66 warn(msg,exit_val=exit_val,level=4)
67 warn(msg,exit_val=exit_val,level=4)
67
68
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 = []
@@ -3,23 +3,44 b''
3 # test suite on all supported python versions. To use it, "pip install tox"
3 # test suite on all supported python versions. To use it, "pip install tox"
4 # and then run "tox" from this directory.
4 # and then run "tox" from this directory.
5
5
6 # Building the source distribution requires both fabric's fab binary
7 # (http://www.fabfile.org/) and the lessc binary of the css preprocessor
8 # less (http://lesscss.org/) in the PATH.
9 # "pip install fabric" will install fabric. Less can be installed by
10 # node.js' (http://nodejs.org/) package manager npm:
11 # "npm install -g less".
12
13 # Javascript tests need additional dependencies that can be installed
14 # using node.js' package manager npm:
15 # [*] casperjs: "npm install -g casperjs"
16 # [*] slimerjs: "npm install -g slimerjs"
17 # [*] phantomjs: "npm install -g phantomjs"
18
19 # Note: qt4 versions break some tests with tornado versions >=4.0.
20
6 [tox]
21 [tox]
7 envlist = py27, py33
22 envlist = py27, py33, py34
8
23
9 [testenv]
24 [testenv]
10 deps =
25 deps =
26 pyzmq
11 nose
27 nose
12 mock
28 tornado<4.0
13 tornado
14 jinja2
29 jinja2
15 sphinx
30 sphinx
16 pygments
31 pygments
32 jsonpointer
33 jsonschema
34 mistune
35
17 # To avoid loading IPython module in the current directory, change
36 # To avoid loading IPython module in the current directory, change
18 # current directory to ".tox/py*/tmp" before running test.
37 # current directory to ".tox/py*/tmp" before running test.
19 changedir = {envtmpdir}
38 changedir = {envtmpdir}
20
39
21 commands =
40 commands =
22 # As pip does not treat egg, use easy_install to install PyZMQ.
41 iptest --all
23 # See also: https://github.com/zeromq/pyzmq
42
24 easy_install -q pyzmq
43 [testenv:py27]
25 iptest --all
44 deps=
45 mock
46 {[testenv]deps}
1 NO CONTENT: file was removed
NO CONTENT: file was removed
General Comments 0
You need to be logged in to leave comments. Login now