diff options
| author | Cliff Click <cliffc@acm.org> | 2024-12-03 22:44:36 -0800 |
|---|---|---|
| committer | Cliff Click <cliffc@acm.org> | 2025-01-15 15:07:30 -0800 |
| commit | 0697119593c00af15aeb2072e8b42122dde31c66 (patch) | |
| tree | 1f1001ac8f7e2527de72cf98d0360a90757f5308 /chapter18 | |
| parent | 2136abe8071833fd072c4be13c885525b46f5320 (diff) | |
| download | Simple-0697119593c00af15aeb2072e8b42122dde31c66.tar.gz Simple-0697119593c00af15aeb2072e8b42122dde31c66.zip | |
viewer improvements
viewer highlights parsed text;
larger input box
removes some double-display
handles mouse over-run
Diffstat (limited to 'chapter18')
| -rw-r--r-- | chapter18/docs/index.html | 77 | ||||
| -rw-r--r-- | chapter18/src/main/java/com/seaofnodes/simple/JSViewer.java | 3 | ||||
| -rw-r--r-- | chapter18/src/main/java/com/seaofnodes/simple/Parser.java | 4 |
3 files changed, 57 insertions, 27 deletions
diff --git a/chapter18/docs/index.html b/chapter18/docs/index.html index 3a425f25..c2441202 100644 --- a/chapter18/docs/index.html +++ b/chapter18/docs/index.html @@ -8,7 +8,15 @@ <body style="height: 100%; margin:0"> <div style="display:flex; flex-flow:column; height: 100%;"> - <div id="head" style="flex: 0 1 auto; align-self:center; "> HEADER </div> + <div style="position:fixed; top:0; left:0; height:20%; width:30%;" > + <div align="center" >Simple Program:</div> + <textarea + id="program" + autofocus="true" + name="Program" + defaultValue="return 0;" + ></textarea> + </div> <div id="fill" style="flex: 1 1 auto"> </div> <div id="graph" style="flex: 0 1 auto; align-self:center;"> </div> @@ -20,7 +28,6 @@ <div id="N" style="font-size: 20px; border-style: ridge; min-width: 50px; text-align: right; padding-right: 10px;">0</div> <button id="doNext" type="button" onclick="doNext()" class="button">⮞</button> <div id="len" style="font-size: 20px; min-width: 50px; text-align: right; padding-right: 10px;">0</div> - <button id="doNew" type="button" onclick="doNew ()" class="button">New</button> <button id="doExit" type="button" onclick="doExit()" class="button">Exit</button> </div> </div> @@ -44,25 +51,24 @@ // Websocket. :-P const socket = new WebSocket("ws://localhost:12345"); - // Read user program + const DOC_PROG = document.getElementById('program'); + // Default value seems to be ignored??? + DOC_PROG.value="return 0;"; function get_program() { + console.log("get_program"); + var src = DOC_PROG.value; + console.log(src); + // Reset visualizer state before sending updateN(0); dots=[]; done=false; - var src = prompt("Simple program:",`struct Vector2D { int x; int y; }; -Vector2D !v = new Vector2D; -v.x = 1; -if (arg) - v.y = 2; -else - v.y = 3; -return v; -`); + // Send program; will start getting DOT frames shortly socket.send(src); // Once the program is sent, timer starts _timer = setTimeout("close()",100000) }; + DOC_PROG.onchange=get_program; // Go forwards in the animation function doNext() { @@ -87,8 +93,6 @@ return v; // exit function doExit() { socket.send(null); close(); }; - // New program - function doNew() { get_program(); } // Update step counter display and buttons function updateN(newN) { @@ -118,26 +122,54 @@ return v; } document.getElementById("N") .textContent = N==dots.length ? (">"+(N-1)) : N; document.getElementById("len").textContent = dots.length; - }; // Render an animation, from idx to end by step. + // 'end' is inclusive. + var renderActive = -1; function render(idx, end, step) { - _rend(idx,end+step,step); + old = renderActive; + renderActive = (end+step); + // No active, so start rendering + if( old == -1 ) + _rend(idx,end+step,step); } // Render an animation in a 'for' loop of frames // until we hit the end. Looping is done via callbacks. + // end is exclusive. var aix = -1; // Last DOT rendered function _rend(idx,end,step) { // Skip animation if already rendered/showing on screen - // if( idx==aix ) _rendNext(idx,end,step); - aix = idx; - graphviz.renderDot(dots[idx]).on("end", _rendNext(idx,end,step)) + if( idx==aix ) _rendNext(idx,end,step); + else { + aix = idx; + var str = dots[idx].indexOf("// POS: "); + console.log(str); + if( str == -1 ) DOC_PROG.setSelectionRange(0,0); + else { + var pos = Number(dots[idx].substring(str+8,str+12)); + console.log(pos,pos+1); + document.getElementById("program").focus(); + document.getElementById("program").setSelectionRange(pos,pos+1); + } + graphviz.renderDot(dots[idx]).on("end", _rendNext(idx,end,step)) + } } function _rendNext(idx,end,step) { + // Not at end so... if( idx+step != end ) + // Render next step _rend(idx+step,end,step); + else { + // All desired frames rendered + if( renderActive == end ) { + renderActive = -1; // all frames done + } else { + // Skip-a-few and render the last asked for + _rend(renderActive-1,renderActive,1) + } + } }; @@ -147,7 +179,7 @@ return v; socket.onmessage = (event) => { clearTimeout(_timer); _timer=null; const dot = event.data; - console.log("Received:", dot.substring(0,100)); + console.log("Received:", dot.substring(0,40)); if( dot == "!" ) { // Server requests client resets @@ -160,7 +192,7 @@ return v; } else if( dot.startsWith("digraph") ) { // Received a new graph dots.push(dot); - console.log(dot); + //console.log(dot); updateN(N); socket.send("+"); // Get another frame // If at-end, receiving a graph immediately renders @@ -182,8 +214,5 @@ return v; console.error('WebSocket error:', error); }; - // Starter situation, as-if reset - get_program(); - </script> </body> diff --git a/chapter18/src/main/java/com/seaofnodes/simple/JSViewer.java b/chapter18/src/main/java/com/seaofnodes/simple/JSViewer.java index 79a84edf..c63b5118 100644 --- a/chapter18/src/main/java/com/seaofnodes/simple/JSViewer.java +++ b/chapter18/src/main/java/com/seaofnodes/simple/JSViewer.java @@ -30,6 +30,7 @@ public class JSViewer implements AutoCloseable { } void run( ) throws Exception { + SERVER.put("!"); while( true ) { String src = SERVER.get(); switch( src ) { @@ -74,6 +75,8 @@ public class JSViewer implements AutoCloseable { Collection<Node> all = GraphVisualizer.findAll(P==null ? null : P._xScopes, STOP, P==null ? null : P._scope); SB sb = new SB(); sb.p("digraph view_").p(N++).p(" {\n").ii(); + if( P!=null ) + sb.i().p("// POS: ").p(P.pos()).nl(); // To keep the Scopes below the graph and pointing up into the graph we // need to group the Nodes in a subgraph cluster, and the scopes into a diff --git a/chapter18/src/main/java/com/seaofnodes/simple/Parser.java b/chapter18/src/main/java/com/seaofnodes/simple/Parser.java index 47bfe08e..04af20f7 100644 --- a/chapter18/src/main/java/com/seaofnodes/simple/Parser.java +++ b/chapter18/src/main/java/com/seaofnodes/simple/Parser.java @@ -640,7 +640,6 @@ public class Parser { // A Block scope parse, and inspect the scope afterward for fields. _scope.push(true); - _xScopes.push(_scope); require("{"); while (!peek('}') && !_lexer.isEOF()) parseStatement(); @@ -661,7 +660,6 @@ public class Parser { // Done with struct/block scope require("}"); require(";"); - _xScopes.pop(); _scope.pop(); return null; } @@ -1183,7 +1181,7 @@ public class Parser { private boolean peek(char ch) { return _lexer.peek(ch); } private boolean peekIsId() { return _lexer.peekIsId(); } - private int pos() { return _lexer._position; } + public int pos() { return _lexer._position; } private int pos(int pos) { int old = _lexer._position; _lexer._position = pos; |
