Show More
@@ -0,0 +1,57 b'' | |||
|
1 | // Copyright (c) IPython Development Team. | |
|
2 | // Distributed under the terms of the Modified BSD License. | |
|
3 | ||
|
4 | define([ | |
|
5 | "widgets/js/widget", | |
|
6 | "jquery", | |
|
7 | 'notebook/js/outputarea', | |
|
8 | ], function(widget, $, outputarea) { | |
|
9 | 'use strict'; | |
|
10 | ||
|
11 | var OutputView = widget.DOMWidgetView.extend({ | |
|
12 | initialize: function (parameters) { | |
|
13 | // Public constructor | |
|
14 | OutputView.__super__.initialize.apply(this, [parameters]); | |
|
15 | this.model.on('msg:custom', this._handle_route_msg, this); | |
|
16 | }, | |
|
17 | ||
|
18 | render: function(){ | |
|
19 | // Called when view is rendered. | |
|
20 | this.output_area = new outputarea.OutputArea({ | |
|
21 | selector: this.$el, | |
|
22 | prompt_area: false, | |
|
23 | events: this.model.widget_manager.notebook.events, | |
|
24 | keyboard_manager: this.model.widget_manager.keyboard_manager }); | |
|
25 | ||
|
26 | // Make output area reactive. | |
|
27 | var that = this; | |
|
28 | this.output_area.element.on('changed', function() { | |
|
29 | that.model.set('contents', that.output_area.element.html()); | |
|
30 | }); | |
|
31 | this.model.on('change:contents', function(){ | |
|
32 | var html = this.model.get('contents'); | |
|
33 | if (this.output_area.element.html() != html) { | |
|
34 | this.output_area.element.html(html); | |
|
35 | } | |
|
36 | }, this); | |
|
37 | ||
|
38 | // Set initial contents. | |
|
39 | this.output_area.element.html(this.model.get('contents')); | |
|
40 | }, | |
|
41 | ||
|
42 | _handle_route_msg: function(content) { | |
|
43 | var cell = this.options.cell; | |
|
44 | if (content && cell) { | |
|
45 | if (content.method == 'push') { | |
|
46 | cell.push_output_area(this.output_area); | |
|
47 | } else if (content.method == 'pop') { | |
|
48 | cell.pop_output_area(this.output_area); | |
|
49 | } | |
|
50 | } | |
|
51 | }, | |
|
52 | }); | |
|
53 | ||
|
54 | return { | |
|
55 | 'OutputView': OutputView, | |
|
56 | }; | |
|
57 | }); |
@@ -0,0 +1,50 b'' | |||
|
1 | """Output class. | |
|
2 | ||
|
3 | Represents a widget that can be used to display output within the widget area. | |
|
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 | import sys | |
|
11 | from IPython.utils.traitlets import Unicode, List | |
|
12 | from IPython.display import clear_output | |
|
13 | from IPython.testing.skipdoctest import skip_doctest | |
|
14 | ||
|
15 | @skip_doctest | |
|
16 | class Output(DOMWidget): | |
|
17 | """Widget used as a context manager to display output. | |
|
18 | ||
|
19 | This widget can capture and display stdout, stderr, and rich output. To use | |
|
20 | it, create an instance of it and display it. Then use it as a context | |
|
21 | manager. Any output produced while in it's context will be captured and | |
|
22 | displayed in it instead of the standard output area. | |
|
23 | ||
|
24 | Example | |
|
25 | from IPython.html import widgets | |
|
26 | from IPython.display import display | |
|
27 | out = widgets.Output() | |
|
28 | display(out) | |
|
29 | ||
|
30 | print('prints to output area') | |
|
31 | ||
|
32 | with out: | |
|
33 | print('prints to output widget')""" | |
|
34 | _view_name = Unicode('OutputView', sync=True) | |
|
35 | ||
|
36 | def clear_output(self, *pargs, **kwargs): | |
|
37 | with self: | |
|
38 | clear_output(*pargs, **kwargs) | |
|
39 | ||
|
40 | def __enter__(self): | |
|
41 | self._flush() | |
|
42 | self.send({'method': 'push'}) | |
|
43 | ||
|
44 | def __exit__(self, exception_type, exception_value, traceback): | |
|
45 | self._flush() | |
|
46 | self.send({'method': 'pop'}) | |
|
47 | ||
|
48 | def _flush(self): | |
|
49 | sys.stdout.flush() | |
|
50 | sys.stderr.flush() |
@@ -23,6 +23,7 b' define([' | |||
|
23 | 23 | 'notebook/js/codemirror-ipython' |
|
24 | 24 | ], function(IPython, $, utils, keyboard, cell, outputarea, completer, celltoolbar, CodeMirror, cmpython, cmip) { |
|
25 | 25 | "use strict"; |
|
26 | ||
|
26 | 27 | var Cell = cell.Cell; |
|
27 | 28 | |
|
28 | 29 | /* local util for codemirror */ |
@@ -79,6 +80,23 b' define([' | |||
|
79 | 80 | this.input_prompt_number = null; |
|
80 | 81 | this.celltoolbar = null; |
|
81 | 82 | this.output_area = null; |
|
83 | // Keep a stack of the 'active' output areas (where active means the | |
|
84 | // output area that recieves output). When a user activates an output | |
|
85 | // area, it gets pushed to the stack. Then, when the output area is | |
|
86 | // deactivated, it's popped from the stack. When the stack is empty, | |
|
87 | // the cell's output area is used. | |
|
88 | this.active_output_areas = []; | |
|
89 | var that = this; | |
|
90 | Object.defineProperty(this, 'active_output_area', { | |
|
91 | get: function() { | |
|
92 | if (that.active_output_areas && that.active_output_areas.length > 0) { | |
|
93 | return that.active_output_areas[that.active_output_areas.length-1]; | |
|
94 | } else { | |
|
95 | return that.output_area; | |
|
96 | } | |
|
97 | }, | |
|
98 | }); | |
|
99 | ||
|
82 | 100 | this.last_msg_id = null; |
|
83 | 101 | this.completer = null; |
|
84 | 102 | |
@@ -91,8 +109,6 b' define([' | |||
|
91 | 109 | |
|
92 | 110 | // Attributes we want to override in this subclass. |
|
93 | 111 | this.cell_type = "code"; |
|
94 | ||
|
95 | var that = this; | |
|
96 | 112 | this.element.focusout( |
|
97 | 113 | function() { that.auto_highlight(); } |
|
98 | 114 | ); |
@@ -118,6 +134,23 b' define([' | |||
|
118 | 134 | CodeCell.prototype = Object.create(Cell.prototype); |
|
119 | 135 | |
|
120 | 136 | /** |
|
137 | * @method push_output_area | |
|
138 | */ | |
|
139 | CodeCell.prototype.push_output_area = function (output_area) { | |
|
140 | this.active_output_areas.push(output_area); | |
|
141 | }; | |
|
142 | ||
|
143 | /** | |
|
144 | * @method pop_output_area | |
|
145 | */ | |
|
146 | CodeCell.prototype.pop_output_area = function (output_area) { | |
|
147 | var index = this.active_output_areas.lastIndexOf(output_area); | |
|
148 | if (index > -1) { | |
|
149 | this.active_output_areas.splice(index, 1); | |
|
150 | } | |
|
151 | }; | |
|
152 | ||
|
153 | /** | |
|
121 | 154 | * @method auto_highlight |
|
122 | 155 | */ |
|
123 | 156 | CodeCell.prototype.auto_highlight = function () { |
@@ -282,8 +315,8 b' define([' | |||
|
282 | 315 | console.log("Can't execute, kernel is not connected."); |
|
283 | 316 | return; |
|
284 | 317 | } |
|
285 | ||
|
286 | this.output_area.clear_output(); | |
|
318 | ||
|
319 | this.active_output_area.clear_output(); | |
|
287 | 320 | |
|
288 | 321 | // Clear widget area |
|
289 | 322 | this.widget_subarea.html(''); |
@@ -312,6 +345,7 b' define([' | |||
|
312 | 345 | * @method get_callbacks |
|
313 | 346 | */ |
|
314 | 347 | CodeCell.prototype.get_callbacks = function () { |
|
348 | var that = this; | |
|
315 | 349 | return { |
|
316 | 350 | shell : { |
|
317 | 351 | reply : $.proxy(this._handle_execute_reply, this), |
@@ -321,8 +355,12 b' define([' | |||
|
321 | 355 | } |
|
322 | 356 | }, |
|
323 | 357 | iopub : { |
|
324 | output : $.proxy(this.output_area.handle_output, this.output_area), | |
|
325 |
|
|
|
358 | output : function() { | |
|
359 | that.active_output_area.handle_output.apply(that.active_output_area, arguments); | |
|
360 | }, | |
|
361 | clear_output : function() { | |
|
362 | that.active_output_area.handle_clear_output.apply(that.active_output_area, arguments); | |
|
363 | }, | |
|
326 | 364 | }, |
|
327 | 365 | input : $.proxy(this._handle_input_request, this) |
|
328 | 366 | }; |
@@ -356,7 +394,7 b' define([' | |||
|
356 | 394 | * @private |
|
357 | 395 | */ |
|
358 | 396 | CodeCell.prototype._handle_input_request = function (msg) { |
|
359 | this.output_area.append_raw_input(msg); | |
|
397 | this.active_output_area.append_raw_input(msg); | |
|
360 | 398 | }; |
|
361 | 399 | |
|
362 | 400 | |
@@ -459,7 +497,7 b' define([' | |||
|
459 | 497 | |
|
460 | 498 | |
|
461 | 499 | CodeCell.prototype.clear_output = function (wait) { |
|
462 | this.output_area.clear_output(wait); | |
|
500 | this.active_output_area.clear_output(wait); | |
|
463 | 501 | this.set_input_prompt(); |
|
464 | 502 | }; |
|
465 | 503 |
@@ -400,6 +400,9 b' define([' | |||
|
400 | 400 | this._append_javascript_error(err, subarea); |
|
401 | 401 | this.element.append(toinsert); |
|
402 | 402 | } |
|
403 | ||
|
404 | // Notify others of changes. | |
|
405 | this.element.trigger('changed'); | |
|
403 | 406 | }; |
|
404 | 407 | |
|
405 | 408 | |
@@ -832,6 +835,10 b' define([' | |||
|
832 | 835 | // them to fire if the image is never added to the page. |
|
833 | 836 | this.element.find('img').off('load'); |
|
834 | 837 | this.element.html(""); |
|
838 | ||
|
839 | // Notify others of changes. | |
|
840 | this.element.trigger('changed'); | |
|
841 | ||
|
835 | 842 | this.outputs = []; |
|
836 | 843 | this.trusted = true; |
|
837 | 844 | this.unscroll_area(); |
@@ -9,6 +9,7 b' define([' | |||
|
9 | 9 | "widgets/js/widget_float", |
|
10 | 10 | "widgets/js/widget_image", |
|
11 | 11 | "widgets/js/widget_int", |
|
12 | "widgets/js/widget_output", | |
|
12 | 13 | "widgets/js/widget_selection", |
|
13 | 14 | "widgets/js/widget_selectioncontainer", |
|
14 | 15 | "widgets/js/widget_string", |
@@ -6,6 +6,7 b' from .widget_box import Box, Popup, FlexBox, HBox, VBox' | |||
|
6 | 6 | from .widget_float import FloatText, BoundedFloatText, FloatSlider, FloatProgress, FloatRangeSlider |
|
7 | 7 | from .widget_image import Image |
|
8 | 8 | from .widget_int import IntText, BoundedIntText, IntSlider, IntProgress, IntRangeSlider |
|
9 | from .widget_output import Output | |
|
9 | 10 | from .widget_selection import RadioButtons, ToggleButtons, Dropdown, Select |
|
10 | 11 | from .widget_selectioncontainer import Tab, Accordion |
|
11 | 12 | from .widget_string import HTML, Latex, Text, Textarea |
General Comments 0
You need to be logged in to leave comments.
Login now