Merge pull request #5897 from ellisonbg/notebook-docs

Major rewrite of notebook based documentation/examples
This commit is contained in:
Jonathan Frederic 2014-08-22 12:50:33 -07:00
commit 5611adfafa
37 changed files with 11072 additions and 1577 deletions

View File

@ -0,0 +1,796 @@
{
"metadata": {
"celltoolbar": "Slideshow",
"name": "",
"signature": "sha256:32ada55b57f8674a38435bae581b0f53caefd829dca5c5a7931ab3d04a7d86bb"
},
"nbformat": 3,
"nbformat_minor": 0,
"worksheets": [
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"[Index](Index.ipynb) - [Back](Widget Styling.ipynb)"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"from __future__ import print_function # For py 2.7 compat"
],
"language": "python",
"metadata": {},
"outputs": []
},
{
"cell_type": "heading",
"level": 1,
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"Building a Custom Widget"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The widget framework is built **on top of the Comm framework** (short for communication). The Comm framework is a framework that **allows you send/receive JSON messages** to/from the front-end (as seen below).\n",
"\n",
"![Widget layer](images/WidgetArch.png)\n",
"\n",
"To create a custom widget, you need to **define the widget both in the back-end and in the front-end**. "
]
},
{
"cell_type": "heading",
"level": 1,
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"Building a Custom Widget"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"To get started, you'll create a **simple hello world widget**. Later you'll build on this foundation to make more complex widgets."
]
},
{
"cell_type": "heading",
"level": 2,
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"Back-end (Python)"
]
},
{
"cell_type": "heading",
"level": 3,
"metadata": {},
"source": [
"DOMWidget and Widget"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"To define a widget, you must inherit from the **Widget or DOMWidget** base class. If you intend for your widget to be **displayed in the IPython notebook**, you'll need to **inherit from the DOMWidget**. The DOMWidget class itself inherits from the Widget class. The Widget class is useful for cases in which the **Widget is not meant to be displayed directly in the notebook**, but **instead as a child of another rendering environment**. For example, if you wanted to create a three.js widget (a popular WebGL library), you would implement the rendering window as a DOMWidget and any 3D objects or lights meant to be rendered in that window as Widgets."
]
},
{
"cell_type": "heading",
"level": 3,
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"_view_name"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Inheriting from the DOMWidget does not tell the widget framework what front-end widget to associate with your back-end widget. Instead, you must tell it yourself by defining a **specially named Traitlet, `_view_name`** (as seen below)."
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"from IPython.html import widgets\n",
"from IPython.utils.traitlets import Unicode\n",
"\n",
"class HelloWidget(widgets.DOMWidget):\n",
" _view_name = Unicode('HelloView', sync=True)"
],
"language": "python",
"metadata": {},
"outputs": []
},
{
"cell_type": "heading",
"level": 3,
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"sync=True traitlets"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Traitlets is** an IPython library for defining **type-safe properties** on configurable objects. For this tutorial you do not need to worry about the *configurable* piece of the traitlets machinery. The **`sync=True` keyword argument** tells the widget framework to **handle synchronizing that value to the front-end**. Without `sync=True`, the front-end would have no knowledge of `_view_name`."
]
},
{
"cell_type": "heading",
"level": 3,
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"Other traitlet types"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Unicode, used for _view_name, is not the only Traitlet type, there are many more some of which are listed below: \n",
"\n",
"- Any\n",
"- Bool\n",
"- Bytes\n",
"- CBool\n",
"- CBytes\n",
"- CComplex\n",
"- CFloat\n",
"- CInt\n",
"- CLong\n",
"- CRegExp\n",
"- CUnicode\n",
"- CaselessStrEnum\n",
"- Complex\n",
"- Dict\n",
"- DottedObjectName\n",
"- Enum\n",
"- Float\n",
"- FunctionType\n",
"- Instance\n",
"- InstanceType\n",
"- Int\n",
"- List\n",
"- Long\n",
"- Set\n",
"- TCPAddress\n",
"- Tuple\n",
"- Type\n",
"- Unicode\n",
"\n",
"**Not all of these traitlets can be synchronized** across the network, **only the JSON-able** traits and **Widget instances** will be synchronized."
]
},
{
"cell_type": "heading",
"level": 2,
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"Front-end (JavaScript)"
]
},
{
"cell_type": "heading",
"level": 3,
"metadata": {},
"source": [
"Models and views"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The IPython widget framework front-end relies heavily on [Backbone.js](http://backbonejs.org/). **Backbone.js is an MVC (model view controller) framework**. Widgets defined in the back-end are automatically **synchronized with generic Backbone.js models** in the front-end. The traitlets are added to the front-end instance **automatically on first state push**. The **`_view_name` trait** that you defined earlier is used by the widget framework to create the corresponding Backbone.js view and **link that view to the model**."
]
},
{
"cell_type": "heading",
"level": 3,
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"Import the WidgetManager"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"You first need to **import the WidgetManager**. You will use it later to register your view by name (the same name you used in the back-end). To import the widget manager, use the `require` method of [require.js](http://requirejs.org/) (as seen below)."
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"%%javascript\n",
"\n",
"require([\"widgets/js/widget\"], function(WidgetManager){\n",
" \n",
"});"
],
"language": "python",
"metadata": {},
"outputs": []
},
{
"cell_type": "heading",
"level": 3,
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"Define the view"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Next define your widget view class. **Inherit from the `DOMWidgetView`** by using the `.extend` method. Register the view class with the widget manager by calling **`.register_widget_view`**. The **first parameter is the widget view name** (`_view_name` that you defined earlier in Python) and the **second is a handle to the class type**."
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"%%javascript\n",
"\n",
"require([\"widgets/js/widget\"], function(WidgetManager){\n",
" \n",
" // Define the HelloView\n",
" var HelloView = IPython.DOMWidgetView.extend({\n",
" \n",
" });\n",
" \n",
" // Register the HelloView with the widget manager.\n",
" WidgetManager.register_widget_view('HelloView', HelloView);\n",
"});"
],
"language": "python",
"metadata": {},
"outputs": []
},
{
"cell_type": "heading",
"level": 3,
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"Render method"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Lastly, **override the base `render` method** of the view to define custom rendering logic. A handle to the widget's default div element can be acquired via **`this.$el`**. The `$el` property is a **[jQuery](http://jquery.com/) object handle** (which can be thought of as a supercharged version of the normal DOM element's handle)."
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"%%javascript\n",
"\n",
"require([\"widgets/js/widget\"], function(WidgetManager){ \n",
" \n",
" var HelloView = IPython.DOMWidgetView.extend({\n",
" \n",
" // Render the view.\n",
" render: function(){ \n",
" this.$el.text('Hello World!'); \n",
" },\n",
" });\n",
" \n",
" WidgetManager.register_widget_view('HelloView', HelloView);\n",
"});"
],
"language": "python",
"metadata": {},
"outputs": []
},
{
"cell_type": "heading",
"level": 2,
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"Test"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"You should be able to display your widget just like any other widget now."
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"HelloWidget()"
],
"language": "python",
"metadata": {},
"outputs": []
},
{
"cell_type": "heading",
"level": 2,
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"Making the widget stateful"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"There is not much that you can do with the above example that you can't do with the IPython display framework. To change this, you will make the widget stateful. Instead of displaying a static \"hello world\" message, it will **display a string set by the back-end**. First you need to **add a traitlet in the back-end**. Use the name of **`value` to stay consistent** with the rest of the widget framework and to **allow your widget to be used with interact**."
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"class HelloWidget(widgets.DOMWidget):\n",
" _view_name = Unicode('HelloView', sync=True)\n",
" value = Unicode('Hello World!', sync=True)"
],
"language": "python",
"metadata": {},
"outputs": []
},
{
"cell_type": "heading",
"level": 3,
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"Accessing the model from the view"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"To access the model associate with a view instance, use the **`model` property** of the view. **`get` and `set`** methods are used to interact with the Backbone model. **`get` is trivial**, however you have to **be careful when using `set`**. **After calling the model `set`** you need call the **view's `touch` method**. This associates the `set` operation with a particular view so **output will be routed to the correct cell**. The model also has a **`on` method** which allows you to listen to events triggered by the model (like value changes)."
]
},
{
"cell_type": "heading",
"level": 3,
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"Rendering model contents"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"By **replacing the string literal with a call to `model.get`**, the view will now display the **value of the back-end upon display**. However, it will not update itself to a new value when the value changes."
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"%%javascript\n",
"\n",
"require([\"widgets/js/widget\"], function(WidgetManager){ \n",
" \n",
" var HelloView = IPython.DOMWidgetView.extend({\n",
" \n",
" render: function(){ \n",
" this.$el.text(this.model.get('value')); \n",
" },\n",
" });\n",
" \n",
" WidgetManager.register_widget_view('HelloView', HelloView);\n",
"});"
],
"language": "python",
"metadata": {},
"outputs": []
},
{
"cell_type": "heading",
"level": 3,
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"Dynamic updates"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"To get the view to **update itself dynamically**, register a function to update the view's value when the model's `value` property changes. This can be done using the **`model.on` method**. The `on` method takes three parameters, an event name, callback handle, and callback context. The Backbone **event named `change`** will fire whenever the model changes. By **appending `:value`** to it, you tell Backbone to only listen to the change event of the `value` property (as seen below)."
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"%%javascript\n",
"\n",
"require([\"widgets/js/widget\"], function(WidgetManager){ \n",
" \n",
" var HelloView = IPython.DOMWidgetView.extend({\n",
" \n",
" \n",
" render: function(){ \n",
" this.value_changed();\n",
" this.model.on('change:value', this.value_changed, this);\n",
" },\n",
" \n",
" value_changed: function() {\n",
" this.$el.text(this.model.get('value')); \n",
" },\n",
" });\n",
" \n",
" WidgetManager.register_widget_view('HelloView', HelloView);\n",
"});"
],
"language": "python",
"metadata": {},
"outputs": []
},
{
"cell_type": "heading",
"level": 2,
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"Test"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"w = HelloWidget()\n",
"w"
],
"language": "python",
"metadata": {},
"outputs": []
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"w.value = 'test'"
],
"language": "python",
"metadata": {},
"outputs": []
},
{
"cell_type": "heading",
"level": 1,
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"Finishing"
]
},
{
"cell_type": "heading",
"level": 2,
"metadata": {},
"source": [
"Bidirectional communication"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The examples above dump the value directly into the DOM. There is no way for you to interact with this dumped data in the front-end. To create an example that **accepts input**, you will have to do something more than blindly dumping the contents of value into the DOM. In this part of the tutorial, you will **use a jQuery spinner** to display and accept input in the front-end. IPython currently lacks a spinner implementation so this widget will be unique."
]
},
{
"cell_type": "heading",
"level": 3,
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"Update the Python code"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"You will need to change the type of the **value traitlet to `Int`**. It also makes sense to **change the name of the widget** to something more appropriate, like `SpinnerWidget`."
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"from IPython.utils.traitlets import CInt\n",
"class SpinnerWidget(widgets.DOMWidget):\n",
" _view_name = Unicode('SpinnerView', sync=True)\n",
" value = CInt(0, sync=True)"
],
"language": "python",
"metadata": {},
"outputs": []
},
{
"cell_type": "heading",
"level": 3,
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"Updating the Javascript code"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The [jQuery docs for the spinner control](https://jqueryui.com/spinner/) say to use **`.spinner` to create a spinner** in an element. Calling **`.spinner` on `$el` will create a spinner inside `$el`**. Make sure to **update the widget name here too** so it's the same as `_view_name` in the back-end."
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"%%javascript\n",
"\n",
"require([\"widgets/js/widget\"], function(WidgetManager){ \n",
" \n",
" var SpinnerView = IPython.DOMWidgetView.extend({\n",
" \n",
" render: function(){ \n",
" \n",
" // jQuery code to create a spinner and append it to $el\n",
" this.$input = $('<input />');\n",
" this.$el.append(this.$input);\n",
" this.$spinner = this.$input.spinner({\n",
" change: function( event, ui ) {}\n",
" });\n",
" \n",
" this.value_changed();\n",
" this.model.on('change:value', this.value_changed, this);\n",
" },\n",
" \n",
" value_changed: function() {\n",
" \n",
" },\n",
" });\n",
" \n",
" WidgetManager.register_widget_view('SpinnerView', SpinnerView);\n",
"});"
],
"language": "python",
"metadata": {},
"outputs": []
},
{
"cell_type": "heading",
"level": 3,
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"Getting and setting the value"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"To **set the value of the spinner on update from the back-end**, you need to use **jQuery's `spinner` API**. `spinner.spinner('value', new)` will set the value of the spinner. Add that code to the **`value_changed` method** to make the spinner **update with the value stored in the back-end((. Using jQuery's spinner API, you can add a function to handle the **spinner `change` event** by passing it in when constructing the spinner. Inside the `change` event, call **`model.set`** to set the value and then **`touch`** to inform the framework that this view was the view that caused the change to the model. **Note: The `var that = this;` is a JavaScript trick to pass the current context into closures.**"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"%%javascript\n",
"\n",
"require([\"widgets/js/widget\"], function(WidgetManager){ \n",
" \n",
" var SpinnerView = IPython.DOMWidgetView.extend({\n",
" \n",
" render: function(){ \n",
"\n",
" var that = this;\n",
" this.$input = $('<input />');\n",
" this.$el.append(this.$input);\n",
" this.$spinner = this.$input.spinner({\n",
" change: function( event, ui ) {\n",
" that.handle_spin();\n",
" },\n",
" spin: function( event, ui ) {\n",
" that.handle_spin();\n",
" }\n",
" });\n",
" \n",
" this.value_changed();\n",
" this.model.on('change:value', this.value_changed, this);\n",
" },\n",
" \n",
" value_changed: function() {\n",
" this.$spinner.spinner('value', this.model.get('value'));\n",
" },\n",
" \n",
" handle_spin: function() {\n",
" this.model.set('value', this.$spinner.spinner('value'));\n",
" this.touch();\n",
" },\n",
" });\n",
" \n",
" WidgetManager.register_widget_view('SpinnerView', SpinnerView);\n",
"});"
],
"language": "python",
"metadata": {},
"outputs": []
},
{
"cell_type": "heading",
"level": 2,
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"Test"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"w = SpinnerWidget(value=5)\n",
"w"
],
"language": "python",
"metadata": {},
"outputs": []
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"w.value"
],
"language": "python",
"metadata": {},
"outputs": []
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"w.value = 20"
],
"language": "python",
"metadata": {},
"outputs": []
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Trying to **use the spinner with another widget**."
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"from IPython.display import display\n",
"w1 = SpinnerWidget(value=0)\n",
"w2 = widgets.IntSliderWidget()\n",
"display(w1,w2)\n",
"\n",
"from IPython.utils.traitlets import link\n",
"mylink = link((w1, 'value'), (w2, 'value'))"
],
"language": "python",
"metadata": {},
"outputs": []
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"[Index](Index.ipynb) - [Back](Widget Styling.ipynb)"
]
}
],
"metadata": {}
}
]
}

View File

@ -1,7 +1,7 @@
{
"metadata": {
"name": "",
"signature": "sha256:3f30c6e839ac39f890da34a2af6bf50bf0d99ea32f7aadc043f3e31f619e4bc9"
"signature": "sha256:6d8c7c51322c4911e478068e8fa8e897bd72c614096f5df110ed86d01d66001c"
},
"nbformat": 3,
"nbformat_minor": 0,
@ -13,14 +13,14 @@
"level": 1,
"metadata": {},
"source": [
"Interact"
"Using Interact"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The `interact` function provides a high-level interface for creating user interface controls to use in exploring code and data interactively."
"The `interact` function (`IPython.html.widgets.interact`) automatically creates user interface (UI) controls for exploring code and data interactively. It is the easiest way to get started using IPython's widgets."
]
},
{
@ -28,66 +28,70 @@
"collapsed": false,
"input": [
"from IPython.html.widgets import interact, interactive, fixed\n",
"from IPython.html import widgets\n",
"from IPython.display import clear_output, display, HTML"
"from IPython.html import widgets"
],
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 1
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"<div class=\"alert alert-success\">\n",
"As of IPython 2.0, the widgets in this notebook won't show up on http://nbviewer.ipython.org. To view the widgets and interact with them, you will need to download this notebook and run it with an IPython Notebook server.\n",
"</div>"
]
},
{
"cell_type": "heading",
"level": 2,
"metadata": {},
"source": [
"Basic interact"
"Basic `interact`"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Here is a simple function that displays its arguments as an HTML table:"
"At the most basic level, `interact` autogenerates UI controls for function arguments, and then calls the function with those arguments when you manipulate the controls interactively. To use `interact`, you need to define a function that you want to explore. Here is a function that prints its only argument `x`."
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"def show_args(**kwargs):\n",
" s = '<h3>Arguments:</h3><table>\\n'\n",
" for k,v in kwargs.items():\n",
" s += '<tr><td>{0}</td><td>{1}</td></tr>\\n'.format(k,v)\n",
" s += '</table>'\n",
" display(HTML(s))"
"def f(x):\n",
" print x"
],
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 2
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"When you pass this function as the first argument to `interact` along with an integer keyword argument (`x=10`), a slider is generated and bound to the function."
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"show_args(a=10, b='Hi There', c=True)"
"interact(f, x=10);"
],
"language": "python",
"metadata": {},
"outputs": [
{
"html": [
"<h3>Arguments:</h3><table>\n",
"<tr><td>a</td><td>10</td></tr>\n",
"<tr><td>c</td><td>True</td></tr>\n",
"<tr><td>b</td><td>Hi There</td></tr>\n",
"</table>"
],
"metadata": {},
"output_type": "display_data",
"output_type": "stream",
"stream": "stdout",
"text": [
"<IPython.core.display.HTML object>"
"9\n"
]
}
],
@ -97,71 +101,667 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"Let's use this function to explore how `interact` works."
"When you move the slider, the function is called and the current value of `x` is printed.\n",
"\n",
"If you pass `True` or `False`, `interact` will generate a checkbox:"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"i = interact(show_args,\n",
" Temp=(0,10),\n",
" Current=(0.,10.,0.01),\n",
" z=True,\n",
" Text=u'Type here!',\n",
" #Algorithm=['This','That','Other'],\n",
" a=widgets.FloatSliderWidget(min=-10.0, max=10.0, step=0.1, value=5.0, description=\"Float (a)\")\n",
" )"
"interact(f, x=True);"
],
"language": "python",
"metadata": {},
"outputs": [
{
"html": [
"<h3>Arguments:</h3><table>\n",
"<tr><td>Current</td><td>4.99</td></tr>\n",
"<tr><td>Text</td><td>Type here!</td></tr>\n",
"<tr><td>z</td><td>True</td></tr>\n",
"<tr><td>Temp</td><td>5</td></tr>\n",
"<tr><td>Float (a)</td><td>5.0</td></tr>\n",
"</table>"
],
"metadata": {},
"output_type": "display_data",
"output_type": "stream",
"stream": "stdout",
"text": [
"<IPython.core.display.HTML object>"
"True\n"
]
}
],
"prompt_number": 4
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"If you pass a string, `interact` will generate a text area."
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"i.widget"
"interact(f, x='Hi there!');"
],
"language": "python",
"metadata": {},
"outputs": [
{
"html": [
"<h3>Arguments:</h3><table>\n",
"<tr><td>Current</td><td>4.99</td></tr>\n",
"<tr><td>Text</td><td>Type here!</td></tr>\n",
"<tr><td>z</td><td>True</td></tr>\n",
"<tr><td>Temp</td><td>5</td></tr>\n",
"<tr><td>Float (a)</td><td>5.0</td></tr>\n",
"</table>"
],
"metadata": {},
"output_type": "display_data",
"output_type": "stream",
"stream": "stdout",
"text": [
"<IPython.core.display.HTML object>"
"Hi there!\n"
]
}
],
"prompt_number": 5
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"`interact` can also be used as a decorator. This allows you to define a function and interact with it in a single shot. As this example shows, `interact` also works with functions that have multiple arguments."
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"@interact(x=True, y=1.0)\n",
"def g(x, y):\n",
" print x, y"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"True 1.0\n"
]
}
],
"prompt_number": 6
},
{
"cell_type": "heading",
"level": 2,
"metadata": {},
"source": [
"Fixing arguments using `fixed`"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"There are times when you may want to explore a function using `interact`, but fix one or more of its arguments to specific values. This can be accomplished by wrapping values with the `fixed` function."
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"def h(p, q):\n",
" print p, q"
],
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 7
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"When we call `interact`, we pass `fixed(20)` for q to hold it fixed at a value of `20`."
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"interact(h, p=5, q=fixed(20));"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"5 20\n"
]
}
],
"prompt_number": 8
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Notice that a slider is only produced for `p` as the value of `q` is fixed."
]
},
{
"cell_type": "heading",
"level": 2,
"metadata": {},
"source": [
"Widget abbreviations"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"When you pass an integer valued keyword argument (`x=10`) to `interact`, it generates an integer valued slider control with a range of $[-10,+3\\times10]$. In this case `10` is an *abbreviation* for an actual slider widget:\n",
"\n",
"```python\n",
"IntSliderWidget(min=-10,max=30,step=1,value=10)\n",
"```\n",
"\n",
"In fact, we can get the same result if we pass this `IntSliderWidget` as the keyword argument for `x`:"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"interact(f, x=widgets.IntSliderWidget(min=-10,max=30,step=1,value=10));"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"10\n"
]
}
],
"prompt_number": 9
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"This examples clarifies how `interact` proceses its keyword arguments:\n",
"\n",
"1. If the keyword argument is `Widget` instance with a `value` attribute, that widget is used. Any widget with a `value` attribute can be used, even custom ones.\n",
"2. Otherwise, the value is treated as a *widget abbreviation* that is converted to a widget before it is used.\n",
"\n",
"The following table gives an overview of different widget abbreviations:\n",
"\n",
"<table class=\"table table-condensed table-bordered\">\n",
" <tr><td><strong>Keyword argument</strong></td><td><strong>Widget</strong></td></tr> \n",
" <tr><td>`True` or `False`</td><td>CheckboxWiget</td></tr> \n",
" <tr><td>`'Hi there'`</td><td>TextareaWidget</td></tr>\n",
" <tr><td>`value` or `(min,max)` or `(min,max,step)` if integers are passed</td><td>IntSliderWidget</td></tr>\n",
" <tr><td>`value` or `(min,max)` or `(min,max,step)` if floats are passed</td><td>FloatSliderWidget</td></tr>\n",
" <tr><td>`('orange','apple')` or `{'one':1,'two':2}`</td><td>DropdownWidget</td></tr>\n",
"</table>"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"You have seen how the checkbox and textarea widgets work above. Here, more details about the different abbreviations for sliders and dropdowns are given.\n",
"\n",
"If a 2-tuple of integers is passed `(min,max)` a integer valued slider is produced with those minimum and maximum (inclusive) values. In this case, the default step size of `1` is used."
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"interact(f, x=(0,4));"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"2\n"
]
}
],
"prompt_number": 10
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"If a 3-tuple of integers is passed `(min,max,step)` the step size can also be set."
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"interact(f, x=(0,8,2));"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"4\n"
]
}
],
"prompt_number": 11
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"A float valued slider is produced if the elements of the tuples are floats. Here the minimum is `0.0`, the maximum is `10.0` and step size is `0.1` (the default)."
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"interact(f, x=(0.0,10.0));"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"5.0\n"
]
}
],
"prompt_number": 12
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The step size can be changed by passing a 3rd element in the tuple."
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"interact(f, x=(0.0,10.0,0.01));"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"4.99\n"
]
}
],
"prompt_number": 13
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"For both integer and float valued sliders, you can pick the initial value of the widget by passing a default keyword argument to the underlying Python function. Here we set the initial value of a float slider to `5.5`."
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"@interact(x=(0.0,20.0,0.5))\n",
"def h(x=5.5):\n",
" print x"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"5.5\n"
]
}
],
"prompt_number": 14
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Dropdown menus can be produced by passing a tuple of strings. In this case, the strings are both used as the names in the dropdown menu UI and passed to the underlying Python function."
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"interact(f, x=('apples','oranges'));"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"apples\n"
]
}
],
"prompt_number": 15
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"If you want a dropdown menu that passes non-string values to the Python function, you can pass a dictionary. The keys in the dictionary are used for the names in the dropdown menu UI and the values are the arguments that are passed to the underlying Python function."
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"interact(f, x={'one': 10, 'two': 20});"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"20\n"
]
}
],
"prompt_number": 16
},
{
"cell_type": "heading",
"level": 2,
"metadata": {},
"source": [
"Using function annotations with `interact`"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"If you are using Python 3, you can also specify widget abbreviations using [function annotations](https://docs.python.org/3/tutorial/controlflow.html#function-annotations). This is a convenient approach allows the widget abbreviations to be defined with a function.\n",
"\n",
"Define a function with an checkbox widget abbreviation for the argument `x`."
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"def f(x:True):\n",
" print x"
],
"language": "python",
"metadata": {},
"outputs": []
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Then, because the widget abbreviation has already been defined, you can call `interact` with a single argument."
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"interact(f);"
],
"language": "python",
"metadata": {},
"outputs": []
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"If you are running Python 2, function annotations can be defined using the `@annotate` function."
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"from IPython.utils.py3compat import annotate"
],
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 50
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"@annotate(x=True)\n",
"def f(x):\n",
" print x"
],
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 51
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"interact(f);"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"True\n"
]
}
],
"prompt_number": 52
},
{
"cell_type": "heading",
"level": 2,
"metadata": {},
"source": [
"`interactive`"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"In addition to `interact` IPython provides another function, `interactive`, that is useful when you want to reuse the widget that are produced or access the data that is bound to the UI controls."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Here is a function that returns the sum of its two arguments."
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"def f(a, b):\n",
" return a+b"
],
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 18
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Unlike `interact`, `interactive` returns a `Widget` instance rather than immediately displaying the widget."
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"w = interactive(f, a=10, b=20)"
],
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 19
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The widget is a `ContainerWidget`, which is a container for other widgets."
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"type(w)"
],
"language": "python",
"metadata": {},
"outputs": [
{
"metadata": {},
"output_type": "pyout",
"prompt_number": 20,
"text": [
"IPython.html.widgets.widget_container.ContainerWidget"
]
}
],
"prompt_number": 20
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The children of the `ContainerWidget` are two integer valued sliders produced by the widget abbreviations above."
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"w.children"
],
"language": "python",
"metadata": {},
"outputs": [
{
"metadata": {},
"output_type": "pyout",
"prompt_number": 21,
"text": [
"(<IPython.html.widgets.widget_int.IntSliderWidget at 0x10557ee90>,\n",
" <IPython.html.widgets.widget_int.IntSliderWidget at 0x10616ebd0>)"
]
}
],
"prompt_number": 21
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"To actually display the widgets, you can use IPython's `display` function."
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"from IPython.display import display\n",
"display(w)"
],
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 22
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"At this point, the UI controls work just like they would if `interact` had been used. You can manipulate them interactively and the function will be called. However, the widget instance returned by `interactive` also give you access to the current keyword arguments and return value of the underlying Python function.\n",
"\n",
"Here are the current keyword arguments. If you rerun this cell after manipulating the sliders, the values will have changed."
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"w.kwargs"
],
"language": "python",
"metadata": {},
"outputs": [
{
"metadata": {},
"output_type": "pyout",
"prompt_number": 23,
"text": [
"{u'a': 10, u'b': 20}"
]
}
],
"prompt_number": 23
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Here is the current return value of the function."
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"w.result"
],
"language": "python",
"metadata": {},
"outputs": [
{
"metadata": {},
"output_type": "pyout",
"prompt_number": 24,
"text": [
"30"
]
}
],
"prompt_number": 24
}
],
"metadata": {}

