Merge master

Gordon Ball 12 years ago
commit b8c0afbb55

@ -84,6 +84,9 @@ class KernelActionHandler(IPythonHandler):
class ZMQChannelHandler(AuthenticatedZMQStreamHandler):
def __repr__(self):
return "%s(%s)" % (self.__class__.__name__, getattr(self, 'kernel_id', 'uninitialized'))
def create_stream(self):
km = self.kernel_manager
meth = getattr(km, 'connect_%s' % self.channel)
@ -145,6 +148,12 @@ class ZMQChannelHandler(AuthenticatedZMQStreamHandler):
self.zmq_stream.on_recv(self._on_zmq_reply)
def on_message(self, msg):
if self.zmq_stream is None:
return
elif self.zmq_stream.closed():
self.log.info("%s closed, closing websocket.", self)
self.close()
return
msg = json.loads(msg)
self.session.send(self.zmq_stream, msg)

@ -184,6 +184,30 @@ Browsers not listed, including Safari, are supported via the styling under the
justify-content: center;
}
.hbox.baseline,
.vbox.baseline,
.baseline {
/* Old browsers */
-webkit-box-pack: baseline;
-moz-box-pack: baseline;
box-pack: baseline;
/* Modern browsers */
justify-content: baseline;
}
.hbox.stretch,
.vbox.stretch,
.stretch {
/* Old browsers */
-webkit-box-pack: stretch;
-moz-box-pack: stretch;
box-pack: stretch;
/* Modern browsers */
justify-content: stretch;
}
.hbox.align-start,
.vbox.align-start,
.align-start {
@ -219,3 +243,27 @@ Browsers not listed, including Safari, are supported via the styling under the
/* Modern browsers */
align-items: center;
}
.hbox.align-baseline,
.vbox.align-baseline,
.align-baseline {
/* Old browsers */
-webkit-box-align: baseline;
-moz-box-align: baseline;
box-align: baseline;
/* Modern browsers */
align-items: baseline;
}
.hbox.align-stretch,
.vbox.align-stretch,
.align-stretch {
/* Old browsers */
-webkit-box-align: stretch;
-moz-box-align: stretch;
box-align: stretch;
/* Modern browsers */
align-items: stretch;
}

