ipydrawio/docs/Diagram Widget.ipynb

296 wiersze
9.8 KiB
Plaintext

{
"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": [
"if __name__ == \"__main__\" and \"pyodide\" in __import__(\"sys\").modules:\n",
" %pip install -q ipydrawio-widgets"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "cathedral-schema",
"metadata": {},
"outputs": [],
"source": [
"from ipydrawio_widgets import Diagram\n",
"from ipywidgets import (\n",
" Accordion,\n",
" Checkbox,\n",
" FloatSlider,\n",
" HBox,\n",
" IntSlider,\n",
" SelectMultiple,\n",
" Text,\n",
" Textarea,\n",
" VBox,\n",
" jslink,\n",
")\n",
"from traitlets import dlink, link\n",
"\n",
"diagram = Diagram(layout={\"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={\"min_height\": \"400px\"})"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "behavioral-madonna",
"metadata": {},
"outputs": [],
"source": [
"diagram.source.value = \"\"\"<mxfile version=\"13.6.10\">\n",
" <diagram id=\"x\" name=\"Page-1\">\n",
" <mxGraphModel dx=\"1164\" dy=\"293\" grid=\"1\" gridSize=\"10\" guides=\"1\" tooltips=\"1\" connect=\"1\" arrows=\"1\" fold=\"1\" page=\"1\" pageScale=\"1\" pageWidth=\"850\" pageHeight=\"1100\" math=\"0\" shadow=\"0\">\n",
" <root>\n",
" <mxCell id=\"0\"/>\n",
" <mxCell id=\"1\" parent=\"0\"/>\n",
" <mxCell id=\"2\" value=\"\" style=\"edgeStyle=entityRelationEdgeStyle;startArrow=none;endArrow=none;segment=10;curved=1;\" parent=\"1\" source=\"4\" target=\"5\" edge=\"1\">\n",
" <mxGeometry relative=\"1\" as=\"geometry\"/>\n",
" </mxCell>\n",
" <mxCell id=\"3\" value=\"\" style=\"edgeStyle=entityRelationEdgeStyle;startArrow=none;endArrow=none;segment=10;curved=1;\" parent=\"1\" source=\"4\" target=\"6\" edge=\"1\">\n",
" <mxGeometry relative=\"1\" as=\"geometry\">\n",
" <mxPoint x=\"260\" y=\"160\" as=\"sourcePoint\"/>\n",
" </mxGeometry>\n",
" </mxCell>\n",
" <UserObject label=\"The Big Idea\" treeRoot=\"1\" id=\"4\">\n",
" <mxCell style=\"ellipse;whiteSpace=wrap;html=1;align=center;collapsible=0;container=1;recursiveResize=0;\" parent=\"1\" vertex=\"1\">\n",
" <mxGeometry x=\"300\" y=\"140\" width=\"100\" height=\"40\" as=\"geometry\"/>\n",
" </mxCell>\n",
" </UserObject>\n",
" <mxCell id=\"5\" value=\"Branch\" style=\"whiteSpace=wrap;html=1;shape=partialRectangle;top=0;left=0;bottom=1;right=0;points=[[0,1],[1,1]];strokeColor=#000000;fillColor=none;align=center;verticalAlign=bottom;routingCenterY=0.5;snapToPoint=1;collapsible=0;container=1;recursiveResize=0;autosize=1;\" parent=\"1\" vertex=\"1\">\n",
" <mxGeometry x=\"460\" y=\"120\" width=\"80\" height=\"20\" as=\"geometry\"/>\n",
" </mxCell>\n",
" <mxCell id=\"6\" value=\"Sub Topic\" style=\"whiteSpace=wrap;html=1;rounded=1;arcSize=50;align=center;verticalAlign=middle;collapsible=0;container=1;recursiveResize=0;strokeWidth=1;autosize=1;spacing=4;\" parent=\"1\" vertex=\"1\">\n",
" <mxGeometry x=\"460\" y=\"160\" width=\"72\" height=\"26\" as=\"geometry\"/>\n",
" </mxCell>\n",
" </root>\n",
" </mxGraphModel>\n",
" </diagram>\n",
"</mxfile>\"\"\""
]
},
{
"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 = (\n",
" FloatSlider(description=f\"scroll {x}\", min=-1e5, max=1e5) for x in \"xy\"\n",
")\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 = [\n",
" VBox([zoom, scroll_x, scroll_y, current_page]),\n",
" VBox([selected_cells]),\n",
" value,\n",
"]\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",
"\n",
"def update_format(*_):\n",
" diagram.page_format = {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",
"\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 = [\n",
" VBox([zoom, scroll_x, scroll_y, current_page]),\n",
" VBox([selected_cells]),\n",
" VBox([*page_format.values()]),\n",
" value,\n",
"]\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 = [\n",
" VBox([zoom, scroll_x, scroll_y, current_page]),\n",
" VBox([selected_cells]),\n",
" VBox([*page_format.values()]),\n",
" VBox([grid_enabled, grid_size, grid_color]),\n",
" value,\n",
"]\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.3"
}
},
"nbformat": 4,
"nbformat_minor": 5
}