View File

@ -1,13 +1,8 @@
{
"metadata": {
"cell_tags": [
[
"<None>",
null
]
],
"celltoolbar": "Slideshow",
"name": "",
"signature": "sha256:5ac3a85c8bb2f9bb3cd63b524bbb626ab1531176b43a109d13f5d7794f805eee"
"signature": "sha256:916b80c91b959f78d7e5a9d5c9c7d371d3aa2b4476fdb19a7cb5cf9666d68d5b"
},
"nbformat": 3,
"nbformat_minor": 0,
@ -18,319 +13,422 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"To use IPython widgets in the notebook, the widget namespace needs to be imported."
"[Index](Index.ipynb) - [Next](Widget List.ipynb)"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"from IPython.html import widgets # Widget definitions\n",
"from IPython.display import display # Used to display widgets in the notebook"
],
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 2
},
{
"cell_type": "heading",
"level": 1,
"metadata": {},
"source": [
"Basic Widgets"
"Simple Widget Introduction"
]
},
{
"cell_type": "heading",
"level": 2,
"metadata": {},
"source": [
"What are widgets?"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"IPython comes with basic widgets that represent common interactive controls. These widgets are\n",
"\n",
"- CheckboxWidget\n",
"- ToggleButtonWidget\n",
"- FloatSliderWidget\n",
"- BoundedFloatTextWidget\n",
"- FloatProgressWidget\n",
"- FloatTextWidget\n",
"- ImageWidget\n",
"- IntSliderWidget\n",
"- BoundedIntTextWidget\n",
"- IntProgressWidget\n",
"- IntTextWidget\n",
"- ToggleButtonsWidget\n",
"- RadioButtonsWidget\n",
"- DropdownWidget\n",
"- SelectWidget\n",
"- HTMLWidget\n",
"- LatexWidget\n",
"- TextareaWidget\n",
"- TextWidget\n",
"- ButtonWidget\n",
"\n",
"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",
"\n",
"- ContainerWidget\n",
"- PopupWidget\n",
"- AccordionWidget\n",
"- TabWidget\n",
"\n",
"To see the complete list of widgets, one can execute the following"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"[widget for widget in dir(widgets) if widget.endswith('Widget')]"
],
"language": "python",
"metadata": {},
"outputs": [
{
"metadata": {},
"output_type": "pyout",
"prompt_number": 2,
"text": [
"['AccordionWidget',\n",
" 'BoundedFloatTextWidget',\n",
" 'BoundedIntTextWidget',\n",
" 'ButtonWidget',\n",
" 'CheckboxWidget',\n",
" 'ContainerWidget',\n",
" 'DOMWidget',\n",
" 'DropdownWidget',\n",
" 'FloatProgressWidget',\n",
" 'FloatSliderWidget',\n",
" 'FloatTextWidget',\n",
" 'HTMLWidget',\n",
" 'ImageWidget',\n",
" 'IntProgressWidget',\n",
" 'IntSliderWidget',\n",
" 'IntTextWidget',\n",
" 'LatexWidget',\n",
" 'PopupWidget',\n",
" 'RadioButtonsWidget',\n",
" 'SelectWidget',\n",
" 'TabWidget',\n",
" 'TextWidget',\n",
" 'TextareaWidget',\n",
" 'ToggleButtonWidget',\n",
" 'ToggleButtonsWidget',\n",
" 'Widget']"
]
"metadata": {
"slideshow": {
"slide_type": "slide"
}
],
"prompt_number": 2
},
{
"cell_type": "markdown",
"metadata": {},
},
"source": [
"The basic widgets all have sensible default values. Create a *FloatSliderWidget* without displaying it:"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"mywidget = widgets.FloatSliderWidget()"
],
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 3
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"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 or must be returned as the last item in the cell. `mywidget` is displayed by"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"display(mywidget)"
],
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 4
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"or"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"mywidget"
],
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 5
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"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",
"Widgets are elements that exists in both the front-end and the back-end.\n",
"\n",
"Widgets are manipulated via special instance attributes (traitlets). The names of these traitlets are listed in the widget's `keys` attribute (as seen below). A few of these attributes are common to most widgets. The basic attributes are `value`, `description`, `visible`, and `disabled`. `_css` and `_view_name` are private attributes that exist in all widgets and should not be modified."
"![Kernel & front-end diagram](../images/FrontendKernel.png)"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"mywidget.keys"
],
"language": "python",
"cell_type": "heading",
"level": 2,
"metadata": {},
"outputs": [
{
"metadata": {},
"output_type": "pyout",
"prompt_number": 6,
"text": [
"['_view_name',\n",
" 'orientation',\n",
" 'min',\n",
" 'max',\n",
" '_css',\n",
" 'value',\n",
" 'disabled',\n",
" 'visible',\n",
" 'step',\n",
" 'description']"
]
"source": [
"What can they be used for?"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
],
"prompt_number": 6
},
{
"cell_type": "markdown",
"metadata": {},
},
"source": [
"Changing a widget's attribute will automatically update that widget everywhere it is displayed in the notebook. Here, the `value` attribute of `mywidget` is set. The slider shown above updates automatically with the new value. Syncing also works in the other direction - changing the value of the displayed widget will update the property's value."
"You can use widgets to build **interactive GUIs** for your notebooks. \n",
"You can also use widgets to **synchronize stateful and stateless information** between Python and JavaScript."
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"mywidget.value = 25.0"
],
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 7
},
{
"cell_type": "markdown",
"cell_type": "heading",
"level": 2,
"metadata": {},
"source": [
"After changing the widget's value in the notebook by hand to 0.0 (sliding the bar to the far left)."
"Using widgets "
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"mywidget.value"
],
"language": "python",
"metadata": {},
"outputs": [
{
"metadata": {},
"output_type": "pyout",
"prompt_number": 8,
"text": [
"25.0"
]
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
],
"prompt_number": 8
},
{
"cell_type": "markdown",
"metadata": {},
},
"source": [
"Widget values can also be set with kwargs during the construction of the widget (as seen below)."
"To use the widget framework, you need to **import `IPython.html.widgets`**."
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"mysecondwidget = widgets.RadioButtonsWidget(values=[\"Item A\", \"Item B\", \"Item C\"], value=\"Item A\")\n",
"display(mysecondwidget)"
"from IPython.html.widgets import *"
],
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 9
"outputs": []
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"mysecondwidget.value"
],
"language": "python",
"metadata": {},
"outputs": [
{
"metadata": {},
"output_type": "pyout",
"prompt_number": 10,
"text": [
"'Item A'"
]
"cell_type": "heading",
"level": 3,
"metadata": {
"slideshow": {
"slide_type": "slide"
}
],
"prompt_number": 10
},
"source": [
"repr"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Some widgets have special attributes. For example, text boxes and text areas can specify the `placeholder` attribute, which will set \"placeholder\" text to be displayed before the user has typed anything:"
"Widgets have their own display `repr` which allows them to be displayed using IPython's display framework. Constructing and returning an `IntSliderWidget` automatically displays the widget (as seen below). Widgets are **displayed inside the `widget area`**, which sits between the code cell and output. **You can hide all of the widgets** in the `widget area` by clicking the grey *x* in the margin."
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"mytextwidget = widgets.TextWidget()\n",
"mytextwidget.placeholder = \"type something here\"\n",
"display(mytextwidget)"
"IntSliderWidget()"
],
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 4
"outputs": []
},
{
"cell_type": "heading",
"level": 3,
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"display()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"You can also explicitly display the widget using `display(...)`."
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"mytextareawidget = widgets.TextareaWidget()\n",
"mytextareawidget.placeholder = \"your text here\"\n",
"display(mytextareawidget)"
"from IPython.display import display\n",
"w = IntSliderWidget()\n",
"display(w)"
],
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 5
"outputs": []
},
{
"cell_type": "heading",
"level": 3,
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"Multiple display() calls"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"If you display the same widget twice, the displayed instances in the front-end **will remain in sync** with each other."
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"display(w)"
],
"language": "python",
"metadata": {},
"outputs": []
},
{
"cell_type": "heading",
"level": 2,
"metadata": {},
"source": [
"Why does displaying the same widget twice work?"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"Widgets are **represented in the back-end by a single object**. Each time a widget is displayed, **a new representation** of that same object is created in the front-end. These representations are called **views**.\n",
"\n",
"![Kernel & front-end diagram](images/WidgetModelView.png)"
]
},
{
"cell_type": "heading",
"level": 3,
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"Closing widgets"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"You can close a widget by calling its `close()` method."
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"display(w)"
],
"language": "python",
"metadata": {},
"outputs": []
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"w.close()"
],
"language": "python",
"metadata": {},
"outputs": []
},
{
"cell_type": "heading",
"level": 2,
"metadata": {},
"source": [
"Widget properties"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"All of the IPython widgets **share a similar naming scheme**. To read the value of a widget, you can query its `value` property."
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"w = IntSliderWidget()\n",
"display(w)"
],
"language": "python",
"metadata": {},
"outputs": []
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"w.value"
],
"language": "python",
"metadata": {},
"outputs": []
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Similarly, to set a widget's value, you can set its `value` property."
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"w.value = 100"
],
"language": "python",
"metadata": {},
"outputs": []
},
{
"cell_type": "heading",
"level": 3,
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"Keys"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"In addition to `value`, most widgets share `keys`, `description`, `disabled`, and `visible`. To see the entire list of synchronized, stateful properties, of any specific widget, you can **query the `keys` property**."
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"w.keys"
],
"language": "python",
"metadata": {},
"outputs": []
},
{
"cell_type": "heading",
"level": 3,
"metadata": {},
"source": [
"Shorthand for setting the initial values of widget properties"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"While creating a widget, you can set some or all of the initial values of that widget by **defining them as keyword arguments in the widget's constructor** (as seen below)."
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"TextWidget(value='Hello World!', disabled=True)"
],
"language": "python",
"metadata": {},
"outputs": []
},
{
"cell_type": "heading",
"level": 2,
"metadata": {},
"source": [
"Linking two similar widgets"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"If you need to display the same value two different ways, you'll have to use two different widgets. Instead of **attempting to manually synchronize the values** of the two widgets, you can use the `traitlet` `link` function **to link two properties together**. Below, the values of three widgets are linked together."
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"from IPython.utils.traitlets import link\n",
"a = FloatTextWidget()\n",
"b = FloatSliderWidget()\n",
"c = FloatProgressWidget()\n",
"display(a,b,c)\n",
"\n",
"\n",
"mylink = link((a, 'value'), (b, 'value'), (c, 'value'))"
],
"language": "python",
"metadata": {},
"outputs": []
},
{
"cell_type": "heading",
"level": 3,
"metadata": {},
"source": [
"Unlinking widgets"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"Unlinking the widgets is simple. All you have to do is call `.unlink` on the link object."
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"mylink.unlink()"
],
"language": "python",
"metadata": {},
"outputs": []
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"[Index](Index.ipynb) - [Next](Widget List.ipynb)"
]
}
],
"metadata": {}

View File

@ -6,8 +6,9 @@
null
]
],
"celltoolbar": "Slideshow",
"name": "",
"signature": "sha256:8cade57fabc6819dc950bc28502028554861fb1440d5d832922b95fd2b8bf25c"
"signature": "sha256:43e4910dd01111e1206f4f7940a201d6d5e69485df79de96e0ad927eb0046226"
},
"nbformat": 3,
"nbformat_minor": 0,
@ -15,32 +16,148 @@
{
"cells": [
{
"cell_type": "code",
"collapsed": false,
"input": [
"from __future__ import print_function # 2.7 compatability\n",
"\n",
"from IPython.html import widgets # Widget definitions\n",
"from IPython.display import display # Used to display widgets in the notebook"
],
"language": "python",
"cell_type": "markdown",
"metadata": {},
"outputs": [],
"prompt_number": 1
"source": [
"[Index](Index.ipynb) - [Back](Widget List.ipynb) - [Next](Widget Styling.ipynb)"
]
},
{
"cell_type": "heading",
"level": 1,
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"Widget Events"
]
},
{
"cell_type": "heading",
"level": 2,
"metadata": {},
"source": [
"Traitlet Events"
"Special events"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"from __future__ import print_function"
],
"language": "python",
"metadata": {},
"outputs": []
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The `ButtonWidget` is not used to represent a data type. Instead the button widget is used to **handle mouse clicks**. The **`on_click` method** of the `ButtonWidget` can be used to register function to be called when the button is clicked. The doc string of the `on_click` can be seen below."
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"from IPython.html import widgets\n",
"print(widgets.ButtonWidget.on_click.__doc__)"
],
"language": "python",
"metadata": {},
"outputs": []
},
{
"cell_type": "heading",
"level": 3,
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"Example"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"As mentioned in Part 1, the widget attributes are IPython traitlets. Traitlets are eventful. To handle changes, the `on_trait_change` method of the widget can be used to register a callback. The docstring for `on_trait_change` can be seen below. Both the `name` and `remove` properties are optional."
"Since button clicks are **stateless**, they are **transmitted from the front-end to the back-end using custom messages**. By using the `on_click` method, a button that prints a message when it has been clicked is shown below."
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"from IPython.display import display\n",
"button = widgets.ButtonWidget(description=\"Click Me!\")\n",
"display(button)\n",
"\n",
"def on_button_clicked(b):\n",
" print(\"Button clicked.\")\n",
"\n",
"button.on_click(on_button_clicked)"
],
"language": "python",
"metadata": {},
"outputs": []
},
{
"cell_type": "heading",
"level": 3,
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"on_sumbit"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The **`TextWidget`** also has a special **`on_submit` event**. The `on_submit` event **fires when the user hits return**."
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"text = widgets.TextWidget()\n",
"display(text)\n",
"\n",
"def handle_submit(sender):\n",
" print(text.value)\n",
"\n",
"text.on_submit(handle_submit)"
],
"language": "python",
"metadata": {},
"outputs": []
},
{
"cell_type": "heading",
"level": 2,
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"Traitlet events"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Widget properties are IPython traitlets** and **traitlets are eventful**. To handle changes, the **`on_trait_change` method** of the widget can be used to **register a callback**. The doc string for `on_trait_change` can be seen below."
]
},
{
@ -51,45 +168,25 @@
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"Setup a handler to be called when a trait changes.\n",
"\n",
" This is used to setup dynamic notifications of trait changes.\n",
"\n",
" Static handlers can be created by creating methods on a HasTraits\n",
" subclass with the naming convention '_[traitname]_changed'. Thus,\n",
" to create static handler for the trait 'a', create the method\n",
" _a_changed(self, name, old, new) (fewer arguments can be used, see\n",
" below).\n",
"\n",
" Parameters\n",
" ----------\n",
" handler : callable\n",
" A callable that is called when a trait changes. Its\n",
" signature can be handler(), handler(name), handler(name, new)\n",
" or handler(name, old, new).\n",
" name : list, str, None\n",
" If None, the handler will apply to all traits. If a list\n",
" of str, handler will apply to all names in the list. If a\n",
" str, the handler will apply just to that name.\n",
" remove : bool\n",
" If False (the default), then install the handler. If True\n",
" then unintall it.\n",
" \n"
]
"outputs": []
},
{
"cell_type": "heading",
"level": 3,
"metadata": {
"slideshow": {
"slide_type": "slide"
}
],
"prompt_number": 2
},
"source": [
"Signatures"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Mentioned in the doc string, the callback registered can have 4 possible signatures:\n",
"Mentioned in the doc string, the callback registered can have **4 possible signatures**:\n",
"\n",
"- callback()\n",
"- callback(trait_name)\n",
@ -113,133 +210,14 @@
],
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 3
},
{
"cell_type": "heading",
"level": 1,
"metadata": {},
"source": [
"Specialized Events"
]
},
{
"cell_type": "heading",
"level": 2,
"metadata": {},
"source": [
"Button Click Event"
]
"outputs": []
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The `ButtonWidget` is a special widget, like the `ContainerWidget` and `TabWidget`, that isn't used to represent a data type. Instead the button widget is used to handle mouse clicks. The `on_click` method of the `ButtonWidget` can be used to register function to be called when the button is clicked. The docstring of the `on_click` can be seen below."
"[Index](Index.ipynb) - [Back](Widget List.ipynb) - [Next](Widget Styling.ipynb)"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"print(widgets.ButtonWidget.on_click.__doc__)"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"Register a callback to execute when the button is clicked.\n",
"\n",
" The callback will be called with one argument,\n",
" the clicked button widget instance.\n",
"\n",
" Parameters\n",
" ----------\n",
" remove : bool (optional)\n",
" Set to true to remove the callback from the list of callbacks.\n"
]
}
],
"prompt_number": 4
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Button clicks are transmitted from the front-end to the back-end using custom messages. By using the `on_click` method, a button that prints a message when it has been clicked is shown below."
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"button = widgets.ButtonWidget(description=\"Click Me!\")\n",
"display(button)\n",
"\n",
"def on_button_clicked(b):\n",
" print(\"Button clicked.\")\n",
"\n",
"button.on_click(on_button_clicked)"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"Button clicked.\n"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
"Button clicked.\n"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
"Button clicked.\n"
]
}
],
"prompt_number": 5
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Event handlers can also be used to create widgets. In the example below, clicking a button spawns another button with a description equal to how many times the parent button had been clicked at the time."
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"def new_button(clicked):\n",
" button = widgets.ButtonWidget()\n",
" button.clicks = 0\n",
" clicked.clicks += 1\n",
" button.description = \"%d\" % clicked.clicks\n",
" display(button)\n",
" button.on_click(new_button)\n",
"button = widgets.ButtonWidget(description = \"Start\")\n",
"button.clicks = 0\n",
"display(button)\n",
"button.on_click(new_button)\n",
" "
],
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 6
}
],
"metadata": {}

View File

@ -0,0 +1,579 @@
{
"metadata": {
"celltoolbar": "Slideshow",
"name": "",
"signature": "sha256:f8284581eb29fde72c434a9a414fcb60837302177ebaa4af6ff219dd2b726381"
},
"nbformat": 3,
"nbformat_minor": 0,
"worksheets": [
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"[Index](Index.ipynb) - [Back](Widget Basics.ipynb) - [Next](Widget Events.ipynb)"
]
},
{
"cell_type": "heading",
"level": 1,
"metadata": {},
"source": [
"Widget List"
]
},
{
"cell_type": "heading",
"level": 2,
"metadata": {},
"source": [
"Complete list"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"For a complete list of the widgets available to you, you can list the classes in the widget namespace (as seen below). Classes with the suffix `Widget` are widgets. `Widget` and `DOMWidget` are base classes."
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"from IPython.html import widgets\n",
"[w for w in dir(widgets) if w.endswith('Widget')]"
],
"language": "python",
"metadata": {},
"outputs": []
},
{
"cell_type": "heading",
"level": 2,
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"Numeric widgets"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"There are 8 widgets distributed with IPython that are designed to display numeric values. Widgets exist for displaying integers and floats, both bounded and unbounded. The integer widgets share a similar naming scheme to their floating point counterparts. By replacing `Float` with `Int` in the widget name, you can find the Integer equivalent."
]
},
{
"cell_type": "heading",
"level": 3,
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"FloatSliderWidget"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"widgets.FloatSliderWidget(\n",
" value=7.5,\n",
" min=5.0,\n",
" max=10.0,\n",
" step=0.1,\n",
" description='Test:',\n",
")"
],
"language": "python",
"metadata": {},
"outputs": []
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Sliders can also be **displayed vertically**."
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"widgets.FloatSliderWidget(\n",
" value=7.5,\n",
" min=5.0,\n",
" max=10.0,\n",
" step=0.1,\n",
" description='Test',\n",
" orientation='vertical',\n",
")"
],
"language": "python",
"metadata": {},
"outputs": []
},
{
"cell_type": "heading",
"level": 3,
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"FloatProgressWidget"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"widgets.FloatProgressWidget(\n",
" value=7.5,\n",
" min=5.0,\n",
" max=10.0,\n",
" step=0.1,\n",
" description='Loading:',\n",
")"
],
"language": "python",
"metadata": {},
"outputs": []
},
{
"cell_type": "heading",
"level": 3,
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"BoundedFloatTextWidget"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"widgets.BoundedFloatTextWidget(\n",
" value=7.5,\n",
" min=5.0,\n",
" max=10.0,\n",
" description='Text:',\n",
")"
],
"language": "python",
"metadata": {},
"outputs": []
},
{
"cell_type": "heading",
"level": 3,
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"FloatTextWidget"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"widgets.FloatTextWidget(\n",
" value=7.5,\n",
" description='Any:',\n",
")"
],
"language": "python",
"metadata": {},
"outputs": []
},
{
"cell_type": "heading",
"level": 2,
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"Boolean widgets"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"There are two widgets that are designed to display a boolean value."
]
},
{
"cell_type": "heading",
"level": 3,
"metadata": {},
"source": [
"ToggleButtonWidget"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"widgets.ToggleButtonWidget(\n",
" description='Click me',\n",
" value=False,\n",
")"
],
"language": "python",
"metadata": {},
"outputs": []
},
{
"cell_type": "heading",
"level": 3,
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"CheckboxWidget"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"widgets.CheckboxWidget(\n",
" description='Check me',\n",
" value=True,\n",
")"
],
"language": "python",
"metadata": {},
"outputs": []
},
{
"cell_type": "heading",
"level": 2,
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"Selection widgets"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"There are four widgets that can be used to display single selection lists. All four inherit from the same base class. You can specify the **enumeration of selectables by passing a list**. You can **also specify the enumeration as a dictionary**, in which case the **keys will be used as the item displayed** in the list and the corresponding **value will be returned** when an item is selected."
]
},
{
"cell_type": "heading",
"level": 3,
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"DropdownWidget"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"from IPython.display import display\n",
"w = widgets.DropdownWidget(\n",
" values=[1, 2, 3],\n",
" value=2,\n",
" description='Number:',\n",
")\n",
"display(w)"
],
"language": "python",
"metadata": {},
"outputs": []
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"w.value"
],
"language": "python",
"metadata": {},
"outputs": []
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The following is also valid:"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"w = widgets.DropdownWidget(\n",
" values={'One': 1, 'Two': 2, 'Three': 3},\n",
" value=2,\n",
" description='Number:',\n",
")\n",
"display(w)"
],
"language": "python",
"metadata": {},
"outputs": []
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"w.value"
],
"language": "python",
"metadata": {},
"outputs": []
},
{
"cell_type": "heading",
"level": 3,
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"RadioButtonsWidget"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"widgets.RadioButtonsWidget(\n",
" description='Pizza topping:',\n",
" values=['pepperoni', 'pineapple', 'anchovies'],\n",
")"
],
"language": "python",
"metadata": {},
"outputs": []
},
{
"cell_type": "heading",
"level": 3,
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"SelectWidget"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"widgets.SelectWidget(\n",
" description='OS:',\n",
" values=['Linux', 'Windows', 'OSX'],\n",
")"
],
"language": "python",
"metadata": {},
"outputs": []
},
{
"cell_type": "heading",
"level": 3,
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"ToggleButtonsWidget"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"widgets.ToggleButtonsWidget(\n",
" description='Speed:',\n",
" values=['Slow', 'Regular', 'Fast'],\n",
")"
],
"language": "python",
"metadata": {},
"outputs": []
},
{
"cell_type": "heading",
"level": 2,
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"String widgets"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"There are 4 widgets that can be used to display a string value. Of those, the **`TextWidget` and `TextareaWidget` accept input**. The **`LatexWidget` and `HTMLWidget` display the string** as either Latex or HTML respectively, but **do not accept input**."
]
},
{
"cell_type": "heading",
"level": 3,
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"TextWidget"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"widgets.TextWidget(\n",
" description='String:',\n",
" value='Hello World',\n",
")"
],
"language": "python",
"metadata": {},
"outputs": []
},
{
"cell_type": "heading",
"level": 3,
"metadata": {},
"source": [
"TextareaWidget"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"widgets.TextareaWidget(\n",
" description='String:',\n",
" value='Hello World',\n",
")"
],
"language": "python",
"metadata": {},
"outputs": []
},
{
"cell_type": "heading",
"level": 3,
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"LatexWidget"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"widgets.LatexWidget(\n",
" value=\"$$\\\\frac{n!}{k!(n-k)!} = \\\\binom{n}{k}$$\",\n",
")"
],
"language": "python",
"metadata": {},
"outputs": []
},
{
"cell_type": "heading",
"level": 3,
"metadata": {},
"source": [
"HTMLWidget"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"widgets.HTMLWidget(\n",
" value=\"Hello <b>World</b>\"\n",
")"
],
"language": "python",
"metadata": {},
"outputs": []
},
{
"cell_type": "heading",
"level": 2,
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"ButtonWidget"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"widgets.ButtonWidget(description='Click me')"
],
"language": "python",
"metadata": {},
"outputs": []
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"[Index](Index.ipynb) - [Back](Widget Basics.ipynb) - [Next](Widget Events.ipynb)"
]
}
],
"metadata": {}
}
]
}

View File

