Преглед изворни кода

Step Over and Step Out funktionieren jetzt, ausßerdem wurde die Debug Information Table eingebaut

Kolja Strohm пре 6 година
родитељ
комит
eb2c986724

+ 8 - 0
src/animation/AlgorithmStage.java

@@ -27,6 +27,10 @@ public interface AlgorithmStage {
      * For example if all steps are reverted, then {@code FINISHED} is returned.
 	 */
 	public StageStatus forwardStep();
+	
+	public StageStatus forwardStepOver();
+	
+    public StageStatus forwardStepOut();
     
     /**
      * undo one atomic step of the algorithm
@@ -35,5 +39,9 @@ public interface AlgorithmStage {
      */
 	public StageStatus backwardStep();
 	
+    public StageStatus backwardStepOver();
+    
+    public StageStatus backwardStepOut();
+	
     public PseudoCodeNode createPseudocodeTree();
 }

+ 11 - 2
src/animation/AnimatedAlgorithm.java

@@ -1,6 +1,7 @@
 package animation;
 
 import graph.LayeredGraphNode;
+import view.MainView;
 
 public abstract class AnimatedAlgorithm extends Thread implements AlgorithmStage {
 
@@ -22,20 +23,28 @@ public abstract class AnimatedAlgorithm extends Thread implements AlgorithmStage
 				switch( ac.getNextAction() )
 				{
 				case FORWARD:
-					System.out.println( "FORWARD" );
 					forwardStep();
+                    MainView.frame.repaint();
 					break;
                 case FORWARD_OUT:
+                    forwardStepOut();
+                    MainView.frame.repaint();
                     break;
                 case FORWARD_OVER:
+                    forwardStepOver();
+                    MainView.frame.repaint();
                     break;
 				case BACKWARD:
-					System.out.println( "BACKWARD" );
 					backwardStep();
+                    MainView.frame.repaint();
 					break;
                 case BACKWARD_OUT:
+                    backwardStepOut();
+                    MainView.frame.repaint();
                     break;
                 case BACKWARD_OVER:
+                    backwardStepOver();
+                    MainView.frame.repaint();
                     break;
                 default:
                     break;

+ 228 - 93
src/bk/BKNodePlacement.java

@@ -1,5 +1,7 @@
 package bk;
 
+import java.lang.reflect.InvocationTargetException;
+
 import animation.AlgorithmStage;
 import animation.AnimatedAlgorithm;
 import animation.AnimationController;
@@ -37,6 +39,7 @@ public class BKNodePlacement extends AnimatedAlgorithm {
     private PseudoCodeNode layout3Node;
     private PseudoCodeNode layout4Node;
     private PseudoCodeNode combineNode;
+    private boolean inside;
 	
 	public BKNodePlacement(AnimationController controller, LayeredGraphNode graph) {
 		super(controller, graph);
@@ -48,109 +51,20 @@ public class BKNodePlacement extends AnimatedAlgorithm {
 		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;
 	}
 
 	@Override
 	public StageStatus forwardStep() {
-		switch( state )
-		{
-		case CONFLICTS:
-		    conflictsNode.setSelected( true );
-			if( conftion.forwardStep() == StageStatus.FINISHED )
-			{
-	            conflictsNode.setSelected( false );
-	            layout1Node.setSelected( true );
-				state = State.LAYOUT1;
-			}
-			break;
-		case LAYOUT1:
-			if( layouts[ 0 ].forwardStep() == StageStatus.FINISHED )
-			{
-	            layout1Node.setSelected( false );
-	            layout2Node.setSelected( true );
-				state = State.LAYOUT2;
-			}
-			break;
-		case LAYOUT2:
-			if( layouts[ 1 ].forwardStep() == StageStatus.FINISHED )
-			{
-	            layout2Node.setSelected( false );
-                layout3Node.setSelected( true );
-				state = State.LAYOUT3;
-			}
-			break;
-		case LAYOUT3:
-			if( layouts[ 2 ].forwardStep() == StageStatus.FINISHED )
-			{
-                layout3Node.setSelected( false );
-                layout4Node.setSelected( true );
-				state = State.LAYOUT4;
-			}
-			break;
-		case LAYOUT4:
-			if( layouts[ 3 ].forwardStep() == StageStatus.FINISHED )
-			{
-	            layout4Node.setSelected( false );
-                combineNode.setSelected( true );
-				state = State.COMBINE;
-			}
-			break;
-		case COMBINE:
-			return combine.forwardStep();
-		}
-		return StageStatus.UNFINISHED;
+		return forward( "forwardStep" );
 	}
 
 	@Override
 	public StageStatus backwardStep() {
-		switch( state )
-		{
-		case CONFLICTS:
-			return conftion.backwardStep();
-		case LAYOUT1:
-			if( layouts[ 0 ].backwardStep() == StageStatus.FINISHED )
-			{
-	            layout1Node.setSelected( false );
-	            conflictsNode.setSelected( true );
-				state = State.CONFLICTS;
-			}
-			break;
-		case LAYOUT2:
-			if( layouts[ 1 ].backwardStep() == AlgorithmStage.StageStatus.FINISHED )
-			{
-	            layout2Node.setSelected( false );
-	            layout1Node.setSelected( true );
-				state = State.LAYOUT1;
-			}
-			break;
-		case LAYOUT3:
-			if( layouts[ 2 ].backwardStep() == AlgorithmStage.StageStatus.FINISHED )
-			{
-	            layout3Node.setSelected( false );
-	            layout2Node.setSelected( true );
-				state = State.LAYOUT2;
-			}
-			break;
-		case LAYOUT4:
-			if( layouts[ 3 ].backwardStep() == AlgorithmStage.StageStatus.FINISHED )
-			{
-                layout4Node.setSelected( false );
-                layout3Node.setSelected( true );
-				state = State.LAYOUT3;
-			}
-			break;
-		case COMBINE:
-			if( combine.backwardStep() == AlgorithmStage.StageStatus.FINISHED )
-			{
-	            combineNode.setSelected( false );
-	            layout4Node.setSelected( true );
-				state = State.LAYOUT4;
-			}
-			break;
-		}
-		return StageStatus.UNFINISHED;
+	    return backward( "backwardStep" );
 	}
 	
+	@Override
 	public PseudoCodeNode createPseudocodeTree()
 	{
 	    PseudoCodeNode root = new PseudoCodeNode( "BK Node Placement Algorithm" );
@@ -168,4 +82,225 @@ public class BKNodePlacement extends AnimatedAlgorithm {
         root.add( combineNode );
         return root;
 	}
+
+    @Override
+    public StageStatus forwardStepOver() {
+        if( !inside )
+        {
+            State oldState = state;
+            StageStatus status = StageStatus.UNFINISHED;
+            while( state == oldState && status != StageStatus.FINISHED )
+                status = forwardStep();
+            return status;
+        }
+        else
+            return forward( "forwardStepOver" );
+    }
+
+    @Override
+    public StageStatus forwardStepOut() {
+        if( !inside )
+        {
+            StageStatus status = StageStatus.UNFINISHED;
+            while( status != StageStatus.FINISHED )
+                status = forwardStep();
+            return status;
+        }
+        else
+            return forward( "forwardStepOut" );
+    }
+
+    @Override
+    public StageStatus backwardStepOver() {
+        if( !inside )
+        {
+            State oldState = state;
+            StageStatus status = StageStatus.UNFINISHED;
+            while( state == oldState && status != StageStatus.FINISHED )
+                status = backwardStep();
+            return status;
+        }
+        else
+            return backward( "backwardStepOver" );
+    }
+
+    @Override
+    public StageStatus backwardStepOut() {
+        if( !inside )
+        {
+            StageStatus status = StageStatus.UNFINISHED;
+            while( status != StageStatus.FINISHED )
+                status = backwardStep();
+            return status;
+        }
+        else
+            return backward( "backwardStepOut" );
+    }
+    
+    private StageStatus forward( String fName )
+    {
+        try {
+            switch( state )
+            {
+            case CONFLICTS:
+                conflictsNode.setSelected( true );
+                    if( (StageStatus)(ConflictDetection.class.getMethod( fName ).invoke( conftion ) ) == StageStatus.FINISHED )
+                    {
+                        inside = false;
+                        conflictsNode.setSelected( false );
+                        layout1Node.setSelected( true );
+                        state = State.LAYOUT1;
+                    }
+                    else
+                        inside = true;
+                break;
+            case LAYOUT1:
+                if( (StageStatus)(ExtremalLayoutCalc.class.getMethod( fName ).invoke( layouts[ 0 ] ) ) == StageStatus.FINISHED )
+                {
+                    inside = false;
+                    layout1Node.setSelected( false );
+                    layout2Node.setSelected( true );
+                    state = State.LAYOUT2;
+                }
+                else
+                    inside = true;
+                break;
+            case LAYOUT2:
+                if( (StageStatus)(ExtremalLayoutCalc.class.getMethod( fName ).invoke( layouts[ 1 ] ) ) == StageStatus.FINISHED )
+                {
+                    inside = false;
+                    layout2Node.setSelected( false );
+                    layout3Node.setSelected( true );
+                    state = State.LAYOUT3;
+                }
+                else
+                    inside = true;
+                break;
+            case LAYOUT3:
+                if( (StageStatus)(ExtremalLayoutCalc.class.getMethod( fName ).invoke( layouts[ 2 ] ) ) == StageStatus.FINISHED )
+                {
+                    inside = false;
+                    layout3Node.setSelected( false );
+                    layout4Node.setSelected( true );
+                    state = State.LAYOUT4;
+                }
+                else
+                    inside = true;
+                break;
+            case LAYOUT4:
+                if( (StageStatus)(ExtremalLayoutCalc.class.getMethod( fName ).invoke( layouts[ 3 ] ) ) == StageStatus.FINISHED )
+                {
+                    inside = false;
+                    layout4Node.setSelected( false );
+                    combineNode.setSelected( true );
+                    state = State.COMBINE;
+                }
+                else
+                    inside = true;
+                break;
+            case COMBINE:
+                if( (StageStatus)(Combine.class.getMethod( fName ).invoke( combine ) ) == StageStatus.FINISHED )
+                {
+                    inside = false;
+                    return StageStatus.FINISHED;
+                }
+                else
+                    inside = true;
+            }
+        } 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();
+        }
+        return StageStatus.UNFINISHED;
+    }
+
+    private StageStatus backward( String fName ) {
+        try {
+            switch( state )
+            {
+            case CONFLICTS:
+                if( (StageStatus)(ConflictDetection.class.getMethod( fName ).invoke( conftion ) ) == StageStatus.FINISHED )
+                {
+                    inside = false;
+                    return StageStatus.FINISHED;
+                }
+                else
+                    inside = true;
+            case LAYOUT1:
+                if( (StageStatus)(ExtremalLayoutCalc.class.getMethod( fName ).invoke( layouts[ 0 ] ) ) == StageStatus.FINISHED )
+                {
+                    inside = false;
+                    layout1Node.setSelected( false );
+                    conflictsNode.setSelected( true );
+                    state = State.CONFLICTS;
+                }
+                else
+                    inside = true;
+                break;
+            case LAYOUT2:
+                if( (StageStatus)(ExtremalLayoutCalc.class.getMethod( fName ).invoke( layouts[ 1 ] ) ) == AlgorithmStage.StageStatus.FINISHED )
+                {
+                    inside = false;
+                    layout2Node.setSelected( false );
+                    layout1Node.setSelected( true );
+                    state = State.LAYOUT1;
+                }
+                else
+                    inside = true;
+                break;
+            case LAYOUT3:
+                if( (StageStatus)(ExtremalLayoutCalc.class.getMethod( fName ).invoke( layouts[ 2 ] ) ) == AlgorithmStage.StageStatus.FINISHED )
+                {
+                    inside = false;
+                    layout3Node.setSelected( false );
+                    layout2Node.setSelected( true );
+                    state = State.LAYOUT2;
+                }
+                else
+                    inside = true;
+                break;
+            case LAYOUT4:
+                if( (StageStatus)(ExtremalLayoutCalc.class.getMethod( fName ).invoke( layouts[ 3 ] ) ) == AlgorithmStage.StageStatus.FINISHED )
+                {
+                    inside = false;
+                    layout4Node.setSelected( false );
+                    layout3Node.setSelected( true );
+                    state = State.LAYOUT3;
+                }
+                else
+                    inside = true;
+                break;
+            case COMBINE:
+                if( (StageStatus)(Combine.class.getMethod( fName ).invoke( combine ) ) == AlgorithmStage.StageStatus.FINISHED )
+                {
+                    inside = false;
+                    combineNode.setSelected( false );
+                    layout4Node.setSelected( true );
+                    state = State.LAYOUT4;
+                }
+                else
+                    inside = true;
+                break;
+            }
+        } 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();
+        }
+        return StageStatus.UNFINISHED;
+    }
+    
 }

+ 26 - 0
src/bk/BlockCalc.java

@@ -246,4 +246,30 @@ public class BlockCalc implements AlgorithmStage {
         root.add( loopNode );
         return root;
     }
+
+    @Override
+    public StageStatus forwardStepOver() {
+        return forwardStep();
+    }
+
+    @Override
+    public StageStatus forwardStepOut() {
+        StageStatus status = StageStatus.UNFINISHED;
+        while( status != StageStatus.FINISHED )
+            status = forwardStep();
+        return status;
+    }
+
+    @Override
+    public StageStatus backwardStepOver() {
+        return backwardStep();
+    }
+
+    @Override
+    public StageStatus backwardStepOut() {
+        StageStatus status = StageStatus.UNFINISHED;
+        while( status != StageStatus.FINISHED )
+            status = backwardStep();
+        return status;
+    }
 }

+ 77 - 0
src/bk/Combine.java

@@ -36,6 +36,7 @@ public class Combine implements AlgorithmStage {
     private PseudoCodeNode alignNode;
     private PseudoCodeNode setNode;
     private PseudoCodeNode loopNode;
+    private boolean inside;
 	
 	public Combine( LayeredGraphNode graph )
 	{
@@ -43,12 +44,14 @@ public class Combine implements AlgorithmStage {
 		state = State.ALIGN;
 		vIndex = 0;
 		actions = new ArrayList<>();
+		inside = false;
 	}
 	
 	@Override
 	public StageStatus forwardStep() {
 		if( state == State.ALIGN )
 		{
+		    inside = false;
 		    alignNode.setSelected( true );
 			int tblw = (int)graph.getWidth( LayoutType.TOP_BOTTOM_LEFT );
 			int tbrw = (int)graph.getWidth( LayoutType.TOP_BOTTOM_RIGHT );
@@ -80,6 +83,7 @@ public class Combine implements AlgorithmStage {
 			MainView.frame.setSize( MainView.frame.getWidth() + 1, MainView.frame.getHeight() );
 			MainView.frame.setSize( MainView.frame.getWidth() - 1, MainView.frame.getHeight() );
 			actions.add( 0, () -> {
+                inside = false;
 	            setNode.setSelected( false );
                 alignNode.setSelected( true );
 				state = State.ALIGN;
@@ -96,10 +100,13 @@ public class Combine implements AlgorithmStage {
 		{
 			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 );
 			ArrayList< Integer > positions = new ArrayList<>();
@@ -111,6 +118,7 @@ public class Combine implements AlgorithmStage {
 			int oldX = (int)current.getX( LayoutType.COMBINED );
 			current.setX( (positions.get( 1 ) + positions.get( 2 )) / 2, true, LayoutType.COMBINED );
 			actions.add( 0, () -> {
+                inside = true; 
                 setNode.setSelected( true );
                 loopNode.setSelected( true );
 				vIndex--;
@@ -135,7 +143,10 @@ public class Combine implements AlgorithmStage {
 	@Override
 	public StageStatus backwardStep() {
 		if( actions.size() == 0 )
+		{
+            inside = false;
 			return StageStatus.FINISHED;
+		}
 		actions.get( 0 ).reverse();
 		actions.remove( 0 );
 		return StageStatus.UNFINISHED;
@@ -152,4 +163,70 @@ public class Combine implements AlgorithmStage {
         root.add( setNode );
         return root;
     }
+
+    @Override
+    public StageStatus forwardStepOver() {
+        if( !inside )
+        {
+            State oldState = state;
+            StageStatus stage = StageStatus.UNFINISHED;
+            while( state == oldState && stage != StageStatus.FINISHED )
+                stage = forwardStep();
+            return stage;
+        }
+        else
+            return forwardStep();
+    }
+
+    @Override
+    public StageStatus forwardStepOut() {
+        if( !inside )
+        {
+            StageStatus status = StageStatus.UNFINISHED;
+            while( status != StageStatus.FINISHED )
+                status = forwardStep();
+            return status;
+        }
+        else
+        {
+            State oldState = state;
+            StageStatus stage = StageStatus.UNFINISHED;
+            while( state == oldState && stage != StageStatus.FINISHED )
+                stage = forwardStep();
+            return stage;
+        }
+    }
+
+    @Override
+    public StageStatus backwardStepOver() {
+        if( !inside )
+        {
+            State oldState = state;
+            StageStatus stage = StageStatus.UNFINISHED;
+            while( state == oldState && stage != StageStatus.FINISHED )
+                stage = backwardStep();
+            return stage;
+        }
+        else
+            return backwardStep();
+    }
+
+    @Override
+    public StageStatus backwardStepOut() {
+        if( !inside )
+        {
+            StageStatus status = StageStatus.UNFINISHED;
+            while( status != StageStatus.FINISHED )
+                status = backwardStep();
+            return status;
+        }
+        else
+        {
+            State oldState = state;
+            StageStatus stage = StageStatus.UNFINISHED;
+            while( state == oldState && stage != StageStatus.FINISHED )
+                stage = backwardStep();
+            return stage;
+        }
+    }
 }

+ 88 - 0
src/bk/Compaction.java

@@ -39,6 +39,7 @@ public class Compaction implements AlgorithmStage{
     private PseudoCodeNode placeLoopNode;
     private PseudoCodeNode applyNode;
     private PseudoCodeNode applyLoopNode;
+    private boolean inside;
 	
 	
 	public Compaction( LayeredGraphNode graph, LayoutType layout )
@@ -49,6 +50,7 @@ public class Compaction implements AlgorithmStage{
 		stack = new ArrayList<>(); // der call-stack des rekursiven algorithmus
 		vIndex = 0;
 		actions = new ArrayList<>();
+		inside = false;
 	}
 	
 	/**
@@ -81,6 +83,7 @@ public class Compaction implements AlgorithmStage{
 		int acSize = actions.size();
 		if( state == CompactionState.PLACE_BLOCKS ) // blöcke platzieren
 		{
+		    inside = true;
 		    placeNode.setSelected( true );
 		    placeLoopNode.setSelected( true );
 			if( stack.size() == 0 ) // äußere schleife, placeblocks bisher nicht aufgerufen
@@ -108,6 +111,7 @@ public class Compaction implements AlgorithmStage{
 		            applyNode.setSelected( true );
 		            applyLoopNode.setSelected( true );
 					state = CompactionState.APPLY_SHIFT;
+					inside = false;
 					vIndex = 0;
 					actions.add( 0, ()-> {
 	                    applyNode.setSelected( false );
@@ -115,6 +119,7 @@ public class Compaction implements AlgorithmStage{
                         placeNode.setSelected( true );
                         placeLoopNode.setSelected( true );
 						vIndex = oldVIndex;
+						inside = false;
 						state = CompactionState.PLACE_BLOCKS;
 					} );
 				}
@@ -131,6 +136,7 @@ public class Compaction implements AlgorithmStage{
 					
 					// die "undo"-action
 					actions.add( 0, ()-> {
+					    inside = true;
 						stack.get( 0 ).v.setX( oldX, false, layout );
 						stack.get( 0 ).v.setSelected( layout );
 						stack.remove( 0 );
@@ -165,6 +171,7 @@ public class Compaction implements AlgorithmStage{
 		                    
 		                    // die "undo"-action
 							actions.add( 0, ()-> {
+							    inside = true;
 								stack.get( 0 ).v.setX( oldX, false, layout );
 								stack.get( 0 ).v.setSelected( layout );
 								stack.remove( 0 );
@@ -176,6 +183,7 @@ public class Compaction implements AlgorithmStage{
 						    // tue nix
 							sf.w.setSelected( layout );
 							actions.add( 0, ()-> {
+                                inside = true;
 								stack.get( 0 ).u = null;
 							});
 						}
@@ -190,6 +198,7 @@ public class Compaction implements AlgorithmStage{
                             System.out.println( "return place_block( " + sf.v + " )" );
 							stack.remove( 0 );
 							actions.add( 0, ()-> {
+                                inside = true;
 								stack.add( 0, sf );
 								sf.w = oldW;
                                 sf.w.setSelected( layout );
@@ -198,6 +207,7 @@ public class Compaction implements AlgorithmStage{
 						else
 						{ //nur "undo aktion" hinzufügen
 							actions.add( 0, ()-> {
+                                inside = true;
 								sf.w = oldW;
 								sf.w.setSelected( layout );
 							});
@@ -243,6 +253,7 @@ public class Compaction implements AlgorithmStage{
 					    System.out.println( "return place_block( " + sf.v + " )" );
 						stack.remove( 0 );
 						actions.add( 0, ()-> {
+                            inside = true;
 							stack.add( 0, sf );
 							stack.get( 0 ).v.setSink(  oldSink, layout );
 							sinkOfU.setShift( oldShift, layout );
@@ -255,6 +266,7 @@ public class Compaction implements AlgorithmStage{
 					else
 					{ //nur "undo aktion" hinzufügen
 						actions.add( 0, ()-> {
+                            inside = true;
 							stack.get( 0 ).v.setSink(  oldSink, layout );
 							sinkOfU.setShift( oldShift, layout );
 							sf.u = oldU;
@@ -268,6 +280,14 @@ public class Compaction implements AlgorithmStage{
 		}
 		else if( state == CompactionState.APPLY_SHIFT )// "Compute absolute coordinates"
 		{
+            inside = true;
+		    if( vIndex >= graph.getContainedNodes().size() )
+		    {
+                inside = false;
+                applyNode.setSelected( false );
+                applyLoopNode.setSelected( false );
+                return StageStatus.FINISHED;
+		    }
 			LayeredGraphNode v = graph.getContainedNodes().get( vIndex );
 			double oldX = v.getX( layout );
 			boolean oldDef = !v.isXUndefined( layout );
@@ -277,6 +297,7 @@ public class Compaction implements AlgorithmStage{
 			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;
                 applyNode.setSelected( true );
                 applyLoopNode.setSelected( true );
 				v.setX( oldX, oldDef, layout );
@@ -300,6 +321,7 @@ public class Compaction implements AlgorithmStage{
 	public StageStatus backwardStep() {
 		if( actions.size() == 0 )
 		{
+            inside = false;
             placeNode.setSelected( false );
             placeLoopNode.setSelected( false );
 			return StageStatus.FINISHED;
@@ -322,4 +344,70 @@ public class Compaction implements AlgorithmStage{
         root.add( applyNode );
         return root;
     }
+
+    @Override
+    public StageStatus forwardStepOver() {
+        if( !inside )
+        {
+            CompactionState oldState = state;
+            StageStatus stage = StageStatus.UNFINISHED;
+            while( state == oldState && stage != StageStatus.FINISHED )
+                stage = forwardStep();
+            return stage;
+        }
+        else
+            return forwardStep();
+    }
+
+    @Override
+    public StageStatus forwardStepOut() {
+        if( !inside )
+        {
+            StageStatus status = StageStatus.UNFINISHED;
+            while( status != StageStatus.FINISHED )
+                status = forwardStep();
+            return status;
+        }
+        else
+        {
+            CompactionState oldState = state;
+            StageStatus stage = StageStatus.UNFINISHED;
+            while( state == oldState && stage != StageStatus.FINISHED )
+                stage = forwardStep();
+            return stage;
+        }
+    }
+
+    @Override
+    public StageStatus backwardStepOver() {
+        if( !inside )
+        {
+            CompactionState oldState = state;
+            StageStatus stage = StageStatus.UNFINISHED;
+            while( state == oldState && stage != StageStatus.FINISHED )
+                stage = backwardStep();
+            return stage;
+        }
+        else
+            return backwardStep();
+    }
+
+    @Override
+    public StageStatus backwardStepOut() {
+        if( !inside )
+        {
+            StageStatus status = StageStatus.UNFINISHED;
+            while( status != StageStatus.FINISHED )
+                status = backwardStep();
+            return status;
+        }
+        else
+        {
+            CompactionState oldState = state;
+            StageStatus stage = StageStatus.UNFINISHED;
+            while( state == oldState && stage != StageStatus.FINISHED )
+                stage = backwardStep();
+            return stage;
+        }
+    }
 }

+ 26 - 0
src/bk/ConflictDetection.java

@@ -125,4 +125,30 @@ public class ConflictDetection implements AlgorithmStage {
         root.add( loopNode );
         return root;
     }
+
+    @Override
+    public StageStatus forwardStepOver() {
+        return forwardStep();
+    }
+
+    @Override
+    public StageStatus forwardStepOut() {
+        StageStatus status = StageStatus.UNFINISHED;
+        while( status != StageStatus.FINISHED )
+            status = forwardStep();
+        return status;
+    }
+
+    @Override
+    public StageStatus backwardStepOver() {
+        return backwardStep();
+    }
+
+    @Override
+    public StageStatus backwardStepOut() {
+        StageStatus status = StageStatus.UNFINISHED;
+        while( status != StageStatus.FINISHED )
+            status = backwardStep();
+        return status;
+    }
 }

+ 143 - 39
src/bk/ExtremalLayoutCalc.java

@@ -1,5 +1,7 @@
 package bk;
 
+import java.lang.reflect.InvocationTargetException;
+
 import animation.AlgorithmStage;
 import animation.PseudoCodeNode;
 import graph.LayeredGraphNode;
@@ -32,6 +34,7 @@ public class ExtremalLayoutCalc implements AlgorithmStage {
 	private PseudoCodeNode bcNode;
 	private PseudoCodeNode cpNode;
 	private LayoutType type;
+	private boolean inside;
 	
 	
 	public ExtremalLayoutCalc( LayoutType typ, LayeredGraphNode graph )
@@ -40,53 +43,17 @@ public class ExtremalLayoutCalc implements AlgorithmStage {
 		status = LayoutState.BLOCK_CALCULATION;
 		bc = new BlockCalc( graph, typ );
 		cp = new Compaction( graph, typ );
+		inside = false;
 	}
 	
 	@Override
 	public StageStatus forwardStep() {
-		if( status == LayoutState.BLOCK_CALCULATION )
-		{
-		    bcNode.setSelected( true );
-			if( bc.forwardStep() == StageStatus.FINISHED )
-			{
-	            bcNode.setSelected( false );
-	            cpNode.setSelected( true );
-				status = LayoutState.COMPACTION;
-			}
-			return StageStatus.UNFINISHED;
-		}
-		if( status == LayoutState.COMPACTION )
-		{
-			if( cp.forwardStep() == StageStatus.FINISHED )
-			{
-			    cpNode.setSelected( false );
-			    return StageStatus.FINISHED;
-			}
-		}
-		return StageStatus.UNFINISHED;
+		return forward( "forwardStep" );
 	}
 
 	@Override
 	public StageStatus backwardStep() {
-		if( status == LayoutState.BLOCK_CALCULATION )
-		{
-            bcNode.setSelected( true );
-			if( bc.backwardStep() == StageStatus.FINISHED )
-			{
-	            bcNode.setSelected( false );
-                return StageStatus.FINISHED;
-			}
-		}
-		if( status == LayoutState.COMPACTION )
-		{
-            cpNode.setSelected( true );
-			if( cp.backwardStep() == StageStatus.FINISHED )
-			{
-	            cpNode.setSelected( false );
-				status = LayoutState.BLOCK_CALCULATION;
-			}
-		}
-		return StageStatus.UNFINISHED;
+		return backward( "backwardStep" );
 	}
 
     @Override
@@ -105,4 +72,141 @@ public class ExtremalLayoutCalc implements AlgorithmStage {
         pseudoCode.add( cpNode );
         return pseudoCode;
     }
+
+    @Override
+    public StageStatus forwardStepOver() {
+        if( !inside )
+        {
+            LayoutState oldState = status;
+            StageStatus stage = StageStatus.UNFINISHED;
+            while( status == oldState && stage != StageStatus.FINISHED )
+                stage = forwardStep();
+            return stage;
+        }
+        else
+            return forward( "forwardStepOver" );
+    }
+
+    @Override
+    public StageStatus forwardStepOut() {
+        if( !inside )
+        {
+            StageStatus status = StageStatus.UNFINISHED;
+            while( status != StageStatus.FINISHED )
+                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.FINISHED )
+                stage = backwardStep();
+            return stage;
+        }
+        else
+            return backward( "backwardStepOver" );
+    }
+
+    @Override
+    public StageStatus backwardStepOut() {
+        if( !inside )
+        {
+            StageStatus status = StageStatus.UNFINISHED;
+            while( status != StageStatus.FINISHED )
+                status = backwardStep();
+            return status;
+        }
+        else
+            return backward( "backwardStepOut" );
+    }
+    
+    private StageStatus forward( String fName )
+    {
+        try {
+            if( status == LayoutState.BLOCK_CALCULATION )
+            {
+                bcNode.setSelected( true );
+                if( (StageStatus)(BlockCalc.class.getMethod( fName ).invoke( bc ) ) == StageStatus.FINISHED )
+                {
+                    inside = false;
+                    bcNode.setSelected( false );
+                    cpNode.setSelected( true );
+                    status = LayoutState.COMPACTION;
+                }
+                else
+                    inside = true;
+                return StageStatus.UNFINISHED;
+            }
+            if( status == LayoutState.COMPACTION )
+            {
+                if( (StageStatus)(Compaction.class.getMethod( fName ).invoke( cp ) ) == StageStatus.FINISHED )
+                {
+                    inside = false;
+                    cpNode.setSelected( false );
+                    return StageStatus.FINISHED;
+                }
+                else
+                    inside = true;
+            }
+        } 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();
+        }
+        return StageStatus.UNFINISHED;
+    }
+    
+    private StageStatus backward( String fName )
+    {
+        try {
+            if( status == LayoutState.BLOCK_CALCULATION )
+            {
+                bcNode.setSelected( true );
+                if( (StageStatus)(BlockCalc.class.getMethod( fName ).invoke( bc ) ) == StageStatus.FINISHED )
+                {
+                    inside = false;
+                    bcNode.setSelected( false );
+                    return StageStatus.FINISHED;
+                }
+                else
+                    inside = true;
+            }
+            if( status == LayoutState.COMPACTION )
+            {
+                cpNode.setSelected( true );
+                if( (StageStatus)(Compaction.class.getMethod( fName ).invoke( cp ) ) == StageStatus.FINISHED )
+                {
+                    inside = false;
+                    cpNode.setSelected( false );
+                    status = LayoutState.BLOCK_CALCULATION;
+                }
+                else
+                    inside = true;
+            }
+        } 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();
+        }
+        return StageStatus.UNFINISHED;
+    }
 }

+ 68 - 38
src/view/MainView.java

@@ -3,6 +3,7 @@ package view;
 import java.awt.BorderLayout;
 import java.awt.Color;
 import java.awt.Dimension;
+import java.awt.Font;
 import java.awt.GridLayout;
 import java.awt.event.ActionEvent;
 import java.awt.event.ActionListener;
@@ -17,6 +18,7 @@ import javax.swing.JLabel;
 import javax.swing.JLayeredPane;
 import javax.swing.JPanel;
 import javax.swing.JScrollPane;
+import javax.swing.JTextArea;
 import javax.swing.JTextField;
 import javax.swing.JTree;
 import javax.swing.UIManager;
@@ -59,6 +61,7 @@ public class MainView {
     private JLabel delayText;
     private JTextField delay;
     public static JTree pseudoTree;
+    private LayeredGraphNode graph;
 	
 	private String strToLen( String s, int l )
 	{
@@ -71,12 +74,67 @@ public class MainView {
 		return s;
 	}
 	
+	private String debugInfo()
+	{
+	    String info = "Debug Information Table: \n";
+	    info += "_______________________________________________________________________________________________________________________________________________________________________________________________________________________\n";
+	    info += "|" + strToLen( "Top -> Bottom :> Left", 51 ) + "| |" + strToLen( "Top -> Bottom :> Right", 51 ) + "| |" + strToLen( "Bottom -> Top :> Left", 51 ) + "| |" + strToLen( "Bottom -> Top :> Right", 51 ) + "|\n";
+	    info += "|___________________________________________________| |___________________________________________________| |___________________________________________________| |___________________________________________________|\n";
+        info += "| Node | Shift | Sink | Root | Align |  x  |  xDef  | | Node | Shift | Sink | Root | Align |  x  |  xDef  | | Node | Shift | Sink | Root | Align |  x  |  xDef  | | Node | Shift | Sink | Root | Align |  x  |  xDef  |\n";
+        for( LayeredGraphNode n : graph.getContainedNodes() )
+        {
+            info += "|" + strToLen( n.getName(), 6 ) + 
+                    "|" + strToLen( n.getShift( LayoutType.TOP_BOTTOM_LEFT ) + "", 7 ) + 
+                    "|" + strToLen( n.getSink( LayoutType.TOP_BOTTOM_LEFT ).getName(), 6 ) + 
+                    "|" + strToLen( n.getRoot( LayoutType.TOP_BOTTOM_LEFT ).getName(), 6 ) + 
+                    "|" + strToLen( n.getAlignedTo( LayoutType.TOP_BOTTOM_LEFT ).getName(), 7 ) + 
+                    "|" + strToLen( n.getX( LayoutType.TOP_BOTTOM_LEFT ) + "", 5 ) + 
+                    "|" + strToLen( !n.isXUndefined( LayoutType.TOP_BOTTOM_LEFT ) + "", 8 ) + "| " +
+                    "|" + strToLen( n.getName(), 6 ) + 
+                    "|" + strToLen( n.getShift( LayoutType.TOP_BOTTOM_RIGHT ) + "", 7 ) + 
+                    "|" + strToLen( n.getSink( LayoutType.TOP_BOTTOM_RIGHT ).getName(), 6 ) + 
+                    "|" + strToLen( n.getRoot( LayoutType.TOP_BOTTOM_RIGHT ).getName(), 6 ) + 
+                    "|" + strToLen( n.getAlignedTo( LayoutType.TOP_BOTTOM_RIGHT ).getName(), 7 ) + 
+                    "|" + strToLen( n.getX( LayoutType.TOP_BOTTOM_RIGHT ) + "", 5 ) + 
+                    "|" + strToLen( !n.isXUndefined( LayoutType.TOP_BOTTOM_RIGHT ) + "", 8 ) + "| " +
+                    "|" + strToLen( n.getName(), 6 ) + 
+                    "|" + strToLen( n.getShift( LayoutType.BOTTOM_TOP_LEFT ) + "", 7 ) + 
+                    "|" + strToLen( n.getSink( LayoutType.BOTTOM_TOP_LEFT ).getName(), 6 ) + 
+                    "|" + strToLen( n.getRoot( LayoutType.BOTTOM_TOP_LEFT ).getName(), 6 ) + 
+                    "|" + strToLen( n.getAlignedTo( LayoutType.BOTTOM_TOP_LEFT ).getName(), 7 ) + 
+                    "|" + strToLen( n.getX( LayoutType.BOTTOM_TOP_LEFT ) + "", 5 ) + 
+                    "|" + strToLen( !n.isXUndefined( LayoutType.BOTTOM_TOP_LEFT ) + "", 8 ) + "| " +
+                    "|" + strToLen( n.getName(), 6 ) + 
+                    "|" + strToLen( n.getShift( LayoutType.BOTTOM_TOP_RIGHT ) + "", 7 ) + 
+                    "|" + strToLen( n.getSink( LayoutType.BOTTOM_TOP_RIGHT ).getName(), 6 ) + 
+                    "|" + strToLen( n.getRoot( LayoutType.BOTTOM_TOP_RIGHT ).getName(), 6 ) + 
+                    "|" + strToLen( n.getAlignedTo( LayoutType.BOTTOM_TOP_RIGHT ).getName(), 7 ) + 
+                    "|" + strToLen( n.getX( LayoutType.BOTTOM_TOP_RIGHT ) + "", 5 ) + 
+                    "|" + strToLen( !n.isXUndefined( LayoutType.BOTTOM_TOP_RIGHT ) + "", 8 ) + "|\n";
+        }
+        info += "-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------";
+        return info;
+	}
+	
+	private void showDebugInfo()
+	{
+	    JFrame debugFrame = new JFrame();
+	    JTextArea info = new JTextArea();
+	    info.setEditable( false );
+	    info.setFont( new Font( Font.MONOSPACED, Font.PLAIN, 11 ) );
+	    info.setText( debugInfo() );
+	    JScrollPane view = new JScrollPane( info );
+        debugFrame.add( view );
+	    debugFrame.setVisible( true );
+	}
+	
 	/**
 	 * Initialize the window and its contents.
 	 * @param graph the graph that is displayed in this window.
 	 */
 	public MainView( LayeredGraphNode graph )
 	{
+	    this.graph = graph;
         controller = new AnimationController();
         controller.setTimeBetween( 50 );
         BKNodePlacement algorithm = new BKNodePlacement( controller, graph );
@@ -182,6 +240,14 @@ public class MainView {
         });
         debug = new NiceButton( "debug" );
         debug.setLocation( 350, 10 );
+        debug.addActionListener( new ActionListener() {
+
+            @Override
+            public void actionPerformed(ActionEvent e) {
+                showDebugInfo();
+            }
+            
+        });
         generateRandom = new NiceButton( "generateRandom" );
         generateRandom.setLocation( 350, 60 );
         generateRandom.addActionListener( new ActionListener() {
@@ -271,43 +337,7 @@ public class MainView {
         		frame.validate();
         		if( e.getKeyCode() == KeyEvent.VK_D )
         		{
-        			System.out.println( "Debug Information Table: " );
-        			System.out.println( "_______________________________________________________________________________________________________________________________________________________________________________________________________________________" );
-        			System.out.println( "|" + strToLen( "Top -> Bottom :> Left", 51 ) + "| |" + strToLen( "Top -> Bottom :> Right", 51 ) + "| |" + strToLen( "Bottom -> Top :> Left", 51 ) + "| |" + strToLen( "Bottom -> Top :> Right", 51 ) + "|" );
-        			System.out.println( "|___________________________________________________| |___________________________________________________| |___________________________________________________| |___________________________________________________|" );
-        			System.out.println( "| Node | Shift | Sink | Root | Align |  x  |  xDef  | | Node | Shift | Sink | Root | Align |  x  |  xDef  | | Node | Shift | Sink | Root | Align |  x  |  xDef  | | Node | Shift | Sink | Root | Align |  x  |  xDef  |" );
-        			for( LayeredGraphNode n : graph.getContainedNodes() )
-        			{
-        				System.out.println( "|" + strToLen( n.getName(), 6 ) + 
-		        						    "|" + strToLen( n.getShift( LayoutType.TOP_BOTTOM_LEFT ) + "", 7 ) + 
-		        						    "|" + strToLen( n.getSink( LayoutType.TOP_BOTTOM_LEFT ).getName(), 6 ) + 
-		        						    "|" + strToLen( n.getRoot( LayoutType.TOP_BOTTOM_LEFT ).getName(), 6 ) + 
-		        						    "|" + strToLen( n.getAlignedTo( LayoutType.TOP_BOTTOM_LEFT ).getName(), 7 ) + 
-		        						    "|" + strToLen( n.getX( LayoutType.TOP_BOTTOM_LEFT ) + "", 5 ) + 
-		        						    "|" + strToLen( !n.isXUndefined( LayoutType.TOP_BOTTOM_LEFT ) + "", 8 ) + "| " +
-		        						    "|" + strToLen( n.getName(), 6 ) + 
-		        						    "|" + strToLen( n.getShift( LayoutType.TOP_BOTTOM_RIGHT ) + "", 7 ) + 
-		        						    "|" + strToLen( n.getSink( LayoutType.TOP_BOTTOM_RIGHT ).getName(), 6 ) + 
-		        						    "|" + strToLen( n.getRoot( LayoutType.TOP_BOTTOM_RIGHT ).getName(), 6 ) + 
-		        						    "|" + strToLen( n.getAlignedTo( LayoutType.TOP_BOTTOM_RIGHT ).getName(), 7 ) + 
-		        						    "|" + strToLen( n.getX( LayoutType.TOP_BOTTOM_RIGHT ) + "", 5 ) + 
-		        						    "|" + strToLen( !n.isXUndefined( LayoutType.TOP_BOTTOM_RIGHT ) + "", 8 ) + "| " +
-		        						    "|" + strToLen( n.getName(), 6 ) + 
-		        						    "|" + strToLen( n.getShift( LayoutType.BOTTOM_TOP_LEFT ) + "", 7 ) + 
-		        						    "|" + strToLen( n.getSink( LayoutType.BOTTOM_TOP_LEFT ).getName(), 6 ) + 
-		        						    "|" + strToLen( n.getRoot( LayoutType.BOTTOM_TOP_LEFT ).getName(), 6 ) + 
-		        						    "|" + strToLen( n.getAlignedTo( LayoutType.BOTTOM_TOP_LEFT ).getName(), 7 ) + 
-		        						    "|" + strToLen( n.getX( LayoutType.BOTTOM_TOP_LEFT ) + "", 5 ) + 
-		        						    "|" + strToLen( !n.isXUndefined( LayoutType.BOTTOM_TOP_LEFT ) + "", 8 ) + "| " +
-		        						    "|" + strToLen( n.getName(), 6 ) + 
-		        						    "|" + strToLen( n.getShift( LayoutType.BOTTOM_TOP_RIGHT ) + "", 7 ) + 
-		        						    "|" + strToLen( n.getSink( LayoutType.BOTTOM_TOP_RIGHT ).getName(), 6 ) + 
-		        						    "|" + strToLen( n.getRoot( LayoutType.BOTTOM_TOP_RIGHT ).getName(), 6 ) + 
-		        						    "|" + strToLen( n.getAlignedTo( LayoutType.BOTTOM_TOP_RIGHT ).getName(), 7 ) + 
-		        						    "|" + strToLen( n.getX( LayoutType.BOTTOM_TOP_RIGHT ) + "", 5 ) + 
-		        						    "|" + strToLen( !n.isXUndefined( LayoutType.BOTTOM_TOP_RIGHT ) + "", 8 ) + "|");
-        			}
-        			System.out.println( "-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------" );
+        		    System.out.println( debugInfo() );
         		}
             }
 
@@ -351,7 +381,7 @@ public class MainView {
         menue.add( delayText );
         menue.add( delay );
         menue.add( treeView );
-        //menue.add( stepBackwardInto );
+        menue.add( stepBackwardInto );
         menue.add( stepBackwardOut );
         menue.add( runBackward );
 		frame.add( menue, BorderLayout.EAST );