Browse Source

basis des forwärtsausführens fertig

Kolja Strohm 6 years ago
parent
commit
629256c6a0

BIN
material/~$lec07-Nodes-Size.pptx


+ 24 - 17
src/animation/AnimatedAlgorithm.java

@@ -2,6 +2,7 @@ package animation;
 
 import java.awt.event.ComponentEvent;
 import java.awt.event.ComponentListener;
+import java.util.Stack;
 
 import javax.swing.JFrame;
 import javax.swing.JTree;
@@ -16,6 +17,7 @@ public abstract class AnimatedAlgorithm extends Thread implements AlgorithmStage
     protected LayeredGraphNode graph;
     private JFrame view;
     protected PseudoCodeNode root;
+    protected Stack<PseudoCodeNode> activeFunction;
     protected Memory mem;
 
     public AnimatedAlgorithm( AnimationController controller, LayeredGraphNode graph, JFrame view )
@@ -26,6 +28,12 @@ public abstract class AnimatedAlgorithm extends Thread implements AlgorithmStage
         root = null;
         mem = new Memory();
         mem.declare( "graph", graph, true );
+        activeFunction = new Stack<PseudoCodeNode>();
+    }
+    
+    public void addActiveFunction( PseudoCodeNode n )
+    {
+    	activeFunction.push( n );
     }
 
     private void update()
@@ -46,43 +54,42 @@ public abstract class AnimatedAlgorithm extends Thread implements AlgorithmStage
     {
         while( true ) // if this loop would end we could not undo steps any more
         {
+        	CodeStatus status = null;
             try {
+            	while( activeFunction.size() == 0 )
+            		Thread.sleep( 100 );
+            	PseudoCodeNode current = activeFunction.peek();
                 switch( ac.getNextAction() )
                 {
                 case FORWARD:
-                    if( root.forwardStep( mem ) == CodeStatus.FINISHED )
-                        ac.setContinuous( false );
-                    update();
+                	status = current.forwardStep( mem );
                     break;
                 case FORWARD_OUT:
-                    root.forwardStepOut( mem );
-                    update();
+                    status = current.forwardStepOut( mem );
                     break;
                 case FORWARD_OVER:
-                    root.forwardStepOver( mem );
-                    update();
+                    status = current.forwardStepOver( mem );
                     break;
                 case BACKWARD:
-                    if( root.backwardStep( mem ) == CodeStatus.FINISHED )
-                        ac.setContinuous( false );
-                    update();
+                    status = current.backwardStep( mem );
                     break;
                 case BACKWARD_OUT:
-                    root.backwardStepOut( mem );
-                    update();
+                    status = current.backwardStepOut( mem );
                     break;
                 case BACKWARD_OVER:
-                    root.backwardStepOver( mem );
-                    update();
-                    break;
-                default:
+                    status = current.backwardStepOver( mem );
                     break;
                 }
             } catch (InterruptedException e) {
                 e.printStackTrace();
                 return;
             }
-
+            update();
+            if( status == CodeStatus.FINISHED )
+            {
+            	if( activeFunction.size() > 1 )
+            		activeFunction.pop();
+            }
         }
     }
 

+ 27 - 17
src/animation/CodeLine.java

@@ -1,22 +1,32 @@
 package animation;
 