@ -1,355 +0,0 @@
{
"metadata": {
"cell_tags": [
[
"<None>",
null
]
],
"name": "",
"signature": "sha256:cd7d3d42126bdbf20c087014460779dfbdb0a63dcb8f489ba7ebfc230a685edd"
},
"nbformat": 3,
"nbformat_minor": 0,
"worksheets": [
{
"cells": [
{
"cell_type": "code",
"collapsed": false,
"input": [
"from IPython.html import widgets # Widget definitions\n",
"from IPython.display import display # Used to display widgets in the notebook"
],
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 1
},
{
"cell_type": "heading",
"level": 1,
"metadata": {},
"source": [
"CSS"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"When trying to design an attractive widget GUI, styling becomes important.\n",
"Most widget views are DOM (document object model) elements that can be controlled with CSS.\n",
"There are two helper methods that allow the manipulation of the widget's CSS.\n",
"The first is the `Widget.set_css` method.\n",
"This method allows one or more CSS attributes to be set at once. "
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"print(widgets.DOMWidget.set_css.__doc__)"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"Set one or more CSS properties of the widget.\n",
"\n",
" This function has two signatures:\n",
" - set_css(css_dict, selector='')\n",
" - set_css(key, value, selector='')\n",
"\n",
" Parameters\n",
" ----------\n",
" css_dict : dict\n",
" CSS key/value pairs to apply\n",
" key: unicode\n",
" CSS key\n",
" value:\n",
" CSS value\n",
" selector: unicode (optional, kwarg only)\n",
" JQuery selector to use to apply the CSS key/value. If no selector \n",
" is provided, an empty selector is used. An empty selector makes the \n",
" front-end try to apply the css to a default element. The default\n",
" element is an attribute unique to each view, which is a DOM element\n",
" of the view that should be styled with common CSS (see \n",
" `$el_to_style` in the Javascript code).\n",
" \n"
]
}
],
"prompt_number": 2
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The second is `get_css` which allows CSS attributesto be read.\n",
"Note that this method will only read CSS attributes that have been set using the `set_css` method."
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"print(widgets.DOMWidget.get_css.__doc__)"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"Get a CSS property of the widget.\n",
"\n",
" Note: This function does not actually request the CSS from the \n",
" front-end; Only properties that have been set with set_css can be read.\n",
"\n",
" Parameters\n",
" ----------\n",
" key: unicode\n",
" CSS key\n",
" selector: unicode (optional)\n",
" JQuery selector used when the CSS key/value was set.\n",
" \n"
]
}
],
"prompt_number": 3
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Below is an example that applies CSS attributes to a container to emphasize text."
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"label = widgets.LatexWidget()\n",
"label.value = \"$\\\\textbf{ALERT:} Hello World!$\"\n",
"container = widgets.ContainerWidget(children=[label])\n",
"\n",
"# set_css used to set a single CSS attribute.\n",
"container.set_css('border', '3px solid black') # Border the container\n",
"\n",
"# set_css used to set multiple CSS attributes.\n",
"container.set_css({'padding': '6px', # Add padding to the container\n",
" 'background': 'yellow'}) # Fill the container yellow\n",
"\n",
"display(container)"
],
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 4
},
{
"cell_type": "heading",
"level": 1,
"metadata": {},
"source": [
"CSS Classes"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"In some cases, it is necessary to apply CSS classes to your widgets.\n",
"CSS classes allow DOM elements to be indentified in Javascript and CSS.\n",
"The notebook defines its own set of classes to stylize its elements.\n",
"The `add_class` widget method allows you to add CSS classes to your widget."
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"print(widgets.DOMWidget.add_class.__doc__)"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"Add class[es] to a DOM element.\n",
"\n",
" Parameters\n",
" ----------\n",
" class_names: unicode or list\n",
" Class name(s) to add to the DOM element(s).\n",
" selector: unicode (optional)\n",
" JQuery selector to select the DOM element(s) that the class(es) will\n",
" be added to.\n",
" \n"
]
}
],
"prompt_number": 5
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Since `add_class` is a DOM operation, **it will only affect widgets that have already been displayed**.\n",
"`add_class` must be called after the widget has been displayed.\n",
"Extending the example above, the corners of the container can be rounded by adding the `corner-all` CSS class to the container."
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"container = widgets.ContainerWidget()\n",
"container.set_css({'border': '3px solid black',\n",
" 'padding': '6px', \n",
" 'background': 'yellow'}) \n",
"\n",
"label = widgets.LatexWidget()\n",
"label.value = \"$\\\\textbf{ALERT:} Hello World!$\"\n",
"container.children = [label]\n",
"display(container)\n",
"container.add_class('corner-all') # Must be called AFTER display"
],
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 6
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The IPython notebook uses [bootstrap](http://getbootstrap.com/\u200e) for styling.\n",
"The example above can be simplified by using a bootstrap class:"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"label = widgets.LatexWidget(value = \"$\\\\textbf{ALERT:} Hello World!$\")\n",
"display(label)\n",
"\n",
"# Apply twitter bootstrap alert class to the label.\n",
"label.add_class(\"alert\")"
],
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 7
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The example below shows how bootstrap classes can be used to change button apearance."
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"# List of the bootstrap button styles\n",
"button_classes = ['Default', 'btn-primary', 'btn-info', 'btn-success', \n",
" 'btn-warning', 'btn-danger', 'btn-inverse', 'btn-link']\n",
"\n",
"# Create each button and apply the style. Also add margin to the buttons so they space\n",
"# themselves nicely.\n",
"for i in range(8):\n",
" button = widgets.ButtonWidget(description=button_classes[i])\n",
" button.set_css(\"margin\", \"5px\")\n",
" display(button)\n",
" if i > 0: # Don't add a class the first button.\n",
" button.add_class(button_classes[i])\n",
" "
],
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 8
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"It is also useful to be able to remove CSS classes from widgets.\n",
"The `remove_class` method allows you to remove classes from widgets that have been displayed.\n",
"Like `add_class`, it must be called after the widget has been displayed."
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"print(widgets.DOMWidget.remove_class.__doc__)"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"Remove class[es] from a DOM element.\n",
"\n",
" Parameters\n",
" ----------\n",
" class_names: unicode or list\n",
" Class name(s) to remove from the DOM element(s).\n",
" selector: unicode (optional)\n",
" JQuery selector to select the DOM element(s) that the class(es) will\n",
" be removed from.\n",
" \n"
]
}
],
"prompt_number": 9
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The example below animates an alert using different bootstrap styles."
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"import time\n",
"label = widgets.LatexWidget(value = \"$\\\\textbf{ALERT:} Hello World!$\")\n",
"display(label)\n",
"\n",
"# Apply twitter bootstrap alert class to the label.\n",
"label.add_class(\"alert\")\n",
"\n",
"# Animate through additional bootstrap label styles 3 times\n",
"additional_alert_styles = ['alert-error', 'alert-info', 'alert-success']\n",
"for i in range(3 * len(additional_alert_styles)):\n",
" label.add_class(additional_alert_styles[i % 3])\n",
" label.remove_class(additional_alert_styles[(i-1) % 3])\n",
" time.sleep(1)\n",
" "
],
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 10
}
],
"metadata": {}
}
]
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,442 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>ActiveLayerIndex</key>
<integer>0</integer>
<key>ApplicationVersion</key>
<array>
<string>com.omnigroup.OmniGraffle</string>
<string>139.18.0.187838</string>
</array>
<key>AutoAdjust</key>
<true/>
<key>BackgroundGraphic</key>
<dict>
<key>Bounds</key>
<string>{{0, 0}, {576, 733}}</string>
<key>Class</key>
<string>SolidGraphic</string>
<key>ID</key>
<integer>2</integer>
<key>Style</key>
<dict>
<key>shadow</key>
<dict>
<key>Draws</key>
<string>NO</string>
</dict>
<key>stroke</key>
<dict>
<key>Draws</key>
<string>NO</string>
</dict>
</dict>
</dict>
<key>BaseZoom</key>
<integer>0</integer>
<key>CanvasOrigin</key>
<string>{0, 0}</string>
<key>ColumnAlign</key>
<integer>1</integer>
<key>ColumnSpacing</key>
<real>36</real>
<key>CreationDate</key>
<string>2014-05-28 16:41:42 +0000</string>
<key>Creator</key>
<string>bgranger</string>
<key>DisplayScale</key>
<string>1 0/72 in = 1 0/72 in</string>
<key>GraphDocumentVersion</key>
<integer>8</integer>
<key>GraphicsList</key>
<array>
<dict>
<key>Class</key>
<string>LineGraphic</string>
<key>Head</key>
<dict>
<key>ID</key>
<integer>4</integer>
</dict>
<key>ID</key>
<integer>8</integer>
<key>Points</key>
<array>
<string>{301.5, 284.5}</string>
<string>{370.03931790895228, 313.41502474283925}</string>
</array>
<key>Style</key>
<dict>
<key>stroke</key>
<dict>
<key>HeadArrow</key>
<string>0</string>
<key>Legacy</key>
<true/>
<key>Pattern</key>
<integer>1</integer>
<key>TailArrow</key>
<string>0</string>
</dict>
</dict>
</dict>
<dict>
<key>Class</key>
<string>LineGraphic</string>
<key>Head</key>
<dict>
<key>ID</key>
<integer>3</integer>
</dict>
<key>ID</key>
<integer>7</integer>
<key>Points</key>
<array>
<string>{302, 282}</string>
<string>{370.00010962762133, 280.57591393450008}</string>
</array>
<key>Style</key>
<dict>
<key>stroke</key>
<dict>
<key>HeadArrow</key>
<string>0</string>
<key>Legacy</key>
<true/>
<key>Pattern</key>
<integer>1</integer>
<key>TailArrow</key>
<string>0</string>
</dict>
</dict>
</dict>
<dict>
<key>Class</key>
<string>LineGraphic</string>
<key>Head</key>
<dict>
<key>ID</key>
<integer>1</integer>
</dict>
<key>ID</key>
<integer>6</integer>
<key>Points</key>
<array>
<string>{301.5, 280.5}</string>
<string>{370.04817900607623, 248.01101932524512}</string>
</array>
<key>Style</key>
<dict>
<key>stroke</key>
<dict>
<key>HeadArrow</key>
<string>0</string>
<key>Legacy</key>
<true/>
<key>Pattern</key>
<integer>1</integer>
<key>TailArrow</key>
<string>0</string>
</dict>
</dict>
</dict>
<dict>
<key>Bounds</key>
<string>{{241.5, 262}, {58, 36}}</string>
<key>Class</key>
<string>ShapedGraphic</string>
<key>FontInfo</key>
<dict>
<key>Font</key>
<string>Helvetica</string>
<key>Size</key>
<real>12</real>
</dict>
<key>ID</key>
<integer>5</integer>
<key>Shape</key>
<string>Rectangle</string>
<key>Style</key>
<dict>
<key>shadow</key>
<dict>
<key>Draws</key>
<string>NO</string>
</dict>
</dict>
<key>Text</key>
<dict>
<key>Text</key>
<string>{\rtf1\ansi\ansicpg1252\cocoartf1265\cocoasubrtf190
\cocoascreenfonts1{\fonttbl\f0\fnil\fcharset0 xkcd-Regular;}
{\colortbl;\red255\green255\blue255;}
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
\f0\fs20 \cf0 Frontend}</string>
</dict>
</dict>
<dict>
<key>Bounds</key>
<string>{{370.5, 307}, {54, 36}}</string>
<key>Class</key>
<string>ShapedGraphic</string>
<key>FontInfo</key>
<dict>
<key>Font</key>
<string>Helvetica</string>
<key>Size</key>
<real>12</real>
</dict>
<key>ID</key>
<integer>4</integer>
<key>Shape</key>
<string>Rectangle</string>
<key>Style</key>
<dict>
<key>shadow</key>
<dict>
<key>Draws</key>
<string>NO</string>
</dict>
</dict>
<key>Text</key>
<dict>
<key>Text</key>
<string>{\rtf1\ansi\ansicpg1252\cocoartf1265\cocoasubrtf190
\cocoascreenfonts1{\fonttbl\f0\fnil\fcharset0 xkcd-Regular;}
{\colortbl;\red255\green255\blue255;}
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
\f0\fs20 \cf0 R\
Kernel}</string>
</dict>
</dict>
<dict>
<key>Bounds</key>
<string>{{370.5, 262}, {54, 36}}</string>
<key>Class</key>
<string>ShapedGraphic</string>
<key>FontInfo</key>
<dict>
<key>Font</key>
<string>Helvetica</string>
<key>Size</key>
<real>12</real>
</dict>
<key>ID</key>
<integer>3</integer>
<key>Shape</key>
<string>Rectangle</string>
<key>Style</key>
<dict>
<key>shadow</key>
<dict>
<key>Draws</key>
<string>NO</string>
</dict>
</dict>
<key>Text</key>
<dict>
<key>Text</key>
<string>{\rtf1\ansi\ansicpg1252\cocoartf1265\cocoasubrtf190
\cocoascreenfonts1{\fonttbl\f0\fnil\fcharset0 xkcd-Regular;}
{\colortbl;\red255\green255\blue255;}
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
\f0\fs20 \cf0 Julia\
Kernel}</string>
</dict>
</dict>
<dict>
<key>Bounds</key>
<string>{{370.5, 217}, {54, 36}}</string>
<key>Class</key>
<string>ShapedGraphic</string>
<key>FontInfo</key>
<dict>
<key>Font</key>
<string>Helvetica</string>
<key>Size</key>
<real>12</real>
</dict>
<key>ID</key>
<integer>1</integer>
<key>Shape</key>
<string>Rectangle</string>
<key>Style</key>
<dict>
<key>shadow</key>
<dict>
<key>Draws</key>
<string>NO</string>
</dict>
</dict>
<key>Text</key>
<dict>
<key>Text</key>
<string>{\rtf1\ansi\ansicpg1252\cocoartf1265\cocoasubrtf190
\cocoascreenfonts1{\fonttbl\f0\fnil\fcharset0 xkcd-Regular;}
{\colortbl;\red255\green255\blue255;}
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
\f0\fs20 \cf0 Python Kernel}</string>
</dict>
</dict>
</array>
<key>GridInfo</key>
<dict/>
<key>GuidesLocked</key>
<string>NO</string>
<key>GuidesVisible</key>
<string>YES</string>
<key>HPages</key>
<integer>1</integer>
<key>ImageCounter</key>
<integer>1</integer>
<key>KeepToScale</key>
<false/>
<key>Layers</key>
<array>
<dict>
<key>Lock</key>
<string>NO</string>
<key>Name</key>
<string>Layer 1</string>
<key>Print</key>
<string>YES</string>
<key>View</key>
<string>YES</string>
</dict>
</array>
<key>LayoutInfo</key>
<dict>
<key>Animate</key>
<string>NO</string>
<key>circoMinDist</key>
<real>18</real>
<key>circoSeparation</key>
<real>0.0</real>
<key>layoutEngine</key>
<string>dot</string>
<key>neatoSeparation</key>
<real>0.0</real>
<key>twopiSeparation</key>
<real>0.0</real>
</dict>
<key>LinksVisible</key>
<string>NO</string>
<key>MagnetsVisible</key>
<string>NO</string>
<key>MasterSheets</key>
<array/>
<key>ModificationDate</key>
<string>2014-05-28 16:45:20 +0000</string>
<key>Modifier</key>
<string>bgranger</string>
<key>NotesVisible</key>
<string>NO</string>
<key>Orientation</key>
<integer>2</integer>
<key>OriginVisible</key>
<string>NO</string>
<key>PageBreaks</key>
<string>YES</string>
<key>PrintInfo</key>
<dict>
<key>NSBottomMargin</key>
<array>
<string>float</string>
<string>41</string>
</array>
<key>NSHorizonalPagination</key>
<array>
<string>coded</string>
<string>BAtzdHJlYW10eXBlZIHoA4QBQISEhAhOU051bWJlcgCEhAdOU1ZhbHVlAISECE5TT2JqZWN0AIWEASqEhAFxlwCG</string>
</array>
<key>NSLeftMargin</key>
<array>
<string>float</string>
<string>18</string>
</array>
<key>NSPaperSize</key>
<array>
<string>size</string>
<string>{612, 792}</string>
</array>
<key>NSPrintReverseOrientation</key>
<array>
<string>int</string>
<string>0</string>
</array>
<key>NSRightMargin</key>
<array>
<string>float</string>
<string>18</string>
</array>
<key>NSTopMargin</key>
<array>
<string>float</string>
<string>18</string>
</array>
</dict>
<key>PrintOnePage</key>
<false/>
<key>ReadOnly</key>
<string>NO</string>
<key>RowAlign</key>
<integer>1</integer>
<key>RowSpacing</key>
<real>36</real>
<key>SheetTitle</key>
<string>Canvas 1</string>
<key>SmartAlignmentGuidesActive</key>
<string>YES</string>
<key>SmartDistanceGuidesActive</key>
<string>YES</string>
<key>UniqueID</key>
<integer>1</integer>
<key>UseEntirePage</key>
<false/>
<key>VPages</key>
<integer>1</integer>
<key>WindowInfo</key>
<dict>
<key>CurrentSheet</key>
<integer>0</integer>
<key>ExpandedCanvases</key>
<array>
<dict>
<key>name</key>
<string>Canvas 1</string>
</dict>
</array>
<key>Frame</key>
<string>{{387, 6}, {710, 872}}</string>
<key>ListView</key>
<true/>
<key>OutlineWidth</key>
<integer>142</integer>
<key>RightSidebar</key>
<false/>
<key>ShowRuler</key>
<true/>
<key>Sidebar</key>
<true/>
<key>SidebarWidth</key>
<integer>120</integer>
<key>VisibleRegion</key>
<string>{{196.5, 107}, {287.5, 366.5}}</string>
<key>Zoom</key>
<real>2</real>
<key>ZoomValues</key>
<array>
<array>
<string>Canvas 1</string>
<real>2</real>
<real>1</real>
</array>
</array>
</dict>
</dict>
</plist>

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

View File

