{ "cells": [ { "cell_type": "markdown", "id": "nominated-efficiency", "metadata": {}, "source": [ "# Diagram Widget\n", "\n", "The same _renderer_ that powers the [Diagram Document](./Diagram%20Document.ipynb) can be used as a computable _Jupyter Widget_, which offers even more power than the [Diagram Rich Display](./Diagram%20Rich%20Display.ipynb)." ] }, { "cell_type": "code", "execution_count": null, "id": "b925a258-e3ab-4127-8537-f2efc9b0bd59", "metadata": { "tags": [] }, "outputs": [], "source": [ "try: await __import__(\"piplite\").install('ipydrawio-widgets'); \n", "except: pass" ] }, { "cell_type": "code", "execution_count": null, "id": "cathedral-schema", "metadata": {}, "outputs": [], "source": [ "from ipywidgets import HBox, VBox, Textarea, jslink, jsdlink, FloatSlider, IntSlider, Checkbox, Text, SelectMultiple, Accordion\n", "from lxml import etree\n", "from traitlets import observe, link, dlink\n", "from ipydrawio_widgets import Diagram\n", "\n", "diagram = Diagram(layout=dict(min_height=\"80vh\", flex=\"1\"))\n", "box = HBox([diagram])\n", "box" ] }, { "cell_type": "markdown", "id": "illegal-islam", "metadata": {}, "source": [ "## value\n", "\n", "A `Diagram.source`'s `value` trait is the raw drawio XML. You can use one document for multiple diagrams.\n", "\n", "> [graphviz2drawio](https://pypi.org/project/graphviz2drawio) is recommended for getting to **give me some drawio XML from my data right now**. " ] }, { "cell_type": "code", "execution_count": null, "id": "printable-ridge", "metadata": {}, "outputs": [], "source": [ "Diagram(source=diagram.source, layout=dict(min_height=\"400px\"))" ] }, { "cell_type": "code", "execution_count": null, "id": "behavioral-madonna", "metadata": {}, "outputs": [], "source": [ "diagram.source.value = '''\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "'''" ] }, { "cell_type": "code", "execution_count": null, "id": "intimate-jamaica", "metadata": {}, "outputs": [], "source": [ "value = Textarea(description=\"value\", rows=20)\n", "controls = Accordion([value])\n", "controls.set_title(0, \"value\")\n", "jslink((diagram.source, \"value\"), (value, \"value\"))\n", "box.children = [controls, diagram]" ] }, { "cell_type": "markdown", "id": "understanding-notion", "metadata": {}, "source": [ "There are a number of challenges in using it as a protocol:\n", "- includes hostname (ick!)\n", "- includes etag\n", "- stripping these out creates flicker when updating\n", "\n", "At present, tools like jinja2, which work directly with XML, or `lxml`, which can work at a higher level, with e.g. XPath. \n", "\n", "> Stay tuned for better tools for working with this format with e.g. `networkx`" ] }, { "cell_type": "markdown", "id": "dominican-economics", "metadata": {}, "source": [ "## Interactive state\n", "\n", "A `Diagram` exposes a number of parts of both the content and interactive state of the editor." ] }, { "cell_type": "code", "execution_count": null, "id": "ready-reviewer", "metadata": {}, "outputs": [], "source": [ "zoom = FloatSlider(description=\"zoom\", min=0.01)\n", "scroll_x, scroll_y = [FloatSlider(description=f\"scroll {x}\", min=-1e5, max=1e5) for x in \"xy\"]\n", "current_page = IntSlider(description=\"page\")\n", "jslink((diagram, \"zoom\"), (zoom, \"value\"))\n", "jslink((diagram, \"scroll_x\"), (scroll_x, \"value\"))\n", "jslink((diagram, \"scroll_y\"), (scroll_y, \"value\"))\n", "jslink((diagram, \"current_page\"), (current_page, \"value\"))\n", "\n", "controls.children = [VBox([zoom, scroll_x, scroll_y, current_page]), value]\n", "controls._titles = {\"0\": \"ui\", \"1\": \"value\"}" ] }, { "cell_type": "code", "execution_count": null, "id": "alleged-decimal", "metadata": {}, "outputs": [], "source": [ "selected_cells = SelectMultiple(description=\"selected\")\n", "\n", "dlink((diagram, \"cell_ids\"), (selected_cells, \"options\"))\n", "link((diagram, \"selected_cells\"), (selected_cells, \"value\"))\n", "\n", "controls.children = [VBox([zoom, scroll_x, scroll_y, current_page]), VBox([selected_cells]), value]\n", "controls._titles = {\"0\": \"ui\", \"1\": \"selection\", \"2\": \"value\"}\n", "\n", "HBox([selected_cells])" ] }, { "cell_type": "markdown", "id": "sonic-airline", "metadata": {}, "source": [ "## Page Information\n", "`Diagrams` actually describe a \"real thing\", measured in inches." ] }, { "cell_type": "code", "execution_count": null, "id": "cutting-closer", "metadata": {}, "outputs": [], "source": [ "page_format = {\n", " k: IntSlider(description=k, value=v, min=0, max=1e5)\n", " for k,v in diagram.page_format.items()\n", "}\n", "\n", "def update_format(*_):\n", " diagram.page_format = {\n", " k: v.value for k, v in page_format.items()\n", " }\n", "\n", "def update_sliders(*_):\n", " for k, v in page_format.items():\n", " v.value = diagram.page_format[k]\n", " \n", "[v.observe(update_format, \"value\") for k, v in page_format.items()]\n", "[diagram.observe(update_sliders, \"page_format\")]\n", "\n", "\n", "controls.children = [VBox([zoom, scroll_x, scroll_y, current_page]), VBox([selected_cells]), VBox([*page_format.values()]), value]\n", "controls._titles = {\"0\": \"ui\", \"1\": \"selection\", \"2\": \"page\", \"3\": \"value\"}" ] }, { "cell_type": "markdown", "id": "numerical-truck", "metadata": {}, "source": [ "## Grid\n", "\n", "The styling of the on-screen grid is cutomizable. This typically _won't_ be included in export to e.g. SVG." ] }, { "cell_type": "code", "execution_count": null, "id": "simplified-spell", "metadata": {}, "outputs": [], "source": [ "grid_enabled = Checkbox(description=\"grid\")\n", "grid_size = FloatSlider(description=\"grid size\")\n", "grid_color = Text(\"#66666666\", description=\"grid color\")\n", "jslink((diagram, \"grid_enabled\"), (grid_enabled, \"value\"))\n", "jslink((diagram, \"grid_size\"), (grid_size, \"value\"))\n", "jslink((diagram, \"grid_color\"), (grid_color, \"value\"))\n", "\n", "controls.children = [VBox([zoom, scroll_x, scroll_y, current_page]), VBox([selected_cells]), VBox([*page_format.values()]), VBox([ grid_enabled, grid_size, grid_color]), value]\n", "controls._titles = {\"0\": \"ui\", \"1\": \"selection\", \"2\": \"page\", \"3\":\"grid\", \"4\": \"value\"}" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.11.0" } }, "nbformat": 4, "nbformat_minor": 5 }