@ -54,9 +54,19 @@ define([
return;
}
var ks = this.kernelspecs[kernel_name];
try {
this.notebook.start_session(kernel_name);
} catch (e) {
if (e.name === 'SessionAlreadyStarting') {
console.log("Cannot change kernel while waiting for pending session start.");
} else {
// unhandled error
throw e;
}
// only trigger spec_changed if change was successful
return;
}
this.events.trigger('spec_changed.Kernel', ks);
this.notebook.session.delete();
this.notebook.start_session(kernel_name);
};
KernelSelector.prototype.bind_events = function() {

@ -157,12 +157,13 @@ define([
}
});
this.element.find('#kill_and_exit').click(function () {
that.notebook.session.delete();
setTimeout(function(){
var close_window = function () {
// allow closing of new tabs in Chromium, impossible in FF
window.open('', '_self', '');
window.close();
}, 500);
};
// finish with close on success or failure
that.notebook.session.delete(close_window, close_window);
});
// Edit
this.element.find('#cut_cell').click(function () {

@ -62,6 +62,7 @@ define([
this.save_widget = options.save_widget;
this.tooltip = new tooltip.Tooltip(this.events);
this.ws_url = options.ws_url;
this._session_starting = false;
// default_kernel_name is a temporary measure while we implement proper
// kernel selection and delayed start. Do not rely on it.
this.default_kernel_name = 'python';
@ -1525,9 +1526,38 @@ define([
* @method start_session
*/
Notebook.prototype.start_session = function (kernel_name) {
var that = this;
if (kernel_name === undefined) {
kernel_name = this.default_kernel_name;
}
if (this._session_starting) {
throw new session.SessionAlreadyStarting();
}
this._session_starting = true;
if (this.session !== null) {
var s = this.session;
this.session = null;
// need to start the new session in a callback after delete,
// because javascript does not guarantee the ordering of AJAX requests (?!)
s.delete(function () {
// on successful delete, start new session
that._session_starting = false;
that.start_session(kernel_name);
}, function (jqXHR, status, error) {
// log the failed delete, but still create a new session
// 404 just means it was already deleted by someone else,
// but other errors are possible.
utils.log_ajax_error(jqXHR, status, error);
that._session_starting = false;
that.start_session(kernel_name);
}
);
return;
}
this.session = new session.Session({
base_url: this.base_url,
ws_url: this.ws_url,
@ -1539,7 +1569,10 @@ define([
kernel_name: kernel_name,
notebook: this});
this.session.start($.proxy(this._session_started, this));
this.session.start(
$.proxy(this._session_started, this),
$.proxy(this._session_start_failed, this)
);
};
@ -1548,7 +1581,8 @@ define([
* comm manager to the widget manager
*
*/
Notebook.prototype._session_started = function(){
Notebook.prototype._session_started = function (){
this._session_starting = false;
this.kernel = this.session.kernel;
var ncells = this.ncells();
for (var i=0; i<ncells; i++) {
@ -1558,7 +1592,11 @@ define([
}
}
};
Notebook.prototype._session_start_failed = function (jqxhr, status, error){
this._session_starting = false;
utils.log_ajax_error(jqxhr, status, error);
};
/**
* Prompt the user to restart the IPython kernel.
*

@ -109,6 +109,12 @@ define([
knw.set_message("Restarting kernel", 2000);
});
this.events.on('status_dead.Kernel',function () {
that.save_widget.update_document_title();
knw.danger("Dead kernel");
$kernel_ind_icon.attr('class','kernel_dead_icon').attr('title','Kernel Dead');
});
this.events.on('status_interrupting.Kernel',function () {
knw.set_message("Interrupting kernel", 2000);
});
@ -118,6 +124,8 @@ define([
$kernel_ind_icon.attr('class','kernel_busy_icon').attr('title','Kernel Busy');
this.events.on('status_started.Kernel', function (evt, data) {
knw.info("Websockets Connected", 500);
that.events.trigger('status_busy.Kernel');
data.kernel.kernel_info(function () {
that.events.trigger('status_idle.Kernel');
});
@ -153,8 +161,13 @@ define([
var ws_url = data.ws_url;
var early = data.early;
var msg;
$kernel_ind_icon
.attr('class', 'kernel_disconnected_icon')
.attr('title', 'No Connection to Kernel');
if (!early) {
knw.set_message('Reconnecting WebSockets', 1000);
knw.warning('Reconnecting');
setTimeout(function () {
kernel.start_channels();
}, 5000);
@ -173,7 +186,7 @@ define([
"OK": {},
"Reconnect": {
click: function () {
knw.set_message('Reconnecting WebSockets', 1000);
knw.warning('Reconnecting');
setTimeout(function () {
kernel.start_channels();
}, 5000);

@ -43,4 +43,12 @@
.icon(@fa-var-circle);
}
.kernel_dead_icon:before {
.icon(@fa-var-bomb);
}
.kernel_disconnected_icon:before {
.icon(@fa-var-chain-broken);
}

@ -179,10 +179,18 @@ define([
that._websocket_closed(ws_host_url, false);
}
};
var ws_error = function(evt){
if (already_called_onclose){
return;
}
already_called_onclose = true;
that._websocket_closed(ws_host_url, false);
};
var channels = [this.shell_channel, this.iopub_channel, this.stdin_channel];
for (var i=0; i < channels.length; i++) {
channels[i].onopen = $.proxy(this._ws_opened, this);
channels[i].onclose = ws_closed_early;
channels[i].onerror = ws_error;
}
// switch from early-close to late-close message after 1s
setTimeout(function() {
@ -211,7 +219,7 @@ define([
var channels = [this.shell_channel, this.iopub_channel, this.stdin_channel];
for (var i=0; i < channels.length; i++) {
// if any channel is not ready, don't trigger event.
if ( !channels[i].readyState ) return;
if ( channels[i].readyState == WebSocket.OPEN ) return;
}
// all events ready, trigger started event.
this.events.trigger('status_started.Kernel', {kernel: this});
@ -385,15 +393,17 @@ define([
};
Kernel.prototype.kill = function () {
Kernel.prototype.kill = function (success, error) {
if (this.running) {
this.running = false;
var settings = {
cache : false,
type : "DELETE",
error : utils.log_ajax_error,
success : success,
error : error || utils.log_ajax_error,
};
$.ajax(utils.url_join_encode(this.kernel_url), settings);
this.stop_channels();
}
};

@ -21,7 +21,7 @@ define([
this.ws_url = options.ws_url;
};
Session.prototype.start = function(callback) {
Session.prototype.start = function (success, error) {
var that = this;
var model = {
notebook : {
@ -40,11 +40,17 @@ define([
dataType : "json",
success : function (data, status, xhr) {
that._handle_start_success(data);
if (callback) {
callback(data, status, xhr);
if (success) {
success(data, status, xhr);
}
},
error : utils.log_ajax_error,
error : function (xhr, status, err) {
that._handle_start_failure(xhr, status, err);
if (error !== undefined) {
error(xhr, status, err);
}
utils.log_ajax_error(xhr, status, err);
}
};
var url = utils.url_join_encode(this.base_url, 'api/sessions');
$.ajax(url, settings);
@ -71,15 +77,19 @@ define([
$.ajax(url, settings);
};
Session.prototype.delete = function() {
Session.prototype.delete = function (success, error) {
var settings = {
processData : false,
cache : false,
type : "DELETE",
dataType : "json",
error : utils.log_ajax_error,
success : success,
error : error || utils.log_ajax_error,
};
this.kernel.running = false;
if (this.kernel) {
this.kernel.running = false;
this.kernel.stop_channels();
}
var url = utils.url_join_encode(this.base_url, 'api/sessions', this.id);
$.ajax(url, settings);
};
@ -99,6 +109,11 @@ define([
this.kernel = new kernel.Kernel(kernel_service_url, this.ws_url, this.notebook, this.kernel_name);
this.kernel._kernel_started(data.kernel);
};
Session.prototype._handle_start_failure = function (xhr, status, error) {
this.events.trigger('start_failed.Session', [this, xhr, status, error]);
this.events.trigger('status_dead.Kernel');
};
/**
* Prompt the user to restart the IPython kernel.
@ -118,8 +133,18 @@ define([
this.kernel.kill();
};
var SessionAlreadyStarting = function (message) {
this.name = "SessionAlreadyStarting";
this.message = (message || "");
};
SessionAlreadyStarting.prototype = Error.prototype;
// For backwards compatability.
IPython.Session = Session;
return {'Session': Session};
return {
Session: Session,
SessionAlreadyStarting: SessionAlreadyStarting,
};
});

@ -1501,7 +1501,7 @@ div.cell.text_cell.rendered {
box-pack: start;
/* Modern browsers */
justify-content: flex-start;
/* ContainerWidget */
/* Box */
box-sizing: border-box;
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
@ -1532,7 +1532,7 @@ div.cell.text_cell.rendered {
box-pack: start;
/* Modern browsers */
justify-content: flex-start;
/* ContainerWidget */
/* Box */
box-sizing: border-box;
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
@ -1584,7 +1584,7 @@ div.cell.text_cell.rendered {
box-pack: start;
/* Modern browsers */
justify-content: flex-start;
/* ContainerWidget */
/* Box */
box-sizing: border-box;
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
@ -1639,7 +1639,7 @@ div.cell.text_cell.rendered {
box-pack: start;
/* Modern browsers */
justify-content: flex-start;
/* ContainerWidget */
/* Box */
box-sizing: border-box;
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
@ -1691,7 +1691,7 @@ div.cell.text_cell.rendered {
box-pack: start;
/* Modern browsers */
justify-content: flex-start;
/* ContainerWidget */
/* Box */
box-sizing: border-box;
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
@ -1724,7 +1724,7 @@ div.cell.text_cell.rendered {
width: 30px;
}
.widget-modal {
/* ContainerWidget - ModalView */
/* Box - ModalView */
overflow: hidden;
position: absolute !important;
top: 0px;
@ -1732,11 +1732,11 @@ div.cell.text_cell.rendered {
margin-left: 0px !important;
}
.widget-modal-body {
/* ContainerWidget - ModalView Body */
/* Box - ModalView Body */
max-height: none !important;
}
.widget-container {
/* ContainerWidget */
.widget-box {
/* Box */
box-sizing: border-box;
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;

@ -9273,7 +9273,7 @@ div.cell.text_cell.rendered {
box-pack: start;
/* Modern browsers */
justify-content: flex-start;
/* ContainerWidget */
/* Box */
box-sizing: border-box;
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
@ -9304,7 +9304,7 @@ div.cell.text_cell.rendered {
box-pack: start;
/* Modern browsers */
justify-content: flex-start;
/* ContainerWidget */
/* Box */
box-sizing: border-box;
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
@ -9356,7 +9356,7 @@ div.cell.text_cell.rendered {
box-pack: start;
/* Modern browsers */
justify-content: flex-start;
/* ContainerWidget */
/* Box */
box-sizing: border-box;
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
@ -9411,7 +9411,7 @@ div.cell.text_cell.rendered {
box-pack: start;
/* Modern browsers */
justify-content: flex-start;
/* ContainerWidget */
/* Box */
box-sizing: border-box;
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
@ -9463,7 +9463,7 @@ div.cell.text_cell.rendered {
box-pack: start;
/* Modern browsers */
justify-content: flex-start;
/* ContainerWidget */
/* Box */
box-sizing: border-box;
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
@ -9496,7 +9496,7 @@ div.cell.text_cell.rendered {
width: 30px;
}
.widget-modal {
/* ContainerWidget - ModalView */
/* Box - ModalView */
overflow: hidden;
position: absolute !important;
top: 0px;
@ -9504,11 +9504,11 @@ div.cell.text_cell.rendered {
margin-left: 0px !important;
}
.widget-modal-body {
/* ContainerWidget - ModalView Body */
/* Box - ModalView Body */
max-height: none !important;
}
.widget-container {
/* ContainerWidget */
.widget-box {
/* Box */
box-sizing: border-box;
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
@ -10006,6 +10006,38 @@ ul#help_menu li a i {
.kernel_busy_icon:before.pull-right {
margin-left: .3em;
}
.kernel_dead_icon:before {
display: inline-block;
font-family: FontAwesome;
font-style: normal;
font-weight: normal;
line-height: 1;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
content: "\f1e2";
}
.kernel_dead_icon:before.pull-left {
margin-right: .3em;
}
.kernel_dead_icon:before.pull-right {
margin-left: .3em;
}
.kernel_disconnected_icon:before {
display: inline-block;
font-family: FontAwesome;
font-style: normal;
font-weight: normal;
line-height: 1;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
content: "\f127";
}
.kernel_disconnected_icon:before.pull-left {
margin-right: .3em;
}
.kernel_disconnected_icon:before.pull-right {
margin-left: .3em;
}
.notification_widget {
color: #777777;
padding: 1px 12px;

@ -5,7 +5,7 @@ define([
"widgets/js/manager",
"widgets/js/widget_bool",
"widgets/js/widget_button",
"widgets/js/widget_container",
"widgets/js/widget_box",
"widgets/js/widget_float",
"widgets/js/widget_image",
"widgets/js/widget_int",

@ -7,11 +7,10 @@ define([
"bootstrap",
], function(widget, $){
var ContainerView = widget.DOMWidgetView.extend({
var BoxView = widget.DOMWidgetView.extend({
initialize: function(){
// Public constructor
ContainerView.__super__.initialize.apply(this, arguments);
this.update_children([], this.model.get('children'));
BoxView.__super__.initialize.apply(this, arguments);
this.model.on('change:children', function(model, value) {
this.update_children(model.previous('children'), value);
}, this);
@ -19,7 +18,9 @@ define([
render: function(){
// Called when view is rendered.
this.$el.addClass('widget-container').addClass('vbox');
this.$box = this.$el;
this.$box.addClass('widget-box');
this.update_children([], this.model.get('children'));
},
update_children: function(old_list, new_list) {
@ -37,7 +38,7 @@ define([
add_child_model: function(model) {
// Called when a model is added to the children list.
var view = this.create_child_view(model);
this.$el.append(view.$el);
this.$box.append(view.$el);
// Trigger the displayed event of the child view.
this.after_displayed(function() {
@ -45,9 +46,54 @@ define([
});
},
});
var PopupView = widget.DOMWidgetView.extend({
var FlexBoxView = BoxView.extend({
render: function(){
FlexBoxView.__super__.render.apply(this);
this.model.on('change:orientation', this.update_orientation, this);
this.model.on('change:flex', this._flex_changed, this);
this.model.on('change:pack', this._pack_changed, this);
this.model.on('change:align', this._align_changed, this);
this._flex_changed();
this._pack_changed();
this._align_changed();
this.update_orientation();
},
update_orientation: function(){
var orientation = this.model.get("orientation");
if (orientation == "vertical") {
this.$box.removeClass("hbox").addClass("vbox");
} else {
this.$box.removeClass("vbox").addClass("hbox");
}
},
_flex_changed: function(){
if (this.model.previous('flex')) {
this.$box.removeClass('box-flex' + this.model.previous('flex'));
}
this.$box.addClass('box-flex' + this.model.get('flex'));
},
_pack_changed: function(){
if (this.model.previous('pack')) {
this.$box.removeClass(this.model.previous('pack'));
}
this.$box.addClass(this.model.get('pack'));
},
_align_changed: function(){
if (this.model.previous('align')) {
this.$box.removeClass('align-' + this.model.previous('align'));
}
this.$box.addClass('align-' + this.model.get('align'));
},
});
var PopupView = BoxView.extend({
render: function(){
// Called when view is rendered.
var that = this;
@ -130,11 +176,11 @@ define([
this.$title = $('<div />')
.addClass('widget-modal-title')
.html("&nbsp;")
.appendTo(this.$title_bar);
this.$body = $('<div />')
.appendTo(this.$title_bar);
this.$box = $('<div />')
.addClass('modal-body')
.addClass('widget-modal-body')
.addClass('widget-container')
.addClass('widget-box')
.addClass('vbox')
.appendTo(this.$window);
@ -149,7 +195,7 @@ define([
this.$window.draggable({handle: '.popover-title', snap: '#notebook, .modal', snapMode: 'both'});
this.$window.resizable();
this.$window.on('resize', function(){
that.$body.outerHeight(that.$window.innerHeight() - that.$title_bar.outerHeight());
that.$box.outerHeight(that.$window.innerHeight() - that.$title_bar.outerHeight());
});
this._shown_once = false;
@ -203,29 +249,6 @@ define([
this.$window.css('z-index', max_zindex);
},
update_children: function(old_list, new_list) {
// Called when the children list is modified.
this.do_diff(old_list, new_list,
$.proxy(this.remove_child_model, this),
$.proxy(this.add_child_model, this));
},
remove_child_model: function(model) {
// Called when a child is removed from children list.
this.pop_child_view(model).remove();
},
add_child_model: function(model) {
// Called when a child is added to children list.
var view = this.create_child_view(model);
this.$body.append(view.$el);
// Trigger the displayed event of the child view.
this.after_displayed(function() {
view.trigger('displayed');
});
},
update: function(){
// Update the contents of this view
//
@ -277,7 +300,8 @@ define([
});
return {
'ContainerView': ContainerView,
'BoxView': BoxView,
'PopupView': PopupView,
'FlexBoxView': FlexBoxView,
};
});

@ -226,7 +226,7 @@
margin : 5px;
.start();
.widget-container();
.widget-box();
}
.widget-hbox {
@ -258,7 +258,7 @@
}
.widget-modal {
/* ContainerWidget - ModalView */
/* Box - ModalView */
overflow : hidden;
position : absolute !important;
top : 0px;
@ -267,12 +267,12 @@
}
.widget-modal-body {
/* ContainerWidget - ModalView Body */
/* Box - ModalView Body */
max-height: none !important;
}
.widget-container {
/* ContainerWidget */
.widget-box {
/* Box */
.border-box-sizing();
.align-start();
}

@ -1,12 +1,12 @@
//
// Miscellaneous javascript tests
// Kernel tests
//
casper.notebook_test(function () {
this.evaluate(function () {
IPython.notebook.kernel.kernel_info(
function(msg){
IPython._kernel_info_response = msg;
IPython._kernel_info_response = msg;
})
});
@ -24,5 +24,41 @@ casper.notebook_test(function () {
this.test.assertTrue( kernel_info_response.msg_type === 'kernel_info_reply', 'Kernel info request return kernel_info_reply');
this.test.assertTrue( kernel_info_response.content !== undefined, 'Kernel_info_reply is not undefined');
});
this.thenEvaluate(function () {
var kernel = IPython.notebook.session.kernel;
IPython._channels = [
kernel.shell_channel,
kernel.iopub_channel,
kernel.stdin_channel
];
kernel.kill();
});
this.waitFor(function () {
return this.evaluate(function(){
for (var i=0; i < IPython._channels.length; i++) {
var ws = IPython._channels[i];
if (ws.readyState !== ws.CLOSED) {
return false;
}
}
return true;
});
});
this.then(function () {
var states = this.evaluate(function() {
var states = [];
for (var i = 0; i < IPython._channels.length; i++) {
states.push(IPython._channels[i].readyState);
}
return states;
});
for (var i = 0; i < states.length; i++) {
this.test.assertEquals(states[i], WebSocket.CLOSED,
"Kernel.kill closes websockets[" + i + "]");
}
});
});

@ -0,0 +1,43 @@
//
// Tests for the Session object
//
casper.notebook_test(function () {
this.evaluate(function () {
var kernel = IPython.notebook.session.kernel;
IPython._channels = [
kernel.shell_channel,
kernel.iopub_channel,
kernel.stdin_channel
];
IPython.notebook.session.delete();
});
this.waitFor(function () {
return this.evaluate(function(){
for (var i=0; i < IPython._channels.length; i++) {
var ws = IPython._channels[i];
if (ws.readyState !== ws.CLOSED) {
return false;
}
}
return true;
});
});
this.then(function () {
var states = this.evaluate(function() {
var states = [];
for (var i = 0; i < IPython._channels.length; i++) {
states.push(IPython._channels[i].readyState);
}
return states;
});
for (var i = 0; i < states.length; i++) {
this.test.assertEquals(states[i], WebSocket.CLOSED,
"Session.delete closes websockets[" + i + "]");
}
});
});

@ -147,7 +147,7 @@ casper.notebook_test(function () {
var textbox = {};
throttle_index = this.append_cell(
'import time\n' +
'textbox = widgets.TextWidget()\n' +
'textbox = widgets.Text()\n' +
'display(textbox)\n' +
'textbox.add_class("my-throttle-textbox", selector="input")\n' +
'def handle_change(name, old, new):\n' +

@ -7,8 +7,8 @@ casper.notebook_test(function () {
this.execute_cell_then(index);
var bool_index = this.append_cell(
'bool_widgets = [widgets.CheckboxWidget(description="Title", value=True),\n' +
' widgets.ToggleButtonWidget(description="Title", value=True)]\n' +
'bool_widgets = [widgets.Checkbox(description="Title", value=True),\n' +
' widgets.ToggleButton(description="Title", value=True)]\n' +
'display(bool_widgets[0])\n' +
'display(bool_widgets[1])\n' +
'print("Success")');

@ -7,8 +7,8 @@ casper.notebook_test(function () {
this.execute_cell_then(index);
var container_index = this.append_cell(
'container = widgets.ContainerWidget()\n' +
'button = widgets.ButtonWidget()\n'+
'container = widgets.Box()\n' +
'button = widgets.Button()\n'+
'container.children = [button]\n'+
'display(container)\n'+
'container.add_class("my-test-class")\n'+
@ -23,7 +23,7 @@ casper.notebook_test(function () {
'Widget subarea exists.');
this.test.assert(this.cell_element_exists(index,
'.widget-area .widget-subarea .widget-container'),
'.widget-area .widget-subarea .widget-box'),
'Widget container exists.');
this.test.assert(this.cell_element_exists(index,
@ -70,7 +70,7 @@ casper.notebook_test(function () {
'Display container child executed with correct output.');
this.test.assert(! this.cell_element_exists(index,
'.widget-area .widget-subarea .widget-container'),
'.widget-area .widget-subarea .widget-box'),
'Parent container not displayed.');
this.test.assert(this.cell_element_exists(index,

@ -7,7 +7,7 @@ casper.notebook_test(function () {
this.execute_cell_then(index);
var button_index = this.append_cell(
'button = widgets.ButtonWidget(description="Title")\n' +
'button = widgets.Button(description="Title")\n' +
'display(button)\n' +
'print("Success")\n' +
'def handle_click(sender):\n' +

@ -9,7 +9,7 @@ casper.notebook_test(function () {
var float_text = {};
float_text.query = '.widget-area .widget-subarea .widget-hbox-single .my-second-float-text';
float_text.index = this.append_cell(
'float_widget = widgets.FloatTextWidget()\n' +
'float_widget = widgets.FloatText()\n' +
'display(float_widget)\n' +
'float_widget.add_class("my-second-float-text", selector="input")\n' +
'print(float_widget.model_id)\n');
@ -59,8 +59,8 @@ casper.notebook_test(function () {
var slider = {};
slider.query = '.widget-area .widget-subarea .widget-hbox-single .slider';
slider.index = this.append_cell(
'floatrange = [widgets.BoundedFloatTextWidget(), \n' +
' widgets.FloatSliderWidget()]\n' +
'floatrange = [widgets.BoundedFloatText(), \n' +
' widgets.FloatSlider()]\n' +
'[display(floatrange[i]) for i in range(2)]\n' +
'print("Success")\n');
this.execute_cell_then(slider.index, function(index){

@ -18,7 +18,7 @@ casper.notebook_test(function () {
var image_index = this.append_cell(
'import base64\n' +
'data = base64.b64decode("' + test_jpg + '")\n' +
'image = widgets.ImageWidget()\n' +
'image = widgets.Image()\n' +
'image.format = "jpeg"\n' +
'image.value = data\n' +
'image.width = "50px"\n' +

@ -9,7 +9,7 @@ casper.notebook_test(function () {
var int_text = {};
int_text.query = '.widget-area .widget-subarea .widget-hbox-single .my-second-int-text';
int_text.index = this.append_cell(
'int_widget = widgets.IntTextWidget()\n' +
'int_widget = widgets.IntText()\n' +
'display(int_widget)\n' +
'int_widget.add_class("my-second-int-text", selector="input")\n' +
'print(int_widget.model_id)\n');

@ -44,10 +44,10 @@ casper.notebook_test(function () {
//values=["' + selection_values + '"[i] for i in range(4)]
selection_index = this.append_cell(
'values=["' + selection_values + '"[i] for i in range(4)]\n' +
'selection = [widgets.DropdownWidget(values=values),\n' +
' widgets.ToggleButtonsWidget(values=values),\n' +
' widgets.RadioButtonsWidget(values=values),\n' +
' widgets.SelectWidget(values=values)]\n' +
'selection = [widgets.Dropdown(values=values),\n' +
' widgets.ToggleButtons(values=values),\n' +
' widgets.RadioButtons(values=values),\n' +
' widgets.Select(values=values)]\n' +
'[display(selection[i]) for i in range(4)]\n' +
'for widget in selection:\n' +
' def handle_change(name,old,new):\n' +

@ -9,10 +9,10 @@ casper.notebook_test(function () {
// Test tab view
var multicontainer1_query = '.widget-area .widget-subarea div div.nav-tabs';
var multicontainer1_index = this.append_cell(
'multicontainer = widgets.TabWidget()\n' +
'page1 = widgets.TextWidget()\n' +
'page2 = widgets.TextWidget()\n' +
'page3 = widgets.TextWidget()\n' +
'multicontainer = widgets.Tab()\n' +
'page1 = widgets.Text()\n' +
'page2 = widgets.Text()\n' +
'page3 = widgets.Text()\n' +
'multicontainer.children = [page1, page2, page3]\n' +
'display(multicontainer)\n' +
'multicontainer.selected_index = 0\n' +
@ -64,10 +64,10 @@ casper.notebook_test(function () {
// Test accordion view
var multicontainer2_query = '.widget-area .widget-subarea .panel-group';
var multicontainer2_index = this.append_cell(
'multicontainer = widgets.AccordionWidget()\n' +
'page1 = widgets.TextWidget()\n' +
'page2 = widgets.TextWidget()\n' +
'page3 = widgets.TextWidget()\n' +
'multicontainer = widgets.Accordion()\n' +
'page1 = widgets.Text()\n' +
'page2 = widgets.Text()\n' +
'page3 = widgets.Text()\n' +
'multicontainer.children = [page1, page2, page3]\n' +
'multicontainer.set_title(2, "good")\n' +
'display(multicontainer)\n' +

@ -7,10 +7,10 @@ casper.notebook_test(function () {
this.execute_cell_then(index);
var string_index = this.append_cell(
'string_widget = [widgets.TextWidget(value = "xyz", placeholder = "abc"),\n' +
' widgets.TextareaWidget(value = "xyz", placeholder = "def"),\n' +
' widgets.HTMLWidget(value = "xyz"),\n' +
' widgets.LatexWidget(value = "$\\\\LaTeX{}$")]\n' +
'string_widget = [widgets.Text(value = "xyz", placeholder = "abc"),\n' +
' widgets.Textarea(value = "xyz", placeholder = "def"),\n' +
' widgets.HTML(value = "xyz"),\n' +
' widgets.Latex(value = "$\\\\LaTeX{}$")]\n' +
'[display(widget) for widget in string_widget]\n'+
'print("Success")');
this.execute_cell_then(string_index, function(index){

@ -1,12 +1,23 @@
from .widget import Widget, DOMWidget, CallbackDispatcher
from .widget_bool import Checkbox, ToggleButton
from .widget_button import Button
from .widget_box import Box, Popup, FlexBox, HBox, VBox
from .widget_float import FloatText, BoundedFloatText, FloatSlider, FloatProgress, FloatRangeSlider
from .widget_image import Image
from .widget_int import IntText, BoundedIntText, IntSlider, IntProgress, IntRangeSlider
from .widget_selection import RadioButtons, ToggleButtons, Dropdown, Select
from .widget_selectioncontainer import Tab, Accordion
from .widget_string import HTML, Latex, Text, Textarea
from .interaction import interact, interactive, fixed
# Deprecated classes
from .widget_bool import CheckboxWidget, ToggleButtonWidget
from .widget_button import ButtonWidget
from .widget_container import ContainerWidget, PopupWidget
from .widget_float import FloatTextWidget, BoundedFloatTextWidget, FloatSliderWidget, FloatProgressWidget, FloatRangeSliderWidget
from .widget_box import ContainerWidget, PopupWidget
from .widget_float import FloatTextWidget, BoundedFloatTextWidget, FloatSliderWidget, FloatProgressWidget
from .widget_image import ImageWidget
from .widget_int import IntTextWidget, BoundedIntTextWidget, IntSliderWidget, IntProgressWidget, IntRangeSliderWidget
from .widget_int import IntTextWidget, BoundedIntTextWidget, IntSliderWidget, IntProgressWidget
from .widget_selection import RadioButtonsWidget, ToggleButtonsWidget, DropdownWidget, SelectWidget
from .widget_selectioncontainer import TabWidget, AccordionWidget
from .widget_string import HTMLWidget, LatexWidget, TextWidget, TextareaWidget
from .interaction import interact, interactive, fixed

@ -21,9 +21,9 @@ except ImportError:
from inspect import getcallargs
from IPython.core.getipython import get_ipython
from IPython.html.widgets import (Widget, TextWidget,
FloatSliderWidget, IntSliderWidget, CheckboxWidget, DropdownWidget,
ContainerWidget, DOMWidget)
from IPython.html.widgets import (Widget, Text,
FloatSlider, IntSlider, Checkbox, Dropdown,
Box, DOMWidget)
from IPython.display import display, clear_output
from IPython.utils.py3compat import string_types, unicode_type
from IPython.utils.traitlets import HasTraits, Any, Unicode
@ -70,17 +70,17 @@ def _get_min_max_value(min, max, value=None, step=None):
def _widget_abbrev_single_value(o):
"""Make widgets from single values, which can be used as parameter defaults."""
if isinstance(o, string_types):
return TextWidget(value=unicode_type(o))
return Text(value=unicode_type(o))
elif isinstance(o, dict):
return DropdownWidget(values=o)
return Dropdown(values=o)
elif isinstance(o, bool):
return CheckboxWidget(value=o)
return Checkbox(value=o)
elif isinstance(o, float):
min, max, value = _get_min_max_value(None, None, o)
return FloatSliderWidget(value=o, min=min, max=max)
return FloatSlider(value=o, min=min, max=max)
elif isinstance(o, int):
min, max, value = _get_min_max_value(None, None, o)
return IntSliderWidget(value=o, min=min, max=max)
return IntSlider(value=o, min=min, max=max)
else:
return None
@ -89,13 +89,13 @@ def _widget_abbrev(o):
float_or_int = (float, int)
if isinstance(o, (list, tuple)):
if o and all(isinstance(x, string_types) for x in o):
return DropdownWidget(values=[unicode_type(k) for k in o])
return Dropdown(values=[unicode_type(k) for k in o])
elif _matches(o, (float_or_int, float_or_int)):
min, max, value = _get_min_max_value(o[0], o[1])
if all(isinstance(_, int) for _ in o):
cls = IntSliderWidget
cls = IntSlider
else:
cls = FloatSliderWidget
cls = FloatSlider
return cls(value=value, min=min, max=max)
elif _matches(o, (float_or_int, float_or_int, float_or_int)):
step = o[2]
@ -103,9 +103,9 @@ def _widget_abbrev(o):
raise ValueError("step must be >= 0, not %r" % step)
min, max, value = _get_min_max_value(o[0], o[1], step=step)
if all(isinstance(_, int) for _ in o):
cls = IntSliderWidget
cls = IntSlider
else:
cls = FloatSliderWidget
cls = FloatSlider
return cls(value=value, min=min, max=max, step=step)
else:
return _widget_abbrev_single_value(o)
@ -176,7 +176,7 @@ def interactive(__interact_f, **kwargs):
f = __interact_f
co = kwargs.pop('clear_output', True)
kwargs_widgets = []
container = ContainerWidget()
container = Box()
container.result = None
container.args = []
container.kwargs = dict()

@ -92,7 +92,7 @@ def test_single_value_string():
c = interactive(f, a=a)
w = c.children[0]
check_widget(w,
cls=widgets.TextWidget,
cls=widgets.Text,
description='a',
value=a,
)
@ -102,7 +102,7 @@ def test_single_value_bool():
c = interactive(f, a=a)
w = c.children[0]
check_widget(w,
cls=widgets.CheckboxWidget,
cls=widgets.Checkbox,
description='a',
value=a,
)
@ -115,7 +115,7 @@ def test_single_value_dict():
c = interactive(f, d=d)
w = c.children[0]
check_widget(w,
cls=widgets.DropdownWidget,
cls=widgets.Dropdown,
description='d',
values=d,
value=next(iter(d.values())),
@ -126,7 +126,7 @@ def test_single_value_float():
c = interactive(f, a=a)
w = c.children[0]
check_widget(w,
cls=widgets.FloatSliderWidget,
cls=widgets.FloatSlider,
description='a',
value=a,
min= -a if a > 0 else 3*a,
@ -141,7 +141,7 @@ def test_single_value_int():
nt.assert_equal(len(c.children), 1)
w = c.children[0]
check_widget(w,
cls=widgets.IntSliderWidget,
cls=widgets.IntSlider,
description='a',
value=a,
min= -a if a > 0 else 3*a,
@ -159,7 +159,7 @@ def test_list_tuple_2_int():
c = interactive(f, tup=(min, max), lis=[min, max])
nt.assert_equal(len(c.children), 2)
d = dict(
cls=widgets.IntSliderWidget,
cls=widgets.IntSlider,
min=min,
max=max,
step=1,
@ -176,7 +176,7 @@ def test_list_tuple_3_int():
c = interactive(f, tup=(min, max, step), lis=[min, max, step])
nt.assert_equal(len(c.children), 2)
d = dict(
cls=widgets.IntSliderWidget,
cls=widgets.IntSlider,
min=min,
max=max,
step=step,
@ -193,7 +193,7 @@ def test_list_tuple_2_float():
c = interactive(f, tup=(min, max), lis=[min, max])
nt.assert_equal(len(c.children), 2)
d = dict(
cls=widgets.FloatSliderWidget,
cls=widgets.FloatSlider,
min=min,
max=max,
step=.1,
@ -212,7 +212,7 @@ def test_list_tuple_3_float():
c = interactive(f, tup=(min, max, step), lis=[min, max, step])
nt.assert_equal(len(c.children), 2)
d = dict(
cls=widgets.FloatSliderWidget,
cls=widgets.FloatSlider,
min=min,
max=max,
step=step,
@ -227,7 +227,7 @@ def test_list_tuple_str():
c = interactive(f, tup=tuple(values), lis=list(values))
nt.assert_equal(len(c.children), 2)
d = dict(
cls=widgets.DropdownWidget,
cls=widgets.Dropdown,
value=first,
values=dvalues
)
@ -253,15 +253,15 @@ def test_defaults():
c = interactive(f)
check_widgets(c,
n=dict(
cls=widgets.IntSliderWidget,
cls=widgets.IntSlider,
value=10,
),
f=dict(
cls=widgets.FloatSliderWidget,
cls=widgets.FloatSlider,
value=4.5,
),
g=dict(
cls=widgets.IntSliderWidget,
cls=widgets.IntSlider,
value=1,
),
)
@ -274,24 +274,24 @@ def test_default_values():
c = interactive(f)
check_widgets(c,
n=dict(
cls=widgets.IntSliderWidget,
cls=widgets.IntSlider,
value=10,
),
f=dict(
cls=widgets.FloatSliderWidget,
cls=widgets.FloatSlider,
value=4.5,
),
g=dict(
cls=widgets.IntSliderWidget,
cls=widgets.IntSlider,
value=5,
),
h=dict(
cls=widgets.DropdownWidget,
cls=widgets.Dropdown,
values={'a': 1, 'b': 2},
value=2
),
j=dict(
cls=widgets.DropdownWidget,
cls=widgets.Dropdown,
values={'hi':'hi', 'there':'there'},
value='there'
),
@ -305,34 +305,34 @@ def test_default_out_of_bounds():
c = interactive(f)
check_widgets(c,
f=dict(
cls=widgets.FloatSliderWidget,
cls=widgets.FloatSlider,
value=5.,
),
h=dict(
cls=widgets.DropdownWidget,
cls=widgets.Dropdown,
values={'a': 1},
value=1,
),
j=dict(
cls=widgets.DropdownWidget,
cls=widgets.Dropdown,
values={'hi':'hi', 'there':'there'},
value='hi',
),
)
def test_annotations():
@annotate(n=10, f=widgets.FloatTextWidget())
@annotate(n=10, f=widgets.FloatText())
def f(n, f):
pass
c = interactive(f)
check_widgets(c,
n=dict(
cls=widgets.IntSliderWidget,
cls=widgets.IntSlider,
value=10,
),
f=dict(
cls=widgets.FloatTextWidget,
cls=widgets.FloatText,
),
)
@ -344,11 +344,11 @@ def test_priority():
c = interactive(f, kwarg='kwarg')
check_widgets(c,
kwarg=dict(
cls=widgets.TextWidget,
cls=widgets.Text,
value='kwarg',
),
annotate=dict(
cls=widgets.TextWidget,
cls=widgets.Text,
value='annotate',
),
)
@ -362,7 +362,7 @@ def test_decorator_kwarg():
nt.assert_equal(len(displayed), 1)
w = displayed[0].children[0]
check_widget(w,
cls=widgets.IntSliderWidget,
cls=widgets.IntSlider,
value=5,
)
@ -375,7 +375,7 @@ def test_decorator_no_call():
nt.assert_equal(len(displayed), 1)
w = displayed[0].children[0]
check_widget(w,
cls=widgets.TextWidget,
cls=widgets.Text,
value='default',
)
@ -388,7 +388,7 @@ def test_call_interact():
nt.assert_equal(len(displayed), 1)
w = displayed[0].children[0]
check_widget(w,
cls=widgets.TextWidget,
cls=widgets.Text,
value='default',
)
@ -401,7 +401,7 @@ def test_call_interact_kwargs():
nt.assert_equal(len(displayed), 1)
w = displayed[0].children[0]
check_widget(w,
cls=widgets.IntSliderWidget,
cls=widgets.IntSlider,
value=10,
)
@ -417,7 +417,7 @@ def test_call_decorated_on_trait_change():
nt.assert_equal(len(displayed), 1)
w = displayed[0].children[0]
check_widget(w,
cls=widgets.TextWidget,
cls=widgets.Text,
value='default',
)
# test calling the function directly
@ -441,7 +441,7 @@ def test_call_decorated_kwargs_on_trait_change():
nt.assert_equal(len(displayed), 1)
w = displayed[0].children[0]
check_widget(w,
cls=widgets.TextWidget,
cls=widgets.Text,
value='kwarg',
)
# test calling the function directly
@ -458,7 +458,7 @@ def test_fixed():
nt.assert_equal(len(c.children), 1)
w = c.children[0]
check_widget(w,
cls=widgets.TextWidget,
cls=widgets.Text,
value='text',
description='b',
)
@ -467,22 +467,22 @@ def test_default_description():
c = interactive(f, b='text')
w = c.children[0]
check_widget(w,
cls=widgets.TextWidget,
cls=widgets.Text,
value='text',
description='b',
)
def test_custom_description():
c = interactive(f, b=widgets.TextWidget(value='text', description='foo'))
c = interactive(f, b=widgets.Text(value='text', description='foo'))
w = c.children[0]
check_widget(w,
cls=widgets.TextWidget,
cls=widgets.Text,
value='text',
description='foo',
)
def test_int_range_logic():
irsw = widgets.IntRangeSliderWidget
irsw = widgets.IntRangeSlider
w = irsw(value=(2, 4), min=0, max=6)
check_widget(w, cls=irsw, value=(2, 4), min=0, max=6)
w.value = (4, 2)
@ -537,7 +537,7 @@ def test_int_range_logic():
def test_float_range_logic():
frsw = widgets.FloatRangeSliderWidget
frsw = widgets.FloatRangeSlider
w = frsw(value=(.2, .4), min=0., max=.6)
check_widget(w, cls=frsw, value=(.2, .4), min=0., max=.6)
w.value = (.4, .2)
@ -588,4 +588,4 @@ def test_float_range_logic():
with nt.assert_raises(ValueError):
frsw(value=(2, 4), lower=3, upper=3)
with nt.assert_raises(ValueError):
frsw(min=.2, max=.1)
frsw(min=.2, max=.1)

@ -1,4 +1,4 @@
"""BoolWidget class.
"""Bool class.
Represents a boolean using a widget.
"""
@ -15,20 +15,29 @@ Represents a boolean using a widget.
#-----------------------------------------------------------------------------
from .widget import DOMWidget
from IPython.utils.traitlets import Unicode, Bool
from IPython.utils.warn import DeprecatedClass
#-----------------------------------------------------------------------------
# Classes
#-----------------------------------------------------------------------------
class _BoolWidget(DOMWidget):
class _Bool(DOMWidget):
"""A base class for creating widgets that represent booleans."""
value = Bool(False, help="Bool value", sync=True)
description = Unicode('', help="Description of the boolean (label).", sync=True)
description = Unicode('', help="Description of the boolean (label).", sync=True)
disabled = Bool(False, help="Enable or disable user changes.", sync=True)
class CheckboxWidget(_BoolWidget):
class Checkbox(_Bool):
"""Displays a boolean `value`."""
_view_name = Unicode('CheckboxView', sync=True)
class ToggleButtonWidget(_BoolWidget):
_view_name = Unicode('ToggleButtonView', sync=True)
class ToggleButton(_Bool):
"""Displays a boolean `value`."""
_view_name = Unicode('ToggleButtonView', sync=True)
# Remove in IPython 4.0
CheckboxWidget = DeprecatedClass(Checkbox, 'CheckboxWidget')
ToggleButtonWidget = DeprecatedClass(ToggleButton, 'ToggleButtonWidget')

@ -0,0 +1,73 @@
"""Box class.
Represents a container that can be used to group other widgets.
"""
# Copyright (c) IPython Development Team.
# Distributed under the terms of the Modified BSD License.
from .widget import DOMWidget
from IPython.utils.traitlets import Unicode, Tuple, TraitError, Int, CaselessStrEnum
from IPython.utils.warn import DeprecatedClass
class Box(DOMWidget):
"""Displays multiple widgets in a group."""
_view_name = Unicode('BoxView', sync=True)
# Child widgets in the container.
# Using a tuple here to force reassignment to update the list.
# When a proper notifying-list trait exists, that is what should be used here.
children = Tuple(sync=True, allow_none=False)
def __init__(self, children = (), **kwargs):
kwargs['children'] = children
super(Box, self).__init__(**kwargs)
self.on_displayed(Box._fire_children_displayed)
def _fire_children_displayed(self):
for child in self.children:
child._handle_displayed()
class Popup(Box):
"""Displays multiple widgets in an in page popup div."""
_view_name = Unicode('PopupView', sync=True)
description = Unicode(sync=True)
button_text = Unicode(sync=True)
class FlexBox(Box):
"""Displays multiple widgets using the flexible box model."""
_view_name = Unicode('FlexBoxView', sync=True)
orientation = CaselessStrEnum(values=['vertical', 'horizontal'], default_value='vertical', sync=True)
flex = Int(0, sync=True, help="""Specify the flexible-ness of the model.""")
def _flex_changed(self, name, old, new):
new = min(max(0, new), 2)
if self.flex != new:
self.flex = new
_locations = ['start', 'center', 'end', 'baseline', 'stretch']
pack = CaselessStrEnum(
values=_locations,
default_value='start', allow_none=False, sync=True)
align = CaselessStrEnum(
values=_locations,
default_value='start', allow_none=False, sync=True)
def VBox(*pargs, **kwargs):
"""Displays multiple widgets vertically using the flexible box model."""
kwargs['orientation'] = 'vertical'
return FlexBox(*pargs, **kwargs)
def HBox(*pargs, **kwargs):
"""Displays multiple widgets horizontally using the flexible box model."""
kwargs['orientation'] = 'horizontal'
return FlexBox(*pargs, **kwargs)
# Remove in IPython 4.0
ContainerWidget = DeprecatedClass(Box, 'ContainerWidget')
PopupWidget = DeprecatedClass(Popup, 'PopupWidget')

@ -1,4 +1,4 @@
"""ButtonWidget class.
"""Button class.
Represents a button in the frontend using a widget. Allows user to listen for
click events on the button and trigger backend code when the clicks are fired.
@ -16,11 +16,16 @@ click events on the button and trigger backend code when the clicks are fired.
#-----------------------------------------------------------------------------
from .widget import DOMWidget, CallbackDispatcher
from IPython.utils.traitlets import Unicode, Bool
from IPython.utils.warn import DeprecatedClass
#-----------------------------------------------------------------------------
# Classes
#-----------------------------------------------------------------------------
class ButtonWidget(DOMWidget):
class Button(DOMWidget):
"""Button widget.
This widget has an `on_click` method that allows you to listen for the
user clicking on the button. The click event itself is stateless."""
_view_name = Unicode('ButtonView', sync=True)
# Keys
@ -29,7 +34,7 @@ class ButtonWidget(DOMWidget):
def __init__(self, **kwargs):
"""Constructor"""
super(ButtonWidget, self).__init__(**kwargs)
super(Button, self).__init__(**kwargs)
self._click_handlers = CallbackDispatcher()
self.on_msg(self._handle_button_msg)
@ -54,3 +59,7 @@ class ButtonWidget(DOMWidget):
Content of the msg."""
if content.get('event', '') == 'click':
self._click_handlers(self)
# Remove in IPython 4.0
ButtonWidget = DeprecatedClass(Button, 'ButtonWidget')

@ -1,34 +0,0 @@
"""ContainerWidget class.
Represents a container that can be used to group other widgets.
"""
# Copyright (c) IPython Development Team.
# Distributed under the terms of the Modified BSD License.
from .widget import DOMWidget
from IPython.utils.traitlets import Unicode, Tuple, TraitError
class ContainerWidget(DOMWidget):
_view_name = Unicode('ContainerView', sync=True)
# Child widgets in the container.
# Using a tuple here to force reassignment to update the list.
# When a proper notifying-list trait exists, that is what should be used here.
children = Tuple(sync=True, allow_none=False)
def __init__(self, children = (), **kwargs):
kwargs['children'] = children
super(ContainerWidget, self).__init__(**kwargs)
self.on_displayed(ContainerWidget._fire_children_displayed)
def _fire_children_displayed(self):
for child in self.children:
child._handle_displayed()
class PopupWidget(ContainerWidget):
_view_name = Unicode('PopupView', sync=True)
description = Unicode(sync=True)
button_text = Unicode(sync=True)

@ -1,4 +1,4 @@
"""FloatWidget class.
"""Float class.
Represents an unbounded float using a widget.
"""
@ -15,17 +15,18 @@ Represents an unbounded float using a widget.
#-----------------------------------------------------------------------------
from .widget import DOMWidget
from IPython.utils.traitlets import Unicode, CFloat, Bool, Enum, Tuple
from IPython.utils.warn import DeprecatedClass
#-----------------------------------------------------------------------------
# Classes
#-----------------------------------------------------------------------------
class _FloatWidget(DOMWidget):
value = CFloat(0.0, help="Float value", sync=True)
class _Float(DOMWidget):
value = CFloat(0.0, help="Float value", sync=True)
disabled = Bool(False, help="Enable or disable user changes", sync=True)
description = Unicode(help="Description of the value this widget represents", sync=True)
class _BoundedFloatWidget(_FloatWidget):
class _BoundedFloat(_Float):
max = CFloat(100.0, help="Max value", sync=True)
min = CFloat(0.0, help="Min value", sync=True)
step = CFloat(0.1, help="Minimum step that the value can take (ignored by some views)", sync=True)
@ -42,26 +43,26 @@ class _BoundedFloatWidget(_FloatWidget):
self.value = min(max(new, self.min), self.max)
class FloatTextWidget(_FloatWidget):
class FloatText(_Float):
_view_name = Unicode('FloatTextView', sync=True)
class BoundedFloatTextWidget(_BoundedFloatWidget):
class BoundedFloatText(_BoundedFloat):
_view_name = Unicode('FloatTextView', sync=True)
class FloatSliderWidget(_BoundedFloatWidget):
class FloatSlider(_BoundedFloat):
_view_name = Unicode('FloatSliderView', sync=True)
orientation = Enum([u'horizontal', u'vertical'], u'horizontal',
orientation = Enum([u'horizontal', u'vertical'], u'horizontal',
help="Vertical or horizontal.", sync=True)
range = Bool(False, help="Display a range selector", sync=True)
readout = Bool(True, help="Display the current value of the slider next to it.", sync=True)
class FloatProgressWidget(_BoundedFloatWidget):
class FloatProgress(_BoundedFloat):
_view_name = Unicode('ProgressView', sync=True)
class _FloatRangeWidget(_FloatWidget):
class _FloatRange(_Float):
value = Tuple(CFloat, CFloat, default_value=(0.0, 1.0), help="Tuple of (lower, upper) bounds", sync=True)
lower = CFloat(0.0, help="Lower bound", sync=False)
upper = CFloat(1.0, help="Upper bound", sync=False)
@ -90,14 +91,14 @@ class _FloatRangeWidget(_FloatWidget):
elif name == 'upper':
self.value = (self.value[0], new)
class _BoundedFloatRangeWidget(_FloatRangeWidget):
class _BoundedFloatRange(_FloatRange):
step = CFloat(1.0, help="Minimum step that the value can take (ignored by some views)", sync=True)
max = CFloat(100.0, help="Max value", sync=True)
min = CFloat(0.0, help="Min value", sync=True)
def __init__(self, *pargs, **kwargs):
any_value_given = 'value' in kwargs or 'upper' in kwargs or 'lower' in kwargs
_FloatRangeWidget.__init__(self, *pargs, **kwargs)
_FloatRange.__init__(self, *pargs, **kwargs)
# ensure a minimal amount of sanity
if self.min > self.max:
@ -156,9 +157,15 @@ class _BoundedFloatRangeWidget(_FloatRangeWidget):
self.lower = low
class FloatRangeSliderWidget(_BoundedFloatRangeWidget):
class FloatRangeSlider(_BoundedFloatRange):
_view_name = Unicode('FloatSliderView', sync=True)
orientation = Enum([u'horizontal', u'vertical'], u'horizontal',
help="Vertical or horizontal.", sync=True)
range = Bool(True, help="Display a range selector", sync=True)
readout = Bool(True, help="Display the current value of the slider next to it.", sync=True)
# Remove in IPython 4.0
FloatTextWidget = DeprecatedClass(FloatText, 'FloatTextWidget')
BoundedFloatTextWidget = DeprecatedClass(BoundedFloatText, 'BoundedFloatTextWidget')
FloatSliderWidget = DeprecatedClass(FloatSlider, 'FloatSliderWidget')
FloatProgressWidget = DeprecatedClass(FloatProgress, 'FloatProgressWidget')

@ -1,4 +1,4 @@
"""ImageWidget class.
"""Image class.
Represents an image in the frontend using a widget.
"""
@ -17,11 +17,18 @@ import base64
from .widget import DOMWidget
from IPython.utils.traitlets import Unicode, CUnicode, Bytes
from IPython.utils.warn import DeprecatedClass
#-----------------------------------------------------------------------------
# Classes
#-----------------------------------------------------------------------------
class ImageWidget(DOMWidget):
class Image(DOMWidget):
"""Displays an image as a widget.
The `value` of this widget accepts a byte string. The byte string is the raw
image data that you want the browser to display. You can explicitly define
the format of the byte string using the `format` trait (which defaults to
"png")."""
_view_name = Unicode('ImageView', sync=True)
# Define the custom state properties to sync with the front-end
@ -33,3 +40,7 @@ class ImageWidget(DOMWidget):
value = Bytes()
def _value_changed(self, name, old, new):
self._b64value = base64.b64encode(new)
# Remove in IPython 4.0
ImageWidget = DeprecatedClass(Image, 'ImageWidget')

@ -1,4 +1,4 @@
"""IntWidget class.
"""Int class.
Represents an unbounded int using a widget.
"""
@ -15,17 +15,21 @@ Represents an unbounded int using a widget.
#-----------------------------------------------------------------------------
from .widget import DOMWidget
from IPython.utils.traitlets import Unicode, CInt, Bool, Enum, Tuple
from IPython.utils.warn import DeprecatedClass
#-----------------------------------------------------------------------------
# Classes
#-----------------------------------------------------------------------------
class _IntWidget(DOMWidget):
value = CInt(0, help="Int value", sync=True)
class _Int(DOMWidget):
"""Base class used to create widgets that represent an int."""
value = CInt(0, help="Int value", sync=True)
disabled = Bool(False, help="Enable or disable user changes", sync=True)
description = Unicode(help="Description of the value this widget represents", sync=True)
class _BoundedIntWidget(_IntWidget):
class _BoundedInt(_Int):
"""Base class used to create widgets that represent a int that is bounded
by a minium and maximum."""
step = CInt(1, help="Minimum step that the value can take (ignored by some views)", sync=True)
max = CInt(100, help="Max value", sync=True)
min = CInt(0, help="Min value", sync=True)
@ -41,26 +45,30 @@ class _BoundedIntWidget(_IntWidget):
self.value = min(max(new, self.min), self.max)
class IntTextWidget(_IntWidget):
class IntText(_Int):
"""Textbox widget that represents a int."""
_view_name = Unicode('IntTextView', sync=True)
class BoundedIntTextWidget(_BoundedIntWidget):
class BoundedIntText(_BoundedInt):
"""Textbox widget that represents a int bounded by a minimum and maximum value."""
_view_name = Unicode('IntTextView', sync=True)
class IntSliderWidget(_BoundedIntWidget):
class IntSlider(_BoundedInt):
"""Slider widget that represents a int bounded by a minimum and maximum value."""
_view_name = Unicode('IntSliderView', sync=True)
orientation = Enum([u'horizontal', u'vertical'], u'horizontal',
orientation = Enum([u'horizontal', u'vertical'], u'horizontal',
help="Vertical or horizontal.", sync=True)
range = Bool(False, help="Display a range selector", sync=True)
readout = Bool(True, help="Display the current value of the slider next to it.", sync=True)
class IntProgressWidget(_BoundedIntWidget):
class IntProgress(_BoundedInt):
"""Progress bar that represents a int bounded by a minimum and maximum value."""
_view_name = Unicode('ProgressView', sync=True)
class _IntRangeWidget(_IntWidget):
class _IntRange(_Int):
value = Tuple(CInt, CInt, default_value=(0, 1), help="Tuple of (lower, upper) bounds", sync=True)
lower = CInt(0, help="Lower bound", sync=False)
upper = CInt(1, help="Upper bound", sync=False)
@ -89,14 +97,14 @@ class _IntRangeWidget(_IntWidget):
elif name == 'upper':
self.value = (self.value[0], new)
class _BoundedIntRangeWidget(_IntRangeWidget):
class _BoundedIntRange(_IntRange):
step = CInt(1, help="Minimum step that the value can take (ignored by some views)", sync=True)
max = CInt(100, help="Max value", sync=True)
min = CInt(0, help="Min value", sync=True)
def __init__(self, *pargs, **kwargs):
any_value_given = 'value' in kwargs or 'upper' in kwargs or 'lower' in kwargs
_IntRangeWidget.__init__(self, *pargs, **kwargs)
_IntRange.__init__(self, *pargs, **kwargs)
# ensure a minimal amount of sanity
if self.min > self.max:
@ -153,9 +161,15 @@ class _BoundedIntRangeWidget(_IntRangeWidget):
self.upper = high
self.lower = low
class IntRangeSliderWidget(_BoundedIntRangeWidget):
class IntRangeSlider(_BoundedIntRange):
_view_name = Unicode('IntSliderView', sync=True)
orientation = Enum([u'horizontal', u'vertical'], u'horizontal',
help="Vertical or horizontal.", sync=True)
range = Bool(True, help="Display a range selector", sync=True)
readout = Bool(True, help="Display the current value of the slider next to it.", sync=True)
# Remove in IPython 4.0
IntTextWidget = DeprecatedClass(IntText, 'IntTextWidget')
BoundedIntTextWidget = DeprecatedClass(BoundedIntText, 'BoundedIntTextWidget')
IntSliderWidget = DeprecatedClass(IntSlider, 'IntSliderWidget')
IntProgressWidget = DeprecatedClass(IntProgress, 'IntProgressWidget')

@ -1,4 +1,4 @@
"""SelectionWidget classes.
"""Selection classes.
Represents an enumeration using a widget.
"""
@ -20,11 +20,12 @@ from threading import Lock
from .widget import DOMWidget
from IPython.utils.traitlets import Unicode, List, Bool, Any, Dict, TraitError
from IPython.utils.py3compat import unicode_type
from IPython.utils.warn import DeprecatedClass
#-----------------------------------------------------------------------------
# SelectionWidget
#-----------------------------------------------------------------------------
class _SelectionWidget(DOMWidget):
class _Selection(DOMWidget):
"""Base class for Selection widgets
``values`` can be specified as a list or dict. If given as a list,
@ -109,17 +110,30 @@ class _SelectionWidget(DOMWidget):
self.value_lock.release()
class ToggleButtonsWidget(_SelectionWidget):
class ToggleButtons(_Selection):
"""Group of toggle buttons that represent an enumeration. Only one toggle
button can be toggled at any point in time."""
_view_name = Unicode('ToggleButtonsView', sync=True)
class DropdownWidget(_SelectionWidget):
class Dropdown(_Selection):
"""Allows you to select a single item from a dropdown."""
_view_name = Unicode('DropdownView', sync=True)
class RadioButtonsWidget(_SelectionWidget):
class RadioButtons(_Selection):
"""Group of radio buttons that represent an enumeration. Only one radio
button can be toggled at any point in time."""
_view_name = Unicode('RadioButtonsView', sync=True)
class SelectWidget(_SelectionWidget):
class Select(_Selection):
"""Listbox that only allows one item to be selected at any given time."""
_view_name = Unicode('SelectView', sync=True)
# Remove in IPython 4.0
ToggleButtonsWidget = DeprecatedClass(ToggleButtons, 'ToggleButtonsWidget')
DropdownWidget = DeprecatedClass(Dropdown, 'DropdownWidget')
RadioButtonsWidget = DeprecatedClass(RadioButtons, 'RadioButtonsWidget')
SelectWidget = DeprecatedClass(Select, 'SelectWidget')

@ -1,4 +1,4 @@
"""SelectionContainerWidget class.
"""SelectionContainer class.
Represents a multipage container that can be used to group other widgets into
pages.
@ -14,13 +14,15 @@ pages.
#-----------------------------------------------------------------------------
# Imports
#-----------------------------------------------------------------------------
from .widget_container import ContainerWidget
from .widget_box import Box
from IPython.utils.traitlets import Unicode, Dict, CInt
from IPython.utils.warn import DeprecatedClass
#-----------------------------------------------------------------------------
# Classes
#-----------------------------------------------------------------------------
class _SelectionContainerWidget(ContainerWidget):
class _SelectionContainer(Box):
"""Base class used to display multiple child widgets."""
_titles = Dict(help="Titles of the pages", sync=True)
selected_index = CInt(0, sync=True)
@ -50,9 +52,16 @@ class _SelectionContainerWidget(ContainerWidget):
return None
class AccordionWidget(_SelectionContainerWidget):
class Accordion(_SelectionContainer):
"""Displays children each on a separate accordion page."""
_view_name = Unicode('AccordionView', sync=True)
class TabWidget(_SelectionContainerWidget):
class Tab(_SelectionContainer):
"""Displays children each on a separate accordion tab."""
_view_name = Unicode('TabView', sync=True)
# Remove in IPython 4.0
AccordionWidget = DeprecatedClass(Accordion, 'AccordionWidget')
TabWidget = DeprecatedClass(Tab, 'TabWidget')

@ -1,4 +1,4 @@
"""StringWidget class.
"""String class.
Represents a unicode string using a widget.
"""
@ -15,37 +15,44 @@ Represents a unicode string using a widget.
#-----------------------------------------------------------------------------
from .widget import DOMWidget, CallbackDispatcher
from IPython.utils.traitlets import Unicode, Bool
from IPython.utils.warn import DeprecatedClass
#-----------------------------------------------------------------------------
# Classes
#-----------------------------------------------------------------------------
class _StringWidget(DOMWidget):
class _String(DOMWidget):
"""Base class used to create widgets that represent a string."""
value = Unicode(help="String value", sync=True)
disabled = Bool(False, help="Enable or disable user changes", sync=True)
description = Unicode(help="Description of the value this widget represents", sync=True)
placeholder = Unicode("", help="Placeholder text to display when nothing has been typed", sync=True)
class HTMLWidget(_StringWidget):
class HTML(_String):
"""Renders the string `value` as HTML."""
_view_name = Unicode('HTMLView', sync=True)
class LatexWidget(_StringWidget):
class Latex(_String):
"""Renders math inside the string `value` as Latex (requires $ $ or $$ $$
and similar latex tags)."""
_view_name = Unicode('LatexView', sync=True)
class TextareaWidget(_StringWidget):
class Textarea(_String):
"""Multiline text area widget."""
_view_name = Unicode('TextareaView', sync=True)
def scroll_to_bottom(self):
self.send({"method": "scroll_to_bottom"})
class TextWidget(_StringWidget):
class Text(_String):
"""Single line textbox widget."""
_view_name = Unicode('TextView', sync=True)
def __init__(self, **kwargs):
super(TextWidget, self).__init__(**kwargs)
super(Text, self).__init__(**kwargs)
self._submission_callbacks = CallbackDispatcher()
self.on_msg(self._handle_string_msg)
@ -71,3 +78,10 @@ class TextWidget(_StringWidget):
remove: bool (optional)
Whether to unregister the callback"""
self._submission_callbacks.register_callback(callback, remove=remove)
# Remove in IPython 4.0
HTMLWidget = DeprecatedClass(HTML, 'HTMLWidget')
LatexWidget = DeprecatedClass(Latex, 'LatexWidget')
TextareaWidget = DeprecatedClass(Textarea, 'TextareaWidget')
TextWidget = DeprecatedClass(Text, 'TextWidget')

Loading…
Cancel
Save