@ -0,0 +1,876 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>ActiveLayerIndex</key>
<integer>0</integer>
<key>ApplicationVersion</key>
<array>
<string>com.omnigroup.OmniGraffle</string>
<string>139.18.0.187838</string>
</array>
<key>AutoAdjust</key>
<true/>
<key>BackgroundGraphic</key>
<dict>
<key>Bounds</key>
<string>{{0, 0}, {576, 733}}</string>
<key>Class</key>
<string>SolidGraphic</string>
<key>FontInfo</key>
<dict>
<key>Font</key>
<string>xkcd-Regular</string>
<key>Size</key>
<real>11</real>
</dict>
<key>ID</key>
<integer>2</integer>
<key>Style</key>
<dict>
<key>shadow</key>
<dict>
<key>Draws</key>
<string>NO</string>
</dict>
<key>stroke</key>
<dict>
<key>Draws</key>
<string>NO</string>
</dict>
</dict>
</dict>
<key>BaseZoom</key>
<integer>0</integer>
<key>CanvasOrigin</key>
<string>{0, 0}</string>
<key>ColumnAlign</key>
<integer>1</integer>
<key>ColumnSpacing</key>
<real>36</real>
<key>CreationDate</key>
<string>2014-05-27 22:35:15 +0000</string>
<key>Creator</key>
<string>bgranger</string>
<key>DisplayScale</key>
<string>1 0/72 in = 1 0/72 in</string>
<key>GraphDocumentVersion</key>
<integer>8</integer>
<key>GraphicsList</key>
<array>
<dict>
<key>Class</key>
<string>LineGraphic</string>
<key>ID</key>
<integer>24</integer>
<key>Points</key>
<array>
<string>{222.5, 377.5}</string>
<string>{262, 424.66666666666669}</string>
</array>
<key>Style</key>
<dict>
<key>stroke</key>
<dict>
<key>HeadArrow</key>
<string>0</string>
<key>Legacy</key>
<true/>
<key>Pattern</key>
<integer>1</integer>
<key>TailArrow</key>
<string>0</string>
</dict>
</dict>
<key>Tail</key>
<dict>
<key>ID</key>
<integer>23</integer>
</dict>
</dict>
<dict>
<key>Class</key>
<string>LineGraphic</string>
<key>Head</key>
<dict>
<key>ID</key>
<integer>4</integer>
</dict>
<key>ID</key>
<integer>23</integer>
<key>Points</key>
<array>
<string>{222.5, 377.5}</string>
<string>{261.50992666237363, 385.39132104238854}</string>
</array>
<key>Style</key>
<dict>
<key>stroke</key>
<dict>
<key>HeadArrow</key>
<string>0</string>
<key>Legacy</key>
<true/>
<key>Pattern</key>
<integer>1</integer>
<key>TailArrow</key>
<string>0</string>
</dict>
</dict>
</dict>
<dict>
<key>Class</key>
<string>LineGraphic</string>
<key>Head</key>
<dict>
<key>ID</key>
<integer>3</integer>
</dict>
<key>ID</key>
<integer>22</integer>
<key>Points</key>
<array>
<string>{223.5, 376.5}</string>
<string>{261.51605222709946, 366.62761434412533}</string>
</array>
<key>Style</key>
<dict>
<key>stroke</key>
<dict>
<key>HeadArrow</key>
<string>0</string>
<key>Legacy</key>
<true/>
<key>Pattern</key>
<integer>1</integer>
<key>TailArrow</key>
<string>0</string>
</dict>
</dict>
<key>Tail</key>
<dict>
<key>ID</key>
<integer>21</integer>
</dict>
</dict>
<dict>
<key>Class</key>
<string>LineGraphic</string>
<key>ID</key>
<integer>21</integer>
<key>Points</key>
<array>
<string>{223.5, 376.5}</string>
<string>{262, 323.33333333333331}</string>
</array>
<key>Style</key>
<dict>
<key>stroke</key>
<dict>
<key>HeadArrow</key>
<string>0</string>
<key>Legacy</key>
<true/>
<key>Pattern</key>
<integer>1</integer>
<key>TailArrow</key>
<string>0</string>
</dict>
</dict>
</dict>
<dict>
<key>Class</key>
<string>LineGraphic</string>
<key>Head</key>
<dict>
<key>ID</key>
<integer>18</integer>
</dict>
<key>ID</key>
<integer>20</integer>
<key>Points</key>
<array>
<string>{136, 376.24998788995731}</string>
<string>{167.5, 376.24998788995731}</string>
</array>
<key>Style</key>
<dict>
<key>stroke</key>
<dict>
<key>HeadArrow</key>
<string>0</string>
<key>Legacy</key>
<true/>
<key>Pattern</key>
<integer>1</integer>
<key>TailArrow</key>
<string>0</string>
</dict>
</dict>
<key>Tail</key>
<dict>
<key>ID</key>
<integer>19</integer>
</dict>
</dict>
<dict>
<key>Bounds</key>
<string>{{66.5, 364.5}, {69, 23.5}}</string>
<key>Class</key>
<string>ShapedGraphic</string>
<key>ID</key>
<integer>19</integer>
<key>Shape</key>
<string>Rectangle</string>
<key>Style</key>
<dict>
<key>shadow</key>
<dict>
<key>Draws</key>
<string>NO</string>
</dict>
</dict>
<key>Text</key>
<dict>
<key>Text</key>
<string>{\rtf1\ansi\ansicpg1252\cocoartf1265\cocoasubrtf190
\cocoascreenfonts1{\fonttbl\f0\fnil\fcharset0 xkcd-Regular;}
{\colortbl;\red255\green255\blue255;}
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
\f0\fs24 \cf0 FRONTEND}</string>
</dict>
</dict>
<dict>
<key>Bounds</key>
<string>{{168, 364.5}, {52, 23.5}}</string>
<key>Class</key>
<string>ShapedGraphic</string>
<key>ID</key>
<integer>18</integer>
<key>Shape</key>
<string>Rectangle</string>
<key>Style</key>
<dict>
<key>shadow</key>
<dict>
<key>Draws</key>
<string>NO</string>
</dict>
</dict>
<key>Text</key>
<dict>
<key>Text</key>
<string>{\rtf1\ansi\ansicpg1252\cocoartf1265\cocoasubrtf190
\cocoascreenfonts1{\fonttbl\f0\fnil\fcharset0 xkcd-Regular;}
{\colortbl;\red255\green255\blue255;}
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
\f0\fs24 \cf0 Kernel}</string>
</dict>
</dict>
<dict>
<key>Bounds</key>
<string>{{436, 410}, {52, 23.5}}</string>
<key>Class</key>
<string>ShapedGraphic</string>
<key>ID</key>
<integer>17</integer>
<key>Shape</key>
<string>Rectangle</string>
<key>Style</key>
<dict>
<key>shadow</key>
<dict>
<key>Draws</key>
<string>NO</string>
</dict>
</dict>
<key>Text</key>
<dict>
<key>Text</key>
<string>{\rtf1\ansi\ansicpg1252\cocoartf1265\cocoasubrtf190
\cocoascreenfonts1{\fonttbl\f0\fnil\fcharset0 xkcd-Regular;}
{\colortbl;\red255\green255\blue255;}
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
\f0\fs24 \cf0 Kernel}</string>
</dict>
</dict>
<dict>
<key>Bounds</key>
<string>{{436, 379}, {52, 23.5}}</string>
<key>Class</key>
<string>ShapedGraphic</string>
<key>ID</key>
<integer>16</integer>
<key>Shape</key>
<string>Rectangle</string>
<key>Style</key>
<dict>
<key>shadow</key>
<dict>
<key>Draws</key>
<string>NO</string>
</dict>
</dict>
<key>Text</key>
<dict>
<key>Text</key>
<string>{\rtf1\ansi\ansicpg1252\cocoartf1265\cocoasubrtf190
\cocoascreenfonts1{\fonttbl\f0\fnil\fcharset0 xkcd-Regular;}
{\colortbl;\red255\green255\blue255;}
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
\f0\fs24 \cf0 Kernel}</string>
</dict>
</dict>
<dict>
<key>Bounds</key>
<string>{{436, 348}, {52, 23.5}}</string>
<key>Class</key>
<string>ShapedGraphic</string>
<key>ID</key>
<integer>15</integer>
<key>Shape</key>
<string>Rectangle</string>
<key>Style</key>
<dict>
<key>shadow</key>
<dict>
<key>Draws</key>
<string>NO</string>
</dict>
</dict>
<key>Text</key>
<dict>
<key>Text</key>
<string>{\rtf1\ansi\ansicpg1252\cocoartf1265\cocoasubrtf190
\cocoascreenfonts1{\fonttbl\f0\fnil\fcharset0 xkcd-Regular;}
{\colortbl;\red255\green255\blue255;}
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
\f0\fs24 \cf0 Kernel}</string>
</dict>
</dict>
<dict>
<key>Bounds</key>
<string>{{436, 317}, {52, 23.5}}</string>
<key>Class</key>
<string>ShapedGraphic</string>
<key>ID</key>
<integer>14</integer>
<key>Shape</key>
<string>Rectangle</string>
<key>Style</key>
<dict>
<key>shadow</key>
<dict>
<key>Draws</key>
<string>NO</string>
</dict>
</dict>
<key>Text</key>
<dict>
<key>Text</key>
<string>{\rtf1\ansi\ansicpg1252\cocoartf1265\cocoasubrtf190
\cocoascreenfonts1{\fonttbl\f0\fnil\fcharset0 xkcd-Regular;}
{\colortbl;\red255\green255\blue255;}
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
\f0\fs24 \cf0 Kernel}</string>
</dict>
</dict>
<dict>
<key>Bounds</key>
<string>{{378, 410}, {52, 23.5}}</string>
<key>Class</key>
<string>ShapedGraphic</string>
<key>ID</key>
<integer>13</integer>
<key>Shape</key>
<string>Rectangle</string>
<key>Style</key>
<dict>
<key>shadow</key>
<dict>
<key>Draws</key>
<string>NO</string>
</dict>
</dict>
<key>Text</key>
<dict>
<key>Text</key>
<string>{\rtf1\ansi\ansicpg1252\cocoartf1265\cocoasubrtf190
\cocoascreenfonts1{\fonttbl\f0\fnil\fcharset0 xkcd-Regular;}
{\colortbl;\red255\green255\blue255;}
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
\f0\fs24 \cf0 Kernel}</string>
</dict>
</dict>
<dict>
<key>Bounds</key>
<string>{{378, 379}, {52, 23.5}}</string>
<key>Class</key>
<string>ShapedGraphic</string>
<key>ID</key>
<integer>12</integer>
<key>Shape</key>
<string>Rectangle</string>
<key>Style</key>
<dict>
<key>shadow</key>
<dict>
<key>Draws</key>
<string>NO</string>
</dict>
</dict>
<key>Text</key>
<dict>
<key>Text</key>
<string>{\rtf1\ansi\ansicpg1252\cocoartf1265\cocoasubrtf190
\cocoascreenfonts1{\fonttbl\f0\fnil\fcharset0 xkcd-Regular;}
{\colortbl;\red255\green255\blue255;}
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
\f0\fs24 \cf0 Kernel}</string>
</dict>
</dict>
<dict>
<key>Bounds</key>
<string>{{378, 348}, {52, 23.5}}</string>
<key>Class</key>
<string>ShapedGraphic</string>
<key>ID</key>
<integer>11</integer>
<key>Shape</key>
<string>Rectangle</string>
<key>Style</key>
<dict>
<key>shadow</key>
<dict>
<key>Draws</key>
<string>NO</string>
</dict>
</dict>
<key>Text</key>
<dict>
<key>Text</key>
<string>{\rtf1\ansi\ansicpg1252\cocoartf1265\cocoasubrtf190
\cocoascreenfonts1{\fonttbl\f0\fnil\fcharset0 xkcd-Regular;}
{\colortbl;\red255\green255\blue255;}
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
\f0\fs24 \cf0 Kernel}</string>
</dict>
</dict>
<dict>
<key>Bounds</key>
<string>{{378, 317}, {52, 23.5}}</string>
<key>Class</key>
<string>ShapedGraphic</string>
<key>ID</key>
<integer>10</integer>
<key>Shape</key>
<string>Rectangle</string>
<key>Style</key>
<dict>
<key>shadow</key>
<dict>
<key>Draws</key>
<string>NO</string>
</dict>
</dict>
<key>Text</key>
<dict>
<key>Text</key>
<string>{\rtf1\ansi\ansicpg1252\cocoartf1265\cocoasubrtf190
\cocoascreenfonts1{\fonttbl\f0\fnil\fcharset0 xkcd-Regular;}
{\colortbl;\red255\green255\blue255;}
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
\f0\fs24 \cf0 Kernel}</string>
</dict>
</dict>
<dict>
<key>Bounds</key>
<string>{{320, 410}, {52, 23.5}}</string>
<key>Class</key>
<string>ShapedGraphic</string>
<key>ID</key>
<integer>9</integer>
<key>Shape</key>
<string>Rectangle</string>
<key>Style</key>
<dict>
<key>shadow</key>
<dict>
<key>Draws</key>
<string>NO</string>
</dict>
</dict>
<key>Text</key>
<dict>
<key>Text</key>
<string>{\rtf1\ansi\ansicpg1252\cocoartf1265\cocoasubrtf190
\cocoascreenfonts1{\fonttbl\f0\fnil\fcharset0 xkcd-Regular;}
{\colortbl;\red255\green255\blue255;}
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
\f0\fs24 \cf0 Kernel}</string>
</dict>
</dict>
<dict>
<key>Bounds</key>
<string>{{320, 379}, {52, 23.5}}</string>
<key>Class</key>
<string>ShapedGraphic</string>
<key>ID</key>
<integer>8</integer>
<key>Shape</key>
<string>Rectangle</string>
<key>Style</key>
<dict>
<key>shadow</key>
<dict>
<key>Draws</key>
<string>NO</string>
</dict>
</dict>
<key>Text</key>
<dict>
<key>Text</key>
<string>{\rtf1\ansi\ansicpg1252\cocoartf1265\cocoasubrtf190
\cocoascreenfonts1{\fonttbl\f0\fnil\fcharset0 xkcd-Regular;}
{\colortbl;\red255\green255\blue255;}
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
\f0\fs24 \cf0 Kernel}</string>
</dict>
</dict>
<dict>
<key>Bounds</key>
<string>{{320, 348}, {52, 23.5}}</string>
<key>Class</key>
<string>ShapedGraphic</string>
<key>ID</key>
<integer>7</integer>
<key>Shape</key>
<string>Rectangle</string>
<key>Style</key>
<dict>
<key>shadow</key>
<dict>
<key>Draws</key>
<string>NO</string>
</dict>
</dict>
<key>Text</key>
<dict>
<key>Text</key>
<string>{\rtf1\ansi\ansicpg1252\cocoartf1265\cocoasubrtf190
\cocoascreenfonts1{\fonttbl\f0\fnil\fcharset0 xkcd-Regular;}
{\colortbl;\red255\green255\blue255;}
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
\f0\fs24 \cf0 Kernel}</string>
</dict>
</dict>
<dict>
<key>Bounds</key>
<string>{{320, 317}, {52, 23.5}}</string>
<key>Class</key>
<string>ShapedGraphic</string>
<key>ID</key>
<integer>6</integer>
<key>Shape</key>
<string>Rectangle</string>
<key>Style</key>
<dict>
<key>shadow</key>
<dict>
<key>Draws</key>
<string>NO</string>
</dict>
</dict>
<key>Text</key>
<dict>
<key>Text</key>
<string>{\rtf1\ansi\ansicpg1252\cocoartf1265\cocoasubrtf190
\cocoascreenfonts1{\fonttbl\f0\fnil\fcharset0 xkcd-Regular;}
{\colortbl;\red255\green255\blue255;}
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
\f0\fs24 \cf0 Kernel}</string>
</dict>
</dict>
<dict>
<key>Bounds</key>
<string>{{262, 410}, {52, 23.5}}</string>
<key>Class</key>
<string>ShapedGraphic</string>
<key>ID</key>
<integer>5</integer>
<key>Shape</key>
<string>Rectangle</string>
<key>Style</key>
<dict>
<key>shadow</key>
<dict>
<key>Draws</key>
<string>NO</string>
</dict>
</dict>
<key>Text</key>
<dict>
<key>Text</key>
<string>{\rtf1\ansi\ansicpg1252\cocoartf1265\cocoasubrtf190
\cocoascreenfonts1{\fonttbl\f0\fnil\fcharset0 xkcd-Regular;}
{\colortbl;\red255\green255\blue255;}
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
\f0\fs24 \cf0 Kernel}</string>
</dict>
</dict>
<dict>
<key>Bounds</key>
<string>{{262, 379}, {52, 23.5}}</string>
<key>Class</key>
<string>ShapedGraphic</string>
<key>ID</key>
<integer>4</integer>
<key>Shape</key>
<string>Rectangle</string>
<key>Style</key>
<dict>
<key>shadow</key>
<dict>
<key>Draws</key>
<string>NO</string>
</dict>
</dict>
<key>Text</key>
<dict>
<key>Text</key>
<string>{\rtf1\ansi\ansicpg1252\cocoartf1265\cocoasubrtf190
\cocoascreenfonts1{\fonttbl\f0\fnil\fcharset0 xkcd-Regular;}
{\colortbl;\red255\green255\blue255;}
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
\f0\fs24 \cf0 Kernel}</string>
</dict>
</dict>
<dict>
<key>Bounds</key>
<string>{{262, 348}, {52, 23.5}}</string>
<key>Class</key>
<string>ShapedGraphic</string>
<key>ID</key>
<integer>3</integer>
<key>Shape</key>
<string>Rectangle</string>
<key>Style</key>
<dict>
<key>shadow</key>
<dict>
<key>Draws</key>
<string>NO</string>
</dict>
</dict>
<key>Text</key>
<dict>
<key>Text</key>
<string>{\rtf1\ansi\ansicpg1252\cocoartf1265\cocoasubrtf190
\cocoascreenfonts1{\fonttbl\f0\fnil\fcharset0 xkcd-Regular;}
{\colortbl;\red255\green255\blue255;}
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
\f0\fs24 \cf0 Kernel}</string>
</dict>
</dict>
<dict>
<key>Bounds</key>
<string>{{262, 317}, {52, 23.5}}</string>
<key>Class</key>
<string>ShapedGraphic</string>
<key>ID</key>
<integer>1</integer>
<key>Shape</key>
<string>Rectangle</string>
<key>Style</key>
<dict>
<key>shadow</key>
<dict>
<key>Draws</key>
<string>NO</string>
</dict>
</dict>
<key>Text</key>
<dict>
<key>Text</key>
<string>{\rtf1\ansi\ansicpg1252\cocoartf1265\cocoasubrtf190
\cocoascreenfonts1{\fonttbl\f0\fnil\fcharset0 xkcd-Regular;}
{\colortbl;\red255\green255\blue255;}
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
\f0\fs24 \cf0 Kernel}</string>
</dict>
</dict>
</array>
<key>GridInfo</key>
<dict/>
<key>GuidesLocked</key>
<string>NO</string>
<key>GuidesVisible</key>
<string>YES</string>
<key>HPages</key>
<integer>1</integer>
<key>ImageCounter</key>
<integer>1</integer>
<key>KeepToScale</key>
<false/>
<key>Layers</key>
<array>
<dict>
<key>Lock</key>
<string>NO</string>
<key>Name</key>
<string>Layer 1</string>
<key>Print</key>
<string>YES</string>
<key>View</key>
<string>YES</string>
</dict>
</array>
<key>LayoutInfo</key>
<dict>
<key>Animate</key>
<string>NO</string>
<key>circoMinDist</key>
<real>18</real>
<key>circoSeparation</key>
<real>0.0</real>
<key>layoutEngine</key>
<string>dot</string>
<key>neatoSeparation</key>
<real>0.0</real>
<key>twopiSeparation</key>
<real>0.0</real>
</dict>
<key>LinksVisible</key>
<string>NO</string>
<key>MagnetsVisible</key>
<string>NO</string>
<key>MasterSheets</key>
<array/>
<key>ModificationDate</key>
<string>2014-05-27 22:41:37 +0000</string>
<key>Modifier</key>
<string>bgranger</string>
<key>NotesVisible</key>
<string>NO</string>
<key>Orientation</key>
<integer>2</integer>
<key>OriginVisible</key>
<string>NO</string>
<key>PageBreaks</key>
<string>YES</string>
<key>PrintInfo</key>
<dict>
<key>NSBottomMargin</key>
<array>
<string>float</string>
<string>41</string>
</array>
<key>NSHorizonalPagination</key>
<array>
<string>coded</string>
<string>BAtzdHJlYW10eXBlZIHoA4QBQISEhAhOU051bWJlcgCEhAdOU1ZhbHVlAISECE5TT2JqZWN0AIWEASqEhAFxlwCG</string>
</array>
<key>NSLeftMargin</key>
<array>
<string>float</string>
<string>18</string>
</array>
<key>NSPaperSize</key>
<array>
<string>size</string>
<string>{612, 792}</string>
</array>
<key>NSPrintReverseOrientation</key>
<array>
<string>int</string>
<string>0</string>
</array>
<key>NSRightMargin</key>
<array>
<string>float</string>
<string>18</string>
</array>
<key>NSTopMargin</key>
<array>
<string>float</string>
<string>18</string>
</array>
</dict>
<key>PrintOnePage</key>
<false/>
<key>ReadOnly</key>
<string>NO</string>
<key>RowAlign</key>
<integer>1</integer>
<key>RowSpacing</key>
<real>36</real>
<key>SheetTitle</key>
<string>Canvas 1</string>
<key>SmartAlignmentGuidesActive</key>
<string>YES</string>
<key>SmartDistanceGuidesActive</key>
<string>YES</string>
<key>UniqueID</key>
<integer>1</integer>
<key>UseEntirePage</key>
<false/>
<key>VPages</key>
<integer>1</integer>
<key>WindowInfo</key>
<dict>
<key>CurrentSheet</key>
<integer>0</integer>
<key>ExpandedCanvases</key>
<array>
<dict>
<key>name</key>
<string>Canvas 1</string>
</dict>
</array>
<key>Frame</key>
<string>{{367, 6}, {710, 872}}</string>
<key>ListView</key>
<true/>
<key>OutlineWidth</key>
<integer>142</integer>
<key>RightSidebar</key>
<false/>
<key>ShowRuler</key>
<true/>
<key>Sidebar</key>
<true/>
<key>SidebarWidth</key>
<integer>120</integer>
<key>VisibleRegion</key>
<string>{{0, 0}, {575, 733}}</string>
<key>Zoom</key>
<real>1</real>
<key>ZoomValues</key>
<array>
<array>
<string>Canvas 1</string>
<real>1</real>
<real>1.5</real>
</array>
</array>
</dict>
</dict>
</plist>

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

View File

@ -0,0 +1,426 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>ActiveLayerIndex</key>
<integer>0</integer>
<key>ApplicationVersion</key>
<array>
<string>com.omnigroup.OmniGraffle</string>
<string>139.18.0.187838</string>
</array>
<key>AutoAdjust</key>
<true/>
<key>BackgroundGraphic</key>
<dict>
<key>Bounds</key>
<string>{{0, 0}, {576, 733}}</string>
<key>Class</key>
<string>SolidGraphic</string>
<key>ID</key>
<integer>2</integer>
<key>Style</key>
<dict>
<key>shadow</key>
<dict>
<key>Draws</key>
<string>NO</string>
</dict>
<key>stroke</key>
<dict>
<key>Draws</key>
<string>NO</string>
</dict>
</dict>
</dict>
<key>BaseZoom</key>
<integer>0</integer>
<key>CanvasOrigin</key>
<string>{0, 0}</string>
<key>ColumnAlign</key>
<integer>1</integer>
<key>ColumnSpacing</key>
<real>36</real>
<key>CreationDate</key>
<string>2013-11-07 05:58:18 +0000</string>
<key>Creator</key>
<string>bgranger</string>
<key>DisplayScale</key>
<string>1 0/72 in = 1.0000 in</string>
<key>GraphDocumentVersion</key>
<integer>8</integer>
<key>GraphicsList</key>
<array>
<dict>
<key>Class</key>
<string>LineGraphic</string>
<key>Head</key>
<dict>
<key>ID</key>
<integer>28</integer>
</dict>
<key>ID</key>
<integer>33</integer>
<key>Points</key>
<array>
<string>{241.59308245327554, 385.40907928007584}</string>
<string>{270.40691754672446, 347.59092071992416}</string>
</array>
<key>Style</key>
<dict>
<key>stroke</key>
<dict>
<key>HeadArrow</key>
<string>FilledArrow</string>
<key>Legacy</key>
<true/>
<key>LineType</key>
<integer>1</integer>
<key>TailArrow</key>
<string>0</string>
<key>Width</key>
<real>2</real>
</dict>
</dict>
<key>Tail</key>
<dict>
<key>ID</key>
<integer>30</integer>
</dict>
</dict>
<dict>
<key>Class</key>
<string>LineGraphic</string>
<key>Head</key>
<dict>
<key>ID</key>
<integer>30</integer>
</dict>
<key>ID</key>
<integer>32</integer>
<key>Points</key>
<array>
<string>{313.49998123780057, 408.50001815456494}</string>
<string>{262.50001876219557, 408.50001815456494}</string>
</array>
<key>Style</key>
<dict>
<key>stroke</key>
<dict>
<key>HeadArrow</key>
<string>FilledArrow</string>
<key>Legacy</key>
<true/>
<key>LineType</key>
<integer>1</integer>
<key>TailArrow</key>
<string>0</string>
<key>Width</key>
<real>2</real>
</dict>
</dict>
<key>Tail</key>
<dict>
<key>ID</key>
<integer>29</integer>
</dict>
</dict>
<dict>
<key>Class</key>
<string>LineGraphic</string>
<key>Head</key>
<dict>
<key>ID</key>
<integer>29</integer>
</dict>
<key>ID</key>
<integer>31</integer>
<key>Points</key>
<array>
<string>{305.59308378474134, 347.59092246747298}</string>
<string>{334.40691621525866, 385.40907753252702}</string>
</array>
<key>Style</key>
<dict>
<key>stroke</key>
<dict>
<key>HeadArrow</key>
<string>FilledArrow</string>
<key>Legacy</key>
<true/>
<key>LineType</key>
<integer>1</integer>
<key>TailArrow</key>
<string>0</string>
<key>Width</key>
<real>2</real>
</dict>
</dict>
<key>Tail</key>
<dict>
<key>ID</key>
<integer>28</integer>
</dict>
</dict>
<dict>
<key>Bounds</key>
<string>{{186.5, 383.5}, {75, 50}}</string>
<key>Class</key>
<string>ShapedGraphic</string>
<key>ID</key>
<integer>30</integer>
<key>Shape</key>
<string>Circle</string>
<key>Style</key>
<dict>
<key>shadow</key>
<dict>
<key>Draws</key>
<string>NO</string>
</dict>
<key>stroke</key>
<dict>
<key>Width</key>
<real>2</real>
</dict>
</dict>
<key>Text</key>
<dict>
<key>Text</key>
<string>{\rtf1\ansi\ansicpg1252\cocoartf1265\cocoasubrtf190
\cocoascreenfonts1{\fonttbl\f0\fnil\fcharset0 xkcd-Regular;}
{\colortbl;\red255\green255\blue255;}
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
\f0\fs22 \cf0 ComputE}</string>
<key>VerticalPad</key>
<integer>0</integer>
</dict>
</dict>
<dict>
<key>Bounds</key>
<string>{{314.5, 383.5}, {75, 50}}</string>
<key>Class</key>
<string>ShapedGraphic</string>
<key>ID</key>
<integer>29</integer>
<key>Shape</key>
<string>Circle</string>
<key>Style</key>
<dict>
<key>shadow</key>
<dict>
<key>Draws</key>
<string>NO</string>
</dict>
<key>stroke</key>
<dict>
<key>Width</key>
<real>2</real>
</dict>
</dict>
<key>Text</key>
<dict>
<key>Text</key>
<string>{\rtf1\ansi\ansicpg1252\cocoartf1265\cocoasubrtf190
\cocoascreenfonts1{\fonttbl\f0\fnil\fcharset0 xkcd-Regular;}
{\colortbl;\red255\green255\blue255;}
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
\f0\fs22 \cf0 Interact}</string>
<key>VerticalPad</key>
<integer>0</integer>
</dict>
</dict>
<dict>
<key>Bounds</key>
<string>{{250.5, 299.5}, {75, 50}}</string>
<key>Class</key>
<string>ShapedGraphic</string>
<key>ID</key>
<integer>28</integer>
<key>Shape</key>
<string>Circle</string>
<key>Style</key>
<dict>
<key>shadow</key>
<dict>
<key>Draws</key>
<string>NO</string>
</dict>
<key>stroke</key>
<dict>
<key>Width</key>
<real>2</real>
</dict>
</dict>
<key>Text</key>
<dict>
<key>Text</key>
<string>{\rtf1\ansi\ansicpg1252\cocoartf1265\cocoasubrtf190
\cocoascreenfonts1{\fonttbl\f0\fnil\fcharset0 xkcd-Regular;}
{\colortbl;\red255\green255\blue255;}
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
\f0\fs22 \cf0 Visualize}</string>
<key>VerticalPad</key>
<integer>0</integer>
</dict>
</dict>
</array>
<key>GridInfo</key>
<dict/>
<key>GuidesLocked</key>
<string>NO</string>
<key>GuidesVisible</key>
<string>YES</string>
<key>HPages</key>
<integer>1</integer>
<key>ImageCounter</key>
<integer>1</integer>
<key>KeepToScale</key>
<false/>
<key>Layers</key>
<array>
<dict>
<key>Lock</key>
<string>NO</string>
<key>Name</key>
<string>Layer 1</string>
<key>Print</key>
<string>YES</string>
<key>View</key>
<string>YES</string>
</dict>
</array>
<key>LayoutInfo</key>
<dict>
<key>Animate</key>
<string>NO</string>
<key>circoMinDist</key>
<real>18</real>
<key>circoSeparation</key>
<real>0.0</real>
<key>layoutEngine</key>
<string>dot</string>
<key>neatoSeparation</key>
<real>0.0</real>
<key>twopiSeparation</key>
<real>0.0</real>
</dict>
<key>LinksVisible</key>
<string>NO</string>
<key>MagnetsVisible</key>
<string>NO</string>
<key>MasterSheets</key>
<array/>
<key>ModificationDate</key>
<string>2014-05-28 16:49:32 +0000</string>
<key>Modifier</key>
<string>bgranger</string>
<key>NotesVisible</key>
<string>NO</string>
<key>Orientation</key>
<integer>2</integer>
<key>OriginVisible</key>
<string>NO</string>
<key>PageBreaks</key>
<string>YES</string>
<key>PrintInfo</key>
<dict>
<key>NSBottomMargin</key>
<array>
<string>float</string>
<string>41</string>
</array>
<key>NSHorizonalPagination</key>
<array>
<string>coded</string>
<string>BAtzdHJlYW10eXBlZIHoA4QBQISEhAhOU051bWJlcgCEhAdOU1ZhbHVlAISECE5TT2JqZWN0AIWEASqEhAFxlwCG</string>
</array>
<key>NSLeftMargin</key>
<array>
<string>float</string>
<string>18</string>
</array>
<key>NSPaperSize</key>
<array>
<string>size</string>
<string>{612, 792}</string>
</array>
<key>NSPrintReverseOrientation</key>
<array>
<string>int</string>
<string>0</string>
</array>
<key>NSRightMargin</key>
<array>
<string>float</string>
<string>18</string>
</array>
<key>NSTopMargin</key>
<array>
<string>float</string>
<string>18</string>
</array>
</dict>
<key>PrintOnePage</key>
<false/>
<key>ReadOnly</key>
<string>NO</string>
<key>RowAlign</key>
<integer>1</integer>
<key>RowSpacing</key>
<real>36</real>
<key>SheetTitle</key>
<string>Canvas 1</string>
<key>SmartAlignmentGuidesActive</key>
<string>YES</string>
<key>SmartDistanceGuidesActive</key>
<string>YES</string>
<key>UniqueID</key>
<integer>1</integer>
<key>UseEntirePage</key>
<false/>
<key>VPages</key>
<integer>1</integer>
<key>WindowInfo</key>
<dict>
<key>CurrentSheet</key>
<integer>0</integer>
<key>ExpandedCanvases</key>
<array>
<dict>
<key>name</key>
<string>Canvas 1</string>
</dict>
</array>
<key>Frame</key>
<string>{{340, 6}, {710, 872}}</string>
<key>ListView</key>
<true/>
<key>OutlineWidth</key>
<integer>142</integer>
<key>RightSidebar</key>
<false/>
<key>ShowRuler</key>
<true/>
<key>Sidebar</key>
<true/>
<key>SidebarWidth</key>
<integer>120</integer>
<key>VisibleRegion</key>
<string>{{0, 0}, {575, 733}}</string>
<key>Zoom</key>
<real>1</real>
<key>ZoomValues</key>
<array>
<array>
<string>Canvas 1</string>
<real>1</real>
<real>1</real>
</array>
</array>
</dict>
</dict>
</plist>

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

View File

@ -0,0 +1,322 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>ActiveLayerIndex</key>
<integer>0</integer>
<key>ApplicationVersion</key>
<array>
<string>com.omnigroup.OmniGraffle</string>
<string>139.18.0.187838</string>
</array>
<key>AutoAdjust</key>
<true/>
<key>BackgroundGraphic</key>
<dict>
<key>Bounds</key>
<string>{{0, 0}, {576, 733}}</string>
<key>Class</key>
<string>SolidGraphic</string>
<key>ID</key>
<integer>2</integer>
<key>Style</key>
<dict>
<key>shadow</key>
<dict>
<key>Draws</key>
<string>NO</string>
</dict>
<key>stroke</key>
<dict>
<key>Draws</key>
<string>NO</string>
</dict>
</dict>
</dict>
<key>BaseZoom</key>
<integer>0</integer>
<key>CanvasOrigin</key>
<string>{0, 0}</string>
<key>ColumnAlign</key>
<integer>1</integer>
<key>ColumnSpacing</key>
<real>36</real>
<key>CreationDate</key>
<string>2013-11-09 20:06:39 +0000</string>
<key>Creator</key>
<string>bgranger</string>
<key>DisplayScale</key>
<string>1 0/72 in = 1.0000 in</string>
<key>GraphDocumentVersion</key>
<integer>8</integer>
<key>GraphicsList</key>
<array>
<dict>
<key>Bounds</key>
<string>{{212.5, 269.5}, {124.5, 40}}</string>
<key>Class</key>
<string>ShapedGraphic</string>
<key>ID</key>
<integer>5</integer>
<key>Shape</key>
<string>Rectangle</string>
<key>Style</key>
<dict>
<key>shadow</key>
<dict>
<key>Draws</key>
<string>NO</string>
</dict>
</dict>
<key>Text</key>
<dict>
<key>Text</key>
<string>{\rtf1\ansi\ansicpg1252\cocoartf1265\cocoasubrtf190
\cocoascreenfonts1{\fonttbl\f0\fnil\fcharset0 xkcd-Regular;}
{\colortbl;\red255\green255\blue255;}
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
\f0\fs24 \cf0 Interact}</string>
</dict>
</dict>
<dict>
<key>Bounds</key>
<string>{{212.5, 318}, {124.5, 40}}</string>
<key>Class</key>
<string>ShapedGraphic</string>
<key>ID</key>
<integer>4</integer>
<key>Shape</key>
<string>Rectangle</string>
<key>Style</key>
<dict>
<key>shadow</key>
<dict>
<key>Draws</key>
<string>NO</string>
</dict>
</dict>
<key>Text</key>
<dict>
<key>Text</key>
<string>{\rtf1\ansi\ansicpg1252\cocoartf1265\cocoasubrtf190
\cocoascreenfonts1{\fonttbl\f0\fnil\fcharset0 xkcd-Regular;}
{\colortbl;\red255\green255\blue255;}
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
\f0\fs24 \cf0 Widgets}</string>
</dict>
</dict>
<dict>
<key>Bounds</key>
<string>{{212.5, 366.5}, {124.5, 40}}</string>
<key>Class</key>
<string>ShapedGraphic</string>
<key>ID</key>
<integer>3</integer>
<key>Shape</key>
<string>Rectangle</string>
<key>Style</key>
<dict>
<key>shadow</key>
<dict>
<key>Draws</key>
<string>NO</string>
</dict>
</dict>
<key>Text</key>
<dict>
<key>Text</key>
<string>{\rtf1\ansi\ansicpg1252\cocoartf1265\cocoasubrtf190
\cocoascreenfonts1{\fonttbl\f0\fnil\fcharset0 xkcd-Regular;}
{\colortbl;\red255\green255\blue255;}
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
\f0\fs24 \cf0 Comm}</string>
</dict>
</dict>
<dict>
<key>Bounds</key>
<string>{{212.5, 415}, {124.5, 40}}</string>
<key>Class</key>
<string>ShapedGraphic</string>
<key>ID</key>
<integer>1</integer>
<key>Shape</key>
<string>Rectangle</string>
<key>Style</key>
<dict>
<key>shadow</key>
<dict>
<key>Draws</key>
<string>NO</string>
</dict>
</dict>
<key>Text</key>
<dict>
<key>Text</key>
<string>{\rtf1\ansi\ansicpg1252\cocoartf1265\cocoasubrtf190
\cocoascreenfonts1{\fonttbl\f0\fnil\fcharset0 xkcd-Regular;}
{\colortbl;\red255\green255\blue255;}
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
\f0\fs24 \cf0 WebSockets/ZeroMQ}</string>
</dict>
</dict>
</array>
<key>GridInfo</key>
<dict/>
<key>GuidesLocked</key>
<string>NO</string>
<key>GuidesVisible</key>
<string>YES</string>
<key>HPages</key>
<integer>1</integer>
<key>ImageCounter</key>
<integer>1</integer>
<key>KeepToScale</key>
<false/>
<key>Layers</key>
<array>
<dict>
<key>Lock</key>
<string>NO</string>
<key>Name</key>
<string>Layer 1</string>
<key>Print</key>
<string>YES</string>
<key>View</key>
<string>YES</string>
</dict>
</array>
<key>LayoutInfo</key>
<dict>
<key>Animate</key>
<string>NO</string>
<key>circoMinDist</key>
<real>18</real>
<key>circoSeparation</key>
<real>0.0</real>
<key>layoutEngine</key>
<string>dot</string>
<key>neatoSeparation</key>
<real>0.0</real>
<key>twopiSeparation</key>
<real>0.0</real>
</dict>
<key>LinksVisible</key>
<string>NO</string>
<key>MagnetsVisible</key>
<string>NO</string>
<key>MasterSheets</key>
<array/>
<key>ModificationDate</key>
<string>2014-05-28 16:53:16 +0000</string>
<key>Modifier</key>
<string>bgranger</string>
<key>NotesVisible</key>
<string>NO</string>
<key>Orientation</key>
<integer>2</integer>
<key>OriginVisible</key>
<string>NO</string>
<key>PageBreaks</key>
<string>YES</string>
<key>PrintInfo</key>
<dict>
<key>NSBottomMargin</key>
<array>
<string>float</string>
<string>41</string>
</array>
<key>NSHorizonalPagination</key>
<array>
<string>coded</string>
<string>BAtzdHJlYW10eXBlZIHoA4QBQISEhAhOU051bWJlcgCEhAdOU1ZhbHVlAISECE5TT2JqZWN0AIWEASqEhAFxlwCG</string>
</array>
<key>NSLeftMargin</key>
<array>
<string>float</string>
<string>18</string>
</array>
<key>NSPaperSize</key>
<array>
<string>size</string>
<string>{612, 792}</string>
</array>
<key>NSPrintReverseOrientation</key>
<array>
<string>int</string>
<string>0</string>
</array>
<key>NSRightMargin</key>
<array>
<string>float</string>
<string>18</string>
</array>
<key>NSTopMargin</key>
<array>
<string>float</string>
<string>18</string>
</array>
</dict>
<key>PrintOnePage</key>
<false/>
<key>ReadOnly</key>
<string>NO</string>
<key>RowAlign</key>
<integer>1</integer>
<key>RowSpacing</key>
<real>36</real>
<key>SheetTitle</key>
<string>Canvas 1</string>
<key>SmartAlignmentGuidesActive</key>
<string>YES</string>
<key>SmartDistanceGuidesActive</key>
<string>YES</string>
<key>UniqueID</key>
<integer>1</integer>
<key>UseEntirePage</key>
<false/>
<key>VPages</key>
<integer>1</integer>
<key>WindowInfo</key>
<dict>
<key>CurrentSheet</key>
<integer>0</integer>
<key>ExpandedCanvases</key>
<array>
<dict>
<key>name</key>
<string>Canvas 1</string>
</dict>
</array>
<key>Frame</key>
<string>{{367, 6}, {710, 872}}</string>
<key>ListView</key>
<true/>
<key>OutlineWidth</key>
<integer>142</integer>
<key>RightSidebar</key>
<false/>
<key>ShowRuler</key>
<true/>
<key>Sidebar</key>
<true/>
<key>SidebarWidth</key>
<integer>120</integer>
<key>VisibleRegion</key>
<string>{{143.5, 183}, {287.5, 366.5}}</string>
<key>Zoom</key>
<real>2</real>
<key>ZoomValues</key>
<array>
<array>
<string>Canvas 1</string>
<real>2</real>
<real>1</real>
</array>
</array>
</dict>
</dict>
</plist>

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