-public interface CodeLine {
+import java.util.Stack;
 
-    public ControlFlow runForward( Memory m );
-    public ControlFlow runBackward( Memory m );
-    
-    public static final CodeLine DEFAULT_STEP_INTO_STACK = new CodeLine() {
-
-        @Override
-        public ControlFlow runForward(Memory m) {
-            m.addFrame();
-            return new ControlFlow( ControlFlow.STEP_INTO_STACK );
-        }
+public abstract class CodeLine {
 
-        @Override
-        public ControlFlow runBackward(Memory m) {
-            m.addFrame();
-            return new ControlFlow( ControlFlow.STEP_INTO );
-        }
-    };
+	protected interface BackwardAction
+	{
+		public ControlFlow backward( Memory m );
+	}
+	
+	protected Stack<BackwardAction> actions;
+	protected int lineId;
+	private static int nextLineId = 0;
+	
+	public CodeLine()
+	{
+		synchronized( CodeLine.class ) {
+			lineId = nextLineId++;
+		}
+		actions = new Stack<BackwardAction>();
+	}
+	
+    public abstract ControlFlow runForward( Memory m );
+    
+    public ControlFlow runBackward( Memory m )
+    {
+    	if( actions.size() == 0 )
+    		return new ControlFlow( ControlFlow.STEP_OVER );
+    	return actions.pop().backward( m );
+    }
 }

+ 12 - 5
src/animation/ControlFlow.java

@@ -2,20 +2,27 @@ package animation;
 
 public class ControlFlow {
     public static final int STEP_INTO = 0;
-    public static final int STEP_INTO_STACK = 6;
     public static final int STEP_OVER = 1;
-    public static final int STEP_INTO_LOOP = 2;
-    public static final int BREAK_LOOP = 3;
-    public static final int CONTINUE_LOOP = 4;
-    public static final int CALL = 5;
+    public static final int CALL = 2;
     
     private int status;
+    private PseudoCodeNode function;
     
     public ControlFlow( int status )
     {
         this.status = status;
     }
     
+    public ControlFlow( PseudoCodeNode functionNode )
+    {
+    	status = CALL;
+    }
+    
+    public PseudoCodeNode getFunction()
+    {
+    	return function;
+    }
+    
     public int getStatus()
     {
         return status;

+ 54 - 7
src/animation/Memory.java

@@ -1,7 +1,10 @@
 package animation;
 
+import java.util.Iterator;
 import java.util.Stack;
 
+import animation.StackFrame.FrameType;
+
 public class Memory {
 
     private StackFrame global;
@@ -10,17 +13,17 @@ public class Memory {
     public Memory()
     {
         stack = new Stack<StackFrame>();
-        global = new StackFrame();
+        global = new StackFrame( FrameType.FUNCTION );
     }
     
-    public void addFrame()
+    public void addFrame( StackFrame frame )
     {
-        stack.push( new StackFrame() );
+        stack.push( frame );
     }
     
-    public void removeFrame()
+    public StackFrame removeFrame()
     {
-        stack.pop();
+        return stack.pop();
     }
     
     public <T> void declare( String name, T value, boolean global )
@@ -36,7 +39,19 @@ public class Memory {
         if( global )
             this.global.set( name, value );
         else
-            stack.peek().set( name, value );
+        {
+        	Iterator<StackFrame> iterator = stack.iterator();
+        	while (iterator.hasNext()) {
+        	   StackFrame stackF = iterator.next();
+        	   if( stackF.isDefined( name ) )
+        	   {
+        		   stackF.set( name, value );
+        		   return;
+        	   }
+        	   if( stackF.getType() == FrameType.FUNCTION )
+        		   break;
+        	}
+        }
     }
     
     public <T> T read( String name, boolean global )
@@ -44,7 +59,39 @@ public class Memory {
         if( global )
             return this.global.get( name );
         else
-            return stack.peek().get( name );
+        {
+        	Iterator<StackFrame> iterator = stack.iterator();
+        	while (iterator.hasNext()) {
+        	   StackFrame stackF = iterator.next();
+        	   if( stackF.isDefined( name ) )
+        		   stackF.get( name );
+        	   if( stackF.getType() == FrameType.FUNCTION )
+        		   break;
+        	}
+            return null;
+        }
+    }
+    
+    public boolean isSomewhereDefined( String name, boolean global )
+    {
+    	if( global )
+    		return this.global.isDefined( name );
+    	Iterator<StackFrame> iterator = stack.iterator();
+    	while (iterator.hasNext()) {
+    	   StackFrame stackF = iterator.next();
+    	   if( stackF.isDefined( name ) )
+    		   return true;
+    	   if( stackF.getType() == FrameType.FUNCTION )
+    		   break;
+    	}
+    	return false;
+    }
+    
+    public boolean isDefined( String name, boolean global )
+    {
+    	if( global )
+    		return this.global.isDefined( name );
+    	return stack.peek().get( name );
     }
     
     public void undeclare( String name, boolean global )

+ 127 - 70
src/animation/PseudoCodeNode.java

@@ -27,28 +27,33 @@ public class PseudoCodeNode extends DefaultMutableTreeNode {
     }
     
     private static final long serialVersionUID = 1L;
-    
-    private boolean selected;
+
+    private static int nextNodeId = 0;
+    private final int nodeId;
+    private AnimationController controller;
+    private AnimatedAlgorithm alg;
     private JTree tree;
+    private CodeLine code;
+    private boolean selected;
     private boolean breakPoint;
-    private AnimationController controller;
+    private boolean function;
+
     private int currentCodeLine; // next forward code line
-    private int beforeCodeLine; // next backwards code line
-    private CodeLine code;
-    private boolean loop;
-    private boolean stackFrameAdded;
     
-    public PseudoCodeNode( String description, JTree tree, CodeLine line )
+    public PseudoCodeNode( String description, JTree tree, CodeLine line, AnimatedAlgorithm alg )
     {
         super( description );
+        this.alg = alg;
+        synchronized( PseudoCodeNode.class )
+        {
+        	nodeId = nextNodeId++;
+        }
         selected = false;
         this.tree = tree;
         breakPoint = false;
         currentCodeLine = -1;
-        beforeCodeLine = -2;
         code = line;
-        loop = false;
-        stackFrameAdded = false;
+        function = false;
     }
     
     public void setController( AnimationController c )
@@ -63,6 +68,37 @@ public class PseudoCodeNode extends DefaultMutableTreeNode {
         controller = c;
     }
     
+    private void writeToStack( Memory m )
+    {
+    	if( m.isDefined( "_pos" + nodeId, false ) )
+    		throw new IllegalStateException( "variable _pos" + nodeId + " should not exist in current stack frame, but it exists" );
+    	if( m.isDefined( "_func" + nodeId, false ) )
+    		throw new IllegalStateException( "variable _func" + nodeId + " should not exist in current stack frame, but it exists" );
+    	m.declare( "_pos" + nodeId, currentCodeLine, false );
+    	m.declare( "_func" + nodeId, function, false );
+    	setSelected( false );
+    	if( children == null )
+    		return;
+    	for( Object c : children )
+    		((PseudoCodeNode)c).writeToStack( m );
+    }
+    
+    private void loadFromStack( Memory m )
+    {
+    	if( !m.isDefined( "_pos" + nodeId, false ) )
+    		throw new IllegalStateException( "variable _pos" + nodeId + "should exist in current stack frame, but it is undefined" );
+    	if( !m.isDefined( "_func" + nodeId, false ) )
+    		throw new IllegalStateException( "variable _func" + nodeId + "should exist in current stack frame, but it is undefined" );
+    	currentCodeLine = m.read( "_pos" + nodeId, false );
+    	function = m.read( "_func" + nodeId, false );
+    	m.undeclare( "_pos" + nodeId, false );
+    	m.undeclare( "_func" + nodeId, false );
+    	if( children == null )
+    		return;
+    	for( Object c : children )
+    		((PseudoCodeNode)c).loadFromStack( m );
+    }
+    
     @Override
     public void add( MutableTreeNode node )
     {
@@ -162,46 +198,25 @@ public class PseudoCodeNode extends DefaultMutableTreeNode {
     
     private PseudoCodeNode getBackwardNode()
     {
-        if( beforeCodeLine == -1 )
+        if( currentCodeLine - 1 <= -1 )
             return this;
-        if( children != null && children.size() > beforeCodeLine )
-            return ((PseudoCodeNode)children.get( beforeCodeLine )).getBackwardNode();
+        if( children != null && children.size() >= currentCodeLine - 1 )
+            return ((PseudoCodeNode)children.get( currentCodeLine - 1 )).getBackwardNode();
         return this;
     }
     
     private CodeStatus stepInto( Memory m )
     {
-        currentCodeLine = 1;
-        beforeCodeLine = 0;
-        stackFrameAdded = true;
+        currentCodeLine = 0;
         if( children == null || children.size() == 0 )
         {
             setSelected( false );
-            if( stackFrameAdded )
-                m.removeFrame();
-            stackFrameAdded = false;
             return CodeStatus.FINISHED;
         }
         else
         {
             setSelected( false );
-            CodeStatus status = selectChild( 0, m ); // TODO if loop do something when finished
-            if( status == CodeStatus.FINISHED )
-            {
-                if( loop )
-                {
-                    beforeCodeLine = currentCodeLine;
-                    currentCodeLine = -1; // TODO select this node
-                    status = CodeStatus.UNFINISHED;
-                }
-                else
-                {
-                    if( stackFrameAdded )
-                        m.removeFrame();
-                    stackFrameAdded = false;
-                }
-            }
-            return status;
+            return selectChild( 0, m );
         }
     }
     
@@ -217,28 +232,72 @@ public class PseudoCodeNode extends DefaultMutableTreeNode {
             ControlFlow cf = code.runForward( m );
             switch( cf.getStatus() )
             {
-            case ControlFlow.STEP_INTO_LOOP:
-                loop = true;
-                return stepInto( m );
-            case ControlFlow.STEP_INTO_STACK:
-                stackFrameAdded = true;
-                return stepInto( m );
             case ControlFlow.STEP_INTO:
-                return stepInto( m );
+            	function = true;
+            	StackFrame tmp = m.removeFrame();
+            	if( children != null )
+            	{
+            		for( Object c : children )
+            			((PseudoCodeNode)c).writeToStack( m );
+            	}
+            	m.addFrame( tmp );
+                switch( stepInto( m ) )
+                {
+				case BREAKPOINT:
+					return CodeStatus.BREAKPOINT;
+				case FINISHED:
+					currentCodeLine = -1;
+                    switch( setSelected( true ) )
+                    {
+					case SKIP:
+						return forwardStepOverIntern( m );
+					case STOP:
+						return CodeStatus.BREAKPOINT;
+					default:
+						break;
+                    }
+				case UNFINISHED:
+					return CodeStatus.UNFINISHED;
+                }
             case ControlFlow.STEP_OVER:
-                if( stackFrameAdded )
-                    m.removeFrame();
-                stackFrameAdded = false;
+            	if( function )
+            	{
+                	if( children != null )
+                	{
+                		for( Object c : children )
+                			((PseudoCodeNode)c).loadFromStack( m );
+                	}
+            	}
                 return CodeStatus.FINISHED;
+            case ControlFlow.CALL:
+    			alg.addActiveFunction( cf.getFunction() );
+    			setSelected( false );
+    			m.declare( "callback", this, true );
+    			switch( cf.getFunction().setSelected( true ) )
+    			{
+				case CONTINUE:
+					break;
+				case SKIP:
+					switch( cf.getFunction().forwardStepOverIntern( m ) )
+        			{
+					case BREAKPOINT:
+						return CodeStatus.BREAKPOINT;
+					case FINISHED:
+					case UNFINISHED:
+						return CodeStatus.UNFINISHED;
+        			}
+					break;
+				case STOP:
+					return CodeStatus.BREAKPOINT;
+    			}
+    			return CodeStatus.UNFINISHED;
             }
         }
         else
         {
             if( children == null || children.size() <= currentCodeLine )
             {
-                if( stackFrameAdded )
-                    m.removeFrame();
-                return CodeStatus.FINISHED;
+            	throw new IllegalStateException( "Some wired stuff is going on" );
             }
             switch( ( (PseudoCodeNode)children.get( currentCodeLine ) ).forwardStep( m ) )
             {
@@ -246,19 +305,18 @@ public class PseudoCodeNode extends DefaultMutableTreeNode {
                 return CodeStatus.BREAKPOINT;
             case FINISHED:
                 ( (PseudoCodeNode)children.get( currentCodeLine ) ).setSelected( false );
-                beforeCodeLine = currentCodeLine;
                 currentCodeLine++;
                 if( children.size() <= currentCodeLine )
                 {
-                    if( loop )
+                    currentCodeLine = -1;
+                    switch( setSelected( true ) )
                     {
-                        currentCodeLine = -1; // TODO select this node
-                    }
-                    else
-                    {
-                        if( stackFrameAdded )
-                            m.removeFrame();
-                        return CodeStatus.FINISHED;
+					case SKIP:
+						return forwardStepOverIntern( m );
+					case STOP:
+						return CodeStatus.BREAKPOINT;
+					default:
+						break;
                     }
                 }
                 else
@@ -266,16 +324,16 @@ public class PseudoCodeNode extends DefaultMutableTreeNode {
                     CodeStatus status = selectChild( currentCodeLine, m );
                     if( status == CodeStatus.FINISHED )
                     {
-                        if( loop )
-                        {
-                            beforeCodeLine = currentCodeLine;
-                            currentCodeLine = -1; // TODO select this node
-                            status = CodeStatus.UNFINISHED;
-                        }
-                        else
+                        currentCodeLine = -1;
+                        status = CodeStatus.UNFINISHED;
+                        switch( setSelected( true ) )
                         {
-                            if( stackFrameAdded )
-                                m.removeFrame();
+    					case SKIP:
+    						return forwardStepOverIntern( m );
+    					case STOP:
+    						return CodeStatus.BREAKPOINT;
+    					default:
+    						break;
                         }
                     }
                     return status;
@@ -300,7 +358,6 @@ public class PseudoCodeNode extends DefaultMutableTreeNode {
                 return CodeStatus.BREAKPOINT;
             case FINISHED:
                 ( (PseudoCodeNode)children.get( index ) ).setSelected( false );
-                beforeCodeLine = currentCodeLine;
                 currentCodeLine++;
                 if( children == null || currentCodeLine >= children.size() )
                 {
@@ -311,7 +368,7 @@ public class PseudoCodeNode extends DefaultMutableTreeNode {
                     return selectChild( currentCodeLine, m );
                 }
             case UNFINISHED:
-                break;
+            	throw new IllegalStateException( "Skipping a node returned UNFINISHED" );
             }
         case STOP:
             return CodeStatus.BREAKPOINT;

+ 13 - 1
src/animation/StackFrame.java

@@ -4,13 +4,25 @@ import java.util.HashMap;
 
 public class StackFrame {
 
+	public enum FrameType {
+		FUNCTION,
+		LOOP
+	}
+	
     private HashMap< String, Object > data;
+    private FrameType type;
     
-    public StackFrame()
+    public StackFrame( FrameType type )
     {
+    	this.type = type;
         data = new HashMap< String, Object >();
     }
     
+    public FrameType getType()
+    {
+    	return type;
+    }
+    
     public <T> void declare( String name, T value )
     {
         data.put( name, (Object)value );

+ 48 - 29
src/bk/BKNodePlacement.java

@@ -6,6 +6,8 @@ import javax.swing.JTree;
 import animation.AnimatedAlgorithm;
 import animation.AnimationController;
 import animation.CodeLine;
+import animation.ControlFlow;
+import animation.Memory;
 import animation.PseudoCodeNode;
 import graph.LayeredGraphNode;
 import lib.TextLayoutHelper;
@@ -35,25 +37,17 @@ public class BKNodePlacement extends AnimatedAlgorithm {
     private State state;
     private ExtremalLayoutCalc layouts[];
     private Combine combine;
-    private PseudoCodeNode conflictsNode; 
-    private PseudoCodeNode layout1Node;
-    private PseudoCodeNode layout2Node;
-    private PseudoCodeNode layout3Node;
-    private PseudoCodeNode layout4Node;
-    private PseudoCodeNode combineNode;
-    private boolean inside;
 
     public BKNodePlacement(AnimationController controller, LayeredGraphNode graph, JFrame view) {
         super(controller, graph, view);
         state = State.CONFLICTS;
-        conftion = new ConflictDetection( graph );
+        conftion = new ConflictDetection( graph, this );
         layouts = new ExtremalLayoutCalc[ 4 ];
-        layouts[ 0 ] = new ExtremalLayoutCalc( ExtremalLayoutCalc.LayoutType.TOP_BOTTOM_LEFT, graph );
-        layouts[ 1 ] = new ExtremalLayoutCalc( ExtremalLayoutCalc.LayoutType.TOP_BOTTOM_RIGHT, graph );
-        layouts[ 2 ] = new ExtremalLayoutCalc( ExtremalLayoutCalc.LayoutType.BOTTOM_TOP_LEFT, graph );
-        layouts[ 3 ] = new ExtremalLayoutCalc( ExtremalLayoutCalc.LayoutType.BOTTOM_TOP_RIGHT, graph );
-        combine = new Combine( graph );
-        inside = false;
+        layouts[ 0 ] = new ExtremalLayoutCalc( graph, this );
+        layouts[ 1 ] = new ExtremalLayoutCalc( graph, this );
+        layouts[ 2 ] = new ExtremalLayoutCalc( graph, this );
+        layouts[ 3 ] = new ExtremalLayoutCalc( graph, this );
+        combine = new Combine( graph, this );
     }
     
     public State getAlgorithmState()
@@ -64,28 +58,53 @@ public class BKNodePlacement extends AnimatedAlgorithm {
     @Override
     public PseudoCodeNode createPseudocodeTree( JTree tree )
     {
-        root = new PseudoCodeNode( TextLayoutHelper.setupPseudoCodeStage("BK Node Placement Algorithm"), tree, CodeLine.DEFAULT_STEP_INTO_STACK );
+    	root = new PseudoCodeNode( TextLayoutHelper.setupPseudoCodeStage("BK Node Placement Algorithm" ), tree, new CodeLine() {
+
+			@Override
+			public ControlFlow runForward(Memory m) {
+				return new ControlFlow( ControlFlow.STEP_INTO );
+			}
+        	
+        }, this );
         root.setSelected( true );
-        conflictsNode = conftion.createPseudocodeTree( tree );
-        layout1Node = layouts[ 0 ].createPseudocodeTree( tree );
-        layout2Node = layouts[ 1 ].createPseudocodeTree( tree );
-        layout3Node = layouts[ 2 ].createPseudocodeTree( tree );
-        layout4Node = layouts[ 3 ].createPseudocodeTree( tree );
-        combineNode = combine.createPseudocodeTree( tree );
-        root.add( conflictsNode );
-        root.add( layout1Node );
-        root.add( layout2Node );
-        root.add( layout3Node );
-        root.add( layout4Node );
-        root.add( combineNode );
+    	String[] vars = { "graph" };
+    	PseudoCodeNode mainFunction = new PseudoCodeNode( TextLayoutHelper.setupPseudoCode("function bkNodePlacement( graph )", vars ), tree, new CodeLine() {
+
+			@Override
+			public ControlFlow runForward(Memory m) {
+				return new ControlFlow( ControlFlow.STEP_INTO );
+			}
+        	
+        }, this );
+    	
+        PseudoCodeNode conflictDetectionFunction = conftion.createPseudocodeTree( tree );
+        
+        PseudoCodeNode node1 = new PseudoCodeNode( TextLayoutHelper.setupPseudoCode( "call detectConflicts( graph )", vars ), tree, new CodeLine() {
+
+			@Override
+			public ControlFlow runForward(Memory m) {
+				if( !m.isDefined( "line_" + lineId + "_call", false ) )
+				{
+					m.declare( "line_" + lineId + "_call", true, false );
+					return new ControlFlow( conflictDetectionFunction );
+				}
+				else
+				{
+					m.undeclare( "line_" + lineId + "_call", false );
+					return new ControlFlow( ControlFlow.STEP_OVER );
+				}
+			}
+        	
+        }, this );
+        root.add( mainFunction );
+        mainFunction.add( node1 );
+        root.add( conflictDetectionFunction );
         return root;
     }
 
     @Override
     public String getDebugString()
     {
-        if( !inside )
-            return "";
         switch( state )
         {
         case CONFLICTS:

+ 18 - 330
src/bk/BlockCalc.java

@@ -1,19 +1,13 @@
 package bk;
 
-import java.util.ArrayList;
-import java.util.Collections;
-
 import javax.swing.JTree;
 
 import animation.AlgorithmStage;
-import animation.BackwardAction;
+import animation.AnimatedAlgorithm;
 import animation.CodeLine;
 import animation.ControlFlow;
 import animation.Memory;
 import animation.PseudoCodeNode;
-import animation.PseudoCodeNode.CodeAction;
-import bk.ExtremalLayoutCalc.LayoutType;
-import graph.LayeredGraphEdge;
 import graph.LayeredGraphNode;
 import lib.TextLayoutHelper;
 
@@ -24,343 +18,37 @@ import lib.TextLayoutHelper;
  */
 public class BlockCalc implements AlgorithmStage {
 
-    private int layerIndex;
-    private int nodeIndex;
-    private int r;
     private LayeredGraphNode graph;
-    private ArrayList< ArrayList< PseudoCodeNode > > subgraphNodes;
-    private ArrayList< ArrayList< ExtremalLayoutCalc > > subgraphAlgs;
-    private LayoutType layout;
-    private boolean inside;
-    int step;
+    private AnimatedAlgorithm alg;
 
-    public BlockCalc( LayeredGraphNode graph, LayoutType layout )
+    public BlockCalc( LayeredGraphNode graph, AnimatedAlgorithm alg  )
     {
-        this.layout = layout;
-        step = 0;
         this.graph = graph;
-        layerIndex = 0;
-        nodeIndex = 0;
-        r = 0;
-        subgraphNodes = new ArrayList<>();
-        subgraphAlgs = new ArrayList<>();
-        for( ArrayList<LayeredGraphNode> l : graph.getContainedLayers() )
-        {
-            ArrayList< PseudoCodeNode > nodes = new ArrayList<>();
-            ArrayList< ExtremalLayoutCalc > algs = new ArrayList<>();
-            for( int i = 0; i < l.size(); i++ )
-            {
-                nodes.add( null );
-                algs.add( null );
-            }
-            subgraphAlgs.add( algs );
-            subgraphNodes.add( nodes );
-        }
-        inside = false;
-        backwards = new ArrayList<>();
-    }
-
-    private int calcLayerIndex()
-    {
-        if( layout == LayoutType.TOP_BOTTOM_LEFT || layout == LayoutType.TOP_BOTTOM_RIGHT )
-            return layerIndex;
-        if( layout == LayoutType.BOTTOM_TOP_LEFT || layout == LayoutType.BOTTOM_TOP_RIGHT )
-            return graph.getContainedLayers().size() - layerIndex - 1;
-        return -1;
-    }
-
-    private int calcBeforeLayerIndex()
-    {
-        if( layout == LayoutType.TOP_BOTTOM_LEFT || layout == LayoutType.TOP_BOTTOM_RIGHT )
-            return layerIndex - 1;
-        if( layout == LayoutType.BOTTOM_TOP_LEFT || layout == LayoutType.BOTTOM_TOP_RIGHT )
-            return graph.getContainedLayers().size() - layerIndex;
-        return -1;
-    }
-
-    private int calcNodeIndex( int index )
-    {
-        if( layout == LayoutType.TOP_BOTTOM_LEFT || layout == LayoutType.BOTTOM_TOP_LEFT )
-            return index;
-        if( layout == LayoutType.TOP_BOTTOM_RIGHT || layout == LayoutType.BOTTOM_TOP_RIGHT )
-            return graph.getContainedLayers().get( calcLayerIndex() ).size() - index - 1;
-        return index;
-    }
-    
-    private int calcBeforeLayerNodeIndex( int index )
-    {
-        if( layout == LayoutType.TOP_BOTTOM_LEFT || layout == LayoutType.BOTTOM_TOP_LEFT )
-            return index;
-        if( layout == LayoutType.TOP_BOTTOM_RIGHT || layout == LayoutType.BOTTOM_TOP_RIGHT )
-            return graph.getContainedLayers().get( calcBeforeLayerIndex() ).size() - index - 1;
-        return index;
-    }
-
-    @Override
-    public StageStatus forwardStep() {
-        LayeredGraphNode current = graph.getContainedLayers().get( calcLayerIndex() ).get( calcNodeIndex( nodeIndex ) );
-        current.setSelected( layout );
-        if( current.getContainedNodes().size() > 0 )
-        {
-            inside = true;
-            boolean breakpoint = false;
-            boolean selected = subgraphNodes.get( calcLayerIndex() ).get( calcNodeIndex( nodeIndex ) ).isSelected();
-            CodeAction action = subgraphNodes.get( calcLayerIndex() ).get( calcNodeIndex( nodeIndex ) ).setSelected( true );
-            if( !selected )
-                breakpoint |= action == CodeAction.STOP;
-            do {
-                switch( subgraphAlgs.get( calcLayerIndex() ).get( calcNodeIndex( nodeIndex ) ).forwardStep() )
-                {
-                case BREAKPOINT:
-                    return StageStatus.BREAKPOINT;
-                case UNFINISHED:
-                    if( breakpoint )
-                        return StageStatus.BREAKPOINT;
-                    return StageStatus.UNFINISHED;
-                case FINISHED:
-                    inside = false;
-                    subgraphNodes.get( calcLayerIndex() ).get( calcNodeIndex( nodeIndex ) ).setSelected( false );
-                    action = null;
-                    break;
-                }
-            } while( !breakpoint && action == CodeAction.SKIP );
-        }
-        ArrayList< LayeredGraphEdge > incommingEdges = null;
-        if( layout == LayoutType.TOP_BOTTOM_LEFT || layout == LayoutType.TOP_BOTTOM_RIGHT )
-            incommingEdges = current.getSortedIncomingEdges();
-        if( layout == LayoutType.BOTTOM_TOP_LEFT || layout == LayoutType.BOTTOM_TOP_RIGHT )
-            incommingEdges = current.getSortedOutgoingEdges();
-        if( layout == LayoutType.TOP_BOTTOM_RIGHT || layout == LayoutType.BOTTOM_TOP_RIGHT )
-        Collections.reverse( incommingEdges );
-        if( incommingEdges.size() == 0 )
-        {
-            backwards.add( 0, () -> {
-                System.out.println( "Performing Empty Backwards Step..." );
-            });
-            return calcNextState();
-        }
-        int[] ms = {(incommingEdges.size() + 1) / 2, (int)( (incommingEdges.size() + 1) / 2.0 + 0.5 )};
-        boolean backwardsAdded = false;
-        for( int m : ms )
-        {
-            if( current.getAlign( layout ) == current )
-            {
-                LayeredGraphNode u = null;
-                if( layout == LayoutType.TOP_BOTTOM_LEFT || layout == LayoutType.TOP_BOTTOM_RIGHT )
-                    u = incommingEdges.get( m - 1 ).getSources().get( 0 );
-                if( layout == LayoutType.BOTTOM_TOP_LEFT || layout == LayoutType.BOTTOM_TOP_RIGHT )
-                    u = incommingEdges.get( m - 1 ).getTargets().get( 0 );
-                ArrayList<LayeredGraphEdge> conflicts = incommingEdges.get( m - 1 ).calcEdgeCrossings();
-                
-                if( !incommingEdges.get( m - 1 ).isConflicted( layout ) && r < calcBeforeLayerNodeIndex( graph.getContainedLayers().get( calcBeforeLayerIndex() ).indexOf( u ) ) + 1 )
-                {
-                    System.out.println( "" );
-                    ArrayList< Boolean > oldConflicts = new ArrayList<>();
-                    for( LayeredGraphEdge e : conflicts )
-                    {
-                        oldConflicts.add( e.isConflicted( layout ) );
-                        e.setConflicted( true, layout );
-                    }
-                    LayeredGraphNode oldAlignU = u.getAlign( layout );
-                    LayeredGraphNode oldRootCurrent = current.getRoot( layout );
-                    LayeredGraphNode oldAlignCurrent = current.getAlign( layout );
-                    int oldR = r;
-                    u.setAlign( current, layout );
-                    current.setRoot( u.getRoot( layout ), layout );
-                    current.setAlign( current.getRoot( layout ), layout );
-                    r = calcBeforeLayerNodeIndex( graph.getContainedLayers().get( calcBeforeLayerIndex() ).indexOf( u ) ) + 1;
-                    int oldStep = step++;
-                    final LayeredGraphNode uf = u;
-                    backwards.add( 0, () -> {
-                        System.out.println( "Stepping Backwards... (Step " + oldStep + ")" );
-                        for( int i = 0; i < conflicts.size(); i++ )
-                            conflicts.get( i ).setConflicted( oldConflicts.get( i ), layout );
-                        uf.setAlign( oldAlignU, layout );
-                        current.setRoot( oldRootCurrent, layout );
-                        current.setAlign( oldAlignCurrent, layout );
-                        r = oldR;
-                    });
-                    backwardsAdded = true;
-                }
-            }
-        }
-        if( !backwardsAdded )
-        {
-            backwards.add( 0, () -> {
-                System.out.println( "Performing Empty Backwards Step..." );
-            });
-        }
-        CodeAction action = loopNode.setSelected( true );
-        boolean breakpoint = action == CodeAction.STOP;
-        StageStatus status = calcNextState();
-        if( status == StageStatus.FINISHED )
-            return status;
-        if( breakpoint )
-            return StageStatus.BREAKPOINT;
-        if( action == CodeAction.SKIP )
-            return forwardStep();
-        return status;
-    }
-
-    private StageStatus calcNextState()
-    {
-        if( layerIndex >= graph.getContainedLayers().size() - 1 )
-        {
-            if( nodeIndex >= graph.getContainedLayers().get( calcLayerIndex() ).size() -1 )
-            {
-                loopNode.setSelected( false );
-                return StageStatus.FINISHED;
-            }
-        }
-        nodeIndex++;
-        if( nodeIndex >= graph.getContainedLayers().get( calcLayerIndex() ).size() )
-        {
-            layerIndex++;
-            nodeIndex = 0;
-            int oldR = r;
-            r = 0;
-            backwards.add(0, ()->{
-               this.r = oldR;
-            });
-        }
-        return StageStatus.UNFINISHED;
-    }
-
-    @Override
-    public StageStatus backwardStep() {
-        if( subgraphAlgs.get( calcLayerIndex() ).get( calcNodeIndex( nodeIndex ) ) != null )
-        {
-            inside = true;
-            boolean breakpoint = false;
-            boolean selected = subgraphNodes.get( calcLayerIndex() ).get( calcNodeIndex( nodeIndex ) ).isSelected();
-            CodeAction action = subgraphNodes.get( calcLayerIndex() ).get( calcNodeIndex( nodeIndex ) ).setSelected( true );
-            if( !selected )
-                breakpoint |= action == CodeAction.STOP;
-            do {
-                switch( subgraphAlgs.get( calcLayerIndex() ).get( calcNodeIndex( nodeIndex ) ).backwardStep() )
-                {
-                case BREAKPOINT:
-                    return StageStatus.BREAKPOINT;
-                case UNFINISHED:
-                    LayeredGraphNode current = graph.getContainedLayers().get( calcLayerIndex() ).get( calcNodeIndex(  nodeIndex ) );
-                    current.setSelected( layout );
-                    if( breakpoint )
-                        return StageStatus.BREAKPOINT;
-                    return StageStatus.UNFINISHED;
-                case FINISHED:
-                    inside = false;
-                    subgraphNodes.get( calcLayerIndex() ).get( calcNodeIndex( nodeIndex ) ).setSelected( false );
-                    action = null;
-                    break;
-                }
-            } while( !breakpoint && action == CodeAction.SKIP );
-        }
-        CodeAction action = loopNode.setSelected( true );
-        boolean breakpoint = action == CodeAction.STOP;
-        LayeredGraphNode current = graph.getContainedLayers().get( calcLayerIndex() ).get( calcNodeIndex( nodeIndex ) );
-        current.setSelected( layout );
-        if( !backwards.isEmpty() )
-        {
-            backwards.get( 0 ).reverse();
-            backwards.remove( 0 );
-        }
-        StageStatus status = calcBeforeState();
-        if( status == StageStatus.FINISHED )
-            return status;
-        if( breakpoint )
-            return StageStatus.BREAKPOINT;
-        if( action == CodeAction.SKIP )
-            return backwardStep();
-        return status;
-    }
-
-    private StageStatus calcBeforeState()
-    {
-        if( layerIndex == 0 )
-        {
-            if( nodeIndex == 0 )
-            {
-                loopNode.setSelected( false );
-                return StageStatus.FINISHED;
-            }
-        }
-        nodeIndex--;
-        if( nodeIndex < 0 )
-        {
-            layerIndex--;
-            backwards.get( 0 ).reverse();
-            backwards.remove( 0 );
-            nodeIndex = graph.getContainedLayers().get( calcLayerIndex() ).size() - 1;
-        }
-        return StageStatus.UNFINISHED;
+        this.alg = alg;
     }
 
     @Override
     public PseudoCodeNode createPseudocodeTree( JTree tree ) {
-        String[] vars = { "graph" };
-        PseudoCodeNode root = new PseudoCodeNode( TextLayoutHelper.setupPseudoCode( "calculateBlockGraph( graph )", vars ), tree, CodeLine.DEFAULT_STEP_INTO_STACK );
-        PseudoCodeNode[] nodes = new PseudoCodeNode[12];
-        if( layout == LayoutType.TOP_BOTTOM_LEFT || layout == LayoutType.TOP_BOTTOM_RIGHT )
-            nodes[ 0 ] = new PseudoCodeNode( TextLayoutHelper.setupPseudoCode( "for i=0 to |L|-1 do", vars ), tree, new CodeLine() {
-
-                private boolean initialized = false;
-                private Integer i;
-                
-                @Override
-                public ControlFlow runForward(Memory m) {
-                    if( !initialized )
-                    {
-                        initialized = true;
-                        i = 0;
-                        m.declare( "i", i, false );
-                    }
-                    else
-                    {
-                        i++;
-                    }
-                    if( i >= m.<LayeredGraphNode>read( "graph", false ).getContainedLayers().size() )
-                    {
-                        m.undeclare( "i", false );
-                        return new ControlFlow( ControlFlow.STEP_OVER );
-                    }
-                    else
-                        return new ControlFlow( ControlFlow.STEP_INTO_LOOP );
-                }
-
-                @Override
-                public ControlFlow runBackward(Memory m) {
-                    
-                }
-                
-            });
-        do {
-            LayeredGraphNode current = graph.getContainedLayers().get( calcLayerIndex() ).get( calcNodeIndex( nodeIndex ) );
-            if( current.getContainedNodes().size() > 0 )
-            {
-                ExtremalLayoutCalc extcalc = new ExtremalLayoutCalc( layout, current );
-                PseudoCodeNode subNode = extcalc.createPseudocodeTree( loopNode.getTree() );
-                loopNode.add( subNode );
-                subgraphAlgs.get( calcLayerIndex() ).set( calcNodeIndex( nodeIndex ), extcalc );
-                subgraphNodes.get( calcLayerIndex() ).set( calcNodeIndex( nodeIndex ), subNode );
-            }
-        } while( calcNextState() != StageStatus.FINISHED );
-        layerIndex = 0;
-        nodeIndex = 0;
-        backwards.clear();
-        root.add( loopNode );
+        String[] vars = { "graph", "L", "v", "r", "neighbors" };
+        PseudoCodeNode root = new PseudoCodeNode( TextLayoutHelper.setupPseudoCode( "calculateBlockGraph( graph )", vars ), tree, new CodeLine() {
+
+        	private LayeredGraphNode param;
+        	
+			@Override
+			public ControlFlow runForward(Memory m) {
+				param = m.<LayeredGraphNode>read( "param1", true );
+				m.declare( "graph", param, false );
+				m.declare( "Layers", param.getContainedLayers(), false );
+				return new ControlFlow( ControlFlow.STEP_INTO );
+			}
+        	
+        }, alg);
         return root;
     }
     
     @Override
     public String getDebugString()
     {
-        if( inside )
-        {
-            String info = "Subgraph of " + graph.getContainedLayers().get( calcLayerIndex() ).get( calcNodeIndex( nodeIndex ) ).getName() + ":\n";
-            String tmp = subgraphAlgs.get( calcLayerIndex() ).get( calcNodeIndex( nodeIndex ) ).getDebugString();
-            info += tmp;
-            return info;
-        }
         return "";
     }
 }

+ 17 - 448
src/bk/Combine.java

@@ -1,16 +1,13 @@
 package bk;
 
-import java.awt.Color;
-import java.util.ArrayList;
-import java.util.Collections;
-
 import javax.swing.JTree;
 
 import animation.AlgorithmStage;
-import animation.BackwardAction;
+import animation.AnimatedAlgorithm;
+import animation.CodeLine;
+import animation.ControlFlow;
+import animation.Memory;
 import animation.PseudoCodeNode;
-import animation.PseudoCodeNode.CodeAction;
-import bk.ExtremalLayoutCalc.LayoutType;
 import graph.LayeredGraphNode;
 import lib.TextLayoutHelper;
 
@@ -21,462 +18,34 @@ import lib.TextLayoutHelper;
  */
 public class Combine implements AlgorithmStage {
 
-    LayeredGraphNode graph;
-
-    private enum State
-    {
-        ALIGN,
-        SET_COORDINATES
-    }
-
-    private State state;
-    private int btlOffset;
-    private int btrOffset;
-    private int tblOffset;
-    private int tbrOffset;
-    private int vIndex;
-    private ArrayList< BackwardAction > actions;
-    private PseudoCodeNode alignNode;
-    private PseudoCodeNode setNode;
-    private PseudoCodeNode loopNode;
-    private boolean inside;
-    private boolean insideSubgraph;
-    private boolean breakPoint;
-    private boolean skipBackwards;
-    private ArrayList< PseudoCodeNode > subgraphNodes;
-    private ArrayList< Combine > subgraphAlgs;
+    private LayeredGraphNode graph;
+    private AnimatedAlgorithm alg;
 
-    public Combine( LayeredGraphNode graph )
+    public Combine( LayeredGraphNode graph, AnimatedAlgorithm alg )
     {
         this.graph = graph;
-        state = State.ALIGN;
-        vIndex = 0;
-        actions = new ArrayList<>();
-        inside = false;
-        insideSubgraph = false;
-        skipBackwards = false;
-        subgraphNodes = new ArrayList<>();
-        subgraphAlgs = new ArrayList<>();
-        for( @SuppressWarnings("unused") LayeredGraphNode n : graph.getContainedNodes() )
-        {
-            subgraphAlgs.add( null );
-            subgraphNodes.add( null );
-        }
-    }
-
-    @Override
-    public StageStatus forwardStep() {
-        breakPoint = false;
-        if( state == State.ALIGN )
-        {
-            inside = false;
-            boolean sel = alignNode.isSelected();
-            CodeAction action = alignNode.setSelected( true );
-            if( !sel )
-                breakPoint |= action == CodeAction.STOP;
-            int tblw = (int)calcMaxX( LayoutType.TOP_BOTTOM_LEFT );
-            int tbrw = (int)calcMaxX( LayoutType.TOP_BOTTOM_RIGHT );
-            int btlw = (int)calcMaxX( LayoutType.BOTTOM_TOP_LEFT );
-            int btrw = (int)calcMaxX( LayoutType.BOTTOM_TOP_RIGHT );
-            LayoutType minLayout = LayoutType.TOP_BOTTOM_LEFT;
-            int minWidth = tblw;
-            if( tbrw < minWidth )
-            {
-                minWidth = tbrw;
-                minLayout = LayoutType.TOP_BOTTOM_RIGHT;
-            }
-            if( btlw < minWidth )
-            {
-                minWidth = btlw;
-                minLayout = LayoutType.BOTTOM_TOP_LEFT;
-            }
-            if( btrw < minWidth )
-            {
-                minWidth = btrw;
-                minLayout = LayoutType.BOTTOM_TOP_RIGHT;
-            }
-            int minX = calcMinX( minLayout );
-            btlOffset = minX - calcMinX( LayoutType.BOTTOM_TOP_LEFT );
-            tblOffset = minX - calcMinX( LayoutType.TOP_BOTTOM_LEFT );
-            btrOffset = minWidth - btrw;
-            tbrOffset = minWidth - tbrw;
-            Color oldColor = graph.getColor( LayoutType.COMBINED );
-            if( oldColor == null )
-                graph.setColor( Color.BLACK, null );
-            actions.add( 0, () -> {
-                inside = false;
-                loopNode.setSelected( false );
-                setNode.setSelected( false );
-                breakPoint = false;
-                boolean selected = alignNode.isSelected();
-                CodeAction ac = alignNode.setSelected( true );
-                if( !selected )
-                    breakPoint |= ac == CodeAction.STOP;
-                skipBackwards = ac == CodeAction.SKIP;
-                state = State.ALIGN;
-                if( oldColor == null )
-                    graph.setColor( null, null );
-            });
-            state = State.SET_COORDINATES;
-            alignNode.setSelected( false );
-            sel = setNode.isSelected();
-            CodeAction ac = setNode.setSelected( true );
-            boolean skip = ac == CodeAction.SKIP;
-            if( !sel )
-                breakPoint |= ac == CodeAction.STOP;
-            ac = loopNode.setSelected( true );
-            breakPoint |= ac == CodeAction.STOP;
-            skip |= ac == CodeAction.SKIP;
-            if( (action == CodeAction.SKIP || skip) && !breakPoint )
-                return forwardStep();
-        }
-        else
-        {
-            CodeAction action = loopNode.setSelected( true );
-            breakPoint = action == CodeAction.STOP;
-            if( vIndex >= graph.getContainedNodes().size() )
-            {
-                inside = false;
-                setNode.setSelected( false );
-                loopNode.setSelected( false );
-                return StageStatus.FINISHED;
-            }
-            else
-                inside = true;
-            LayeredGraphNode current = graph.getContainedNodes().get( vIndex );
-            current.setSelected( null );
-            if( current.getContainedNodes().size() > 0 )
-            {
-                insideSubgraph = true;
-                boolean breakpoint = false;
-                boolean sel = subgraphNodes.get( vIndex ).isSelected();
-                CodeAction ac = subgraphNodes.get( vIndex ).setSelected( true );
-                if( !sel )
-                    breakpoint |= ac == CodeAction.STOP;
-                do {
-                    switch( subgraphAlgs.get( vIndex ).forwardStep() )
-                    {
-                    case BREAKPOINT:
-                        return StageStatus.BREAKPOINT;
-                    case UNFINISHED:
-                        break;
-                    case FINISHED:
-                        insideSubgraph = false;
-                        subgraphNodes.get( vIndex ).setSelected( false );
-                        ac = null;
-                        break;
-                    }
-                } while( ac == CodeAction.SKIP && !breakpoint );
-            }
-            ArrayList< Integer > positions = new ArrayList<>();
-            positions.add( (Integer)(int)current.getX( LayoutType.TOP_BOTTOM_LEFT ) + tblOffset );
-            positions.add( (Integer)(int)current.getX( LayoutType.TOP_BOTTOM_RIGHT ) + tbrOffset );
-            positions.add( (Integer)(int)current.getX( LayoutType.BOTTOM_TOP_LEFT ) + btlOffset );
-            positions.add( (Integer)(int)current.getX( LayoutType.BOTTOM_TOP_RIGHT ) + btrOffset );
-            Collections.sort( positions );
-            int oldX = (int)current.getX( LayoutType.COMBINED );
-            current.setX( (positions.get( 1 ) + positions.get( 2 )) / 2, true, LayoutType.COMBINED );
-            actions.add( 0, () -> {
-                inside = true;
-                breakPoint = false;
-                boolean selected = setNode.isSelected();
-                CodeAction ac = setNode.setSelected( true );
-                if( !selected )
-                    breakPoint |= ac == CodeAction.STOP;
-                skipBackwards = ac == CodeAction.SKIP;
-                ac = loopNode.setSelected( true );
-                breakPoint |= ac == CodeAction.STOP;
-                skipBackwards |= ac == CodeAction.SKIP;
-                vIndex--;
-                current.setX( oldX, true, LayoutType.COMBINED );
-                current.setSelected( null );
-            });
-            vIndex++;
-            if( action == CodeAction.SKIP && !breakPoint )
-                return forwardStep();
-        }
-        if( breakPoint )
-            return StageStatus.BREAKPOINT;
-        return StageStatus.UNFINISHED;
-    }
-
-    private int calcMinX(  LayoutType layout )
-    {
-        int minX = 0;
-        if( graph.getContainedNodes().size() > 0 )
-            minX = (int)graph.getContainedNodes().get( 0 ).getX( layout );
-        for( LayeredGraphNode n : graph.getContainedNodes() )
-            minX = Math.min( minX, (int)n.getX( layout ) );
-        return minX;
-    }
-
-    private int calcMaxX(  LayoutType layout )
-    {
-        int maxX = 0;
-        if( graph.getContainedNodes().size() > 0 )
-            maxX = (int)graph.getContainedNodes().get( 0 ).getX( layout );
-        for( LayeredGraphNode n : graph.getContainedNodes() )
-            maxX = Math.max( maxX, (int)n.getX( layout ) );
-        return maxX;
-    }
-
-    @Override
-    public StageStatus backwardStep() {
-        if( vIndex < subgraphAlgs.size() && subgraphAlgs.get( vIndex ) != null )
-        {
-            insideSubgraph = true;
-            boolean breakpoint = false;
-            boolean selected = subgraphNodes.get( vIndex ).isSelected();
-            CodeAction action = subgraphNodes.get( vIndex ).setSelected( true );
-            if( !selected )
-                breakpoint |= action == CodeAction.STOP;
-            do {
-                switch( subgraphAlgs.get( vIndex ).backwardStep() )
-                {
-                case BREAKPOINT:
-                    return StageStatus.BREAKPOINT;
-                case UNFINISHED:
-                    LayeredGraphNode current = graph.getContainedNodes().get( vIndex );
-                    current.setSelected( null );
-                    break;
-                case FINISHED:
-                    insideSubgraph = false;
-                    subgraphNodes.get( vIndex ).setSelected( false );
-                    action = null;
-                    break;
-                }
-            } while( !breakpoint && action == CodeAction.SKIP );
-        }
-        if( actions.size() == 0 )
-        {
-            inside = false;
-            alignNode.setSelected( false );
-            return StageStatus.FINISHED;
-        }
-        actions.get( 0 ).reverse();
-        actions.remove( 0 );
-        if( breakPoint )
-            return StageStatus.BREAKPOINT;
-        if( skipBackwards )
-            return backwardStep();
-        return StageStatus.UNFINISHED;
+        this.alg = alg;
     }
 
     @Override
     public PseudoCodeNode createPseudocodeTree( JTree tree ) {
-        PseudoCodeNode root = new PseudoCodeNode( TextLayoutHelper.setupPseudoCodeStage("Balancing"), tree );
-        alignNode = new PseudoCodeNode( TextLayoutHelper.setupPseudoCodeStage("Align Layouts"), tree );
-        setNode = new PseudoCodeNode( TextLayoutHelper.setupPseudoCodeStage("Align to assignment of smallest width"), tree );
-        loopNode = new PseudoCodeNode( "Set coordinates to average median of aligned candidates", tree );
-        for( int i = 0; i < graph.getContainedNodes().size(); i++ )
-        {
-            LayeredGraphNode current = graph.getContainedNodes().get( i );
-            if( current.getContainedNodes().size() > 0 )
-            {
-                Combine extcalc = new Combine( current );
-                PseudoCodeNode subNode = extcalc.createPseudocodeTree( loopNode.getTree() );
-                loopNode.add( subNode );
-                subgraphAlgs.set( i, extcalc );
-                subgraphNodes.set( i, subNode );
-            }
-        }
-        setNode.add( loopNode );
-        root.add( alignNode );
-        root.add( setNode );
+        PseudoCodeNode root = new PseudoCodeNode( TextLayoutHelper.setupPseudoCodeStage("Balancing"), tree, new CodeLine() {
+
+			@Override
+			public ControlFlow runForward(Memory m) {
+				// TODO Auto-generated method stub
+				return null;
+			}
+        	
+        }, alg );
         return root;
     }
-
-    @Override
-    public StageStatus forwardStepOver() {
-        if( !inside )
-        {
-            State oldState = state;
-            StageStatus stage = StageStatus.UNFINISHED;
-            while( state == oldState && stage == StageStatus.UNFINISHED )
-                stage = forwardStep();
-            return stage;
-        }
-        else
-        {
-            if( !insideSubgraph )
-                return forwardStep();
-            else
-            {
-                boolean breakpoint = false;
-                boolean selected = subgraphNodes.get( vIndex ).isSelected();
-                CodeAction action = subgraphNodes.get( vIndex ).setSelected( true );
-                if( !selected )
-                    breakpoint |= action == CodeAction.STOP;
-                do {
-                    switch( subgraphAlgs.get( vIndex ).forwardStepOver() )
-                    {
-                    case BREAKPOINT:
-                        return StageStatus.BREAKPOINT;
-                    case UNFINISHED:
-                        break;
-                    case FINISHED:
-                        insideSubgraph = false;
-                        subgraphNodes.get( vIndex ).setSelected( false );
-                        action = null;
-                        break;
-                    }
-                } while( !breakpoint && action == CodeAction.SKIP );
-                return StageStatus.UNFINISHED;
-            }
-        }
-    }
-
-    @Override
-    public StageStatus forwardStepOut() {
-        if( !inside )
-        {
-            StageStatus status = StageStatus.UNFINISHED;
-            while( status == StageStatus.UNFINISHED )
-                status = forwardStep();
-            return status;
-        }
-        else
-        {
-            if( !insideSubgraph )
-            {
-                State oldState = state;
-                StageStatus stage = StageStatus.UNFINISHED;
-                while( state == oldState && stage == StageStatus.UNFINISHED )
-                    stage = forwardStep();
-                return stage;
-            }
-            else
-            {
-                boolean breakpoint = false;
-                boolean selected = subgraphNodes.get( vIndex ).isSelected();
-                CodeAction action = subgraphNodes.get( vIndex ).setSelected( true );
-                if( !selected )
-                    breakpoint |= action == CodeAction.STOP;
-                do {
-                    switch( subgraphAlgs.get( vIndex ).forwardStepOut() )
-                    {
-                    case BREAKPOINT:
-                        return StageStatus.BREAKPOINT;
-                    case UNFINISHED:
-                        break;
-                    case FINISHED:
-                        insideSubgraph = false;
-                        subgraphNodes.get( vIndex ).setSelected( false );
-                        action = null;
-                        break;
-                    }
-                } while( !breakpoint && action == CodeAction.SKIP );
-                return StageStatus.UNFINISHED;
-            }
-        }
-    }
-
-    @Override
-    public StageStatus backwardStepOver() {
-        if( !inside )
-        {
-            State oldState = state;
-            StageStatus stage = StageStatus.UNFINISHED;
-            while( state == oldState && stage == StageStatus.UNFINISHED )
-                stage = backwardStep();
-            return stage;
-        }
-        else
-        {
-            if( !insideSubgraph )
-                return backwardStep();
-            else
-            {
-                boolean breakpoint = false;
-                boolean selected = subgraphNodes.get( vIndex ).isSelected();
-                CodeAction action = subgraphNodes.get( vIndex ).setSelected( true );
-                if( !selected )
-                    breakpoint |= action == CodeAction.STOP;
-                do {
-                    switch( subgraphAlgs.get( vIndex ).backwardStepOver() )
-                    {
-                    case BREAKPOINT:
-                        return StageStatus.BREAKPOINT;
-                    case UNFINISHED:
-                        break;
-                    case FINISHED:
-                        insideSubgraph = false;
-                        subgraphNodes.get( vIndex ).setSelected( false );
-                        action = null;
-                        break;
-                    }
-                } while( !breakpoint && action == CodeAction.SKIP );
-                return StageStatus.UNFINISHED;
-            }
-        }
-    }
-
-    @Override
-    public StageStatus backwardStepOut() {
-        if( !inside )
-        {
-            StageStatus status = StageStatus.UNFINISHED;
-            while( status == StageStatus.UNFINISHED )
-                status = backwardStep();
-            return status;
-        }
-        else
-        {
-            if( !insideSubgraph )
-            {
-                State oldState = state;
-                StageStatus stage = StageStatus.UNFINISHED;
-                while( state == oldState && stage == StageStatus.UNFINISHED )
-                    stage = backwardStep();
-                return stage;
-            }
-            else
-            {
-                boolean breakpoint = false;
-                boolean selected = subgraphNodes.get( vIndex ).isSelected();
-                CodeAction action = subgraphNodes.get( vIndex ).setSelected( true );
-                if( !selected )
-                    breakpoint |= action == CodeAction.STOP;
-                do {
-                    switch( subgraphAlgs.get( vIndex ).backwardStepOut() )
-                    {
-                    case BREAKPOINT:
-                        return StageStatus.BREAKPOINT;
-                    case UNFINISHED:
-                        break;
-                    case FINISHED:
-                        insideSubgraph = false;
-                        subgraphNodes.get( vIndex ).setSelected( false );
-                        action = null;
-                        break;
-                    }
-                } while( !breakpoint && action == CodeAction.SKIP );
-                return StageStatus.UNFINISHED;
-            }
-        }
-    }
     
     @Override
     public String getDebugString()
     {
         String info = "| Node |  x  | x LU | x RU | x LL | x RL |\n";
         info +=       "|------|-----|------|------|------|------|\n";
-        for( LayeredGraphNode n : graph.getContainedNodes() )
-        {
-            info += "|" + TextLayoutHelper.strToLen( n.getName(), 6 ) + 
-                    "|" + TextLayoutHelper.strToLen( n.getX( LayoutType.COMBINED ) + "", 5 ) + 
-                    "|" + TextLayoutHelper.strToLen( ( n.getX( LayoutType.TOP_BOTTOM_LEFT ) + tblOffset ) + "", 6 ) + 
-                    "|" + TextLayoutHelper.strToLen( ( n.getX( LayoutType.TOP_BOTTOM_RIGHT ) + tbrOffset ) + "", 6 ) + 
-                    "|" + TextLayoutHelper.strToLen( ( n.getX( LayoutType.BOTTOM_TOP_LEFT ) + btlOffset ) + "", 6 ) + 
-                    "|" + TextLayoutHelper.strToLen( ( n.getX( LayoutType.BOTTOM_TOP_RIGHT ) + btrOffset ) + "", 6 ) + "|\n";
-        }
-        if( insideSubgraph && vIndex < graph.getContainedNodes().size() )
-        {
-            info += "Subgraph of " + graph.getContainedNodes().get( vIndex ).getName() + ":\n";
-            String tmp = subgraphAlgs.get( vIndex ).getDebugString();
-            info += tmp;
-            return info;
-        }
         return info;
     }
 }

+ 15 - 515
src/bk/Compaction.java

@@ -6,10 +6,12 @@ import java.util.Collections;
 import javax.swing.JTree;
 
 import animation.AlgorithmStage;
-import animation.BackwardAction;
+import animation.AnimatedAlgorithm;
+import animation.CodeLine;
+import animation.ControlFlow;
+import animation.Memory;
 import animation.PseudoCodeNode;
 import animation.PseudoCodeNode.CodeAction;
-import bk.ExtremalLayoutCalc.LayoutType;
 import graph.LayeredGraphNode;
 import lib.TextLayoutHelper;
 
@@ -20,530 +22,28 @@ import lib.TextLayoutHelper;
  */
 public class Compaction implements AlgorithmStage{
 
-    private enum CompactionState
-    {
-        PLACE_BLOCKS,
-        APPLY_SHIFT
-    }
-
-    private class StackFrame
-    {
-        public LayeredGraphNode v;
-        public LayeredGraphNode u;
-        public LayeredGraphNode w;
-    }
-
-    private CompactionState state;
     private LayeredGraphNode graph;
-    private int vIndex;
+    private AnimatedAlgorithm alg;
 
-    private ArrayList< StackFrame > stack; // TODO: evtl richtigen "Stack" benutzen
-    private ArrayList< BackwardAction > actions; // TODO: evtl richtigen "Stack" benutzen
-    private LayoutType layout;
-    private PseudoCodeNode placeNode;
-    private PseudoCodeNode placeLoopNode;
-    private PseudoCodeNode applyNode;
-    private PseudoCodeNode applyLoopNode;
-    private boolean breakPoint;
-    private boolean inside;
-    private boolean skip;
 
-
-    public Compaction( LayeredGraphNode graph, LayoutType layout )
+    public Compaction( LayeredGraphNode graph, AnimatedAlgorithm alg )
     {
-        this.layout = layout;
         this.graph = graph;
-        state = CompactionState.PLACE_BLOCKS;
-        stack = new ArrayList<>(); // der call-stack des rekursiven algorithmus
-        vIndex = 0;
-        actions = new ArrayList<>();
-        inside = false;
-        skip = false;
-    }
-
-    /**
-     * calculates the minimum spacing needed between two left borders of nodes.
-     * @return the spacing
-     */
-    public double calcSpacing()
-    {
-        double max = 0;
-        for( LayeredGraphNode n : graph.getContainedNodes() )
-            max = Math.max( max, n.getWidth( layout ) );
-        //return max + 25;
-        return max + 5;
-    }
-
-    private LayeredGraphNode getNodeFromIndex( int index )
-    {
-        @SuppressWarnings("unchecked")
-        ArrayList<ArrayList<LayeredGraphNode>> layer = (ArrayList<ArrayList<LayeredGraphNode>>) graph.getContainedLayers().clone();
-        if( layout == LayoutType.BOTTOM_TOP_LEFT || layout == LayoutType.BOTTOM_TOP_RIGHT )
-            Collections.reverse( layer );
-        for( ArrayList< LayeredGraphNode > l : layer )
-        {
-            if( index >= l.size() )
-                index -= l.size();
-            else
-            {
-                if( layout == LayoutType.BOTTOM_TOP_LEFT || layout == LayoutType.TOP_BOTTOM_LEFT )
-                    return l.get( index );
-                else
-                    return l.get( l.size() - index - 1 );
-            }
-        }
-        return null;
-    }
-
-    @Override
-    public StageStatus forwardStep() {
-        breakPoint = false;
-        skip = false;
-        int acSize = actions.size();
-        if( state == CompactionState.PLACE_BLOCKS ) // blöcke platzieren
-        {
-            inside = true;
-            boolean sel = placeNode.isSelected();
-            CodeAction action = placeNode.setSelected( true );
-            if( !sel )
-                breakPoint = action == CodeAction.STOP;
-            skip |= action == CodeAction.SKIP;
-            action = placeLoopNode.setSelected( true );
-            breakPoint |= action == CodeAction.STOP;
-            skip |= action == CodeAction.SKIP;
-            if( stack.size() == 0 ) // äußere schleife, placeblocks bisher nicht aufgerufen
-            {
-                ArrayList< LayeredGraphNode > nodes = graph.getContainedNodes();
-                boolean found = false; // knoten mit v = root[v] gefunden?
-                int oldVIndex = vIndex; // nötig für "undo"
-
-                // suche knoten mit v = root[v] und undefiniertem x-Wert
-                for( ; vIndex < nodes.size(); vIndex++ )
-                {
-                    if( getNodeFromIndex( vIndex ).isXUndefined( layout ) && getNodeFromIndex( vIndex ) == getNodeFromIndex( vIndex ).getRoot( layout ) )
-                    {
-                        found = true;
-                        break;
-                    }
-                }
-
-                // kein knoten gefunden
-                if( !found )
-                {
-                    // wechsele in die phase des Blöckeshiftens
-                    placeNode.setSelected( false );
-                    placeLoopNode.setSelected( false );
-                    sel = applyNode.isSelected();
-                    action = applyNode.setSelected( true );
-                    if( !sel )
-                        breakPoint |= action == CodeAction.STOP;
-                    skip |= action == CodeAction.SKIP;
-                    action = applyLoopNode.setSelected( true );
-                    breakPoint |= action == CodeAction.STOP;
-                    skip |= action == CodeAction.SKIP;
-                    state = CompactionState.APPLY_SHIFT;
-                    inside = false;
-                    vIndex = 0;
-                    actions.add( 0, ()-> {
-                        applyNode.setSelected( false );
-                        applyLoopNode.setSelected( false );
-                        breakPoint = false;
-                        skip = false;
-                        boolean selected = placeNode.isSelected();
-                        CodeAction ac = placeNode.setSelected( true );
-                        if( !selected )
-                            breakPoint |= ac == CodeAction.STOP;
-                        skip |= ac == CodeAction.SKIP;
-                        ac = placeLoopNode.setSelected( true );
-                        breakPoint |= ac == CodeAction.STOP;
-                        skip |= ac == CodeAction.SKIP;
-                        vIndex = oldVIndex;
-                        inside = false;
-                        state = CompactionState.PLACE_BLOCKS;
-                    } );
-                }
-                else // Knoten gefunden
-                {
-                    StackFrame f = new StackFrame(); // enthält lokale variablen
-                    f.v = getNodeFromIndex( vIndex );
-                    double oldX = f.v.getX( layout ); // nötig für "undo"
-                    f.v.setX( 0, true, layout );
-                    f.w = f.v;
-                    f.w.setSelected( layout ); // zeige knoten als aktiven knoten an
-                    System.out.println( "call place_block( " + f.v + " )" );
-                    stack.add( 0, f );
-
-                    // die "undo"-action
-                    actions.add( 0, ()-> {
-                        breakPoint = false;
-                        skip = false;
-                        boolean selected = placeNode.isSelected();
-                        CodeAction ac = placeNode.setSelected( true );
-                        if( !selected )
-                            breakPoint |= ac == CodeAction.STOP;
-                        skip |= ac == CodeAction.SKIP;
-                        ac = placeLoopNode.setSelected( true );
-                        breakPoint |= ac == CodeAction.STOP;
-                        skip |= ac == CodeAction.SKIP;
-                        inside = true;
-                        stack.get( 0 ).v.setX( oldX, false, layout );
-                        stack.get( 0 ).v.setSelected( layout );
-                        stack.remove( 0 );
-                        vIndex = oldVIndex;
-                        state = CompactionState.PLACE_BLOCKS;
-                    });
-                }
-            }
-            else // zurzeit innerhalb einer placeblock methode
-            {
-                StackFrame sf = stack.get( 0 );
-                if( sf.u == null ) // zu beginn der placeblock methode
-                {
-                    int posW = graph.getContainedLayers().get( sf.w.getLayer() ).indexOf( sf.w );
-                    if( (posW >= 1 && (layout == LayoutType.BOTTOM_TOP_LEFT || layout == LayoutType.TOP_BOTTOM_LEFT)) || (posW < graph.getContainedLayers().get( sf.w.getLayer() ).size() - 1 && (layout == LayoutType.BOTTOM_TOP_RIGHT || layout == LayoutType.TOP_BOTTOM_RIGHT)) ) // if pos[w] > 1"
-                    {
-                        int offset = -1;
-                        if( layout == LayoutType.BOTTOM_TOP_RIGHT || layout == LayoutType.TOP_BOTTOM_RIGHT )
-                            offset = 1;
-                        sf.u = graph.getContainedLayers().get( sf.w.getLayer() ).get( posW + offset ).getRoot( layout );
-
-                        if( sf.u.isXUndefined( layout ) ) // nötig placeblock aufzurufen?
-                        {// ja
-                            StackFrame nsf = new StackFrame(); // enthält lokale variablen
-                            nsf.v = sf.u;
-                            double oldX = nsf.v.getX( layout ); // nötig für "undo"
-                            nsf.v.setX( 0, true, layout );
-                            nsf.w = nsf.v;
-                            nsf.w.setSelected( layout ); // zeige knoten als aktiven knoten an
-                            System.out.println( "call place_block( " + nsf.v + " )" );
-                            stack.add( 0, nsf );
-
-                            // die "undo"-action
-                            actions.add( 0, ()-> {
-                                breakPoint = false;
-                                skip = false;
-                                boolean selected = placeNode.isSelected();
-                                CodeAction ac = placeNode.setSelected( true );
-                                if( !selected )
-                                    breakPoint |= ac == CodeAction.STOP;
-                                skip |= ac == CodeAction.SKIP;
-                                ac = placeLoopNode.setSelected( true );
-                                breakPoint |= ac == CodeAction.STOP;
-                                skip |= ac == CodeAction.SKIP;
-                                inside = true;
-                                stack.get( 0 ).v.setX( oldX, false, layout );
-                                stack.get( 0 ).v.setSelected( layout );
-                                stack.remove( 0 );
-                                stack.get( 0 ).u = null;
-                            });
-                        }
-                        else // nein
-                        {
-                            // tue nix
-                            sf.w.setSelected( layout );
-                            actions.add( 0, ()-> {
-                                breakPoint = false;
-                                skip = false;
-                                boolean selected = placeNode.isSelected();
-                                CodeAction ac = placeNode.setSelected( true );
-                                if( !selected )
-                                    breakPoint |= ac == CodeAction.STOP;
-                                skip |= ac == CodeAction.SKIP;
-                                ac = placeLoopNode.setSelected( true );
-                                breakPoint |= ac == CodeAction.STOP;
-                                skip |= ac == CodeAction.SKIP;
-                                inside = true;
-                                stack.get( 0 ).u = null;
-                            });
-                        }
-                    }
-                    else
-                    { // w = align[w]
-                        LayeredGraphNode oldW = sf.w;
-                        sf.w = sf.w.getAlign( layout );
-                        sf.w.setSelected( layout );
-                        if( sf.w == sf.v ) // schleifenabbruchbedingung
-                        { //abbrechen, placeblock beendet
-                            System.out.println( "return place_block( " + sf.v + " )" );
-                            stack.remove( 0 );
-                            actions.add( 0, ()-> {
-                                breakPoint = false;
-                                skip = false;
-                                boolean selected = placeNode.isSelected();
-                                CodeAction ac = placeNode.setSelected( true );
-                                if( !selected )
-                                    breakPoint |= ac == CodeAction.STOP;
-                                skip |= ac == CodeAction.SKIP;
-                                ac = placeLoopNode.setSelected( true );
-                                breakPoint |= ac == CodeAction.STOP;
-                                skip |= ac == CodeAction.SKIP;
-                                inside = true;
-                                stack.add( 0, sf );
-                                sf.w = oldW;
-                                sf.w.setSelected( layout );
-                            });
-                        }
-                        else
-                        { //nur "undo aktion" hinzufügen
-                            actions.add( 0, ()-> {
-                                breakPoint = false;
-                                skip = false;
-                                boolean selected = placeNode.isSelected();
-                                CodeAction ac = placeNode.setSelected( true );
-                                if( !selected )
-                                    breakPoint |= ac == CodeAction.STOP;
-                                skip |= ac == CodeAction.SKIP;
-                                ac = placeLoopNode.setSelected( true );
-                                breakPoint |= ac == CodeAction.STOP;
-                                skip |= ac == CodeAction.SKIP;
-                                inside = true;
-                                sf.w = oldW;
-                                sf.w.setSelected( layout );
-                            });
-                        }
-                    }
-                }
-                else // ein "placeBlock(u)" aufruf hat gerade returned
-                {
-                    // alte Werte merken für undo
-                    LayeredGraphNode oldSink = sf.v.getSink( layout );
-                    LayeredGraphNode sinkOfU = sf.u.getSink( layout );
-                    double oldShift = sinkOfU.getShift( layout );
-                    double oldX = sf.v.getX( layout );
-                    boolean oldDef = !sf.v.isXUndefined( layout );
-
-                    // v für visualisierung markieren
-                    sf.w.setSelected( layout );
-                    
-                    if( sf.v.getSink( layout ) == sf.v ) // sink[v] = v?
-                        sf.v.setSink( sf.u.getSink( layout ), layout ); // sink[v] := sink[u]
-                    int multiplyer = 1;
-                    if( layout == LayoutType.BOTTOM_TOP_RIGHT || layout == LayoutType.TOP_BOTTOM_RIGHT )
-                        multiplyer = -1;
-                    
-                    if( sf.v.getSink( layout ) != sf.u.getSink( layout ) ) // sink[v] != sink [u]?
-                        sf.u.getSink( layout ).setShift( // shift[sink[u]] =
-                          Math.min( sf.u.getSink( layout ).getShift( layout ),  // min(shift[sink[u]]
-                                  multiplyer * (Math.abs(sf.v.getX( layout )) - Math.abs(sf.u.getX( layout )) - calcSpacing()) ), layout ); // y_v - y_u - s
-                    else
-                        // y_v = max {y_v, y_u + s}
-                        sf.v.setX( multiplyer * Math.max( Math.abs( sf.v.getX( layout ) ), Math.abs( sf.u.getX( layout ) ) + calcSpacing() ), true, layout );
-
-
-                    // alte Werte merken für undo
-                    LayeredGraphNode oldW = sf.w;
-                    LayeredGraphNode oldU = sf.u;
-                    
-                    sf.w = sf.w.getAlign( layout ); // w = align[w]
-                    sf.u = null; // u wird nächsten schleifendurchlauf neu gesetzt
-
-                    if( sf.w == sf.v ) // schleifenabbruchbedingung
-                    { //abbrechen, placeblock beendet
-                        System.out.println( "return place_block( " + sf.v + " )" );
-                        stack.remove( 0 );
-                        actions.add( 0, ()-> {
-                            breakPoint = false;
-                            skip = false;
-                            boolean selected = placeNode.isSelected();
-                            CodeAction ac = placeNode.setSelected( true );
-                            if( !selected )
-                                breakPoint |= ac == CodeAction.STOP;
-                            skip |= ac == CodeAction.SKIP;
-                            ac = placeLoopNode.setSelected( true );
-                            breakPoint |= ac == CodeAction.STOP;
-                            skip |= ac == CodeAction.SKIP;
-                            inside = true;
-                            stack.add( 0, sf );
-                            stack.get( 0 ).v.setSink(  oldSink, layout );
-                            sinkOfU.setShift( oldShift, layout );
-                            sf.u = oldU;
-                            sf.v.setX( oldX, oldDef, layout );
-                            sf.w = oldW;
-                            sf.w.setSelected( layout );
-                        });
-                    }
-                    else
-                    { //nur "undo aktion" hinzufügen
-                        actions.add( 0, ()-> {
-                            breakPoint = false;
-                            skip = false;
-                            boolean selected = placeNode.isSelected();
-                            CodeAction ac = placeNode.setSelected( true );
-                            if( !selected )
-                                breakPoint |= ac == CodeAction.STOP;
-                            skip |= ac == CodeAction.SKIP;
-                            ac = placeLoopNode.setSelected( true );
-                            breakPoint |= ac == CodeAction.STOP;
-                            skip |= ac == CodeAction.SKIP;
-                            inside = true;
-                            stack.get( 0 ).v.setSink(  oldSink, layout );
-                            sinkOfU.setShift( oldShift, layout );
-                            sf.u = oldU;
-                            sf.v.setX( oldX, oldDef, layout );
-                            sf.w = oldW;
-                            sf.w.setSelected( layout );
-                        });
-                    }
-                }
-            }
-        }
-        else if( state == CompactionState.APPLY_SHIFT )// "Compute absolute coordinates"
-        {
-            inside = true;
-            skip = false;
-            boolean sel = placeNode.isSelected();
-            CodeAction action = applyNode.setSelected( true );
-            if( !sel )
-                breakPoint |= action == CodeAction.STOP;
-            skip |= action == CodeAction.SKIP;
-            action = applyLoopNode.setSelected( true );
-            breakPoint |= action == CodeAction.STOP;
-            skip |= action == CodeAction.SKIP;
-            if( vIndex >= graph.getContainedNodes().size() )
-            {
-                inside = false;
-                applyNode.setSelected( false );
-                applyLoopNode.setSelected( false );
-                return StageStatus.FINISHED;
-            }
-            LayeredGraphNode v = getNodeFromIndex( vIndex );
-            double oldX = v.getX( layout );
-            boolean oldDef = !v.isXUndefined( layout );
-
-            v.setSelected( layout );
-            v.setX( v.getRoot( layout ).getX( layout ), true, layout ); // y_v = y_root[v]
-            if( v == v.getRoot( layout ) && v.getSink( layout ).getShift( layout ) < Double.POSITIVE_INFINITY )
-                v.setX( v.getX( layout ) + v.getSink( layout ).getShift( layout ), true, layout );
-            actions.add( 0, ()-> {
-                inside = true;
-                breakPoint = false;
-                skip = false;
-                boolean selected = placeNode.isSelected();
-                CodeAction ac = applyNode.setSelected( true );
-                if( !selected )
-                    breakPoint |= ac == CodeAction.STOP;
-                skip |= ac == CodeAction.SKIP;
-                ac = applyLoopNode.setSelected( true );
-                breakPoint |= ac == CodeAction.STOP;
-                skip |= ac == CodeAction.SKIP;
-                v.setX( oldX, oldDef, layout );
-                v.setSelected( layout );
-                vIndex--;
-            } );
-            vIndex++;
-            if( vIndex >= graph.getContainedNodes().size() )
-            {
-                applyNode.setSelected( false );
-                applyLoopNode.setSelected( false );
-                return StageStatus.FINISHED;
-            }
-        }
-        if( actions.size() != acSize + 1 )
-            System.out.println( "ERROR" );
-        if( breakPoint )
-            return StageStatus.BREAKPOINT;
-        if( skip )
-            return forwardStep();
-        return StageStatus.UNFINISHED;
-    }
-
-    @Override
-    public StageStatus backwardStep() {
-        if( actions.size() == 0 )
-        {
-            inside = false;
-            placeNode.setSelected( false );
-            placeLoopNode.setSelected( false );
-            return StageStatus.FINISHED;
-        }
-        actions.get( 0 ).reverse();
-        actions.remove( 0 );
-        if( breakPoint )
-            return StageStatus.BREAKPOINT;
-        if( skip )
-            return backwardStep();
-        return StageStatus.UNFINISHED;
+        this.alg = alg;
     }
 
     @Override
     public PseudoCodeNode createPseudocodeTree( JTree tree ) {
-        PseudoCodeNode root = new PseudoCodeNode( TextLayoutHelper.setupPseudoCodeStage("Horizontal compaction"), tree );
-        placeNode = new PseudoCodeNode( TextLayoutHelper.setupPseudoCodeStage("Root coordinates relative to sink"), tree );
-        placeLoopNode = new PseudoCodeNode( "Loop through root nodes...", tree );
-        placeNode.add( placeLoopNode );
-        applyNode = new PseudoCodeNode( TextLayoutHelper.setupPseudoCodeStage("Absolute coordinates"), tree );
-        applyLoopNode = new PseudoCodeNode( "Loop through all nodes...", tree );
-        applyNode.add( applyLoopNode );
-        root.add( placeNode );
-        root.add( applyNode );
+        PseudoCodeNode root = new PseudoCodeNode( TextLayoutHelper.setupPseudoCodeStage("Horizontal compaction"), tree, new CodeLine() {
+
+			@Override
+			public ControlFlow runForward(Memory m) {
+				return null;
+			}
+        	
+        }, alg );
         return root;
     }
-
-    @Override
-    public StageStatus forwardStepOver() {
-        if( !inside )
-        {
-            CompactionState oldState = state;
-            StageStatus stage = StageStatus.UNFINISHED;
-            while( state == oldState && stage == StageStatus.UNFINISHED )
-                stage = forwardStep();
-            return stage;
-        }
-        else
-            return forwardStep();
-    }
-
-    @Override
-    public StageStatus forwardStepOut() {
-        if( !inside )
-        {
-            StageStatus status = StageStatus.UNFINISHED;
-            while( status == StageStatus.UNFINISHED )
-                status = forwardStep();
-            return status;
-        }
-        else
-        {
-            CompactionState oldState = state;
-            StageStatus stage = StageStatus.UNFINISHED;
-            while( state == oldState && stage == StageStatus.UNFINISHED )
-                stage = forwardStep();
-            return stage;
-        }
-    }
-
-    @Override
-    public StageStatus backwardStepOver() {
-        if( !inside )
-        {
-            CompactionState oldState = state;
-            StageStatus stage = StageStatus.UNFINISHED;
-            while( state == oldState && stage == StageStatus.UNFINISHED )
-                stage = backwardStep();
-            return stage;
-        }
-        else
-            return backwardStep();
-    }
-
-    @Override
-    public StageStatus backwardStepOut() {
-        if( !inside )
-        {
-            StageStatus status = StageStatus.UNFINISHED;
-            while( status == StageStatus.UNFINISHED )
-                status = backwardStep();
-            return status;
-        }
-        else
-        {
-            CompactionState oldState = state;
-            StageStatus stage = StageStatus.UNFINISHED;
-            while( state == oldState && stage == StageStatus.UNFINISHED )
-                stage = backwardStep();
-            return stage;
-        }
-    }
     
     @Override
     public String getDebugString()

+ 46 - 600
src/bk/ConflictDetection.java

@@ -6,7 +6,10 @@ import java.util.Stack;
 import javax.swing.JTree;
 
 import animation.AlgorithmStage;
-import animation.BackwardAction;
+import animation.AnimatedAlgorithm;
+import animation.CodeLine;
+import animation.ControlFlow;
+import animation.Memory;
 import animation.PseudoCodeNode;
 import animation.PseudoCodeNode.CodeAction;
 import graph.LayeredGraphEdge;
@@ -22,396 +25,52 @@ import lib.TextLayoutHelper;
 public class ConflictDetection implements AlgorithmStage {
 
     private LayeredGraphNode graph;
-    private Stack<BackwardAction> actions;
+    private AnimatedAlgorithm alg;
 
-    private int i;
-    private int l1;
-    private int k0;
-    private int k1;
-    private int l;
-    private int k;
-    private int hidden_k;
-    /**
-     * line number in Carstens' pseudocode listing 3.1
-     */
-    private int pseudo_line;
-    private PseudoCodeNode lines[];
-    private boolean breakPoint;
-    private boolean skip;
-    private ArrayList< PseudoCodeNode > subgraphNodes;
-    private ArrayList< ConflictDetection > subgraphAlgs;
-    private int vIndex;
-    private boolean insideSubgraph;
-
-    public ConflictDetection(LayeredGraphNode graph) {
+    public ConflictDetection(LayeredGraphNode graph, AnimatedAlgorithm alg) {
         this.graph = graph;
-        actions = new Stack<>();
-        i = 0; // will be increased before first iteration
-        l1 = -1; // will be increased before first iteration
-        k0 = 0;
-        k1 = 0;
-        l = 0;
-        k = 0;
-        hidden_k = 0;
-        pseudo_line = 1;
-        breakPoint = false;
-        skip = false;
-        subgraphAlgs = new ArrayList<>();
-        subgraphNodes = new ArrayList<>();
-        vIndex = 0;
-        insideSubgraph = false;
-        for( @SuppressWarnings("unused") LayeredGraphNode n : graph.getContainedNodes() )
-        {
-            subgraphAlgs.add( null );
-            subgraphNodes.add( null );
-        }
-    }
-
-
-    @Override
-    public StageStatus forwardStep() {
-        int old_line = pseudo_line;
-        int old_k = k;
-        int old_k0 = k0;
-        int old_k1 = k1;
-        int old_l = l;
-        int old_l1 = l1;
-        int old_hidden_k = hidden_k;
-
-        switch (pseudo_line) {
-        case 1:
-            i++;
-            actions.push(() -> {
-                i--;
-                pseudo_line = old_line;
-                selectNodes(pseudo_line);
-            });
-            if (i <= graph.getContainedLayers().size() - 2) {
-                pseudo_line++;
-            } else {
-                pseudo_line = 16;
-            }
-            break;
-        case 2:
-            k0 = 0;
-            l = 0;
-            l1 = -1; // will be increased before first iteration
-            pseudo_line++;
-            actions.push(() -> {
-                pseudo_line = old_line;
-                k0 = old_k0;
-                l = old_l;
-                l1 = old_l1;
-                selectNodes(pseudo_line);
-            });
-            break;
-        case 3:
-            l1++;
-            actions.push(() -> {
-                l1--;
-                pseudo_line = old_line;
-                selectNodes(pseudo_line);
-            });
-            if (l1 < graph.getContainedLayers().get(i + 1).size()) {
-                pseudo_line += 1;
-            } else {
-                pseudo_line = 1;
-            }
-            break;
-        case 4:
-            actions.push(() -> {
-                pseudo_line = old_line;
-                selectNodes(pseudo_line);
-            });
-            if (graph.getContainedLayers().get(i + 1).size() == l1 || incidentToInnerSegmentBetweenLiPlusOneAndLi()) {
-                pseudo_line++;
-            } else {
-                pseudo_line = 3;
-            }
-            break;
-        case 5:
-            actions.push(() -> {
-                k1 = old_k1;
-                pseudo_line = old_line;
-                selectNodes(pseudo_line);
-            });
-            k1 = graph.getContainedLayers().get(i).size() - 1;
-            pseudo_line++;
-            break;
-        case 6:
-            actions.push(() -> {
-                pseudo_line = old_line;
-                selectNodes(pseudo_line);
-            });
-            if (incidentToInnerSegmentBetweenLiPlusOneAndLi()) {
-                pseudo_line++;
-            } else {
-                pseudo_line = 9;
-            }
-            break;
-        case 7:
-            actions.push(() -> {
-                k1 = old_k1;
-                pseudo_line = old_line;
-                selectNodes(pseudo_line);
-            });
-            k1 = graph.getContainedLayers().get(i).indexOf(
-                    graph.getContainedLayers().get(i + 1).get(l1).getSortedIncomingEdges().get(0).getSources().get(0));
-            pseudo_line = 9;
-            break;
-        case 9:
-            actions.push(() -> {
-                hidden_k = old_hidden_k;
-                pseudo_line = old_line;
-                selectNodes(pseudo_line);
-            });
-            if (l <= l1) {
-                pseudo_line++;
-                hidden_k = 0; // will not be increased before first iteration
-                k = graph.getContainedLayers().get(i).indexOf(graph.getContainedLayers().get(i + 1).get(l)
-                        .getSortedIncomingEdges().get(hidden_k).getSources().get(0));
-            } else {
-                pseudo_line = 15;
-            }
-            break;
-        case 10:
-            actions.push(() -> {
-                k = old_k;
-                pseudo_line = old_line;
-                selectNodes(pseudo_line);
-            });
-            if (hidden_k < graph.getContainedLayers().get(i + 1).get(l).getSortedIncomingEdges().size()) {
-                k = graph.getContainedLayers().get(i).indexOf(graph.getContainedLayers().get(i + 1).get(l)
-                        .getSortedIncomingEdges().get(hidden_k).getSources().get(0));
-                pseudo_line++;
-            } else {
-                pseudo_line = 13;
-            }
-            break;
-        case 11:
-            actions.push(() -> {
-                hidden_k--;
-                graph.getContainedLayers().get(i + 1).get(l).getSortedIncomingEdges().get(hidden_k).setConflicted(false,
-                        null);
-                pseudo_line = old_line;
-                selectNodes(pseudo_line);
-            });
-            if (k < k0 || k > k1) {
-                graph.getContainedLayers().get(i + 1).get(l).getSortedIncomingEdges().get(hidden_k).setConflicted(true,
-                        null);
-            }
-            hidden_k++;
-            pseudo_line = 10;
-            break;
-        case 13:
-            actions.push(() -> {
-                l--;
-                pseudo_line = old_line;
-                selectNodes(pseudo_line);
-            });
-            l++;
-            pseudo_line = 9;
-            break;
-        case 15:
-            actions.push(() -> {
-                k0 = old_k0;
-                pseudo_line = old_line;
-                selectNodes(pseudo_line);
-            });
-            k0 = k1;
-            pseudo_line = 3;
-            break;
-        case 16:
-            if( vIndex < graph.getContainedNodes().size() )
-            {
-                while( vIndex < graph.getContainedNodes().size() && graph.getContainedNodes().get( vIndex ).getContainedNodes().size() == 0 )
-                    vIndex++;
-                if( vIndex < graph.getContainedNodes().size() )
-                {
-                    LayeredGraphNode current = graph.getContainedNodes().get( vIndex );
-                    current.setSelected( null );
-                    if( current.getContainedNodes().size() > 0 )
-                    {
-                        insideSubgraph = true;
-                        breakPoint = false;
-                        boolean sel = subgraphNodes.get( vIndex ).isSelected();
-                        CodeAction ac = subgraphNodes.get( vIndex ).setSelected( true );
-                        if( !sel )
-                            breakPoint |= ac == CodeAction.STOP;
-                        do {
-                            switch( subgraphAlgs.get( vIndex ).forwardStep() )
-                            {
-                            case BREAKPOINT:
-                                return StageStatus.BREAKPOINT;
-                            case UNFINISHED:
-                                break;
-                            case FINISHED:
-                                insideSubgraph = false;
-                                subgraphNodes.get( vIndex ).setSelected( false );
-                                vIndex++;
-                                ac = null;
-                                break;
-                            }
-                        } while( ac == CodeAction.SKIP && !breakPoint );
-                    }
-                }
-            }
-            if( vIndex >= graph.getContainedNodes().size() )
-            {
-                for( PseudoCodeNode p : lines )
-                {
-                    if( p != null )
-                        p.setSelected( false );
-                }
-                return StageStatus.FINISHED;
-            }
-        }
-
-        selectNodes(pseudo_line);
-        if( breakPoint )
-            return StageStatus.BREAKPOINT;
-        if( skip )
-            return forwardStep();
-        return StageStatus.UNFINISHED;
-    }
-
-    private void selectNodes(int next_line) {
-        if( pseudo_line < 16 )
-        {
-            if (next_line >= 3 && l < graph.getContainedLayers().get(i + 1).size()) {
-                graph.getContainedLayers().get(i + 1).get(l).setSelected(null);
-            }
-    
-            if (next_line >= 4) {
-                graph.getContainedLayers().get(i + 1).get(l1).setSelected(null);
-            }
-    
-            if (next_line >= 3) {
-                graph.getContainedLayers().get(i).get(k0).setSelected(null);
-            }
-    
-            if (next_line >= 6) {
-                graph.getContainedLayers().get(i).get(k1).setSelected(null);
-            }
-    
-            if (next_line == 10 || next_line == 11) {
-                graph.getContainedLayers().get(i).get(k).setSelected(null);
-            }
-        }
-        breakPoint = false;
-        skip = false;
-        for( PseudoCodeNode p : lines )
-        {
-            if( p != null )
-                p.setSelected( false );
-        }
-        markCode( lines[ next_line - 1 ] );
-    }
-    
-    private int getCodeDepth( PseudoCodeNode n )
-    {
-        if( n == lines[ 0 ].getParent() )
-            return 0;
-        return 1 + getCodeDepth( (PseudoCodeNode)n.getParent() );
-    }
-    
-    private void markCode( PseudoCodeNode n )
-    {
-        if( n == lines[ 0 ].getRoot() )
-            return;
-        if( !n.hasSelectedSubnode() )
-        {
-            CodeAction action = n.setSelected( true );
-            breakPoint |= action == CodeAction.STOP;
-            skip |= action == CodeAction.SKIP;
-        }
-        else
-        {
-            CodeAction action = n.setSelected( true );
-            skip |= action == CodeAction.SKIP;
-        }
-        if( n == lines[ 0 ] )
-            return;
-        markCode( (PseudoCodeNode)n.getParent() );
-    }
-
-    @Override
-    public StageStatus backwardStep() {
-        if( pseudo_line == 16 )
-        {
-            while( vIndex >= graph.getContainedNodes().size() || ( vIndex >= 0 && graph.getContainedNodes().get( vIndex ).getContainedNodes().size() == 0 )  )
-                vIndex--;
-            if( vIndex >= 0 )
-            {
-                LayeredGraphNode current = graph.getContainedNodes().get( vIndex );
-                current.setSelected( null );
-                if( subgraphAlgs.get( vIndex ) != null )
-                {
-                    insideSubgraph = true;
-                    breakPoint = false;
-                    boolean selected = subgraphNodes.get( vIndex ).isSelected();
-                    CodeAction action = subgraphNodes.get( vIndex ).setSelected( true );
-                    if( !selected )
-                        breakPoint |= action == CodeAction.STOP;
-                    do {
-                        switch( subgraphAlgs.get( vIndex ).backwardStep() )
-                        {
-                        case BREAKPOINT:
-                            return StageStatus.BREAKPOINT;
-                        case UNFINISHED:
-                            break;
-                        case FINISHED:
-                            insideSubgraph = false;
-                            subgraphNodes.get( vIndex ).setSelected( false );
-                            vIndex--;
-                            action = null;
-                            break;
-                        }
-                    } while( !breakPoint && action == CodeAction.SKIP );
-                }
-            }
-            if( vIndex < 0 )
-            {
-                vIndex = 0;
-                if (actions.size() == 0) {
-                    for( PseudoCodeNode p : lines )
-                    {
-                        if( p != null )
-                            p.setSelected( false );
-                    }
-                    return StageStatus.FINISHED;
-                }
-                actions.pop().reverse();
-            }
-        }
-        else
-        {
-            if (actions.size() == 0) {
-                for( PseudoCodeNode p : lines )
-                {
-                    if( p != null )
-                        p.setSelected( false );
-                }
-                return StageStatus.FINISHED;
-            }
-            actions.pop().reverse();
-        }
-        if( breakPoint )
-            return StageStatus.BREAKPOINT;
-        if( skip )
-            return forwardStep();
-        return StageStatus.UNFINISHED;
+        this.alg = alg;
     }
 
     @Override
     public PseudoCodeNode createPseudocodeTree(JTree tree) {
-        PseudoCodeNode root = new PseudoCodeNode(TextLayoutHelper.setupPseudoCodeStage("Preprocessing (mark type 1 conflicts)"), tree);
-        lines = new PseudoCodeNode[16];
-        String vars[] = { "i", "L", "k0", "l", "l1", "k1", "k", "v" };
-        lines[ 0 ] = new PseudoCodeNode( TextLayoutHelper.setupPseudoCode( "for i=1 to |L|-2 do", vars ), tree );
+        String vars[] = { "i", "L", "k0", "l", "l1", "k1", "k", "v", "graph" };
+        PseudoCodeNode root = new PseudoCodeNode(TextLayoutHelper.setupPseudoCode("mark_conflicts( graph )", vars), tree, new CodeLine() {
+
+			@Override
+			public ControlFlow runForward(Memory m) {
+				if( !m.isDefined( "param1", true ) )
+					return new ControlFlow( ControlFlow.STEP_OVER );
+				//m.addFrame();
+				LayeredGraphNode param = m.<LayeredGraphNode>read( "param1", true );
+				m.undeclare( "param1", true );
+				m.declare( "graph", param, false );
+				m.declare( "Layers", param.getContainedLayers(), false );
+				return new ControlFlow( ControlFlow.STEP_INTO );
+			}
+        }, alg );
+        PseudoCodeNode[] lines = new PseudoCodeNode[16];
+        lines[ 0 ] = new PseudoCodeNode( TextLayoutHelper.setupPseudoCode( "for i=1 to |L|-2 do", vars ), tree, new CodeLine() {
+
+			@Override
+			public ControlFlow runForward(Memory m) {
+				// TODO Auto-generated method stub
+				return null;
+			}
+        	
+        }, alg );
         root.add( lines[ 0 ] );
-        lines[ 1 ] = new PseudoCodeNode( TextLayoutHelper.setupPseudoCode( "k0 = 0; l = 0;", vars ), tree );
+        lines[ 1 ] = new PseudoCodeNode( TextLayoutHelper.setupPseudoCode( "k0 = 0; l = 0;", vars ), tree, new CodeLine() {
+
+			@Override
+			public ControlFlow runForward(Memory m) {
+				// TODO Auto-generated method stub
+				return null;
+			}
+        	
+        }, alg);
         lines[ 0 ].add( lines[ 1 ] );
+        /*
         lines[ 2 ] = new PseudoCodeNode( TextLayoutHelper.setupPseudoCode( "for l1=0 to |L[i+1]|-1 do", vars ), tree );
         lines[ 0 ].add( lines[ 2 ] );
         lines[ 3 ] = new PseudoCodeNode( TextLayoutHelper.setupPseudoCode( "if l1==|L[i+1]|-1 or L[i+1][l1] incident to inner segment between L[i+1] and L[i] then", vars ), tree );
@@ -433,212 +92,12 @@ public class ConflictDetection implements AlgorithmStage {
         lines[ 14 ] = new PseudoCodeNode( TextLayoutHelper.setupPseudoCode( "k0 = k1;", vars ), tree );
         lines[ 3 ].add( lines[ 14 ] );
         lines[ 15 ] = new PseudoCodeNode( TextLayoutHelper.setupPseudoCodeStage( "mark conflicts in subgraphs" ), tree );
-        root.add( lines[ 15 ] );
-        for( int i = 0; i < graph.getContainedNodes().size(); i++ )
-        {
-            LayeredGraphNode current = graph.getContainedNodes().get( i );
-            if( current.getContainedNodes().size() > 0 )
-            {
-                ConflictDetection extcalc = new ConflictDetection( current );
-                PseudoCodeNode subNode = extcalc.createPseudocodeTree( tree );
-                lines[ 15 ].add( subNode );
-                subgraphAlgs.set( i, extcalc );
-                subgraphNodes.set( i, subNode );
-            }
-        }
+        root.add( lines[ 15 ] );*/
         return root;
     }
 
     @Override
-    public StageStatus forwardStepOver() {
-        if( !insideSubgraph )
-        {
-            int depth = getCodeDepth( lines[ pseudo_line - 1 ] );
-            do
-            {
-                switch( forwardStep() )
-                {
-                case BREAKPOINT:
-                    return StageStatus.BREAKPOINT;
-                case FINISHED:
-                    return StageStatus.FINISHED;
-                case UNFINISHED:
-                    break;
-                }
-            } while( depth < getCodeDepth( lines[ pseudo_line - 1 ] ) );
-            return StageStatus.UNFINISHED;
-        }
-        else
-        {
-            boolean breakpoint = false;
-            boolean selected = subgraphNodes.get( vIndex ).isSelected();
-            CodeAction action = subgraphNodes.get( vIndex ).setSelected( true );
-            if( !selected )
-                breakpoint |= action == CodeAction.STOP;
-            do {
-                switch( subgraphAlgs.get( vIndex ).forwardStepOver() )
-                {
-                case BREAKPOINT:
-                    return StageStatus.BREAKPOINT;
-                case UNFINISHED:
-                    if( breakpoint )
-                        return StageStatus.BREAKPOINT;
-                    return StageStatus.UNFINISHED;
-                case FINISHED:
-                    insideSubgraph = false;
-                    subgraphNodes.get( vIndex ).setSelected( false );
-                    action = null;
-                    break;
-                }
-            } while( !breakpoint && action == CodeAction.SKIP );
-            return StageStatus.UNFINISHED;
-        }
-    }
-
-    @Override
-    public StageStatus forwardStepOut() {
-        if( !insideSubgraph )
-        {
-            int depth = getCodeDepth( lines[ pseudo_line - 1 ] );
-            do
-            {
-                switch( forwardStep() )
-                {
-                case BREAKPOINT:
-                    return StageStatus.BREAKPOINT;
-                case FINISHED:
-                    return StageStatus.FINISHED;
-                case UNFINISHED:
-                    break;
-                }
-            } while( depth <= getCodeDepth( lines[ pseudo_line - 1 ] ) );
-            return StageStatus.UNFINISHED;
-        }
-        else
-        {
-            boolean breakpoint = false;
-            boolean selected = subgraphNodes.get( vIndex ).isSelected();
-            CodeAction action = subgraphNodes.get( vIndex ).setSelected( true );
-            if( !selected )
-                breakpoint |= action == CodeAction.STOP;
-            do {
-                switch( subgraphAlgs.get( vIndex ).forwardStepOut() )
-                {
-                case BREAKPOINT:
-                    return StageStatus.BREAKPOINT;
-                case UNFINISHED:
-                    if( breakpoint )
-                        return StageStatus.BREAKPOINT;
-                    return StageStatus.UNFINISHED;
-                case FINISHED:
-                    insideSubgraph = false;
-                    subgraphNodes.get( vIndex ).setSelected( false );
-                    action = null;
-                    break;
-                }
-            } while( !breakpoint && action == CodeAction.SKIP );
-            return StageStatus.UNFINISHED;
-        }
-    }
-
-    @Override
-    public StageStatus backwardStepOver() {
-        if( !insideSubgraph )
-        {
-            int depth = getCodeDepth( lines[ pseudo_line - 1 ] );
-            do
-            {
-                switch( backwardStep() )
-                {
-                case BREAKPOINT:
-                    return StageStatus.BREAKPOINT;
-                case FINISHED:
-                    return StageStatus.FINISHED;
-                case UNFINISHED:
-                    break;
-                }
-            } while( depth < getCodeDepth( lines[ pseudo_line - 1 ] ) );
-            return StageStatus.UNFINISHED;
-        }
-        else
-        {
-            boolean breakpoint = false;
-            boolean selected = subgraphNodes.get( vIndex ).isSelected();
-            CodeAction action = subgraphNodes.get( vIndex ).setSelected( true );
-            if( !selected )
-                breakpoint |= action == CodeAction.STOP;
-            do {
-                switch( subgraphAlgs.get( vIndex ).backwardStepOver() )
-                {
-                case BREAKPOINT:
-                    return StageStatus.BREAKPOINT;
-                case UNFINISHED:
-                    LayeredGraphNode current = graph.getContainedNodes().get( vIndex );
-                    current.setSelected( null );
-                    if( breakpoint )
-                        return StageStatus.BREAKPOINT;
-                    return StageStatus.UNFINISHED;
-                case FINISHED:
-                    insideSubgraph = false;
-                    subgraphNodes.get( vIndex ).setSelected( false );
-                    action = null;
-                    break;
-                }
-            } while( !breakpoint && action == CodeAction.SKIP );
-            return StageStatus.UNFINISHED;
-        }
-    }
-
-    @Override
-    public StageStatus backwardStepOut() {
-        if( !insideSubgraph )
-        {
-            int depth = getCodeDepth( lines[ pseudo_line - 1 ] );
-            do
-            {
-                switch( backwardStep() )
-                {
-                case BREAKPOINT:
-                    return StageStatus.BREAKPOINT;
-                case FINISHED:
-                    return StageStatus.FINISHED;
-                case UNFINISHED:
-                    break;
-                }
-            } while( depth <= getCodeDepth( lines[ pseudo_line - 1 ] ) );
-            return StageStatus.UNFINISHED;
-        }
-        else
-        {
-            boolean breakpoint = false;
-            boolean selected = subgraphNodes.get( vIndex ).isSelected();
-            CodeAction action = subgraphNodes.get( vIndex ).setSelected( true );
-            if( !selected )
-                breakpoint |= action == CodeAction.STOP;
-            do {
-                switch( subgraphAlgs.get( vIndex ).backwardStepOut() )
-                {
-                case BREAKPOINT:
-                    return StageStatus.BREAKPOINT;
-                case UNFINISHED:
-                    LayeredGraphNode current = graph.getContainedNodes().get( vIndex );
-                    current.setSelected( null );
-                    if( breakpoint )
-                        return StageStatus.BREAKPOINT;
-                    return StageStatus.UNFINISHED;
-                case FINISHED:
-                    insideSubgraph = false;
-                    subgraphNodes.get( vIndex ).setSelected( false );
-                    action = null;
-                    break;
-                }
-            } while( !breakpoint && action == CodeAction.SKIP );
-            return StageStatus.UNFINISHED;
-        }
-    }
-
-    @Override
-    public String getDebugString() {
+    public String getDebugString() {/*
         String info = "| i  | l  | l1 | k0 | k1 | k  |\n";
         info +=       "|----|----|----|----|----|----|\n";
         info += "|" + TextLayoutHelper.strToLen( "" + i, 4 ) + 
@@ -654,21 +113,8 @@ public class ConflictDetection implements AlgorithmStage {
             info += tmp;
             return info;
         }
-        return info;
+        return info;*/
+    	return "";
     }
 
-    /**
-     * part of line 4 and 6 in the pseudocode
-     * 
-     * @return
-     */
-    private boolean incidentToInnerSegmentBetweenLiPlusOneAndLi() {
-        LayeredGraphNode curr = graph.getContainedLayers().get(i + 1).get(l1);
-        for (LayeredGraphEdge e : curr.getIncomingEdges()) {
-            if (e.isDummyEdge()) {
-                return true;
-            }
-        }
-        return false;
-    }
 }

+ 19 - 245
src/bk/ExtremalLayoutCalc.java

@@ -1,12 +1,13 @@
 package bk;
 
-import java.lang.reflect.InvocationTargetException;
-
 import javax.swing.JTree;
 
 import animation.AlgorithmStage;
+import animation.AnimatedAlgorithm;
+import animation.CodeLine;
+import animation.ControlFlow;
+import animation.Memory;
 import animation.PseudoCodeNode;
-import animation.PseudoCodeNode.CodeAction;
 import graph.LayeredGraphNode;
 import lib.TextLayoutHelper;
 
@@ -16,7 +17,8 @@ import lib.TextLayoutHelper;
  *
  */
 public class ExtremalLayoutCalc implements AlgorithmStage {
-    /**
+	
+	/**
      * There are four types of layouts, based on iteration order and median alignment.
      * Additionally there is one layout for the combined coordinates.
      * @author kolja
@@ -29,112 +31,28 @@ public class ExtremalLayoutCalc implements AlgorithmStage {
         BOTTOM_TOP_RIGHT,
         COMBINED
     }
-
-    private enum LayoutState
-    {
-        BLOCK_CALCULATION,
-        COMPACTION
-    }
-
-    private PseudoCodeNode pseudoCode;
-    private BlockCalc bc;
-    private Compaction cp;
-    private LayoutState status;
-    private PseudoCodeNode bcNode;
-    private PseudoCodeNode cpNode;
-    private LayoutType type;
-    private boolean inside;
+	
     private LayeredGraphNode graph;
+    private AnimatedAlgorithm alg;
 
-    public ExtremalLayoutCalc( LayoutType typ, LayeredGraphNode graph )
+    public ExtremalLayoutCalc( LayeredGraphNode graph, AnimatedAlgorithm alg )
     {
         this.graph = graph;
-        type = typ;
-        status = LayoutState.BLOCK_CALCULATION;
-        bc = new BlockCalc( graph, typ );
-        cp = new Compaction( graph, typ );
-        inside = false;
-    }
-
-    @Override
-    public StageStatus forwardStep() {
-        return forward( "forwardStep" );
-    }
-
-    @Override
-    public StageStatus backwardStep() {
-        return backward( "backwardStep" );
+        this.alg = alg;
     }
 
     @Override
     public PseudoCodeNode createPseudocodeTree( JTree tree ) {
-        if( type == LayoutType.TOP_BOTTOM_LEFT )
-            pseudoCode = new PseudoCodeNode( TextLayoutHelper.setupPseudoCodeStage("Extremal layout: leftmost upper"), tree );
-        if( type == LayoutType.TOP_BOTTOM_RIGHT )
-            pseudoCode = new PseudoCodeNode( TextLayoutHelper.setupPseudoCodeStage("Extremal layout: rightmost upper"), tree );
-        if( type == LayoutType.BOTTOM_TOP_LEFT )
-            pseudoCode = new PseudoCodeNode( TextLayoutHelper.setupPseudoCodeStage("Extremal layout: leftmost lower"), tree );;
-        if( type == LayoutType.BOTTOM_TOP_RIGHT )
-            pseudoCode = new PseudoCodeNode( TextLayoutHelper.setupPseudoCodeStage("Extremal layout: rightmost lower"), tree );
-        bcNode = bc.createPseudocodeTree( tree );
-        cpNode = cp.createPseudocodeTree( tree );
-        pseudoCode.add( bcNode );
-        pseudoCode.add( cpNode );
-        return pseudoCode;
-    }
-
-    @Override
-    public StageStatus forwardStepOver() {
-        if( !inside )
-        {
-            LayoutState oldState = status;
-            StageStatus stage = StageStatus.UNFINISHED;
-            while( status == oldState && stage == StageStatus.UNFINISHED )
-                stage = forwardStep();
-            return stage;
-        }
-        else
-            return forward( "forwardStepOver" );
-    }
+    	PseudoCodeNode root = new PseudoCodeNode( TextLayoutHelper.setupPseudoCode( "function calcLaout( layout, graph )", new String[0] ), tree, new CodeLine() {
 
-    @Override
-    public StageStatus forwardStepOut() {
-        if( !inside )
-        {
-            StageStatus status = StageStatus.UNFINISHED;
-            while( status == StageStatus.UNFINISHED )
-                status = forwardStep();
-            return status;
-        }
-        else
-            return forward( "forwardStepOut" );
-    }
-
-    @Override
-    public StageStatus backwardStepOver() {
-        if( !inside )
-        {
-            LayoutState oldState = status;
-            StageStatus stage = StageStatus.UNFINISHED;
-            while( status == oldState && stage == StageStatus.UNFINISHED )
-                stage = backwardStep();
-            return stage;
-        }
-        else
-            return backward( "backwardStepOver" );
-    }
-
-    @Override
-    public StageStatus backwardStepOut() {
-        if( !inside )
-        {
-            StageStatus status = StageStatus.UNFINISHED;
-            while( status == StageStatus.UNFINISHED )
-                status = backwardStep();
-            return status;
-        }
-        else
-            return backward( "backwardStepOut" );
+			@Override
+			public ControlFlow runForward(Memory m) {
+				// TODO Auto-generated method stub
+				return null;
+			}
+    		
+    	}, alg );
+        return root;
     }
 
     @Override
@@ -142,150 +60,6 @@ public class ExtremalLayoutCalc implements AlgorithmStage {
     {
         String info = "| Node | Shift | Sink | Root | Align |  x  |  xDef  |\n";
         info +=       "|------|-------|------|------|-------|-----|--------|\n";
-        for( LayeredGraphNode n : graph.getContainedNodes() )
-        {
-            info += "|" + TextLayoutHelper.strToLen( n.getName(), 6 ) + 
-                    "|" + TextLayoutHelper.strToLen( n.getShift( type ) + "", 7 ) + 
-                    "|" + TextLayoutHelper.strToLen( n.getSink( type ).getName(), 6 ) + 
-                    "|" + TextLayoutHelper.strToLen( n.getRoot( type ).getName(), 6 ) + 
-                    "|" + TextLayoutHelper.strToLen( n.getAlign( type ).getName(), 7 ) + 
-                    "|" + TextLayoutHelper.strToLen( n.getX( type ) + "", 5 ) + 
-                    "|" + TextLayoutHelper.strToLen( !n.isXUndefined( type ) + "", 8 ) + "|\n";
-        }
-        if( inside && status == LayoutState.BLOCK_CALCULATION )
-            info += bc.getDebugString();
         return info;
     }
-    
-    private StageStatus forward( String fName )
-    {
-        boolean breakpoint = false;
-        CodeAction action = null;
-        try {
-            if( status == LayoutState.BLOCK_CALCULATION )
-            {
-                boolean selected = bcNode.isSelected();
-                action = bcNode.setSelected( true );
-                if( !selected )
-                    breakpoint |= action == CodeAction.STOP;
-                do {
-                    switch( (StageStatus)(BlockCalc.class.getMethod( fName ).invoke( bc ) ) )
-                    {
-                    case FINISHED:
-                        inside = false;
-                        bcNode.setSelected( false );
-                        CodeAction ac = cpNode.setSelected( true );
-                        status = LayoutState.COMPACTION;
-                        if( ac == CodeAction.SKIP && !breakpoint )
-                            return forward( fName );
-                        break;
-                    case BREAKPOINT:
-                        inside = true;
-                        return StageStatus.BREAKPOINT;
-                    case UNFINISHED:
-                        inside = true;
-                    }
-                } while( !breakpoint && action == CodeAction.SKIP );
-            }
-            else if( status == LayoutState.COMPACTION )
-            {
-                boolean selected = cpNode.isSelected();
-                action = cpNode.setSelected( true );
-                if( !selected )
-                    breakpoint |= action == CodeAction.STOP;
-                do {
-                    switch( (StageStatus)(Compaction.class.getMethod( fName ).invoke( cp ) ) )
-                    {
-                    case FINISHED:
-                        inside = false;
-                        cpNode.setSelected( false );
-                        return StageStatus.FINISHED;
-                    case BREAKPOINT:
-                        inside = true;
-                        return StageStatus.BREAKPOINT;
-                    case UNFINISHED:
-                        inside = true;
-                    }
-                } while( !breakpoint && action == CodeAction.SKIP );
-            }
-        } catch (IllegalAccessException e) {
-            e.printStackTrace();
-        } catch (IllegalArgumentException e) {
-            e.printStackTrace();
-        } catch (InvocationTargetException e) {
-            e.printStackTrace();
-        } catch (NoSuchMethodException e) {
-            e.printStackTrace();
-        } catch (SecurityException e) {
-            e.printStackTrace();
-        }
-        if( breakpoint )
-            return StageStatus.BREAKPOINT;
-        return StageStatus.UNFINISHED;
-    }
-    
-    private StageStatus backward( String fName )
-    {
-        boolean breakpoint = false;
-        CodeAction action = null;
-        try {
-            if( status == LayoutState.BLOCK_CALCULATION )
-            {
-                boolean sel = bcNode.isSelected();
-                action = bcNode.setSelected( true );
-                if( !sel )
-                    breakpoint |= action == CodeAction.STOP;
-                do {
-                    switch( (StageStatus)(BlockCalc.class.getMethod( fName ).invoke( bc ) ) )
-                    {
-                    case FINISHED:
-                        inside = false;
-                        bcNode.setSelected( false );
-                        return StageStatus.FINISHED;
-                    case BREAKPOINT:
-                        inside = true;
-                        return StageStatus.BREAKPOINT;
-                    case UNFINISHED:
-                        inside = true;
-                    }
-                } while( !breakpoint && action == CodeAction.SKIP );
-            }
-            else if( status == LayoutState.COMPACTION )
-            {
-                boolean sel = cpNode.isSelected();
-                action = cpNode.setSelected( true );
-                if( !sel )
-                    breakpoint |= action == CodeAction.STOP;
-                do {
-                    switch( (StageStatus)(Compaction.class.getMethod( fName ).invoke( cp ) ) )
-                    {
-                    case FINISHED:
-                        inside = false;
-                        cpNode.setSelected( false );
-                        status = LayoutState.BLOCK_CALCULATION;
-                        action = null;
-                        break;
-                    case BREAKPOINT:
-                        inside = true;
-                        return StageStatus.BREAKPOINT;
-                    case UNFINISHED:
-                        inside = true;
-                    }
-                } while( !breakpoint && action == CodeAction.SKIP );
-            }
-        } catch (IllegalAccessException e) {
-            e.printStackTrace();
-        } catch (IllegalArgumentException e) {
-            e.printStackTrace();
-        } catch (InvocationTargetException e) {
-            e.printStackTrace();
-        } catch (NoSuchMethodException e) {
-            e.printStackTrace();
-        } catch (SecurityException e) {
-            e.printStackTrace();
-        }
-        if( breakpoint )
-            return StageStatus.BREAKPOINT;
-        return StageStatus.UNFINISHED;
-    }
 }

+ 75 - 0
src/codelines/BackwardForEachLoop.java

@@ -0,0 +1,75 @@
+package codelines;
+
+import java.util.List;
+
+import animation.CodeLine;
+import animation.ControlFlow;
+import animation.Memory;
+import animation.StackFrame;
+import animation.StackFrame.FrameType;
+
+public class BackwardForEachLoop <T> extends CodeLine {
+
+	String listVar;
+	String loopVar;
+	
+	public BackwardForEachLoop( String listName, String varName )
+	{
+		this.listVar = listName;
+		this.loopVar = varName;
+	}
+	
+	@Override
+	public ControlFlow runForward(Memory m) {
+		boolean declared = false; // prove if it is the first step in the loop
+		if( !m.isSomewhereDefined( "line_" + lineId + "_index", false ) )
+		{ // first loop step
+			m.declare( "line_" + lineId + "_index", m.<List<T>>read( listVar, false ).size() - 1, false );
+			declared = true;
+		}
+		if( m.<Integer>read( "line_" + lineId + "_index", false ) < 0 ) // prove if the loop has finished
+		{
+			m.undeclare( "line_" + lineId + "_index", false );
+			actions.add( (Memory mem) -> {
+				return new ControlFlow( ControlFlow.STEP_OVER ); // loop was not called so nothing to reverse
+			});
+			return new ControlFlow( ControlFlow.STEP_OVER ); // don't execute the loop body
+		}
+		if( declared )
+		{
+			m.addFrame( new StackFrame( FrameType.LOOP ) );
+			m.declare( loopVar, m.<List<T>>read( listVar, false ).get( m.read( "line_" + lineId + "_index", false ) ), false ); // set loop variable
+			actions.add( (Memory mem) -> {
+				mem.removeFrame();
+				mem.undeclare( "line_" + lineId + "_index", false );
+				return new ControlFlow( ControlFlow.STEP_OVER ); // step out of the loop
+			} );
+		}
+		else
+		{
+			int oldIndex = m.<Integer>read( "line_" + lineId + "_index", false );
+			m.write( "line_" + lineId + "_index", oldIndex - 1, false ); // count index down
+			if( m.<Integer>read( "line_" + lineId + "_index", false ) < 0 ) // prove if loop was finished
+			{
+				StackFrame sf = m.removeFrame(); // remove loop stack
+				m.undeclare( "line_" + lineId + "_index", false );
+				actions.add( (Memory mem) -> {
+					mem.write( "line_" + lineId + "_index", oldIndex, false );
+					mem.addFrame( sf ); // restore last loop stack
+					return new ControlFlow( ControlFlow.STEP_INTO ); // step into the loop body
+				});
+				return new ControlFlow( ControlFlow.STEP_OVER ); // step out of the loop
+			}
+			StackFrame old = m.removeFrame(); // fresh stack frame for loop body
+			m.addFrame( new StackFrame( FrameType.LOOP ) );
+			m.write( loopVar, m.<List<T>>read( listVar, false ).get( m.read( "line_" + lineId + "_index", false ) ), false ); // update loop variable
+			actions.push( (Memory mem) -> {
+				m.removeFrame();
+				m.addFrame( old );
+				mem.write( "line_" + lineId + "_index", oldIndex, false );
+				return new ControlFlow( ControlFlow.STEP_INTO );
+			});
+		}
+		return new ControlFlow( ControlFlow.STEP_INTO );
+	}
+}

+ 34 - 0
src/codelines/DeclareVariable.java

@@ -0,0 +1,34 @@
+package codelines;
+
+import animation.CodeLine;
+import animation.ControlFlow;
+import animation.Memory;
+
+public class DeclareVariable <T> extends CodeLine {
+
+	private boolean oldExists;
+	private T val;
+	private String name;
+	
+	public DeclareVariable( String name, T value )
+	{
+		this.val = value;
+		this.name = name;
+	}
+
+	@Override
+	public ControlFlow runForward(Memory m) {
+		
+		oldExists = m.isDefined( name, false );
+		T oldVal = m.read( name, false );
+		m.declare( name, val, false );
+		actions.add( (Memory mem) -> {
+			if( !oldExists )
+				m.undeclare( name, false );
+			else
+				m.declare( name, oldVal, false );
+			return new ControlFlow( ControlFlow.STEP_OVER );
+		});
+		return new ControlFlow( ControlFlow.STEP_OVER );
+	}
+}

+ 75 - 0
src/codelines/DefaultForEachLoop.java

@@ -0,0 +1,75 @@
+package codelines;
+
+import java.util.List;
+
+import animation.CodeLine;
+import animation.ControlFlow;
+import animation.Memory;
+import animation.StackFrame;
+import animation.StackFrame.FrameType;
+
+public class DefaultForEachLoop <T> extends CodeLine {
+
+	String listVar;
+	String loopVar;
+	
+	public DefaultForEachLoop( String listName, String varName )
+	{
+		this.listVar = listName;
+		this.loopVar = varName;
+	}
+	
+	@Override
+	public ControlFlow runForward(Memory m) {
+		boolean declared = false; // prove if it is the first step in the loop
+		if( !m.isSomewhereDefined( "line_" + lineId + "_index", false ) )
+		{ // first loop step
+			m.declare( "line_" + lineId + "_index", 0, false );
+			declared = true;
+		}
+		if( m.<Integer>read( "line_" + lineId + "_index", false ) > m.<List<T>>read( listVar, false ).size() - 1 ) // prove if the loop has finished
+		{
+			m.undeclare( "line_" + lineId + "_index", false );
+			actions.add( (Memory mem) -> {
+				return new ControlFlow( ControlFlow.STEP_OVER ); // loop was not called so nothing to reverse
+			});
+			return new ControlFlow( ControlFlow.STEP_OVER ); // don't execute the loop body
+		}
+		if( declared )
+		{
+			m.addFrame( new StackFrame( FrameType.LOOP ) );
+			m.declare( loopVar, m.<List<T>>read( listVar, false ).get( m.read( "line_" + lineId + "_index", false ) ), false ); // set loop variable
+			actions.add( (Memory mem) -> {
+				mem.removeFrame();
+				mem.undeclare( "line_" + lineId + "_index", false );
+				return new ControlFlow( ControlFlow.STEP_OVER ); // step out of the loop
+			} );
+		}
+		else
+		{
+			int oldIndex = m.<Integer>read( "line_" + lineId + "_index", false );
+			m.write( "line_" + lineId + "_index", oldIndex + 1, false ); // count index down
+			if( m.<Integer>read( "line_" + lineId + "_index", false ) > m.<List<T>>read( listVar, false ).size() - 1 ) // prove if loop was finished
+			{
+				StackFrame sf = m.removeFrame(); // remove loop stack
+				m.undeclare( "line_" + lineId + "_index", false );
+				actions.add( (Memory mem) -> {
+					mem.write( "line_" + lineId + "_index", oldIndex, false );
+					mem.addFrame( sf ); // restore last loop stack
+					return new ControlFlow( ControlFlow.STEP_INTO ); // step into the loop body
+				});
+				return new ControlFlow( ControlFlow.STEP_OVER ); // step out of the loop
+			}
+			StackFrame old = m.removeFrame(); // fresh stack frame for loop body
+			m.addFrame( new StackFrame( FrameType.LOOP ) );
+			m.write( loopVar, m.<List<T>>read( listVar, false ).get( m.read( "line_" + lineId + "_index", false ) ), false ); // update loop variable
+			actions.push( (Memory mem) -> {
+				m.removeFrame();
+				m.addFrame( old );
+				mem.write( "line_" + lineId + "_index", oldIndex, false );
+				return new ControlFlow( ControlFlow.STEP_INTO );
+			});
+		}
+		return new ControlFlow( ControlFlow.STEP_INTO );
+	}
+}

+ 0 - 57
src/codelines/DefaultForLoop.java

@@ -1,57 +0,0 @@
-package codelines;
-
-import animation.CodeLine;
-import animation.ControlFlow;
-import animation.Memory;
-
-public class DefaultForLoop implements CodeLine {
-
-    private boolean initialized = false;
-    private Integer i;
-    private int start;
-    private int max;
-    private String vName;
-    
-    public DefaultForLoop( String vName, int start, int max )
-    {
-        this.start = start;
-        this.max = max;
-        this.vName = vName;
-    }
-    
-    @Override
-    public ControlFlow runForward(Memory m) {
-        if( !initialized )
-        {
-            initialized = true;
-            i = start;
-            m.declare( vName, i, false );
-        }
-        else
-        {
-            i++;
-        }
-        if( i > max )
-        {
-            m.undeclare( vName, false );
-            return new ControlFlow( ControlFlow.STEP_OVER );
-        }
-        else
-            return new ControlFlow( ControlFlow.STEP_INTO_LOOP );
-    }
-
-    @Override
-    public ControlFlow runBackward(Memory m) {
-        i--;
-        m.declare( vName, i, false );
-        if( i < start )
-        {
-            initialized = false;
-            m.undeclare( vName, false );
-            return new ControlFlow( ControlFlow.STEP_OVER );
-        }
-        else
-            return new ControlFlow( ControlFlow.STEP_INTO_LOOP );
-    }
-
-}

+ 1 - 1
src/lib/TextLayoutHelper.java

@@ -20,7 +20,7 @@ public class TextLayoutHelper {
         return s;
     }
     
-    private static String[] keywords = { "for", "do", "to", "then", "else", "if", "foreach", "while", "or", "and" };
+    private static String[] keywords = { "for", "do", "to", "then", "else", "if", "foreach", "while", "or", "and", "call", "function" };
     private static String[] delimiter = { "\\+", "\\-", "\\[", "\\]", "\\|", " ", "^", "$", "\\=", "\\,", "\\(", "\\;" };
     
     private static String getDelimiterRegex()