@@ -24,6 +24,11 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
2424// and receives a complete execution trace, which it parses and displays to HTML.
2525
2626
27+ // set to true to use jsPlumb library to render connections between
28+ // stack and heap objects
29+ var useJsPlumbRendering = false ;
30+
31+
2732var localTesting = false ; // if this is true, mock-data.js had also better be included
2833
2934
@@ -33,6 +38,11 @@ var lightLineColor = '#FFFFCC';
3338var errorColor = '#F87D76' ;
3439var visitedLineColor = '#3D58A2' ;
3540
41+ var lightGray = "#dddddd" ;
42+ var darkBlue = "#3D58A2" ;
43+ var pinkish = "#F15149" ;
44+
45+
3646// ugh globals!
3747var curTrace = null ;
3848var curInstr = 0 ;
@@ -238,8 +248,12 @@ function updateOutput() {
238248
239249// Renders the current trace entry (curEntry) into the div named by vizDiv
240250function renderDataStructures ( curEntry , vizDiv ) {
241- renderDataStructuresVersion1 ( curEntry , vizDiv ) ;
242- //renderDataStructuresVersion2(curEntry, vizDiv);
251+ if ( useJsPlumbRendering ) {
252+ renderDataStructuresVersion2 ( curEntry , vizDiv ) ;
253+ }
254+ else {
255+ renderDataStructuresVersion1 ( curEntry , vizDiv ) ;
256+ }
243257}
244258
245259
@@ -378,14 +392,17 @@ function renderDataStructuresVersion1(curEntry, vizDiv) {
378392//
379393// This version was originally created in September 2011
380394function renderDataStructuresVersion2 ( curEntry , vizDiv ) {
381- //console.log(curEntry);
382-
383395 $ ( vizDiv ) . html ( '' ) ; // CLEAR IT!
384396
385397 // create a tabular layout for stack and heap side-by-side
386398 // TODO: figure out how to do this using CSS in a robust way!
387399 $ ( vizDiv ) . html ( '<table id="stackHeapTable"><tr><td><div id="stack"></div></td><td><div id="heap"></div></td></tr></table>' ) ;
388400
401+
402+ // Key: CSS ID of the div element representing the variable
403+ // Value: CSS ID of the div element representing the value rendered in the heap
404+ connectionEndpointIDs = { } ;
405+
389406 // first render the stack (and global vars)
390407
391408 // render locals on stack:
@@ -442,6 +459,10 @@ function renderDataStructuresVersion2(curEntry, vizDiv) {
442459 // characters that are illegal for CSS ID's ...
443460 var varDivID = divID + '__' + varname ;
444461 curTr . find ( "td.stackFrameValue" ) . append ( '<div id="' + varDivID + '"> </div>' ) ;
462+
463+ assert ( connectionEndpointIDs [ varDivID ] === undefined ) ;
464+ var heapObjID = 'heap_object_' + getObjectID ( val ) ;
465+ connectionEndpointIDs [ varDivID ] = heapObjID ;
445466 }
446467 } ) ;
447468 }
@@ -528,6 +549,10 @@ function renderDataStructuresVersion2(curEntry, vizDiv) {
528549 // characters that are illegal for CSS ID's ...
529550 var varDivID = 'global__' + varname ;
530551 curTr . find ( "td.stackFrameValue" ) . append ( '<div id="' + varDivID + '"> </div>' ) ;
552+
553+ assert ( connectionEndpointIDs [ varDivID ] === undefined ) ;
554+ var heapObjID = 'heap_object_' + getObjectID ( val ) ;
555+ connectionEndpointIDs [ varDivID ] = heapObjID ;
531556 }
532557 }
533558 } ) ;
@@ -611,6 +636,63 @@ function renderDataStructuresVersion2(curEntry, vizDiv) {
611636
612637 // finally connect stack variables to heap objects via connectors
613638
639+ for ( varID in connectionEndpointIDs ) {
640+ var valueID = connectionEndpointIDs [ varID ] ;
641+ jsPlumb . connect ( { source : varID , target : valueID } ) ;
642+ }
643+
644+
645+ // add an on-click listener to all stack frame headers
646+ $ ( ".stackFrameHeader" ) . click ( function ( ) {
647+ var enclosingStackFrame = $ ( this ) . parent ( ) ;
648+ var enclosingStackFrameID = enclosingStackFrame . attr ( 'id' ) ;
649+
650+ var allConnections = jsPlumb . getConnections ( ) ;
651+ for ( var i = 0 ; i < allConnections . length ; i ++ ) {
652+ var c = allConnections [ i ] ;
653+
654+ // this is VERY VERY fragile code, since it assumes that going up
655+ // five layers of parent() calls will get you from the source end
656+ // of the connector to the enclosing stack frame
657+ var stackFrameDiv = c . source . parent ( ) . parent ( ) . parent ( ) . parent ( ) . parent ( ) ;
658+
659+ // if this connector starts in the selected stack frame ...
660+ if ( stackFrameDiv . attr ( 'id' ) == enclosingStackFrameID ) {
661+ // then HIGHLIGHT IT!
662+ c . setPaintStyle ( { lineWidth :2 , strokeStyle : darkBlue } ) ;
663+ c . endpoints [ 0 ] . setPaintStyle ( { fillStyle : darkBlue } ) ;
664+ c . endpoints [ 1 ] . setVisible ( false , true , true ) ; // JUST set right endpoint to be invisible
665+
666+ // ... and move it to the VERY FRONT
667+ $ ( c . canvas ) . css ( "z-index" , 1000 ) ;
668+ }
669+ else {
670+ // else unhighlight it
671+ c . setPaintStyle ( { lineWidth :1 , strokeStyle : lightGray } ) ;
672+ c . endpoints [ 0 ] . setPaintStyle ( { fillStyle : lightGray } ) ;
673+ c . endpoints [ 1 ] . setVisible ( false , true , true ) ; // JUST set right endpoint to be invisible
674+ $ ( c . canvas ) . css ( "z-index" , 0 ) ;
675+ }
676+ }
677+
678+ // clear everything, then just activate $(this) one ...
679+ $ ( ".stackFrame" ) . removeClass ( "selectedStackFrame" ) ;
680+ $ ( ".stackFrameHeader" ) . addClass ( "inactiveStackFrameHeader" ) ;
681+
682+ enclosingStackFrame . addClass ( "selectedStackFrame" ) ;
683+ $ ( this ) . removeClass ( "inactiveStackFrameHeader" ) ;
684+ } ) ;
685+
686+
687+ // 'click' on the top-most stack frame if available,
688+ // or on "Global variables" otherwise
689+ if ( curEntry . stack_locals != undefined && curEntry . stack_locals . length ) {
690+ $ ( '#stack_header0' ) . trigger ( 'click' ) ;
691+ }
692+ else {
693+ $ ( '#globals_header' ) . trigger ( 'click' ) ;
694+ }
695+
614696}
615697
616698function isPrimitiveType ( obj ) {
@@ -1042,11 +1124,28 @@ $(document).ready(function() {
10421124 return false ;
10431125 } ) ;
10441126
1127+ $ ( "#towersOfHanoiLink" ) . click ( function ( ) {
1128+ $ . get ( "example-code/towers_of_hanoi.txt" , function ( dat ) { $ ( "#pyInput" ) . val ( dat ) ; } ) ;
1129+ return false ;
1130+ } ) ;
1131+
10451132 $ ( "#pwTryFinallyLink" ) . click ( function ( ) {
10461133 $ . get ( "example-code/wentworth_try_finally.txt" , function ( dat ) { $ ( "#pyInput" ) . val ( dat ) ; } ) ;
10471134 return false ;
10481135 } ) ;
10491136
1137+ if ( useJsPlumbRendering ) {
1138+ // set some sensible defaults
1139+ jsPlumb . Defaults . Endpoint = [ "Dot" , { radius :3 } ] ;
1140+ //jsPlumb.Defaults.Endpoint = ["Rectangle", {width:3, height:3}];
1141+ jsPlumb . Defaults . EndpointStyle = { fillStyle : lightGray } ;
1142+ jsPlumb . Defaults . Anchors = [ "RightMiddle" , "LeftMiddle" ] ;
1143+ jsPlumb . Defaults . Connector = [ "Bezier" , { curviness :15 } ] ; /* too much 'curviness' causes lines to run together */
1144+ jsPlumb . Defaults . PaintStyle = { lineWidth :1 , strokeStyle : lightGray } ;
1145+
1146+ jsPlumb . Defaults . EndpointHoverStyle = { fillStyle : pinkish } ;
1147+ jsPlumb . Defaults . HoverPaintStyle = { lineWidth :2 , strokeStyle : pinkish } ;
1148+ }
10501149
10511150 // select an example on start-up:
10521151 $ ( "#tutorialExampleLink" ) . trigger ( 'click' ) ;
0 commit comments