View File

@ -0,0 +1,523 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>ActiveLayerIndex</key>
<integer>0</integer>
<key>ApplicationVersion</key>
<array>
<string>com.omnigroup.OmniGraffle</string>
<string>139.18.0.187838</string>
</array>
<key>AutoAdjust</key>
<true/>
<key>BackgroundGraphic</key>
<dict>
<key>Bounds</key>
<string>{{0, 0}, {576, 733}}</string>
<key>Class</key>
<string>SolidGraphic</string>
<key>ID</key>
<integer>2</integer>
<key>Style</key>
<dict>
<key>shadow</key>
<dict>
<key>Draws</key>
<string>NO</string>
</dict>
<key>stroke</key>
<dict>
<key>Draws</key>
<string>NO</string>
</dict>
</dict>
</dict>
<key>BaseZoom</key>
<integer>0</integer>
<key>CanvasOrigin</key>
<string>{0, 0}</string>
<key>ColumnAlign</key>
<integer>1</integer>
<key>ColumnSpacing</key>
<real>36</real>
<key>CreationDate</key>
<string>2014-07-06 03:46:05 +0000</string>
<key>Creator</key>
<string>bgranger</string>
<key>DisplayScale</key>
<string>1 0/72 in = 1 0/72 in</string>
<key>GraphDocumentVersion</key>
<integer>8</integer>
<key>GraphicsList</key>
<array>
<dict>
<key>Bounds</key>
<string>{{230.33332316080816, 214.66666666666825}, {171, 15}}</string>
<key>Class</key>
<string>ShapedGraphic</string>
<key>FitText</key>
<string>YES</string>
<key>Flow</key>
<string>Resize</string>
<key>ID</key>
<integer>21</integer>
<key>Shape</key>
<string>Rectangle</string>
<key>Style</key>
<dict>
<key>fill</key>
<dict>
<key>Draws</key>
<string>NO</string>
</dict>
<key>shadow</key>
<dict>
<key>Draws</key>
<string>NO</string>
</dict>
<key>stroke</key>
<dict>
<key>Draws</key>
<string>NO</string>
</dict>
</dict>
<key>Text</key>
<dict>
<key>Pad</key>
<integer>0</integer>
<key>Text</key>
<string>{\rtf1\ansi\ansicpg1252\cocoartf1265\cocoasubrtf200
\cocoascreenfonts1{\fonttbl\f0\fnil\fcharset0 xkcd-Regular;}
{\colortbl;\red255\green255\blue255;}
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
\f0\fs24 \cf0 frontend (HTML/JavaScript)}</string>
<key>VerticalPad</key>
<integer>0</integer>
</dict>
<key>Wrap</key>
<string>NO</string>
</dict>
<dict>
<key>Bounds</key>
<string>{{70.166664123535156, 214.66667683919241}, {95, 15}}</string>
<key>Class</key>
<string>ShapedGraphic</string>
<key>FitText</key>
<string>YES</string>
<key>Flow</key>
<string>Resize</string>
<key>ID</key>
<integer>20</integer>
<key>Shape</key>
<string>Rectangle</string>
<key>Style</key>
<dict>
<key>fill</key>
<dict>
<key>Draws</key>
<string>NO</string>
</dict>
<key>shadow</key>
<dict>
<key>Draws</key>
<string>NO</string>
</dict>
<key>stroke</key>
<dict>
<key>Draws</key>
<string>NO</string>
</dict>
</dict>
<key>Text</key>
<dict>
<key>Pad</key>
<integer>0</integer>
<key>Text</key>
<string>{\rtf1\ansi\ansicpg1252\cocoartf1265\cocoasubrtf200
\cocoascreenfonts1{\fonttbl\f0\fnil\fcharset0 xkcd-Regular;}
{\colortbl;\red255\green255\blue255;}
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
\f0\fs24 \cf0 Kernel (Python)}</string>
<key>VerticalPad</key>
<integer>0</integer>
</dict>
<key>Wrap</key>
<string>NO</string>
</dict>
<dict>
<key>Class</key>
<string>LineGraphic</string>
<key>Head</key>
<dict>
<key>ID</key>
<integer>8</integer>
</dict>
<key>ID</key>
<integer>18</integer>
<key>Points</key>
<array>
<string>{302.62321350991539, 355.71147093607129}</string>
<string>{329.06618954727776, 386.2881834750354}</string>
</array>
<key>Style</key>
<dict>
<key>stroke</key>
<dict>
<key>HeadArrow</key>
<string>FilledArrow</string>
<key>Legacy</key>
<true/>
<key>Pattern</key>
<integer>1</integer>
<key>TailArrow</key>
<string>FilledArrow</string>
</dict>
</dict>
<key>Tail</key>
<dict>
<key>ID</key>
<integer>6</integer>
</dict>
</dict>
<dict>
<key>Class</key>
<string>LineGraphic</string>
<key>Head</key>
<dict>
<key>ID</key>
<integer>7</integer>
</dict>
<key>ID</key>
<integer>16</integer>
<key>Points</key>
<array>
<string>{302.60973386333222, 314.95496159151998}</string>
<string>{329.03248543221167, 284.3780603888232}</string>
</array>
<key>Style</key>
<dict>
<key>stroke</key>
<dict>
<key>HeadArrow</key>
<string>FilledArrow</string>
<key>Legacy</key>
<true/>
<key>Pattern</key>
<integer>1</integer>
<key>TailArrow</key>
<string>FilledArrow</string>
</dict>
</dict>
<key>Tail</key>
<dict>
<key>ID</key>
<integer>6</integer>
</dict>
</dict>
<dict>
<key>Class</key>
<string>LineGraphic</string>
<key>Head</key>
<dict>
<key>ID</key>
<integer>6</integer>
</dict>
<key>ID</key>
<integer>15</integer>
<key>Points</key>
<array>
<string>{143.33332567510072, 335.32575675071013}</string>
<string>{229.83332831581788, 335.30805933679687}</string>
</array>
<key>Style</key>
<dict>
<key>stroke</key>
<dict>
<key>HeadArrow</key>
<string>FilledArrow</string>
<key>Legacy</key>
<true/>
<key>Pattern</key>
<integer>1</integer>
<key>TailArrow</key>
<string>FilledArrow</string>
</dict>
</dict>
<key>Tail</key>
<dict>
<key>ID</key>
<integer>5</integer>
</dict>
</dict>
<dict>
<key>Bounds</key>
<string>{{291.99996948242188, 386.66658655802428}, {109.33333587646484, 40}}</string>
<key>Class</key>
<string>ShapedGraphic</string>
<key>ID</key>
<integer>8</integer>
<key>Shape</key>
<string>Rectangle</string>
<key>Style</key>
<dict>
<key>shadow</key>
<dict>
<key>Draws</key>
<string>NO</string>
</dict>
</dict>
<key>Text</key>
<dict>
<key>Text</key>
<string>{\rtf1\ansi\ansicpg1252\cocoartf1265\cocoasubrtf200
\cocoascreenfonts1{\fonttbl\f0\fnil\fcharset0 xkcd-Regular;}
{\colortbl;\red255\green255\blue255;}
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
\f0\fs24 \cf0 widget View}</string>
</dict>
</dict>
<dict>
<key>Bounds</key>
<string>{{291.99998982747394, 243.99996948241886}, {109.33333587646484, 40}}</string>
<key>Class</key>
<string>ShapedGraphic</string>
<key>ID</key>
<integer>7</integer>
<key>Shape</key>
<string>Rectangle</string>
<key>Style</key>
<dict>
<key>shadow</key>
<dict>
<key>Draws</key>
<string>NO</string>
</dict>
</dict>
<key>Text</key>
<dict>
<key>Text</key>
<string>{\rtf1\ansi\ansicpg1252\cocoartf1265\cocoasubrtf200
\cocoascreenfonts1{\fonttbl\f0\fnil\fcharset0 xkcd-Regular;}
{\colortbl;\red255\green255\blue255;}
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
\f0\fs24 \cf0 widget View}</string>
</dict>
</dict>
<dict>
<key>Bounds</key>
<string>{{230.33332824706363, 315.33327865600415}, {109.33333587646484, 40}}</string>
<key>Class</key>
<string>ShapedGraphic</string>
<key>ID</key>
<integer>6</integer>
<key>Shape</key>
<string>Rectangle</string>
<key>Style</key>
<dict>
<key>shadow</key>
<dict>
<key>Draws</key>
<string>NO</string>
</dict>
</dict>
<key>Text</key>
<dict>
<key>Text</key>
<string>{\rtf1\ansi\ansicpg1252\cocoartf1265\cocoasubrtf200
\cocoascreenfonts1{\fonttbl\f0\fnil\fcharset0 xkcd-Regular;}
{\colortbl;\red255\green255\blue255;}
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
\f0\fs24 \cf0 widget model}</string>
</dict>
</dict>
<dict>
<key>Bounds</key>
<string>{{70.166661580401851, 315.33329264322913}, {72.666664123535156, 40}}</string>
<key>Class</key>
<string>ShapedGraphic</string>
<key>ID</key>
<integer>5</integer>
<key>Shape</key>
<string>Rectangle</string>
<key>Style</key>
<dict>
<key>shadow</key>
<dict>
<key>Draws</key>
<string>NO</string>
</dict>
</dict>
<key>Text</key>
<dict>
<key>Text</key>
<string>{\rtf1\ansi\ansicpg1252\cocoartf1265\cocoasubrtf200
\cocoascreenfonts1{\fonttbl\f0\fnil\fcharset0 xkcd-Regular;}
{\colortbl;\red255\green255\blue255;}
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
\f0\fs24 \cf0 widget}</string>
</dict>
</dict>
</array>
<key>GridInfo</key>
<dict/>
<key>GuidesLocked</key>
<string>NO</string>
<key>GuidesVisible</key>
<string>YES</string>
<key>HPages</key>
<integer>1</integer>
<key>ImageCounter</key>
<integer>1</integer>
<key>KeepToScale</key>
<false/>
<key>Layers</key>
<array>
<dict>
<key>Lock</key>
<string>NO</string>
<key>Name</key>
<string>Layer 1</string>
<key>Print</key>
<string>YES</string>
<key>View</key>
<string>YES</string>
</dict>
</array>
<key>LayoutInfo</key>
<dict>
<key>Animate</key>
<string>NO</string>
<key>circoMinDist</key>
<real>18</real>
<key>circoSeparation</key>
<real>0.0</real>
<key>layoutEngine</key>
<string>dot</string>
<key>neatoSeparation</key>
<real>0.0</real>
<key>twopiSeparation</key>
<real>0.0</real>
</dict>
<key>LinksVisible</key>
<string>NO</string>
<key>MagnetsVisible</key>
<string>NO</string>
<key>MasterSheets</key>
<array/>
<key>ModificationDate</key>
<string>2014-07-06 03:57:02 +0000</string>
<key>Modifier</key>
<string>bgranger</string>
<key>NotesVisible</key>
<string>NO</string>
<key>Orientation</key>
<integer>2</integer>
<key>OriginVisible</key>
<string>NO</string>
<key>PageBreaks</key>
<string>YES</string>
<key>PrintInfo</key>
<dict>
<key>NSBottomMargin</key>
<array>
<string>float</string>
<string>41</string>
</array>
<key>NSHorizonalPagination</key>
<array>
<string>coded</string>
<string>BAtzdHJlYW10eXBlZIHoA4QBQISEhAhOU051bWJlcgCEhAdOU1ZhbHVlAISECE5TT2JqZWN0AIWEASqEhAFxlwCG</string>
</array>
<key>NSLeftMargin</key>
<array>
<string>float</string>
<string>18</string>
</array>
<key>NSPaperSize</key>
<array>
<string>size</string>
<string>{612, 792}</string>
</array>
<key>NSPrintReverseOrientation</key>
<array>
<string>int</string>
<string>0</string>
</array>
<key>NSRightMargin</key>
<array>
<string>float</string>
<string>18</string>
</array>
<key>NSTopMargin</key>
<array>
<string>float</string>
<string>18</string>
</array>
</dict>
<key>PrintOnePage</key>
<false/>
<key>ReadOnly</key>
<string>NO</string>
<key>RowAlign</key>
<integer>1</integer>
<key>RowSpacing</key>
<real>36</real>
<key>SheetTitle</key>
<string>Canvas 1</string>
<key>SmartAlignmentGuidesActive</key>
<string>YES</string>
<key>SmartDistanceGuidesActive</key>
<string>YES</string>
<key>UniqueID</key>
<integer>1</integer>
<key>UseEntirePage</key>
<false/>
<key>VPages</key>
<integer>1</integer>
<key>WindowInfo</key>
<dict>
<key>CurrentSheet</key>
<integer>0</integer>
<key>ExpandedCanvases</key>
<array>
<dict>
<key>name</key>
<string>Canvas 1</string>
</dict>
</array>
<key>Frame</key>
<string>{{17, 3}, {1112, 875}}</string>
<key>ListView</key>
<false/>
<key>OutlineWidth</key>
<integer>142</integer>
<key>RightSidebar</key>
<true/>
<key>ShowRuler</key>
<true/>
<key>Sidebar</key>
<true/>
<key>SidebarWidth</key>
<integer>120</integer>
<key>VisibleRegion</key>
<string>{{0, 105.33333333333333}, {556, 490.66666666666669}}</string>
<key>Zoom</key>
<real>1.5</real>
<key>ZoomValues</key>
<array>
<array>
<string>Canvas 1</string>
<real>1.5</real>
<real>1</real>
</array>
</array>
</dict>
</dict>
</plist>

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

View File

@ -0,0 +1,496 @@
{
"metadata": {
"name": ""
},
"nbformat": 3,
"nbformat_minor": 0,
"worksheets": [
{
"cells": [
{
"cell_type": "heading",
"level": 1,
"metadata": {},
"source": [
"NbConvert"
]
},
{
"cell_type": "heading",
"level": 2,
"metadata": {},
"source": [
"Command line usage"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"`NbConvert` is the library, and the command line tool that allow to convert from notebook to other formats.\n",
"It is a technological preview in 1.0 but is already usable and highly configurable.\n",
"It ships already with many default available formats : `html`, `latex`, `markdown`, `python`, `rst` and `slides`\n",
"which are fully base on Jinja templating engine, so writing a converter for your custom format or tweeking the existing \n",
"one should be extra simple."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"You can invoke nbconvert by doing\n",
"\n",
"```bash\n",
"$ ipython nbconvert <options and arguments>\n",
"```\n",
"\n",
"Call `ipython nbconvert` with the `--help` flag or no aruments to get basic help on how to use it.\n",
"For more information about configuration use the `--help-all` flag"
]
},
{
"cell_type": "heading",
"level": 3,
"metadata": {},
"source": [
"Basic export"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We will be converting `Custom Display Logic.ipynb`. \n",
"Be sure to have runed some of the cells in it to have output otherwise you will only see input in nbconvert.\n",
"Nbconvert **do not execute the code** in the notebook files, it only converts what is inside."
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"%%bash\n",
"ipython nbconvert '04 - Custom Display Logic.ipynb'"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stderr",
"text": [
"[NbConvertApp] Using existing profile dir: u'/Users/bussonniermatthias/.ipython/profile_default'\n",
"[NbConvertApp] Converting notebook 04 - Custom Display Logic.ipynb to html\n",
"[NbConvertApp] Support files will be in 04 - Custom Display Logic_files/\n",
"[NbConvertApp] Loaded template html_full.tpl\n",
"[NbConvertApp] Writing 221081 bytes to 04 - Custom Display Logic.html\n"
]
}
],
"prompt_number": 1
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Html is the default value (that can be configured) , so the verbose form would be "
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"%%bash\n",
"ipython nbconvert --to=html '04 - Custom Display Logic.ipynb'"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stderr",
"text": [
"[NbConvertApp] Using existing profile dir: u'/Users/bussonniermatthias/.ipython/profile_default'\n",
"[NbConvertApp] Converting notebook 04 - Custom Display Logic.ipynb to html\n",
"[NbConvertApp] Support files will be in 04 - Custom Display Logic_files/\n",
"[NbConvertApp] Loaded template html_full.tpl\n",
"[NbConvertApp] Writing 221081 bytes to 04 - Custom Display Logic.html\n"
]
}
],
"prompt_number": 2
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"You can also convert to latex, which will take care of extractin the embeded base64 encoded png, or the svg and call inkscape to convert those svg to pdf if necessary :"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"%%bash\n",
"ipython nbconvert --to=latex '04 - Custom Display Logic.ipynb'"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stderr",
"text": [
"[NbConvertApp] Using existing profile dir: u'/Users/bussonniermatthias/.ipython/profile_default'\n",
"[NbConvertApp] Converting notebook 04 - Custom Display Logic.ipynb to latex\n",
"[NbConvertApp] Support files will be in 04 - Custom Display Logic_files/\n",
"Setting Language: .UTF-8\n",
"\n",
"(process:26432): Gtk-WARNING **: Locale not supported by C library.\n",
"\tUsing the fallback 'C' locale.\n",
"Setting Language: .UTF-8\n",
"\n",
"(process:26472): Gtk-WARNING **: Locale not supported by C library.\n",
"\tUsing the fallback 'C' locale.\n",
"Setting Language: .UTF-8\n",
"\n",
"(process:26512): Gtk-WARNING **: Locale not supported by C library.\n",
"\tUsing the fallback 'C' locale.\n",
"Setting Language: .UTF-8\n",
"\n",
"(process:26552): Gtk-WARNING **: Locale not supported by C library.\n",
"\tUsing the fallback 'C' locale.\n",
"Setting Language: .UTF-8\n",
"\n",
"(process:26592): Gtk-WARNING **: Locale not supported by C library.\n",
"\tUsing the fallback 'C' locale.\n",
"[NbConvertApp] Loaded template latex_article.tplx\n",
"[NbConvertApp] Writing 41196 bytes to 04 - Custom Display Logic.tex\n"
]
}
],
"prompt_number": 3
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"You should just have to compile the generated `.tex` file. If you get the required packages installed, if should compile out of the box.\n",
"\n",
"For convenience we allow to run extra action after the conversion has been done, in particular for `latex` we have a `pdf` post-processor. \n",
"You can define the postprocessor tu run with the `--post` flag."
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"%%bash\n",
"ipython nbconvert --to=latex '04 - Custom Display Logic.ipynb' --post=pdf"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stderr",
"text": [
"[NbConvertApp] Using existing profile dir: u'/Users/bussonniermatthias/.ipython/profile_default'\n",
"[NbConvertApp] Converting notebook 04 - Custom Display Logic.ipynb to latex\n",
"[NbConvertApp] Support files will be in 04 - Custom Display Logic_files/\n",
"Setting Language: .UTF-8\n",
"\n",
"(process:26658): Gtk-WARNING **: Locale not supported by C library.\n",
"\tUsing the fallback 'C' locale.\n",
"Setting Language: .UTF-8\n",
"\n",
"(process:26698): Gtk-WARNING **: Locale not supported by C library.\n",
"\tUsing the fallback 'C' locale.\n",
"Setting Language: .UTF-8\n",
"\n",
"(process:26738): Gtk-WARNING **: Locale not supported by C library.\n",
"\tUsing the fallback 'C' locale.\n",
"Setting Language: .UTF-8\n",
"\n",
"(process:26778): Gtk-WARNING **: Locale not supported by C library.\n",
"\tUsing the fallback 'C' locale.\n",
"Setting Language: .UTF-8\n",
"\n",
"(process:26818): Gtk-WARNING **: Locale not supported by C library.\n",
"\tUsing the fallback 'C' locale.\n",
"[NbConvertApp] Loaded template latex_article.tplx\n",
"[NbConvertApp] Writing 41196 bytes to 04 - Custom Display Logic.tex\n",
"[NbConvertApp] Building PDF: ['pdflatex', '04 - Custom Display Logic.tex']\n"
]
}
],
"prompt_number": 4
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Have a look at `04 - Custom Display Logic.pdf`, toward the end, where we compared `display()` vs `display_html()` and returning the object.\n",
"See how the cell where we use `display_html` was not able to display the circle, whereas the two other ones were able to select one of the oher representation they know how to display."
]
},
{
"cell_type": "heading",
"level": 3,
"metadata": {},
"source": [
"Customizing template"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"let's look at the first 20 lines of the `python` exporter"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"pyfile = !ipython nbconvert --to python '04 - Custom Display Logic.ipynb' --stdout\n",
"for l in pyfile[20:40]:\n",
" print l"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"# 1. Implementing special display methods such as `_repr_html_`.\n",
"# 2. Registering a display function for a particular type.\n",
"# \n",
"# In this Notebook we show how both approaches work.\n",
"\n",
"# Before we get started, we will import the various display functions for displaying the different formats we will create.\n",
"\n",
"# In[54]:\n",
"\n",
"from IPython.display import display\n",
"from IPython.display import (\n",
" display_html, display_jpeg, display_png,\n",
" display_javascript, display_svg, display_latex\n",
")\n",
"\n",
"\n",
"### Implementing special display methods\n",
"\n",
"# The main idea of the first approach is that you have to implement special display methods, one for each representation you want to use. Here is a list of the names of the special methods and the values they must return:\n",
"# \n"
]
}
],
"prompt_number": 5
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We see that the non-code cell are exported to the file. To have a cleaner script, we will export only the code contained in the code cells.\n",
"\n",
"To do so, we will inherit the python template, and overwrite the markdown blocks to be empty."
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"%%writefile simplepython.tpl\n",
"{% extends 'python.tpl'%}\n",
"\n",
"{% block markdowncell -%}\n",
"{% endblock markdowncell %}\n",
"\n",
"## we also want to get rig of header cell\n",
"{% block headingcell -%}\n",
"{% endblock headingcell %}\n",
"\n",
"## and let's change the appearance of input prompt\n",
"{% block in_prompt %}\n",
"# This was input cell with prompt number : {{ cell.prompt_number if cell.prompt_number else ' ' }}\n",
"{%- endblock in_prompt %}"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"Overwriting simplepython.tpl\n"
]
}
],
"prompt_number": 6
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"pyfile = !ipython nbconvert --to python '04 - Custom Display Logic.ipynb' --stdout --template=simplepython.tpl\n",
"\n",
"for l in pyfile[4:40]:\n",
" print l\n",
"print '...'"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"\n",
"# This was input cell with prompt number : 54\n",
"from IPython.display import display\n",
"from IPython.display import (\n",
" display_html, display_jpeg, display_png,\n",
" display_javascript, display_svg, display_latex\n",
")\n",
"\n",
"\n",
"# This was input cell with prompt number : 55\n",
"get_ipython().magic(u'load soln/mycircle.py')\n",
"\n",
"\n",
"# This was input cell with prompt number : 56\n",
"class MyCircle(object):\n",
" \n",
" def _repr_html_(self):\n",
" return \"&#x25CB; (<b>html</b>)\"\n",
"\n",
" def _repr_svg_(self):\n",
" return \"\"\"<svg width='100px' height='100px'>\n",
" <circle cx=\"50\" cy=\"50\" r=\"20\" stroke=\"black\" stroke-width=\"1\" fill=\"blue\"/>\n",
" </svg>\"\"\"\n",
" \n",
" def _repr_latex_(self):\n",
" return r\"$\\bigcirc \\LaTeX$\"\n",
"\n",
" def _repr_javascript_(self):\n",
" return \"alert('I am a circle!');\"\n",
"\n",
"\n",
"# This was input cell with prompt number : 57\n",
"c = MyCircle()\n",
"\n",
"\n",
"# This was input cell with prompt number : 58\n",
"...\n"
]
}
],
"prompt_number": 7
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"I'll let you read Jinja manual for the exact syntax of the template."
]
},
{
"cell_type": "heading",
"level": 2,
"metadata": {},
"source": [
"Template that use cells metadata"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Notebook fileformat support attaching arbitrary JSON metadata to each cell of a notebook. In this part we will use those metadata."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"First you need to choose another notebook you want to convert to html, and tag some of the cell with metadata.\n",
"You can see the file `soln/celldiff.js` for a solution on how to tag, or follow the javascript tutorial to see how to do that. Use what we have written there to tag cells of some notebooks to `Easy`|`Medium`|`Hard`|`<None>`, and convert this notebook using your template."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"you might need the following : \n",
"```\n",
"{% extends 'html_full.tpl'%}\n",
"{% block any_cell %}\n",
"{{ super() }}\n",
"<div style=\"background-color:red\">\n",
"<div style='background-color:orange'>\n",
"```\n",
"\n",
"`metadata` might not exist, be sure to :\n",
"\n",
"`cell['metadata'].get('example',{}).get('difficulty','')`\n",
"\n",
"tip: use `%%writefile` to edit the template in the notebook :-)"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"%%bash\n",
"# ipython nbconvert --to html <your chosen notebook.ipynb> --template=<your template file>"
],
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 8
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"%loadpy soln/coloreddiff.tpl"
],
"language": "python",
"metadata": {},
"outputs": []
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"# ipython nbconvert --to html '04 - Custom Display Logic.ipynb' --template=soln/coloreddiff.tpl"
],
"language": "python",
"metadata": {},
"outputs": []
},
{
"cell_type": "heading",
"level": 3,
"metadata": {},
"source": [
"Get rid of all command line flags."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"As of all of IPython nbconvert can be configured using profiles and passing the `--profile` flag. \n",
"Moreover if a `config.py` file exist in current working directory nbconvert will use that, or read the config file you give to it with the `--config=<file>` flag. \n",
"\n",
"In the end, if you are often running nbconvert on the sam project, `$ ipython nbconvert` should be enough to get you up and ready."
]
}
],
"metadata": {}
}
]
}

