From 26e14e4710bd373b43455f48bae17ffa12623825 Mon Sep 17 00:00:00 2001
From: Michael Leuschel <leuschel@uni-duesseldorf.de>
Date: Thu, 13 Jul 2023 13:36:30 +0200
Subject: [PATCH] add test for VisB rendering

Signed-off-by: Michael Leuschel <leuschel@uni-duesseldorf.de>
---
 notebooks/tests/VisB_Test.ipynb | 858 ++++++++++++++++++++++++++++++++
 1 file changed, 858 insertions(+)
 create mode 100644 notebooks/tests/VisB_Test.ipynb

diff --git a/notebooks/tests/VisB_Test.ipynb b/notebooks/tests/VisB_Test.ipynb
new file mode 100644
index 0000000..cedd994
--- /dev/null
+++ b/notebooks/tests/VisB_Test.ipynb
@@ -0,0 +1,858 @@
+{
+ "cells": [
+  {
+   "cell_type": "markdown",
+   "id": "c91030ef",
+   "metadata": {},
+   "source": [
+    "# Test VisB Rendering"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 1,
+   "id": "30b8bf50",
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "Loaded machine: button_def"
+      ]
+     },
+     "execution_count": 1,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "::load\n",
+    "MACHINE button_def\n",
+    "// An example that uses VisB DEFINITIONS instead of a JSON and SVG file\n",
+    "DEFINITIONS \n",
+    "  VISB_JSON_FILE == \"\"; // \"button.svg\";\n",
+    "  VISB_SVG_BOX == rec(height:200, width:240);\n",
+    "  VISB_SVG_CONTENTS == '''\n",
+    "   <defs>\n",
+    "    <marker id=\"arrowhead\" markerWidth=\"10\" markerHeight=\"7\"\n",
+    "    refX=\"0\" refY=\"3.5\" orient=\"auto\">\n",
+    "      <polygon points=\"0 0, 10 3.5, 0 7\" />\n",
+    "    </marker>\n",
+    "  </marker>\n",
+    "  </defs>\n",
+    "''';\n",
+    "  VISB_SVG_OBJECTS == rec(`id`:\"button\", svg_class:\"circle\",\n",
+    "     cx:\"100\",cy:\"100\", r:\"80\", \n",
+    "     stroke:\"black\", `stroke-width`:\"2\");\n",
+    "  VISB_SVG_UPDATES == rec(`id`:\"button\",\n",
+    "     fill: IF button=TRUE THEN \"green\" ELSE \"red\" END);\n",
+    "  VISB_SVG_HOVERS == rec(`id`:\"button\",\n",
+    "     stroke:\"gray\", `stroke-width`:\"5\");\n",
+    "     \n",
+    "  VISB_SVG_OBJECTS_ARROW == rec( svg_class:\"line\",\n",
+    "         `id`: \"arrow\",\n",
+    "          stroke:\"gray\",\n",
+    "          `stroke-width`:2.0,\n",
+    "          x1:100, y1:100,\n",
+    "          `marker-end`: \"url(#arrowhead)\");\n",
+    "  VISB_SVG_UPDATES2 == rec(`id`:\"arrow\", \n",
+    "                           visible:\"TRUE\",\n",
+    "                           y2:IF button=TRUE THEN 180.0 ELSE 20.0 END,\n",
+    "                           x2:100.0);\n",
+    "VARIABLES button\n",
+    "INVARIANT button:BOOL\n",
+    "INITIALISATION button := FALSE\n",
+    "OPERATIONS\n",
+    "  toggle_button /* desc change status of button */ = BEGIN\n",
+    "    button:= bool(button=FALSE)\n",
+    "  END\n",
+    "END"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 2,
+   "id": "91082d92",
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "Executed operation: INITIALISATION()"
+      ]
+     },
+     "execution_count": 2,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    ":init"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 3,
+   "id": "7eee20b7",
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/html": [
+       "<!DOCTYPE html>\n",
+       "<html>\n",
+       "<head>\n",
+       "     <!-- html file generated by ProB from a VisB visualization -->\n",
+       "     <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n",
+       "     <meta http-equiv=\"content-type\" content=\"text/html; charset=utf-8\">\n",
+       "     <script>\n",
+       "        function setAttr(id, attribute, value){\n",
+       "\t\t\tvar obj = document.getElementById(id);\n",
+       "\t\t\tif (obj == null) {\n",
+       "\t\t\t    if (id != \"visb_debug_messages\") {\n",
+       "\t\t\t\t     console.error(\"Unknown SVG id \" + id + \" for attribute \" + attribute);\n",
+       "\t\t\t\t}\n",
+       "\t\t\t} else if(attribute==\"text\") {\n",
+       "\t\t\t\tobj.textContent = value;\n",
+       "\t\t\t} else if(attribute==\"class\" && value != \"\") {\n",
+       "\t\t\t   if(value[0]==\"+\") {\n",
+       "\t\t\t      obj.classList.add(value.substr(1));\n",
+       "\t\t\t   } else if(value[0]==\"-\") {\n",
+       "\t\t\t      obj.classList.remove(value.substr(1));\n",
+       "\t\t\t   } else {\n",
+       "\t\t\t\t  obj.setAttribute(attribute, value);\n",
+       "\t\t\t   }\n",
+       "\t\t\t} else {\n",
+       "\t\t\t\tobj.setAttribute(attribute, value);\n",
+       "\t\t\t}\n",
+       "        }\n",
+       "\t\tfunction sleep(ms) {\n",
+       "\t\t    return new Promise(resolve => setTimeout(resolve, ms));\n",
+       "\t\t}\n",
+       "\t\tvar lastSelectedRow = 0;\n",
+       "\t\tfunction highlightRow(id) {\n",
+       "             if (lastSelectedRow>0) {setAttr(\"row\"+lastSelectedRow,\"bgcolor\",\"\")};\n",
+       "             setAttr(\"row\"+id,\"bgcolor\",\"yellow\");\n",
+       "             lastSelectedRow = id;\n",
+       "\t\t}\n",
+       "\t\tfunction backStep() {\n",
+       "\t\t     if (lastSelectedRow>1) {\n",
+       "\t\t       var prev = lastSelectedRow-1;\n",
+       "\t\t       document.getElementById(\"row\"+prev).click();\n",
+       "\t\t     }\n",
+       "\t\t}\n",
+       "\t\tfunction forwardStep() {\n",
+       "\t\t     if (lastSelectedRow>0) {\n",
+       "\t\t        var nxt = lastSelectedRow+1;\n",
+       "\t\t        var row = document.getElementById(\"row\"+(nxt));\n",
+       "\t\t        if (row != null) { row.click() };\n",
+       "\t\t     }\n",
+       "\t\t}\n",
+       "    </script>\n",
+       "  \n",
+       "\t<style>\n",
+       "\ttable {\n",
+       "\t  font-family: arial, sans-serif;\n",
+       "\t  font-size: 11px;\n",
+       "\t  border-collapse: collapse;\n",
+       "\t  width: 100%;\n",
+       "\t}\n",
+       "\ttd, th {\n",
+       "\t  border: 1px solid #dddddd;\n",
+       "\t  text-align: left;\n",
+       "\t  padding: 2px;\n",
+       "\t}\n",
+       "/* \n",
+       "\ttr:nth-child(even) {\n",
+       "\t  background-color: #dddddd;\n",
+       "\t}\n",
+       " */\n",
+       "\t</style> \n",
+       "\t\n",
+       "\t<style>\n",
+       "\t.collapsible {\n",
+       "\t  cursor: pointer;\n",
+       "\t}\n",
+       "\t.collapsible-style {\n",
+       "\t  background-color: #777;\n",
+       "\t  color: white;\n",
+       "\t  padding: 6px;\n",
+       "\t  width: 100%;\n",
+       "\t  border: none;\n",
+       "\t  text-align: left;\n",
+       "\t  outline: none;\n",
+       "\t  font-size: 12px;\n",
+       "\t}\n",
+       "\n",
+       "\t.active, .collapsible:hover {\n",
+       "\t  background-color: #555;\n",
+       "\t}\n",
+       "\t\n",
+       "\t.collapsible:after {\n",
+       "\t  content: '\\002B';\n",
+       "\t  color: white;\n",
+       "\t  font-weight: bold;\n",
+       "\t  float: right;\n",
+       "\t  margin-left: 5px;\n",
+       "\t}\n",
+       "\n",
+       "\t.active:after {\n",
+       "\t  content: \"\\2212\";\n",
+       "\t}\n",
+       "\n",
+       "\t.coll-content-hid {\n",
+       "\t  padding: 0 12px;\n",
+       "\t  display: none;\n",
+       "\t  overflow: hidden;\n",
+       "\t  background-color: #f1f1f1;\n",
+       "\t}\n",
+       "\t.coll-content-vis {\n",
+       "\t  padding: 0 12px;\n",
+       "\t  display: block;\n",
+       "\t  overflow: hidden;\n",
+       "\t  background-color: #f1f1f1;\n",
+       "\t}\n",
+       "\t.visb-messages {\n",
+       "\t  text-align: left;\n",
+       "\t  outline: none;\n",
+       "\t  font-size: 12px;\n",
+       "\t  font-family: arial, sans-serif;\n",
+       "\t}\n",
+       "  </style>\n",
+       "\n",
+       "        \n",
+       "\n",
+       " <script>\n",
+       "   function visualise0(stepNr) {\n",
+       "       setAttr(\"visb_debug_messages\",\"text\",\"Step \"+stepNr+\"/1, State ID: 0\");\n",
+       "Extracting SVG updates from VISB_SVG_UPDATES\n",
+       "       setAttr(\"button\",\"fill\",\"red\");\n",
+       "Extracting SVG updates from VISB_SVG_UPDATES2\n",
+       "       setAttr(\"arrow\",\"visible\",\"TRUE\");\n",
+       "       setAttr(\"arrow\",\"x2\",\"100.0\");\n",
+       "       setAttr(\"arrow\",\"y2\",\"20.0\");\n",
+       "       highlightRow(stepNr);\n",
+       "     }\n",
+       "   async function runAll(delay) {\n",
+       "   visualise0(1);\n",
+       "   setAttr(\"visb_debug_messages\",\"text\",\"Step: 1/1,  State ID: 0,  Event: \");\n",
+       "   await sleep(delay);\n",
+       "   }\n",
+       " </script>\n",
+       "\n",
+       "   <script>\n",
+       "   function registerHovers() {\n",
+       "     var obj;\n",
+       "   obj = document.getElementById(\"button\");\n",
+       "   obj.onmouseover = function(ev){\n",
+       "       setAttr(\"button\",\"stroke\",\"gray\")\n",
+       "       setAttr(\"button\",\"stroke-width\",\"5\")\n",
+       "     };\n",
+       "   obj.onmouseout = function(){\n",
+       "       setAttr(\"button\",\"stroke\",\"black\")\n",
+       "       setAttr(\"button\",\"stroke-width\",\"2\")\n",
+       "     };\n",
+       "   }\n",
+       "  </script>\n",
+       "    </head>\n",
+       "<body>\n",
+       "    <button type=\"button\" class=\"collapsible collapsible-style\">SVG Visualisation</button>\n",
+       "    <div text-align=\"left\"> \n",
+       " \n",
+       "\n",
+       "<svg  xmlns=\"http://www.w3.org/2000/svg\"\n",
+       "      width=\"240\" height=\"200\" viewBox=\"0 0 240 200\" >\n",
+       "Detected VISB_SVG_CONTENTS (requires_nothing)\n",
+       "\n",
+       "   <defs>\n",
+       "    <marker id=\"arrowhead\" markerWidth=\"10\" markerHeight=\"7\"\n",
+       "    refX=\"0\" refY=\"3.5\" orient=\"auto\">\n",
+       "      <polygon points=\"0 0, 10 3.5, 0 7\" />\n",
+       "    </marker>\n",
+       "  </marker>\n",
+       "  </defs>\n",
+       "\n",
+       "Extracting SVG updates from VISB_SVG_UPDATES\n",
+       "Extracting SVG updates from VISB_SVG_UPDATES2\n",
+       " <circle id=\"button\" cx=\"100\" cy=\"100\" fill=\"red\" r=\"80\" stroke=\"black\" stroke-width=\"2\"></circle>\n",
+       " <line id=\"arrow\" marker-end=\"url(#arrowhead)\" stroke=\"gray\" stroke-width=\"2.0\" visible=\"TRUE\" x1=\"100\" x2=\"100.0\" y1=\"100\" y2=\"20.0\"></line>\n",
+       "</svg>\n",
+       " </div>\n",
+       " <button type=\"button\" class=\"collapsible-style\">Trace (length=1)</button>\n",
+       "<div class=\"coll-content-vis\">\n",
+       " <table> <tr> <th>Nr</th> <th>Event</th> <th>Target State ID</th> </tr>\n",
+       "\n",
+       "  <tr id=\"row1\" onclick=\"visualise0(1)\"><td>1</td><td style=\"cursor:pointer\"></td><td><button onclick=\"visualise0(1);\">State 0</button></td></tr>\n",
+       " </table>\n",
+       " </div>\n",
+       " <script> visualise0(1); </script>\n",
+       " </div>\n",
+       " <script> registerHovers() </script>\n",
+       " \n",
+       "<script>\n",
+       "var collapsibles = document.getElementsByClassName(\"collapsible\");\n",
+       "var ii;\n",
+       "\n",
+       "for (ii = 0; ii < collapsibles.length; ii++) {\n",
+       "  collapsibles[ii].addEventListener(\"click\", function() {\n",
+       "    this.classList.toggle(\"active\");\n",
+       "    var content = this.nextElementSibling;\n",
+       "    if (content.style.display === \"block\") {\n",
+       "      content.style.display = \"none\";\n",
+       "    } else {\n",
+       "      content.style.display = \"block\";\n",
+       "    }\n",
+       "  });\n",
+       "}\n",
+       "</script>\n",
+       "\n",
+       "</body>\n",
+       "</html>\n",
+       "\n"
+      ],
+      "text/plain": [
+       "<VisB visualization>"
+      ]
+     },
+     "execution_count": 3,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    ":show"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 4,
+   "id": "0e4f3287",
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "Executed operation: toggle_button()"
+      ]
+     },
+     "execution_count": 4,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    ":exec toggle_button"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 5,
+   "id": "1d766206",
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/html": [
+       "<!DOCTYPE html>\n",
+       "<html>\n",
+       "<head>\n",
+       "     <!-- html file generated by ProB from a VisB visualization -->\n",
+       "     <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n",
+       "     <meta http-equiv=\"content-type\" content=\"text/html; charset=utf-8\">\n",
+       "     <script>\n",
+       "        function setAttr(id, attribute, value){\n",
+       "\t\t\tvar obj = document.getElementById(id);\n",
+       "\t\t\tif (obj == null) {\n",
+       "\t\t\t    if (id != \"visb_debug_messages\") {\n",
+       "\t\t\t\t     console.error(\"Unknown SVG id \" + id + \" for attribute \" + attribute);\n",
+       "\t\t\t\t}\n",
+       "\t\t\t} else if(attribute==\"text\") {\n",
+       "\t\t\t\tobj.textContent = value;\n",
+       "\t\t\t} else if(attribute==\"class\" && value != \"\") {\n",
+       "\t\t\t   if(value[0]==\"+\") {\n",
+       "\t\t\t      obj.classList.add(value.substr(1));\n",
+       "\t\t\t   } else if(value[0]==\"-\") {\n",
+       "\t\t\t      obj.classList.remove(value.substr(1));\n",
+       "\t\t\t   } else {\n",
+       "\t\t\t\t  obj.setAttribute(attribute, value);\n",
+       "\t\t\t   }\n",
+       "\t\t\t} else {\n",
+       "\t\t\t\tobj.setAttribute(attribute, value);\n",
+       "\t\t\t}\n",
+       "        }\n",
+       "\t\tfunction sleep(ms) {\n",
+       "\t\t    return new Promise(resolve => setTimeout(resolve, ms));\n",
+       "\t\t}\n",
+       "\t\tvar lastSelectedRow = 0;\n",
+       "\t\tfunction highlightRow(id) {\n",
+       "             if (lastSelectedRow>0) {setAttr(\"row\"+lastSelectedRow,\"bgcolor\",\"\")};\n",
+       "             setAttr(\"row\"+id,\"bgcolor\",\"yellow\");\n",
+       "             lastSelectedRow = id;\n",
+       "\t\t}\n",
+       "\t\tfunction backStep() {\n",
+       "\t\t     if (lastSelectedRow>1) {\n",
+       "\t\t       var prev = lastSelectedRow-1;\n",
+       "\t\t       document.getElementById(\"row\"+prev).click();\n",
+       "\t\t     }\n",
+       "\t\t}\n",
+       "\t\tfunction forwardStep() {\n",
+       "\t\t     if (lastSelectedRow>0) {\n",
+       "\t\t        var nxt = lastSelectedRow+1;\n",
+       "\t\t        var row = document.getElementById(\"row\"+(nxt));\n",
+       "\t\t        if (row != null) { row.click() };\n",
+       "\t\t     }\n",
+       "\t\t}\n",
+       "    </script>\n",
+       "  \n",
+       "\t<style>\n",
+       "\ttable {\n",
+       "\t  font-family: arial, sans-serif;\n",
+       "\t  font-size: 11px;\n",
+       "\t  border-collapse: collapse;\n",
+       "\t  width: 100%;\n",
+       "\t}\n",
+       "\ttd, th {\n",
+       "\t  border: 1px solid #dddddd;\n",
+       "\t  text-align: left;\n",
+       "\t  padding: 2px;\n",
+       "\t}\n",
+       "/* \n",
+       "\ttr:nth-child(even) {\n",
+       "\t  background-color: #dddddd;\n",
+       "\t}\n",
+       " */\n",
+       "\t</style> \n",
+       "\t\n",
+       "\t<style>\n",
+       "\t.collapsible {\n",
+       "\t  cursor: pointer;\n",
+       "\t}\n",
+       "\t.collapsible-style {\n",
+       "\t  background-color: #777;\n",
+       "\t  color: white;\n",
+       "\t  padding: 6px;\n",
+       "\t  width: 100%;\n",
+       "\t  border: none;\n",
+       "\t  text-align: left;\n",
+       "\t  outline: none;\n",
+       "\t  font-size: 12px;\n",
+       "\t}\n",
+       "\n",
+       "\t.active, .collapsible:hover {\n",
+       "\t  background-color: #555;\n",
+       "\t}\n",
+       "\t\n",
+       "\t.collapsible:after {\n",
+       "\t  content: '\\002B';\n",
+       "\t  color: white;\n",
+       "\t  font-weight: bold;\n",
+       "\t  float: right;\n",
+       "\t  margin-left: 5px;\n",
+       "\t}\n",
+       "\n",
+       "\t.active:after {\n",
+       "\t  content: \"\\2212\";\n",
+       "\t}\n",
+       "\n",
+       "\t.coll-content-hid {\n",
+       "\t  padding: 0 12px;\n",
+       "\t  display: none;\n",
+       "\t  overflow: hidden;\n",
+       "\t  background-color: #f1f1f1;\n",
+       "\t}\n",
+       "\t.coll-content-vis {\n",
+       "\t  padding: 0 12px;\n",
+       "\t  display: block;\n",
+       "\t  overflow: hidden;\n",
+       "\t  background-color: #f1f1f1;\n",
+       "\t}\n",
+       "\t.visb-messages {\n",
+       "\t  text-align: left;\n",
+       "\t  outline: none;\n",
+       "\t  font-size: 12px;\n",
+       "\t  font-family: arial, sans-serif;\n",
+       "\t}\n",
+       "  </style>\n",
+       "\n",
+       "        \n",
+       "\n",
+       " <script>\n",
+       "   function visualise1(stepNr) {\n",
+       "       setAttr(\"visb_debug_messages\",\"text\",\"Step \"+stepNr+\"/1, State ID: 1\");\n",
+       "Extracting SVG updates from VISB_SVG_UPDATES\n",
+       "       setAttr(\"button\",\"fill\",\"green\");\n",
+       "Extracting SVG updates from VISB_SVG_UPDATES2\n",
+       "       setAttr(\"arrow\",\"visible\",\"TRUE\");\n",
+       "       setAttr(\"arrow\",\"x2\",\"100.0\");\n",
+       "       setAttr(\"arrow\",\"y2\",\"180.0\");\n",
+       "       highlightRow(stepNr);\n",
+       "     }\n",
+       "   async function runAll(delay) {\n",
+       "   visualise1(1);\n",
+       "   setAttr(\"visb_debug_messages\",\"text\",\"Step: 1/1,  State ID: 1,  Event: \");\n",
+       "   await sleep(delay);\n",
+       "   }\n",
+       " </script>\n",
+       "\n",
+       "   <script>\n",
+       "   function registerHovers() {\n",
+       "     var obj;\n",
+       "   obj = document.getElementById(\"button\");\n",
+       "   obj.onmouseover = function(ev){\n",
+       "       setAttr(\"button\",\"stroke\",\"gray\")\n",
+       "       setAttr(\"button\",\"stroke-width\",\"5\")\n",
+       "     };\n",
+       "   obj.onmouseout = function(){\n",
+       "       setAttr(\"button\",\"stroke\",\"black\")\n",
+       "       setAttr(\"button\",\"stroke-width\",\"2\")\n",
+       "     };\n",
+       "   }\n",
+       "  </script>\n",
+       "    </head>\n",
+       "<body>\n",
+       "    <button type=\"button\" class=\"collapsible collapsible-style\">SVG Visualisation</button>\n",
+       "    <div text-align=\"left\"> \n",
+       " \n",
+       "\n",
+       "<svg  xmlns=\"http://www.w3.org/2000/svg\"\n",
+       "      width=\"240\" height=\"200\" viewBox=\"0 0 240 200\" >\n",
+       "Detected VISB_SVG_CONTENTS (requires_nothing)\n",
+       "\n",
+       "   <defs>\n",
+       "    <marker id=\"arrowhead\" markerWidth=\"10\" markerHeight=\"7\"\n",
+       "    refX=\"0\" refY=\"3.5\" orient=\"auto\">\n",
+       "      <polygon points=\"0 0, 10 3.5, 0 7\" />\n",
+       "    </marker>\n",
+       "  </marker>\n",
+       "  </defs>\n",
+       "\n",
+       "Extracting SVG updates from VISB_SVG_UPDATES\n",
+       "Extracting SVG updates from VISB_SVG_UPDATES2\n",
+       " <circle id=\"button\" cx=\"100\" cy=\"100\" fill=\"green\" r=\"80\" stroke=\"black\" stroke-width=\"2\"></circle>\n",
+       " <line id=\"arrow\" marker-end=\"url(#arrowhead)\" stroke=\"gray\" stroke-width=\"2.0\" visible=\"TRUE\" x1=\"100\" x2=\"100.0\" y1=\"100\" y2=\"180.0\"></line>\n",
+       "</svg>\n",
+       " </div>\n",
+       " <button type=\"button\" class=\"collapsible-style\">Trace (length=1)</button>\n",
+       "<div class=\"coll-content-vis\">\n",
+       " <table> <tr> <th>Nr</th> <th>Event</th> <th>Target State ID</th> </tr>\n",
+       "\n",
+       "  <tr id=\"row1\" onclick=\"visualise1(1)\"><td>1</td><td style=\"cursor:pointer\"></td><td><button onclick=\"visualise1(1);\">State 1</button></td></tr>\n",
+       " </table>\n",
+       " </div>\n",
+       " <script> visualise1(1); </script>\n",
+       " </div>\n",
+       " <script> registerHovers() </script>\n",
+       " \n",
+       "<script>\n",
+       "var collapsibles = document.getElementsByClassName(\"collapsible\");\n",
+       "var ii;\n",
+       "\n",
+       "for (ii = 0; ii < collapsibles.length; ii++) {\n",
+       "  collapsibles[ii].addEventListener(\"click\", function() {\n",
+       "    this.classList.toggle(\"active\");\n",
+       "    var content = this.nextElementSibling;\n",
+       "    if (content.style.display === \"block\") {\n",
+       "      content.style.display = \"none\";\n",
+       "    } else {\n",
+       "      content.style.display = \"block\";\n",
+       "    }\n",
+       "  });\n",
+       "}\n",
+       "</script>\n",
+       "\n",
+       "</body>\n",
+       "</html>\n",
+       "\n"
+      ],
+      "text/plain": [
+       "<VisB visualization>"
+      ]
+     },
+     "execution_count": 5,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    ":show"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 6,
+   "id": "a921eeea",
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "Executed operation: toggle_button()"
+      ]
+     },
+     "execution_count": 6,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    ":exec toggle_button"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 7,
+   "id": "15eedcc6",
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/html": [
+       "<!DOCTYPE html>\n",
+       "<html>\n",
+       "<head>\n",
+       "     <!-- html file generated by ProB from a VisB visualization -->\n",
+       "     <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n",
+       "     <meta http-equiv=\"content-type\" content=\"text/html; charset=utf-8\">\n",
+       "     <script>\n",
+       "        function setAttr(id, attribute, value){\n",
+       "\t\t\tvar obj = document.getElementById(id);\n",
+       "\t\t\tif (obj == null) {\n",
+       "\t\t\t    if (id != \"visb_debug_messages\") {\n",
+       "\t\t\t\t     console.error(\"Unknown SVG id \" + id + \" for attribute \" + attribute);\n",
+       "\t\t\t\t}\n",
+       "\t\t\t} else if(attribute==\"text\") {\n",
+       "\t\t\t\tobj.textContent = value;\n",
+       "\t\t\t} else if(attribute==\"class\" && value != \"\") {\n",
+       "\t\t\t   if(value[0]==\"+\") {\n",
+       "\t\t\t      obj.classList.add(value.substr(1));\n",
+       "\t\t\t   } else if(value[0]==\"-\") {\n",
+       "\t\t\t      obj.classList.remove(value.substr(1));\n",
+       "\t\t\t   } else {\n",
+       "\t\t\t\t  obj.setAttribute(attribute, value);\n",
+       "\t\t\t   }\n",
+       "\t\t\t} else {\n",
+       "\t\t\t\tobj.setAttribute(attribute, value);\n",
+       "\t\t\t}\n",
+       "        }\n",
+       "\t\tfunction sleep(ms) {\n",
+       "\t\t    return new Promise(resolve => setTimeout(resolve, ms));\n",
+       "\t\t}\n",
+       "\t\tvar lastSelectedRow = 0;\n",
+       "\t\tfunction highlightRow(id) {\n",
+       "             if (lastSelectedRow>0) {setAttr(\"row\"+lastSelectedRow,\"bgcolor\",\"\")};\n",
+       "             setAttr(\"row\"+id,\"bgcolor\",\"yellow\");\n",
+       "             lastSelectedRow = id;\n",
+       "\t\t}\n",
+       "\t\tfunction backStep() {\n",
+       "\t\t     if (lastSelectedRow>1) {\n",
+       "\t\t       var prev = lastSelectedRow-1;\n",
+       "\t\t       document.getElementById(\"row\"+prev).click();\n",
+       "\t\t     }\n",
+       "\t\t}\n",
+       "\t\tfunction forwardStep() {\n",
+       "\t\t     if (lastSelectedRow>0) {\n",
+       "\t\t        var nxt = lastSelectedRow+1;\n",
+       "\t\t        var row = document.getElementById(\"row\"+(nxt));\n",
+       "\t\t        if (row != null) { row.click() };\n",
+       "\t\t     }\n",
+       "\t\t}\n",
+       "    </script>\n",
+       "  \n",
+       "\t<style>\n",
+       "\ttable {\n",
+       "\t  font-family: arial, sans-serif;\n",
+       "\t  font-size: 11px;\n",
+       "\t  border-collapse: collapse;\n",
+       "\t  width: 100%;\n",
+       "\t}\n",
+       "\ttd, th {\n",
+       "\t  border: 1px solid #dddddd;\n",
+       "\t  text-align: left;\n",
+       "\t  padding: 2px;\n",
+       "\t}\n",
+       "/* \n",
+       "\ttr:nth-child(even) {\n",
+       "\t  background-color: #dddddd;\n",
+       "\t}\n",
+       " */\n",
+       "\t</style> \n",
+       "\t\n",
+       "\t<style>\n",
+       "\t.collapsible {\n",
+       "\t  cursor: pointer;\n",
+       "\t}\n",
+       "\t.collapsible-style {\n",
+       "\t  background-color: #777;\n",
+       "\t  color: white;\n",
+       "\t  padding: 6px;\n",
+       "\t  width: 100%;\n",
+       "\t  border: none;\n",
+       "\t  text-align: left;\n",
+       "\t  outline: none;\n",
+       "\t  font-size: 12px;\n",
+       "\t}\n",
+       "\n",
+       "\t.active, .collapsible:hover {\n",
+       "\t  background-color: #555;\n",
+       "\t}\n",
+       "\t\n",
+       "\t.collapsible:after {\n",
+       "\t  content: '\\002B';\n",
+       "\t  color: white;\n",
+       "\t  font-weight: bold;\n",
+       "\t  float: right;\n",
+       "\t  margin-left: 5px;\n",
+       "\t}\n",
+       "\n",
+       "\t.active:after {\n",
+       "\t  content: \"\\2212\";\n",
+       "\t}\n",
+       "\n",
+       "\t.coll-content-hid {\n",
+       "\t  padding: 0 12px;\n",
+       "\t  display: none;\n",
+       "\t  overflow: hidden;\n",
+       "\t  background-color: #f1f1f1;\n",
+       "\t}\n",
+       "\t.coll-content-vis {\n",
+       "\t  padding: 0 12px;\n",
+       "\t  display: block;\n",
+       "\t  overflow: hidden;\n",
+       "\t  background-color: #f1f1f1;\n",
+       "\t}\n",
+       "\t.visb-messages {\n",
+       "\t  text-align: left;\n",
+       "\t  outline: none;\n",
+       "\t  font-size: 12px;\n",
+       "\t  font-family: arial, sans-serif;\n",
+       "\t}\n",
+       "  </style>\n",
+       "\n",
+       "        \n",
+       "\n",
+       " <script>\n",
+       "   function visualise0(stepNr) {\n",
+       "       setAttr(\"visb_debug_messages\",\"text\",\"Step \"+stepNr+\"/1, State ID: 0\");\n",
+       "Extracting SVG updates from VISB_SVG_UPDATES\n",
+       "       setAttr(\"button\",\"fill\",\"red\");\n",
+       "Extracting SVG updates from VISB_SVG_UPDATES2\n",
+       "       setAttr(\"arrow\",\"visible\",\"TRUE\");\n",
+       "       setAttr(\"arrow\",\"x2\",\"100.0\");\n",
+       "       setAttr(\"arrow\",\"y2\",\"20.0\");\n",
+       "       highlightRow(stepNr);\n",
+       "     }\n",
+       "   async function runAll(delay) {\n",
+       "   visualise0(1);\n",
+       "   setAttr(\"visb_debug_messages\",\"text\",\"Step: 1/1,  State ID: 0,  Event: \");\n",
+       "   await sleep(delay);\n",
+       "   }\n",
+       " </script>\n",
+       "\n",
+       "   <script>\n",
+       "   function registerHovers() {\n",
+       "     var obj;\n",
+       "   obj = document.getElementById(\"button\");\n",
+       "   obj.onmouseover = function(ev){\n",
+       "       setAttr(\"button\",\"stroke\",\"gray\")\n",
+       "       setAttr(\"button\",\"stroke-width\",\"5\")\n",
+       "     };\n",
+       "   obj.onmouseout = function(){\n",
+       "       setAttr(\"button\",\"stroke\",\"black\")\n",
+       "       setAttr(\"button\",\"stroke-width\",\"2\")\n",
+       "     };\n",
+       "   }\n",
+       "  </script>\n",
+       "    </head>\n",
+       "<body>\n",
+       "    <button type=\"button\" class=\"collapsible collapsible-style\">SVG Visualisation</button>\n",
+       "    <div text-align=\"left\"> \n",
+       " \n",
+       "\n",
+       "<svg  xmlns=\"http://www.w3.org/2000/svg\"\n",
+       "      width=\"240\" height=\"200\" viewBox=\"0 0 240 200\" >\n",
+       "Detected VISB_SVG_CONTENTS (requires_nothing)\n",
+       "\n",
+       "   <defs>\n",
+       "    <marker id=\"arrowhead\" markerWidth=\"10\" markerHeight=\"7\"\n",
+       "    refX=\"0\" refY=\"3.5\" orient=\"auto\">\n",
+       "      <polygon points=\"0 0, 10 3.5, 0 7\" />\n",
+       "    </marker>\n",
+       "  </marker>\n",
+       "  </defs>\n",
+       "\n",
+       "Extracting SVG updates from VISB_SVG_UPDATES\n",
+       "Extracting SVG updates from VISB_SVG_UPDATES2\n",
+       " <circle id=\"button\" cx=\"100\" cy=\"100\" fill=\"red\" r=\"80\" stroke=\"black\" stroke-width=\"2\"></circle>\n",
+       " <line id=\"arrow\" marker-end=\"url(#arrowhead)\" stroke=\"gray\" stroke-width=\"2.0\" visible=\"TRUE\" x1=\"100\" x2=\"100.0\" y1=\"100\" y2=\"20.0\"></line>\n",
+       "</svg>\n",
+       " </div>\n",
+       " <button type=\"button\" class=\"collapsible-style\">Trace (length=1)</button>\n",
+       "<div class=\"coll-content-vis\">\n",
+       " <table> <tr> <th>Nr</th> <th>Event</th> <th>Target State ID</th> </tr>\n",
+       "\n",
+       "  <tr id=\"row1\" onclick=\"visualise0(1)\"><td>1</td><td style=\"cursor:pointer\"></td><td><button onclick=\"visualise0(1);\">State 0</button></td></tr>\n",
+       " </table>\n",
+       " </div>\n",
+       " <script> visualise0(1); </script>\n",
+       " </div>\n",
+       " <script> registerHovers() </script>\n",
+       " \n",
+       "<script>\n",
+       "var collapsibles = document.getElementsByClassName(\"collapsible\");\n",
+       "var ii;\n",
+       "\n",
+       "for (ii = 0; ii < collapsibles.length; ii++) {\n",
+       "  collapsibles[ii].addEventListener(\"click\", function() {\n",
+       "    this.classList.toggle(\"active\");\n",
+       "    var content = this.nextElementSibling;\n",
+       "    if (content.style.display === \"block\") {\n",
+       "      content.style.display = \"none\";\n",
+       "    } else {\n",
+       "      content.style.display = \"block\";\n",
+       "    }\n",
+       "  });\n",
+       "}\n",
+       "</script>\n",
+       "\n",
+       "</body>\n",
+       "</html>\n",
+       "\n"
+      ],
+      "text/plain": [
+       "<VisB visualization>"
+      ]
+     },
+     "execution_count": 7,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    ":show"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "8e25955c",
+   "metadata": {},
+   "outputs": [],
+   "source": []
+  }
+ ],
+ "metadata": {
+  "kernelspec": {
+   "display_name": "ProB 2",
+   "language": "prob",
+   "name": "prob2"
+  },
+  "language_info": {
+   "codemirror_mode": "prob2_jupyter_repl",
+   "file_extension": ".prob",
+   "mimetype": "text/x-prob2-jupyter-repl",
+   "name": "prob"
+  }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 5
+}
-- 
GitLab