Widget Tester.ipynb
278 lines
| 11.1 KiB
| text/plain
|
TextLexer
Jonathan Frederic
|
r14429 | { | |
"metadata": { | |||
"name": "" | |||
}, | |||
"nbformat": 3, | |||
"nbformat_minor": 0, | |||
"worksheets": [ | |||
{ | |||
"cells": [ | |||
{ | |||
"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": [ | |||
"This notebook shows how widgets can be used to manipulate the properties of other widgets." | |||
] | |||
}, | |||
{ | |||
"cell_type": "markdown", | |||
"metadata": {}, | |||
"source": [ | |||
"To list the properties of a widget and allow the user to modify them, a function that keeps widgets in sync with traits is required. This function will syncronize a traitlet of one widget with a traitlet of another widget. The method also supports one way syncronization of types that have string representations with string traits." | |||
] | |||
}, | |||
{ | |||
"cell_type": "code", | |||
"collapsed": false, | |||
"input": [ | |||
"def sync_widgets_properties(widget_a, property_a, widget_b, property_b, str_rep=False):\n", | |||
" def set_property_a(name, old, new):\n", | |||
" if old != new:\n", | |||
" if str_rep:\n", | |||
" setattr(widget_a, property_a, str(new))\n", | |||
" else:\n", | |||
" setattr(widget_a, property_a, new)\n", | |||
" def set_property_b(name, old, new):\n", | |||
" if old != new and not str_rep:\n", | |||
" setattr(widget_b, property_b, new)\n", | |||
" widget_a.on_trait_change(set_property_b, property_a)\n", | |||
" widget_b.on_trait_change(set_property_a, property_b)\n", | |||
" if str_rep:\n", | |||
" setattr(widget_a, property_a, str(getattr(widget_b, property_b)))\n", | |||
" else:\n", | |||
" setattr(widget_a, property_a, getattr(widget_b, property_b))\n", | |||
" \n", | |||
" return widget_a" | |||
], | |||
"language": "python", | |||
"metadata": {}, | |||
"outputs": [], | |||
"prompt_number": 2 | |||
}, | |||
{ | |||
"cell_type": "markdown", | |||
"metadata": {}, | |||
"source": [ | |||
"This function will create a best match widget to represent a traitlet of another widget. The function will then bind the two widgets using the `sync_widget_properties` method above." | |||
] | |||
}, | |||
{ | |||
"cell_type": "code", | |||
"collapsed": false, | |||
"input": [ | |||
"def create_hooked_widget(control, key):\n", | |||
" property_type = type(getattr(control, key))\n", | |||
" \n", | |||
" if key == \"orientation\":\n", | |||
" return sync_widgets_properties(widgets.SelectionWidget(values=['vertical', 'horizontal'], default_view_name='ToggleButtonsView'), 'value', control, key)\n", | |||
" elif property_type is int:\n", | |||
" return sync_widgets_properties(widgets.IntWidget(), 'value', control, key)\n", | |||
" elif property_type is float:\n", | |||
" return sync_widgets_properties(widgets.FloatWidget(), 'value', control, key)\n", | |||
" elif property_type is bool:\n", | |||
" return sync_widgets_properties(widgets.BoolWidget(), 'value', control, key)\n", | |||
" elif property_type is str or property_type is unicode:\n", | |||
" return sync_widgets_properties(widgets.StringWidget(), 'value', control, key)\n", | |||
" else:\n", | |||
" return sync_widgets_properties(widgets.StringWidget(disabled=True), 'value', control, key, str_rep=True)\n", | |||
" " | |||
], | |||
"language": "python", | |||
"metadata": {}, | |||
"outputs": [], | |||
"prompt_number": 3 | |||
}, | |||
{ | |||
"cell_type": "markdown", | |||
"metadata": {}, | |||
"source": [ | |||
"This function creates a modal that allows the user to read the doc string associated with a callable. The user can then invoke the callbable from the same modal." | |||
] | |||
}, | |||
{ | |||
"cell_type": "code", | |||
"collapsed": false, | |||
"input": [ | |||
"modals = {}\n", | |||
"def get_method_modal(control, method_name, parent=None):\n", | |||
" if not method_name in dir(control):\n", | |||
" return None\n", | |||
" if not control in modals:\n", | |||
" modals[control] = {}\n", | |||
" if not method_name in modals[control]:\n", | |||
" new_modal = widgets.ContainerWidget(default_view_name=\"ModalView\")\n", | |||
" new_modal.description=\"Invoke \" + method_name\n", | |||
" new_modal.button_text = method_name + \"(...)\"\n", | |||
" \n", | |||
" doc_str = 'No doc string'\n", | |||
" try:\n", | |||
" doc_str = '<pre>' + getattr(control, method_name).__doc__ + '</pre>'\n", | |||
" except:\n", | |||
" pass\n", | |||
" \n", | |||
Jonathan Frederic
|
r14446 | " doc_label = widgets.StringWidget(parent=new_modal,default_view_name='HTMLView', value=doc_str)\n", | |
Jonathan Frederic
|
r14429 | " doc_label.set_css('color', 'blue')\n", | |
" exec_box = widgets.ContainerWidget(parent=new_modal)\n", | |||
" exec_box.hbox()\n", | |||
" exec_box.pack_center()\n", | |||
" exec_box.align_center()\n", | |||
Jonathan Frederic
|
r14446 | " open_label = widgets.StringWidget(parent=exec_box,default_view_name='HTMLView', value=method_name+'( ')\n", | |
Jonathan Frederic
|
r14429 | " exec_str = widgets.StringWidget(parent=exec_box)\n", | |
Jonathan Frederic
|
r14446 | " close_label = widgets.StringWidget(parent=exec_box,default_view_name='HTMLView', value=' )')\n", | |
Jonathan Frederic
|
r14429 | " button_row = widgets.ContainerWidget(parent=new_modal)\n", | |
" button_row.hbox()\n", | |||
" button_row.pack_end()\n", | |||
" button_box = widgets.ContainerWidget(parent=button_row)\n", | |||
" button_box.flex0()\n", | |||
" exec_button = widgets.ButtonWidget(parent=button_box, description=\"Execute\")\n", | |||
" \n", | |||
" def handle_method_exec():\n", | |||
" my_control = control\n", | |||
" exec \"my_control.\" + method_name.replace('\\n', '') + \"(\" + exec_str.value + \")\" in globals(), locals()\n", | |||
" exec_button.on_click(handle_method_exec)\n", | |||
" exec_str.on_submit(handle_method_exec)\n", | |||
" \n", | |||
" if parent is not None:\n", | |||
" new_modal.parent = parent\n", | |||
" \n", | |||
" modals[control][method_name] = new_modal\n", | |||
" display(new_modal)\n", | |||
" return modals[control][method_name]" | |||
], | |||
"language": "python", | |||
"metadata": {}, | |||
"outputs": [], | |||
"prompt_number": 4 | |||
}, | |||
{ | |||
"cell_type": "markdown", | |||
"metadata": {}, | |||
"source": [ | |||
"This function renders the control panel." | |||
] | |||
}, | |||
{ | |||
"cell_type": "code", | |||
"collapsed": false, | |||
"input": [ | |||
"def hook_control(control, parent=None):\n", | |||
" explorer = widgets.ContainerWidget()\n", | |||
" if parent is not None:\n", | |||
" explorer.parent = parent\n", | |||
" explorer.hbox()\n", | |||
" \n", | |||
" viewer = widgets.ContainerWidget(parent=explorer)\n", | |||
" viewer.set_css({\n", | |||
" 'background': 'white',\n", | |||
" 'border': '1px solid #000',\n", | |||
" 'overflow': 'hidden',\n", | |||
" })\n", | |||
" viewer.flex2()\n", | |||
" \n", | |||
" control.parent = viewer\n", | |||
" \n", | |||
" side = widgets.ContainerWidget(parent=explorer)\n", | |||
" side.flex1()\n", | |||
" \n", | |||
" side_tab = widgets.MulticontainerWidget(parent=side)\n", | |||
" side_tab.set_css('margin', '5px')\n", | |||
" \n", | |||
" properties = widgets.ContainerWidget(parent=side_tab)\n", | |||
" methods = widgets.ContainerWidget(parent=side_tab)\n", | |||
" side_tab.set_title(0, 'Properties')\n", | |||
" side_tab.set_title(1, 'Methods')\n", | |||
" \n", | |||
" for key in sorted(control.keys):\n", | |||
" property_control = create_hooked_widget(control, key)\n", | |||
" property_control.parent = properties\n", | |||
" property_control.description = key + ':'\n", | |||
" \n", | |||
" methods.vbox()\n", | |||
" methods.set_css('overflow', 'hidden')\n", | |||
" \n", | |||
" methods_container = widgets.ContainerWidget(parent=methods)\n", | |||
" methods_container.flex1()\n", | |||
" methods_buttons = widgets.ContainerWidget(parent=methods)\n", | |||
" methods_buttons.flex0()\n", | |||
" methods_buttons.hbox()\n", | |||
" methods_buttons.pack_end()\n", | |||
" methods_buttons.set_css({\n", | |||
" 'padding-top': '5px',\n", | |||
" 'padding-right': '50px',\n", | |||
" })\n", | |||
" \n", | |||
" execute_button = widgets.ButtonWidget(parent=methods_buttons, description=\"Invoke\")\n", | |||
" \n", | |||
" method_list = widgets.SelectionWidget(parent=methods_container, default_view_name=\"ListBoxView\")\n", | |||
" method_list.description = \"Names:\"\n", | |||
" method_list.set_css('height', '400px')\n", | |||
" method_list.values = [attr_name for attr_name in dir(control) if callable(getattr(control, attr_name)) and not attr_name.startswith('_')]\n", | |||
" \n", | |||
" def handle_execute_method():\n", | |||
" get_method_modal(control, method_list.value, parent=parent)\n", | |||
" execute_button.on_click(handle_execute_method)\n", | |||
" \n", | |||
" display(explorer) \n", | |||
" explorer.add_class('well')\n", | |||
" return explorer" | |||
], | |||
"language": "python", | |||
"metadata": {}, | |||
"outputs": [], | |||
"prompt_number": 5 | |||
}, | |||
{ | |||
"cell_type": "markdown", | |||
"metadata": {}, | |||
"source": [ | |||
"This final bit of code allows the user to select what control and view he/she wants to manipulate." | |||
] | |||
}, | |||
{ | |||
"cell_type": "code", | |||
"collapsed": false, | |||
"input": [ | |||
"control_tester = widgets.ContainerWidget()\n", | |||
"widget_names = [widget_name for widget_name in dir(widgets) if widget_name.endswith('Widget') and widget_name != \"Widget\"]\n", | |||
"widget_selector = widgets.SelectionWidget(parent=control_tester, description=\"Widget type:\", values=widget_names)\n", | |||
"view_name = widgets.StringWidget(parent=control_tester, description=\"View name (optional):\")\n", | |||
"display_button_container = widgets.ContainerWidget(parent=control_tester)\n", | |||
"display_button_container.hbox()\n", | |||
"display_button_container.pack_end()\n", | |||
"display_button_container.set_css(\"padding\", \"5px\")\n", | |||
"display_button = widgets.ButtonWidget(parent=display_button_container, description=\"Display\")\n", | |||
"display(control_tester)\n", | |||
"\n", | |||
"last_displayed = [None]\n", | |||
"def handle_display():\n", | |||
" if last_displayed[0] is not None:\n", | |||
" last_displayed[0].close()\n", | |||
" widget_type = getattr(widgets, widget_selector.value)\n", | |||
" widget = widget_type()\n", | |||
" if len(view_name.value) > 0:\n", | |||
" widget.default_view_name = view_name.value\n", | |||
" last_displayed[0] = hook_control(widget)\n", | |||
"display_button.on_click(handle_display)\n", | |||
"view_name.on_submit(handle_display)\n" | |||
], | |||
"language": "python", | |||
"metadata": {}, | |||
"outputs": [], | |||
"prompt_number": 6 | |||
} | |||
], | |||
"metadata": {} | |||
} | |||
] | |||
} |