View File

@ -0,0 +1,149 @@
{
"metadata": {
"name": ""
},
"nbformat": 3,
"nbformat_minor": 0,
"worksheets": [
{
"cells": [
{
"cell_type": "heading",
"level": 1,
"metadata": {},
"source": [
"Keyboard Shortcut Customization"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Starting with IPython 2.0 keyboard shortcuts in command and edit mode are fully customizable. These customizations are made using the IPython JavaScript API. Here is an example that makes the `r` key available for running a cell:"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"%%javascript\n",
"\n",
"IPython.keyboard_manager.command_shortcuts.add_shortcut('r', {\n",
" help : 'run cell',\n",
" help_index : 'zz',\n",
" handler : function (event) {\n",
" IPython.notebook.execute_cell();\n",
" return false;\n",
" }}\n",
");"
],
"language": "python",
"metadata": {},
"outputs": [
{
"javascript": [
"\n",
"IPython.keyboard_manager.command_shortcuts.add_shortcut('r', {\n",
" help : 'run cell',\n",
" help_index : 'zz',\n",
" handler : function (event) {\n",
" IPython.notebook.execute_cell();\n",
" return false;\n",
" }}\n",
");"
],
"metadata": {},
"output_type": "display_data",
"text": [
"<IPython.core.display.Javascript at 0x10e8d1890>"
]
}
],
"prompt_number": 7
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"There are a couple of points to mention about this API:\n",
"\n",
"* The `help_index` field is used to sort the shortcuts in the Keyboard Shortcuts help dialog. It defaults to `zz`.\n",
"* When a handler returns `false` it indicates that the event should stop propagating and the default action should not be performed. For further details about the `event` object or event handling, see the jQuery docs.\n",
"* If you don't need a `help` or `help_index` field, you can simply pass a function as the second argument to `add_shortcut`."
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"%%javascript\n",
"\n",
"IPython.keyboard_manager.command_shortcuts.add_shortcut('r', function (event) {\n",
" IPython.notebook.execute_cell();\n",
" return false;\n",
"});"
],
"language": "python",
"metadata": {},
"outputs": [
{
"javascript": [
"\n",
"IPython.keyboard_manager.command_shortcuts.add_shortcut('r', function (event) {\n",
" IPython.notebook.execute_cell();\n",
" return false;\n",
"});"
],
"metadata": {},
"output_type": "display_data",
"text": [
"<IPython.core.display.Javascript at 0x1019baf90>"
]
}
],
"prompt_number": 11
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Likewise, to remove a shortcut, use `remove_shortcut`:"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"%%javascript\n",
"\n",
"IPython.keyboard_manager.command_shortcuts.remove_shortcut('r');"
],
"language": "python",
"metadata": {},
"outputs": [
{
"javascript": [
"\n",
"IPython.keyboard_manager.command_shortcuts.remove_shortcut('r');"
],
"metadata": {},
"output_type": "display_data",
"text": [
"<IPython.core.display.Javascript at 0x10e8d1950>"
]
}
],
"prompt_number": 8
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"If you want your keyboard shortcuts to be active for all of your notebooks, put the above API calls into your `<profile>/static/custom/custom.js` file."
]
}
],
"metadata": {}
}
]
}

View File

@ -1,7 +1,7 @@
{
"metadata": {
"name": "",
"signature": "sha256:c9fdf35bcd07c381b988af18346fceeb08107ce216817e4bd398641e9c93ecc1"
"signature": "sha256:fe084460e647ed671f6335e872a6b8e83a00f03dd2c1c47122f99e1218164cf4"
},
"nbformat": 3,
"nbformat_minor": 0,
@ -34,7 +34,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"The IPython Notebook is a web-based interactive computing system that enables users to author documents that include live code, narrative text, LaTeX equations, HTML, images and video. These documents are contain a full record of a computation and its results and can be shared on email, [Dropbox](http://dropbox.com), version control systems (like git/[GitHub](http://github.com)) or [nbviewer.ipython.org](http://nbviewer.ipython.org)."
"The IPython Notebook is a web-based interactive computing system that enables users to author documents that include live code, narrative text, LaTeX equations, HTML, images and video. These documents contain a full record of a computation and its results and can be shared on email, [Dropbox](http://dropbox.com), version control systems (like git/[GitHub](http://github.com)) or [nbviewer.ipython.org](http://nbviewer.ipython.org)."
]
},
{
@ -49,14 +49,16 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"* [User Interface](User Interface.ipynb)\n",
"* [What is the IPython Notebook?](What is the IPython Notebook%3F.ipynb)\n",
"* [Running the Notebook Server](Running the Notebook Server.ipynb)\n",
"* [Notebook Basics](Notebook Basics.ipynb)\n",
"* [Running Code](Running Code.ipynb)\n",
"* [Basic Output](Basic Output.ipynb)\n",
"* [Plotting with Matplotlib](Plotting with Matplotlib.ipynb)\n",
"* [Markdown Cells](Markdown Cells.ipynb)\n",
"* [Typesetting Math Using MathJax](Typesetting Math Using MathJax.ipynb)\n",
"* [Display System](Display System.ipynb)\n",
"* [Custom Display Logic](Custom Display Logic.ipynb)"
"* [Working With Markdown Cells](Working With Markdown Cells.ipynb)\n",
"* [Custom Keyboard Shortcuts](Custom Keyboard Shortcuts.ipynb)\n",
"* [JavaScript Notebook Extensions](JavaScript Notebook Extensions.ipynb)\n",
"* [Notebook Security](Notebook Security.ipynb)\n",
"* [Converting Notebooks With nbconvert](Converting Notebooks With nbconvert.ipynb)\n",
"* [Using nbconvert as a Library](Using nbconvert as a Library.ipynb)"
]
},
{
@ -71,12 +73,9 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"* [Trapezoid Rule](Trapezoid Rule.ipynb)\n",
"* [SymPy](SymPy.ipynb)\n",
"* [Raw Input](Raw Input.ipynb)\n",
"* [Importing Notebooks](Importing Notebooks.ipynb)\n",
"* [Connecting with the Qt Console](Connecting with the Qt Console.ipynb)\n",
"* [Animations Using clear_output](Animations Using clear_output.ipynb)"
"* [Typesetting Equations](Typesetting Equations.ipynb)"
]
}
],

View File

@ -0,0 +1,770 @@
{
"metadata": {
"name": ""
},
"nbformat": 3,
"nbformat_minor": 0,
"worksheets": [
{
"cells": [
{
"cell_type": "heading",
"level": 1,
"metadata": {},
"source": [
"Embrasing web standards"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"One of the main reason that allowed us to developp the current notebook web application \n",
"was to embrase the web technology. \n",
"\n",
"By beeing a pure web application using HTML, Javascript and CSS, the Notebook can get \n",
"all the web technology improvement for free. Thus, as browsers support for different \n",
"media extend, The notebook web app should be able to be compatible without modification. \n",
"\n",
"This is also true with performance of the User Interface as the speed of javascript VM increase. "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The other advantage of using only web technology is that the code of the interface is fully accessible to the end user, and modifiable live.\n",
"Even if this task is not always easy, we strive to keep our code as accessible and reusable as possible.\n",
"This should allow with minimum effort to develop small extensions that customize the behavior of the web interface. "
]
},
{
"cell_type": "heading",
"level": 2,
"metadata": {},
"source": [
"Tempering with Notebook app"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The first tool that is availlable to you and that you shoudl be aware of are browser \"developpers tool\". The exact naming can change across browser, and might require the installation of extensions. But basically they can allow you to inspect/modify the DOM, and interact with the javascript code that run the frontend.\n",
"\n",
" - In Chrome and safari Developper tools are in the menu [Put mmenu name in english here] \n",
" - In firefox you might need to install [Firebug](http://getfirebug.com/)\n",
" - others ?\n",
" \n",
"Those will be your best friends to debug and try different approach for your extensions."
]
},
{
"cell_type": "heading",
"level": 3,
"metadata": {},
"source": [
"Injecting JS"
]
},
{
"cell_type": "heading",
"level": 4,
"metadata": {},
"source": [
"using magics"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Above tools can be tedious to edit long javascipt files. Hopefully we provide the `%%javascript` magic. This allows you to quickly inject javascript into the notebook. Still the javascript injected this way will not survive reloading. Hence it is a good tool for testing an refinig a script.\n",
"\n",
"You might see here and there people modifying css and injecting js into notebook by reading file and publishing them into the notebook.\n",
"Not only this often break the flow of the notebook and make the re-execution of the notebook broken, but it also mean that you need to execute those cells on all the notebook every time you need to update the code.\n",
"\n",
"This can still be usefull in some cases, like the `%autosave` magic that allows to control the time between each save. But this can be replaced by a Javascript dropdown menu to select save interval."
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"## you can inspect the autosave code to see what it does.\n",
"%autosave??"
],
"language": "python",
"metadata": {},
"outputs": []
},
{
"cell_type": "heading",
"level": 4,
"metadata": {},
"source": [
"custom.js"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"To inject Javascript we provide an entry point: `custom.js` that allow teh user to execute and load other resources into the notebook.\n",
"Javascript code in `custom.js` will be executed when the notebook app start and can then be used to customise almost anything in the UI and in the behavior of the notebook.\n",
"\n",
"`custom.js` can be found in IPython profile dir, and so you can have different UI modification on a per profile basis, as well as share your modfication with others."
]
},
{
"cell_type": "heading",
"level": 5,
"metadata": {},
"source": [
"Because we like you...."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"You have been provided with an already existing profile folder with this tutorial...\n",
"start the notebook from the root of the tutorial directory with :\n",
"\n",
"```bash\n",
"$ ipython notebook --ProfileDir.location=./profile_euroscipy\n",
"```"
]
},
{
"cell_type": "heading",
"level": 5,
"metadata": {},
"source": [
"but back to theory"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"profile_dir = ! ipython locate\n",
"profile_dir = profile_dir[0]\n",
"profile_dir"
],
"language": "python",
"metadata": {},
"outputs": [
{
"metadata": {},
"output_type": "pyout",
"prompt_number": 1,
"text": [
"'/Users/bussonniermatthias/.ipython'"
]
}
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"and custom js is in "
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"import os.path\n",
"custom_js_path = os.path.join(profile_dir,'profile_default','static','custom','custom.js')"
],
"language": "python",
"metadata": {},
"outputs": []
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"# my custom js\n",
"with open(custom_js_path) as f:\n",
" for l in f: \n",
" print l,"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"// we want strict javascript that fails\n",
"// on ambiguous syntax\n",
"\"using strict\";\n",
"\n",
"// notebook loaded is not perfect as it is re-triggerd on\n",
"// revert to checkpoint but this allow extesnsion to be loaded\n",
"// late enough to work.\n",
"$([IPython.events]).on('notebook_loaded.Notebook', function(){\n",
"\n",
"\n",
" /** Use path to js file relative to /static/ dir without leading slash, or\n",
" * js extension.\n",
" * Link directly to file is js extension isa simple file\n",
" *\n",
" * first argument of require is a **list** that can contains several modules if needed.\n",
" **/\n",
"\n",
" //require(['custom/noscroll']);\n",
" // require(['custom/clean_start'])\n",
" // require(['custom/toggle_all_line_number'])\n",
" // require(['custom/gist_it']);\n",
" // require(['custom/autosavetime']);\n",
"\n",
" /**\n",
" * Link to entrypoint if extesnsion is a folder.\n",
" * to be consistent with commonjs module, the entrypoint is main.js\n",
" * here youcan also trigger a custom function on load that will do extra\n",
" * action with the module if needed\n",
" **/\n",
" require(['custom/slidemode/main'])\n",
"\n",
" // require(['custom/autoscroll']);\n",
"\n",
" //require(['custom/css_selector/main'])\n",
" require(['custom/pre_exec_strip']);\n",
" // require(['custom/no_exec_dunder']);\n",
" // load_ext('nbviewer_theme')\n",
"\n",
"\n",
" require(['custom/clippytip/main']);\n",
"\n",
" IPython.toolbar.add_buttons_group([\n",
" {\n",
" 'label' : 'run qtconsole',\n",
" 'icon' : 'icon-paper-clip', // select your icon from http://jqueryui.com/themeroller/\n",
" 'callback': function(){\n",
" IPython.tooltip.remove_and_cancel_tooltip(true)\n",
" $('#tooltip').empty() \n",
" $('#tooltip').attr('style','') \n",
" IPython.tooltip = new IPython.ClippyTip()\n",
" }\n",
" },\n",
" {\n",
" 'label' : 'run qtconsole',\n",
" 'icon' : 'icon-th-large', // select your icon from http://jqueryui.com/themeroller/\n",
" 'callback': function(){\n",
" IPython.tooltip.remove_and_cancel_tooltip(true)\n",
" $('#tooltip').empty() \n",
" $('#tooltip').attr('style','')\n",
" IPython.tooltip = new IPython.Tooltip()\n",
" }\n",
" }\n",
" // add more button here if needed.\n",
" ]);\n",
" //\n",
"\n",
"});\n",
"\n",
"/*\n",
"$([IPython.events]).on('notebook_loaded.Notebook', function(){\n",
" IPython.toolbar.add_buttons_group([\n",
" {\n",
" 'label' : 'run qtconsole',\n",
" 'icon' : 'ui-icon-calculator',\n",
" 'callback': function(){IPython.notebook.kernel.execute('%qtconsole')}\n",
" }\n",
" ]);\n",
"});\n",
"*/\n",
"\n",
"//$([IPython.events]).on('notebook_loaded.Notebook', function(){\n",
"// mobile_preset = []\n",
"// var edit = function(div, cell) {\n",
"// var button_container = $(div);\n",
"// var button = $('<div/>').button({icons:{primary:'ui-icon-pencil'}});\n",
"// button.click(function(){\n",
"// cell.edit()\n",
"// })\n",
"// button_container.append(button);\n",
"// }\n",
"//\n",
"// IPython.CellToolbar.register_callback('mobile.edit',edit);\n",
"// mobile_preset.push('mobile.edit');\n",
"//\n",
"// IPython.CellToolbar.register_preset('Mobile',mobile_preset);\n",
"//});\n"
]
}
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Note that `custom.js` is ment to be modified by user, when writing a script, you can define it in a separate file and add a line of configuration into `custom.js` that will fetch and execute the file."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Warning** : even if modification of `custom.js` take effect immediately after browser refresh (except if browser cache is aggressive), *creating* a file in `static/` directory need a **server restart**."
]
},
{
"cell_type": "heading",
"level": 2,
"metadata": {},
"source": [
"Exercise :"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" - Create a `custom.js` in the right location with the following content:\n",
"```javascript\n",
"alert(\"hello world from custom.js\")\n",
"```\n",
"\n",
" - Restart your server and open any notebook.\n",
" - Be greeted by custom.js"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Have a look at [default custom.js](https://github.com/ipython/ipython/blob/1.x/IPython/html/static/custom/custom.js), to see it's content and some more explanation."
]
},
{
"cell_type": "heading",
"level": 4,
"metadata": {},
"source": [
"For the quick ones : "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We've seen above that you can change the autosave rate by using a magic. This is typically something I don't want to type everytime, and that I don't like to embed into my workwlow and documents. (reader don't care what my autosave time is), let's build an extension that allow to do it. "
]
},
{
"cell_type": "markdown",
"metadata": {
"foo": true
},
"source": [
"Create a dropdow elemement in the toolbar (DOM `IPython.toolbar.element`), you will need \n",
"\n",
"- `IPython.notebook.set_autosave_interval(miliseconds)`\n",
"- know that 1min = 60 sec, and 1 sec = 1000 ms"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"```javascript\n",
"\n",
"var label = jQuery('<label/>').text('AutoScroll Limit:');\n",
"var select = jQuery('<select/>')\n",
" //.append(jQuery('<option/>').attr('value', '2').text('2min (default)'))\n",
" .append(jQuery('<option/>').attr('value', undefined).text('disabled'))\n",
"\n",
" // TODO:\n",
" //the_toolbar_element.append(label)\n",
" //the_toolbar_element.append(select);\n",
" \n",
"select.change(function() {\n",
" var val = jQuery(this).val() // val will be the value in [2]\n",
" // TODO\n",
" // this will be called when dropdown changes\n",
"\n",
"});\n",
"\n",
"var time_m = [1,5,10,15,30];\n",
"for (var i=0; i < time_m.length; i++) {\n",
" var ts = time_m[i];\n",
" //[2] ____ this will be `val` on [1] \n",
" // | \n",
" // v \n",
" select.append($('<option/>').attr('value', ts).text(thr+'min'));\n",
" // this will fill up the dropdown `select` with\n",
" // 1 min\n",
" // 5 min\n",
" // 10 min\n",
" // 10 min\n",
" // ...\n",
"}\n",
"```"
]
},
{
"cell_type": "heading",
"level": 4,
"metadata": {},
"source": [
"A non interactive example first"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"I like my cython to be nicely highlighted\n",
"\n",
"```javascript\n",
"IPython.config.cell_magic_highlight['magic_text/x-cython'] = {}\n",
"IPython.config.cell_magic_highlight['magic_text/x-cython'].reg = [/^%%cython/]\n",
"```\n",
"\n",
"`text/x-cython` is the name of CodeMirror mode name, `magic_` prefix will just patch the mode so that the first line that contains a magic does not screw up the highlighting. `reg`is a list or regular expression that will trigger the change of mode."
]
},
{
"cell_type": "heading",
"level": 4,
"metadata": {},
"source": [
"Get more docs"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Sadly you will have to read the js source file (but there are lots of comments) an/or build the javascript documentation using yuidoc.\n",
"If you have `node` and `yui-doc` installed:"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"```bash\n",
"$ cd ~/ipython/IPython/html/static/notebook/js/\n",
"$ yuidoc . --server\n",
"warn: (yuidoc): Failed to extract port, setting to the default :3000\n",
"info: (yuidoc): Starting YUIDoc@0.3.45 using YUI@3.9.1 with NodeJS@0.10.15\n",
"info: (yuidoc): Scanning for yuidoc.json file.\n",
"info: (yuidoc): Starting YUIDoc with the following options:\n",
"info: (yuidoc):\n",
"{ port: 3000,\n",
" nocode: false,\n",
" paths: [ '.' ],\n",
" server: true,\n",
" outdir: './out' }\n",
"info: (yuidoc): Scanning for yuidoc.json file.\n",
"info: (server): Starting server: http://127.0.0.1:3000\n",
"```\n",
"\n",
"and browse http://127.0.0.1:3000 to get docs"
]
},
{
"cell_type": "heading",
"level": 4,
"metadata": {
"foo": true
},
"source": [
"Some convenience methods"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"By browsing the doc you will see that we have soem convenience methods that avoid to re-invent the UI everytime :\n",
"```javascript\n",
"IPython.toolbar.add_buttons_group([\n",
" {\n",
" 'label' : 'run qtconsole',\n",
" 'icon' : 'icon-terminal', // select your icon from \n",
" // http://fortawesome.github.io/Font-Awesome/icons/\n",
" 'callback': function(){IPython.notebook.kernel.execute('%qtconsole')}\n",
" }\n",
" // add more button here if needed.\n",
" ]);\n",
"```\n",
"with a [lot of icons] you can select from. \n",
"\n",
"[lot of icons]: http://fortawesome.github.io/Font-Awesome/icons/"
]
},
{
"cell_type": "heading",
"level": 2,
"metadata": {
"foo": true
},
"source": [
"Cell Metadata"
]
},
{
"cell_type": "markdown",
"metadata": {
"foo": true
},
"source": [
"The most requested feature is generaly to be able to distinguish individual cell in th enotebook, or run specific action with them.\n",
"To do so, you can either use `IPython.notebook.get_selected_cell()`, or rely on `CellToolbar`. This allow you to register aset of action and graphical element that will be attached on individual cells."
]
},
{
"cell_type": "heading",
"level": 3,
"metadata": {},
"source": [
"Cell Toolbar"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"You can see some example of what can be done by toggling the `Cell Toolbar` selector in the toolbar on top of the notebook. It provide two default `presets` that are `Default` and `slideshow`. Default allow edit the metadata attached to each cell manually."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"First we define a function that takes at first parameter an element on the DOM in which to inject UI element. Second element will be the cell this element will be registerd with. Then we will need to register that function ad give it a name.\n"
]
},
{
"cell_type": "heading",
"level": 4,
"metadata": {},
"source": [
"Register a callback"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"%%javascript\n",
"var CellToolbar = IPython.CellToolbar\n",
"var toggle = function(div, cell) {\n",
" var button_container = $(div)\n",
"\n",
" // let's create a button that show the current value of the metadata\n",
" var button = $('<button/>').addClass('btn btn-mini').text(String(cell.metadata.foo));\n",
"\n",
" // On click, change the metadata value and update the button label\n",
" button.click(function(){\n",
" var v = cell.metadata.foo;\n",
" cell.metadata.foo = !v;\n",
" button.text(String(!v));\n",
" })\n",
"\n",
" // add the button to the DOM div.\n",
" button_container.append(button);\n",
"}\n",
"\n",
" // now we register the callback under the name foo to give the\n",
" // user the ability to use it later\n",
" CellToolbar.register_callback('tuto.foo', toggle);"
],
"language": "python",
"metadata": {},
"outputs": [
{
"javascript": [
"var CellToolbar = IPython.CellToolbar\n",
"var toggle = function(div, cell) {\n",
" var button_container = $(div)\n",
"\n",
" // let's create a button that show the current value of the metadata\n",
" var button = $('<button/>').addClass('btn btn-mini').text(String(cell.metadata.foo));\n",
"\n",
" // On click, change the metadata value and update the button label\n",
" button.click(function(){\n",
" var v = cell.metadata.foo;\n",
" cell.metadata.foo = !v;\n",
" button.text(String(!v));\n",
" })\n",
"\n",
" // add the button to the DOM div.\n",
" button_container.append(button);\n",
"}\n",
"\n",
" // now we register the callback under the name foo to give the\n",
" // user the ability to use it later\n",
" CellToolbar.register_callback('tuto.foo', toggle);"
],
"metadata": {},
"output_type": "display_data",
"text": [
"<IPython.core.display.Javascript at 0x10c94a590>"
]
}
],
"prompt_number": 51
},
{
"cell_type": "heading",
"level": 4,
"metadata": {},
"source": [
"Registering a preset"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"This function can now be part of many `preset` of the CellToolBar."
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"%%javascript\n",
"IPython.CellToolbar.register_preset('Tutorial 1',['tuto.foo','default.rawedit'])\n",
"IPython.CellToolbar.register_preset('Tutorial 2',['slideshow.select','tuto.foo'])"
],
"language": "python",
"metadata": {
"foo": true,
"slideshow": {
"slide_type": "subslide"
}
},
"outputs": [
{
"javascript": [
"IPython.CellToolbar.register_preset('Tutorial 1',['tuto.foo','default.rawedit'])\n",
"IPython.CellToolbar.register_preset('Tutorial 2',['slideshow.select','tuto.foo'])"
],
"metadata": {},
"output_type": "display_data",
"text": [
"<IPython.core.display.Javascript at 0x10c94a510>"
]
}
],
"prompt_number": 54
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"You should now have access to two presets :\n",
"\n",
" - Tutorial 1\n",
" - Tutorial 2\n",
" \n",
"And check that the buttons you defin share state when you toggle preset. \n",
"Check moreover that the metadata of the cell is modified when you clisk the button, and that when saved on reloaded the metadata is still availlable."
]
},
{
"cell_type": "heading",
"level": 4,
"metadata": {},
"source": [
"Exercise:"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Try to wrap the all code in a file, put this file in `{profile}/static/custom/<a-name>.js`, and add \n",
"\n",
"```\n",
"require(['custom/<a-name>']);\n",
"```\n",
"\n",
"in `custom.js` to have this script automatically loaded in all your notebooks.\n",
"\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"`require` is provided by a [javascript library](http://requirejs.org/) that allow to express dependency. For simple extension like the previous one we directly mute the global namespace, but for more complexe extension you could pass acallback to `require([...], <callback>)` call, to allow the user to pass configuration information to your plugin.\n",
"\n",
"In Python lang, \n",
"\n",
"```javascript\n",
"require(['a/b', 'c/d'], function( e, f){\n",
" e.something()\n",
" f.something()\n",
"})\n",
"```\n",
"\n",
"could be read as\n",
"```python\n",
"import a.b as e\n",
"import c.d as f\n",
"e.something()\n",
"f.something()\n",
"```\n",
"\n",
"\n",
"See for example @damianavila [\"ZenMode\" plugin](https://github.com/ipython-contrib/IPython-notebook-extensions/blob/master/custom.example.js#L34) :\n",
"\n",
"```javascript\n",
"\n",
"// read that as\n",
"// import custom.zenmode.main as zenmode\n",
"require(['custom/zenmode/main'],function(zenmode){\n",
" zenmode.background('images/back12.jpg');\n",
"})\n",
"```\n"
]
},
{
"cell_type": "heading",
"level": 4,
"metadata": {},
"source": [
"For the quickest"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Try to use [the following](https://github.com/ipython/ipython/blob/1.x/IPython/html/static/notebook/js/celltoolbar.js#L367) to bind a dropdown list to `cell.metadata.difficulty.select`. \n",
"\n",
"It should be able to take the 4 following values :\n",
"\n",
" - `<None>`\n",
" - `Easy`\n",
" - `Medium`\n",
" - `Hard`\n",
" \n",
"We will use it to customise the output of the converted notebook depending of the tag on each cell"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"%load soln/celldiff.js"
],
"language": "python",
"metadata": {},
"outputs": []
}
],
"metadata": {}
}
]
}

