##// END OF EJS Templates
s/LabelView/HTMLView
Jonathan Frederic -
Show More
@@ -1,167 +1,167 b''
1 //----------------------------------------------------------------------------
1 //----------------------------------------------------------------------------
2 // Copyright (C) 2013 The IPython Development Team
2 // Copyright (C) 2013 The IPython Development Team
3 //
3 //
4 // Distributed under the terms of the BSD License. The full license is in
4 // Distributed under the terms of the BSD License. The full license is in
5 // the file COPYING, distributed as part of this software.
5 // the file COPYING, distributed as part of this software.
6 //----------------------------------------------------------------------------
6 //----------------------------------------------------------------------------
7
7
8 //============================================================================
8 //============================================================================
9 // StringWidget
9 // StringWidget
10 //============================================================================
10 //============================================================================
11
11
12 /**
12 /**
13 * @module IPython
13 * @module IPython
14 * @namespace IPython
14 * @namespace IPython
15 **/
15 **/
16
16
17 define(["notebook/js/widget"], function(widget_manager){
17 define(["notebook/js/widget"], function(widget_manager){
18 var StringWidgetModel = IPython.WidgetModel.extend({});
18 var StringWidgetModel = IPython.WidgetModel.extend({});
19 widget_manager.register_widget_model('StringWidgetModel', StringWidgetModel);
19 widget_manager.register_widget_model('StringWidgetModel', StringWidgetModel);
20
20
21 var LabelView = IPython.WidgetView.extend({
21 var HTMLView = IPython.WidgetView.extend({
22
22
23 // Called when view is rendered.
23 // Called when view is rendered.
24 render : function(){
24 render : function(){
25 this.update(); // Set defaults.
25 this.update(); // Set defaults.
26 },
26 },
27
27
28 // Handles: Backend -> Frontend Sync
28 // Handles: Backend -> Frontend Sync
29 // Frontent -> Frontend Sync
29 // Frontent -> Frontend Sync
30 update : function(){
30 update : function(){
31 this.$el.html(this.model.get('value'));
31 this.$el.html(this.model.get('value'));
32 return IPython.WidgetView.prototype.update.call(this);
32 return IPython.WidgetView.prototype.update.call(this);
33 },
33 },
34
34
35 });
35 });
36
36
37 widget_manager.register_widget_view('LabelView', LabelView);
37 widget_manager.register_widget_view('HTMLView', HTMLView);
38
38
39 var TextAreaView = IPython.WidgetView.extend({
39 var TextAreaView = IPython.WidgetView.extend({
40
40
41 // Called when view is rendered.
41 // Called when view is rendered.
42 render: function(){
42 render: function(){
43 this.$el
43 this.$el
44 .addClass('widget-hbox')
44 .addClass('widget-hbox')
45 .html('');
45 .html('');
46 this.$label = $('<div />')
46 this.$label = $('<div />')
47 .appendTo(this.$el)
47 .appendTo(this.$el)
48 .addClass('widget-hlabel')
48 .addClass('widget-hlabel')
49 .hide();
49 .hide();
50 this.$textbox = $('<textarea />')
50 this.$textbox = $('<textarea />')
51 .attr('rows', 5)
51 .attr('rows', 5)
52 .addClass('widget-text')
52 .addClass('widget-text')
53 .appendTo(this.$el);
53 .appendTo(this.$el);
54 this.$el_to_style = this.$textbox; // Set default element to style
54 this.$el_to_style = this.$textbox; // Set default element to style
55 this.update(); // Set defaults.
55 this.update(); // Set defaults.
56
56
57 this.model.on_msg($.proxy(this._handle_textarea_msg, this));
57 this.model.on_msg($.proxy(this._handle_textarea_msg, this));
58 },
58 },
59
59
60
60
61 _handle_textarea_msg: function (content){
61 _handle_textarea_msg: function (content){
62 if (content.method == "scroll_to_bottom") {
62 if (content.method == "scroll_to_bottom") {
63 this.scroll_to_bottom();
63 this.scroll_to_bottom();
64 }
64 }
65 },
65 },
66
66
67
67
68 scroll_to_bottom: function (){
68 scroll_to_bottom: function (){
69 this.$textbox.scrollTop(this.$textbox[0].scrollHeight);
69 this.$textbox.scrollTop(this.$textbox[0].scrollHeight);
70 },
70 },
71
71
72
72
73 // Handles: Backend -> Frontend Sync
73 // Handles: Backend -> Frontend Sync
74 // Frontent -> Frontend Sync
74 // Frontent -> Frontend Sync
75 update: function(){
75 update: function(){
76 if (!this.user_invoked_update) {
76 if (!this.user_invoked_update) {
77 this.$textbox.val(this.model.get('value'));
77 this.$textbox.val(this.model.get('value'));
78 }
78 }
79
79
80 var disabled = this.model.get('disabled');
80 var disabled = this.model.get('disabled');
81 this.$textbox.prop('disabled', disabled);
81 this.$textbox.prop('disabled', disabled);
82
82
83 var description = this.model.get('description');
83 var description = this.model.get('description');
84 if (description.length == 0) {
84 if (description.length == 0) {
85 this.$label.hide();
85 this.$label.hide();
86 } else {
86 } else {
87 this.$label.html(description);
87 this.$label.html(description);
88 this.$label.show();
88 this.$label.show();
89 }
89 }
90 return IPython.WidgetView.prototype.update.call(this);
90 return IPython.WidgetView.prototype.update.call(this);
91 },
91 },
92
92
93 events: {"keyup textarea": "handleChanging",
93 events: {"keyup textarea": "handleChanging",
94 "paste textarea": "handleChanging",
94 "paste textarea": "handleChanging",
95 "cut textarea": "handleChanging"},
95 "cut textarea": "handleChanging"},
96
96
97 // Handles and validates user input.
97 // Handles and validates user input.
98 handleChanging: function(e) {
98 handleChanging: function(e) {
99 this.user_invoked_update = true;
99 this.user_invoked_update = true;
100 this.model.set('value', e.target.value);
100 this.model.set('value', e.target.value);
101 this.model.update_other_views(this);
101 this.model.update_other_views(this);
102 this.user_invoked_update = false;
102 this.user_invoked_update = false;
103 },
103 },
104 });
104 });
105
105
106 widget_manager.register_widget_view('TextAreaView', TextAreaView);
106 widget_manager.register_widget_view('TextAreaView', TextAreaView);
107
107
108 var TextBoxView = IPython.WidgetView.extend({
108 var TextBoxView = IPython.WidgetView.extend({
109
109
110 // Called when view is rendered.
110 // Called when view is rendered.
111 render: function(){
111 render: function(){
112 this.$el
112 this.$el
113 .addClass('widget-hbox-single')
113 .addClass('widget-hbox-single')
114 .html('');
114 .html('');
115 this.$label = $('<div />')
115 this.$label = $('<div />')
116 .addClass('widget-hlabel')
116 .addClass('widget-hlabel')
117 .appendTo(this.$el)
117 .appendTo(this.$el)
118 .hide();
118 .hide();
119 this.$textbox = $('<input type="text" />')
119 this.$textbox = $('<input type="text" />')
120 .addClass('input')
120 .addClass('input')
121 .addClass('widget-text')
121 .addClass('widget-text')
122 .appendTo(this.$el);
122 .appendTo(this.$el);
123 this.$el_to_style = this.$textbox; // Set default element to style
123 this.$el_to_style = this.$textbox; // Set default element to style
124 this.update(); // Set defaults.
124 this.update(); // Set defaults.
125 },
125 },
126
126
127 // Handles: Backend -> Frontend Sync
127 // Handles: Backend -> Frontend Sync
128 // Frontent -> Frontend Sync
128 // Frontent -> Frontend Sync
129 update: function(){
129 update: function(){
130 if (this.$textbox.val() != this.model.get('value')) {
130 if (this.$textbox.val() != this.model.get('value')) {
131 this.$textbox.val(this.model.get('value'));
131 this.$textbox.val(this.model.get('value'));
132 }
132 }
133
133
134 var disabled = this.model.get('disabled');
134 var disabled = this.model.get('disabled');
135 this.$textbox.prop('disabled', disabled);
135 this.$textbox.prop('disabled', disabled);
136
136
137 var description = this.model.get('description');
137 var description = this.model.get('description');
138 if (description.length == 0) {
138 if (description.length == 0) {
139 this.$label.hide();
139 this.$label.hide();
140 } else {
140 } else {
141 this.$label.html(description);
141 this.$label.html(description);
142 this.$label.show();
142 this.$label.show();
143 }
143 }
144 return IPython.WidgetView.prototype.update.call(this);
144 return IPython.WidgetView.prototype.update.call(this);
145 },
145 },
146
146
147 events: {"keyup input": "handleChanging",
147 events: {"keyup input": "handleChanging",
148 "paste input": "handleChanging",
148 "paste input": "handleChanging",
149 "cut input": "handleChanging",
149 "cut input": "handleChanging",
150 "keypress input": "handleKeypress"},
150 "keypress input": "handleKeypress"},
151
151
152 // Handles and validates user input.
152 // Handles and validates user input.
153 handleChanging: function(e) {
153 handleChanging: function(e) {
154 this.model.set('value', e.target.value);
154 this.model.set('value', e.target.value);
155 this.model.update_other_views(this);
155 this.model.update_other_views(this);
156 },
156 },
157
157
158 // Handles text submition
158 // Handles text submition
159 handleKeypress: function(e) {
159 handleKeypress: function(e) {
160 if (e.keyCode == 13) { // Return key
160 if (e.keyCode == 13) { // Return key
161 this.send({event: 'submit'});
161 this.send({event: 'submit'});
162 }
162 }
163 },
163 },
164 });
164 });
165
165
166 widget_manager.register_widget_view('TextBoxView', TextBoxView);
166 widget_manager.register_widget_view('TextBoxView', TextBoxView);
167 });
167 });
@@ -1,1358 +1,1358 b''
1 {
1 {
2 "metadata": {
2 "metadata": {
3 "name": ""
3 "name": ""
4 },
4 },
5 "nbformat": 3,
5 "nbformat": 3,
6 "nbformat_minor": 0,
6 "nbformat_minor": 0,
7 "worksheets": [
7 "worksheets": [
8 {
8 {
9 "cells": [
9 "cells": [
10 {
10 {
11 "cell_type": "code",
11 "cell_type": "code",
12 "collapsed": false,
12 "collapsed": false,
13 "input": [
13 "input": [
14 "from __future__ import print_function # py 2.7 compat\n",
14 "from __future__ import print_function # py 2.7 compat\n",
15 "\n",
15 "\n",
16 "import networkx as nx"
16 "import networkx as nx"
17 ],
17 ],
18 "language": "python",
18 "language": "python",
19 "metadata": {},
19 "metadata": {},
20 "outputs": [],
20 "outputs": [],
21 "prompt_number": 1
21 "prompt_number": 1
22 },
22 },
23 {
23 {
24 "cell_type": "markdown",
24 "cell_type": "markdown",
25 "metadata": {},
25 "metadata": {},
26 "source": [
26 "source": [
27 "This notebook demonstrates how NetworkX and D3 can be married using custom widget code."
27 "This notebook demonstrates how NetworkX and D3 can be married using custom widget code."
28 ]
28 ]
29 },
29 },
30 {
30 {
31 "cell_type": "heading",
31 "cell_type": "heading",
32 "level": 1,
32 "level": 1,
33 "metadata": {},
33 "metadata": {},
34 "source": [
34 "source": [
35 "Hooking NetworkX Graphs"
35 "Hooking NetworkX Graphs"
36 ]
36 ]
37 },
37 },
38 {
38 {
39 "cell_type": "markdown",
39 "cell_type": "markdown",
40 "metadata": {},
40 "metadata": {},
41 "source": [
41 "source": [
42 "NetworkX graphs do not have events that can be listened to. In order to watch the NetworkX graph object for changes a custom eventful graph object must be created. The custom eventful graph object will inherit from the base graph object and use special eventful dictionaries instead of standard Python dict instances. Because NetworkX nests dictionaries inside dictionaries, it's important that the eventful dictionary is capable of recognizing when a dictionary value is set to another dictionary instance. When this happens, the eventful dictionary needs to also make the new dictionary an eventful dictionary. This allows the eventful dictionary to listen to changes made to dictionaries within dictionaries."
42 "NetworkX graphs do not have events that can be listened to. In order to watch the NetworkX graph object for changes a custom eventful graph object must be created. The custom eventful graph object will inherit from the base graph object and use special eventful dictionaries instead of standard Python dict instances. Because NetworkX nests dictionaries inside dictionaries, it's important that the eventful dictionary is capable of recognizing when a dictionary value is set to another dictionary instance. When this happens, the eventful dictionary needs to also make the new dictionary an eventful dictionary. This allows the eventful dictionary to listen to changes made to dictionaries within dictionaries."
43 ]
43 ]
44 },
44 },
45 {
45 {
46 "cell_type": "code",
46 "cell_type": "code",
47 "collapsed": false,
47 "collapsed": false,
48 "input": [
48 "input": [
49 "class EventfulDict(dict):\n",
49 "class EventfulDict(dict):\n",
50 " \n",
50 " \n",
51 " def __init__(self, *args, **kwargs):\n",
51 " def __init__(self, *args, **kwargs):\n",
52 " self._add_callbacks = []\n",
52 " self._add_callbacks = []\n",
53 " self._del_callbacks = []\n",
53 " self._del_callbacks = []\n",
54 " self._set_callbacks = []\n",
54 " self._set_callbacks = []\n",
55 " dict.__init__(self, *args, **kwargs)\n",
55 " dict.__init__(self, *args, **kwargs)\n",
56 " \n",
56 " \n",
57 " def on_add(self, callback, remove=False):\n",
57 " def on_add(self, callback, remove=False):\n",
58 " self._register_callback(self._add_callbacks, callback, remove)\n",
58 " self._register_callback(self._add_callbacks, callback, remove)\n",
59 " def on_del(self, callback, remove=False):\n",
59 " def on_del(self, callback, remove=False):\n",
60 " self._register_callback(self._del_callbacks, callback, remove)\n",
60 " self._register_callback(self._del_callbacks, callback, remove)\n",
61 " def on_set(self, callback, remove=False):\n",
61 " def on_set(self, callback, remove=False):\n",
62 " self._register_callback(self._set_callbacks, callback, remove)\n",
62 " self._register_callback(self._set_callbacks, callback, remove)\n",
63 " def _register_callback(self, callback_list, callback, remove=False):\n",
63 " def _register_callback(self, callback_list, callback, remove=False):\n",
64 " if callable(callback):\n",
64 " if callable(callback):\n",
65 " if remove and callback in callback_list:\n",
65 " if remove and callback in callback_list:\n",
66 " callback_list.remove(callback)\n",
66 " callback_list.remove(callback)\n",
67 " elif not remove and not callback in callback_list:\n",
67 " elif not remove and not callback in callback_list:\n",
68 " callback_list.append(callback)\n",
68 " callback_list.append(callback)\n",
69 " else:\n",
69 " else:\n",
70 " raise Exception('Callback must be callable.')\n",
70 " raise Exception('Callback must be callable.')\n",
71 "\n",
71 "\n",
72 " def _handle_add(self, key, value):\n",
72 " def _handle_add(self, key, value):\n",
73 " self._try_callbacks(self._add_callbacks, key, value)\n",
73 " self._try_callbacks(self._add_callbacks, key, value)\n",
74 " def _handle_del(self, key):\n",
74 " def _handle_del(self, key):\n",
75 " self._try_callbacks(self._del_callbacks, key)\n",
75 " self._try_callbacks(self._del_callbacks, key)\n",
76 " def _handle_set(self, key, value):\n",
76 " def _handle_set(self, key, value):\n",
77 " self._try_callbacks(self._set_callbacks, key, value)\n",
77 " self._try_callbacks(self._set_callbacks, key, value)\n",
78 " def _try_callbacks(self, callback_list, *pargs, **kwargs):\n",
78 " def _try_callbacks(self, callback_list, *pargs, **kwargs):\n",
79 " for callback in callback_list:\n",
79 " for callback in callback_list:\n",
80 " callback(*pargs, **kwargs)\n",
80 " callback(*pargs, **kwargs)\n",
81 " \n",
81 " \n",
82 " def __setitem__(self, key, value):\n",
82 " def __setitem__(self, key, value):\n",
83 " return_val = None\n",
83 " return_val = None\n",
84 " exists = False\n",
84 " exists = False\n",
85 " if key in self:\n",
85 " if key in self:\n",
86 " exists = True\n",
86 " exists = True\n",
87 " \n",
87 " \n",
88 " # If the user sets the property to a new dict, make the dict\n",
88 " # If the user sets the property to a new dict, make the dict\n",
89 " # eventful and listen to the changes of it ONLY if it is not\n",
89 " # eventful and listen to the changes of it ONLY if it is not\n",
90 " # already eventful. Any modification to this new dict will\n",
90 " # already eventful. Any modification to this new dict will\n",
91 " # fire a set event of the parent dict.\n",
91 " # fire a set event of the parent dict.\n",
92 " if isinstance(value, dict) and not isinstance(value, EventfulDict):\n",
92 " if isinstance(value, dict) and not isinstance(value, EventfulDict):\n",
93 " new_dict = EventfulDict(value)\n",
93 " new_dict = EventfulDict(value)\n",
94 " \n",
94 " \n",
95 " def handle_change(*pargs, **kwargs):\n",
95 " def handle_change(*pargs, **kwargs):\n",
96 " self._try_callbacks(self._set_callbacks, key, dict.__getitem__(self, key))\n",
96 " self._try_callbacks(self._set_callbacks, key, dict.__getitem__(self, key))\n",
97 " \n",
97 " \n",
98 " new_dict.on_add(handle_change)\n",
98 " new_dict.on_add(handle_change)\n",
99 " new_dict.on_del(handle_change)\n",
99 " new_dict.on_del(handle_change)\n",
100 " new_dict.on_set(handle_change)\n",
100 " new_dict.on_set(handle_change)\n",
101 " return_val = dict.__setitem__(self, key, new_dict)\n",
101 " return_val = dict.__setitem__(self, key, new_dict)\n",
102 " else:\n",
102 " else:\n",
103 " return_val = dict.__setitem__(self, key, value)\n",
103 " return_val = dict.__setitem__(self, key, value)\n",
104 " \n",
104 " \n",
105 " if exists:\n",
105 " if exists:\n",
106 " self._handle_set(key, value)\n",
106 " self._handle_set(key, value)\n",
107 " else:\n",
107 " else:\n",
108 " self._handle_add(key, value)\n",
108 " self._handle_add(key, value)\n",
109 " return return_val\n",
109 " return return_val\n",
110 " \n",
110 " \n",
111 "\n",
111 "\n",
112 " def __delitem__(self, key):\n",
112 " def __delitem__(self, key):\n",
113 " return_val = dict.__delitem__(self, key)\n",
113 " return_val = dict.__delitem__(self, key)\n",
114 " self._handle_del(key)\n",
114 " self._handle_del(key)\n",
115 " return return_val\n",
115 " return return_val\n",
116 "\n",
116 "\n",
117 " \n",
117 " \n",
118 " def pop(self, key):\n",
118 " def pop(self, key):\n",
119 " return_val = dict.pop(self, key)\n",
119 " return_val = dict.pop(self, key)\n",
120 " if key in self:\n",
120 " if key in self:\n",
121 " self._handle_del(key)\n",
121 " self._handle_del(key)\n",
122 " return return_val\n",
122 " return return_val\n",
123 "\n",
123 "\n",
124 " def popitem(self):\n",
124 " def popitem(self):\n",
125 " popped = dict.popitem(self)\n",
125 " popped = dict.popitem(self)\n",
126 " if popped is not None and popped[0] is not None:\n",
126 " if popped is not None and popped[0] is not None:\n",
127 " self._handle_del(popped[0])\n",
127 " self._handle_del(popped[0])\n",
128 " return popped\n",
128 " return popped\n",
129 "\n",
129 "\n",
130 " def update(self, other_dict):\n",
130 " def update(self, other_dict):\n",
131 " for (key, value) in other_dict.items():\n",
131 " for (key, value) in other_dict.items():\n",
132 " self[key] = value\n",
132 " self[key] = value\n",
133 " \n",
133 " \n",
134 " def clear(self):\n",
134 " def clear(self):\n",
135 " for key in list(self.keys()):\n",
135 " for key in list(self.keys()):\n",
136 " del self[key]"
136 " del self[key]"
137 ],
137 ],
138 "language": "python",
138 "language": "python",
139 "metadata": {},
139 "metadata": {},
140 "outputs": [],
140 "outputs": [],
141 "prompt_number": 2
141 "prompt_number": 2
142 },
142 },
143 {
143 {
144 "cell_type": "markdown",
144 "cell_type": "markdown",
145 "metadata": {},
145 "metadata": {},
146 "source": [
146 "source": [
147 "Override the NetworkX Graph object to make an eventful graph."
147 "Override the NetworkX Graph object to make an eventful graph."
148 ]
148 ]
149 },
149 },
150 {
150 {
151 "cell_type": "code",
151 "cell_type": "code",
152 "collapsed": false,
152 "collapsed": false,
153 "input": [
153 "input": [
154 "class EventfulGraph(nx.Graph):\n",
154 "class EventfulGraph(nx.Graph):\n",
155 " \n",
155 " \n",
156 " def __init__(self, *pargs, **kwargs):\n",
156 " def __init__(self, *pargs, **kwargs):\n",
157 " \"\"\"Initialize a graph with edges, name, graph attributes.\"\"\"\n",
157 " \"\"\"Initialize a graph with edges, name, graph attributes.\"\"\"\n",
158 " super(EventfulGraph, self).__init__(*pargs, **kwargs)\n",
158 " super(EventfulGraph, self).__init__(*pargs, **kwargs)\n",
159 " \n",
159 " \n",
160 " self.graph = EventfulDict(self.graph)\n",
160 " self.graph = EventfulDict(self.graph)\n",
161 " self.node = EventfulDict(self.node)\n",
161 " self.node = EventfulDict(self.node)\n",
162 " self.adj = EventfulDict(self.adj)\n",
162 " self.adj = EventfulDict(self.adj)\n",
163 " "
163 " "
164 ],
164 ],
165 "language": "python",
165 "language": "python",
166 "metadata": {},
166 "metadata": {},
167 "outputs": [],
167 "outputs": [],
168 "prompt_number": 3
168 "prompt_number": 3
169 },
169 },
170 {
170 {
171 "cell_type": "markdown",
171 "cell_type": "markdown",
172 "metadata": {},
172 "metadata": {},
173 "source": [
173 "source": [
174 "To make sure that the eventful graph works, create a new graph and log the dictionary events raised."
174 "To make sure that the eventful graph works, create a new graph and log the dictionary events raised."
175 ]
175 ]
176 },
176 },
177 {
177 {
178 "cell_type": "code",
178 "cell_type": "code",
179 "collapsed": false,
179 "collapsed": false,
180 "input": [
180 "input": [
181 "def echo_dict_events(eventful_dict, prefix=''):\n",
181 "def echo_dict_events(eventful_dict, prefix=''):\n",
182 " def key_add(key, value):\n",
182 " def key_add(key, value):\n",
183 " print(prefix + 'add (%s, %s)' % (key, str(value)))\n",
183 " print(prefix + 'add (%s, %s)' % (key, str(value)))\n",
184 " def key_set(key, value):\n",
184 " def key_set(key, value):\n",
185 " print(prefix + 'set (%s, %s)' % (key, str(value)))\n",
185 " print(prefix + 'set (%s, %s)' % (key, str(value)))\n",
186 " def key_del(key):\n",
186 " def key_del(key):\n",
187 " print(prefix + 'del %s' % key)\n",
187 " print(prefix + 'del %s' % key)\n",
188 " eventful_dict.on_add(key_add)\n",
188 " eventful_dict.on_add(key_add)\n",
189 " eventful_dict.on_set(key_set)\n",
189 " eventful_dict.on_set(key_set)\n",
190 " eventful_dict.on_del(key_del)\n",
190 " eventful_dict.on_del(key_del)\n",
191 " \n",
191 " \n",
192 "def echo_graph_events(eventful_graph):\n",
192 "def echo_graph_events(eventful_graph):\n",
193 " for key in ['graph', 'node', 'adj']:\n",
193 " for key in ['graph', 'node', 'adj']:\n",
194 " echo_dict_events(getattr(eventful_graph, key), prefix=key+' ')"
194 " echo_dict_events(getattr(eventful_graph, key), prefix=key+' ')"
195 ],
195 ],
196 "language": "python",
196 "language": "python",
197 "metadata": {},
197 "metadata": {},
198 "outputs": [],
198 "outputs": [],
199 "prompt_number": 4
199 "prompt_number": 4
200 },
200 },
201 {
201 {
202 "cell_type": "code",
202 "cell_type": "code",
203 "collapsed": false,
203 "collapsed": false,
204 "input": [
204 "input": [
205 "G = EventfulGraph()\n",
205 "G = EventfulGraph()\n",
206 "echo_graph_events(G)\n",
206 "echo_graph_events(G)\n",
207 "\n",
207 "\n",
208 "G.add_node('hello')\n",
208 "G.add_node('hello')\n",
209 "G.add_node('goodbye', fill=\"red\")\n",
209 "G.add_node('goodbye', fill=\"red\")\n",
210 "G.add_edges_from([(1,2),(1,3), (1,'goodbye')], stroke=\"lime\")"
210 "G.add_edges_from([(1,2),(1,3), (1,'goodbye')], stroke=\"lime\")"
211 ],
211 ],
212 "language": "python",
212 "language": "python",
213 "metadata": {},
213 "metadata": {},
214 "outputs": [
214 "outputs": [
215 {
215 {
216 "output_type": "stream",
216 "output_type": "stream",
217 "stream": "stdout",
217 "stream": "stdout",
218 "text": [
218 "text": [
219 "adj add (hello, {})\n",
219 "adj add (hello, {})\n",
220 "node add (hello, {})\n",
220 "node add (hello, {})\n",
221 "adj add (goodbye, {})\n",
221 "adj add (goodbye, {})\n",
222 "node add (goodbye, {'fill': 'red'})\n",
222 "node add (goodbye, {'fill': 'red'})\n",
223 "adj add (1, {})\n",
223 "adj add (1, {})\n",
224 "node add (1, {})\n",
224 "node add (1, {})\n",
225 "adj add (2, {})\n",
225 "adj add (2, {})\n",
226 "node add (2, {})\n",
226 "node add (2, {})\n",
227 "adj set (1, {2: {'stroke': 'lime'}})\n",
227 "adj set (1, {2: {'stroke': 'lime'}})\n",
228 "adj set (2, {1: {'stroke': 'lime'}})\n",
228 "adj set (2, {1: {'stroke': 'lime'}})\n",
229 "adj add (3, {})\n",
229 "adj add (3, {})\n",
230 "node add (3, {})\n",
230 "node add (3, {})\n",
231 "adj set (1, {2: {'stroke': 'lime'}, 3: {'stroke': 'lime'}})\n",
231 "adj set (1, {2: {'stroke': 'lime'}, 3: {'stroke': 'lime'}})\n",
232 "adj set (3, {1: {'stroke': 'lime'}})\n",
232 "adj set (3, {1: {'stroke': 'lime'}})\n",
233 "adj set (1, {2: {'stroke': 'lime'}, 3: {'stroke': 'lime'}, 'goodbye': {'stroke': 'lime'}})\n",
233 "adj set (1, {2: {'stroke': 'lime'}, 3: {'stroke': 'lime'}, 'goodbye': {'stroke': 'lime'}})\n",
234 "adj set (goodbye, {1: {'stroke': 'lime'}})\n"
234 "adj set (goodbye, {1: {'stroke': 'lime'}})\n"
235 ]
235 ]
236 }
236 }
237 ],
237 ],
238 "prompt_number": 5
238 "prompt_number": 5
239 },
239 },
240 {
240 {
241 "cell_type": "code",
241 "cell_type": "code",
242 "collapsed": false,
242 "collapsed": false,
243 "input": [
243 "input": [
244 "G.adj"
244 "G.adj"
245 ],
245 ],
246 "language": "python",
246 "language": "python",
247 "metadata": {},
247 "metadata": {},
248 "outputs": [
248 "outputs": [
249 {
249 {
250 "metadata": {},
250 "metadata": {},
251 "output_type": "pyout",
251 "output_type": "pyout",
252 "prompt_number": 6,
252 "prompt_number": 6,
253 "text": [
253 "text": [
254 "{1: {2: {'stroke': 'lime'},\n",
254 "{1: {2: {'stroke': 'lime'},\n",
255 " 3: {'stroke': 'lime'},\n",
255 " 3: {'stroke': 'lime'},\n",
256 " 'goodbye': {'stroke': 'lime'}},\n",
256 " 'goodbye': {'stroke': 'lime'}},\n",
257 " 2: {1: {'stroke': 'lime'}},\n",
257 " 2: {1: {'stroke': 'lime'}},\n",
258 " 3: {1: {'stroke': 'lime'}},\n",
258 " 3: {1: {'stroke': 'lime'}},\n",
259 " 'goodbye': {1: {'stroke': 'lime'}},\n",
259 " 'goodbye': {1: {'stroke': 'lime'}},\n",
260 " 'hello': {}}"
260 " 'hello': {}}"
261 ]
261 ]
262 }
262 }
263 ],
263 ],
264 "prompt_number": 6
264 "prompt_number": 6
265 },
265 },
266 {
266 {
267 "cell_type": "code",
267 "cell_type": "code",
268 "collapsed": false,
268 "collapsed": false,
269 "input": [
269 "input": [
270 "G.node"
270 "G.node"
271 ],
271 ],
272 "language": "python",
272 "language": "python",
273 "metadata": {},
273 "metadata": {},
274 "outputs": [
274 "outputs": [
275 {
275 {
276 "metadata": {},
276 "metadata": {},
277 "output_type": "pyout",
277 "output_type": "pyout",
278 "prompt_number": 7,
278 "prompt_number": 7,
279 "text": [
279 "text": [
280 "{1: {}, 2: {}, 3: {}, 'goodbye': {'fill': 'red'}, 'hello': {}}"
280 "{1: {}, 2: {}, 3: {}, 'goodbye': {'fill': 'red'}, 'hello': {}}"
281 ]
281 ]
282 }
282 }
283 ],
283 ],
284 "prompt_number": 7
284 "prompt_number": 7
285 },
285 },
286 {
286 {
287 "cell_type": "heading",
287 "cell_type": "heading",
288 "level": 1,
288 "level": 1,
289 "metadata": {},
289 "metadata": {},
290 "source": [
290 "source": [
291 "D3 Widget"
291 "D3 Widget"
292 ]
292 ]
293 },
293 },
294 {
294 {
295 "cell_type": "markdown",
295 "cell_type": "markdown",
296 "metadata": {},
296 "metadata": {},
297 "source": [
297 "source": [
298 "The D3 widget will blindly port all of the dictionary events over custom widget messages."
298 "The D3 widget will blindly port all of the dictionary events over custom widget messages."
299 ]
299 ]
300 },
300 },
301 {
301 {
302 "cell_type": "code",
302 "cell_type": "code",
303 "collapsed": false,
303 "collapsed": false,
304 "input": [
304 "input": [
305 "from IPython.html import widgets # Widget definitions\n",
305 "from IPython.html import widgets # Widget definitions\n",
306 "from IPython.display import display # Used to display widgets in the notebook"
306 "from IPython.display import display # Used to display widgets in the notebook"
307 ],
307 ],
308 "language": "python",
308 "language": "python",
309 "metadata": {},
309 "metadata": {},
310 "outputs": [],
310 "outputs": [],
311 "prompt_number": 8
311 "prompt_number": 8
312 },
312 },
313 {
313 {
314 "cell_type": "code",
314 "cell_type": "code",
315 "collapsed": false,
315 "collapsed": false,
316 "input": [
316 "input": [
317 "# Import the base Widget class and the traitlets Unicode class.\n",
317 "# Import the base Widget class and the traitlets Unicode class.\n",
318 "from IPython.html.widgets import Widget\n",
318 "from IPython.html.widgets import Widget\n",
319 "from IPython.utils.traitlets import Unicode, Int\n",
319 "from IPython.utils.traitlets import Unicode, Int\n",
320 "\n",
320 "\n",
321 "# Define our ForceDirectedGraphWidget and its target model and default view.\n",
321 "# Define our ForceDirectedGraphWidget and its target model and default view.\n",
322 "class ForceDirectedGraphWidget(Widget):\n",
322 "class ForceDirectedGraphWidget(Widget):\n",
323 " target_name = Unicode('ForceDirectedGraphModel')\n",
323 " target_name = Unicode('ForceDirectedGraphModel')\n",
324 " default_view_name = Unicode('D3ForceDirectedGraphView')\n",
324 " default_view_name = Unicode('D3ForceDirectedGraphView')\n",
325 " \n",
325 " \n",
326 " _keys = ['width', 'height']\n",
326 " _keys = ['width', 'height']\n",
327 " width = Int(400)\n",
327 " width = Int(400)\n",
328 " height = Int(300)\n",
328 " height = Int(300)\n",
329 " \n",
329 " \n",
330 " def __init__(self, eventful_graph, *pargs, **kwargs):\n",
330 " def __init__(self, eventful_graph, *pargs, **kwargs):\n",
331 " Widget.__init__(self, *pargs, **kwargs)\n",
331 " Widget.__init__(self, *pargs, **kwargs)\n",
332 " \n",
332 " \n",
333 " self._eventful_graph = eventful_graph\n",
333 " self._eventful_graph = eventful_graph\n",
334 " self._send_dict_changes(eventful_graph.graph, 'graph')\n",
334 " self._send_dict_changes(eventful_graph.graph, 'graph')\n",
335 " self._send_dict_changes(eventful_graph.node, 'node')\n",
335 " self._send_dict_changes(eventful_graph.node, 'node')\n",
336 " self._send_dict_changes(eventful_graph.adj, 'adj')\n",
336 " self._send_dict_changes(eventful_graph.adj, 'adj')\n",
337 " \n",
337 " \n",
338 " \n",
338 " \n",
339 " def _repr_widget_(self, *pargs, **kwargs):\n",
339 " def _repr_widget_(self, *pargs, **kwargs):\n",
340 " \n",
340 " \n",
341 " # Show the widget, then send the current state\n",
341 " # Show the widget, then send the current state\n",
342 " Widget._repr_widget_(self, *pargs, **kwargs)\n",
342 " Widget._repr_widget_(self, *pargs, **kwargs)\n",
343 " for (key, value) in self._eventful_graph.graph.items():\n",
343 " for (key, value) in self._eventful_graph.graph.items():\n",
344 " self.send({'dict': 'graph', 'action': 'add', 'key': key, 'value': value})\n",
344 " self.send({'dict': 'graph', 'action': 'add', 'key': key, 'value': value})\n",
345 " for (key, value) in self._eventful_graph.node.items():\n",
345 " for (key, value) in self._eventful_graph.node.items():\n",
346 " self.send({'dict': 'node', 'action': 'add', 'key': key, 'value': value})\n",
346 " self.send({'dict': 'node', 'action': 'add', 'key': key, 'value': value})\n",
347 " for (key, value) in self._eventful_graph.adj.items():\n",
347 " for (key, value) in self._eventful_graph.adj.items():\n",
348 " self.send({'dict': 'adj', 'action': 'add', 'key': key, 'value': value})\n",
348 " self.send({'dict': 'adj', 'action': 'add', 'key': key, 'value': value})\n",
349 " \n",
349 " \n",
350 " \n",
350 " \n",
351 " def _send_dict_changes(self, eventful_dict, dict_name):\n",
351 " def _send_dict_changes(self, eventful_dict, dict_name):\n",
352 " def key_add(key, value):\n",
352 " def key_add(key, value):\n",
353 " self.send({'dict': dict_name, 'action': 'add', 'key': key, 'value': value})\n",
353 " self.send({'dict': dict_name, 'action': 'add', 'key': key, 'value': value})\n",
354 " def key_set(key, value):\n",
354 " def key_set(key, value):\n",
355 " self.send({'dict': dict_name, 'action': 'set', 'key': key, 'value': value})\n",
355 " self.send({'dict': dict_name, 'action': 'set', 'key': key, 'value': value})\n",
356 " def key_del(key):\n",
356 " def key_del(key):\n",
357 " self.send({'dict': dict_name, 'action': 'del', 'key': key})\n",
357 " self.send({'dict': dict_name, 'action': 'del', 'key': key})\n",
358 " eventful_dict.on_add(key_add)\n",
358 " eventful_dict.on_add(key_add)\n",
359 " eventful_dict.on_set(key_set)\n",
359 " eventful_dict.on_set(key_set)\n",
360 " eventful_dict.on_del(key_del)\n",
360 " eventful_dict.on_del(key_del)\n",
361 " "
361 " "
362 ],
362 ],
363 "language": "python",
363 "language": "python",
364 "metadata": {},
364 "metadata": {},
365 "outputs": [],
365 "outputs": [],
366 "prompt_number": 9
366 "prompt_number": 9
367 },
367 },
368 {
368 {
369 "cell_type": "markdown",
369 "cell_type": "markdown",
370 "metadata": {},
370 "metadata": {},
371 "source": [
371 "source": [
372 "The front-end listens to the dictionary events and keeps the D3 control in sync with the dictionary in the back-end."
372 "The front-end listens to the dictionary events and keeps the D3 control in sync with the dictionary in the back-end."
373 ]
373 ]
374 },
374 },
375 {
375 {
376 "cell_type": "code",
376 "cell_type": "code",
377 "collapsed": false,
377 "collapsed": false,
378 "input": [
378 "input": [
379 "%%javascript\n",
379 "%%javascript\n",
380 "\n",
380 "\n",
381 "require([\"http://d3js.org/d3.v3.min.js\", \"notebook/js/widget\"], function(){\n",
381 "require([\"http://d3js.org/d3.v3.min.js\", \"notebook/js/widget\"], function(){\n",
382 " \n",
382 " \n",
383 " // Define the ForceDirectedGraphModel and register it with the widget manager.\n",
383 " // Define the ForceDirectedGraphModel and register it with the widget manager.\n",
384 " var ForceDirectedGraphModel = IPython.WidgetModel.extend({});\n",
384 " var ForceDirectedGraphModel = IPython.WidgetModel.extend({});\n",
385 " IPython.widget_manager.register_widget_model('ForceDirectedGraphModel', ForceDirectedGraphModel);\n",
385 " IPython.widget_manager.register_widget_model('ForceDirectedGraphModel', ForceDirectedGraphModel);\n",
386 " \n",
386 " \n",
387 " // Define the D3ForceDirectedGraphView\n",
387 " // Define the D3ForceDirectedGraphView\n",
388 " var D3ForceDirectedGraphView = IPython.WidgetView.extend({\n",
388 " var D3ForceDirectedGraphView = IPython.WidgetView.extend({\n",
389 " \n",
389 " \n",
390 " render: function(){\n",
390 " render: function(){\n",
391 " this.guid = 'd3force' + IPython.utils.uuid();\n",
391 " this.guid = 'd3force' + IPython.utils.uuid();\n",
392 " this.setElement($('<div />', {id: this.guid}));\n",
392 " this.setElement($('<div />', {id: this.guid}));\n",
393 " this.model.on_msg($.proxy(this.handle_msg, this));\n",
393 " this.model.on_msg($.proxy(this.handle_msg, this));\n",
394 " this.has_drawn = false;\n",
394 " this.has_drawn = false;\n",
395 " },\n",
395 " },\n",
396 " \n",
396 " \n",
397 " try_add_node: function(id){\n",
397 " try_add_node: function(id){\n",
398 " var index = this.find_node(id);\n",
398 " var index = this.find_node(id);\n",
399 " if (index == -1) {\n",
399 " if (index == -1) {\n",
400 " var node = {id: id};\n",
400 " var node = {id: id};\n",
401 " this.nodes.push(node);\n",
401 " this.nodes.push(node);\n",
402 " return node;\n",
402 " return node;\n",
403 " } else {\n",
403 " } else {\n",
404 " return this.nodes[index];\n",
404 " return this.nodes[index];\n",
405 " }\n",
405 " }\n",
406 " },\n",
406 " },\n",
407 " \n",
407 " \n",
408 " update_node: function(node, attributes) {\n",
408 " update_node: function(node, attributes) {\n",
409 " if (node !== null) {\n",
409 " if (node !== null) {\n",
410 " for (var key in attributes) {\n",
410 " for (var key in attributes) {\n",
411 " node[key] = attributes[key];\n",
411 " node[key] = attributes[key];\n",
412 " }\n",
412 " }\n",
413 " this._update_node(d3.select('#' + this.guid + node.id));\n",
413 " this._update_node(d3.select('#' + this.guid + node.id));\n",
414 " }\n",
414 " }\n",
415 " },\n",
415 " },\n",
416 " \n",
416 " \n",
417 " remove_node: function(id){\n",
417 " remove_node: function(id){\n",
418 " this.remove_links_to(id);\n",
418 " this.remove_links_to(id);\n",
419 " \n",
419 " \n",
420 " var found_index = this.find_node(id);\n",
420 " var found_index = this.find_node(id);\n",
421 " if (found_index>=0) {\n",
421 " if (found_index>=0) {\n",
422 " this.nodes.splice(found_index, 1);\n",
422 " this.nodes.splice(found_index, 1);\n",
423 " }\n",
423 " }\n",
424 " },\n",
424 " },\n",
425 " \n",
425 " \n",
426 " find_node: function(id){\n",
426 " find_node: function(id){\n",
427 " var found_index = -1;\n",
427 " var found_index = -1;\n",
428 " for (var index in this.nodes) {\n",
428 " for (var index in this.nodes) {\n",
429 " if (this.nodes[index].id == id) {\n",
429 " if (this.nodes[index].id == id) {\n",
430 " found_index = index;\n",
430 " found_index = index;\n",
431 " break;\n",
431 " break;\n",
432 " }\n",
432 " }\n",
433 " }\n",
433 " }\n",
434 " return found_index;\n",
434 " return found_index;\n",
435 " },\n",
435 " },\n",
436 " \n",
436 " \n",
437 " find_link: function(source_id, target_id){\n",
437 " find_link: function(source_id, target_id){\n",
438 " for (var index in this.links) {\n",
438 " for (var index in this.links) {\n",
439 " if (this.links[index].source.id == source_id && this.links[index].target.id == target_id) {\n",
439 " if (this.links[index].source.id == source_id && this.links[index].target.id == target_id) {\n",
440 " return index;\n",
440 " return index;\n",
441 " }\n",
441 " }\n",
442 " }\n",
442 " }\n",
443 " return -1;\n",
443 " return -1;\n",
444 " },\n",
444 " },\n",
445 " \n",
445 " \n",
446 " try_add_link: function(source_id, target_id){\n",
446 " try_add_link: function(source_id, target_id){\n",
447 " var index = this.find_link(source_id, target_id);\n",
447 " var index = this.find_link(source_id, target_id);\n",
448 " if (index == -1) {\n",
448 " if (index == -1) {\n",
449 " var source_node = this.try_add_node(source_id);\n",
449 " var source_node = this.try_add_node(source_id);\n",
450 " var target_node = this.try_add_node(target_id);\n",
450 " var target_node = this.try_add_node(target_id);\n",
451 " var new_link = {source: source_node, target: target_node};\n",
451 " var new_link = {source: source_node, target: target_node};\n",
452 " this.links.push(new_link);\n",
452 " this.links.push(new_link);\n",
453 " return new_link;\n",
453 " return new_link;\n",
454 " } else {\n",
454 " } else {\n",
455 " return this.links[index]\n",
455 " return this.links[index]\n",
456 " }\n",
456 " }\n",
457 " },\n",
457 " },\n",
458 " \n",
458 " \n",
459 " update_link: function(link, attributes){\n",
459 " update_link: function(link, attributes){\n",
460 " if (link != null) {\n",
460 " if (link != null) {\n",
461 " for (var key in attributes) {\n",
461 " for (var key in attributes) {\n",
462 " link[key] = attributes[key];\n",
462 " link[key] = attributes[key];\n",
463 " }\n",
463 " }\n",
464 " this._update_edge(d3.select('#' + this.guid + link.source.id + \"-\" + link.target.id));\n",
464 " this._update_edge(d3.select('#' + this.guid + link.source.id + \"-\" + link.target.id));\n",
465 " }\n",
465 " }\n",
466 " },\n",
466 " },\n",
467 " \n",
467 " \n",
468 " remove_links: function(source_id){\n",
468 " remove_links: function(source_id){\n",
469 " var found_indicies = [];\n",
469 " var found_indicies = [];\n",
470 " for (var index in this.links) {\n",
470 " for (var index in this.links) {\n",
471 " if (this.links[index].source.id == source_id) {\n",
471 " if (this.links[index].source.id == source_id) {\n",
472 " found_indicies.push(index);\n",
472 " found_indicies.push(index);\n",
473 " }\n",
473 " }\n",
474 " }\n",
474 " }\n",
475 " found_indicies.reverse();\n",
475 " found_indicies.reverse();\n",
476 " \n",
476 " \n",
477 " for (var index in found_indicies) {\n",
477 " for (var index in found_indicies) {\n",
478 " this.links.splice(index, 1);\n",
478 " this.links.splice(index, 1);\n",
479 " };\n",
479 " };\n",
480 " },\n",
480 " },\n",
481 " \n",
481 " \n",
482 " remove_links_to: function(id){\n",
482 " remove_links_to: function(id){\n",
483 " var found_indicies = [];\n",
483 " var found_indicies = [];\n",
484 " for (var index in this.links) {\n",
484 " for (var index in this.links) {\n",
485 " if (this.links[index].source.id == id || this.links[index].target.id == id) {\n",
485 " if (this.links[index].source.id == id || this.links[index].target.id == id) {\n",
486 " found_indicies.push(index);\n",
486 " found_indicies.push(index);\n",
487 " }\n",
487 " }\n",
488 " }\n",
488 " }\n",
489 " found_indicies.reverse();\n",
489 " found_indicies.reverse();\n",
490 " \n",
490 " \n",
491 " for (var index in found_indicies) {\n",
491 " for (var index in found_indicies) {\n",
492 " this.links.splice(index, 1);\n",
492 " this.links.splice(index, 1);\n",
493 " };\n",
493 " };\n",
494 " },\n",
494 " },\n",
495 " \n",
495 " \n",
496 " handle_msg: function(content){\n",
496 " handle_msg: function(content){\n",
497 " var dict = content.dict;\n",
497 " var dict = content.dict;\n",
498 " var action = content.action;\n",
498 " var action = content.action;\n",
499 " var key = content.key;\n",
499 " var key = content.key;\n",
500 " \n",
500 " \n",
501 " if (dict=='node') {\n",
501 " if (dict=='node') {\n",
502 " if (action=='add' || action=='set') {\n",
502 " if (action=='add' || action=='set') {\n",
503 " this.update_node(this.try_add_node(key), content.value)\n",
503 " this.update_node(this.try_add_node(key), content.value)\n",
504 " } else if (action=='del') {\n",
504 " } else if (action=='del') {\n",
505 " this.remove_node(key);\n",
505 " this.remove_node(key);\n",
506 " }\n",
506 " }\n",
507 " \n",
507 " \n",
508 " } else if (dict=='adj') {\n",
508 " } else if (dict=='adj') {\n",
509 " if (action=='add' || action=='set') {\n",
509 " if (action=='add' || action=='set') {\n",
510 " var links = content.value;\n",
510 " var links = content.value;\n",
511 " for (var target_id in links) {\n",
511 " for (var target_id in links) {\n",
512 " this.update_link(this.try_add_link(key, target_id), links[target_id]);\n",
512 " this.update_link(this.try_add_link(key, target_id), links[target_id]);\n",
513 " }\n",
513 " }\n",
514 " } else if (action=='del') {\n",
514 " } else if (action=='del') {\n",
515 " this.remove_links(key);\n",
515 " this.remove_links(key);\n",
516 " }\n",
516 " }\n",
517 " }\n",
517 " }\n",
518 " this.start();\n",
518 " this.start();\n",
519 " },\n",
519 " },\n",
520 " \n",
520 " \n",
521 " start: function() {\n",
521 " start: function() {\n",
522 " var node = this.svg.selectAll(\".node\"),\n",
522 " var node = this.svg.selectAll(\".node\"),\n",
523 " link = this.svg.selectAll(\".link\");\n",
523 " link = this.svg.selectAll(\".link\");\n",
524 " \n",
524 " \n",
525 " var link = link.data(this.force.links(), function(d) { return d.source.id + \"-\" + d.target.id; });\n",
525 " var link = link.data(this.force.links(), function(d) { return d.source.id + \"-\" + d.target.id; });\n",
526 " this._update_edge(link.enter().insert(\"line\", \".node\"))\n",
526 " this._update_edge(link.enter().insert(\"line\", \".node\"))\n",
527 " link.exit().remove();\n",
527 " link.exit().remove();\n",
528 " \n",
528 " \n",
529 " var node = node.data(this.force.nodes(), function(d) { return d.id;});\n",
529 " var node = node.data(this.force.nodes(), function(d) { return d.id;});\n",
530 " var that = this;\n",
530 " var that = this;\n",
531 " this._update_node(node.enter().append(\"circle\"));\n",
531 " this._update_node(node.enter().append(\"circle\"));\n",
532 " node.exit().remove();\n",
532 " node.exit().remove();\n",
533 " \n",
533 " \n",
534 " this.force.start();\n",
534 " this.force.start();\n",
535 " },\n",
535 " },\n",
536 " \n",
536 " \n",
537 " _update_node: function(node) {\n",
537 " _update_node: function(node) {\n",
538 " var that = this;\n",
538 " var that = this;\n",
539 " node\n",
539 " node\n",
540 " .attr(\"id\", function(d) { return that.guid + d.id; })\n",
540 " .attr(\"id\", function(d) { return that.guid + d.id; })\n",
541 " .attr(\"class\", function(d) { return \"node \" + d.id; })\n",
541 " .attr(\"class\", function(d) { return \"node \" + d.id; })\n",
542 " .attr(\"r\", function(d) {\n",
542 " .attr(\"r\", function(d) {\n",
543 " if (d.r == undefined) {\n",
543 " if (d.r == undefined) {\n",
544 " return 8; \n",
544 " return 8; \n",
545 " } else {\n",
545 " } else {\n",
546 " return d.r;\n",
546 " return d.r;\n",
547 " }\n",
547 " }\n",
548 " \n",
548 " \n",
549 " })\n",
549 " })\n",
550 " .style(\"fill\", function(d) {\n",
550 " .style(\"fill\", function(d) {\n",
551 " if (d.fill == undefined) {\n",
551 " if (d.fill == undefined) {\n",
552 " return that.color(d.group); \n",
552 " return that.color(d.group); \n",
553 " } else {\n",
553 " } else {\n",
554 " return d.fill;\n",
554 " return d.fill;\n",
555 " }\n",
555 " }\n",
556 " \n",
556 " \n",
557 " })\n",
557 " })\n",
558 " .style(\"stroke\", function(d) {\n",
558 " .style(\"stroke\", function(d) {\n",
559 " if (d.stroke == undefined) {\n",
559 " if (d.stroke == undefined) {\n",
560 " return \"#FFF\"; \n",
560 " return \"#FFF\"; \n",
561 " } else {\n",
561 " } else {\n",
562 " return d.stroke;\n",
562 " return d.stroke;\n",
563 " }\n",
563 " }\n",
564 " \n",
564 " \n",
565 " })\n",
565 " })\n",
566 " .style(\"stroke-width\", function(d) {\n",
566 " .style(\"stroke-width\", function(d) {\n",
567 " if (d.strokewidth == undefined) {\n",
567 " if (d.strokewidth == undefined) {\n",
568 " return \"#FFF\"; \n",
568 " return \"#FFF\"; \n",
569 " } else {\n",
569 " } else {\n",
570 " return d.strokewidth;\n",
570 " return d.strokewidth;\n",
571 " }\n",
571 " }\n",
572 " \n",
572 " \n",
573 " })\n",
573 " })\n",
574 " .call(this.force.drag);\n",
574 " .call(this.force.drag);\n",
575 " },\n",
575 " },\n",
576 " \n",
576 " \n",
577 " _update_edge: function(edge) {\n",
577 " _update_edge: function(edge) {\n",
578 " var that = this;\n",
578 " var that = this;\n",
579 " edge\n",
579 " edge\n",
580 " .attr(\"id\", function(d) { return that.guid + d.source.id + \"-\" + d.target.id; })\n",
580 " .attr(\"id\", function(d) { return that.guid + d.source.id + \"-\" + d.target.id; })\n",
581 " .attr(\"class\", \"link\")\n",
581 " .attr(\"class\", \"link\")\n",
582 " .style(\"stroke-width\", function(d) {\n",
582 " .style(\"stroke-width\", function(d) {\n",
583 " if (d.strokewidth == undefined) {\n",
583 " if (d.strokewidth == undefined) {\n",
584 " return \"1.5px\"; \n",
584 " return \"1.5px\"; \n",
585 " } else {\n",
585 " } else {\n",
586 " return d.strokewidth;\n",
586 " return d.strokewidth;\n",
587 " }\n",
587 " }\n",
588 " \n",
588 " \n",
589 " })\n",
589 " })\n",
590 " .style('stroke', function(d) {\n",
590 " .style('stroke', function(d) {\n",
591 " if (d.stroke == undefined) {\n",
591 " if (d.stroke == undefined) {\n",
592 " return \"#999\"; \n",
592 " return \"#999\"; \n",
593 " } else {\n",
593 " } else {\n",
594 " return d.stroke;\n",
594 " return d.stroke;\n",
595 " }\n",
595 " }\n",
596 " \n",
596 " \n",
597 " });\n",
597 " });\n",
598 " },\n",
598 " },\n",
599 " \n",
599 " \n",
600 " tick: function() {\n",
600 " tick: function() {\n",
601 " var node = this.svg.selectAll(\".node\"),\n",
601 " var node = this.svg.selectAll(\".node\"),\n",
602 " link = this.svg.selectAll(\".link\");\n",
602 " link = this.svg.selectAll(\".link\");\n",
603 " \n",
603 " \n",
604 " link.attr(\"x1\", function(d) { return d.source.x; })\n",
604 " link.attr(\"x1\", function(d) { return d.source.x; })\n",
605 " .attr(\"y1\", function(d) { return d.source.y; })\n",
605 " .attr(\"y1\", function(d) { return d.source.y; })\n",
606 " .attr(\"x2\", function(d) { return d.target.x; })\n",
606 " .attr(\"x2\", function(d) { return d.target.x; })\n",
607 " .attr(\"y2\", function(d) { return d.target.y; });\n",
607 " .attr(\"y2\", function(d) { return d.target.y; });\n",
608 " \n",
608 " \n",
609 " node.attr(\"cx\", function(d) { return d.x; })\n",
609 " node.attr(\"cx\", function(d) { return d.x; })\n",
610 " .attr(\"cy\", function(d) { return d.y; });\n",
610 " .attr(\"cy\", function(d) { return d.y; });\n",
611 " },\n",
611 " },\n",
612 " \n",
612 " \n",
613 " update: function(){\n",
613 " update: function(){\n",
614 " if (!this.has_drawn) {\n",
614 " if (!this.has_drawn) {\n",
615 " this.has_drawn = true;\n",
615 " this.has_drawn = true;\n",
616 " \n",
616 " \n",
617 " var width = this.model.get('width'),\n",
617 " var width = this.model.get('width'),\n",
618 " height = this.model.get('height');\n",
618 " height = this.model.get('height');\n",
619 " \n",
619 " \n",
620 " this.color = d3.scale.category20();\n",
620 " this.color = d3.scale.category20();\n",
621 " \n",
621 " \n",
622 " this.nodes = [];\n",
622 " this.nodes = [];\n",
623 " this.links = [];\n",
623 " this.links = [];\n",
624 " \n",
624 " \n",
625 " this.force = d3.layout.force()\n",
625 " this.force = d3.layout.force()\n",
626 " .nodes(this.nodes)\n",
626 " .nodes(this.nodes)\n",
627 " .links(this.links)\n",
627 " .links(this.links)\n",
628 " .charge(function (d) {\n",
628 " .charge(function (d) {\n",
629 " if (d.charge === undefined) {\n",
629 " if (d.charge === undefined) {\n",
630 " return -120;\n",
630 " return -120;\n",
631 " } else {\n",
631 " } else {\n",
632 " return d.charge;\n",
632 " return d.charge;\n",
633 " }\n",
633 " }\n",
634 " })\n",
634 " })\n",
635 " .linkDistance(function (d) {\n",
635 " .linkDistance(function (d) {\n",
636 " if (d.distance === undefined) {\n",
636 " if (d.distance === undefined) {\n",
637 " return 40;\n",
637 " return 40;\n",
638 " } else {\n",
638 " } else {\n",
639 " return d.distance;\n",
639 " return d.distance;\n",
640 " }\n",
640 " }\n",
641 " })\n",
641 " })\n",
642 " .linkStrength(function (d) {\n",
642 " .linkStrength(function (d) {\n",
643 " if (d.strength === undefined) {\n",
643 " if (d.strength === undefined) {\n",
644 " return 1.0;\n",
644 " return 1.0;\n",
645 " } else {\n",
645 " } else {\n",
646 " return d.strength;\n",
646 " return d.strength;\n",
647 " }\n",
647 " }\n",
648 " })\n",
648 " })\n",
649 " .size([width, height])\n",
649 " .size([width, height])\n",
650 " .on(\"tick\", $.proxy(this.tick, this));\n",
650 " .on(\"tick\", $.proxy(this.tick, this));\n",
651 " \n",
651 " \n",
652 " this.svg = d3.select(\"#\" + this.guid).append(\"svg\")\n",
652 " this.svg = d3.select(\"#\" + this.guid).append(\"svg\")\n",
653 " .attr(\"width\", width)\n",
653 " .attr(\"width\", width)\n",
654 " .attr(\"height\", height);\n",
654 " .attr(\"height\", height);\n",
655 " \n",
655 " \n",
656 " var that = this;\n",
656 " var that = this;\n",
657 " setTimeout(function() {\n",
657 " setTimeout(function() {\n",
658 " that.start();\n",
658 " that.start();\n",
659 " }, 0);\n",
659 " }, 0);\n",
660 " }\n",
660 " }\n",
661 " \n",
661 " \n",
662 " return IPython.WidgetView.prototype.update.call(this);\n",
662 " return IPython.WidgetView.prototype.update.call(this);\n",
663 " },\n",
663 " },\n",
664 " \n",
664 " \n",
665 " });\n",
665 " });\n",
666 " \n",
666 " \n",
667 " // Register the D3ForceDirectedGraphView with the widget manager.\n",
667 " // Register the D3ForceDirectedGraphView with the widget manager.\n",
668 " IPython.widget_manager.register_widget_view('D3ForceDirectedGraphView', D3ForceDirectedGraphView);\n",
668 " IPython.widget_manager.register_widget_view('D3ForceDirectedGraphView', D3ForceDirectedGraphView);\n",
669 "});"
669 "});"
670 ],
670 ],
671 "language": "python",
671 "language": "python",
672 "metadata": {},
672 "metadata": {},
673 "outputs": [
673 "outputs": [
674 {
674 {
675 "javascript": [
675 "javascript": [
676 "\n",
676 "\n",
677 "require([\"http://d3js.org/d3.v3.min.js\", \"notebook/js/widget\"], function(){\n",
677 "require([\"http://d3js.org/d3.v3.min.js\", \"notebook/js/widget\"], function(){\n",
678 " \n",
678 " \n",
679 " // Define the ForceDirectedGraphModel and register it with the widget manager.\n",
679 " // Define the ForceDirectedGraphModel and register it with the widget manager.\n",
680 " var ForceDirectedGraphModel = IPython.WidgetModel.extend({});\n",
680 " var ForceDirectedGraphModel = IPython.WidgetModel.extend({});\n",
681 " IPython.widget_manager.register_widget_model('ForceDirectedGraphModel', ForceDirectedGraphModel);\n",
681 " IPython.widget_manager.register_widget_model('ForceDirectedGraphModel', ForceDirectedGraphModel);\n",
682 " \n",
682 " \n",
683 " // Define the D3ForceDirectedGraphView\n",
683 " // Define the D3ForceDirectedGraphView\n",
684 " var D3ForceDirectedGraphView = IPython.WidgetView.extend({\n",
684 " var D3ForceDirectedGraphView = IPython.WidgetView.extend({\n",
685 " \n",
685 " \n",
686 " render: function(){\n",
686 " render: function(){\n",
687 " this.guid = 'd3force' + IPython.utils.uuid();\n",
687 " this.guid = 'd3force' + IPython.utils.uuid();\n",
688 " this.setElement($('<div />', {id: this.guid}));\n",
688 " this.setElement($('<div />', {id: this.guid}));\n",
689 " this.model.on_msg($.proxy(this.handle_msg, this));\n",
689 " this.model.on_msg($.proxy(this.handle_msg, this));\n",
690 " this.has_drawn = false;\n",
690 " this.has_drawn = false;\n",
691 " },\n",
691 " },\n",
692 " \n",
692 " \n",
693 " try_add_node: function(id){\n",
693 " try_add_node: function(id){\n",
694 " var index = this.find_node(id);\n",
694 " var index = this.find_node(id);\n",
695 " if (index == -1) {\n",
695 " if (index == -1) {\n",
696 " var node = {id: id};\n",
696 " var node = {id: id};\n",
697 " this.nodes.push(node);\n",
697 " this.nodes.push(node);\n",
698 " return node;\n",
698 " return node;\n",
699 " } else {\n",
699 " } else {\n",
700 " return this.nodes[index];\n",
700 " return this.nodes[index];\n",
701 " }\n",
701 " }\n",
702 " },\n",
702 " },\n",
703 " \n",
703 " \n",
704 " update_node: function(node, attributes) {\n",
704 " update_node: function(node, attributes) {\n",
705 " if (node !== null) {\n",
705 " if (node !== null) {\n",
706 " for (var key in attributes) {\n",
706 " for (var key in attributes) {\n",
707 " node[key] = attributes[key];\n",
707 " node[key] = attributes[key];\n",
708 " }\n",
708 " }\n",
709 " this._update_node(d3.select('#' + this.guid + node.id));\n",
709 " this._update_node(d3.select('#' + this.guid + node.id));\n",
710 " }\n",
710 " }\n",
711 " },\n",
711 " },\n",
712 " \n",
712 " \n",
713 " remove_node: function(id){\n",
713 " remove_node: function(id){\n",
714 " this.remove_links_to(id);\n",
714 " this.remove_links_to(id);\n",
715 " \n",
715 " \n",
716 " var found_index = this.find_node(id);\n",
716 " var found_index = this.find_node(id);\n",
717 " if (found_index>=0) {\n",
717 " if (found_index>=0) {\n",
718 " this.nodes.splice(found_index, 1);\n",
718 " this.nodes.splice(found_index, 1);\n",
719 " }\n",
719 " }\n",
720 " },\n",
720 " },\n",
721 " \n",
721 " \n",
722 " find_node: function(id){\n",
722 " find_node: function(id){\n",
723 " var found_index = -1;\n",
723 " var found_index = -1;\n",
724 " for (var index in this.nodes) {\n",
724 " for (var index in this.nodes) {\n",
725 " if (this.nodes[index].id == id) {\n",
725 " if (this.nodes[index].id == id) {\n",
726 " found_index = index;\n",
726 " found_index = index;\n",
727 " break;\n",
727 " break;\n",
728 " }\n",
728 " }\n",
729 " }\n",
729 " }\n",
730 " return found_index;\n",
730 " return found_index;\n",
731 " },\n",
731 " },\n",
732 " \n",
732 " \n",
733 " find_link: function(source_id, target_id){\n",
733 " find_link: function(source_id, target_id){\n",
734 " for (var index in this.links) {\n",
734 " for (var index in this.links) {\n",
735 " if (this.links[index].source.id == source_id && this.links[index].target.id == target_id) {\n",
735 " if (this.links[index].source.id == source_id && this.links[index].target.id == target_id) {\n",
736 " return index;\n",
736 " return index;\n",
737 " }\n",
737 " }\n",
738 " }\n",
738 " }\n",
739 " return -1;\n",
739 " return -1;\n",
740 " },\n",
740 " },\n",
741 " \n",
741 " \n",
742 " try_add_link: function(source_id, target_id){\n",
742 " try_add_link: function(source_id, target_id){\n",
743 " var index = this.find_link(source_id, target_id);\n",
743 " var index = this.find_link(source_id, target_id);\n",
744 " if (index == -1) {\n",
744 " if (index == -1) {\n",
745 " var source_node = this.try_add_node(source_id);\n",
745 " var source_node = this.try_add_node(source_id);\n",
746 " var target_node = this.try_add_node(target_id);\n",
746 " var target_node = this.try_add_node(target_id);\n",
747 " var new_link = {source: source_node, target: target_node};\n",
747 " var new_link = {source: source_node, target: target_node};\n",
748 " this.links.push(new_link);\n",
748 " this.links.push(new_link);\n",
749 " return new_link;\n",
749 " return new_link;\n",
750 " } else {\n",
750 " } else {\n",
751 " return this.links[index]\n",
751 " return this.links[index]\n",
752 " }\n",
752 " }\n",
753 " },\n",
753 " },\n",
754 " \n",
754 " \n",
755 " update_link: function(link, attributes){\n",
755 " update_link: function(link, attributes){\n",
756 " if (link != null) {\n",
756 " if (link != null) {\n",
757 " for (var key in attributes) {\n",
757 " for (var key in attributes) {\n",
758 " link[key] = attributes[key];\n",
758 " link[key] = attributes[key];\n",
759 " }\n",
759 " }\n",
760 " this._update_edge(d3.select('#' + this.guid + link.source.id + \"-\" + link.target.id));\n",
760 " this._update_edge(d3.select('#' + this.guid + link.source.id + \"-\" + link.target.id));\n",
761 " }\n",
761 " }\n",
762 " },\n",
762 " },\n",
763 " \n",
763 " \n",
764 " remove_links: function(source_id){\n",
764 " remove_links: function(source_id){\n",
765 " var found_indicies = [];\n",
765 " var found_indicies = [];\n",
766 " for (var index in this.links) {\n",
766 " for (var index in this.links) {\n",
767 " if (this.links[index].source.id == source_id) {\n",
767 " if (this.links[index].source.id == source_id) {\n",
768 " found_indicies.push(index);\n",
768 " found_indicies.push(index);\n",
769 " }\n",
769 " }\n",
770 " }\n",
770 " }\n",
771 " found_indicies.reverse();\n",
771 " found_indicies.reverse();\n",
772 " \n",
772 " \n",
773 " for (var index in found_indicies) {\n",
773 " for (var index in found_indicies) {\n",
774 " this.links.splice(index, 1);\n",
774 " this.links.splice(index, 1);\n",
775 " };\n",
775 " };\n",
776 " },\n",
776 " },\n",
777 " \n",
777 " \n",
778 " remove_links_to: function(id){\n",
778 " remove_links_to: function(id){\n",
779 " var found_indicies = [];\n",
779 " var found_indicies = [];\n",
780 " for (var index in this.links) {\n",
780 " for (var index in this.links) {\n",
781 " if (this.links[index].source.id == id || this.links[index].target.id == id) {\n",
781 " if (this.links[index].source.id == id || this.links[index].target.id == id) {\n",
782 " found_indicies.push(index);\n",
782 " found_indicies.push(index);\n",
783 " }\n",
783 " }\n",
784 " }\n",
784 " }\n",
785 " found_indicies.reverse();\n",
785 " found_indicies.reverse();\n",
786 " \n",
786 " \n",
787 " for (var index in found_indicies) {\n",
787 " for (var index in found_indicies) {\n",
788 " this.links.splice(index, 1);\n",
788 " this.links.splice(index, 1);\n",
789 " };\n",
789 " };\n",
790 " },\n",
790 " },\n",
791 " \n",
791 " \n",
792 " handle_msg: function(content){\n",
792 " handle_msg: function(content){\n",
793 " var dict = content.dict;\n",
793 " var dict = content.dict;\n",
794 " var action = content.action;\n",
794 " var action = content.action;\n",
795 " var key = content.key;\n",
795 " var key = content.key;\n",
796 " \n",
796 " \n",
797 " if (dict=='node') {\n",
797 " if (dict=='node') {\n",
798 " if (action=='add' || action=='set') {\n",
798 " if (action=='add' || action=='set') {\n",
799 " this.update_node(this.try_add_node(key), content.value)\n",
799 " this.update_node(this.try_add_node(key), content.value)\n",
800 " } else if (action=='del') {\n",
800 " } else if (action=='del') {\n",
801 " this.remove_node(key);\n",
801 " this.remove_node(key);\n",
802 " }\n",
802 " }\n",
803 " \n",
803 " \n",
804 " } else if (dict=='adj') {\n",
804 " } else if (dict=='adj') {\n",
805 " if (action=='add' || action=='set') {\n",
805 " if (action=='add' || action=='set') {\n",
806 " var links = content.value;\n",
806 " var links = content.value;\n",
807 " for (var target_id in links) {\n",
807 " for (var target_id in links) {\n",
808 " this.update_link(this.try_add_link(key, target_id), links[target_id]);\n",
808 " this.update_link(this.try_add_link(key, target_id), links[target_id]);\n",
809 " }\n",
809 " }\n",
810 " } else if (action=='del') {\n",
810 " } else if (action=='del') {\n",
811 " this.remove_links(key);\n",
811 " this.remove_links(key);\n",
812 " }\n",
812 " }\n",
813 " }\n",
813 " }\n",
814 " this.start();\n",
814 " this.start();\n",
815 " },\n",
815 " },\n",
816 " \n",
816 " \n",
817 " start: function() {\n",
817 " start: function() {\n",
818 " var node = this.svg.selectAll(\".node\"),\n",
818 " var node = this.svg.selectAll(\".node\"),\n",
819 " link = this.svg.selectAll(\".link\");\n",
819 " link = this.svg.selectAll(\".link\");\n",
820 " \n",
820 " \n",
821 " var link = link.data(this.force.links(), function(d) { return d.source.id + \"-\" + d.target.id; });\n",
821 " var link = link.data(this.force.links(), function(d) { return d.source.id + \"-\" + d.target.id; });\n",
822 " this._update_edge(link.enter().insert(\"line\", \".node\"))\n",
822 " this._update_edge(link.enter().insert(\"line\", \".node\"))\n",
823 " link.exit().remove();\n",
823 " link.exit().remove();\n",
824 " \n",
824 " \n",
825 " var node = node.data(this.force.nodes(), function(d) { return d.id;});\n",
825 " var node = node.data(this.force.nodes(), function(d) { return d.id;});\n",
826 " var that = this;\n",
826 " var that = this;\n",
827 " this._update_node(node.enter().append(\"circle\"));\n",
827 " this._update_node(node.enter().append(\"circle\"));\n",
828 " node.exit().remove();\n",
828 " node.exit().remove();\n",
829 " \n",
829 " \n",
830 " this.force.start();\n",
830 " this.force.start();\n",
831 " },\n",
831 " },\n",
832 " \n",
832 " \n",
833 " _update_node: function(node) {\n",
833 " _update_node: function(node) {\n",
834 " var that = this;\n",
834 " var that = this;\n",
835 " node\n",
835 " node\n",
836 " .attr(\"id\", function(d) { return that.guid + d.id; })\n",
836 " .attr(\"id\", function(d) { return that.guid + d.id; })\n",
837 " .attr(\"class\", function(d) { return \"node \" + d.id; })\n",
837 " .attr(\"class\", function(d) { return \"node \" + d.id; })\n",
838 " .attr(\"r\", function(d) {\n",
838 " .attr(\"r\", function(d) {\n",
839 " if (d.r == undefined) {\n",
839 " if (d.r == undefined) {\n",
840 " return 8; \n",
840 " return 8; \n",
841 " } else {\n",
841 " } else {\n",
842 " return d.r;\n",
842 " return d.r;\n",
843 " }\n",
843 " }\n",
844 " \n",
844 " \n",
845 " })\n",
845 " })\n",
846 " .style(\"fill\", function(d) {\n",
846 " .style(\"fill\", function(d) {\n",
847 " if (d.fill == undefined) {\n",
847 " if (d.fill == undefined) {\n",
848 " return that.color(d.group); \n",
848 " return that.color(d.group); \n",
849 " } else {\n",
849 " } else {\n",
850 " return d.fill;\n",
850 " return d.fill;\n",
851 " }\n",
851 " }\n",
852 " \n",
852 " \n",
853 " })\n",
853 " })\n",
854 " .style(\"stroke\", function(d) {\n",
854 " .style(\"stroke\", function(d) {\n",
855 " if (d.stroke == undefined) {\n",
855 " if (d.stroke == undefined) {\n",
856 " return \"#FFF\"; \n",
856 " return \"#FFF\"; \n",
857 " } else {\n",
857 " } else {\n",
858 " return d.stroke;\n",
858 " return d.stroke;\n",
859 " }\n",
859 " }\n",
860 " \n",
860 " \n",
861 " })\n",
861 " })\n",
862 " .style(\"stroke-width\", function(d) {\n",
862 " .style(\"stroke-width\", function(d) {\n",
863 " if (d.strokewidth == undefined) {\n",
863 " if (d.strokewidth == undefined) {\n",
864 " return \"#FFF\"; \n",
864 " return \"#FFF\"; \n",
865 " } else {\n",
865 " } else {\n",
866 " return d.strokewidth;\n",
866 " return d.strokewidth;\n",
867 " }\n",
867 " }\n",
868 " \n",
868 " \n",
869 " })\n",
869 " })\n",
870 " .call(this.force.drag);\n",
870 " .call(this.force.drag);\n",
871 " },\n",
871 " },\n",
872 " \n",
872 " \n",
873 " _update_edge: function(edge) {\n",
873 " _update_edge: function(edge) {\n",
874 " var that = this;\n",
874 " var that = this;\n",
875 " edge\n",
875 " edge\n",
876 " .attr(\"id\", function(d) { return that.guid + d.source.id + \"-\" + d.target.id; })\n",
876 " .attr(\"id\", function(d) { return that.guid + d.source.id + \"-\" + d.target.id; })\n",
877 " .attr(\"class\", \"link\")\n",
877 " .attr(\"class\", \"link\")\n",
878 " .style(\"stroke-width\", function(d) {\n",
878 " .style(\"stroke-width\", function(d) {\n",
879 " if (d.strokewidth == undefined) {\n",
879 " if (d.strokewidth == undefined) {\n",
880 " return \"1.5px\"; \n",
880 " return \"1.5px\"; \n",
881 " } else {\n",
881 " } else {\n",
882 " return d.strokewidth;\n",
882 " return d.strokewidth;\n",
883 " }\n",
883 " }\n",
884 " \n",
884 " \n",
885 " })\n",
885 " })\n",
886 " .style('stroke', function(d) {\n",
886 " .style('stroke', function(d) {\n",
887 " if (d.stroke == undefined) {\n",
887 " if (d.stroke == undefined) {\n",
888 " return \"#999\"; \n",
888 " return \"#999\"; \n",
889 " } else {\n",
889 " } else {\n",
890 " return d.stroke;\n",
890 " return d.stroke;\n",
891 " }\n",
891 " }\n",
892 " \n",
892 " \n",
893 " });\n",
893 " });\n",
894 " },\n",
894 " },\n",
895 " \n",
895 " \n",
896 " tick: function() {\n",
896 " tick: function() {\n",
897 " var node = this.svg.selectAll(\".node\"),\n",
897 " var node = this.svg.selectAll(\".node\"),\n",
898 " link = this.svg.selectAll(\".link\");\n",
898 " link = this.svg.selectAll(\".link\");\n",
899 " \n",
899 " \n",
900 " link.attr(\"x1\", function(d) { return d.source.x; })\n",
900 " link.attr(\"x1\", function(d) { return d.source.x; })\n",
901 " .attr(\"y1\", function(d) { return d.source.y; })\n",
901 " .attr(\"y1\", function(d) { return d.source.y; })\n",
902 " .attr(\"x2\", function(d) { return d.target.x; })\n",
902 " .attr(\"x2\", function(d) { return d.target.x; })\n",
903 " .attr(\"y2\", function(d) { return d.target.y; });\n",
903 " .attr(\"y2\", function(d) { return d.target.y; });\n",
904 " \n",
904 " \n",
905 " node.attr(\"cx\", function(d) { return d.x; })\n",
905 " node.attr(\"cx\", function(d) { return d.x; })\n",
906 " .attr(\"cy\", function(d) { return d.y; });\n",
906 " .attr(\"cy\", function(d) { return d.y; });\n",
907 " },\n",
907 " },\n",
908 " \n",
908 " \n",
909 " update: function(){\n",
909 " update: function(){\n",
910 " if (!this.has_drawn) {\n",
910 " if (!this.has_drawn) {\n",
911 " this.has_drawn = true;\n",
911 " this.has_drawn = true;\n",
912 " \n",
912 " \n",
913 " var width = this.model.get('width'),\n",
913 " var width = this.model.get('width'),\n",
914 " height = this.model.get('height');\n",
914 " height = this.model.get('height');\n",
915 " \n",
915 " \n",
916 " this.color = d3.scale.category20();\n",
916 " this.color = d3.scale.category20();\n",
917 " \n",
917 " \n",
918 " this.nodes = [];\n",
918 " this.nodes = [];\n",
919 " this.links = [];\n",
919 " this.links = [];\n",
920 " \n",
920 " \n",
921 " this.force = d3.layout.force()\n",
921 " this.force = d3.layout.force()\n",
922 " .nodes(this.nodes)\n",
922 " .nodes(this.nodes)\n",
923 " .links(this.links)\n",
923 " .links(this.links)\n",
924 " .charge(function (d) {\n",
924 " .charge(function (d) {\n",
925 " if (d.charge === undefined) {\n",
925 " if (d.charge === undefined) {\n",
926 " return -120;\n",
926 " return -120;\n",
927 " } else {\n",
927 " } else {\n",
928 " return d.charge;\n",
928 " return d.charge;\n",
929 " }\n",
929 " }\n",
930 " })\n",
930 " })\n",
931 " .linkDistance(function (d) {\n",
931 " .linkDistance(function (d) {\n",
932 " if (d.distance === undefined) {\n",
932 " if (d.distance === undefined) {\n",
933 " return 40;\n",
933 " return 40;\n",
934 " } else {\n",
934 " } else {\n",
935 " return d.distance;\n",
935 " return d.distance;\n",
936 " }\n",
936 " }\n",
937 " })\n",
937 " })\n",
938 " .linkStrength(function (d) {\n",
938 " .linkStrength(function (d) {\n",
939 " if (d.strength === undefined) {\n",
939 " if (d.strength === undefined) {\n",
940 " return 1.0;\n",
940 " return 1.0;\n",
941 " } else {\n",
941 " } else {\n",
942 " return d.strength;\n",
942 " return d.strength;\n",
943 " }\n",
943 " }\n",
944 " })\n",
944 " })\n",
945 " .size([width, height])\n",
945 " .size([width, height])\n",
946 " .on(\"tick\", $.proxy(this.tick, this));\n",
946 " .on(\"tick\", $.proxy(this.tick, this));\n",
947 " \n",
947 " \n",
948 " this.svg = d3.select(\"#\" + this.guid).append(\"svg\")\n",
948 " this.svg = d3.select(\"#\" + this.guid).append(\"svg\")\n",
949 " .attr(\"width\", width)\n",
949 " .attr(\"width\", width)\n",
950 " .attr(\"height\", height);\n",
950 " .attr(\"height\", height);\n",
951 " \n",
951 " \n",
952 " var that = this;\n",
952 " var that = this;\n",
953 " setTimeout(function() {\n",
953 " setTimeout(function() {\n",
954 " that.start();\n",
954 " that.start();\n",
955 " }, 0);\n",
955 " }, 0);\n",
956 " }\n",
956 " }\n",
957 " \n",
957 " \n",
958 " return IPython.WidgetView.prototype.update.call(this);\n",
958 " return IPython.WidgetView.prototype.update.call(this);\n",
959 " },\n",
959 " },\n",
960 " \n",
960 " \n",
961 " });\n",
961 " });\n",
962 " \n",
962 " \n",
963 " // Register the D3ForceDirectedGraphView with the widget manager.\n",
963 " // Register the D3ForceDirectedGraphView with the widget manager.\n",
964 " IPython.widget_manager.register_widget_view('D3ForceDirectedGraphView', D3ForceDirectedGraphView);\n",
964 " IPython.widget_manager.register_widget_view('D3ForceDirectedGraphView', D3ForceDirectedGraphView);\n",
965 "});"
965 "});"
966 ],
966 ],
967 "metadata": {},
967 "metadata": {},
968 "output_type": "display_data",
968 "output_type": "display_data",
969 "text": [
969 "text": [
970 "<IPython.core.display.Javascript at 0x278b9d0>"
970 "<IPython.core.display.Javascript at 0x2281b10>"
971 ]
971 ]
972 }
972 }
973 ],
973 ],
974 "prompt_number": 10
974 "prompt_number": 10
975 },
975 },
976 {
976 {
977 "cell_type": "heading",
977 "cell_type": "heading",
978 "level": 1,
978 "level": 1,
979 "metadata": {},
979 "metadata": {},
980 "source": [
980 "source": [
981 "Test"
981 "Test"
982 ]
982 ]
983 },
983 },
984 {
984 {
985 "cell_type": "code",
985 "cell_type": "code",
986 "collapsed": false,
986 "collapsed": false,
987 "input": [
987 "input": [
988 "floating_container = widgets.ContainerWidget(default_view_name='ModalView')\n",
988 "floating_container = widgets.ContainerWidget(default_view_name='ModalView')\n",
989 "floating_container.description = \"Dynamic D3 rendering of a NetworkX graph\"\n",
989 "floating_container.description = \"Dynamic D3 rendering of a NetworkX graph\"\n",
990 "floating_container.button_text = \"Render Window\"\n",
990 "floating_container.button_text = \"Render Window\"\n",
991 "floating_container.set_css({\n",
991 "floating_container.set_css({\n",
992 " 'width': '420px',\n",
992 " 'width': '420px',\n",
993 " 'height': '350px'}, selector='modal')\n",
993 " 'height': '350px'}, selector='modal')\n",
994 "\n",
994 "\n",
995 "G = EventfulGraph()\n",
995 "G = EventfulGraph()\n",
996 "d3 = ForceDirectedGraphWidget(G, parent=floating_container)\n",
996 "d3 = ForceDirectedGraphWidget(G, parent=floating_container)\n",
997 "display(floating_container)"
997 "display(floating_container)"
998 ],
998 ],
999 "language": "python",
999 "language": "python",
1000 "metadata": {},
1000 "metadata": {},
1001 "outputs": [],
1001 "outputs": [],
1002 "prompt_number": 11
1002 "prompt_number": 11
1003 },
1003 },
1004 {
1004 {
1005 "cell_type": "markdown",
1005 "cell_type": "markdown",
1006 "metadata": {},
1006 "metadata": {},
1007 "source": [
1007 "source": [
1008 "The following code creates an animation of some of the plot's properties."
1008 "The following code creates an animation of some of the plot's properties."
1009 ]
1009 ]
1010 },
1010 },
1011 {
1011 {
1012 "cell_type": "code",
1012 "cell_type": "code",
1013 "collapsed": false,
1013 "collapsed": false,
1014 "input": [
1014 "input": [
1015 "import time\n",
1015 "import time\n",
1016 "\n",
1016 "\n",
1017 "G.add_node(1, fill=\"red\", stroke=\"black\")\n",
1017 "G.add_node(1, fill=\"red\", stroke=\"black\")\n",
1018 "time.sleep(1.0)\n",
1018 "time.sleep(1.0)\n",
1019 "\n",
1019 "\n",
1020 "G.add_node(2, fill=\"gold\", stroke=\"black\")\n",
1020 "G.add_node(2, fill=\"gold\", stroke=\"black\")\n",
1021 "time.sleep(1.0)\n",
1021 "time.sleep(1.0)\n",
1022 "\n",
1022 "\n",
1023 "G.add_node(3, fill=\"green\", stroke=\"black\")\n",
1023 "G.add_node(3, fill=\"green\", stroke=\"black\")\n",
1024 "time.sleep(1.0)\n",
1024 "time.sleep(1.0)\n",
1025 "\n",
1025 "\n",
1026 "G.add_edges_from([(1,2),(1,3), (2,3)], stroke=\"#aaa\", strokewidth=\"1px\", distance=200, strength=0.5)\n",
1026 "G.add_edges_from([(1,2),(1,3), (2,3)], stroke=\"#aaa\", strokewidth=\"1px\", distance=200, strength=0.5)\n",
1027 "time.sleep(1.0)\n",
1027 "time.sleep(1.0)\n",
1028 "\n",
1028 "\n",
1029 "G.adj[1][2]['distance'] = 20\n",
1029 "G.adj[1][2]['distance'] = 20\n",
1030 "time.sleep(1.0)\n",
1030 "time.sleep(1.0)\n",
1031 "\n",
1031 "\n",
1032 "G.adj[1][3]['distance'] = 20\n",
1032 "G.adj[1][3]['distance'] = 20\n",
1033 "time.sleep(1.0)\n",
1033 "time.sleep(1.0)\n",
1034 "\n",
1034 "\n",
1035 "G.adj[2][3]['distance'] = 20\n",
1035 "G.adj[2][3]['distance'] = 20\n",
1036 "time.sleep(1.0)\n",
1036 "time.sleep(1.0)\n",
1037 "\n",
1037 "\n",
1038 "G.node[1]['r'] = 16\n",
1038 "G.node[1]['r'] = 16\n",
1039 "time.sleep(0.3)\n",
1039 "time.sleep(0.3)\n",
1040 "G.node[1]['r'] = 8\n",
1040 "G.node[1]['r'] = 8\n",
1041 "G.node[2]['r'] = 16\n",
1041 "G.node[2]['r'] = 16\n",
1042 "time.sleep(0.3)\n",
1042 "time.sleep(0.3)\n",
1043 "G.node[2]['r'] = 8\n",
1043 "G.node[2]['r'] = 8\n",
1044 "G.node[3]['r'] = 16\n",
1044 "G.node[3]['r'] = 16\n",
1045 "time.sleep(0.3)\n",
1045 "time.sleep(0.3)\n",
1046 "G.node[3]['r'] = 8\n",
1046 "G.node[3]['r'] = 8\n",
1047 "\n",
1047 "\n",
1048 "G.node[1]['fill'] = 'purple'\n",
1048 "G.node[1]['fill'] = 'purple'\n",
1049 "time.sleep(0.3)\n",
1049 "time.sleep(0.3)\n",
1050 "G.node[1]['fill'] = 'red'\n",
1050 "G.node[1]['fill'] = 'red'\n",
1051 "G.node[2]['fill'] = 'purple'\n",
1051 "G.node[2]['fill'] = 'purple'\n",
1052 "time.sleep(0.3)\n",
1052 "time.sleep(0.3)\n",
1053 "G.node[2]['fill'] = 'gold'\n",
1053 "G.node[2]['fill'] = 'gold'\n",
1054 "G.node[3]['fill'] = 'purple'\n",
1054 "G.node[3]['fill'] = 'purple'\n",
1055 "time.sleep(0.3)\n",
1055 "time.sleep(0.3)\n",
1056 "G.node[3]['fill'] = 'green'\n",
1056 "G.node[3]['fill'] = 'green'\n",
1057 "time.sleep(1.0)\n",
1057 "time.sleep(1.0)\n",
1058 "\n",
1058 "\n",
1059 "G.node.clear()\n",
1059 "G.node.clear()\n",
1060 "time.sleep(1.0)\n",
1060 "time.sleep(1.0)\n",
1061 "\n",
1061 "\n",
1062 "floating_container.close()\n"
1062 "floating_container.close()\n"
1063 ],
1063 ],
1064 "language": "python",
1064 "language": "python",
1065 "metadata": {},
1065 "metadata": {},
1066 "outputs": [],
1066 "outputs": [],
1067 "prompt_number": 12
1067 "prompt_number": 12
1068 },
1068 },
1069 {
1069 {
1070 "cell_type": "heading",
1070 "cell_type": "heading",
1071 "level": 2,
1071 "level": 2,
1072 "metadata": {},
1072 "metadata": {},
1073 "source": [
1073 "source": [
1074 "Prime Factor Finder"
1074 "Prime Factor Finder"
1075 ]
1075 ]
1076 },
1076 },
1077 {
1077 {
1078 "cell_type": "markdown",
1078 "cell_type": "markdown",
1079 "metadata": {},
1079 "metadata": {},
1080 "source": [
1080 "source": [
1081 "Find the prime numbers inside a large integer"
1081 "Find the prime numbers inside a large integer"
1082 ]
1082 ]
1083 },
1083 },
1084 {
1084 {
1085 "cell_type": "code",
1085 "cell_type": "code",
1086 "collapsed": false,
1086 "collapsed": false,
1087 "input": [
1087 "input": [
1088 "def is_int(number):\n",
1088 "def is_int(number):\n",
1089 " return int(number) == number\n",
1089 " return int(number) == number\n",
1090 "\n",
1090 "\n",
1091 "def factor_int(number):\n",
1091 "def factor_int(number):\n",
1092 " return [i + 1 for i in range(number) if is_int(number / (float(i) + 1.0))] "
1092 " return [i + 1 for i in range(number) if is_int(number / (float(i) + 1.0))] "
1093 ],
1093 ],
1094 "language": "python",
1094 "language": "python",
1095 "metadata": {},
1095 "metadata": {},
1096 "outputs": [],
1096 "outputs": [],
1097 "prompt_number": 13
1097 "prompt_number": 13
1098 },
1098 },
1099 {
1099 {
1100 "cell_type": "code",
1100 "cell_type": "code",
1101 "collapsed": false,
1101 "collapsed": false,
1102 "input": [
1102 "input": [
1103 "import time\n",
1103 "import time\n",
1104 "BACKGROUND = '#F7EBD5'\n",
1104 "BACKGROUND = '#F7EBD5'\n",
1105 "PARENT_COLOR = '#66635D'\n",
1105 "PARENT_COLOR = '#66635D'\n",
1106 "FACTOR_COLOR = '#6CC5C1'\n",
1106 "FACTOR_COLOR = '#6CC5C1'\n",
1107 "EDGE_COLOR = '#000000'\n",
1107 "EDGE_COLOR = '#000000'\n",
1108 "PRIME_COLOR = '#E54140'\n",
1108 "PRIME_COLOR = '#E54140'\n",
1109 "\n",
1109 "\n",
1110 "existing_graphs = []\n",
1110 "existing_graphs = []\n",
1111 "\n",
1111 "\n",
1112 "def add_unique_node(graph, value, **kwargs):\n",
1112 "def add_unique_node(graph, value, **kwargs):\n",
1113 " index = len(graph.node)\n",
1113 " index = len(graph.node)\n",
1114 " graph.add_node(index, charge=-50, strokewidth=0, value=value, **kwargs)\n",
1114 " graph.add_node(index, charge=-50, strokewidth=0, value=value, **kwargs)\n",
1115 " return index\n",
1115 " return index\n",
1116 "\n",
1116 "\n",
1117 "def plot_primes(graph, number, parent, start_number, delay=0.0):\n",
1117 "def plot_primes(graph, number, parent, start_number, delay=0.0):\n",
1118 " if delay > 0.0:\n",
1118 " if delay > 0.0:\n",
1119 " time.sleep(delay)\n",
1119 " time.sleep(delay)\n",
1120 " \n",
1120 " \n",
1121 " factors = factor_int(number)\n",
1121 " factors = factor_int(number)\n",
1122 " if len(factors) > 2:\n",
1122 " if len(factors) > 2:\n",
1123 " for factor in factors:\n",
1123 " for factor in factors:\n",
1124 " if factor != number:\n",
1124 " if factor != number:\n",
1125 " factor_size = max(float(factor) / start_number * 30.0,3.0)\n",
1125 " factor_size = max(float(factor) / start_number * 30.0,3.0)\n",
1126 " parent_factor_size = max(float(number) / start_number * 30.0,3.0)\n",
1126 " parent_factor_size = max(float(number) / start_number * 30.0,3.0)\n",
1127 " index = add_unique_node(graph, number, fill=FACTOR_COLOR, r='%.2fpx' % factor_size)\n",
1127 " index = add_unique_node(graph, number, fill=FACTOR_COLOR, r='%.2fpx' % factor_size)\n",
1128 " graph.add_edge(index, parent, distance=parent_factor_size+factor_size, stroke=EDGE_COLOR)\n",
1128 " graph.add_edge(index, parent, distance=parent_factor_size+factor_size, stroke=EDGE_COLOR)\n",
1129 " plot_primes(graph, factor, parent=index, start_number=start_number, delay=delay)\n",
1129 " plot_primes(graph, factor, parent=index, start_number=start_number, delay=delay)\n",
1130 " else:\n",
1130 " else:\n",
1131 " # Prime, set parent color to prime color.\n",
1131 " # Prime, set parent color to prime color.\n",
1132 " graph.node[parent]['fill'] = PRIME_COLOR\n",
1132 " graph.node[parent]['fill'] = PRIME_COLOR\n",
1133 "\n",
1133 "\n",
1134 "def graph_primes(number, delay):\n",
1134 "def graph_primes(number, delay):\n",
1135 " if len(existing_graphs) > 0:\n",
1135 " if len(existing_graphs) > 0:\n",
1136 " for graph in existing_graphs:\n",
1136 " for graph in existing_graphs:\n",
1137 " graph.close()\n",
1137 " graph.close()\n",
1138 " del existing_graphs[:]\n",
1138 " del existing_graphs[:]\n",
1139 " \n",
1139 " \n",
1140 " floating_container = widgets.ContainerWidget(default_view_name='ModalView')\n",
1140 " floating_container = widgets.ContainerWidget(default_view_name='ModalView')\n",
1141 " floating_container.description = \"Factors of %d\" % number\n",
1141 " floating_container.description = \"Factors of %d\" % number\n",
1142 " floating_container.button_text = str(number)\n",
1142 " floating_container.button_text = str(number)\n",
1143 " floating_container.set_css({\n",
1143 " floating_container.set_css({\n",
1144 " 'width': '620px',\n",
1144 " 'width': '620px',\n",
1145 " 'height': '450px'}, selector='modal')\n",
1145 " 'height': '450px'}, selector='modal')\n",
1146 " \n",
1146 " \n",
1147 " graph = EventfulGraph()\n",
1147 " graph = EventfulGraph()\n",
1148 " d3 = ForceDirectedGraphWidget(graph, parent=floating_container)\n",
1148 " d3 = ForceDirectedGraphWidget(graph, parent=floating_container)\n",
1149 " floating_container.set_css('background', BACKGROUND)\n",
1149 " floating_container.set_css('background', BACKGROUND)\n",
1150 " d3.width = 600\n",
1150 " d3.width = 600\n",
1151 " d3.height = 400\n",
1151 " d3.height = 400\n",
1152 " display(floating_container)\n",
1152 " display(floating_container)\n",
1153 " existing_graphs.append(floating_container)\n",
1153 " existing_graphs.append(floating_container)\n",
1154 " \n",
1154 " \n",
1155 " index = add_unique_node(graph, number, fill=PARENT_COLOR, r='30px')\n",
1155 " index = add_unique_node(graph, number, fill=PARENT_COLOR, r='30px')\n",
1156 " plot_primes(graph, number=number, parent=index, start_number=number, delay=delay)"
1156 " plot_primes(graph, number=number, parent=index, start_number=number, delay=delay)"
1157 ],
1157 ],
1158 "language": "python",
1158 "language": "python",
1159 "metadata": {},
1159 "metadata": {},
1160 "outputs": [],
1160 "outputs": [],
1161 "prompt_number": 14
1161 "prompt_number": 14
1162 },
1162 },
1163 {
1163 {
1164 "cell_type": "code",
1164 "cell_type": "code",
1165 "collapsed": false,
1165 "collapsed": false,
1166 "input": [
1166 "input": [
1167 "box = widgets.ContainerWidget()\n",
1167 "box = widgets.ContainerWidget()\n",
1168 "box.vbox()\n",
1168 "box.vbox()\n",
1169 "box.align_center()\n",
1169 "box.align_center()\n",
1170 "box.pack_center()\n",
1170 "box.pack_center()\n",
1171 "header = widgets.StringWidget(parent=box, default_view_name=\"LabelView\", value=\"<h1>Number Factorizer</h1><br>\")\n",
1171 "header = widgets.StringWidget(parent=box, default_view_name=\"LabelView\", value=\"<h1>Number Factorizer</h1><br>\")\n",
1172 "subbox = widgets.ContainerWidget(parent=box)\n",
1172 "subbox = widgets.ContainerWidget(parent=box)\n",
1173 "subbox.hbox()\n",
1173 "subbox.hbox()\n",
1174 "subbox.align_center()\n",
1174 "subbox.align_center()\n",
1175 "subbox.pack_center()\n",
1175 "subbox.pack_center()\n",
1176 "number = widgets.IntWidget(value=100, parent=subbox)\n",
1176 "number = widgets.IntWidget(value=100, parent=subbox)\n",
1177 "button = widgets.ButtonWidget(description=\"Calculate\", parent=subbox)\n",
1177 "button = widgets.ButtonWidget(description=\"Calculate\", parent=subbox)\n",
1178 "speed = widgets.FloatRangeWidget(parent=box, min=0.0, max=0.5, value=0.4, step=0.01)\n",
1178 "speed = widgets.FloatRangeWidget(parent=box, min=0.0, max=0.5, value=0.4, step=0.01)\n",
1179 "display(box)\n",
1179 "display(box)\n",
1180 "box.add_class('well well-small')\n",
1180 "box.add_class('well well-small')\n",
1181 "\n",
1181 "\n",
1182 "def handle_caclulate():\n",
1182 "def handle_caclulate():\n",
1183 " graph_primes(number.value, 0.5-speed.value)\n",
1183 " graph_primes(number.value, 0.5-speed.value)\n",
1184 "button.on_click(handle_caclulate)\n"
1184 "button.on_click(handle_caclulate)\n"
1185 ],
1185 ],
1186 "language": "python",
1186 "language": "python",
1187 "metadata": {},
1187 "metadata": {},
1188 "outputs": [],
1188 "outputs": [],
1189 "prompt_number": 15
1189 "prompt_number": 15
1190 },
1190 },
1191 {
1191 {
1192 "cell_type": "heading",
1192 "cell_type": "heading",
1193 "level": 2,
1193 "level": 2,
1194 "metadata": {},
1194 "metadata": {},
1195 "source": [
1195 "source": [
1196 "Twitter Tweet Watcher"
1196 "Twitter Tweet Watcher"
1197 ]
1197 ]
1198 },
1198 },
1199 {
1199 {
1200 "cell_type": "markdown",
1200 "cell_type": "markdown",
1201 "metadata": {},
1201 "metadata": {},
1202 "source": [
1202 "source": [
1203 "This example requires the Python \"twitter\" library to be installed (https://github.com/sixohsix/twitter). You can install Python twitter by running `sudo pip install twitter` or `sudo easy_install twitter` from the commandline."
1203 "This example requires the Python \"twitter\" library to be installed (https://github.com/sixohsix/twitter). You can install Python twitter by running `sudo pip install twitter` or `sudo easy_install twitter` from the commandline."
1204 ]
1204 ]
1205 },
1205 },
1206 {
1206 {
1207 "cell_type": "code",
1207 "cell_type": "code",
1208 "collapsed": false,
1208 "collapsed": false,
1209 "input": [
1209 "input": [
1210 "from twitter import *\n",
1210 "from twitter import *\n",
1211 "import time, datetime\n",
1211 "import time, datetime\n",
1212 "import math\n",
1212 "import math\n",
1213 "\n",
1213 "\n",
1214 "twitter_timestamp_format = \"%a %b %d %X +0000 %Y\""
1214 "twitter_timestamp_format = \"%a %b %d %X +0000 %Y\""
1215 ],
1215 ],
1216 "language": "python",
1216 "language": "python",
1217 "metadata": {},
1217 "metadata": {},
1218 "outputs": [],
1218 "outputs": [],
1219 "prompt_number": 16
1219 "prompt_number": 16
1220 },
1220 },
1221 {
1221 {
1222 "cell_type": "code",
1222 "cell_type": "code",
1223 "collapsed": false,
1223 "collapsed": false,
1224 "input": [
1224 "input": [
1225 "# Sign on to twitter.\n",
1225 "# Sign on to twitter.\n",
1226 "auth = OAuth(\n",
1226 "auth = OAuth(\n",
1227 " consumer_key='iQvYfTfuD86fgVWGjPY0UA',\n",
1227 " consumer_key='iQvYfTfuD86fgVWGjPY0UA',\n",
1228 " consumer_secret='C3jjP6vzYzTYoHV4s5NYPGuRkpT5SulKRKTkRmYg',\n",
1228 " consumer_secret='C3jjP6vzYzTYoHV4s5NYPGuRkpT5SulKRKTkRmYg',\n",
1229 " token='2218195843-cOPQa0D1Yk3JbvjvsCa0tIYzBOEWxINekmGcEql',\n",
1229 " token='2218195843-cOPQa0D1Yk3JbvjvsCa0tIYzBOEWxINekmGcEql',\n",
1230 " token_secret='3BFncT1zAvJRN6rj8haCxveZVLZWZ23QeulxzByXWlfoO'\n",
1230 " token_secret='3BFncT1zAvJRN6rj8haCxveZVLZWZ23QeulxzByXWlfoO'\n",
1231 ")\n",
1231 ")\n",
1232 "twitter = Twitter(auth = auth)\n",
1232 "twitter = Twitter(auth = auth)\n",
1233 "twitter_stream = TwitterStream(auth = auth, block = False)"
1233 "twitter_stream = TwitterStream(auth = auth, block = False)"
1234 ],
1234 ],
1235 "language": "python",
1235 "language": "python",
1236 "metadata": {},
1236 "metadata": {},
1237 "outputs": [],
1237 "outputs": [],
1238 "prompt_number": 17
1238 "prompt_number": 17
1239 },
1239 },
1240 {
1240 {
1241 "cell_type": "code",
1241 "cell_type": "code",
1242 "collapsed": false,
1242 "collapsed": false,
1243 "input": [
1243 "input": [
1244 "widget_container = widgets.ContainerWidget()\n",
1244 "widget_container = widgets.ContainerWidget()\n",
1245 "widget_container.hbox()\n",
1245 "widget_container.hbox()\n",
1246 "floating_container = widgets.ContainerWidget(parent=widget_container, default_view_name='ModalView')\n",
1246 "floating_container = widgets.ContainerWidget(parent=widget_container, default_view_name='ModalView')\n",
1247 "floating_container.description = \"Dynamic D3 rendering of a NetworkX graph\"\n",
1247 "floating_container.description = \"Dynamic D3 rendering of a NetworkX graph\"\n",
1248 "floating_container.button_text = \"Render Window\"\n",
1248 "floating_container.button_text = \"Render Window\"\n",
1249 "floating_container.set_css({\n",
1249 "floating_container.set_css({\n",
1250 " 'width': '620px',\n",
1250 " 'width': '620px',\n",
1251 " 'height': '450px'}, selector='modal')\n",
1251 " 'height': '450px'}, selector='modal')\n",
1252 "\n",
1252 "\n",
1253 "graph = EventfulGraph()\n",
1253 "graph = EventfulGraph()\n",
1254 "d3 = ForceDirectedGraphWidget(graph, parent=floating_container)\n",
1254 "d3 = ForceDirectedGraphWidget(graph, parent=floating_container)\n",
1255 "d3.width = 600\n",
1255 "d3.width = 600\n",
1256 "d3.height = 400\n",
1256 "d3.height = 400\n",
1257 "\n",
1257 "\n",
1258 "stop_button = widgets.ButtonWidget(parent=widget_container, description=\"Stop\")\n",
1258 "stop_button = widgets.ButtonWidget(parent=widget_container, description=\"Stop\")\n",
1259 "stop_button.set_css('margin-left', '5px')\n",
1259 "stop_button.set_css('margin-left', '5px')\n",
1260 " \n",
1260 " \n",
1261 "# Only listen to tweets while they are available and the user\n",
1261 "# Only listen to tweets while they are available and the user\n",
1262 "# doesn't want to stop.\n",
1262 "# doesn't want to stop.\n",
1263 "stop_listening = [False]\n",
1263 "stop_listening = [False]\n",
1264 "def handle_stop():\n",
1264 "def handle_stop():\n",
1265 " stop_listening[0] = True\n",
1265 " stop_listening[0] = True\n",
1266 " print(\"Service stopped\")\n",
1266 " print(\"Service stopped\")\n",
1267 "stop_button.on_click(handle_stop)\n",
1267 "stop_button.on_click(handle_stop)\n",
1268 "\n",
1268 "\n",
1269 "def watch_tweets(screen_name=None):\n",
1269 "def watch_tweets(screen_name=None):\n",
1270 " display(widget_container)\n",
1270 " display(widget_container)\n",
1271 " graph.node.clear()\n",
1271 " graph.node.clear()\n",
1272 " graph.adj.clear()\n",
1272 " graph.adj.clear()\n",
1273 " start_timestamp = None\n",
1273 " start_timestamp = None\n",
1274 " stop_button.add_class('btn-danger')\n",
1274 " stop_button.add_class('btn-danger')\n",
1275 " \n",
1275 " \n",
1276 " # Get Barack's tweets\n",
1276 " # Get Barack's tweets\n",
1277 " tweets = twitter.statuses.user_timeline(screen_name=screen_name)\n",
1277 " tweets = twitter.statuses.user_timeline(screen_name=screen_name)\n",
1278 " user_id = twitter.users.lookup(screen_name=screen_name)[0]['id']\n",
1278 " user_id = twitter.users.lookup(screen_name=screen_name)[0]['id']\n",
1279 " \n",
1279 " \n",
1280 " # Determine the maximum number of retweets.\n",
1280 " # Determine the maximum number of retweets.\n",
1281 " max_retweets = 0.0\n",
1281 " max_retweets = 0.0\n",
1282 " for tweet in tweets:\n",
1282 " for tweet in tweets:\n",
1283 " max_retweets = float(max(tweet['retweet_count'], max_retweets))\n",
1283 " max_retweets = float(max(tweet['retweet_count'], max_retweets))\n",
1284 " \n",
1284 " \n",
1285 " \n",
1285 " \n",
1286 " def plot_tweet(tweet, parent=None, elapsed_seconds=1.0, color=\"gold\"):\n",
1286 " def plot_tweet(tweet, parent=None, elapsed_seconds=1.0, color=\"gold\"):\n",
1287 " new_id = tweet['id']\n",
1287 " new_id = tweet['id']\n",
1288 " graph.add_node(\n",
1288 " graph.add_node(\n",
1289 " new_id, \n",
1289 " new_id, \n",
1290 " r=max(float(tweet['retweet_count']) / max_retweets * 30.0, 3.0),\n",
1290 " r=max(float(tweet['retweet_count']) / max_retweets * 30.0, 3.0),\n",
1291 " charge=-60,\n",
1291 " charge=-60,\n",
1292 " fill = color,\n",
1292 " fill = color,\n",
1293 " )\n",
1293 " )\n",
1294 " \n",
1294 " \n",
1295 " if parent is not None:\n",
1295 " if parent is not None:\n",
1296 " parent_radius = max(float(parent['retweet_count']) / max_retweets * 30.0, 3.0)\n",
1296 " parent_radius = max(float(parent['retweet_count']) / max_retweets * 30.0, 3.0)\n",
1297 " graph.node[parent['id']]['r'] = parent_radius\n",
1297 " graph.node[parent['id']]['r'] = parent_radius\n",
1298 " \n",
1298 " \n",
1299 " graph.add_edge(new_id, parent['id'], distance=math.log(elapsed_seconds) * 9.0 + parent_radius)\n",
1299 " graph.add_edge(new_id, parent['id'], distance=math.log(elapsed_seconds) * 9.0 + parent_radius)\n",
1300 " graph.node[new_id]['fill'] = 'red'\n",
1300 " graph.node[new_id]['fill'] = 'red'\n",
1301 " \n",
1301 " \n",
1302 " \n",
1302 " \n",
1303 " # Plot each tweet.\n",
1303 " # Plot each tweet.\n",
1304 " for tweet in tweets:\n",
1304 " for tweet in tweets:\n",
1305 " plot_tweet(tweet)\n",
1305 " plot_tweet(tweet)\n",
1306 " \n",
1306 " \n",
1307 " kernel=get_ipython().kernel\n",
1307 " kernel=get_ipython().kernel\n",
1308 " iterator = twitter_stream.statuses.filter(follow=user_id)\n",
1308 " iterator = twitter_stream.statuses.filter(follow=user_id)\n",
1309 " \n",
1309 " \n",
1310 " while not stop_listening[0]:\n",
1310 " while not stop_listening[0]:\n",
1311 " kernel.do_one_iteration()\n",
1311 " kernel.do_one_iteration()\n",
1312 " \n",
1312 " \n",
1313 " for tweet in iterator:\n",
1313 " for tweet in iterator:\n",
1314 " kernel.do_one_iteration()\n",
1314 " kernel.do_one_iteration()\n",
1315 " if stop_listening[0] or tweet is None:\n",
1315 " if stop_listening[0] or tweet is None:\n",
1316 " break\n",
1316 " break\n",
1317 " else:\n",
1317 " else:\n",
1318 " if 'retweeted_status' in tweet:\n",
1318 " if 'retweeted_status' in tweet:\n",
1319 " original_tweet = tweet['retweeted_status']\n",
1319 " original_tweet = tweet['retweeted_status']\n",
1320 " if original_tweet['id'] in graph.node:\n",
1320 " if original_tweet['id'] in graph.node:\n",
1321 " tweet_timestamp = datetime.datetime.strptime(tweet['created_at'], twitter_timestamp_format) \n",
1321 " tweet_timestamp = datetime.datetime.strptime(tweet['created_at'], twitter_timestamp_format) \n",
1322 " if start_timestamp is None:\n",
1322 " if start_timestamp is None:\n",
1323 " start_timestamp = tweet_timestamp\n",
1323 " start_timestamp = tweet_timestamp\n",
1324 " elapsed_seconds = max((tweet_timestamp - start_timestamp).total_seconds(),1.0)\n",
1324 " elapsed_seconds = max((tweet_timestamp - start_timestamp).total_seconds(),1.0)\n",
1325 " \n",
1325 " \n",
1326 " plot_tweet(tweet, parent=original_tweet, elapsed_seconds=elapsed_seconds)\n",
1326 " plot_tweet(tweet, parent=original_tweet, elapsed_seconds=elapsed_seconds)\n",
1327 " elif 'id' in tweet:\n",
1327 " elif 'id' in tweet:\n",
1328 " plot_tweet(tweet, color='lime')\n"
1328 " plot_tweet(tweet, color='lime')\n"
1329 ],
1329 ],
1330 "language": "python",
1330 "language": "python",
1331 "metadata": {},
1331 "metadata": {},
1332 "outputs": [],
1332 "outputs": [],
1333 "prompt_number": 18
1333 "prompt_number": 18
1334 },
1334 },
1335 {
1335 {
1336 "cell_type": "code",
1336 "cell_type": "code",
1337 "collapsed": false,
1337 "collapsed": false,
1338 "input": [
1338 "input": [
1339 "watch_tweets(screen_name=\"justinbieber\")"
1339 "watch_tweets(screen_name=\"justinbieber\")"
1340 ],
1340 ],
1341 "language": "python",
1341 "language": "python",
1342 "metadata": {},
1342 "metadata": {},
1343 "outputs": [
1343 "outputs": [
1344 {
1344 {
1345 "output_type": "stream",
1345 "output_type": "stream",
1346 "stream": "stdout",
1346 "stream": "stdout",
1347 "text": [
1347 "text": [
1348 "Service stopped\n"
1348 "Service stopped\n"
1349 ]
1349 ]
1350 }
1350 }
1351 ],
1351 ],
1352 "prompt_number": 19
1352 "prompt_number": 19
1353 }
1353 }
1354 ],
1354 ],
1355 "metadata": {}
1355 "metadata": {}
1356 }
1356 }
1357 ]
1357 ]
1358 } No newline at end of file
1358 }
@@ -1,200 +1,200 b''
1 {
1 {
2 "metadata": {
2 "metadata": {
3 "name": ""
3 "name": ""
4 },
4 },
5 "nbformat": 3,
5 "nbformat": 3,
6 "nbformat_minor": 0,
6 "nbformat_minor": 0,
7 "worksheets": [
7 "worksheets": [
8 {
8 {
9 "cells": [
9 "cells": [
10 {
10 {
11 "cell_type": "markdown",
11 "cell_type": "markdown",
12 "metadata": {},
12 "metadata": {},
13 "source": [
13 "source": [
14 "Simple example notebook that shows how one can use widgets to build custom dialogs."
14 "Simple example notebook that shows how one can use widgets to build custom dialogs."
15 ]
15 ]
16 },
16 },
17 {
17 {
18 "cell_type": "code",
18 "cell_type": "code",
19 "collapsed": false,
19 "collapsed": false,
20 "input": [
20 "input": [
21 "from IPython.html import widgets\n",
21 "from IPython.html import widgets\n",
22 "from IPython.display import display"
22 "from IPython.display import display"
23 ],
23 ],
24 "language": "python",
24 "language": "python",
25 "metadata": {},
25 "metadata": {},
26 "outputs": [],
26 "outputs": [],
27 "prompt_number": 1
27 "prompt_number": 1
28 },
28 },
29 {
29 {
30 "cell_type": "markdown",
30 "cell_type": "markdown",
31 "metadata": {},
31 "metadata": {},
32 "source": [
32 "source": [
33 "By using Bootstrap's modal class and ContainerWidgets, we can build a simple dialog window."
33 "By using Bootstrap's modal class and ContainerWidgets, we can build a simple dialog window."
34 ]
34 ]
35 },
35 },
36 {
36 {
37 "cell_type": "code",
37 "cell_type": "code",
38 "collapsed": false,
38 "collapsed": false,
39 "input": [
39 "input": [
40 "def scrub_text_html(text):\n",
40 "def scrub_text_html(text):\n",
41 " text = text.replace('&', '&amp;')\n",
41 " text = text.replace('&', '&amp;')\n",
42 " text = text.replace(' ', '&nbsp;')\n",
42 " text = text.replace(' ', '&nbsp;')\n",
43 " text = text.replace('<', '&lt;')\n",
43 " text = text.replace('<', '&lt;')\n",
44 " text = text.replace('>', '&gt;')\n",
44 " text = text.replace('>', '&gt;')\n",
45 " text = text.replace('\\n', '<br>\\n')\n",
45 " text = text.replace('\\n', '<br>\\n')\n",
46 " return text\n",
46 " return text\n",
47 "\n",
47 "\n",
48 "def create_dialog(title=None, on_hidden=None):\n",
48 "def create_dialog(title=None, on_hidden=None):\n",
49 " dialog = widgets.ContainerWidget(visible=False)\n",
49 " dialog = widgets.ContainerWidget(visible=False)\n",
50 " dialog_header = widgets.ContainerWidget(parent=dialog)\n",
50 " dialog_header = widgets.ContainerWidget(parent=dialog)\n",
51 " dialog_header_close = widgets.ButtonWidget(parent=dialog_header, description = '&times;')\n",
51 " dialog_header_close = widgets.ButtonWidget(parent=dialog_header, description = '&times;')\n",
52 " dialog_header_label = widgets.StringWidget(parent=dialog_header, default_view_name='LabelView')\n",
52 " dialog_header_label = widgets.StringWidget(parent=dialog_header, default_view_name='HTMLView')\n",
53 " dialog_body = widgets.ContainerWidget(parent=dialog)\n",
53 " dialog_body = widgets.ContainerWidget(parent=dialog)\n",
54 " dialog_footer = widgets.ContainerWidget(parent=dialog)\n",
54 " dialog_footer = widgets.ContainerWidget(parent=dialog)\n",
55 " \n",
55 " \n",
56 " if title is None or title == '':\n",
56 " if title is None or title == '':\n",
57 " title = ' '\n",
57 " title = ' '\n",
58 " dialog_header_label.value = '<h3>%s</h3>' % scrub_text_html(title)\n",
58 " dialog_header_label.value = '<h3>%s</h3>' % scrub_text_html(title)\n",
59 " \n",
59 " \n",
60 " def handle_close():\n",
60 " def handle_close():\n",
61 " dialog.visible = False\n",
61 " dialog.visible = False\n",
62 " if on_hidden is not None:\n",
62 " if on_hidden is not None:\n",
63 " on_hidden(dialog)\n",
63 " on_hidden(dialog)\n",
64 " dialog_header_close.on_click(handle_close)\n",
64 " dialog_header_close.on_click(handle_close)\n",
65 " \n",
65 " \n",
66 " display(dialog)\n",
66 " display(dialog)\n",
67 " \n",
67 " \n",
68 " dialog_header.add_class('modal-header')\n",
68 " dialog_header.add_class('modal-header')\n",
69 " dialog_body.add_class('modal-body')\n",
69 " dialog_body.add_class('modal-body')\n",
70 " dialog_footer.add_class('modal-footer')\n",
70 " dialog_footer.add_class('modal-footer')\n",
71 " dialog.add_class('modal')\n",
71 " dialog.add_class('modal')\n",
72 " \n",
72 " \n",
73 " dialog_header_close.remove_class('btn')\n",
73 " dialog_header_close.remove_class('btn')\n",
74 " dialog_header_close.add_class('close')\n",
74 " dialog_header_close.add_class('close')\n",
75 " \n",
75 " \n",
76 " return dialog_body, dialog_footer, dialog\n"
76 " return dialog_body, dialog_footer, dialog\n"
77 ],
77 ],
78 "language": "python",
78 "language": "python",
79 "metadata": {},
79 "metadata": {},
80 "outputs": [],
80 "outputs": [],
81 "prompt_number": 2
81 "prompt_number": 2
82 },
82 },
83 {
83 {
84 "cell_type": "markdown",
84 "cell_type": "markdown",
85 "metadata": {},
85 "metadata": {},
86 "source": [
86 "source": [
87 "Using this `show_dialog` method, custom dialogs can be made using widgets. Below is an example of a Yes/No dialog."
87 "Using this `show_dialog` method, custom dialogs can be made using widgets. Below is an example of a Yes/No dialog."
88 ]
88 ]
89 },
89 },
90 {
90 {
91 "cell_type": "code",
91 "cell_type": "code",
92 "collapsed": false,
92 "collapsed": false,
93 "input": [
93 "input": [
94 "# Since Python has a global thread lock, everything runs on a single thread.\n",
94 "# Since Python has a global thread lock, everything runs on a single thread.\n",
95 "# Because of this, we use an asynronous model (callbacks).\n",
95 "# Because of this, we use an asynronous model (callbacks).\n",
96 "def show_yes_no(prompt, yes_callback=None, no_callback=None, title=None):\n",
96 "def show_yes_no(prompt, yes_callback=None, no_callback=None, title=None):\n",
97 " \n",
97 " \n",
98 " def handle_hidden(dialog_window):\n",
98 " def handle_hidden(dialog_window):\n",
99 " if no_callback is not None:\n",
99 " if no_callback is not None:\n",
100 " no_callback()\n",
100 " no_callback()\n",
101 " dialog_window.close()\n",
101 " dialog_window.close()\n",
102 " \n",
102 " \n",
103 " (dialog_body, dialog_footer, dialog_window) = create_dialog(title=title, on_hidden=handle_hidden)\n",
103 " (dialog_body, dialog_footer, dialog_window) = create_dialog(title=title, on_hidden=handle_hidden)\n",
104 " \n",
104 " \n",
105 " def handle_yes():\n",
105 " def handle_yes():\n",
106 " dialog_window.visible = False\n",
106 " dialog_window.visible = False\n",
107 " if yes_callback is not None:\n",
107 " if yes_callback is not None:\n",
108 " yes_callback()\n",
108 " yes_callback()\n",
109 " dialog_window.close()\n",
109 " dialog_window.close()\n",
110 " \n",
110 " \n",
111 " def handle_no():\n",
111 " def handle_no():\n",
112 " dialog_window.visible = False\n",
112 " dialog_window.visible = False\n",
113 " handle_hidden(dialog_window)\n",
113 " handle_hidden(dialog_window)\n",
114 " \n",
114 " \n",
115 " yes_button = widgets.ButtonWidget(parent=dialog_footer, description='Yes')\n",
115 " yes_button = widgets.ButtonWidget(parent=dialog_footer, description='Yes')\n",
116 " yes_button.on_click(handle_yes)\n",
116 " yes_button.on_click(handle_yes)\n",
117 " no_button = widgets.ButtonWidget(parent=dialog_footer, description='No')\n",
117 " no_button = widgets.ButtonWidget(parent=dialog_footer, description='No')\n",
118 " no_button.on_click(handle_no)\n",
118 " no_button.on_click(handle_no)\n",
119 " prompt_label = widgets.StringWidget(parent=dialog_body, value=scrub_text_html(prompt), default_view_name='LabelView')\n",
119 " prompt_label = widgets.StringWidget(parent=dialog_body, value=scrub_text_html(prompt), default_view_name='HTMLView')\n",
120 " \n",
120 " \n",
121 " display(yes_button)\n",
121 " display(yes_button)\n",
122 " display(no_button)\n",
122 " display(no_button)\n",
123 " display(prompt_label)\n",
123 " display(prompt_label)\n",
124 " \n",
124 " \n",
125 " yes_button.add_class('btn-success')\n",
125 " yes_button.add_class('btn-success')\n",
126 " no_button.add_class('btn-danger')\n",
126 " no_button.add_class('btn-danger')\n",
127 " \n",
127 " \n",
128 " dialog_window.visible=True\n",
128 " dialog_window.visible=True\n",
129 " \n",
129 " \n",
130 " "
130 " "
131 ],
131 ],
132 "language": "python",
132 "language": "python",
133 "metadata": {},
133 "metadata": {},
134 "outputs": [],
134 "outputs": [],
135 "prompt_number": 3
135 "prompt_number": 3
136 },
136 },
137 {
137 {
138 "cell_type": "heading",
138 "cell_type": "heading",
139 "level": 1,
139 "level": 1,
140 "metadata": {},
140 "metadata": {},
141 "source": [
141 "source": [
142 "Test"
142 "Test"
143 ]
143 ]
144 },
144 },
145 {
145 {
146 "cell_type": "code",
146 "cell_type": "code",
147 "collapsed": false,
147 "collapsed": false,
148 "input": [
148 "input": [
149 "def yes():\n",
149 "def yes():\n",
150 " show_yes_no(\"Do you want to show the dialog again?\", yes, title=\"Self displaying dialog\")\n",
150 " show_yes_no(\"Do you want to show the dialog again?\", yes, title=\"Self displaying dialog\")\n",
151 "yes()"
151 "yes()"
152 ],
152 ],
153 "language": "python",
153 "language": "python",
154 "metadata": {},
154 "metadata": {},
155 "outputs": [],
155 "outputs": [],
156 "prompt_number": 4
156 "prompt_number": 4
157 },
157 },
158 {
158 {
159 "cell_type": "markdown",
159 "cell_type": "markdown",
160 "metadata": {},
160 "metadata": {},
161 "source": [
161 "source": [
162 "Dialog result handlers can contain nested dialogs. The following example shows how syncronous logic can be simulated using closures."
162 "Dialog result handlers can contain nested dialogs. The following example shows how syncronous logic can be simulated using closures."
163 ]
163 ]
164 },
164 },
165 {
165 {
166 "cell_type": "code",
166 "cell_type": "code",
167 "collapsed": false,
167 "collapsed": false,
168 "input": [
168 "input": [
169 "title = \"Interactive Story\"\n",
169 "title = \"Interactive Story\"\n",
170 "def open_door():\n",
170 "def open_door():\n",
171 " show_yes_no(\"The house is empty. You are tired and decide to sleep. You live to see another day.\")\n",
171 " show_yes_no(\"The house is empty. You are tired and decide to sleep. You live to see another day.\")\n",
172 "\n",
172 "\n",
173 "def stay_outside():\n",
173 "def stay_outside():\n",
174 " def fight():\n",
174 " def fight():\n",
175 " show_yes_no(\"You try to fight the wolves but die in the process.\", title=title)\n",
175 " show_yes_no(\"You try to fight the wolves but die in the process.\", title=title)\n",
176 " \n",
176 " \n",
177 " def panic():\n",
177 " def panic():\n",
178 " def flight():\n",
178 " def flight():\n",
179 " show_yes_no(\"You run as fast as you can. You manage to escape the\\n\" + \\\n",
179 " show_yes_no(\"You run as fast as you can. You manage to escape the\\n\" + \\\n",
180 " \"wolves but the cold is beginning to get to you. You\\n\" + \\\n",
180 " \"wolves but the cold is beginning to get to you. You\\n\" + \\\n",
181 " \"sit in the snow to take a nap. You freeze and die.\", title=title)\n",
181 " \"sit in the snow to take a nap. You freeze and die.\", title=title)\n",
182 " \n",
182 " \n",
183 " show_yes_no(\"You panic. Do you enter the cabin now?\", open_door, flight, title=title)\n",
183 " show_yes_no(\"You panic. Do you enter the cabin now?\", open_door, flight, title=title)\n",
184 " \n",
184 " \n",
185 " show_yes_no(\"A pack of wolves approach. Do you want to fight them?\", fight, panic, title=title)\n",
185 " show_yes_no(\"A pack of wolves approach. Do you want to fight them?\", fight, panic, title=title)\n",
186 "\n",
186 "\n",
187 "show_yes_no(\"You are standing outside in a blizzard on a cold winter night.\\n\" + \\\n",
187 "show_yes_no(\"You are standing outside in a blizzard on a cold winter night.\\n\" + \\\n",
188 " \"A warm cabin with the lights on is in front of you.\\n\\n\" + \\\n",
188 " \"A warm cabin with the lights on is in front of you.\\n\\n\" + \\\n",
189 " \"Do you want to enter the cabin?\", open_door, stay_outside, title=title)\n"
189 " \"Do you want to enter the cabin?\", open_door, stay_outside, title=title)\n"
190 ],
190 ],
191 "language": "python",
191 "language": "python",
192 "metadata": {},
192 "metadata": {},
193 "outputs": [],
193 "outputs": [],
194 "prompt_number": 5
194 "prompt_number": 5
195 }
195 }
196 ],
196 ],
197 "metadata": {}
197 "metadata": {}
198 }
198 }
199 ]
199 ]
200 } No newline at end of file
200 }
@@ -1,194 +1,194 b''
1 {
1 {
2 "metadata": {
2 "metadata": {
3 "name": ""
3 "name": ""
4 },
4 },
5 "nbformat": 3,
5 "nbformat": 3,
6 "nbformat_minor": 0,
6 "nbformat_minor": 0,
7 "worksheets": [
7 "worksheets": [
8 {
8 {
9 "cells": [
9 "cells": [
10 {
10 {
11 "cell_type": "code",
11 "cell_type": "code",
12 "collapsed": false,
12 "collapsed": false,
13 "input": [
13 "input": [
14 "from IPython.html import widgets\n",
14 "from IPython.html import widgets\n",
15 "from IPython.display import display, Javascript, clear_output\n",
15 "from IPython.display import display, Javascript, clear_output\n",
16 "from IPython.nbconvert import get_export_names, export_by_name\n",
16 "from IPython.nbconvert import get_export_names, export_by_name\n",
17 "from IPython.nbconvert.writers import FilesWriter\n",
17 "from IPython.nbconvert.writers import FilesWriter\n",
18 "from IPython.nbformat import current"
18 "from IPython.nbformat import current"
19 ],
19 ],
20 "language": "python",
20 "language": "python",
21 "metadata": {},
21 "metadata": {},
22 "outputs": [],
22 "outputs": [],
23 "prompt_number": 1
23 "prompt_number": 1
24 },
24 },
25 {
25 {
26 "cell_type": "markdown",
26 "cell_type": "markdown",
27 "metadata": {},
27 "metadata": {},
28 "source": [
28 "source": [
29 "Create and *display* a StringWidget without a view. The StringWidget will be used to store the notebook name which is otherwise only available in the front-end."
29 "Create and *display* a StringWidget without a view. The StringWidget will be used to store the notebook name which is otherwise only available in the front-end."
30 ]
30 ]
31 },
31 },
32 {
32 {
33 "cell_type": "code",
33 "cell_type": "code",
34 "collapsed": false,
34 "collapsed": false,
35 "input": [
35 "input": [
36 "notebook_name = widgets.StringWidget(default_view_name='')\n",
36 "notebook_name = widgets.StringWidget(default_view_name='')\n",
37 "display(notebook_name)"
37 "display(notebook_name)"
38 ],
38 ],
39 "language": "python",
39 "language": "python",
40 "metadata": {},
40 "metadata": {},
41 "outputs": [],
41 "outputs": [],
42 "prompt_number": 2
42 "prompt_number": 2
43 },
43 },
44 {
44 {
45 "cell_type": "markdown",
45 "cell_type": "markdown",
46 "metadata": {},
46 "metadata": {},
47 "source": [
47 "source": [
48 "Get the current notebook's name by pushing JavaScript to the browser that sets the notebook name in a string widget."
48 "Get the current notebook's name by pushing JavaScript to the browser that sets the notebook name in a string widget."
49 ]
49 ]
50 },
50 },
51 {
51 {
52 "cell_type": "code",
52 "cell_type": "code",
53 "collapsed": false,
53 "collapsed": false,
54 "input": [
54 "input": [
55 "js = \"\"\"var model = IPython.notebook.kernel.comm_manager.comms['{comm_id}'].model;\n",
55 "js = \"\"\"var model = IPython.notebook.kernel.comm_manager.comms['{comm_id}'].model;\n",
56 "model.set('value', IPython.notebook.notebook_name);\n",
56 "model.set('value', IPython.notebook.notebook_name);\n",
57 "model.save();\"\"\".format(comm_id=notebook_name._comm.comm_id)\n",
57 "model.save();\"\"\".format(comm_id=notebook_name._comm.comm_id)\n",
58 "display(Javascript(data=js))"
58 "display(Javascript(data=js))"
59 ],
59 ],
60 "language": "python",
60 "language": "python",
61 "metadata": {},
61 "metadata": {},
62 "outputs": [
62 "outputs": [
63 {
63 {
64 "javascript": [
64 "javascript": [
65 "var model = IPython.notebook.kernel.comm_manager.comms['79dbd18695b3432b94e2265533474474'].model;\n",
65 "var model = IPython.notebook.kernel.comm_manager.comms['af0fadc224134034af6141995abf625a'].model;\n",
66 "model.set('value', IPython.notebook.notebook_name);\n",
66 "model.set('value', IPython.notebook.notebook_name);\n",
67 "model.save();"
67 "model.save();"
68 ],
68 ],
69 "metadata": {},
69 "metadata": {},
70 "output_type": "display_data",
70 "output_type": "display_data",
71 "text": [
71 "text": [
72 "<IPython.core.display.Javascript at 0x208f110>"
72 "<IPython.core.display.Javascript at 0x3756790>"
73 ]
73 ]
74 }
74 }
75 ],
75 ],
76 "prompt_number": 3
76 "prompt_number": 3
77 },
77 },
78 {
78 {
79 "cell_type": "code",
79 "cell_type": "code",
80 "collapsed": false,
80 "collapsed": false,
81 "input": [
81 "input": [
82 "filename = notebook_name.value\n",
82 "filename = notebook_name.value\n",
83 "filename"
83 "filename"
84 ],
84 ],
85 "language": "python",
85 "language": "python",
86 "metadata": {},
86 "metadata": {},
87 "outputs": [
87 "outputs": [
88 {
88 {
89 "metadata": {},
89 "metadata": {},
90 "output_type": "pyout",
90 "output_type": "pyout",
91 "prompt_number": 4,
91 "prompt_number": 4,
92 "text": [
92 "text": [
93 "u'Export As (nbconvert).ipynb'"
93 "u'Export As (nbconvert).ipynb'"
94 ]
94 ]
95 }
95 }
96 ],
96 ],
97 "prompt_number": 4
97 "prompt_number": 4
98 },
98 },
99 {
99 {
100 "cell_type": "markdown",
100 "cell_type": "markdown",
101 "metadata": {},
101 "metadata": {},
102 "source": [
102 "source": [
103 "Create the widget that will allow the user to Export the current notebook."
103 "Create the widget that will allow the user to Export the current notebook."
104 ]
104 ]
105 },
105 },
106 {
106 {
107 "cell_type": "code",
107 "cell_type": "code",
108 "collapsed": false,
108 "collapsed": false,
109 "input": [
109 "input": [
110 "container = widgets.ContainerWidget()\n",
110 "container = widgets.ContainerWidget()\n",
111 "container.vbox()\n",
111 "container.vbox()\n",
112 "container.align_center()\n",
112 "container.align_center()\n",
113 "\n",
113 "\n",
114 "options = widgets.ContainerWidget(parent=container)\n",
114 "options = widgets.ContainerWidget(parent=container)\n",
115 "options.hbox()\n",
115 "options.hbox()\n",
116 "options.align_center()\n",
116 "options.align_center()\n",
117 "exporter_names = widgets.SelectionWidget(parent=options, values=get_export_names(), value='html')\n",
117 "exporter_names = widgets.SelectionWidget(parent=options, values=get_export_names(), value='html')\n",
118 "export_button = widgets.ButtonWidget(parent=options, description=\"Export\")\n",
118 "export_button = widgets.ButtonWidget(parent=options, description=\"Export\")\n",
119 "\n",
119 "\n",
120 "download_link = widgets.StringWidget(parent=container, default_view_name=\"LabelView\", visible=False)"
120 "download_link = widgets.StringWidget(parent=container, default_view_name=\"HTMLView\", visible=False)"
121 ],
121 ],
122 "language": "python",
122 "language": "python",
123 "metadata": {},
123 "metadata": {},
124 "outputs": [],
124 "outputs": [],
125 "prompt_number": 5
125 "prompt_number": 5
126 },
126 },
127 {
127 {
128 "cell_type": "markdown",
128 "cell_type": "markdown",
129 "metadata": {},
129 "metadata": {},
130 "source": [
130 "source": [
131 "Export the notebook when the export button is clicked."
131 "Export the notebook when the export button is clicked."
132 ]
132 ]
133 },
133 },
134 {
134 {
135 "cell_type": "code",
135 "cell_type": "code",
136 "collapsed": false,
136 "collapsed": false,
137 "input": [
137 "input": [
138 "file_writer = FilesWriter()\n",
138 "file_writer = FilesWriter()\n",
139 "\n",
139 "\n",
140 "def export(name, nb):\n",
140 "def export(name, nb):\n",
141 " \n",
141 " \n",
142 " # Get a unique key for the notebook and set it in the resources object.\n",
142 " # Get a unique key for the notebook and set it in the resources object.\n",
143 " notebook_name = name[:name.rfind('.')]\n",
143 " notebook_name = name[:name.rfind('.')]\n",
144 " resources = {}\n",
144 " resources = {}\n",
145 " resources['unique_key'] = notebook_name\n",
145 " resources['unique_key'] = notebook_name\n",
146 " resources['output_files_dir'] = '%s_files' % notebook_name\n",
146 " resources['output_files_dir'] = '%s_files' % notebook_name\n",
147 "\n",
147 "\n",
148 " # Try to export\n",
148 " # Try to export\n",
149 " try:\n",
149 " try:\n",
150 " output, resources = export_by_name(exporter_names.value, nb)\n",
150 " output, resources = export_by_name(exporter_names.value, nb)\n",
151 " except ConversionException as e:\n",
151 " except ConversionException as e:\n",
152 " download_link.value = \"<br>Could not export notebook!\"\n",
152 " download_link.value = \"<br>Could not export notebook!\"\n",
153 " else:\n",
153 " else:\n",
154 " write_results = file_writer.write(output, resources, notebook_name=notebook_name)\n",
154 " write_results = file_writer.write(output, resources, notebook_name=notebook_name)\n",
155 " \n",
155 " \n",
156 " download_link.value = \"<br>Results: <a href='files/{filename}'><i>\\\"{filename}\\\"</i></a>\".format(filename=write_results)\n",
156 " download_link.value = \"<br>Results: <a href='files/{filename}'><i>\\\"{filename}\\\"</i></a>\".format(filename=write_results)\n",
157 " download_link.visible = True"
157 " download_link.visible = True"
158 ],
158 ],
159 "language": "python",
159 "language": "python",
160 "metadata": {},
160 "metadata": {},
161 "outputs": [],
161 "outputs": [],
162 "prompt_number": 6
162 "prompt_number": 6
163 },
163 },
164 {
164 {
165 "cell_type": "code",
165 "cell_type": "code",
166 "collapsed": false,
166 "collapsed": false,
167 "input": [
167 "input": [
168 "def handle_export():\n",
168 "def handle_export():\n",
169 " with open(filename, 'r') as f:\n",
169 " with open(filename, 'r') as f:\n",
170 " export(filename, current.read(f, 'json'))\n",
170 " export(filename, current.read(f, 'json'))\n",
171 "export_button.on_click(handle_export)"
171 "export_button.on_click(handle_export)"
172 ],
172 ],
173 "language": "python",
173 "language": "python",
174 "metadata": {},
174 "metadata": {},
175 "outputs": [],
175 "outputs": [],
176 "prompt_number": 7
176 "prompt_number": 7
177 },
177 },
178 {
178 {
179 "cell_type": "code",
179 "cell_type": "code",
180 "collapsed": false,
180 "collapsed": false,
181 "input": [
181 "input": [
182 "download_link.visible = False\n",
182 "download_link.visible = False\n",
183 "display(container)"
183 "display(container)"
184 ],
184 ],
185 "language": "python",
185 "language": "python",
186 "metadata": {},
186 "metadata": {},
187 "outputs": [],
187 "outputs": [],
188 "prompt_number": 8
188 "prompt_number": 8
189 }
189 }
190 ],
190 ],
191 "metadata": {}
191 "metadata": {}
192 }
192 }
193 ]
193 ]
194 } No newline at end of file
194 }
@@ -1,222 +1,223 b''
1 {
1 {
2 "metadata": {
2 "metadata": {
3 "cell_tags": [
3 "cell_tags": [
4 [
4 [
5 "<None>",
5 "<None>",
6 null
6 null
7 ]
7 ]
8 ],
8 ],
9 "name": ""
9 "name": ""
10 },
10 },
11 "nbformat": 3,
11 "nbformat": 3,
12 "nbformat_minor": 0,
12 "nbformat_minor": 0,
13 "worksheets": [
13 "worksheets": [
14 {
14 {
15 "cells": [
15 "cells": [
16 {
16 {
17 "cell_type": "code",
17 "cell_type": "code",
18 "collapsed": false,
18 "collapsed": false,
19 "input": [
19 "input": [
20 "from __future__ import print_function # py 2.7 compat\n",
20 "from __future__ import print_function # py 2.7 compat\n",
21 "\n",
21 "\n",
22 "import base64\n",
22 "from IPython.html import widgets # Widget definitions\n",
23 "from IPython.html import widgets # Widget definitions\n",
23 "from IPython.display import display # Used to display widgets in the notebook"
24 "from IPython.display import display # Used to display widgets in the notebook"
24 ],
25 ],
25 "language": "python",
26 "language": "python",
26 "metadata": {},
27 "metadata": {},
27 "outputs": [],
28 "outputs": [],
28 "prompt_number": 1
29 "prompt_number": 1
29 },
30 },
30 {
31 {
31 "cell_type": "heading",
32 "cell_type": "heading",
32 "level": 1,
33 "level": 1,
33 "metadata": {},
34 "metadata": {},
34 "source": [
35 "source": [
35 "Custom Widget"
36 "Custom Widget"
36 ]
37 ]
37 },
38 },
38 {
39 {
39 "cell_type": "code",
40 "cell_type": "code",
40 "collapsed": false,
41 "collapsed": false,
41 "input": [
42 "input": [
42 "# Import the base Widget class and the traitlets Unicode class.\n",
43 "# Import the base Widget class and the traitlets Unicode class.\n",
43 "from IPython.html.widgets import Widget\n",
44 "from IPython.html.widgets import Widget\n",
44 "from IPython.utils.traitlets import Unicode, Int\n",
45 "from IPython.utils.traitlets import Unicode, Int\n",
45 "\n",
46 "\n",
46 "# Define our FileWidget and its target model and default view.\n",
47 "# Define our FileWidget and its target model and default view.\n",
47 "class FileWidget(Widget):\n",
48 "class FileWidget(Widget):\n",
48 " target_name = Unicode('FileWidgetModel')\n",
49 " target_name = Unicode('FileWidgetModel')\n",
49 " default_view_name = Unicode('FilePickerView')\n",
50 " default_view_name = Unicode('FilePickerView')\n",
50 " \n",
51 " \n",
51 " # Define the custom state properties to sync with the front-end\n",
52 " # Define the custom state properties to sync with the front-end\n",
52 " _keys = ['value', 'filename']\n",
53 " _keys = ['value', 'filename']\n",
53 " value = Unicode('')\n",
54 " value = Unicode('')\n",
54 " filename = Unicode('')\n",
55 " filename = Unicode('')\n",
55 " on_failed = Int(0)"
56 " on_failed = Int(0)"
56 ],
57 ],
57 "language": "python",
58 "language": "python",
58 "metadata": {},
59 "metadata": {},
59 "outputs": [],
60 "outputs": [],
60 "prompt_number": 2
61 "prompt_number": 2
61 },
62 },
62 {
63 {
63 "cell_type": "code",
64 "cell_type": "code",
64 "collapsed": false,
65 "collapsed": false,
65 "input": [
66 "input": [
66 "%%javascript\n",
67 "%%javascript\n",
67 "\n",
68 "\n",
68 "require([\"notebook/js/widget\"], function(){\n",
69 "require([\"notebook/js/widget\"], function(){\n",
69 " \n",
70 " \n",
70 " // Define the FileModel and register it with the widget manager.\n",
71 " // Define the FileModel and register it with the widget manager.\n",
71 " var FileModel = IPython.WidgetModel.extend({});\n",
72 " var FileModel = IPython.WidgetModel.extend({});\n",
72 " IPython.widget_manager.register_widget_model('FileWidgetModel', FileModel);\n",
73 " IPython.widget_manager.register_widget_model('FileWidgetModel', FileModel);\n",
73 " \n",
74 " \n",
74 " // Define the FilePickerView\n",
75 " // Define the FilePickerView\n",
75 " var FilePickerView = IPython.WidgetView.extend({\n",
76 " var FilePickerView = IPython.WidgetView.extend({\n",
76 " \n",
77 " \n",
77 " render: function(){\n",
78 " render: function(){\n",
78 " var that = this;\n",
79 " var that = this;\n",
79 " this.$el = $('<input />')\n",
80 " this.$el = $('<input />')\n",
80 " .attr('type', 'file')\n",
81 " .attr('type', 'file')\n",
81 " .change(function(evt){ that.handleFileChange(evt) });\n",
82 " .change(function(evt){ that.handleFileChange(evt) });\n",
82 " },\n",
83 " },\n",
83 " \n",
84 " \n",
84 " // Handles: User input\n",
85 " // Handles: User input\n",
85 " handleFileChange: function(evt) { \n",
86 " handleFileChange: function(evt) { \n",
86 " \n",
87 " \n",
87 " //Retrieve the first (and only!) File from the FileList object\n",
88 " //Retrieve the first (and only!) File from the FileList object\n",
88 " var that = this;\n",
89 " var that = this;\n",
89 " var f = evt.target.files[0];\n",
90 " var f = evt.target.files[0];\n",
90 " if (f) {\n",
91 " if (f) {\n",
91 " var r = new FileReader();\n",
92 " var r = new FileReader();\n",
92 " r.onload = function(e) {\n",
93 " r.onload = function(e) {\n",
93 " that.model.set('value', e.target.result);\n",
94 " that.model.set('value', e.target.result);\n",
94 " that.model.update_other_views(that);\n",
95 " that.model.update_other_views(that);\n",
95 " }\n",
96 " }\n",
96 " r.readAsText(f);\n",
97 " r.readAsText(f);\n",
97 " } else {\n",
98 " } else {\n",
98 " this.model.set('on_failed', this.model.get('on_failed') + 1);\n",
99 " this.model.set('on_failed', this.model.get('on_failed') + 1);\n",
99 " this.model.update_other_views(this);\n",
100 " this.model.update_other_views(this);\n",
100 " }\n",
101 " }\n",
101 " this.model.set('filename', f.name);\n",
102 " this.model.set('filename', f.name);\n",
102 " this.model.update_other_views(this);\n",
103 " this.model.update_other_views(this);\n",
103 " },\n",
104 " },\n",
104 " });\n",
105 " });\n",
105 " \n",
106 " \n",
106 " // Register the DatePickerView with the widget manager.\n",
107 " // Register the DatePickerView with the widget manager.\n",
107 " IPython.widget_manager.register_widget_view('FilePickerView', FilePickerView);\n",
108 " IPython.widget_manager.register_widget_view('FilePickerView', FilePickerView);\n",
108 "});"
109 "});"
109 ],
110 ],
110 "language": "python",
111 "language": "python",
111 "metadata": {},
112 "metadata": {},
112 "outputs": [
113 "outputs": [
113 {
114 {
114 "javascript": [
115 "javascript": [
115 "\n",
116 "\n",
116 "require([\"notebook/js/widget\"], function(){\n",
117 "require([\"notebook/js/widget\"], function(){\n",
117 " \n",
118 " \n",
118 " // Define the FileModel and register it with the widget manager.\n",
119 " // Define the FileModel and register it with the widget manager.\n",
119 " var FileModel = IPython.WidgetModel.extend({});\n",
120 " var FileModel = IPython.WidgetModel.extend({});\n",
120 " IPython.widget_manager.register_widget_model('FileWidgetModel', FileModel);\n",
121 " IPython.widget_manager.register_widget_model('FileWidgetModel', FileModel);\n",
121 " \n",
122 " \n",
122 " // Define the FilePickerView\n",
123 " // Define the FilePickerView\n",
123 " var FilePickerView = IPython.WidgetView.extend({\n",
124 " var FilePickerView = IPython.WidgetView.extend({\n",
124 " \n",
125 " \n",
125 " render: function(){\n",
126 " render: function(){\n",
126 " var that = this;\n",
127 " var that = this;\n",
127 " this.$el = $('<input />')\n",
128 " this.$el = $('<input />')\n",
128 " .attr('type', 'file')\n",
129 " .attr('type', 'file')\n",
129 " .change(function(evt){ that.handleFileChange(evt) });\n",
130 " .change(function(evt){ that.handleFileChange(evt) });\n",
130 " },\n",
131 " },\n",
131 " \n",
132 " \n",
132 " // Handles: User input\n",
133 " // Handles: User input\n",
133 " handleFileChange: function(evt) { \n",
134 " handleFileChange: function(evt) { \n",
134 " \n",
135 " \n",
135 " //Retrieve the first (and only!) File from the FileList object\n",
136 " //Retrieve the first (and only!) File from the FileList object\n",
136 " var that = this;\n",
137 " var that = this;\n",
137 " var f = evt.target.files[0];\n",
138 " var f = evt.target.files[0];\n",
138 " if (f) {\n",
139 " if (f) {\n",
139 " var r = new FileReader();\n",
140 " var r = new FileReader();\n",
140 " r.onload = function(e) {\n",
141 " r.onload = function(e) {\n",
141 " that.model.set('value', e.target.result);\n",
142 " that.model.set('value', e.target.result);\n",
142 " that.model.update_other_views(that);\n",
143 " that.model.update_other_views(that);\n",
143 " }\n",
144 " }\n",
144 " r.readAsText(f);\n",
145 " r.readAsText(f);\n",
145 " } else {\n",
146 " } else {\n",
146 " this.model.set('on_failed', this.model.get('on_failed') + 1);\n",
147 " this.model.set('on_failed', this.model.get('on_failed') + 1);\n",
147 " this.model.update_other_views(this);\n",
148 " this.model.update_other_views(this);\n",
148 " }\n",
149 " }\n",
149 " this.model.set('filename', f.name);\n",
150 " this.model.set('filename', f.name);\n",
150 " this.model.update_other_views(this);\n",
151 " this.model.update_other_views(this);\n",
151 " },\n",
152 " },\n",
152 " });\n",
153 " });\n",
153 " \n",
154 " \n",
154 " // Register the DatePickerView with the widget manager.\n",
155 " // Register the DatePickerView with the widget manager.\n",
155 " IPython.widget_manager.register_widget_view('FilePickerView', FilePickerView);\n",
156 " IPython.widget_manager.register_widget_view('FilePickerView', FilePickerView);\n",
156 "});"
157 "});"
157 ],
158 ],
158 "metadata": {},
159 "metadata": {},
159 "output_type": "display_data",
160 "output_type": "display_data",
160 "text": [
161 "text": [
161 "<IPython.core.display.Javascript at 0x7f14f1c78cd0>"
162 "<IPython.core.display.Javascript at 0x7f14f1c78cd0>"
162 ]
163 ]
163 }
164 }
164 ],
165 ],
165 "prompt_number": 3
166 "prompt_number": 3
166 },
167 },
167 {
168 {
168 "cell_type": "heading",
169 "cell_type": "heading",
169 "level": 1,
170 "level": 1,
170 "metadata": {},
171 "metadata": {},
171 "source": [
172 "source": [
172 "Usage"
173 "Usage"
173 ]
174 ]
174 },
175 },
175 {
176 {
176 "cell_type": "code",
177 "cell_type": "code",
177 "collapsed": false,
178 "collapsed": false,
178 "input": [
179 "input": [
179 "file_widget = FileWidget()\n",
180 "file_widget = FileWidget()\n",
180 "display(file_widget)\n",
181 "display(file_widget)\n",
181 "\n",
182 "\n",
182 "def file_loading():\n",
183 "def file_loading():\n",
183 " print(\"Loading %s\" % file_widget.filename)\n",
184 " print(\"Loading %s\" % file_widget.filename)\n",
184 "\n",
185 "\n",
185 "def file_loaded():\n",
186 "def file_loaded():\n",
186 " print(\"Loaded, file contents: %s\" % file_widget.value)\n",
187 " print(\"Loaded, file contents: %s\" % file_widget.value)\n",
187 "\n",
188 "\n",
188 "def file_failed(name, old_value, new_value):\n",
189 "def file_failed(name, old_value, new_value):\n",
189 " if new_value > old_value:\n",
190 " if new_value > old_value:\n",
190 " print(\"Could not load file contents of %s\" % file_widget.filename)\n",
191 " print(\"Could not load file contents of %s\" % file_widget.filename)\n",
191 "\n",
192 "\n",
192 "\n",
193 "\n",
193 "file_widget.on_trait_change(file_loading, 'filename')\n",
194 "file_widget.on_trait_change(file_loading, 'filename')\n",
194 "file_widget.on_trait_change(file_loaded, 'value')\n",
195 "file_widget.on_trait_change(file_loaded, 'value')\n",
195 "file_widget.on_trait_change(file_failed, 'on_failed')"
196 "file_widget.on_trait_change(file_failed, 'on_failed')"
196 ],
197 ],
197 "language": "python",
198 "language": "python",
198 "metadata": {},
199 "metadata": {},
199 "outputs": [
200 "outputs": [
200 {
201 {
201 "output_type": "stream",
202 "output_type": "stream",
202 "stream": "stdout",
203 "stream": "stdout",
203 "text": [
204 "text": [
204 "Loading test.txt\n"
205 "Loading test.txt\n"
205 ]
206 ]
206 },
207 },
207 {
208 {
208 "output_type": "stream",
209 "output_type": "stream",
209 "stream": "stdout",
210 "stream": "stdout",
210 "text": [
211 "text": [
211 "Loaded, file contents: Hello World!\n",
212 "Loaded, file contents: Hello World!\n",
212 "\n"
213 "\n"
213 ]
214 ]
214 }
215 }
215 ],
216 ],
216 "prompt_number": 4
217 "prompt_number": 4
217 }
218 }
218 ],
219 ],
219 "metadata": {}
220 "metadata": {}
220 }
221 }
221 ]
222 ]
222 } No newline at end of file
223 }
@@ -1,325 +1,325 b''
1 {
1 {
2 "metadata": {
2 "metadata": {
3 "cell_tags": [
3 "cell_tags": [
4 [
4 [
5 "<None>",
5 "<None>",
6 null
6 null
7 ]
7 ]
8 ],
8 ],
9 "name": ""
9 "name": ""
10 },
10 },
11 "nbformat": 3,
11 "nbformat": 3,
12 "nbformat_minor": 0,
12 "nbformat_minor": 0,
13 "worksheets": [
13 "worksheets": [
14 {
14 {
15 "cells": [
15 "cells": [
16 {
16 {
17 "cell_type": "markdown",
17 "cell_type": "markdown",
18 "metadata": {},
18 "metadata": {},
19 "source": [
19 "source": [
20 "To use IPython widgets in the notebook, the widget namespace and display function need to be imported."
20 "To use IPython widgets in the notebook, the widget namespace and display function need to be imported."
21 ]
21 ]
22 },
22 },
23 {
23 {
24 "cell_type": "code",
24 "cell_type": "code",
25 "collapsed": false,
25 "collapsed": false,
26 "input": [
26 "input": [
27 "from IPython.html import widgets # Widget definitions\n",
27 "from IPython.html import widgets # Widget definitions\n",
28 "from IPython.display import display # Used to display widgets in the notebook"
28 "from IPython.display import display # Used to display widgets in the notebook"
29 ],
29 ],
30 "language": "python",
30 "language": "python",
31 "metadata": {},
31 "metadata": {},
32 "outputs": [],
32 "outputs": [],
33 "prompt_number": 1
33 "prompt_number": 1
34 },
34 },
35 {
35 {
36 "cell_type": "heading",
36 "cell_type": "heading",
37 "level": 1,
37 "level": 1,
38 "metadata": {},
38 "metadata": {},
39 "source": [
39 "source": [
40 "Basic Widgets"
40 "Basic Widgets"
41 ]
41 ]
42 },
42 },
43 {
43 {
44 "cell_type": "markdown",
44 "cell_type": "markdown",
45 "metadata": {},
45 "metadata": {},
46 "source": [
46 "source": [
47 "The IPython notebook comes preloaded with basic widgets that represent common data types. These widgets are\n",
47 "The IPython notebook comes preloaded with basic widgets that represent common data types. These widgets are\n",
48 "\n",
48 "\n",
49 "- BoolWidget : boolean \n",
49 "- BoolWidget : boolean \n",
50 "- FloatRangeWidget : bounded float \n",
50 "- FloatRangeWidget : bounded float \n",
51 "- FloatWidget : unbounded float \n",
51 "- FloatWidget : unbounded float \n",
52 "- IntRangeWidget : bounded integer \n",
52 "- IntRangeWidget : bounded integer \n",
53 "- IntWidget : unbounded integer \n",
53 "- IntWidget : unbounded integer \n",
54 "- SelectionWidget : enumeration \n",
54 "- SelectionWidget : enumeration \n",
55 "- StringWidget : string \n",
55 "- StringWidget : string \n",
56 "\n",
56 "\n",
57 "A few special widgets are also included, that can be used to capture events and change how other widgets are displayed. These widgets are\n",
57 "A few special widgets are also included, that can be used to capture events and change how other widgets are displayed. These widgets are\n",
58 "\n",
58 "\n",
59 "- ButtonWidget \n",
59 "- ButtonWidget \n",
60 "- ContainerWidget \n",
60 "- ContainerWidget \n",
61 "- MulticontainerWidget \n",
61 "- MulticontainerWidget \n",
62 "\n",
62 "\n",
63 "To see the complete list of widgets, one can execute the following"
63 "To see the complete list of widgets, one can execute the following"
64 ]
64 ]
65 },
65 },
66 {
66 {
67 "cell_type": "code",
67 "cell_type": "code",
68 "collapsed": false,
68 "collapsed": false,
69 "input": [
69 "input": [
70 "[widget for widget in dir(widgets) if widget.endswith('Widget')]"
70 "[widget for widget in dir(widgets) if widget.endswith('Widget')]"
71 ],
71 ],
72 "language": "python",
72 "language": "python",
73 "metadata": {},
73 "metadata": {},
74 "outputs": [
74 "outputs": [
75 {
75 {
76 "metadata": {},
76 "metadata": {},
77 "output_type": "pyout",
77 "output_type": "pyout",
78 "prompt_number": 2,
78 "prompt_number": 2,
79 "text": [
79 "text": [
80 "['BoolWidget',\n",
80 "['BoolWidget',\n",
81 " 'ButtonWidget',\n",
81 " 'ButtonWidget',\n",
82 " 'ContainerWidget',\n",
82 " 'ContainerWidget',\n",
83 " 'FloatRangeWidget',\n",
83 " 'FloatRangeWidget',\n",
84 " 'FloatWidget',\n",
84 " 'FloatWidget',\n",
85 " 'IntRangeWidget',\n",
85 " 'IntRangeWidget',\n",
86 " 'IntWidget',\n",
86 " 'IntWidget',\n",
87 " 'MulticontainerWidget',\n",
87 " 'MulticontainerWidget',\n",
88 " 'SelectionWidget',\n",
88 " 'SelectionWidget',\n",
89 " 'StringWidget',\n",
89 " 'StringWidget',\n",
90 " 'Widget']"
90 " 'Widget']"
91 ]
91 ]
92 }
92 }
93 ],
93 ],
94 "prompt_number": 2
94 "prompt_number": 2
95 },
95 },
96 {
96 {
97 "cell_type": "markdown",
97 "cell_type": "markdown",
98 "metadata": {},
98 "metadata": {},
99 "source": [
99 "source": [
100 "The basic widgets can all be constructed without arguments. The following creates a FloatRangeWidget without displaying it"
100 "The basic widgets can all be constructed without arguments. The following creates a FloatRangeWidget without displaying it"
101 ]
101 ]
102 },
102 },
103 {
103 {
104 "cell_type": "code",
104 "cell_type": "code",
105 "collapsed": false,
105 "collapsed": false,
106 "input": [
106 "input": [
107 "mywidget = widgets.FloatRangeWidget()"
107 "mywidget = widgets.FloatRangeWidget()"
108 ],
108 ],
109 "language": "python",
109 "language": "python",
110 "metadata": {},
110 "metadata": {},
111 "outputs": [],
111 "outputs": [],
112 "prompt_number": 3
112 "prompt_number": 3
113 },
113 },
114 {
114 {
115 "cell_type": "markdown",
115 "cell_type": "markdown",
116 "metadata": {},
116 "metadata": {},
117 "source": [
117 "source": [
118 "Constructing a widget does not display it on the page. To display a widget, the widget must be passed to the IPython `display(object)` method. `mywidget` is displayed by"
118 "Constructing a widget does not display it on the page. To display a widget, the widget must be passed to the IPython `display(object)` method. `mywidget` is displayed by"
119 ]
119 ]
120 },
120 },
121 {
121 {
122 "cell_type": "code",
122 "cell_type": "code",
123 "collapsed": false,
123 "collapsed": false,
124 "input": [
124 "input": [
125 "display(mywidget)"
125 "display(mywidget)"
126 ],
126 ],
127 "language": "python",
127 "language": "python",
128 "metadata": {},
128 "metadata": {},
129 "outputs": [],
129 "outputs": [],
130 "prompt_number": 4
130 "prompt_number": 4
131 },
131 },
132 {
132 {
133 "cell_type": "markdown",
133 "cell_type": "markdown",
134 "metadata": {},
134 "metadata": {},
135 "source": [
135 "source": [
136 "It's important to realize that widgets are not the same as output, even though they are displayed with `display`. Widgets are drawn in a special widget area. That area is marked with a close button which allows you to collapse the widgets. Widgets cannot be interleaved with output. Doing so would break the ability to make simple animations using `clear_output`.\n",
136 "It's important to realize that widgets are not the same as output, even though they are displayed with `display`. Widgets are drawn in a special widget area. That area is marked with a close button which allows you to collapse the widgets. Widgets cannot be interleaved with output. Doing so would break the ability to make simple animations using `clear_output`.\n",
137 "\n",
137 "\n",
138 "Widgets are manipulated via special instance properties (traitlets). The names of these instance properties are listed in the widget's `keys` property (as seen below). A few of these properties are common to most, if not all, widgets. The common properties are `value`, `description`, `visible`, and `disabled`. `_css`, `_add_class`, and `_remove_class` are internal properties that exist in all widgets and should not be modified."
138 "Widgets are manipulated via special instance properties (traitlets). The names of these instance properties are listed in the widget's `keys` property (as seen below). A few of these properties are common to most, if not all, widgets. The common properties are `value`, `description`, `visible`, and `disabled`. `_css`, `_add_class`, and `_remove_class` are internal properties that exist in all widgets and should not be modified."
139 ]
139 ]
140 },
140 },
141 {
141 {
142 "cell_type": "code",
142 "cell_type": "code",
143 "collapsed": false,
143 "collapsed": false,
144 "input": [
144 "input": [
145 "mywidget.keys"
145 "mywidget.keys"
146 ],
146 ],
147 "language": "python",
147 "language": "python",
148 "metadata": {},
148 "metadata": {},
149 "outputs": [
149 "outputs": [
150 {
150 {
151 "metadata": {},
151 "metadata": {},
152 "output_type": "pyout",
152 "output_type": "pyout",
153 "prompt_number": 5,
153 "prompt_number": 5,
154 "text": [
154 "text": [
155 "['visible',\n",
155 "['visible',\n",
156 " '_css',\n",
156 " '_css',\n",
157 " '_add_class',\n",
157 " '_add_class',\n",
158 " '_remove_class',\n",
158 " '_remove_class',\n",
159 " 'value',\n",
159 " 'value',\n",
160 " 'step',\n",
160 " 'step',\n",
161 " 'max',\n",
161 " 'max',\n",
162 " 'min',\n",
162 " 'min',\n",
163 " 'disabled',\n",
163 " 'disabled',\n",
164 " 'orientation',\n",
164 " 'orientation',\n",
165 " 'description']"
165 " 'description']"
166 ]
166 ]
167 }
167 }
168 ],
168 ],
169 "prompt_number": 5
169 "prompt_number": 5
170 },
170 },
171 {
171 {
172 "cell_type": "markdown",
172 "cell_type": "markdown",
173 "metadata": {},
173 "metadata": {},
174 "source": [
174 "source": [
175 "Changing a widget's property value will automatically update that widget everywhere it is displayed in the notebook. Here the value of `mywidget` is set. The slider shown above (after input 4) updates automatically to the new value. In reverse, changing the value of the displayed widget will update the property's value."
175 "Changing a widget's property value will automatically update that widget everywhere it is displayed in the notebook. Here the value of `mywidget` is set. The slider shown above (after input 4) updates automatically to the new value. In reverse, changing the value of the displayed widget will update the property's value."
176 ]
176 ]
177 },
177 },
178 {
178 {
179 "cell_type": "code",
179 "cell_type": "code",
180 "collapsed": false,
180 "collapsed": false,
181 "input": [
181 "input": [
182 "mywidget.value = 25.0"
182 "mywidget.value = 25.0"
183 ],
183 ],
184 "language": "python",
184 "language": "python",
185 "metadata": {},
185 "metadata": {},
186 "outputs": [],
186 "outputs": [],
187 "prompt_number": 6
187 "prompt_number": 6
188 },
188 },
189 {
189 {
190 "cell_type": "markdown",
190 "cell_type": "markdown",
191 "metadata": {},
191 "metadata": {},
192 "source": [
192 "source": [
193 "After changing the widget's value in the notebook by hand to 0.0 (sliding the bar to the far left)."
193 "After changing the widget's value in the notebook by hand to 0.0 (sliding the bar to the far left)."
194 ]
194 ]
195 },
195 },
196 {
196 {
197 "cell_type": "code",
197 "cell_type": "code",
198 "collapsed": false,
198 "collapsed": false,
199 "input": [
199 "input": [
200 "mywidget.value"
200 "mywidget.value"
201 ],
201 ],
202 "language": "python",
202 "language": "python",
203 "metadata": {},
203 "metadata": {},
204 "outputs": [
204 "outputs": [
205 {
205 {
206 "metadata": {},
206 "metadata": {},
207 "output_type": "pyout",
207 "output_type": "pyout",
208 "prompt_number": 7,
208 "prompt_number": 7,
209 "text": [
209 "text": [
210 "0.0"
210 "0.0"
211 ]
211 ]
212 }
212 }
213 ],
213 ],
214 "prompt_number": 7
214 "prompt_number": 7
215 },
215 },
216 {
216 {
217 "cell_type": "markdown",
217 "cell_type": "markdown",
218 "metadata": {},
218 "metadata": {},
219 "source": [
219 "source": [
220 "Widget property values can also be set with kwargs during the construction of the widget (as seen below)."
220 "Widget property values can also be set with kwargs during the construction of the widget (as seen below)."
221 ]
221 ]
222 },
222 },
223 {
223 {
224 "cell_type": "code",
224 "cell_type": "code",
225 "collapsed": false,
225 "collapsed": false,
226 "input": [
226 "input": [
227 "mysecondwidget = widgets.SelectionWidget(values=[\"Item A\", \"Item B\", \"Item C\"], value=\"Nothing Selected\")\n",
227 "mysecondwidget = widgets.SelectionWidget(values=[\"Item A\", \"Item B\", \"Item C\"], value=\"Nothing Selected\")\n",
228 "display(mysecondwidget)"
228 "display(mysecondwidget)"
229 ],
229 ],
230 "language": "python",
230 "language": "python",
231 "metadata": {},
231 "metadata": {},
232 "outputs": [],
232 "outputs": [],
233 "prompt_number": 8
233 "prompt_number": 8
234 },
234 },
235 {
235 {
236 "cell_type": "heading",
236 "cell_type": "heading",
237 "level": 1,
237 "level": 1,
238 "metadata": {},
238 "metadata": {},
239 "source": [
239 "source": [
240 "Views"
240 "Views"
241 ]
241 ]
242 },
242 },
243 {
243 {
244 "cell_type": "markdown",
244 "cell_type": "markdown",
245 "metadata": {},
245 "metadata": {},
246 "source": [
246 "source": [
247 "The data types that most of the widgets represent can be displayed more than one way. A `view` is a visual representation of a widget in the notebook. In the example in the section above, the default `view` for the `FloatRangeWidget` is used. The default view is set in the widgets `default_view_name` instance property (as seen below)."
247 "The data types that most of the widgets represent can be displayed more than one way. A `view` is a visual representation of a widget in the notebook. In the example in the section above, the default `view` for the `FloatRangeWidget` is used. The default view is set in the widgets `default_view_name` instance property (as seen below)."
248 ]
248 ]
249 },
249 },
250 {
250 {
251 "cell_type": "code",
251 "cell_type": "code",
252 "collapsed": false,
252 "collapsed": false,
253 "input": [
253 "input": [
254 "mywidget.default_view_name"
254 "mywidget.default_view_name"
255 ],
255 ],
256 "language": "python",
256 "language": "python",
257 "metadata": {},
257 "metadata": {},
258 "outputs": [
258 "outputs": [
259 {
259 {
260 "metadata": {},
260 "metadata": {},
261 "output_type": "pyout",
261 "output_type": "pyout",
262 "prompt_number": 9,
262 "prompt_number": 9,
263 "text": [
263 "text": [
264 "u'FloatSliderView'"
264 "u'FloatSliderView'"
265 ]
265 ]
266 }
266 }
267 ],
267 ],
268 "prompt_number": 9
268 "prompt_number": 9
269 },
269 },
270 {
270 {
271 "cell_type": "markdown",
271 "cell_type": "markdown",
272 "metadata": {},
272 "metadata": {},
273 "source": [
273 "source": [
274 "When a widget is displayed using `display(...)`, the `default_view_name` is used to determine what view type should be used to display the widget. View names are case sensitive. Sometimes the default view isn't the best view to represent a piece of data. To change what view is used, either the `default_view_name` can be changed or the `view_name` kwarg of `display` can be set. This also can be used to display one widget multiple ways in one output (as seen below)."
274 "When a widget is displayed using `display(...)`, the `default_view_name` is used to determine what view type should be used to display the widget. View names are case sensitive. Sometimes the default view isn't the best view to represent a piece of data. To change what view is used, either the `default_view_name` can be changed or the `view_name` kwarg of `display` can be set. This also can be used to display one widget multiple ways in one output (as seen below)."
275 ]
275 ]
276 },
276 },
277 {
277 {
278 "cell_type": "code",
278 "cell_type": "code",
279 "collapsed": false,
279 "collapsed": false,
280 "input": [
280 "input": [
281 "display(mywidget)\n",
281 "display(mywidget)\n",
282 "display(mywidget, view_name=\"FloatTextView\")"
282 "display(mywidget, view_name=\"FloatTextView\")"
283 ],
283 ],
284 "language": "python",
284 "language": "python",
285 "metadata": {},
285 "metadata": {},
286 "outputs": [],
286 "outputs": [],
287 "prompt_number": 10
287 "prompt_number": 10
288 },
288 },
289 {
289 {
290 "cell_type": "markdown",
290 "cell_type": "markdown",
291 "metadata": {},
291 "metadata": {},
292 "source": [
292 "source": [
293 "Some views work with multiple different widget types and some views only work with one. The complete list of views and supported widgets is below. The default views are italicized.\n",
293 "Some views work with multiple different widget types and some views only work with one. The complete list of views and supported widgets is below. The default views are italicized.\n",
294 "\n",
294 "\n",
295 "| Widget Name | View Names |\n",
295 "| Widget Name | View Names |\n",
296 "|:-----------------------|:--------------------|\n",
296 "|:-----------------------|:--------------------|\n",
297 "| BoolWidget | *CheckboxView* |\n",
297 "| BoolWidget | *CheckboxView* |\n",
298 "| | ToggleButtonView |\n",
298 "| | ToggleButtonView |\n",
299 "| ButtonWidget | *ButtonView* |\n",
299 "| ButtonWidget | *ButtonView* |\n",
300 "| ContainerWidget | *ContainerView* |\n",
300 "| ContainerWidget | *ContainerView* |\n",
301 "| | ModalView |\n",
301 "| | ModalView |\n",
302 "| FloatRangeWidget | *FloatSliderView* |\n",
302 "| FloatRangeWidget | *FloatSliderView* |\n",
303 "| | FloatTextView |\n",
303 "| | FloatTextView |\n",
304 "| | ProgressView |\n",
304 "| | ProgressView |\n",
305 "| FloatWidget | *FloatTextView* |\n",
305 "| FloatWidget | *FloatTextView* |\n",
306 "| IntRangeWidget | *IntSliderView* |\n",
306 "| IntRangeWidget | *IntSliderView* |\n",
307 "| | IntTextView |\n",
307 "| | IntTextView |\n",
308 "| | ProgressView |\n",
308 "| | ProgressView |\n",
309 "| IntWidget | *IntTextView* |\n",
309 "| IntWidget | *IntTextView* |\n",
310 "| MulticontainerWidget | AccordionView |\n",
310 "| MulticontainerWidget | AccordionView |\n",
311 "| | *TabView* |\n",
311 "| | *TabView* |\n",
312 "| SelectionWidget | ToggleButtonsView |\n",
312 "| SelectionWidget | ToggleButtonsView |\n",
313 "| | RadioButtonsView |\n",
313 "| | RadioButtonsView |\n",
314 "| | *DropdownView* |\n",
314 "| | *DropdownView* |\n",
315 "| | ListBoxView |\n",
315 "| | ListBoxView |\n",
316 "| StringWidget | LabelView |\n",
316 "| StringWidget | HTMLView |\n",
317 "| | TextAreaView |\n",
317 "| | TextAreaView |\n",
318 "| | *TextBoxView* |\n"
318 "| | *TextBoxView* |\n"
319 ]
319 ]
320 }
320 }
321 ],
321 ],
322 "metadata": {}
322 "metadata": {}
323 }
323 }
324 ]
324 ]
325 } No newline at end of file
325 }
@@ -1,337 +1,337 b''
1 {
1 {
2 "metadata": {
2 "metadata": {
3 "cell_tags": [
3 "cell_tags": [
4 [
4 [
5 "<None>",
5 "<None>",
6 null
6 null
7 ]
7 ]
8 ],
8 ],
9 "name": ""
9 "name": ""
10 },
10 },
11 "nbformat": 3,
11 "nbformat": 3,
12 "nbformat_minor": 0,
12 "nbformat_minor": 0,
13 "worksheets": [
13 "worksheets": [
14 {
14 {
15 "cells": [
15 "cells": [
16 {
16 {
17 "cell_type": "code",
17 "cell_type": "code",
18 "collapsed": false,
18 "collapsed": false,
19 "input": [
19 "input": [
20 "from IPython.html import widgets # Widget definitions\n",
20 "from IPython.html import widgets # Widget definitions\n",
21 "from IPython.display import display # Used to display widgets in the notebook"
21 "from IPython.display import display # Used to display widgets in the notebook"
22 ],
22 ],
23 "language": "python",
23 "language": "python",
24 "metadata": {},
24 "metadata": {},
25 "outputs": [],
25 "outputs": [],
26 "prompt_number": 1
26 "prompt_number": 1
27 },
27 },
28 {
28 {
29 "cell_type": "heading",
29 "cell_type": "heading",
30 "level": 1,
30 "level": 1,
31 "metadata": {},
31 "metadata": {},
32 "source": [
32 "source": [
33 "CSS"
33 "CSS"
34 ]
34 ]
35 },
35 },
36 {
36 {
37 "cell_type": "markdown",
37 "cell_type": "markdown",
38 "metadata": {},
38 "metadata": {},
39 "source": [
39 "source": [
40 "When trying to design an attractive widget GUI, styling becomes important. Widget views are DOM (document object model) elements that can be controlled with CSS. There are two helper methods defined on widget that allow the manipulation of the widget's CSS. The first is the `set_css` method, whos doc string is displayed below. This method allows one or more CSS attributes to be set at once. "
40 "When trying to design an attractive widget GUI, styling becomes important. Widget views are DOM (document object model) elements that can be controlled with CSS. There are two helper methods defined on widget that allow the manipulation of the widget's CSS. The first is the `set_css` method, whos doc string is displayed below. This method allows one or more CSS attributes to be set at once. "
41 ]
41 ]
42 },
42 },
43 {
43 {
44 "cell_type": "code",
44 "cell_type": "code",
45 "collapsed": false,
45 "collapsed": false,
46 "input": [
46 "input": [
47 "print(widgets.Widget.set_css.__doc__)"
47 "print(widgets.Widget.set_css.__doc__)"
48 ],
48 ],
49 "language": "python",
49 "language": "python",
50 "metadata": {},
50 "metadata": {},
51 "outputs": [
51 "outputs": [
52 {
52 {
53 "output_type": "stream",
53 "output_type": "stream",
54 "stream": "stdout",
54 "stream": "stdout",
55 "text": [
55 "text": [
56 "Set one or more CSS properties of the widget (shared among all of the \n",
56 "Set one or more CSS properties of the widget (shared among all of the \n",
57 " views). This function has two signatures:\n",
57 " views). This function has two signatures:\n",
58 " - set_css(css_dict, [selector=''])\n",
58 " - set_css(css_dict, [selector=''])\n",
59 " - set_css(key, value, [selector=''])\n",
59 " - set_css(key, value, [selector=''])\n",
60 "\n",
60 "\n",
61 " Parameters\n",
61 " Parameters\n",
62 " ----------\n",
62 " ----------\n",
63 " css_dict : dict\n",
63 " css_dict : dict\n",
64 " CSS key/value pairs to apply\n",
64 " CSS key/value pairs to apply\n",
65 " key: unicode\n",
65 " key: unicode\n",
66 " CSS key\n",
66 " CSS key\n",
67 " value\n",
67 " value\n",
68 " CSS value\n",
68 " CSS value\n",
69 " selector: unicode (optional)\n",
69 " selector: unicode (optional)\n",
70 " JQuery selector to use to apply the CSS key/value.\n",
70 " JQuery selector to use to apply the CSS key/value.\n",
71 " \n"
71 " \n"
72 ]
72 ]
73 }
73 }
74 ],
74 ],
75 "prompt_number": 2
75 "prompt_number": 2
76 },
76 },
77 {
77 {
78 "cell_type": "markdown",
78 "cell_type": "markdown",
79 "metadata": {},
79 "metadata": {},
80 "source": [
80 "source": [
81 "The second is `get_css` which allows CSS attributes that have been set to be read. Note that this method will only read CSS attributes that have been set using the `set_css` method. `get_css`'s doc string is displayed below."
81 "The second is `get_css` which allows CSS attributes that have been set to be read. Note that this method will only read CSS attributes that have been set using the `set_css` method. `get_css`'s doc string is displayed below."
82 ]
82 ]
83 },
83 },
84 {
84 {
85 "cell_type": "code",
85 "cell_type": "code",
86 "collapsed": false,
86 "collapsed": false,
87 "input": [
87 "input": [
88 "print(widgets.Widget.get_css.__doc__)"
88 "print(widgets.Widget.get_css.__doc__)"
89 ],
89 ],
90 "language": "python",
90 "language": "python",
91 "metadata": {},
91 "metadata": {},
92 "outputs": [
92 "outputs": [
93 {
93 {
94 "output_type": "stream",
94 "output_type": "stream",
95 "stream": "stdout",
95 "stream": "stdout",
96 "text": [
96 "text": [
97 "Get a CSS property of the widget. Note, this function does not \n",
97 "Get a CSS property of the widget. Note, this function does not \n",
98 " actually request the CSS from the front-end; Only properties that have \n",
98 " actually request the CSS from the front-end; Only properties that have \n",
99 " been set with set_css can be read.\n",
99 " been set with set_css can be read.\n",
100 "\n",
100 "\n",
101 " Parameters\n",
101 " Parameters\n",
102 " ----------\n",
102 " ----------\n",
103 " key: unicode\n",
103 " key: unicode\n",
104 " CSS key\n",
104 " CSS key\n",
105 " selector: unicode (optional)\n",
105 " selector: unicode (optional)\n",
106 " JQuery selector used when the CSS key/value was set.\n",
106 " JQuery selector used when the CSS key/value was set.\n",
107 " \n"
107 " \n"
108 ]
108 ]
109 }
109 }
110 ],
110 ],
111 "prompt_number": 3
111 "prompt_number": 3
112 },
112 },
113 {
113 {
114 "cell_type": "markdown",
114 "cell_type": "markdown",
115 "metadata": {},
115 "metadata": {},
116 "source": [
116 "source": [
117 "Below is an example that applies CSS attributes to a container to emphasize text."
117 "Below is an example that applies CSS attributes to a container to emphasize text."
118 ]
118 ]
119 },
119 },
120 {
120 {
121 "cell_type": "code",
121 "cell_type": "code",
122 "collapsed": false,
122 "collapsed": false,
123 "input": [
123 "input": [
124 "container = widgets.ContainerWidget()\n",
124 "container = widgets.ContainerWidget()\n",
125 "\n",
125 "\n",
126 "# set_css used to set a single CSS attribute.\n",
126 "# set_css used to set a single CSS attribute.\n",
127 "container.set_css('border', '3px solid black') # Border the container\n",
127 "container.set_css('border', '3px solid black') # Border the container\n",
128 "\n",
128 "\n",
129 "# set_css used to set multiple CSS attributes.\n",
129 "# set_css used to set multiple CSS attributes.\n",
130 "container.set_css({'padding': '6px', # Add padding to the container\n",
130 "container.set_css({'padding': '6px', # Add padding to the container\n",
131 " 'background': 'yellow'}) # Fill the container yellow\n",
131 " 'background': 'yellow'}) # Fill the container yellow\n",
132 "\n",
132 "\n",
133 "label = widgets.StringWidget(default_view_name=\"LabelView\", parent=container)\n",
133 "label = widgets.StringWidget(default_view_name=\"HTMLView\", parent=container)\n",
134 "label.value = \"<strong>ALERT: </strong> Hello World!\"\n",
134 "label.value = \"<strong>ALERT: </strong> Hello World!\"\n",
135 "\n",
135 "\n",
136 "display(container)"
136 "display(container)"
137 ],
137 ],
138 "language": "python",
138 "language": "python",
139 "metadata": {},
139 "metadata": {},
140 "outputs": [],
140 "outputs": [],
141 "prompt_number": 4
141 "prompt_number": 4
142 },
142 },
143 {
143 {
144 "cell_type": "heading",
144 "cell_type": "heading",
145 "level": 1,
145 "level": 1,
146 "metadata": {},
146 "metadata": {},
147 "source": [
147 "source": [
148 "DOM Classes"
148 "DOM Classes"
149 ]
149 ]
150 },
150 },
151 {
151 {
152 "cell_type": "markdown",
152 "cell_type": "markdown",
153 "metadata": {},
153 "metadata": {},
154 "source": [
154 "source": [
155 "In some cases it's necessary to apply DOM classes to your widgets. DOM classes allow DOM elements to be indentified by Javascript and CSS. The notebook defines its own set of classes to stylize its elements. The `add_class` widget method allows you to add DOM classes to your widget's definition. The `add_class` method's doc string can be seen below."
155 "In some cases it's necessary to apply DOM classes to your widgets. DOM classes allow DOM elements to be indentified by Javascript and CSS. The notebook defines its own set of classes to stylize its elements. The `add_class` widget method allows you to add DOM classes to your widget's definition. The `add_class` method's doc string can be seen below."
156 ]
156 ]
157 },
157 },
158 {
158 {
159 "cell_type": "code",
159 "cell_type": "code",
160 "collapsed": false,
160 "collapsed": false,
161 "input": [
161 "input": [
162 "print(widgets.Widget.add_class.__doc__)"
162 "print(widgets.Widget.add_class.__doc__)"
163 ],
163 ],
164 "language": "python",
164 "language": "python",
165 "metadata": {},
165 "metadata": {},
166 "outputs": [
166 "outputs": [
167 {
167 {
168 "output_type": "stream",
168 "output_type": "stream",
169 "stream": "stdout",
169 "stream": "stdout",
170 "text": [
170 "text": [
171 "Add class[es] to a DOM element\n",
171 "Add class[es] to a DOM element\n",
172 "\n",
172 "\n",
173 " Parameters\n",
173 " Parameters\n",
174 " ----------\n",
174 " ----------\n",
175 " class_name: unicode\n",
175 " class_name: unicode\n",
176 " Class name(s) to add to the DOM element(s). Multiple class names \n",
176 " Class name(s) to add to the DOM element(s). Multiple class names \n",
177 " must be space separated.\n",
177 " must be space separated.\n",
178 " selector: unicode (optional)\n",
178 " selector: unicode (optional)\n",
179 " JQuery selector to select the DOM element(s) that the class(es) will \n",
179 " JQuery selector to select the DOM element(s) that the class(es) will \n",
180 " be added to.\n",
180 " be added to.\n",
181 " \n"
181 " \n"
182 ]
182 ]
183 }
183 }
184 ],
184 ],
185 "prompt_number": 5
185 "prompt_number": 5
186 },
186 },
187 {
187 {
188 "cell_type": "markdown",
188 "cell_type": "markdown",
189 "metadata": {},
189 "metadata": {},
190 "source": [
190 "source": [
191 "Since `add_class` if a DOM operation, it will only affect widgets that have been displayed. `add_class` must be called after the widget has been displayed. Extending the example above, the corners of the container can be rounded by adding the `corner-all` notebook class to the container (as seen below). "
191 "Since `add_class` if a DOM operation, it will only affect widgets that have been displayed. `add_class` must be called after the widget has been displayed. Extending the example above, the corners of the container can be rounded by adding the `corner-all` notebook class to the container (as seen below). "
192 ]
192 ]
193 },
193 },
194 {
194 {
195 "cell_type": "code",
195 "cell_type": "code",
196 "collapsed": false,
196 "collapsed": false,
197 "input": [
197 "input": [
198 "container = widgets.ContainerWidget()\n",
198 "container = widgets.ContainerWidget()\n",
199 "container.set_css({'border': '3px solid black',\n",
199 "container.set_css({'border': '3px solid black',\n",
200 " 'padding': '6px',\n",
200 " 'padding': '6px', \n",
201 " 'background': 'yellow'}) \n",
201 " 'background': 'yellow'}) \n",
202 "\n",
202 "\n",
203 "label = widgets.StringWidget(default_view_name=\"LabelView\", parent=container) \n",
203 "label = widgets.StringWidget(default_view_name=\"HTMLView\", parent=container)\n",
204 "label.value = \"<strong>ALERT: </strong> Hello World!\"\n",
204 "label.value = \"<strong>ALERT: </strong> Hello World!\"\n",
205 "\n",
205 "\n",
206 "display(container)\n",
206 "display(container)\n",
207 "container.add_class('corner-all') # Must be called AFTER display"
207 "container.add_class('corner-all') # Must be called AFTER display"
208 ],
208 ],
209 "language": "python",
209 "language": "python",
210 "metadata": {},
210 "metadata": {},
211 "outputs": [],
211 "outputs": [],
212 "prompt_number": 6
212 "prompt_number": 6
213 },
213 },
214 {
214 {
215 "cell_type": "markdown",
215 "cell_type": "markdown",
216 "metadata": {},
216 "metadata": {},
217 "source": [
217 "source": [
218 "The IPython notebook uses bootstrap for styling. The example above can be simplified by using a bootstrap class (as seen below). Bootstrap documentation can be found at http://getbootstrap.com/\u200e ."
218 "The IPython notebook uses bootstrap for styling. The example above can be simplified by using a bootstrap class (as seen below). Bootstrap documentation can be found at http://getbootstrap.com/\u200e ."
219 ]
219 ]
220 },
220 },
221 {
221 {
222 "cell_type": "code",
222 "cell_type": "code",
223 "collapsed": false,
223 "collapsed": false,
224 "input": [
224 "input": [
225 "label = widgets.StringWidget(value = \"<strong>ALERT: </strong> Hello World!\")\n",
225 "label = widgets.StringWidget(value = \"<strong>ALERT: </strong> Hello World!\")\n",
226 "display(label, view_name=\"LabelView\")\n",
226 "display(label, view_name=\"HTMLView\")\n",
227 "\n",
227 "\n",
228 "# Apply twitter bootstrap alert class to the label.\n",
228 "# Apply twitter bootstrap alert class to the label.\n",
229 "label.add_class(\"alert\")"
229 "label.add_class(\"alert\")"
230 ],
230 ],
231 "language": "python",
231 "language": "python",
232 "metadata": {},
232 "metadata": {},
233 "outputs": [],
233 "outputs": [],
234 "prompt_number": 7
234 "prompt_number": 7
235 },
235 },
236 {
236 {
237 "cell_type": "markdown",
237 "cell_type": "markdown",
238 "metadata": {},
238 "metadata": {},
239 "source": [
239 "source": [
240 "The example below shows how bootstrap classes can be used to change button apearance."
240 "The example below shows how bootstrap classes can be used to change button apearance."
241 ]
241 ]
242 },
242 },
243 {
243 {
244 "cell_type": "code",
244 "cell_type": "code",
245 "collapsed": false,
245 "collapsed": false,
246 "input": [
246 "input": [
247 "# List of the bootstrap button styles\n",
247 "# List of the bootstrap button styles\n",
248 "button_classes = ['Default', 'btn-primary', 'btn-info', 'btn-success', \n",
248 "button_classes = ['Default', 'btn-primary', 'btn-info', 'btn-success', \n",
249 " 'btn-warning', 'btn-danger', 'btn-inverse', 'btn-link']\n",
249 " 'btn-warning', 'btn-danger', 'btn-inverse', 'btn-link']\n",
250 "\n",
250 "\n",
251 "# Create each button and apply the style. Also add margin to the buttons so they space\n",
251 "# Create each button and apply the style. Also add margin to the buttons so they space\n",
252 "# themselves nicely.\n",
252 "# themselves nicely.\n",
253 "for i in range(8):\n",
253 "for i in range(8):\n",
254 " button = widgets.ButtonWidget(description=button_classes[i])\n",
254 " button = widgets.ButtonWidget(description=button_classes[i])\n",
255 " button.set_css(\"margin\", \"5px\")\n",
255 " button.set_css(\"margin\", \"5px\")\n",
256 " display(button)\n",
256 " display(button)\n",
257 " if i > 0: # Don't add a class the first button.\n",
257 " if i > 0: # Don't add a class the first button.\n",
258 " button.add_class(button_classes[i])\n",
258 " button.add_class(button_classes[i])\n",
259 " "
259 " "
260 ],
260 ],
261 "language": "python",
261 "language": "python",
262 "metadata": {},
262 "metadata": {},
263 "outputs": [],
263 "outputs": [],
264 "prompt_number": 8
264 "prompt_number": 8
265 },
265 },
266 {
266 {
267 "cell_type": "markdown",
267 "cell_type": "markdown",
268 "metadata": {},
268 "metadata": {},
269 "source": [
269 "source": [
270 "It's also useful to be able to remove DOM classes from widgets. The `remove_class` widget method allows you to remove classes from widgets that have been displayed. Like `add_widget`, it must be called after the widget has been displayed. The doc string of `remove_class` can be seen below."
270 "It's also useful to be able to remove DOM classes from widgets. The `remove_class` widget method allows you to remove classes from widgets that have been displayed. Like `add_widget`, it must be called after the widget has been displayed. The doc string of `remove_class` can be seen below."
271 ]
271 ]
272 },
272 },
273 {
273 {
274 "cell_type": "code",
274 "cell_type": "code",
275 "collapsed": false,
275 "collapsed": false,
276 "input": [
276 "input": [
277 "print(widgets.Widget.remove_class.__doc__)"
277 "print(widgets.Widget.remove_class.__doc__)"
278 ],
278 ],
279 "language": "python",
279 "language": "python",
280 "metadata": {},
280 "metadata": {},
281 "outputs": [
281 "outputs": [
282 {
282 {
283 "output_type": "stream",
283 "output_type": "stream",
284 "stream": "stdout",
284 "stream": "stdout",
285 "text": [
285 "text": [
286 "Remove class[es] from a DOM element\n",
286 "Remove class[es] from a DOM element\n",
287 "\n",
287 "\n",
288 " Parameters\n",
288 " Parameters\n",
289 " ----------\n",
289 " ----------\n",
290 " class_name: unicode\n",
290 " class_name: unicode\n",
291 " Class name(s) to remove from the DOM element(s). Multiple class \n",
291 " Class name(s) to remove from the DOM element(s). Multiple class \n",
292 " names must be space separated.\n",
292 " names must be space separated.\n",
293 " selector: unicode (optional)\n",
293 " selector: unicode (optional)\n",
294 " JQuery selector to select the DOM element(s) that the class(es) will \n",
294 " JQuery selector to select the DOM element(s) that the class(es) will \n",
295 " be removed from.\n",
295 " be removed from.\n",
296 " \n"
296 " \n"
297 ]
297 ]
298 }
298 }
299 ],
299 ],
300 "prompt_number": 9
300 "prompt_number": 9
301 },
301 },
302 {
302 {
303 "cell_type": "markdown",
303 "cell_type": "markdown",
304 "metadata": {},
304 "metadata": {},
305 "source": [
305 "source": [
306 "The example below animates an alert using different bootstrap styles."
306 "The example below animates an alert using different bootstrap styles."
307 ]
307 ]
308 },
308 },
309 {
309 {
310 "cell_type": "code",
310 "cell_type": "code",
311 "collapsed": false,
311 "collapsed": false,
312 "input": [
312 "input": [
313 "import time\n",
313 "import time\n",
314 "label = widgets.StringWidget(value = \"<strong>ALERT: </strong> Hello World!\")\n",
314 "label = widgets.StringWidget(value = \"<strong>ALERT: </strong> Hello World!\")\n",
315 "display(label, view_name=\"LabelView\")\n",
315 "display(label, view_name=\"HTMLView\")\n",
316 "\n",
316 "\n",
317 "# Apply twitter bootstrap alert class to the label.\n",
317 "# Apply twitter bootstrap alert class to the label.\n",
318 "label.add_class(\"alert\")\n",
318 "label.add_class(\"alert\")\n",
319 "\n",
319 "\n",
320 "# Animate through additional bootstrap label styles 3 times\n",
320 "# Animate through additional bootstrap label styles 3 times\n",
321 "additional_alert_styles = ['alert-error', 'alert-info', 'alert-success']\n",
321 "additional_alert_styles = ['alert-error', 'alert-info', 'alert-success']\n",
322 "for i in range(3 * len(additional_alert_styles)):\n",
322 "for i in range(3 * len(additional_alert_styles)):\n",
323 " label.add_class(additional_alert_styles[i % 3])\n",
323 " label.add_class(additional_alert_styles[i % 3])\n",
324 " label.remove_class(additional_alert_styles[(i-1) % 3])\n",
324 " label.remove_class(additional_alert_styles[(i-1) % 3])\n",
325 " time.sleep(1)\n",
325 " time.sleep(1)\n",
326 " "
326 " "
327 ],
327 ],
328 "language": "python",
328 "language": "python",
329 "metadata": {},
329 "metadata": {},
330 "outputs": [],
330 "outputs": [],
331 "prompt_number": 10
331 "prompt_number": 10
332 }
332 }
333 ],
333 ],
334 "metadata": {}
334 "metadata": {}
335 }
335 }
336 ]
336 ]
337 } No newline at end of file
337 }
@@ -1,304 +1,304 b''
1 {
1 {
2 "metadata": {
2 "metadata": {
3 "cell_tags": [
3 "cell_tags": [
4 [
4 [
5 "<None>",
5 "<None>",
6 null
6 null
7 ]
7 ]
8 ],
8 ],
9 "name": ""
9 "name": ""
10 },
10 },
11 "nbformat": 3,
11 "nbformat": 3,
12 "nbformat_minor": 0,
12 "nbformat_minor": 0,
13 "worksheets": [
13 "worksheets": [
14 {
14 {
15 "cells": [
15 "cells": [
16 {
16 {
17 "cell_type": "code",
17 "cell_type": "code",
18 "collapsed": false,
18 "collapsed": false,
19 "input": [
19 "input": [
20 "from IPython.html import widgets # Widget definitions\n",
20 "from IPython.html import widgets # Widget definitions\n",
21 "from IPython.display import display # Used to display widgets in the notebook"
21 "from IPython.display import display # Used to display widgets in the notebook"
22 ],
22 ],
23 "language": "python",
23 "language": "python",
24 "metadata": {},
24 "metadata": {},
25 "outputs": [],
25 "outputs": [],
26 "prompt_number": 1
26 "prompt_number": 1
27 },
27 },
28 {
28 {
29 "cell_type": "heading",
29 "cell_type": "heading",
30 "level": 1,
30 "level": 1,
31 "metadata": {},
31 "metadata": {},
32 "source": [
32 "source": [
33 "Alignment"
33 "Alignment"
34 ]
34 ]
35 },
35 },
36 {
36 {
37 "cell_type": "markdown",
37 "cell_type": "markdown",
38 "metadata": {},
38 "metadata": {},
39 "source": [
39 "source": [
40 "Most widgets have a `description` property which allows a label for the widget to be defined. The label of the widget has a fixed minimum width. The text of the label is always right aligned and the widget is left aligned (as seen below) "
40 "Most widgets have a `description` property which allows a label for the widget to be defined. The label of the widget has a fixed minimum width. The text of the label is always right aligned and the widget is left aligned (as seen below) "
41 ]
41 ]
42 },
42 },
43 {
43 {
44 "cell_type": "code",
44 "cell_type": "code",
45 "collapsed": false,
45 "collapsed": false,
46 "input": [
46 "input": [
47 "display(widgets.StringWidget(description=\"a:\"))\n",
47 "display(widgets.StringWidget(description=\"a:\"))\n",
48 "display(widgets.StringWidget(description=\"aa:\"))\n",
48 "display(widgets.StringWidget(description=\"aa:\"))\n",
49 "display(widgets.StringWidget(description=\"aaa:\"))"
49 "display(widgets.StringWidget(description=\"aaa:\"))"
50 ],
50 ],
51 "language": "python",
51 "language": "python",
52 "metadata": {},
52 "metadata": {},
53 "outputs": [],
53 "outputs": [],
54 "prompt_number": 2
54 "prompt_number": 2
55 },
55 },
56 {
56 {
57 "cell_type": "markdown",
57 "cell_type": "markdown",
58 "metadata": {},
58 "metadata": {},
59 "source": [
59 "source": [
60 "If a label is longer than the minimum width, the widget is shifted to the right (as seen below)."
60 "If a label is longer than the minimum width, the widget is shifted to the right (as seen below)."
61 ]
61 ]
62 },
62 },
63 {
63 {
64 "cell_type": "code",
64 "cell_type": "code",
65 "collapsed": false,
65 "collapsed": false,
66 "input": [
66 "input": [
67 "display(widgets.StringWidget(description=\"a:\"))\n",
67 "display(widgets.StringWidget(description=\"a:\"))\n",
68 "display(widgets.StringWidget(description=\"aa:\"))\n",
68 "display(widgets.StringWidget(description=\"aa:\"))\n",
69 "display(widgets.StringWidget(description=\"aaa:\"))\n",
69 "display(widgets.StringWidget(description=\"aaa:\"))\n",
70 "display(widgets.StringWidget(description=\"aaaaaaaaaaaaaaaaaa:\"))"
70 "display(widgets.StringWidget(description=\"aaaaaaaaaaaaaaaaaa:\"))"
71 ],
71 ],
72 "language": "python",
72 "language": "python",
73 "metadata": {},
73 "metadata": {},
74 "outputs": [],
74 "outputs": [],
75 "prompt_number": 3
75 "prompt_number": 3
76 },
76 },
77 {
77 {
78 "cell_type": "markdown",
78 "cell_type": "markdown",
79 "metadata": {},
79 "metadata": {},
80 "source": [
80 "source": [
81 "If a `description` is not set for the widget, the label is not displayed (as seen below)."
81 "If a `description` is not set for the widget, the label is not displayed (as seen below)."
82 ]
82 ]
83 },
83 },
84 {
84 {
85 "cell_type": "code",
85 "cell_type": "code",
86 "collapsed": false,
86 "collapsed": false,
87 "input": [
87 "input": [
88 "display(widgets.StringWidget(description=\"a:\"))\n",
88 "display(widgets.StringWidget(description=\"a:\"))\n",
89 "display(widgets.StringWidget(description=\"aa:\"))\n",
89 "display(widgets.StringWidget(description=\"aa:\"))\n",
90 "display(widgets.StringWidget(description=\"aaa:\"))\n",
90 "display(widgets.StringWidget(description=\"aaa:\"))\n",
91 "display(widgets.StringWidget())"
91 "display(widgets.StringWidget())"
92 ],
92 ],
93 "language": "python",
93 "language": "python",
94 "metadata": {},
94 "metadata": {},
95 "outputs": [],
95 "outputs": [],
96 "prompt_number": 4
96 "prompt_number": 4
97 },
97 },
98 {
98 {
99 "cell_type": "heading",
99 "cell_type": "heading",
100 "level": 1,
100 "level": 1,
101 "metadata": {},
101 "metadata": {},
102 "source": [
102 "source": [
103 "Custom Alignment"
103 "Custom Alignment"
104 ]
104 ]
105 },
105 },
106 {
106 {
107 "cell_type": "markdown",
107 "cell_type": "markdown",
108 "metadata": {},
108 "metadata": {},
109 "source": [
109 "source": [
110 "`ContainerWidget`s allow for custom alignment of widgets. The `hbox` and `vbox` methods (parameterless) cause the `ContainerWidget` to both horizontally and vertically align its children. The following example compares `vbox` to `hbox`."
110 "`ContainerWidget`s allow for custom alignment of widgets. The `hbox` and `vbox` methods (parameterless) cause the `ContainerWidget` to both horizontally and vertically align its children. The following example compares `vbox` to `hbox`."
111 ]
111 ]
112 },
112 },
113 {
113 {
114 "cell_type": "code",
114 "cell_type": "code",
115 "collapsed": false,
115 "collapsed": false,
116 "input": [
116 "input": [
117 "child_style = {\n",
117 "child_style = {\n",
118 " 'background': '#77CC77',\n",
118 " 'background': '#77CC77',\n",
119 " 'padding': '25px',\n",
119 " 'padding': '25px',\n",
120 " 'margin': '5px',\n",
120 " 'margin': '5px',\n",
121 " 'font-size': 'xx-large',\n",
121 " 'font-size': 'xx-large',\n",
122 " 'color': 'white',\n",
122 " 'color': 'white',\n",
123 "}\n",
123 "}\n",
124 "\n",
124 "\n",
125 "def make_container(title):\n",
125 "def make_container(title):\n",
126 " display(widgets.StringWidget(default_view_name='LabelView', value='<h2><br>' + title + '</h2>'))\n",
126 " display(widgets.StringWidget(default_view_name='HTMLView', value='<h2><br>' + title + '</h2>'))\n",
127 " container = widgets.ContainerWidget()\n",
127 " container = widgets.ContainerWidget()\n",
128 " container.set_css('background', '#999999')\n",
128 " container.set_css('background', '#999999')\n",
129 " display(container)\n",
129 " display(container)\n",
130 " return container\n",
130 " return container\n",
131 "\n",
131 "\n",
132 "def fill_container(container):\n",
132 "def fill_container(container):\n",
133 " components = []\n",
133 " components = []\n",
134 " for i in range(3):\n",
134 " for i in range(3):\n",
135 " components.append(widgets.StringWidget(parent=container, default_view_name='LabelView', value=\"ABC\"[i]))\n",
135 " components.append(widgets.StringWidget(parent=container, default_view_name='HTMLView', value=\"ABC\"[i]))\n",
136 " components[i].set_css(child_style)\n",
136 " components[i].set_css(child_style)\n",
137 " display(components[i])\n",
137 " display(components[i])\n",
138 " \n",
138 " \n",
139 "container = make_container('VBox')\n",
139 "container = make_container('VBox')\n",
140 "container.vbox()\n",
140 "container.vbox()\n",
141 "fill_container(container)\n",
141 "fill_container(container)\n",
142 "\n",
142 "\n",
143 "container = make_container('HBox')\n",
143 "container = make_container('HBox')\n",
144 "container.hbox()\n",
144 "container.hbox()\n",
145 "fill_container(container)\n"
145 "fill_container(container)\n"
146 ],
146 ],
147 "language": "python",
147 "language": "python",
148 "metadata": {},
148 "metadata": {},
149 "outputs": [],
149 "outputs": [],
150 "prompt_number": 5
150 "prompt_number": 5
151 },
151 },
152 {
152 {
153 "cell_type": "markdown",
153 "cell_type": "markdown",
154 "metadata": {},
154 "metadata": {},
155 "source": [
155 "source": [
156 "The `ContainerWidget` `pack_start`, `pack_center`, and `pack_end` methods (parameterless) adjust the alignment of the widgets on the axis that they are being rendered on. Below is an example of the different alignments."
156 "The `ContainerWidget` `pack_start`, `pack_center`, and `pack_end` methods (parameterless) adjust the alignment of the widgets on the axis that they are being rendered on. Below is an example of the different alignments."
157 ]
157 ]
158 },
158 },
159 {
159 {
160 "cell_type": "code",
160 "cell_type": "code",
161 "collapsed": false,
161 "collapsed": false,
162 "input": [
162 "input": [
163 "container = make_container('HBox Pack Start')\n",
163 "container = make_container('HBox Pack Start')\n",
164 "container.hbox()\n",
164 "container.hbox()\n",
165 "container.pack_start()\n",
165 "container.pack_start()\n",
166 "fill_container(container)\n",
166 "fill_container(container)\n",
167 " \n",
167 " \n",
168 "container = make_container('HBox Pack Center')\n",
168 "container = make_container('HBox Pack Center')\n",
169 "container.hbox()\n",
169 "container.hbox()\n",
170 "container.pack_center()\n",
170 "container.pack_center()\n",
171 "fill_container(container)\n",
171 "fill_container(container)\n",
172 " \n",
172 " \n",
173 "container = make_container('HBox Pack End')\n",
173 "container = make_container('HBox Pack End')\n",
174 "container.hbox()\n",
174 "container.hbox()\n",
175 "container.pack_end()\n",
175 "container.pack_end()\n",
176 "fill_container(container)"
176 "fill_container(container)"
177 ],
177 ],
178 "language": "python",
178 "language": "python",
179 "metadata": {},
179 "metadata": {},
180 "outputs": [],
180 "outputs": [],
181 "prompt_number": 6
181 "prompt_number": 6
182 },
182 },
183 {
183 {
184 "cell_type": "markdown",
184 "cell_type": "markdown",
185 "metadata": {},
185 "metadata": {},
186 "source": [
186 "source": [
187 "The `ContainerWidget` `flex0`, `flex1`, and `flex2` methods (parameterless) modify the containers flexibility. Changing a container flexibility affects how and if the container will occupy the remaining space. Setting `flex0` has the same result as setting no flex. Below is an example of different flex configurations. The number on the boxes correspond to the applied flex."
187 "The `ContainerWidget` `flex0`, `flex1`, and `flex2` methods (parameterless) modify the containers flexibility. Changing a container flexibility affects how and if the container will occupy the remaining space. Setting `flex0` has the same result as setting no flex. Below is an example of different flex configurations. The number on the boxes correspond to the applied flex."
188 ]
188 ]
189 },
189 },
190 {
190 {
191 "cell_type": "code",
191 "cell_type": "code",
192 "collapsed": false,
192 "collapsed": false,
193 "input": [
193 "input": [
194 "def fill_container(container, flexes):\n",
194 "def fill_container(container, flexes):\n",
195 " components = []\n",
195 " components = []\n",
196 " for i in range(len(flexes)):\n",
196 " for i in range(len(flexes)):\n",
197 " components.append(widgets.ContainerWidget(parent=container))\n",
197 " components.append(widgets.ContainerWidget(parent=container))\n",
198 " components[i].set_css(child_style)\n",
198 " components[i].set_css(child_style)\n",
199 " \n",
199 " \n",
200 " label = widgets.StringWidget(parent=components[i], default_view_name='LabelView', value=str(flexes[i]))\n",
200 " label = widgets.StringWidget(parent=components[i], default_view_name='HTMLView', value=str(flexes[i]))\n",
201 " \n",
201 " \n",
202 " if flexes[i] == 0:\n",
202 " if flexes[i] == 0:\n",
203 " components[i].flex0()\n",
203 " components[i].flex0()\n",
204 " elif flexes[i] == 1:\n",
204 " elif flexes[i] == 1:\n",
205 " components[i].flex1()\n",
205 " components[i].flex1()\n",
206 " elif flexes[i] == 2:\n",
206 " elif flexes[i] == 2:\n",
207 " components[i].flex2()\n",
207 " components[i].flex2()\n",
208 " display(components[i])\n",
208 " display(components[i])\n",
209 " \n",
209 " \n",
210 "container = make_container('Different Flex Configurations')\n",
210 "container = make_container('Different Flex Configurations')\n",
211 "container.hbox()\n",
211 "container.hbox()\n",
212 "fill_container(container, [0, 0, 0])\n",
212 "fill_container(container, [0, 0, 0])\n",
213 " \n",
213 " \n",
214 "container = make_container('')\n",
214 "container = make_container('')\n",
215 "container.hbox()\n",
215 "container.hbox()\n",
216 "fill_container(container, [0, 0, 1])\n",
216 "fill_container(container, [0, 0, 1])\n",
217 " \n",
217 " \n",
218 "container = make_container('')\n",
218 "container = make_container('')\n",
219 "container.hbox()\n",
219 "container.hbox()\n",
220 "fill_container(container, [0, 1, 1])\n",
220 "fill_container(container, [0, 1, 1])\n",
221 " \n",
221 " \n",
222 "container = make_container('')\n",
222 "container = make_container('')\n",
223 "container.hbox()\n",
223 "container.hbox()\n",
224 "fill_container(container, [0, 2, 2])\n",
224 "fill_container(container, [0, 2, 2])\n",
225 " \n",
225 " \n",
226 "container = make_container('')\n",
226 "container = make_container('')\n",
227 "container.hbox()\n",
227 "container.hbox()\n",
228 "fill_container(container, [0, 1, 2])\n",
228 "fill_container(container, [0, 1, 2])\n",
229 " \n",
229 " \n",
230 "container = make_container('')\n",
230 "container = make_container('')\n",
231 "container.hbox()\n",
231 "container.hbox()\n",
232 "fill_container(container, [1, 1, 2])"
232 "fill_container(container, [1, 1, 2])"
233 ],
233 ],
234 "language": "python",
234 "language": "python",
235 "metadata": {},
235 "metadata": {},
236 "outputs": [],
236 "outputs": [],
237 "prompt_number": 7
237 "prompt_number": 7
238 },
238 },
239 {
239 {
240 "cell_type": "markdown",
240 "cell_type": "markdown",
241 "metadata": {},
241 "metadata": {},
242 "source": [
242 "source": [
243 "The `ContainerWidget` `align_start`, `align_center`, and `align_end` methods (parameterless) adjust the alignment of the widgets on the axis perpindicular to the one that they are being rendered on. Below is an example of the different alignments."
243 "The `ContainerWidget` `align_start`, `align_center`, and `align_end` methods (parameterless) adjust the alignment of the widgets on the axis perpindicular to the one that they are being rendered on. Below is an example of the different alignments."
244 ]
244 ]
245 },
245 },
246 {
246 {
247 "cell_type": "code",
247 "cell_type": "code",
248 "collapsed": false,
248 "collapsed": false,
249 "input": [
249 "input": [
250 "def fill_container(container):\n",
250 "def fill_container(container):\n",
251 " components = []\n",
251 " components = []\n",
252 " for i in range(3):\n",
252 " for i in range(3):\n",
253 " components.append(widgets.StringWidget(parent=container, default_view_name='LabelView', value=\"ABC\"[i]))\n",
253 " components.append(widgets.StringWidget(parent=container, default_view_name='HTMLView', value=\"ABC\"[i]))\n",
254 " components[i].set_css(child_style)\n",
254 " components[i].set_css(child_style)\n",
255 " components[i].set_css('height', str((i+1) * 50) + 'px')\n",
255 " components[i].set_css('height', str((i+1) * 50) + 'px')\n",
256 " display(components[i])\n",
256 " display(components[i])\n",
257 "\n",
257 "\n",
258 "container = make_container('HBox Align Start')\n",
258 "container = make_container('HBox Align Start')\n",
259 "container.hbox()\n",
259 "container.hbox()\n",
260 "container.align_start()\n",
260 "container.align_start()\n",
261 "fill_container(container)\n",
261 "fill_container(container)\n",
262 " \n",
262 " \n",
263 "container = make_container('HBox Align Center')\n",
263 "container = make_container('HBox Align Center')\n",
264 "container.hbox()\n",
264 "container.hbox()\n",
265 "container.align_center()\n",
265 "container.align_center()\n",
266 "fill_container(container)\n",
266 "fill_container(container)\n",
267 " \n",
267 " \n",
268 "container = make_container('HBox Align End')\n",
268 "container = make_container('HBox Align End')\n",
269 "container.hbox()\n",
269 "container.hbox()\n",
270 "container.align_end()\n",
270 "container.align_end()\n",
271 "fill_container(container)"
271 "fill_container(container)"
272 ],
272 ],
273 "language": "python",
273 "language": "python",
274 "metadata": {},
274 "metadata": {},
275 "outputs": [],
275 "outputs": [],
276 "prompt_number": 8
276 "prompt_number": 8
277 },
277 },
278 {
278 {
279 "cell_type": "markdown",
279 "cell_type": "markdown",
280 "metadata": {},
280 "metadata": {},
281 "source": [
281 "source": [
282 "By default the widget area is a `vbox`; however, there are many uses for a `hbox`. The example below uses a `hbox` to display a set of vertical sliders, like an equalizer."
282 "By default the widget area is a `vbox`; however, there are many uses for a `hbox`. The example below uses a `hbox` to display a set of vertical sliders, like an equalizer."
283 ]
283 ]
284 },
284 },
285 {
285 {
286 "cell_type": "code",
286 "cell_type": "code",
287 "collapsed": false,
287 "collapsed": false,
288 "input": [
288 "input": [
289 "container = widgets.ContainerWidget()\n",
289 "container = widgets.ContainerWidget()\n",
290 "container.hbox()\n",
290 "container.hbox()\n",
291 "for i in range(15):\n",
291 "for i in range(15):\n",
292 " widgets.FloatRangeWidget(orientation='vertical', parent=container, description=str(i+1), value=50.0)\n",
292 " widgets.FloatRangeWidget(orientation='vertical', parent=container, description=str(i+1), value=50.0)\n",
293 "display(container)"
293 "display(container)"
294 ],
294 ],
295 "language": "python",
295 "language": "python",
296 "metadata": {},
296 "metadata": {},
297 "outputs": [],
297 "outputs": [],
298 "prompt_number": 9
298 "prompt_number": 9
299 }
299 }
300 ],
300 ],
301 "metadata": {}
301 "metadata": {}
302 }
302 }
303 ]
303 ]
304 } No newline at end of file
304 }
@@ -1,249 +1,249 b''
1 {
1 {
2 "metadata": {
2 "metadata": {
3 "name": ""
3 "name": ""
4 },
4 },
5 "nbformat": 3,
5 "nbformat": 3,
6 "nbformat_minor": 0,
6 "nbformat_minor": 0,
7 "worksheets": [
7 "worksheets": [
8 {
8 {
9 "cells": [
9 "cells": [
10 {
10 {
11 "cell_type": "heading",
11 "cell_type": "heading",
12 "level": 1,
12 "level": 1,
13 "metadata": {},
13 "metadata": {},
14 "source": [
14 "source": [
15 "Build the Variable Inspector"
15 "Build the Variable Inspector"
16 ]
16 ]
17 },
17 },
18 {
18 {
19 "cell_type": "code",
19 "cell_type": "code",
20 "collapsed": false,
20 "collapsed": false,
21 "input": [
21 "input": [
22 "from IPython.html import widgets\n",
22 "from IPython.html import widgets\n",
23 "from IPython.display import display\n",
23 "from IPython.display import display\n",
24 "import re"
24 "import re"
25 ],
25 ],
26 "language": "python",
26 "language": "python",
27 "metadata": {},
27 "metadata": {},
28 "outputs": [],
28 "outputs": [],
29 "prompt_number": 1
29 "prompt_number": 1
30 },
30 },
31 {
31 {
32 "cell_type": "heading",
32 "cell_type": "heading",
33 "level": 3,
33 "level": 3,
34 "metadata": {},
34 "metadata": {},
35 "source": [
35 "source": [
36 "Create Variable Inspector Controls"
36 "Create Variable Inspector Controls"
37 ]
37 ]
38 },
38 },
39 {
39 {
40 "cell_type": "code",
40 "cell_type": "code",
41 "collapsed": false,
41 "collapsed": false,
42 "input": [
42 "input": [
43 "_popout = widgets.ContainerWidget(default_view_name=\"ModalView\")\n",
43 "_popout = widgets.ContainerWidget(default_view_name=\"ModalView\")\n",
44 "_popout.description = \"Variable Inspector\"\n",
44 "_popout.description = \"Variable Inspector\"\n",
45 "_popout.button_text = _popout.description\n",
45 "_popout.button_text = _popout.description\n",
46 "_popout.vbox()\n",
46 "_popout.vbox()\n",
47 "\n",
47 "\n",
48 "_modal_header_execs_label = widgets.StringWidget(parent=_popout, default_view_name=\"LabelView\")\n",
48 "_modal_header_execs_label = widgets.StringWidget(parent=_popout, default_view_name=\"HTMLView\")\n",
49 "_modal_header_execs_label.execs = 0\n",
49 "_modal_header_execs_label.execs = 0\n",
50 "\n",
50 "\n",
51 "_modal_body = widgets.ContainerWidget(parent=_popout)\n",
51 "_modal_body = widgets.ContainerWidget(parent=_popout)\n",
52 "_modal_body.flex1()\n",
52 "_modal_body.flex1()\n",
53 "_modal_body.set_css('overflow-y', 'scroll')\n",
53 "_modal_body.set_css('overflow-y', 'scroll')\n",
54 "_modal_body_label = widgets.StringWidget(parent=_modal_body, default_view_name=\"LabelView\")\n",
54 "_modal_body_label = widgets.StringWidget(parent=_modal_body, default_view_name=\"HTMLView\")\n",
55 "_modal_body_label.value = 'Not hooked'\n",
55 "_modal_body_label.value = 'Not hooked'\n",
56 "\n",
56 "\n",
57 "_modal_footer = widgets.ContainerWidget(parent=_popout)\n",
57 "_modal_footer = widgets.ContainerWidget(parent=_popout)\n",
58 "_var_filter = widgets.SelectionWidget(values=['Public', 'Private', 'IPython'], parent=_modal_footer, value='Public', default_view_name='ToggleButtonsView')\n",
58 "_var_filter = widgets.SelectionWidget(values=['Public', 'Private', 'IPython'], parent=_modal_footer, value='Public', default_view_name='ToggleButtonsView')\n",
59 "\n",
59 "\n",
60 "display(_popout)\n",
60 "display(_popout)\n",
61 "\n",
61 "\n",
62 "_modal_footer.add_class('modal-footer')\n"
62 "_modal_footer.add_class('modal-footer')\n"
63 ],
63 ],
64 "language": "python",
64 "language": "python",
65 "metadata": {},
65 "metadata": {},
66 "outputs": [],
66 "outputs": [],
67 "prompt_number": 2
67 "prompt_number": 2
68 },
68 },
69 {
69 {
70 "cell_type": "heading",
70 "cell_type": "heading",
71 "level": 3,
71 "level": 3,
72 "metadata": {},
72 "metadata": {},
73 "source": [
73 "source": [
74 "Method that Fills the Inspector"
74 "Method that Fills the Inspector"
75 ]
75 ]
76 },
76 },
77 {
77 {
78 "cell_type": "code",
78 "cell_type": "code",
79 "collapsed": false,
79 "collapsed": false,
80 "input": [
80 "input": [
81 "_ipython_input = re.compile('_i[0-9]*')\n",
81 "_ipython_input = re.compile('_i[0-9]*')\n",
82 "\n",
82 "\n",
83 "def _fill_inspector():\n",
83 "def _fill_inspector():\n",
84 " \n",
84 " \n",
85 " # Apply filter to variable names.\n",
85 " # Apply filter to variable names.\n",
86 " names = []\n",
86 " names = []\n",
87 " for name in sorted(_ipython.user_ns):\n",
87 " for name in sorted(_ipython.user_ns):\n",
88 " \n",
88 " \n",
89 " match = _ipython_input.match(name)\n",
89 " match = _ipython_input.match(name)\n",
90 " is_ipython = (match is not None and match.group() == name) or \\\n",
90 " is_ipython = (match is not None and match.group() == name) or \\\n",
91 " name == '_dh' or \\\n",
91 " name == '_dh' or \\\n",
92 " name == '_ih' or \\\n",
92 " name == '_ih' or \\\n",
93 " name == '_ii' or \\\n",
93 " name == '_ii' or \\\n",
94 " name == '_iii' or \\\n",
94 " name == '_iii' or \\\n",
95 " name == '_oh' or \\\n",
95 " name == '_oh' or \\\n",
96 " name == '_sh' or \\\n",
96 " name == '_sh' or \\\n",
97 " name == 'get_ipython' or \\\n",
97 " name == 'get_ipython' or \\\n",
98 " name == 'In' or \\\n",
98 " name == 'In' or \\\n",
99 " name == 'Out' or \\\n",
99 " name == 'Out' or \\\n",
100 " name == 'exit' or \\\n",
100 " name == 'exit' or \\\n",
101 " name == 'help' or \\\n",
101 " name == 'help' or \\\n",
102 " name == 'quit' or \\\n",
102 " name == 'quit' or \\\n",
103 " name == '_' or \\\n",
103 " name == '_' or \\\n",
104 " name == '__' or \\\n",
104 " name == '__' or \\\n",
105 " name == '___'\n",
105 " name == '___'\n",
106 " \n",
106 " \n",
107 " is_private = name.startswith('_')\n",
107 " is_private = name.startswith('_')\n",
108 " is_public = not is_private\n",
108 " is_public = not is_private\n",
109 " \n",
109 " \n",
110 " var_filter = _var_filter.value\n",
110 " var_filter = _var_filter.value\n",
111 " if var_filter == 'IPython' and is_ipython:\n",
111 " if var_filter == 'IPython' and is_ipython:\n",
112 " names.append(name)\n",
112 " names.append(name)\n",
113 " elif var_filter == 'Private' and (is_private and not is_ipython):\n",
113 " elif var_filter == 'Private' and (is_private and not is_ipython):\n",
114 " names.append(name)\n",
114 " names.append(name)\n",
115 " elif var_filter == 'Public' and (is_public and not is_ipython):\n",
115 " elif var_filter == 'Public' and (is_public and not is_ipython):\n",
116 " names.append(name)\n",
116 " names.append(name)\n",
117 " \n",
117 " \n",
118 " # Render each name and it's value.\n",
118 " # Render each name and it's value.\n",
119 " variable_list_html = \"\"\"\n",
119 " variable_list_html = \"\"\"\n",
120 "<table class=\"table table-bordered table-striped\" style=\"width: 100%; overflow: hidden; table-layout:fixed;\">\n",
120 "<table class=\"table table-bordered table-striped\" style=\"width: 100%; overflow: hidden; table-layout:fixed;\">\n",
121 " <tr><th>Name</th><th>Type</th><th>Value</th>\"\"\"\n",
121 " <tr><th>Name</th><th>Type</th><th>Value</th>\"\"\"\n",
122 " for name in names:\n",
122 " for name in names:\n",
123 " var_value = _ipython.user_ns[name]\n",
123 " var_value = _ipython.user_ns[name]\n",
124 " var_type = type(var_value)\n",
124 " var_type = type(var_value)\n",
125 " var_small_value = str(var_value)[:100].replace(\"&\", \"&amp;\").replace(\"<\", \"&lt;\")\n",
125 " var_small_value = str(var_value)[:100].replace(\"&\", \"&amp;\").replace(\"<\", \"&lt;\")\n",
126 " \n",
126 " \n",
127 " if str(var_value) != var_small_value:\n",
127 " if str(var_value) != var_small_value:\n",
128 " var_small_value += '<br><div class=\"label label-info\">...</div>'\n",
128 " var_small_value += '<br><div class=\"label label-info\">...</div>'\n",
129 " \n",
129 " \n",
130 " row = \"\"\"\n",
130 " row = \"\"\"\n",
131 "<tr style='overflow: hidden;'>\n",
131 "<tr style='overflow: hidden;'>\n",
132 " <td style='width: 30%; overflow: hidden;'>{name}</td>\n",
132 " <td style='width: 30%; overflow: hidden;'>{name}</td>\n",
133 " <td style='width: 30%; overflow: hidden;'>{type}</td>\n",
133 " <td style='width: 30%; overflow: hidden;'>{type}</td>\n",
134 " <td style='width: 40%; overflow: hidden;'>{small_value}</td>\n",
134 " <td style='width: 40%; overflow: hidden;'>{small_value}</td>\n",
135 "</tr>\n",
135 "</tr>\n",
136 "\"\"\".format(name=name, type=var_type.__name__, small_value=var_small_value, value=str(var_value))\n",
136 "\"\"\".format(name=name, type=var_type.__name__, small_value=var_small_value, value=str(var_value))\n",
137 " variable_list_html += row + '\\n'\n",
137 " variable_list_html += row + '\\n'\n",
138 " variable_list_html += '</table>'\n",
138 " variable_list_html += '</table>'\n",
139 " _modal_body_label.value = variable_list_html\n",
139 " _modal_body_label.value = variable_list_html\n",
140 " \n",
140 " \n",
141 " "
141 " "
142 ],
142 ],
143 "language": "python",
143 "language": "python",
144 "metadata": {},
144 "metadata": {},
145 "outputs": [],
145 "outputs": [],
146 "prompt_number": 3
146 "prompt_number": 3
147 },
147 },
148 {
148 {
149 "cell_type": "heading",
149 "cell_type": "heading",
150 "level": 3,
150 "level": 3,
151 "metadata": {},
151 "metadata": {},
152 "source": [
152 "source": [
153 "Hook Cell Execute and Filter Change"
153 "Hook Cell Execute and Filter Change"
154 ]
154 ]
155 },
155 },
156 {
156 {
157 "cell_type": "code",
157 "cell_type": "code",
158 "collapsed": false,
158 "collapsed": false,
159 "input": [
159 "input": [
160 "_ipython = get_ipython()\n",
160 "_ipython = get_ipython()\n",
161 "\n",
161 "\n",
162 "try:\n",
162 "try:\n",
163 " del _ipython._post_execute[handle_cell_executed]\n",
163 " del _ipython._post_execute[handle_cell_executed]\n",
164 "except:\n",
164 "except:\n",
165 " pass\n",
165 " pass\n",
166 "\n",
166 "\n",
167 "def _handle_cell_executed():\n",
167 "def _handle_cell_executed():\n",
168 " _modal_header_execs_label.execs += 1\n",
168 " _modal_header_execs_label.execs += 1\n",
169 " _modal_header_execs_label.value = '%d cell executions captured' % _modal_header_execs_label.execs\n",
169 " _modal_header_execs_label.value = '%d cell executions captured' % _modal_header_execs_label.execs\n",
170 " _fill_inspector()\n",
170 " _fill_inspector()\n",
171 "_ipython.register_post_execute(_handle_cell_executed)\n",
171 "_ipython.register_post_execute(_handle_cell_executed)\n",
172 "\n",
172 "\n",
173 "def _handle_filter_changed():\n",
173 "def _handle_filter_changed():\n",
174 " _fill_inspector()\n",
174 " _fill_inspector()\n",
175 "_var_filter.on_trait_change(_handle_filter_changed, 'value')"
175 "_var_filter.on_trait_change(_handle_filter_changed, 'value')"
176 ],
176 ],
177 "language": "python",
177 "language": "python",
178 "metadata": {},
178 "metadata": {},
179 "outputs": [],
179 "outputs": [],
180 "prompt_number": 4
180 "prompt_number": 4
181 },
181 },
182 {
182 {
183 "cell_type": "heading",
183 "cell_type": "heading",
184 "level": 1,
184 "level": 1,
185 "metadata": {},
185 "metadata": {},
186 "source": [
186 "source": [
187 "Test"
187 "Test"
188 ]
188 ]
189 },
189 },
190 {
190 {
191 "cell_type": "code",
191 "cell_type": "code",
192 "collapsed": false,
192 "collapsed": false,
193 "input": [
193 "input": [
194 "a = 5"
194 "a = 5"
195 ],
195 ],
196 "language": "python",
196 "language": "python",
197 "metadata": {},
197 "metadata": {},
198 "outputs": [],
198 "outputs": [],
199 "prompt_number": 5
199 "prompt_number": 5
200 },
200 },
201 {
201 {
202 "cell_type": "code",
202 "cell_type": "code",
203 "collapsed": false,
203 "collapsed": false,
204 "input": [
204 "input": [
205 "b = 3.0"
205 "b = 3.0"
206 ],
206 ],
207 "language": "python",
207 "language": "python",
208 "metadata": {},
208 "metadata": {},
209 "outputs": [],
209 "outputs": [],
210 "prompt_number": 6
210 "prompt_number": 6
211 },
211 },
212 {
212 {
213 "cell_type": "code",
213 "cell_type": "code",
214 "collapsed": false,
214 "collapsed": false,
215 "input": [
215 "input": [
216 "c = a * b"
216 "c = a * b"
217 ],
217 ],
218 "language": "python",
218 "language": "python",
219 "metadata": {},
219 "metadata": {},
220 "outputs": [],
220 "outputs": [],
221 "prompt_number": 7
221 "prompt_number": 7
222 },
222 },
223 {
223 {
224 "cell_type": "code",
224 "cell_type": "code",
225 "collapsed": false,
225 "collapsed": false,
226 "input": [
226 "input": [
227 "d = \"String\""
227 "d = \"String\""
228 ],
228 ],
229 "language": "python",
229 "language": "python",
230 "metadata": {},
230 "metadata": {},
231 "outputs": [],
231 "outputs": [],
232 "prompt_number": 8
232 "prompt_number": 8
233 },
233 },
234 {
234 {
235 "cell_type": "code",
235 "cell_type": "code",
236 "collapsed": false,
236 "collapsed": false,
237 "input": [
237 "input": [
238 "del b"
238 "del b"
239 ],
239 ],
240 "language": "python",
240 "language": "python",
241 "metadata": {},
241 "metadata": {},
242 "outputs": [],
242 "outputs": [],
243 "prompt_number": 9
243 "prompt_number": 9
244 }
244 }
245 ],
245 ],
246 "metadata": {}
246 "metadata": {}
247 }
247 }
248 ]
248 ]
249 } No newline at end of file
249 }
@@ -1,279 +1,279 b''
1 {
1 {
2 "metadata": {
2 "metadata": {
3 "name": ""
3 "name": ""
4 },
4 },
5 "nbformat": 3,
5 "nbformat": 3,
6 "nbformat_minor": 0,
6 "nbformat_minor": 0,
7 "worksheets": [
7 "worksheets": [
8 {
8 {
9 "cells": [
9 "cells": [
10 {
10 {
11 "cell_type": "code",
11 "cell_type": "code",
12 "collapsed": false,
12 "collapsed": false,
13 "input": [
13 "input": [
14 "from IPython.html import widgets\n",
14 "from IPython.html import widgets\n",
15 "from IPython.display import display"
15 "from IPython.display import display"
16 ],
16 ],
17 "language": "python",
17 "language": "python",
18 "metadata": {},
18 "metadata": {},
19 "outputs": [],
19 "outputs": [],
20 "prompt_number": 1
20 "prompt_number": 1
21 },
21 },
22 {
22 {
23 "cell_type": "markdown",
23 "cell_type": "markdown",
24 "metadata": {},
24 "metadata": {},
25 "source": [
25 "source": [
26 "This notebook shows how widgets can be used to manipulate the properties of other widgets."
26 "This notebook shows how widgets can be used to manipulate the properties of other widgets."
27 ]
27 ]
28 },
28 },
29 {
29 {
30 "cell_type": "markdown",
30 "cell_type": "markdown",
31 "metadata": {},
31 "metadata": {},
32 "source": [
32 "source": [
33 "To list the properties of a widget and allow the user to modify them, a function that keeps widgets in sync with traits is required. This function will syncronize a traitlet of one widget with a traitlet of another widget. The method also supports one way syncronization of types that have string representations with string traits."
33 "To list the properties of a widget and allow the user to modify them, a function that keeps widgets in sync with traits is required. This function will syncronize a traitlet of one widget with a traitlet of another widget. The method also supports one way syncronization of types that have string representations with string traits."
34 ]
34 ]
35 },
35 },
36 {
36 {
37 "cell_type": "code",
37 "cell_type": "code",
38 "collapsed": false,
38 "collapsed": false,
39 "input": [
39 "input": [
40 "def sync_widgets_properties(widget_a, property_a, widget_b, property_b, str_rep=False):\n",
40 "def sync_widgets_properties(widget_a, property_a, widget_b, property_b, str_rep=False):\n",
41 " def set_property_a(name, old, new):\n",
41 " def set_property_a(name, old, new):\n",
42 " if old != new:\n",
42 " if old != new:\n",
43 " if str_rep:\n",
43 " if str_rep:\n",
44 " setattr(widget_a, property_a, str(new))\n",
44 " setattr(widget_a, property_a, str(new))\n",
45 " else:\n",
45 " else:\n",
46 " setattr(widget_a, property_a, new)\n",
46 " setattr(widget_a, property_a, new)\n",
47 " def set_property_b(name, old, new):\n",
47 " def set_property_b(name, old, new):\n",
48 " if old != new and not str_rep:\n",
48 " if old != new and not str_rep:\n",
49 " setattr(widget_b, property_b, new)\n",
49 " setattr(widget_b, property_b, new)\n",
50 " widget_a.on_trait_change(set_property_b, property_a)\n",
50 " widget_a.on_trait_change(set_property_b, property_a)\n",
51 " widget_b.on_trait_change(set_property_a, property_b)\n",
51 " widget_b.on_trait_change(set_property_a, property_b)\n",
52 " if str_rep:\n",
52 " if str_rep:\n",
53 " setattr(widget_a, property_a, str(getattr(widget_b, property_b)))\n",
53 " setattr(widget_a, property_a, str(getattr(widget_b, property_b)))\n",
54 " else:\n",
54 " else:\n",
55 " setattr(widget_a, property_a, getattr(widget_b, property_b))\n",
55 " setattr(widget_a, property_a, getattr(widget_b, property_b))\n",
56 " \n",
56 " \n",
57 " return widget_a"
57 " return widget_a"
58 ],
58 ],
59 "language": "python",
59 "language": "python",
60 "metadata": {},
60 "metadata": {},
61 "outputs": [],
61 "outputs": [],
62 "prompt_number": 2
62 "prompt_number": 2
63 },
63 },
64 {
64 {
65 "cell_type": "markdown",
65 "cell_type": "markdown",
66 "metadata": {},
66 "metadata": {},
67 "source": [
67 "source": [
68 "This function will create a best match widget to represent a traitlet of another widget. The function will then bind the two widgets using the `sync_widget_properties` method above."
68 "This function will create a best match widget to represent a traitlet of another widget. The function will then bind the two widgets using the `sync_widget_properties` method above."
69 ]
69 ]
70 },
70 },
71 {
71 {
72 "cell_type": "code",
72 "cell_type": "code",
73 "collapsed": false,
73 "collapsed": false,
74 "input": [
74 "input": [
75 "def create_hooked_widget(control, key):\n",
75 "def create_hooked_widget(control, key):\n",
76 " property_type = type(getattr(control, key))\n",
76 " property_type = type(getattr(control, key))\n",
77 " \n",
77 " \n",
78 " if key == \"orientation\":\n",
78 " if key == \"orientation\":\n",
79 " return sync_widgets_properties(widgets.SelectionWidget(values=['vertical', 'horizontal'], default_view_name='ToggleButtonsView'), 'value', control, key)\n",
79 " return sync_widgets_properties(widgets.SelectionWidget(values=['vertical', 'horizontal'], default_view_name='ToggleButtonsView'), 'value', control, key)\n",
80 " elif property_type is int:\n",
80 " elif property_type is int:\n",
81 " return sync_widgets_properties(widgets.IntWidget(), 'value', control, key)\n",
81 " return sync_widgets_properties(widgets.IntWidget(), 'value', control, key)\n",
82 " elif property_type is float:\n",
82 " elif property_type is float:\n",
83 " return sync_widgets_properties(widgets.FloatWidget(), 'value', control, key)\n",
83 " return sync_widgets_properties(widgets.FloatWidget(), 'value', control, key)\n",
84 " elif property_type is bool:\n",
84 " elif property_type is bool:\n",
85 " return sync_widgets_properties(widgets.BoolWidget(), 'value', control, key)\n",
85 " return sync_widgets_properties(widgets.BoolWidget(), 'value', control, key)\n",
86 " elif property_type is str or property_type is unicode:\n",
86 " elif property_type is str or property_type is unicode:\n",
87 " return sync_widgets_properties(widgets.StringWidget(), 'value', control, key)\n",
87 " return sync_widgets_properties(widgets.StringWidget(), 'value', control, key)\n",
88 " else:\n",
88 " else:\n",
89 " return sync_widgets_properties(widgets.StringWidget(disabled=True), 'value', control, key, str_rep=True)\n",
89 " return sync_widgets_properties(widgets.StringWidget(disabled=True), 'value', control, key, str_rep=True)\n",
90 " "
90 " "
91 ],
91 ],
92 "language": "python",
92 "language": "python",
93 "metadata": {},
93 "metadata": {},
94 "outputs": [],
94 "outputs": [],
95 "prompt_number": 3
95 "prompt_number": 3
96 },
96 },
97 {
97 {
98 "cell_type": "markdown",
98 "cell_type": "markdown",
99 "metadata": {},
99 "metadata": {},
100 "source": [
100 "source": [
101 "This function creates a modal that allows the user to read the doc string associated with a callable. The user can then invoke the callbable from the same modal."
101 "This function creates a modal that allows the user to read the doc string associated with a callable. The user can then invoke the callbable from the same modal."
102 ]
102 ]
103 },
103 },
104 {
104 {
105 "cell_type": "code",
105 "cell_type": "code",
106 "collapsed": false,
106 "collapsed": false,
107 "input": [
107 "input": [
108 "modals = {}\n",
108 "modals = {}\n",
109 "def get_method_modal(control, method_name, parent=None):\n",
109 "def get_method_modal(control, method_name, parent=None):\n",
110 " if not method_name in dir(control):\n",
110 " if not method_name in dir(control):\n",
111 " return None\n",
111 " return None\n",
112 " if not control in modals:\n",
112 " if not control in modals:\n",
113 " modals[control] = {}\n",
113 " modals[control] = {}\n",
114 " if not method_name in modals[control]:\n",
114 " if not method_name in modals[control]:\n",
115 " new_modal = widgets.ContainerWidget(default_view_name=\"ModalView\")\n",
115 " new_modal = widgets.ContainerWidget(default_view_name=\"ModalView\")\n",
116 " new_modal.description=\"Invoke \" + method_name\n",
116 " new_modal.description=\"Invoke \" + method_name\n",
117 " new_modal.button_text = method_name + \"(...)\"\n",
117 " new_modal.button_text = method_name + \"(...)\"\n",
118 " \n",
118 " \n",
119 " doc_str = 'No doc string'\n",
119 " doc_str = 'No doc string'\n",
120 " try:\n",
120 " try:\n",
121 " doc_str = '<pre>' + getattr(control, method_name).__doc__ + '</pre>'\n",
121 " doc_str = '<pre>' + getattr(control, method_name).__doc__ + '</pre>'\n",
122 " except:\n",
122 " except:\n",
123 " pass\n",
123 " pass\n",
124 " \n",
124 " \n",
125 " doc_label = widgets.StringWidget(parent=new_modal,default_view_name='LabelView', value=doc_str)\n",
125 " doc_label = widgets.StringWidget(parent=new_modal,default_view_name='HTMLView', value=doc_str)\n",
126 " doc_label.set_css('color', 'blue')\n",
126 " doc_label.set_css('color', 'blue')\n",
127 " exec_box = widgets.ContainerWidget(parent=new_modal)\n",
127 " exec_box = widgets.ContainerWidget(parent=new_modal)\n",
128 " exec_box.hbox()\n",
128 " exec_box.hbox()\n",
129 " exec_box.pack_center()\n",
129 " exec_box.pack_center()\n",
130 " exec_box.align_center()\n",
130 " exec_box.align_center()\n",
131 " open_label = widgets.StringWidget(parent=exec_box,default_view_name='LabelView', value=method_name+'(&nbsp;&nbsp;')\n",
131 " open_label = widgets.StringWidget(parent=exec_box,default_view_name='HTMLView', value=method_name+'(&nbsp;&nbsp;')\n",
132 " exec_str = widgets.StringWidget(parent=exec_box)\n",
132 " exec_str = widgets.StringWidget(parent=exec_box)\n",
133 " close_label = widgets.StringWidget(parent=exec_box,default_view_name='LabelView', value='&nbsp;&nbsp;)')\n",
133 " close_label = widgets.StringWidget(parent=exec_box,default_view_name='HTMLView', value='&nbsp;&nbsp;)')\n",
134 " button_row = widgets.ContainerWidget(parent=new_modal)\n",
134 " button_row = widgets.ContainerWidget(parent=new_modal)\n",
135 " button_row.hbox()\n",
135 " button_row.hbox()\n",
136 " button_row.pack_end()\n",
136 " button_row.pack_end()\n",
137 " button_box = widgets.ContainerWidget(parent=button_row)\n",
137 " button_box = widgets.ContainerWidget(parent=button_row)\n",
138 " button_box.flex0()\n",
138 " button_box.flex0()\n",
139 " exec_button = widgets.ButtonWidget(parent=button_box, description=\"Execute\")\n",
139 " exec_button = widgets.ButtonWidget(parent=button_box, description=\"Execute\")\n",
140 " \n",
140 " \n",
141 " def handle_method_exec():\n",
141 " def handle_method_exec():\n",
142 " my_control = control\n",
142 " my_control = control\n",
143 " exec \"my_control.\" + method_name.replace('\\n', '') + \"(\" + exec_str.value + \")\" in globals(), locals()\n",
143 " exec \"my_control.\" + method_name.replace('\\n', '') + \"(\" + exec_str.value + \")\" in globals(), locals()\n",
144 " exec_button.on_click(handle_method_exec)\n",
144 " exec_button.on_click(handle_method_exec)\n",
145 " exec_str.on_submit(handle_method_exec)\n",
145 " exec_str.on_submit(handle_method_exec)\n",
146 " \n",
146 " \n",
147 " if parent is not None:\n",
147 " if parent is not None:\n",
148 " new_modal.parent = parent\n",
148 " new_modal.parent = parent\n",
149 " \n",
149 " \n",
150 " modals[control][method_name] = new_modal\n",
150 " modals[control][method_name] = new_modal\n",
151 " display(new_modal)\n",
151 " display(new_modal)\n",
152 " return modals[control][method_name]"
152 " return modals[control][method_name]"
153 ],
153 ],
154 "language": "python",
154 "language": "python",
155 "metadata": {},
155 "metadata": {},
156 "outputs": [],
156 "outputs": [],
157 "prompt_number": 4
157 "prompt_number": 4
158 },
158 },
159 {
159 {
160 "cell_type": "markdown",
160 "cell_type": "markdown",
161 "metadata": {},
161 "metadata": {},
162 "source": [
162 "source": [
163 "This function renders the control panel."
163 "This function renders the control panel."
164 ]
164 ]
165 },
165 },
166 {
166 {
167 "cell_type": "code",
167 "cell_type": "code",
168 "collapsed": false,
168 "collapsed": false,
169 "input": [
169 "input": [
170 "def hook_control(control, parent=None):\n",
170 "def hook_control(control, parent=None):\n",
171 " explorer = widgets.ContainerWidget()\n",
171 " explorer = widgets.ContainerWidget()\n",
172 " if parent is not None:\n",
172 " if parent is not None:\n",
173 " explorer.parent = parent\n",
173 " explorer.parent = parent\n",
174 " explorer.hbox()\n",
174 " explorer.hbox()\n",
175 " \n",
175 " \n",
176 " viewer = widgets.ContainerWidget(parent=explorer)\n",
176 " viewer = widgets.ContainerWidget(parent=explorer)\n",
177 " viewer.set_css({\n",
177 " viewer.set_css({\n",
178 " 'background': 'white',\n",
178 " 'background': 'white',\n",
179 " 'border': '1px solid #000',\n",
179 " 'border': '1px solid #000',\n",
180 " 'overflow': 'hidden',\n",
180 " 'overflow': 'hidden',\n",
181 " })\n",
181 " })\n",
182 " viewer.flex2()\n",
182 " viewer.flex2()\n",
183 " \n",
183 " \n",
184 " control.parent = viewer\n",
184 " control.parent = viewer\n",
185 " \n",
185 " \n",
186 " side = widgets.ContainerWidget(parent=explorer)\n",
186 " side = widgets.ContainerWidget(parent=explorer)\n",
187 " side.flex1()\n",
187 " side.flex1()\n",
188 " \n",
188 " \n",
189 " side_tab = widgets.MulticontainerWidget(parent=side)\n",
189 " side_tab = widgets.MulticontainerWidget(parent=side)\n",
190 " side_tab.set_css('margin', '5px')\n",
190 " side_tab.set_css('margin', '5px')\n",
191 " \n",
191 " \n",
192 " properties = widgets.ContainerWidget(parent=side_tab)\n",
192 " properties = widgets.ContainerWidget(parent=side_tab)\n",
193 " methods = widgets.ContainerWidget(parent=side_tab)\n",
193 " methods = widgets.ContainerWidget(parent=side_tab)\n",
194 " side_tab.set_title(0, 'Properties')\n",
194 " side_tab.set_title(0, 'Properties')\n",
195 " side_tab.set_title(1, 'Methods')\n",
195 " side_tab.set_title(1, 'Methods')\n",
196 " \n",
196 " \n",
197 " for key in sorted(control.keys):\n",
197 " for key in sorted(control.keys):\n",
198 " property_control = create_hooked_widget(control, key)\n",
198 " property_control = create_hooked_widget(control, key)\n",
199 " property_control.parent = properties\n",
199 " property_control.parent = properties\n",
200 " property_control.description = key + ':'\n",
200 " property_control.description = key + ':'\n",
201 " \n",
201 " \n",
202 " methods.vbox()\n",
202 " methods.vbox()\n",
203 " methods.set_css('overflow', 'hidden')\n",
203 " methods.set_css('overflow', 'hidden')\n",
204 " \n",
204 " \n",
205 " methods_container = widgets.ContainerWidget(parent=methods)\n",
205 " methods_container = widgets.ContainerWidget(parent=methods)\n",
206 " methods_container.flex1()\n",
206 " methods_container.flex1()\n",
207 " methods_buttons = widgets.ContainerWidget(parent=methods)\n",
207 " methods_buttons = widgets.ContainerWidget(parent=methods)\n",
208 " methods_buttons.flex0()\n",
208 " methods_buttons.flex0()\n",
209 " methods_buttons.hbox()\n",
209 " methods_buttons.hbox()\n",
210 " methods_buttons.pack_end()\n",
210 " methods_buttons.pack_end()\n",
211 " methods_buttons.set_css({\n",
211 " methods_buttons.set_css({\n",
212 " 'padding-top': '5px',\n",
212 " 'padding-top': '5px',\n",
213 " 'padding-right': '50px',\n",
213 " 'padding-right': '50px',\n",
214 " })\n",
214 " })\n",
215 " \n",
215 " \n",
216 " execute_button = widgets.ButtonWidget(parent=methods_buttons, description=\"Invoke\")\n",
216 " execute_button = widgets.ButtonWidget(parent=methods_buttons, description=\"Invoke\")\n",
217 " \n",
217 " \n",
218 " method_list = widgets.SelectionWidget(parent=methods_container, default_view_name=\"ListBoxView\")\n",
218 " method_list = widgets.SelectionWidget(parent=methods_container, default_view_name=\"ListBoxView\")\n",
219 " method_list.description = \"Names:\"\n",
219 " method_list.description = \"Names:\"\n",
220 " method_list.set_css('height', '400px')\n",
220 " method_list.set_css('height', '400px')\n",
221 " method_list.values = [attr_name for attr_name in dir(control) if callable(getattr(control, attr_name)) and not attr_name.startswith('_')]\n",
221 " method_list.values = [attr_name for attr_name in dir(control) if callable(getattr(control, attr_name)) and not attr_name.startswith('_')]\n",
222 " \n",
222 " \n",
223 " def handle_execute_method():\n",
223 " def handle_execute_method():\n",
224 " get_method_modal(control, method_list.value, parent=parent)\n",
224 " get_method_modal(control, method_list.value, parent=parent)\n",
225 " execute_button.on_click(handle_execute_method)\n",
225 " execute_button.on_click(handle_execute_method)\n",
226 " \n",
226 " \n",
227 " display(explorer) \n",
227 " display(explorer) \n",
228 " explorer.add_class('well')\n",
228 " explorer.add_class('well')\n",
229 " return explorer"
229 " return explorer"
230 ],
230 ],
231 "language": "python",
231 "language": "python",
232 "metadata": {},
232 "metadata": {},
233 "outputs": [],
233 "outputs": [],
234 "prompt_number": 5
234 "prompt_number": 5
235 },
235 },
236 {
236 {
237 "cell_type": "markdown",
237 "cell_type": "markdown",
238 "metadata": {},
238 "metadata": {},
239 "source": [
239 "source": [
240 "This final bit of code allows the user to select what control and view he/she wants to manipulate."
240 "This final bit of code allows the user to select what control and view he/she wants to manipulate."
241 ]
241 ]
242 },
242 },
243 {
243 {
244 "cell_type": "code",
244 "cell_type": "code",
245 "collapsed": false,
245 "collapsed": false,
246 "input": [
246 "input": [
247 "control_tester = widgets.ContainerWidget()\n",
247 "control_tester = widgets.ContainerWidget()\n",
248 "widget_names = [widget_name for widget_name in dir(widgets) if widget_name.endswith('Widget') and widget_name != \"Widget\"]\n",
248 "widget_names = [widget_name for widget_name in dir(widgets) if widget_name.endswith('Widget') and widget_name != \"Widget\"]\n",
249 "widget_selector = widgets.SelectionWidget(parent=control_tester, description=\"Widget type:\", values=widget_names)\n",
249 "widget_selector = widgets.SelectionWidget(parent=control_tester, description=\"Widget type:\", values=widget_names)\n",
250 "view_name = widgets.StringWidget(parent=control_tester, description=\"View name (optional):\")\n",
250 "view_name = widgets.StringWidget(parent=control_tester, description=\"View name (optional):\")\n",
251 "display_button_container = widgets.ContainerWidget(parent=control_tester)\n",
251 "display_button_container = widgets.ContainerWidget(parent=control_tester)\n",
252 "display_button_container.hbox()\n",
252 "display_button_container.hbox()\n",
253 "display_button_container.pack_end()\n",
253 "display_button_container.pack_end()\n",
254 "display_button_container.set_css(\"padding\", \"5px\")\n",
254 "display_button_container.set_css(\"padding\", \"5px\")\n",
255 "display_button = widgets.ButtonWidget(parent=display_button_container, description=\"Display\")\n",
255 "display_button = widgets.ButtonWidget(parent=display_button_container, description=\"Display\")\n",
256 "display(control_tester)\n",
256 "display(control_tester)\n",
257 "\n",
257 "\n",
258 "last_displayed = [None]\n",
258 "last_displayed = [None]\n",
259 "def handle_display():\n",
259 "def handle_display():\n",
260 " if last_displayed[0] is not None:\n",
260 " if last_displayed[0] is not None:\n",
261 " last_displayed[0].close()\n",
261 " last_displayed[0].close()\n",
262 " widget_type = getattr(widgets, widget_selector.value)\n",
262 " widget_type = getattr(widgets, widget_selector.value)\n",
263 " widget = widget_type()\n",
263 " widget = widget_type()\n",
264 " if len(view_name.value) > 0:\n",
264 " if len(view_name.value) > 0:\n",
265 " widget.default_view_name = view_name.value\n",
265 " widget.default_view_name = view_name.value\n",
266 " last_displayed[0] = hook_control(widget)\n",
266 " last_displayed[0] = hook_control(widget)\n",
267 "display_button.on_click(handle_display)\n",
267 "display_button.on_click(handle_display)\n",
268 "view_name.on_submit(handle_display)\n"
268 "view_name.on_submit(handle_display)\n"
269 ],
269 ],
270 "language": "python",
270 "language": "python",
271 "metadata": {},
271 "metadata": {},
272 "outputs": [],
272 "outputs": [],
273 "prompt_number": 6
273 "prompt_number": 6
274 }
274 }
275 ],
275 ],
276 "metadata": {}
276 "metadata": {}
277 }
277 }
278 ]
278 ]
279 } No newline at end of file
279 }
General Comments 0
You need to be logged in to leave comments. Login now