diff --git a/examples/widgets/Dialogs.ipynb b/examples/widgets/Dialogs.ipynb new file mode 100644 index 0000000..6e71286 --- /dev/null +++ b/examples/widgets/Dialogs.ipynb @@ -0,0 +1,200 @@ +{ + "metadata": { + "name": "" + }, + "nbformat": 3, + "nbformat_minor": 0, + "worksheets": [ + { + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Simple example notebook that shows how one can use widgets to build custom dialogs." + ] + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "from IPython.html import widgets\n", + "from IPython.display import display" + ], + "language": "python", + "metadata": {}, + "outputs": [], + "prompt_number": 1 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "By using Bootstrap's modal class and ContainerWidgets, we can build a simple dialog window." + ] + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "def scrub_text_html(text):\n", + " text = text.replace('&', '&')\n", + " text = text.replace(' ', ' ')\n", + " text = text.replace('<', '<')\n", + " text = text.replace('>', '>')\n", + " text = text.replace('\\n', '
\\n')\n", + " return text\n", + "\n", + "def create_dialog(title=None, on_hidden=None):\n", + " dialog = widgets.ContainerWidget(visible=False)\n", + " dialog_header = widgets.ContainerWidget(parent=dialog)\n", + " dialog_header_close = widgets.ButtonWidget(parent=dialog_header, description = '×')\n", + " dialog_header_label = widgets.StringWidget(parent=dialog_header, default_view_name='LabelView')\n", + " dialog_body = widgets.ContainerWidget(parent=dialog)\n", + " dialog_footer = widgets.ContainerWidget(parent=dialog)\n", + " \n", + " if title is None or title == '':\n", + " title = ' '\n", + " dialog_header_label.value = '

%s

' % scrub_text_html(title)\n", + " \n", + " def handle_close():\n", + " dialog.visible = False\n", + " if on_hidden is not None:\n", + " on_hidden(dialog)\n", + " dialog_header_close.on_click(handle_close)\n", + " \n", + " display(dialog)\n", + " \n", + " dialog_header.add_class('modal-header')\n", + " dialog_body.add_class('modal-body')\n", + " dialog_footer.add_class('modal-footer')\n", + " dialog.add_class('modal')\n", + " \n", + " dialog_header_close.remove_class('btn')\n", + " dialog_header_close.add_class('close')\n", + " \n", + " return dialog_body, dialog_footer, dialog\n" + ], + "language": "python", + "metadata": {}, + "outputs": [], + "prompt_number": 2 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Using this `show_dialog` method, custom dialogs can be made using widgets. Below is an example of a Yes/No dialog." + ] + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "# Since Python has a global thread lock, everything runs on a single thread.\n", + "# Because of this, we use an asynronous model (callbacks).\n", + "def show_yes_no(prompt, yes_callback=None, no_callback=None, title=None):\n", + " \n", + " def handle_hidden(dialog_window):\n", + " if no_callback is not None:\n", + " no_callback()\n", + " dialog_window.close()\n", + " \n", + " (dialog_body, dialog_footer, dialog_window) = create_dialog(title=title, on_hidden=handle_hidden)\n", + " \n", + " def handle_yes():\n", + " dialog_window.visible = False\n", + " if yes_callback is not None:\n", + " yes_callback()\n", + " dialog_window.close()\n", + " \n", + " def handle_no():\n", + " dialog_window.visible = False\n", + " handle_hidden(dialog_window)\n", + " \n", + " yes_button = widgets.ButtonWidget(parent=dialog_footer, description='Yes')\n", + " yes_button.on_click(handle_yes)\n", + " no_button = widgets.ButtonWidget(parent=dialog_footer, description='No')\n", + " no_button.on_click(handle_no)\n", + " prompt_label = widgets.StringWidget(parent=dialog_body, value=scrub_text_html(prompt), default_view_name='LabelView')\n", + " \n", + " display(yes_button)\n", + " display(no_button)\n", + " display(prompt_label)\n", + " \n", + " yes_button.add_class('btn-success')\n", + " no_button.add_class('btn-danger')\n", + " \n", + " dialog_window.visible=True\n", + " \n", + " " + ], + "language": "python", + "metadata": {}, + "outputs": [], + "prompt_number": 3 + }, + { + "cell_type": "heading", + "level": 1, + "metadata": {}, + "source": [ + "Test" + ] + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "def yes():\n", + " show_yes_no(\"Do you want to show the dialog again?\", yes, title=\"Self displaying dialog\")\n", + "yes()" + ], + "language": "python", + "metadata": {}, + "outputs": [], + "prompt_number": 4 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Dialog result handlers can contain nested dialogs. The following example shows how syncronous logic can be simulated using closures." + ] + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "title = \"Interactive Story\"\n", + "def open_door():\n", + " show_yes_no(\"The house is empty. You are tired and decide to sleep. You live to see another day.\")\n", + "\n", + "def stay_outside():\n", + " def fight():\n", + " show_yes_no(\"You try to fight the wolves but die in the process.\", title=title)\n", + " \n", + " def panic():\n", + " def flight():\n", + " show_yes_no(\"You run as fast as you can. You manage to escape the\\n\" + \\\n", + " \"wolves but the cold is beginning to get to you. You\\n\" + \\\n", + " \"sit in the snow to take a nap. You freeze and die.\", title=title)\n", + " \n", + " show_yes_no(\"You panic. Do you enter the cabin now?\", open_door, flight, title=title)\n", + " \n", + " show_yes_no(\"A pack of wolves approach. Do you want to fight them?\", fight, panic, title=title)\n", + "\n", + "show_yes_no(\"You are standing outside in a blizzard on a cold winter night.\\n\" + \\\n", + " \"A warm cabin with the lights on is in front of you.\\n\\n\" + \\\n", + " \"Do you want to enter the cabin?\", open_door, stay_outside, title=title)\n" + ], + "language": "python", + "metadata": {}, + "outputs": [], + "prompt_number": 5 + } + ], + "metadata": {} + } + ] +} \ No newline at end of file