View File

@ -0,0 +1,254 @@
{
"metadata": {
"name": "",
"signature": "sha256:1a6a6a01ea6dbb9b101174c11ba522cb145e4a070685a43a71b5ccdb75672909"
},
"nbformat": 3,
"nbformat_minor": 0,
"worksheets": [
{
"cells": [
{
"cell_type": "heading",
"level": 1,
"metadata": {},
"source": [
"Notebook Basics"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"This notebook assumes that you already have IPython [installed](http://ipython.org/install.html) and are able to start the notebook server by running:\n",
"\n",
" ipython notebook\n",
"\n",
"For more details on how to run the notebook server, see [Running the Notebook Server](Running the Notebook Server.ipynb)."
]
},
{
"cell_type": "heading",
"level": 2,
"metadata": {},
"source": [
"The Notebook dashboard"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"When you first start the notebook server, your browser will open to the notebook dashboard. The dashboard serves as a home page for the notebook. Its main purpose is to display the notebooks in the current directory. For example, here is a screenshot of the dashboard page for the `examples` directory in the IPython repository:\n",
"\n",
"<img src=\"images/dashboard_notebooks_tab.png\" />\n",
"\n",
"The top of the notebook list displays clickable breadcrumbs of the current directory. By clicking on these breadcrumbs or on sub-directories in the notebook list, you can navigate your file system.\n",
"\n",
"To create a new notebook, click on the \"New Notebook\" button at the top of the list.\n",
"\n",
"Notebooks can be uploaded to the current directory by dragging a notebook file onto the notebook list or by the \"click here\" text above the list.\n",
"\n",
"The notebook list shows a red \"Shutdown\" button for running notebooks and a \"Delete\" button for stopped notebooks. Notebook remain running until you explicitly click the \"Shutdown\" button; closing the notebook's page is not sufficient.\n",
"\n",
"To see all of your running notebooks along with their directories, click on the \"Running\" tab:\n",
"\n",
"<img src=\"images/dashboard_running_tab.png\" />\n",
"\n",
"This view provides a convenient way to track notebooks that you start as you navigate the file system in a long running notebook server."
]
},
{
"cell_type": "heading",
"level": 2,
"metadata": {},
"source": [
"Overview of the Notebook UI"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"<div class=\"alert\">\n",
"As of IPython 2.0, the user interface has changed significantly. Because of this we highly recommend existing users to review this information after upgrading to IPython 2.0. All new users of IPython should review this information as well.\n",
"</div>"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"If you create a new notebook or open an existing one, you will be taken to the notebook user interface (UI). This UI allows you to run code and author notebook documents interactively. The notebook UI has the following main areas:\n",
"\n",
"* Menu\n",
"* Toolbar\n",
"* Notebook area and cells\n",
"\n",
"IPython 2.0 has an interactive tour of these elements that can be started in the \"Help:User Interface Tour\" menu item."
]
},
{
"cell_type": "heading",
"level": 2,
"metadata": {},
"source": [
"Modal editor"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Starting with IPython 2.0, the IPython Notebook has a modal user interface. This means that the keyboard does different things depending on which mode the Notebook is in. There are two modes: edit mode and command mode."
]
},
{
"cell_type": "heading",
"level": 3,
"metadata": {},
"source": [
"Edit mode"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Edit mode is indicated by a green cell border and a prompt showing in the editor area:\n",
"\n",
"<img src=\"images/edit_mode.png\">\n",
"\n",
"When a cell is in edit mode, you can type into the cell, like a normal text editor."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"<div class=\"alert alert-success\">\n",
"Enter edit mode by pressing `Enter` or using the mouse to click on a cell's editor area.\n",
"</div>"
]
},
{
"cell_type": "heading",
"level": 3,
"metadata": {},
"source": [
"Command mode"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Command mode is indicated by a grey cell border:\n",
"\n",
"<img src=\"images/command_mode.png\">\n",
"\n",
"When you are in command mode, you are able to edit the notebook as a whole, but not type into individual cells. Most importantly, in command mode, the keyboard is mapped to a set of shortcuts that let you perform notebook and cell actions efficiently. For example, if you are in command mode and you press `c`, you will copy the current cell - no modifier is needed."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"<div class=\"alert alert-error\">\n",
"Don't try to type into a cell in command mode; unexpected things will happen!\n",
"</div>"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"<div class=\"alert alert-success\">\n",
"Enter command mode by pressing `Esc` or using the mouse to click *outside* a cell's editor area.\n",
"</div>"
]
},
{
"cell_type": "heading",
"level": 2,
"metadata": {},
"source": [
"Mouse navigation"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"All navigation and actions in the Notebook are available using the mouse through the menubar and toolbar, which are both above the main Notebook area:\n",
"\n",
"<img src=\"images/menubar_toolbar.png\">"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The first idea of mouse based navigation is that **cells can be selected by clicking on them.** The currently selected cell gets a grey or green border depending on whether the notebook is in edit or command mode. If you click inside a cell's editor area, you will enter edit mode. If you click on the prompt or output area of a cell you will enter command mode.\n",
"\n",
"If you are running this notebook in a live session (not on http://nbviewer.ipython.org) try selecting different cells and going between edit and command mode. Try typing into a cell."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The second idea of mouse based navigation is that **cell actions usually apply to the currently selected cell**. Thus if you want to run the code in a cell, you would select it and click the <button><i class=\"icon-play\"></i></button> button in the toolbar or the \"Cell:Run\" menu item. Similarly, to copy a cell you would select it and click the <button><i class=\"icon-copy\"></i></button> button in the toolbar or the \"Edit:Copy\" menu item. With this simple pattern, you should be able to do most everything you need with the mouse.\n",
"\n",
"Markdown and heading cells have one other state that can be modified with the mouse. These cells can either be rendered or unrendered. When they are rendered, you will see a nice formatted representation of the cell's contents. When they are unrendered, you will see the raw text source of the cell. To render the selected cell with the mouse, click the <button><i class=\"icon-play\"></i></button> button in the toolbar or the \"Cell:Run\" menu item. To unrender the selected cell, double click on the cell."
]
},
{
"cell_type": "heading",
"level": 2,
"metadata": {},
"source": [
"Keyboard Navigation"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The modal user interface of the IPython Notebook has been optimized for efficient keyboard usage. This is made possible by having two different sets of keyboard shortcuts: one set that is active in edit mode and another in command mode.\n",
"\n",
"The most important keyboard shortcuts are `Enter`, which enters edit mode, and `Esc`, which enters command mode.\n",
"\n",
"In edit mode, most of the keyboard is dedicated to typing into the cell's editor. Thus, in edit mode there are relatively few shortcuts:\n",
"\n",
"<img src=\"images/edit_shortcuts.png\">"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"In command mode, the entire keyboard is available for shortcuts, so there are many more:\n",
"\n",
"<img src=\"images/command_shortcuts.png\">"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We recommend learning the command mode shortcuts in the following rough order:\n",
"\n",
"1. Basic navigation: `enter`, `shift-enter`, `up/k`, `down/j`\n",
"2. Saving the notebook: `s`\n",
"2. Cell types: `y`, `m`, `1-6`, `t`\n",
"3. Cell creation and movement: `a`, `b`, `ctrl+k`, `ctrl+j`\n",
"4. Cell editing: `x`, `c`, `v`, `d`, `z`, `shift+=`\n",
"5. Kernel operations: `i`, `.`"
]
}
],
"metadata": {}
}
]
}

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,389 @@
{
"metadata": {
"name": "",
"signature": "sha256:ee4b22b4c949fe21b3e5cda24f0916ba59d8c09443f4a897d98b96d4a73ac335"
},
"nbformat": 3,
"nbformat_minor": 0,
"worksheets": [
{
"cells": [
{
"cell_type": "heading",
"level": 1,
"metadata": {},
"source": [
"Running the Notebook Server"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The IPython notebook server is a custom web server that runs the notebook web application. Most of the time, users run the notebook server on their local computer using IPython's command line interface."
]
},
{
"cell_type": "heading",
"level": 2,
"metadata": {},
"source": [
"Starting the notebook server using the command line"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"You can start the notebook server from the command line (Terminal on Mac/Linux, CMD prompt on Windows) by running the following command: \n",
"\n",
" ipython notebook\n",
"\n",
"This will print some information about the notebook server in your terminal, including the URL of the web application (by default, `http://127.0.0.1:8888`). It will then open your default web browser to this URL.\n",
"\n",
"When the notebook opens, you will see the **notebook dashboard**, which will show a list of the notebooks and subdirectories in the directory where the notebook server was started. As of IPython 2.0, the dashboard allows you to navigate to different subdirectories. Because of this, it is no longer necessary to start a separate notebook server for each subdirectory. Most of the time, you will want to start a notebook server in the highest directory in your filesystem where notebooks can be found. Often this will be your home directory.\n",
"\n",
"You can start more than one notebook server at the same time. By default, the first notebook server starts on port 8888 and later notebook servers search for open ports near that one.\n",
"\n",
"You can also specify the port manually:\n",
"\n",
" ipython notebook --port 9999\n",
"\n",
"Or start notebook server without opening a web browser.\n",
"\n",
" ipython notebook --no-browser\n",
"\n",
"The notebook server has a number of other command line arguments that can be displayed with the `--help` flag: \n",
"\n",
" ipython notebook --help\n",
"\n",
"<div class=\"alert alert-failure\">\n",
"It used to be possible to specify kernel options, such as <code>--pylab inline</code> from the command line. This is deprecated in IPython 2.0 and will be removed in IPython 3.0. To enable matplotlib based plotting for the Python kernel use the <code>%matplotlib</code> magic command.\n",
"</div>\n",
"\n"
]
},
{
"cell_type": "heading",
"level": 2,
"metadata": {},
"source": [
"Configuring the IPython Notebook"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The notebook web server can also be configured using IPython profiles and configuration files. The Notebook web server configuration options are set in a file named `ipython_notebook_config.py` in your IPython *profile directory*. The profile directory is a subfolder of your IPython directory, which itself is usually `.ipython` in your home directory.\n",
"\n",
"You can display the location of your default profile directory by running the command:"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"!ipython profile locate default"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"/Users/bgranger/.ipython/profile_default\r\n"
]
}
],
"prompt_number": 7
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The default version of `ipython_notebook_config.py` lists all of the options available along with documentation for each. Changes made to that file will affect all notebook servers run under that profile. Command line options always override those set in configuration files.\n",
"\n",
"You can create a new profile:"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"!ipython profile create my_profile"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"[ProfileCreate] Generating default config file: u'/Users/bgranger/.ipython/profile_my_profile/ipython_config.py'\r\n"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
"[ProfileCreate] Generating default config file: u'/Users/bgranger/.ipython/profile_my_profile/ipython_qtconsole_config.py'\r\n"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
"[ProfileCreate] Generating default config file: u'/Users/bgranger/.ipython/profile_my_profile/ipython_notebook_config.py'\r\n",
"[ProfileCreate] Generating default config file: u'/Users/bgranger/.ipython/profile_my_profile/ipython_nbconvert_config.py'\r\n"
]
}
],
"prompt_number": 3
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"And then view its location:"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"!ipython profile locate my_profile"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"/Users/bgranger/.ipython/profile_my_profile\r\n"
]
}
],
"prompt_number": 5
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"To start the notebook server using a given profile, run the following:\n",
"\n",
" ipython notebook --profile=my_profile"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"More details about IPython configuration files and profiles can be found [here](http://ipython.org/ipython-doc/dev/config/intro.html)."
]
},
{
"cell_type": "heading",
"level": 2,
"metadata": {},
"source": [
"Securing the notebook server"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The IPython Notebook allows arbitrary code execution on the computer running it. Thus, the notebook web server should never be run on the open internet without first securing it. By default, the notebook server only listens on local network interface (`127.0.0.1`) There are two steps required to secure the notebook server:\n",
"\n",
"1. Setting a password\n",
"2. Encrypt network traffic using SSL"
]
},
{
"cell_type": "heading",
"level": 3,
"metadata": {},
"source": [
"Setting a password"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"You can protect your notebook server with a simple single password by setting the `NotebookApp.password` configurable. You can prepare a hashed password using the function `IPython.lib.passwd`:"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"from IPython.lib import passwd\n",
"password = passwd(\"secret\")\n",
"password"
],
"language": "python",
"metadata": {},
"outputs": [
{
"metadata": {},
"output_type": "pyout",
"prompt_number": 1,
"text": [
"'sha1:6c2164fc2b22:ed55ecf07fc0f985ab46561483c0e888e8964ae6'"
]
}
],
"prompt_number": 1
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"You can then add this to your `ipython_notebook_config.py`:\n",
"\n",
"```python\n",
"# Password to use for web authentication\n",
"c = get_config()\n",
"c.NotebookApp.password = \n",
"u'sha1:6c2164fc2b22:ed55ecf07fc0f985ab46561483c0e888e8964ae6'\n",
"```"
]
},
{
"cell_type": "heading",
"level": 3,
"metadata": {},
"source": [
"Using SSL/HTTPS"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"When using a password, it is a good idea to also use SSL, so that your \n",
"password is not sent unencrypted by your browser to the web server. When running the notebook on the public internet this is absolutely required.\n",
"\n",
"The first step is to generate an SSL certificate. A self-signed certificate can be generated with ``openssl``. For example, the following command will create a certificate valid for 365 days with both the key and certificate data written to the same file:\n",
"\n",
" openssl req -x509 -nodes -days 365 -newkey rsa:1024 -keyout mycert.pem -out mycert.pem\n",
"\n",
"In most cases, you should run this command in your profile directory, which will make it easy to use the generated key and certificate.\n",
"\n",
"When you connect to a notebook server over HTTPS using a self-signed certificate, your browser will warn you of a dangerous certificate because it is self-signed. If you want to have a fully compliant certificate that will not raise warnings, it is possible (but rather involved) to obtain one,\n",
"as explained in detail in [this tutorial](http://arstechnica.com/security/news/2009/12/how-to-get-set-with-a-secure-sertificate-for-free.ars)\n",
"\t\n",
"When you enable SSL support, you will need to access the notebook server over ``https://``, rather than plain ``http://``. The startup message from the notebook server prints the correct URL, but it is easy to overlook and think the server is for some reason non-responsive.\n",
"\n",
"Once you have generated the key and certificate, you can configure the notebook server to use them, by adding the following to `ipython_notebook_config.py`:\n",
"\n",
"```python\n",
"# The full path to an SSL/TLS certificate file.\n",
"c.NotebookApp.certfile = u'/Users/bgranger/.ipython/profile_my_profile/mycert.crt'\n",
"\n",
"# The full path to a private key file for usage with SSL/TLS.\n",
"c.NotebookApp.keyfile = u'/Users/bgranger/.ipython/profile_my_profile/mycert.key'\n",
"```"
]
},
{
"cell_type": "heading",
"level": 2,
"metadata": {},
"source": [
"Running a public notebook server"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"<div class=\"alert alert-error\">\n",
"Don't run a public notebook server unless you first secure it with a password and SSL/HTTPS as described above\n",
"</div>\n",
"\n",
"By default the notebook server only listens on the `localhost/127.0.0.1` network interface. If you want to connect to the notebook from another computers, or over the internet, you need to configure the notebook server to listen on all network interfaces and not open the browser. You will often also want to disable the automatic launching of the web browser.\n",
"\n",
"This can be accomplished by passing a command line options.\n",
"\n",
" ipython notebook --ip=* --no-browser\n",
"\n",
"You can also add the following to your`ipython_notebook_config.py` file:\n",
"\n",
"```python\n",
"c.NotebookApp.ip = '*'\n",
"c.NotebookApp.open_browser = False\n",
"```"
]
},
{
"cell_type": "heading",
"level": 2,
"metadata": {},
"source": [
"Running with a different URL prefix"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The notebook dashboard typically lives at the URL `http://localhost:8888/tree`. If you prefer that it lives, together with the \n",
"rest of the notebook web application, under a base URL prefix, such as `http://localhost:8888/ipython/tree`, you can do so by adding the following lines to your `ipython_notebook_config.py` file.\n",
"\n",
"```python\n",
"c.NotebookApp.base_url = '/ipython/'\n",
"c.NotebookApp.webapp_settings = {'static_url_prefix':'/ipython/static/'}\n",
"```"
]
},
{
"cell_type": "heading",
"level": 2,
"metadata": {},
"source": [
"Using a different notebook store"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"By default, the notebook server stores the notebook documents that it saves as files in the working directory of the notebook server, also known as the\n",
"`notebook_dir`. This logic is implemented in the `FileNotebookManager` class. However, the server can be configured to use a different notebook manager class, which can store the notebooks in a different format. \n",
"\n",
"The [bookstore](https://github.com/rgbkrk/bookstore) package currently allows users to store notebooks on Rackspace CloudFiles or OpenStack Swift based object stores.\n",
"\n",
"Writing a notebook manager is as simple as extending the base class `NotebookManager`. The [simple_notebook_manager](https://github.com/khinsen/simple_notebook_manager) provides a great example\n",
"of an in memory notebook manager, created solely for the purpose of\n",
"illustrating the notebook manager API."
]
},
{
"cell_type": "heading",
"level": 2,
"metadata": {},
"source": [
"Known issues"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"When behind a proxy, especially if your system or browser is set to autodetect the proxy, the notebook web application might fail to connect to the server's websockets, and present you with a warning at startup. In this case, you need to configure your system not to use the proxy for the server's address.\n",
"\n",
"For example, in Firefox, go to the Preferences panel, Advanced section,\n",
"Network tab, click 'Settings...', and add the address of the notebook server\n",
"to the 'No proxy for' field."
]
}
],
"metadata": {}
}
]
}

View File

