|
@@ -1,9 +1,23 @@
|
|
package bk;
|
|
package bk;
|
|
|
|
|
|
|
|
+import java.awt.Color;
|
|
|
|
+import java.util.ArrayList;
|
|
|
|
+import java.util.Collections;
|
|
|
|
+import java.util.List;
|
|
|
|
+
|
|
import javax.swing.JTree;
|
|
import javax.swing.JTree;
|
|
|
|
|
|
|
|
+import animation.CodeLine;
|
|
|
|
+import animation.ControlFlow;
|
|
|
|
+import animation.Memory;
|
|
|
|
+import animation.Memory.MemoryType;
|
|
|
|
+import animation.Memory.ReadOnlyMemory;
|
|
import animation.PseudoCodeNode;
|
|
import animation.PseudoCodeNode;
|
|
|
|
+import codelines.DeclareVariable;
|
|
|
|
+import codelines.ForEachLoop;
|
|
import codelines.FunctionDefinition;
|
|
import codelines.FunctionDefinition;
|
|
|
|
+import codelines.SetVariable;
|
|
|
|
+import graph.LayeredGraphNode;
|
|
|
|
|
|
/**
|
|
/**
|
|
* The stage of the combination of the four extremal layouts.
|
|
* The stage of the combination of the four extremal layouts.
|
|
@@ -13,8 +27,199 @@ import codelines.FunctionDefinition;
|
|
public class Combine {
|
|
public class Combine {
|
|
|
|
|
|
public static PseudoCodeNode combine( JTree tree ) {
|
|
public static PseudoCodeNode combine( JTree tree ) {
|
|
- String[] vars = { "graph" };
|
|
|
|
- PseudoCodeNode root = new PseudoCodeNode( "function combine( graph )", vars, tree, new FunctionDefinition( vars ) );
|
|
|
|
|
|
+ String[] vars = { "graph", "l", "l_min", "v", "positions" };
|
|
|
|
+ @SuppressWarnings("serial")
|
|
|
|
+ PseudoCodeNode root = new PseudoCodeNode( "function combine( graph )", vars, tree, new FunctionDefinition( new String[]{ "graph" } ) ){
|
|
|
|
+ @Override
|
|
|
|
+ public String getDebugOutput( Memory m )
|
|
|
|
+ {
|
|
|
|
+ if( m.isSomewhereDefined( "v", MemoryType.LOCAL ) )
|
|
|
|
+ m.<LayeredGraphNode>read( "v", MemoryType.LOCAL).setSelected( null );
|
|
|
|
+ return super.getDebugOutput( m );
|
|
|
|
+ }
|
|
|
|
+ };
|
|
|
|
+ root.add( new PseudoCodeNode( "-- Align all Layouts to the one with the smallest width --", vars, tree, new CodeLine() {
|
|
|
|
+ @Override
|
|
|
|
+ public ControlFlow runForward(Memory m) {
|
|
|
|
+ LayeredGraphNode graph = m.read( "graph", MemoryType.LOCAL );
|
|
|
|
+ if( graph.parent() == null )
|
|
|
|
+ graph.setColor( Color.BLACK, null );
|
|
|
|
+ actions.add( (Memory mem) -> {
|
|
|
|
+ if( graph.parent() == null )
|
|
|
|
+ graph.setColor( null, null );
|
|
|
|
+ });
|
|
|
|
+ return null;
|
|
|
|
+ }
|
|
|
|
+ }));
|
|
|
|
+ PseudoCodeNode firstLoop = new PseudoCodeNode( "foreach l in ['DOWN_RIGHT', 'DOWN_LEFT', 'UP_RIGHT', 'UP_LEFT'] do", vars, tree, new ForEachLoop<String>( "l" ) {
|
|
|
|
+ @Override
|
|
|
|
+ protected List<String> list(ReadOnlyMemory m) {
|
|
|
|
+ ArrayList< String > list = new ArrayList<String>();
|
|
|
|
+ list.add( "DOWN_RIGHT" );
|
|
|
|
+ list.add( "DOWN_LEFT" );
|
|
|
|
+ list.add( "UP_RIGHT" );
|
|
|
|
+ list.add( "UP_LEFT" );
|
|
|
|
+ return list;
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ root.add( firstLoop );
|
|
|
|
+ firstLoop.add( new PseudoCodeNode( "min[l] = minimum x coordinate in l;", vars, tree, new CodeLine() {
|
|
|
|
+ @Override
|
|
|
|
+ public ControlFlow runForward(Memory m) {
|
|
|
|
+ String layout = m.read( "l", MemoryType.LOCAL );
|
|
|
|
+ m.declare( "min[" + layout + "]", calcMinX( m.read( "graph", MemoryType.LOCAL ), LayoutType.fromString( layout ) ), MemoryType.GLOBAL );
|
|
|
|
+ actions.add( (Memory mem) -> {
|
|
|
|
+ mem.undeclare( "min[" + layout + "]", MemoryType.GLOBAL );
|
|
|
|
+ });
|
|
|
|
+ return new ControlFlow( ControlFlow.STEP_OVER );
|
|
|
|
+ }
|
|
|
|
+ }));
|
|
|
|
+ firstLoop.add( new PseudoCodeNode( "max[l] = maximum x coordinate in l;", vars, tree, new CodeLine() {
|
|
|
|
+ @Override
|
|
|
|
+ public ControlFlow runForward(Memory m) {
|
|
|
|
+ String layout = m.read( "l", MemoryType.LOCAL );
|
|
|
|
+ m.declare( "max[" + layout + "]", calcMaxX( m.read( "graph", MemoryType.LOCAL ), LayoutType.fromString( layout ) ), MemoryType.GLOBAL );
|
|
|
|
+ actions.add( (Memory mem) -> {
|
|
|
|
+ mem.undeclare( "max[" + layout + "]", MemoryType.GLOBAL );
|
|
|
|
+ });
|
|
|
|
+ return new ControlFlow( ControlFlow.STEP_OVER );
|
|
|
|
+ }
|
|
|
|
+ }));
|
|
|
|
+ firstLoop.add( new PseudoCodeNode( "width[l] = max[l] - min[l];", vars, tree, new CodeLine() {
|
|
|
|
+ @Override
|
|
|
|
+ public ControlFlow runForward(Memory m) {
|
|
|
|
+ String layout = m.read( "l", MemoryType.LOCAL );
|
|
|
|
+ m.declare( "height[" + layout + "]", m.<Integer>read( "max[" + layout + "]", MemoryType.LOCAL ) - m.<Integer>read( "min[" + layout + "]", MemoryType.LOCAL ), MemoryType.GLOBAL );
|
|
|
|
+ actions.add( (Memory mem) -> {
|
|
|
|
+ mem.undeclare( "width[" + layout + "]", MemoryType.GLOBAL );
|
|
|
|
+ });
|
|
|
|
+ return new ControlFlow( ControlFlow.STEP_OVER );
|
|
|
|
+ }
|
|
|
|
+ }));
|
|
|
|
+ root.add( new PseudoCodeNode( "l_min = l with width[l] == min(width);", vars, tree, new DeclareVariable<String>( "l_min" ) {
|
|
|
|
+ @Override
|
|
|
|
+ protected String value(ReadOnlyMemory m) {
|
|
|
|
+ String min = "DOWN_RIGHT";
|
|
|
|
+ int minW = m.read( "width[DOWN_RIGHT]", MemoryType.GLOBAL );
|
|
|
|
+ for( String l : new String[]{ "DOWN_LEFT", "UP_RIGHT", "UP_LEFT" } )
|
|
|
|
+ {
|
|
|
|
+ if( minW > m.<Integer>read( "width[" + l + "]", MemoryType.GLOBAL ) )
|
|
|
|
+ {
|
|
|
|
+ minW = m.<Integer>read( "width[" + l + "]", MemoryType.GLOBAL );
|
|
|
|
+ min = l;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ return min;
|
|
|
|
+ }
|
|
|
|
+ }));
|
|
|
|
+ PseudoCodeNode secondLoop = new PseudoCodeNode( "foreach l in ['DOWN_RIGHT', 'DOWN_LEFT', 'UP_RIGHT', 'UP_LEFT'] do", vars, tree, new ForEachLoop<String>( "l" ) {
|
|
|
|
+ @Override
|
|
|
|
+ protected List<String> list(ReadOnlyMemory m) {
|
|
|
|
+ ArrayList< String > list = new ArrayList<String>();
|
|
|
|
+ list.add( "DOWN_RIGHT" );
|
|
|
|
+ list.add( "DOWN_LEFT" );
|
|
|
|
+ list.add( "UP_RIGHT" );
|
|
|
|
+ list.add( "UP_LEFT" );
|
|
|
|
+ return list;
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ root.add( secondLoop );
|
|
|
|
+ secondLoop.add( new PseudoCodeNode( "shift[l] = l.contains('RIGHT') ? min[l_min] - min[l] : max[l_min] - max[l];", vars, tree, new CodeLine() {
|
|
|
|
+ @Override
|
|
|
|
+ public ControlFlow runForward(Memory m) {
|
|
|
|
+ String layout = m.read( "l", MemoryType.LOCAL );
|
|
|
|
+ String lMin = m.read( "l_min", MemoryType.LOCAL );
|
|
|
|
+ if( layout.contains( "RIGHT" ) )
|
|
|
|
+ m.declare( "shift[" + layout + "]", m.<Integer>read( "min[" + lMin + "]", MemoryType.LOCAL ) - m.<Integer>read( "min[" + layout + "]", MemoryType.LOCAL ), MemoryType.GLOBAL );
|
|
|
|
+ else
|
|
|
|
+ m.declare( "shift[" + layout + "]", m.<Integer>read( "max[" + lMin + "]", MemoryType.LOCAL ) - m.<Integer>read( "max[" + layout + "]", MemoryType.LOCAL ), MemoryType.GLOBAL );
|
|
|
|
+ actions.add( (Memory mem) -> {
|
|
|
|
+ mem.undeclare( "shift[" + layout + "]", MemoryType.GLOBAL );
|
|
|
|
+ });
|
|
|
|
+ return new ControlFlow( ControlFlow.STEP_OVER );
|
|
|
|
+ }
|
|
|
|
+ }));
|
|
|
|
+ PseudoCodeNode thirdLoop = new PseudoCodeNode( "foreach v in graph do", vars, tree, new ForEachLoop<LayeredGraphNode>( "v" ) {
|
|
|
|
+ @Override
|
|
|
|
+ protected List<LayeredGraphNode> list(ReadOnlyMemory m) {
|
|
|
|
+ return m.<LayeredGraphNode>read( "graph", MemoryType.LOCAL ).getContainedNodes();
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ root.add( thirdLoop );
|
|
|
|
+ thirdLoop.add( new PseudoCodeNode( "positions = [];", vars, tree, new DeclareVariable<ArrayList<Integer>>( "positions") {
|
|
|
|
+ @Override
|
|
|
|
+ protected ArrayList<Integer> value(ReadOnlyMemory m) {
|
|
|
|
+ return new ArrayList<Integer>();
|
|
|
|
+ }
|
|
|
|
+ }));
|
|
|
|
+ PseudoCodeNode innerLoop = new PseudoCodeNode( "foreach l in ['DOWN_RIGHT', 'DOWN_LEFT', 'UP_RIGHT', 'UP_LEFT'] do", vars, tree, new ForEachLoop<String>( "l" ) {
|
|
|
|
+ @Override
|
|
|
|
+ protected List<String> list(ReadOnlyMemory m) {
|
|
|
|
+ ArrayList< String > list = new ArrayList<String>();
|
|
|
|
+ list.add( "DOWN_RIGHT" );
|
|
|
|
+ list.add( "DOWN_LEFT" );
|
|
|
|
+ list.add( "UP_RIGHT" );
|
|
|
|
+ list.add( "UP_LEFT" );
|
|
|
|
+ return list;
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ innerLoop.add( new PseudoCodeNode( "positions.add(x[v] in l);", vars, tree, new CodeLine() {
|
|
|
|
+ @Override
|
|
|
|
+ public ControlFlow runForward(Memory m) {
|
|
|
|
+ String layout = m.read( "l", MemoryType.LOCAL );
|
|
|
|
+ ArrayList<Integer> positions = m.read( "positions", MemoryType.LOCAL );
|
|
|
|
+ positions.add( (int)m.<LayeredGraphNode>read( "v", MemoryType.LOCAL ).getX( LayoutType.fromString( layout ) ) + m.<Integer>read( "shift[" + layout + "]", MemoryType.GLOBAL ) );
|
|
|
|
+ actions.add( (Memory mem) -> {
|
|
|
|
+ positions.remove( positions.size() - 1 );
|
|
|
|
+ });
|
|
|
|
+ return new ControlFlow( ControlFlow.STEP_OVER );
|
|
|
|
+ }
|
|
|
|
+ }));
|
|
|
|
+ thirdLoop.add( innerLoop );
|
|
|
|
+ thirdLoop.add( new PseudoCodeNode( "positions = sort( positions );", vars, tree, new SetVariable<ArrayList<Integer>>( "positions" ) {
|
|
|
|
+ @Override
|
|
|
|
+ public ArrayList<Integer> value(ReadOnlyMemory m) {
|
|
|
|
+ ArrayList<Integer> positions = m.read( "positions", MemoryType.LOCAL );
|
|
|
|
+ ArrayList<Integer> neu = new ArrayList<Integer>();
|
|
|
|
+ for( int p : positions )
|
|
|
|
+ neu.add( p );
|
|
|
|
+ Collections.sort( neu );
|
|
|
|
+ return neu;
|
|
|
|
+ }
|
|
|
|
+ }));
|
|
|
|
+ thirdLoop.add( new PseudoCodeNode( "x[v] = (positions[1]+positions[2]) / 2;", vars, tree, new CodeLine() {
|
|
|
|
+ @Override
|
|
|
|
+ public ControlFlow runForward(Memory m) {
|
|
|
|
+ ArrayList<Integer> positions = m.read( "positions", MemoryType.LOCAL );
|
|
|
|
+ LayeredGraphNode v = m.read( "v", MemoryType.LOCAL );
|
|
|
|
+ double old = v.getX( LayoutType.COMBINED );
|
|
|
|
+ v.setX( (positions.get( 1 ) + positions.get( 2 )) / 2.0, true, LayoutType.COMBINED );
|
|
|
|
+ actions.add( (Memory mem) -> {
|
|
|
|
+ v.setX( old, false, LayoutType.COMBINED );
|
|
|
|
+ });
|
|
|
|
+ return new ControlFlow( ControlFlow.STEP_OVER );
|
|
|
|
+ }
|
|
|
|
+ }));
|
|
return root;
|
|
return root;
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+ private static int calcMinX( LayeredGraphNode graph, 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 static int calcMaxX( LayeredGraphNode graph, 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;
|
|
|
|
+ }
|
|
}
|
|
}
|