Merge pull request #6670 from jdfreder/output_widget

Output widget
Min RK 12 years ago
commit 7252efd22c

@ -23,6 +23,7 @@ define([
'notebook/js/codemirror-ipython'
], function(IPython, $, utils, keyboard, cell, outputarea, completer, celltoolbar, CodeMirror, cmpython, cmip) {
"use strict";
var Cell = cell.Cell;
/* local util for codemirror */
@ -79,6 +80,23 @@ define([
this.input_prompt_number = null;
this.celltoolbar = null;
this.output_area = null;
// Keep a stack of the 'active' output areas (where active means the
// output area that recieves output). When a user activates an output
// area, it gets pushed to the stack. Then, when the output area is
// deactivated, it's popped from the stack. When the stack is empty,
// the cell's output area is used.
this.active_output_areas = [];
var that = this;
Object.defineProperty(this, 'active_output_area', {
get: function() {
if (that.active_output_areas && that.active_output_areas.length > 0) {
return that.active_output_areas[that.active_output_areas.length-1];
} else {
return that.output_area;
}
},
});
this.last_msg_id = null;
this.completer = null;
@ -91,8 +109,6 @@ define([
// Attributes we want to override in this subclass.
this.cell_type = "code";
var that = this;
this.element.focusout(
function() { that.auto_highlight(); }
);
@ -117,6 +133,23 @@ define([
CodeCell.prototype = Object.create(Cell.prototype);
/**
* @method push_output_area
*/
CodeCell.prototype.push_output_area = function (output_area) {
this.active_output_areas.push(output_area);
};
/**
* @method pop_output_area
*/
CodeCell.prototype.pop_output_area = function (output_area) {
var index = this.active_output_areas.lastIndexOf(output_area);
if (index > -1) {
this.active_output_areas.splice(index, 1);
}
};
/**
* @method auto_highlight
*/
@ -282,8 +315,8 @@ define([
console.log("Can't execute, kernel is not connected.");
return;
}
this.output_area.clear_output();
this.active_output_area.clear_output();
// Clear widget area
this.widget_subarea.html('');
@ -312,6 +345,7 @@ define([
* @method get_callbacks
*/
CodeCell.prototype.get_callbacks = function () {
var that = this;
return {
shell : {
reply : $.proxy(this._handle_execute_reply, this),
@ -321,8 +355,12 @@ define([
}
},
iopub : {
output : $.proxy(this.output_area.handle_output, this.output_area),
clear_output : $.proxy(this.output_area.handle_clear_output, this.output_area),
output : function() {
that.active_output_area.handle_output.apply(that.active_output_area, arguments);
},
clear_output : function() {
that.active_output_area.handle_clear_output.apply(that.active_output_area, arguments);
},
},
input : $.proxy(this._handle_input_request, this)
};
@ -356,7 +394,7 @@ define([
* @private
*/
CodeCell.prototype._handle_input_request = function (msg) {
this.output_area.append_raw_input(msg);
this.active_output_area.append_raw_input(msg);
};
@ -459,7 +497,7 @@ define([
CodeCell.prototype.clear_output = function (wait) {
this.output_area.clear_output(wait);
this.active_output_area.clear_output(wait);
this.set_input_prompt();
};

@ -400,6 +400,9 @@ define([
this._append_javascript_error(err, subarea);
this.element.append(toinsert);
}
// Notify others of changes.
this.element.trigger('changed');
};
@ -832,6 +835,10 @@ define([
// them to fire if the image is never added to the page.
this.element.find('img').off('load');
this.element.html("");
// Notify others of changes.
this.element.trigger('changed');
this.outputs = [];
this.trusted = true;
this.unscroll_area();

@ -9,6 +9,7 @@ define([
"widgets/js/widget_float",
"widgets/js/widget_image",
"widgets/js/widget_int",
"widgets/js/widget_output",
"widgets/js/widget_selection",
"widgets/js/widget_selectioncontainer",
"widgets/js/widget_string",

@ -0,0 +1,57 @@
// Copyright (c) IPython Development Team.
// Distributed under the terms of the Modified BSD License.
define([
"widgets/js/widget",
"jquery",
'notebook/js/outputarea',
], function(widget, $, outputarea) {
'use strict';
var OutputView = widget.DOMWidgetView.extend({
initialize: function (parameters) {
// Public constructor
OutputView.__super__.initialize.apply(this, [parameters]);
this.model.on('msg:custom', this._handle_route_msg, this);
},
render: function(){
// Called when view is rendered.
this.output_area = new outputarea.OutputArea({
selector: this.$el,
prompt_area: false,
events: this.model.widget_manager.notebook.events,
keyboard_manager: this.model.widget_manager.keyboard_manager });
// Make output area reactive.
var that = this;
this.output_area.element.on('changed', function() {
that.model.set('contents', that.output_area.element.html());
});
this.model.on('change:contents', function(){
var html = this.model.get('contents');
if (this.output_area.element.html() != html) {
this.output_area.element.html(html);
}
}, this);
// Set initial contents.
this.output_area.element.html(this.model.get('contents'));
},
_handle_route_msg: function(content) {
var cell = this.options.cell;
if (content && cell) {
if (content.method == 'push') {
cell.push_output_area(this.output_area);
} else if (content.method == 'pop') {
cell.pop_output_area(this.output_area);
}
}
},
});
return {
'OutputView': OutputView,
};
});

@ -6,6 +6,7 @@ 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_output import Output
from .widget_selection import RadioButtons, ToggleButtons, Dropdown, Select
from .widget_selectioncontainer import Tab, Accordion
from .widget_string import HTML, Latex, Text, Textarea

@ -0,0 +1,50 @@
"""Output class.
Represents a widget that can be used to display output within the widget area.
"""
# Copyright (c) IPython Development Team.
# Distributed under the terms of the Modified BSD License.
from .widget import DOMWidget
import sys
from IPython.utils.traitlets import Unicode, List
from IPython.display import clear_output
from IPython.testing.skipdoctest import skip_doctest
@skip_doctest
class Output(DOMWidget):
"""Widget used as a context manager to display output.
This widget can capture and display stdout, stderr, and rich output. To use
it, create an instance of it and display it. Then use it as a context
manager. Any output produced while in it's context will be captured and
displayed in it instead of the standard output area.
Example
from IPython.html import widgets
from IPython.display import display
out = widgets.Output()
display(out)
print('prints to output area')
with out:
print('prints to output widget')"""
_view_name = Unicode('OutputView', sync=True)
def clear_output(self, *pargs, **kwargs):
with self:
clear_output(*pargs, **kwargs)
def __enter__(self):
self._flush()
self.send({'method': 'push'})
def __exit__(self, exception_type, exception_value, traceback):
self._flush()
self.send({'method': 'pop'})
def _flush(self):
sys.stdout.flush()
sys.stderr.flush()
Loading…
Cancel
Save