@ -1,445 +0,0 @@
{
"metadata": {
"name": ""
},
"nbformat": 3,
"nbformat_minor": 0,
"worksheets": [
{
"cells": [
{
"cell_type": "heading",
"level": 1,
"metadata": {},
"source": [
"User Interface"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"This notebook describes the user interface of the IPython Notebook. This includes both mouse and keyboard based navigation and interaction.\n",
"\n",
"<div class=\"alert\" style=\"margin: 10px\">\n",
"As of IPython 2.0, the user interface has changed significantly. Because of this we highly recommend existing users to review this information after upgrading to IPython 2.0. All new users of IPython should review this information as well.\n",
"</div>"
]
},
{
"cell_type": "heading",
"level": 2,
"metadata": {},
"source": [
"Modal editor"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Starting with IPython 2.0, the IPython Notebook has a modal user interface. This means that the keyboard does different things depending on which mode the Notebook is in. There are two modes: edit mode and command mode."
]
},
{
"cell_type": "heading",
"level": 3,
"metadata": {},
"source": [
"Edit mode"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Edit mode is indicated by a green cell border and a prompt showing in the editor area:\n",
"\n",
"<img src=\"images/edit_mode.png\">\n",
"\n",
"When a cell is in edit mode, you can type into the cell, like a normal text editor.\n",
"\n",
"<div class=\"alert alert-success\" style=\"margin: 10px\">\n",
"Enter edit mode by pressing `enter` or using the mouse to click on a cell's editor area.\n",
"</div>"
]
},
{
"cell_type": "heading",
"level": 3,
"metadata": {},
"source": [
"Command mode"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Command mode is indicated by a grey cell border:\n",
"\n",
"<img src=\"images/command_mode.png\">\n",
"\n",
"When you are in command mode, you are able to edit the notebook as a whole, but not type into individual cells. Most importantly, in command mode, the keyboard is mapped to a set of shortcuts that let you perform notebook and cell actions efficiently. For example, if you are in command mode and you press `c`, you will copy the current cell - no modifier is needed.\n",
"\n",
"<div class=\"alert alert-error\" style=\"margin: 10px\">\n",
"Don't try to type into a cell in command mode; unexpected things will happen!\n",
"</div>\n",
"\n",
"<div class=\"alert alert-success\" style=\"margin: 10px\">\n",
"Enter command mode by pressing `esc` or using the mouse to click *outside* a cell's editor area.\n",
"</div>"
]
},
{
"cell_type": "heading",
"level": 2,
"metadata": {},
"source": [
"Mouse navigation"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"All navigation and actions in the Notebook are available using the mouse through the menubar and toolbar, which are both above the main Notebook area:\n",
"\n",
"<img src=\"images/menubar_toolbar.png\">"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The first idea of mouse based navigation is that **cells can be selected by clicking on them.** The currently selected cell gets a grey or green border depending on whether the notebook is in edit or command mode. If you click inside a cell's editor area, you will enter edit mode. If you click on the prompt or output area of a cell you will enter command mode.\n",
"\n",
"If you are running this notebook in a live session (not on http://nbviewer.ipython.org) try selecting different cells and going between edit and command mode. Try typing into a cell."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The second idea of mouse based navigation is that **cell actions usually apply to the currently selected cell**. Thus if you want to run the code in a cell, you would select it and click the \"Play\" button in the toolbar or the \"Cell:Run\" menu item. Similarly, to copy a cell you would select it and click the \"Copy\" button in the toolbar or the \"Edit:Copy\" menu item. With this simple pattern, you should be able to do most everything you need with the mouse.\n",
"\n",
"Markdown and heading cells have one other state that can be modified with the mouse. These cells can either be rendered or unrendered. When they are rendered, you will see a nice formatted representation of the cell's contents. When they are unrendered, you will see the raw text source of the cell. To render the selected cell with the mouse, click the \"Play\" button in the toolbar or the \"Cell:Run\" menu item. To unrender the selected cell, double click on the cell."
]
},
{
"cell_type": "heading",
"level": 2,
"metadata": {},
"source": [
"Keyboard Navigation"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The modal user interface of the IPython Notebook has been optimized for efficient keyboard usage. This is made possible by having two different sets of keyboard shortcuts: one set that is active in edit mode and another in command mode.\n",
"\n",
"The most important keyboard shortcuts are `enter`, which enters edit mode, and `esc`, which enters command mode.\n",
"\n",
"In edit mode, most of the keyboard is dedicated to typing into the cell's editor. Thus, in edit mode there are relatively few shortcuts:"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The `display_edit_shortcuts()` function used here is defined in the [Utilities section](#Utilities) at the bottom of this notebook."
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"display_edit_shortcuts()"
],
"language": "python",
"metadata": {},
"outputs": [
{
"html": [
"<div class=\"hbox\"><div class=\"box-flex0\"><div class=\"quickhelp\"><span class=\"shortcut_key\">esc</span><span class=\"shortcut_descr\"> : command mode</span></div><div class=\"quickhelp\"><span class=\"shortcut_key\">ctrl+m</span><span class=\"shortcut_descr\"> : command mode</span></div><div class=\"quickhelp\"><span class=\"shortcut_key\">shift+enter</span><span class=\"shortcut_descr\"> : run cell</span></div><div class=\"quickhelp\"><span class=\"shortcut_key\">ctrl+enter</span><span class=\"shortcut_descr\"> : run cell, select below</span></div></div><div class=\"box-flex0\"><div class=\"quickhelp\"><span class=\"shortcut_key\">alt+enter</span><span class=\"shortcut_descr\"> : run cell, insert below</span></div><div class=\"quickhelp\"><span class=\"shortcut_key\">alt+-</span><span class=\"shortcut_descr\"> : split cell</span></div><div class=\"quickhelp\"><span class=\"shortcut_key\">meta+s</span><span class=\"shortcut_descr\"> : save notebook</span></div><div class=\"quickhelp\"><span class=\"shortcut_key\">ctrl+s</span><span class=\"shortcut_descr\"> : save notebook</span></div></div></div>"
],
"output_type": "display_data"
},
{
"javascript": [
"var help = IPython.quick_help.build_edit_help();\n",
"help.children().first().remove();\n",
"this.append_output({output_type: 'display_data', html: help.html()});"
],
"metadata": {},
"output_type": "display_data",
"text": [
"<IPython.core.display.Javascript at 0x10e8d1a50>"
]
}
],
"prompt_number": 17
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"There are two other keyboard shortcuts in edit mode that are not listed here:\n",
"\n",
"* `tab`: trigger \"tab\" completion\n",
"* `shift+tab`: open the tooltip"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"In command mode, the entire keyboard is available for shortcuts:"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"display_command_shortcuts()"
],
"language": "python",
"metadata": {},
"outputs": [
{
"html": [
"<div class=\"hbox\"><div class=\"box-flex0\"><div class=\"quickhelp\"><span class=\"shortcut_key\">enter</span><span class=\"shortcut_descr\"> : edit mode</span></div><div class=\"quickhelp\"><span class=\"shortcut_key\">shift+enter</span><span class=\"shortcut_descr\"> : run cell</span></div><div class=\"quickhelp\"><span class=\"shortcut_key\">ctrl+enter</span><span class=\"shortcut_descr\"> : run cell, select below</span></div><div class=\"quickhelp\"><span class=\"shortcut_key\">alt+enter</span><span class=\"shortcut_descr\"> : run cell, insert below</span></div><div class=\"quickhelp\"><span class=\"shortcut_key\">y</span><span class=\"shortcut_descr\"> : to code</span></div><div class=\"quickhelp\"><span class=\"shortcut_key\">m</span><span class=\"shortcut_descr\"> : to markdown</span></div><div class=\"quickhelp\"><span class=\"shortcut_key\">t</span><span class=\"shortcut_descr\"> : to raw</span></div><div class=\"quickhelp\"><span class=\"shortcut_key\">1</span><span class=\"shortcut_descr\"> : to heading 1</span></div><div class=\"quickhelp\"><span class=\"shortcut_key\">2</span><span class=\"shortcut_descr\"> : to heading 2</span></div><div class=\"quickhelp\"><span class=\"shortcut_key\">3</span><span class=\"shortcut_descr\"> : to heading 3</span></div><div class=\"quickhelp\"><span class=\"shortcut_key\">4</span><span class=\"shortcut_descr\"> : to heading 4</span></div><div class=\"quickhelp\"><span class=\"shortcut_key\">5</span><span class=\"shortcut_descr\"> : to heading 5</span></div><div class=\"quickhelp\"><span class=\"shortcut_key\">6</span><span class=\"shortcut_descr\"> : to heading 6</span></div><div class=\"quickhelp\"><span class=\"shortcut_key\">up</span><span class=\"shortcut_descr\"> : select previous cell</span></div><div class=\"quickhelp\"><span class=\"shortcut_key\">down</span><span class=\"shortcut_descr\"> : select next cell</span></div><div class=\"quickhelp\"><span class=\"shortcut_key\">k</span><span class=\"shortcut_descr\"> : select previous cell</span></div><div class=\"quickhelp\"><span class=\"shortcut_key\">j</span><span class=\"shortcut_descr\"> : select next cell</span></div><div class=\"quickhelp\"><span class=\"shortcut_key\">ctrl+k</span><span class=\"shortcut_descr\"> : move cell up</span></div></div><div class=\"box-flex0\"><div class=\"quickhelp\"><span class=\"shortcut_key\">ctrl+j</span><span class=\"shortcut_descr\"> : move cell down</span></div><div class=\"quickhelp\"><span class=\"shortcut_key\">a</span><span class=\"shortcut_descr\"> : insert cell above</span></div><div class=\"quickhelp\"><span class=\"shortcut_key\">b</span><span class=\"shortcut_descr\"> : insert cell below</span></div><div class=\"quickhelp\"><span class=\"shortcut_key\">x</span><span class=\"shortcut_descr\"> : cut cell</span></div><div class=\"quickhelp\"><span class=\"shortcut_key\">c</span><span class=\"shortcut_descr\"> : copy cell</span></div><div class=\"quickhelp\"><span class=\"shortcut_key\">v</span><span class=\"shortcut_descr\"> : paste cell below</span></div><div class=\"quickhelp\"><span class=\"shortcut_key\">z</span><span class=\"shortcut_descr\"> : undo last delete</span></div><div class=\"quickhelp\"><span class=\"shortcut_key\">d</span><span class=\"shortcut_descr\"> : delete cell (press twice)</span></div><div class=\"quickhelp\"><span class=\"shortcut_key\">shift+=</span><span class=\"shortcut_descr\"> : merge cell below</span></div><div class=\"quickhelp\"><span class=\"shortcut_key\">s</span><span class=\"shortcut_descr\"> : save notebook</span></div><div class=\"quickhelp\"><span class=\"shortcut_key\">meta+s</span><span class=\"shortcut_descr\"> : save notebook</span></div><div class=\"quickhelp\"><span class=\"shortcut_key\">ctrl+s</span><span class=\"shortcut_descr\"> : save notebook</span></div><div class=\"quickhelp\"><span class=\"shortcut_key\">l</span><span class=\"shortcut_descr\"> : toggle line numbers</span></div><div class=\"quickhelp\"><span class=\"shortcut_key\">o</span><span class=\"shortcut_descr\"> : toggle output</span></div><div class=\"quickhelp\"><span class=\"shortcut_key\">shift+o</span><span class=\"shortcut_descr\"> : toggle output</span></div><div class=\"quickhelp\"><span class=\"shortcut_key\">h</span><span class=\"shortcut_descr\"> : keyboard shortcuts</span></div><div class=\"quickhelp\"><span class=\"shortcut_key\">i</span><span class=\"shortcut_descr\"> : interrupt kernel</span></div><div class=\"quickhelp\"><span class=\"shortcut_key\">.</span><span class=\"shortcut_descr\"> : restart kernel</span></div></div></div>"
],
"output_type": "display_data"
},
{
"javascript": [
"var help = IPython.quick_help.build_command_help();\n",
"help.children().first().remove();\n",
"this.append_output({output_type: 'display_data', html: help.html()});"
],
"metadata": {},
"output_type": "display_data",
"text": [
"<IPython.core.display.Javascript at 0x10e8d1650>"
]
}
],
"prompt_number": 18
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Here the rough order in which we recommend learning the command mode shortcuts:\n",
"\n",
"1. Basic navigation: `enter`, `shift-enter`, `up/k`, `down/j`\n",
"2. Saving the notebook: `s`\n",
"2. Cell types: `y`, `m`, `1-6`, `t`\n",
"3. Cell creation and movement: `a`, `b`, `ctrl+k`, `ctrl+j`\n",
"4. Cell editing: `x`, `c`, `v`, `d`, `z`, `shift+=`\n",
"5. Kernel operations: `i`, `.`"
]
},
{
"cell_type": "heading",
"level": 2,
"metadata": {},
"source": [
"Keyboard shortcut customization"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Starting with IPython 2.0 keyboard shortcuts in command and edit mode are fully customizable. These customizations are made using the IPython JavaScript API. Here is an example that makes the `r` key available for running a cell:"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"%%javascript\n",
"\n",
"IPython.keyboard_manager.command_shortcuts.add_shortcut('r', {\n",
" help : 'run cell',\n",
" help_index : 'zz',\n",
" handler : function (event) {\n",
" IPython.notebook.execute_cell();\n",
" return false;\n",
" }}\n",
");"
],
"language": "python",
"metadata": {},
"outputs": [
{
"javascript": [
"\n",
"IPython.keyboard_manager.command_shortcuts.add_shortcut('r', {\n",
" help : 'run cell',\n",
" help_index : 'zz',\n",
" handler : function (event) {\n",
" IPython.notebook.execute_cell();\n",
" return false;\n",
" }}\n",
");"
],
"metadata": {},
"output_type": "display_data",
"text": [
"<IPython.core.display.Javascript at 0x10e8d1890>"
]
}
],
"prompt_number": 7
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"There are a couple of points to mention about this API:\n",
"\n",
"* The `help_index` field is used to sort the shortcuts in the Keyboard Shortcuts help dialog. It defaults to `zz`.\n",
"* When a handler returns `false` it indicates that the event should stop propagating and the default action should not be performed. For further details about the `event` object or event handling, see the jQuery docs.\n",
"* If you don't need a `help` or `help_index` field, you can simply pass a function as the second argument to `add_shortcut`."
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"%%javascript\n",
"\n",
"IPython.keyboard_manager.command_shortcuts.add_shortcut('r', function (event) {\n",
" IPython.notebook.execute_cell();\n",
" return false;\n",
"});"
],
"language": "python",
"metadata": {},
"outputs": [
{
"javascript": [
"\n",
"IPython.keyboard_manager.command_shortcuts.add_shortcut('r', function (event) {\n",
" IPython.notebook.execute_cell();\n",
" return false;\n",
"});"
],
"metadata": {},
"output_type": "display_data",
"text": [
"<IPython.core.display.Javascript at 0x1019baf90>"
]
}
],
"prompt_number": 11
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Likewise, to remove a shortcut, use `remove_shortcut`:"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"%%javascript\n",
"\n",
"IPython.keyboard_manager.command_shortcuts.remove_shortcut('r');"
],
"language": "python",
"metadata": {},
"outputs": [
{
"javascript": [
"\n",
"IPython.keyboard_manager.command_shortcuts.remove_shortcut('r');"
],
"metadata": {},
"output_type": "display_data",
"text": [
"<IPython.core.display.Javascript at 0x10e8d1950>"
]
}
],
"prompt_number": 8
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"If you want your keyboard shortcuts to be active for all of your notebooks, put the above API calls into your `<profile>/static/custom/custom.js` file."
]
},
{
"cell_type": "heading",
"level": 2,
"metadata": {},
"source": [
"Utilities"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We use the following functions to generate the keyboard shortcut listings above."
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"from IPython.display import Javascript, display, HTML\n",
"\n",
"t = \"\"\"var help = IPython.quick_help.build_{0}_help();\n",
"help.children().first().remove();\n",
"this.append_output({{output_type: 'display_data', html: help.html()}});\"\"\"\n",
"\n",
"def display_command_shortcuts():\n",
" display(Javascript(t.format('command')))\n",
"\n",
"def display_edit_shortcuts():\n",
" display(Javascript(t.format('edit')))\n",
"\n",
"display(HTML(\"\"\"\n",
"<style>\n",
".shortcut_key {display: inline-block; width: 15ex; text-align: right; font-family: monospace;}\n",
".shortcut_descr {display: inline-block;}\n",
"div.quickhelp {float: none; width: 100%;}\n",
"</style>\n",
"\"\"\"))"
],
"language": "python",
"metadata": {},
"outputs": [
{
"html": [
"\n",
"<style>\n",
".shortcut_key {display: inline-block; width: 15ex; text-align: right; font-family: monospace;}\n",
".shortcut_descr {display: inline-block;}\n",
"div.quickhelp {float: none; width: 100%;}\n",
"</style>\n"
],
"metadata": {},
"output_type": "display_data",
"text": [
"<IPython.core.display.HTML at 0x10e8b0710>"
]
}
],
"prompt_number": 16
}
],
"metadata": {}
}
]
}

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,180 @@
{
"metadata": {
"celltoolbar": "Slideshow",
"name": "",
"signature": "sha256:ad9cb95b14212dbf9fc8ecafa475d0e368e4cb7c7306b89628b500e7e40068b6"
},
"nbformat": 3,
"nbformat_minor": 0,
"worksheets": [
{
"cells": [
{
"cell_type": "heading",
"level": 1,
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"What is the IPython Notebook?"
]
},
{
"cell_type": "heading",
"level": 2,
"metadata": {},
"source": [
"Introduction"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The IPython Notebook is an **interactive computing environment** that enables users to author notebook documents that include: \n",
"- Live code\n",
"- Interactive widgets\n",
"- Plots\n",
"- Narrative text\n",
"- Equations\n",
"- Images\n",
"- Video\n",
"\n",
"These documents provide a **complete and self-contained record of a computation** that can be converted to various formats and shared with others using email, [Dropbox](http://dropbox.com), version control systems (like git/[GitHub](http://github.com)) or [nbviewer.ipython.org](http://nbviewer.ipython.org)."
]
},
{
"cell_type": "heading",
"level": 3,
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"Components"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The IPython Notebook combines three components:\n",
"\n",
"* **The notebook web application**: An interactive web application for writing and running code interactively and authoring notebook documents.\n",
"* **Kernels**: Separate processes started by the notebook web application that runs users' code in a given language and returns output back to the notebook web application. The kernel also handles things like computations for interactive widgets, tab completion and introspection. \n",
"* **Notebook documents**: Self-contained documents that contain a representation of all content visible in the notebook web application, including inputs and outputs of the computations, narrative\n",
"text, equations, images, and rich media representations of objects. Each notebook document has its own kernel."
]
},
{
"cell_type": "heading",
"level": 2,
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"Notebook web application"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The notebook web application enables users to:\n",
"\n",
"* **Edit code in the browser**, with automatic syntax highlighting, indentation, and tab completion/introspection.\n",
"* **Run code from the browser**, with the results of computations attached to the code which generated them.\n",
"* See the results of computations with **rich media representations**, such as HTML, LaTeX, PNG, SVG, PDF, etc.\n",
"* Create and use **interactive JavaScript wigets**, which bind interactive user interface controls and visualizations to reactive kernel side computations.\n",
"* Author **narrative text** using the [Markdown](https://daringfireball.net/projects/markdown/) markup language.\n",
"* Build **hierarchical documents** that are organized into sections with different levels of headings.\n",
"* Include mathematical equations using **LaTeX syntax in Markdown**, which are rendered in-browser by [MathJax](http://www.mathjax.org/).\n",
"* Start **parallel computing** clusters that work with IPython's interactive parallel computing libraries `IPython.parallel`."
]
},
{
"cell_type": "heading",
"level": 2,
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"Kernels"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Through IPython's kernel and messaging architecture, the Notebook allows code to be run in a range of different programming languages. For each notebook document that a user opens, the web application starts a kernel that runs the code for that notebook. Each kernel is capable of running code in a single programming language and there are kernels available in the following languages:\n",
"\n",
"* Python(https://github.com/ipython/ipython)\n",
"* Julia (https://github.com/JuliaLang/IJulia.jl)\n",
"* R (https://github.com/takluyver/IRkernel)\n",
"* Ruby (https://github.com/minrk/iruby)\n",
"* Haskell (https://github.com/gibiansky/IHaskell)\n",
"* Scala (https://github.com/Bridgewater/scala-notebook)\n",
"* node.js (https://gist.github.com/Carreau/4279371)\n",
"* Go (https://github.com/takluyver/igo)\n",
"\n",
"The default kernel runs Python code. When it is released in the Summer/Fall of 2014, IPython 3.0 will provide a simple way for users to pick which of these kernels is used for a given notebook. \n",
"\n",
"Each of these kernels communicate with the notebook web application and web browser using a JSON over ZeroMQ/WebSockets message protocol that is described [here](http://ipython.org/ipython-doc/dev/development/messaging.html). Most users don't need to know about these details, but it helps to understand that \"kernels run code.\""
]
},
{
"cell_type": "heading",
"level": 2,
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"Notebook documents"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Notebook documents contain the **inputs and outputs** of an interactive session as well as **narrative text** that accompanies the code but is not meant for execution. **Rich output** generated by running code, including HTML, images, video, and plots, is embeddeed in the notebook, which makes it a complete and self-contained record of a computation. "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"When you run the notebook web application on your computer, notebook documents are just **files on your local filesystem with a `.ipynb` extension**. This allows you to use familiar workflows for organizing your notebooks into folders and sharing them with others using email, Dropbox and version control systems."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Notebooks consist of a **linear sequence of cells**. There are four basic cell types:\n",
"\n",
"* **Code cells:** Input and output of live code that is run in the kernel\n",
"* **Markdown cells:** Narrative text with embedded LaTeX equations\n",
"* **Heading cells:** 6 levels of hierarchical organization and formatting\n",
"* **Raw cells:** Unformatted text that is included, without modification, when notebooks are converted to different formats using nbconvert\n",
"\n",
"Internally, notebook documents are **[JSON](http://en.wikipedia.org/wiki/JSO) data** with **binary values [base64]**(http://en.wikipedia.org/wiki/Base64) encoded. This allows them to be **read and manipulated programmatically** by any programming language. Because JSON is a text format, notebook documents are version control friendly.\n",
"\n",
"**Notebooks can be exported** to different static formats including HTML, reStructeredText, LaTeX, PDF, and slide shows ([reveal.js](http://lab.hakim.se/reveal-js/#/)) using IPython's `nbconvert` utility.\n",
"\n",
"Furthermore, any notebook document available from a **public URL on or GitHub can be shared** via http://nbviewer.ipython.org. This service loads the notebook document from the URL and renders it as a static web page. The resulting web page may thus be shared with others **without their needing to install IPython**."
]
}
],
"metadata": {}
}
]
}

View File

@ -1,7 +1,7 @@
{
"metadata": {
"name": "",
"signature": "sha256:056f083d2453c83c77ea0a659e9185084426263c9e42b4c0ccbb91c773d9503b"
"signature": "sha256:3b7cae0c0936f25e6ccb7acafe310c08a4162a1a7fd66fa9874a52cffa0f64f9"
},
"nbformat": 3,
"nbformat_minor": 0,
@ -182,6 +182,53 @@
"$$e^x=\\sum_{i=0}^\\infty \\frac{1}{i!}x^i$$"
]
},
{
"cell_type": "heading",
"level": 2,
"metadata": {},
"source": [
"Github flavored markdown (GFM)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The Notebook webapp support Github flavored markdown meaning that you can use triple backticks for code blocks \n",
"<pre>\n",
"```python\n",
"print \"Hello World\"\n",
"```\n",
"\n",
"```javascript\n",
"console.log(\"Hello World\")\n",
"```\n",
"</pre>\n",
"\n",
"Gives \n",
"```python\n",
"print \"Hello World\"\n",
"```\n",
"\n",
"```javascript\n",
"console.log(\"Hello World\")\n",
"```\n",
"\n",
"And a table like this : \n",
"\n",
"<pre>\n",
"| This | is |\n",
"|------|------|\n",
"| a | table| \n",
"</pre>\n",
"\n",
"A nice Html Table\n",
"\n",
"| This | is |\n",
"|------|------|\n",
"| a | table| "
]
},
{
"cell_type": "heading",
"level": 2,

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 112 KiB

View File

@ -0,0 +1,461 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>ActiveLayerIndex</key>
<integer>0</integer>
<key>ApplicationVersion</key>
<array>
<string>com.omnigroup.OmniGraffle</string>
<string>139.18.0.187838</string>
</array>
<key>AutoAdjust</key>
<true/>
<key>BackgroundGraphic</key>
<dict>
<key>Bounds</key>
<string>{{0, 0}, {576, 733}}</string>
<key>Class</key>
<string>SolidGraphic</string>
<key>ID</key>
<integer>2</integer>
<key>Style</key>
<dict>
<key>shadow</key>
<dict>
<key>Draws</key>
<string>NO</string>
</dict>
<key>stroke</key>
<dict>
<key>Draws</key>
<string>NO</string>
</dict>
</dict>
</dict>
<key>BaseZoom</key>
<integer>0</integer>
<key>CanvasOrigin</key>
<string>{0, 0}</string>
<key>ColumnAlign</key>
<integer>1</integer>
<key>ColumnSpacing</key>
<real>36</real>
<key>CreationDate</key>
<string>2014-05-27 21:39:30 +0000</string>
<key>Creator</key>
<string>bgranger</string>
<key>DisplayScale</key>
<string>1 0/72 in = 1.0000 in</string>
<key>GraphDocumentVersion</key>
<integer>8</integer>
<key>GraphicsList</key>
<array>
<dict>
<key>Class</key>
<string>LineGraphic</string>
<key>ControlPoints</key>
<array>
<string>{0, 0}</string>
<string>{-7, 8}</string>
<string>{6.9999849080788863, -8.0000033519149838}</string>
<string>{0, 0}</string>
</array>
<key>ID</key>
<integer>29</integer>
<key>Points</key>
<array>
<string>{164, 341.5}</string>
<string>{186.5, 338}</string>
<string>{196, 327.5}</string>
</array>
<key>Style</key>
<dict>
<key>stroke</key>
<dict>
<key>Bezier</key>
<true/>
<key>HeadArrow</key>
<string>0</string>
<key>Legacy</key>
<true/>
<key>LineType</key>
<integer>1</integer>
<key>TailArrow</key>
<string>0</string>
</dict>
</dict>
</dict>
<dict>
<key>Bounds</key>
<string>{{107.64779663085938, 305.5}, {69.088050842285156, 84.499992370605469}}</string>
<key>Class</key>
<string>ShapedGraphic</string>
<key>ID</key>
<integer>9</integer>
<key>ImageID</key>
<integer>1</integer>
<key>Shape</key>
<string>Rectangle</string>
<key>Style</key>
<dict>
<key>fill</key>
<dict>
<key>Draws</key>
<string>NO</string>
</dict>
<key>shadow</key>
<dict>
<key>Draws</key>
<string>NO</string>
</dict>
<key>stroke</key>
<dict>
<key>Draws</key>
<string>NO</string>
</dict>
</dict>
</dict>
<dict>
<key>Class</key>
<string>LineGraphic</string>
<key>Head</key>
<dict>
<key>ID</key>
<integer>6</integer>
<key>Position</key>
<real>0.53676468133926392</real>
</dict>
<key>ID</key>
<integer>8</integer>
<key>Points</key>
<array>
<string>{288.09285678056523, 276}</string>
<string>{288.49999833106995, 304.50001973116196}</string>
</array>
<key>Style</key>
<dict>
<key>stroke</key>
<dict>
<key>HeadArrow</key>
<string>FilledArrow</string>
<key>Legacy</key>
<true/>
<key>LineType</key>
<integer>1</integer>
<key>TailArrow</key>
<string>0</string>
</dict>
</dict>
<key>Tail</key>
<dict>
<key>ID</key>
<integer>7</integer>
</dict>
</dict>
<dict>
<key>Bounds</key>
<string>{{207, 263}, {162, 13}}</string>
<key>Class</key>
<string>ShapedGraphic</string>
<key>FitText</key>
<string>YES</string>
<key>Flow</key>
<string>Resize</string>
<key>ID</key>
<integer>7</integer>
<key>Shape</key>
<string>Rectangle</string>
<key>Style</key>
<dict>
<key>fill</key>
<dict>
<key>Draws</key>
<string>NO</string>
</dict>
<key>shadow</key>
<dict>
<key>Draws</key>
<string>NO</string>
</dict>
<key>stroke</key>
<dict>
<key>Draws</key>
<string>NO</string>
</dict>
</dict>
<key>Text</key>
<dict>
<key>Pad</key>
<integer>0</integer>
<key>Text</key>
<string>{\rtf1\ansi\ansicpg1252\cocoartf1265\cocoasubrtf190
\cocoascreenfonts1{\fonttbl\f0\fnil\fcharset0 xkcd-Regular;}
{\colortbl;\red255\green255\blue255;}
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
\f0\fs20 \cf0 Interactive Computing Protocol}</string>
<key>VerticalPad</key>
<integer>0</integer>
</dict>
<key>Wrap</key>
<string>NO</string>
</dict>
<dict>
<key>Class</key>
<string>LineGraphic</string>
<key>Head</key>
<dict>
<key>ID</key>
<integer>1</integer>
</dict>
<key>ID</key>
<integer>6</integer>
<key>Points</key>
<array>
<string>{252, 304.50001973116196}</string>
<string>{320, 304.50001973116196}</string>
</array>
<key>Style</key>
<dict>
<key>stroke</key>
<dict>
<key>HeadArrow</key>
<string>FilledArrow</string>
<key>Legacy</key>
<true/>
<key>LineType</key>
<integer>1</integer>
<key>Pattern</key>
<integer>1</integer>
<key>TailArrow</key>
<string>FilledArrow</string>
</dict>
</dict>
<key>Tail</key>
<dict>
<key>ID</key>
<integer>5</integer>
</dict>
</dict>
<dict>
<key>Bounds</key>
<string>{{186.5, 286.5}, {65, 36}}</string>
<key>Class</key>
<string>ShapedGraphic</string>
<key>ID</key>
<integer>5</integer>
<key>Shape</key>
<string>Rectangle</string>
<key>Style</key>
<dict>
<key>shadow</key>
<dict>
<key>Draws</key>
<string>NO</string>
</dict>
</dict>
<key>Text</key>
<dict>
<key>Text</key>
<string>{\rtf1\ansi\ansicpg1252\cocoartf1265\cocoasubrtf190
\cocoascreenfonts1{\fonttbl\f0\fnil\fcharset0 xkcd-Regular;}
{\colortbl;\red255\green255\blue255;}
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
\f0\fs20 \cf0 Frontend}</string>
</dict>
</dict>
<dict>
<key>Bounds</key>
<string>{{320.5, 286.5}, {65, 36}}</string>
<key>Class</key>
<string>ShapedGraphic</string>
<key>ID</key>
<integer>1</integer>
<key>Shape</key>
<string>Rectangle</string>
<key>Style</key>
<dict>
<key>shadow</key>
<dict>
<key>Draws</key>
<string>NO</string>
</dict>
</dict>
<key>Text</key>
<dict>
<key>Text</key>
<string>{\rtf1\ansi\ansicpg1252\cocoartf1265\cocoasubrtf190
\cocoascreenfonts1{\fonttbl\f0\fnil\fcharset0 xkcd-Regular;}
{\colortbl;\red255\green255\blue255;}
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
\f0\fs20 \cf0 Kernel}</string>
</dict>
</dict>
</array>
<key>GridInfo</key>
<dict/>
<key>GuidesLocked</key>
<string>NO</string>
<key>GuidesVisible</key>
<string>YES</string>
<key>HPages</key>
<integer>1</integer>
<key>ImageCounter</key>
<integer>2</integer>
<key>ImageLinkBack</key>
<array>
<dict/>
</array>
<key>ImageList</key>
<array>
<string>image1.png</string>
</array>
<key>KeepToScale</key>
<false/>
<key>Layers</key>
<array>
<dict>
<key>Lock</key>
<string>NO</string>
<key>Name</key>
<string>Layer 1</string>
<key>Print</key>
<string>YES</string>
<key>View</key>
<string>YES</string>
</dict>
</array>
<key>LayoutInfo</key>
<dict>
<key>Animate</key>
<string>NO</string>
<key>circoMinDist</key>
<real>18</real>
<key>circoSeparation</key>
<real>0.0</real>
<key>layoutEngine</key>
<string>dot</string>
<key>neatoSeparation</key>
<real>0.0</real>
<key>twopiSeparation</key>
<real>0.0</real>
</dict>
<key>LinksVisible</key>
<string>NO</string>
<key>MagnetsVisible</key>
<string>NO</string>
<key>MasterSheets</key>
<array/>
<key>ModificationDate</key>
<string>2014-05-27 22:28:18 +0000</string>
<key>Modifier</key>
<string>bgranger</string>
<key>NotesVisible</key>
<string>NO</string>
<key>Orientation</key>
<integer>2</integer>
<key>OriginVisible</key>
<string>NO</string>
<key>PageBreaks</key>
<string>YES</string>
<key>PrintInfo</key>
<dict>
<key>NSBottomMargin</key>
<array>
<string>float</string>
<string>41</string>
</array>
<key>NSHorizonalPagination</key>
<array>
<string>coded</string>
<string>BAtzdHJlYW10eXBlZIHoA4QBQISEhAhOU051bWJlcgCEhAdOU1ZhbHVlAISECE5TT2JqZWN0AIWEASqEhAFxlwCG</string>
</array>
<key>NSLeftMargin</key>
<array>
<string>float</string>
<string>18</string>
</array>
<key>NSPaperSize</key>
<array>
<string>size</string>
<string>{612, 792}</string>
</array>
<key>NSPrintReverseOrientation</key>
<array>
<string>int</string>
<string>0</string>
</array>
<key>NSRightMargin</key>
<array>
<string>float</string>
<string>18</string>
</array>
<key>NSTopMargin</key>
<array>
<string>float</string>
<string>18</string>
</array>
</dict>
<key>PrintOnePage</key>
<false/>
<key>ReadOnly</key>
<string>NO</string>
<key>RowAlign</key>
<integer>1</integer>
<key>RowSpacing</key>
<real>36</real>
<key>SheetTitle</key>
<string>Canvas 1</string>
<key>SmartAlignmentGuidesActive</key>
<string>YES</string>
<key>SmartDistanceGuidesActive</key>
<string>YES</string>
<key>UniqueID</key>
<integer>1</integer>
<key>UseEntirePage</key>
<false/>
<key>VPages</key>
<integer>1</integer>
<key>WindowInfo</key>
<dict>
<key>CurrentSheet</key>
<integer>0</integer>
<key>ExpandedCanvases</key>
<array>
<dict>
<key>name</key>
<string>Canvas 1</string>
</dict>
</array>
<key>Frame</key>
<string>{{277, 7}, {832, 871}}</string>
<key>ListView</key>
<true/>
<key>OutlineWidth</key>
<integer>142</integer>
<key>RightSidebar</key>
<false/>
<key>ShowRuler</key>
<true/>
<key>Sidebar</key>
<true/>
<key>SidebarWidth</key>
<integer>120</integer>
<key>VisibleRegion</key>
<string>{{96.5, 197.5}, {348.5, 366}}</string>
<key>Zoom</key>
<real>2</real>
<key>ZoomValues</key>
<array>
<array>
<string>Canvas 1</string>
<real>2</real>
<real>1</real>
</array>
</array>
</dict>
</dict>
</plist>

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

View File

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 15 KiB