MainView.java 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769
  1. package view;
  2. import java.awt.BorderLayout;
  3. import java.awt.Dimension;
  4. import java.awt.Font;
  5. import java.awt.GridLayout;
  6. import java.awt.event.ActionEvent;
  7. import java.awt.event.ActionListener;
  8. import java.awt.event.ComponentAdapter;
  9. import java.awt.event.ComponentEvent;
  10. import java.awt.event.ComponentListener;
  11. import java.awt.event.KeyEvent;
  12. import java.awt.event.MouseAdapter;
  13. import java.awt.event.MouseEvent;
  14. import java.beans.PropertyChangeEvent;
  15. import java.beans.PropertyChangeListener;
  16. import javax.swing.JButton;
  17. import javax.swing.JFileChooser;
  18. import javax.swing.JFrame;
  19. import javax.swing.JLabel;
  20. import javax.swing.JLayeredPane;
  21. import javax.swing.JMenu;
  22. import javax.swing.JMenuItem;
  23. import javax.swing.JPanel;
  24. import javax.swing.JPopupMenu;
  25. import javax.swing.JScrollPane;
  26. import javax.swing.JSplitPane;
  27. import javax.swing.JTextArea;
  28. import javax.swing.JTextField;
  29. import javax.swing.JTree;
  30. import javax.swing.border.BevelBorder;
  31. import javax.swing.filechooser.FileNameExtensionFilter;
  32. import javax.swing.tree.DefaultTreeModel;
  33. import javax.swing.tree.TreePath;
  34. import org.eclipse.elk.graph.ElkNode;
  35. import bk.BKNodePlacement;
  36. import bk.BKNodePlacement.Stage;
  37. import bk.LayoutType;
  38. import graph.LayeredGraphEdge;
  39. import graph.LayeredGraphNode;
  40. import graph.LayeredNode;
  41. import graph.io.Reader;
  42. import graph.io.Writer;
  43. import lib.SimpleNodePlacement;
  44. import lib.TextLayoutHelper;
  45. import processor.Action;
  46. import processor.ProcessController;
  47. import processor.PseudoCodeNode;
  48. import processor.PseudoCodeProcessor;
  49. /**
  50. * The main window of the application.
  51. * There should only be one instance of this class at the same time.
  52. * The JFrame of that single instance can be accessed by the static field {code MainView.frame}.
  53. * @author kolja
  54. *
  55. */
  56. public class MainView {
  57. /**
  58. * The 'frame' of the main window.
  59. * The reason why there can only be one instance of this class.
  60. */
  61. private static int frameCounter = 0;
  62. /**
  63. * Random Graph Generator should olny exist once for all windows (so the values will be stored)
  64. */
  65. private static final RandomGraphDialog randomDialog = new RandomGraphDialog();
  66. private JFrame frame;
  67. private ProcessController controller;
  68. private JButton stepForward;
  69. private JButton stepForwardInto;
  70. private JButton stepForwardOut;
  71. private JButton stepBackward;
  72. private JButton stepBackwardInto;
  73. private JButton stepBackwardOut;
  74. private JButton runForward;
  75. private JButton runBackward;
  76. private JButton pause;
  77. private JButton load;
  78. private JButton save;
  79. private JButton debug;
  80. private JButton options;
  81. private JButton randomGraph;
  82. private JLabel delayText;
  83. private JTextField delay;
  84. private JTree pseudoTree;
  85. private LayeredGraphNode graph;
  86. private OptionsDialog optionsDialog;
  87. private String debugInfo()
  88. {
  89. String info = "Debug Information Table: \n";
  90. info += "_______________________________________________________________________________________________________________________________________________________________________________________________________________________\n";
  91. info += "|" + TextLayoutHelper.strToLen( "Top -> Bottom :> Left", 51 ) + "| |" + TextLayoutHelper.strToLen( "Top -> Bottom :> Right", 51 ) + "| |" + TextLayoutHelper.strToLen( "Bottom -> Top :> Left", 51 ) + "| |" + TextLayoutHelper.strToLen( "Bottom -> Top :> Right", 51 ) + "|\n";
  92. info += "|___________________________________________________| |___________________________________________________| |___________________________________________________| |___________________________________________________|\n";
  93. 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";
  94. for( LayeredGraphNode n : graph.getContainedNodes() )
  95. {
  96. info += "|" + TextLayoutHelper.strToLen( n.toString(), 6 ) +
  97. "|" + TextLayoutHelper.strToLen( n.getShift( LayoutType.LEFTMOST_UPPER ) + "", 7 ) +
  98. "|" + TextLayoutHelper.strToLen( n.getSink( LayoutType.LEFTMOST_UPPER ).toString(), 6 ) +
  99. "|" + TextLayoutHelper.strToLen( n.getRoot( LayoutType.LEFTMOST_UPPER ).toString(), 6 ) +
  100. "|" + TextLayoutHelper.strToLen( n.getAlign( LayoutType.LEFTMOST_UPPER ).toString(), 7 ) +
  101. "|" + TextLayoutHelper.strToLen( n.getX( LayoutType.LEFTMOST_UPPER ) + "", 5 ) +
  102. "|" + TextLayoutHelper.strToLen( !n.isXUndefined( LayoutType.LEFTMOST_UPPER ) + "", 8 ) + "| " +
  103. "|" + TextLayoutHelper.strToLen( n.toString(), 6 ) +
  104. "|" + TextLayoutHelper.strToLen( n.getShift( LayoutType.RIGHTMOST_UPPER ) + "", 7 ) +
  105. "|" + TextLayoutHelper.strToLen( n.getSink( LayoutType.RIGHTMOST_UPPER ).toString(), 6 ) +
  106. "|" + TextLayoutHelper.strToLen( n.getRoot( LayoutType.RIGHTMOST_UPPER ).toString(), 6 ) +
  107. "|" + TextLayoutHelper.strToLen( n.getAlign( LayoutType.RIGHTMOST_UPPER ).toString(), 7 ) +
  108. "|" + TextLayoutHelper.strToLen( n.getX( LayoutType.RIGHTMOST_UPPER ) + "", 5 ) +
  109. "|" + TextLayoutHelper.strToLen( !n.isXUndefined( LayoutType.RIGHTMOST_UPPER ) + "", 8 ) + "| " +
  110. "|" + TextLayoutHelper.strToLen( n.toString(), 6 ) +
  111. "|" + TextLayoutHelper.strToLen( n.getShift( LayoutType.LEFTMOST_LOWER ) + "", 7 ) +
  112. "|" + TextLayoutHelper.strToLen( n.getSink( LayoutType.LEFTMOST_LOWER ).toString(), 6 ) +
  113. "|" + TextLayoutHelper.strToLen( n.getRoot( LayoutType.LEFTMOST_LOWER ).toString(), 6 ) +
  114. "|" + TextLayoutHelper.strToLen( n.getAlign( LayoutType.LEFTMOST_LOWER ).toString(), 7 ) +
  115. "|" + TextLayoutHelper.strToLen( n.getX( LayoutType.LEFTMOST_LOWER ) + "", 5 ) +
  116. "|" + TextLayoutHelper.strToLen( !n.isXUndefined( LayoutType.LEFTMOST_LOWER ) + "", 8 ) + "| " +
  117. "|" + TextLayoutHelper.strToLen( n.toString(), 6 ) +
  118. "|" + TextLayoutHelper.strToLen( n.getShift( LayoutType.RIGHTMOST_LOWER ) + "", 7 ) +
  119. "|" + TextLayoutHelper.strToLen( n.getSink( LayoutType.RIGHTMOST_LOWER ).toString(), 6 ) +
  120. "|" + TextLayoutHelper.strToLen( n.getRoot( LayoutType.RIGHTMOST_LOWER ).toString(), 6 ) +
  121. "|" + TextLayoutHelper.strToLen( n.getAlign( LayoutType.RIGHTMOST_LOWER ).toString(), 7 ) +
  122. "|" + TextLayoutHelper.strToLen( n.getX( LayoutType.RIGHTMOST_LOWER ) + "", 5 ) +
  123. "|" + TextLayoutHelper.strToLen( !n.isXUndefined( LayoutType.RIGHTMOST_LOWER ) + "", 8 ) + "|\n";
  124. }
  125. info += "-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------";
  126. return info;
  127. }
  128. private void showDebugInfo()
  129. {
  130. JFrame debugFrame = new JFrame();
  131. JTextArea info = new JTextArea();
  132. info.setEditable( false );
  133. info.setFont( new Font( Font.MONOSPACED, Font.PLAIN, 11 ) );
  134. String infoS = debugInfo();
  135. info.setText( infoS );
  136. JScrollPane view = new JScrollPane( info );
  137. debugFrame.add( view );
  138. debugFrame.setSize( frame.getWidth(), frame.getHeight() );
  139. debugFrame.setVisible( true );
  140. if (infoS.trim().equals("")) {
  141. System.out.println( "" );
  142. System.out.println( "Debug info:" );
  143. System.out.println( infoS );
  144. System.out.println( "" );
  145. }
  146. }
  147. public MainView( ElkNode graph )
  148. {
  149. this( LayeredNode.convertToLayeredGraph( graph ) );
  150. }
  151. /**
  152. * Initialize the window and its contents.
  153. * There is good reason not to split up this method to smaller methods:
  154. * Imagine a tree with a fixed number of nodes, but limited degree of branching.
  155. * The the height of the tree is at least inversely proportional to the degree of branching.
  156. * This means halving the maximum method size by splitting methods would make the call stack twice as high
  157. * and this way debugging twice as time-consuming.
  158. * @param graph the graph that is displayed in this window.
  159. */
  160. public MainView( LayeredGraphNode graph )
  161. {
  162. graph.setColor( null, null );
  163. frameCounter++;
  164. this.graph = graph;
  165. frame = new JFrame( "NodeShuffler" );
  166. frame.addWindowListener(new java.awt.event.WindowAdapter() {
  167. @Override
  168. public void windowClosing(java.awt.event.WindowEvent windowEvent) {
  169. frameCounter--;
  170. if( frameCounter == 0 )
  171. System.exit( 0 );
  172. }
  173. });
  174. // Create Pseudo Code and Processor
  175. BKNodePlacement algorithm = new BKNodePlacement();
  176. pseudoTree = new JTree();
  177. PseudoCodeNode tree = algorithm.createPseudocodeTree( pseudoTree );
  178. PseudoCodeProcessor processor = new PseudoCodeProcessor( tree, graph, frame );
  179. controller = processor.getController();
  180. // Create Menu GUI
  181. stepForward = new NiceButton( "stepForward" );
  182. stepForward.setLocation( 10, 10 );
  183. stepForward.setMnemonic( KeyEvent.VK_DOWN );
  184. stepForward.setToolTipText( "Forward step over (alt + down arrow key)" );
  185. stepForward.addActionListener( new ActionListener() {
  186. @Override
  187. public void actionPerformed(ActionEvent e) {
  188. controller.setContinuous( false );
  189. controller.setNextAction( Action.FORWARD_OVER );
  190. }
  191. });
  192. stepForwardInto = new NiceButton( "stepForwardInto" );
  193. stepForwardInto.setLocation( 60, 10 );
  194. stepForwardInto.setMnemonic( KeyEvent.VK_RIGHT );
  195. stepForwardInto.setToolTipText( "Forward step into (alt + right arrow key)" );
  196. stepForwardInto.addActionListener( new ActionListener() {
  197. @Override
  198. public void actionPerformed(ActionEvent e) {
  199. controller.setContinuous( false );
  200. controller.setNextAction( Action.FORWARD );
  201. }
  202. });
  203. stepForwardOut = new NiceButton( "stepForwardOut" );
  204. stepForwardOut.setLocation( 110, 10 );
  205. stepForwardOut.setMnemonic( KeyEvent.VK_PAGE_DOWN );
  206. stepForwardOut.setToolTipText( "Forward step out (alt + page down key)" );
  207. stepForwardOut.addActionListener( new ActionListener() {
  208. @Override
  209. public void actionPerformed(ActionEvent e) {
  210. controller.setContinuous( false );
  211. controller.setNextAction( Action.FORWARD_OUT );
  212. }
  213. });
  214. runForward = new NiceButton( "runForward" );
  215. runForward.setLocation( 160, 10 );
  216. runForward.setMnemonic( KeyEvent.VK_P );
  217. runForward.setToolTipText( "Run forwards (alt + p)" );
  218. runForward.addActionListener( new ActionListener() {
  219. @Override
  220. public void actionPerformed(ActionEvent e) {
  221. controller.setContinuous( true );
  222. controller.setNextAction( Action.FORWARD );
  223. }
  224. });
  225. runBackward = new NiceButton( "runBackward" );
  226. runBackward.setLocation( 160, 60 );
  227. runBackward.setMnemonic( KeyEvent.VK_R );
  228. runBackward.setToolTipText( "Run backwards (alt + r)" );
  229. runBackward.addActionListener( new ActionListener() {
  230. @Override
  231. public void actionPerformed(ActionEvent e) {
  232. controller.setContinuous( true );
  233. controller.setNextAction( Action.BACKWARD );
  234. }
  235. });
  236. options = new NiceButton( "settings" );
  237. options.setLocation( 210, 60 );
  238. options.setMnemonic( KeyEvent.VK_O );
  239. options.setToolTipText( "Preferences (alt + o)" );
  240. options.addActionListener( new ActionListener() {
  241. @Override
  242. public void actionPerformed(ActionEvent e) {
  243. optionsDialog.setVisible( true );
  244. }
  245. });
  246. stepBackward = new NiceButton( "stepBackward" );
  247. stepBackward.setLocation( 10, 60 );
  248. stepBackward.setMnemonic( KeyEvent.VK_UP );
  249. stepBackward.setToolTipText( "Backward step over (alt + up arrow key)" );
  250. stepBackward.addActionListener( new ActionListener() {
  251. @Override
  252. public void actionPerformed(ActionEvent e) {
  253. controller.setContinuous( false );
  254. controller.setNextAction( Action.BACKWARD_OVER );
  255. }
  256. });
  257. stepBackwardInto = new NiceButton( "stepBackwardInto" );
  258. stepBackwardInto.setLocation( 60, 60 );
  259. stepBackwardInto.setMnemonic( KeyEvent.VK_LEFT );
  260. stepBackwardInto.setToolTipText( "Backward step into (alt + left arrow key)" );
  261. stepBackwardInto.addActionListener( new ActionListener() {
  262. @Override
  263. public void actionPerformed(ActionEvent e) {
  264. controller.setContinuous( false );
  265. controller.setNextAction( Action.BACKWARD );
  266. }
  267. });
  268. stepBackwardOut = new NiceButton( "stepBackwardOut" );
  269. stepBackwardOut.setLocation( 110, 60 );
  270. stepBackwardOut.setMnemonic( KeyEvent.VK_PAGE_UP );
  271. stepBackwardOut.setToolTipText( "Backward step out (alt + page up)" );
  272. stepBackwardOut.addActionListener( new ActionListener() {
  273. @Override
  274. public void actionPerformed(ActionEvent e) {
  275. controller.setContinuous( false );
  276. controller.setNextAction( Action.BACKWARD_OUT );
  277. }
  278. });
  279. pause = new NiceButton( "pause" );
  280. pause.setLocation( 210, 10 );
  281. pause.setMnemonic( KeyEvent.VK_PAUSE );
  282. pause.setToolTipText( "Pause (alt + pause)" );
  283. pause.addActionListener( new ActionListener() {
  284. @Override
  285. public void actionPerformed(ActionEvent e) {
  286. controller.setContinuous( false );
  287. }
  288. });
  289. debug = new NiceButton( "debug" );
  290. debug.setLocation( 360, 10 );
  291. debug.setMnemonic( KeyEvent.VK_D );
  292. debug.setToolTipText( "Show debug info (alt + d)" );
  293. debug.addActionListener( new ActionListener() {
  294. @Override
  295. public void actionPerformed(ActionEvent e) {
  296. showDebugInfo();
  297. }
  298. });
  299. randomGraph = new NiceButton( "random" );
  300. randomGraph.setLocation( 360, 60 );
  301. randomGraph.setMnemonic( KeyEvent.VK_G );
  302. randomGraph.setToolTipText( "Generate random graph (alt + g)" );
  303. randomGraph.addActionListener( new ActionListener() {
  304. @Override
  305. public void actionPerformed(ActionEvent e) {
  306. randomDialog.setVisible( true );
  307. }
  308. });
  309. delayText = new JLabel( "Delay (ms)" );
  310. delayText.setBounds( 260, 10, 80, 20 );
  311. delay = new JTextField( String.valueOf(ProcessController.DEFAULT_DELAY) );
  312. delay.setBounds( 260, 30, 90, 20 );
  313. delay.getDocument().addDocumentListener( new NumberDocumentListener( new NumberDocumentListener.Action() {
  314. @Override
  315. public void action(int val) {
  316. controller.setDelay( Integer.parseInt( delay.getText() ) );
  317. }
  318. }, delay ) );
  319. load = new NiceButton( "load" );
  320. load.setLocation( 260, 60 );
  321. load.setMnemonic( KeyEvent.VK_L );
  322. load.setToolTipText( "Load a graph (alt + l)" );
  323. load.addActionListener( new ActionListener() {
  324. @Override
  325. public void actionPerformed(ActionEvent e) {
  326. JFileChooser chooser = new JFileChooser();
  327. chooser.setFileFilter( new FileNameExtensionFilter("Json Graph", "json") );
  328. chooser.showOpenDialog( frame );
  329. if( chooser.getSelectedFile() != null )
  330. {
  331. Reader r = new Reader( chooser.getSelectedFile().getAbsolutePath() );
  332. LayeredGraphNode graph = r.readInputGraph();
  333. SimpleNodePlacement.placeNodes( graph );
  334. new MainView( graph );
  335. }
  336. }
  337. });
  338. save = new NiceButton( "save" );
  339. save.setLocation( 310, 60 );
  340. save.setMnemonic( KeyEvent.VK_S );
  341. save.setToolTipText( "Save graph (alt + s)" );
  342. save.addActionListener( new ActionListener() {
  343. @Override
  344. public void actionPerformed(ActionEvent e) {
  345. JFileChooser chooser = new JFileChooser();
  346. chooser.setFileFilter( new FileNameExtensionFilter("Json Graph", "json") );
  347. chooser.showSaveDialog( frame );
  348. if( chooser.getSelectedFile() != null )
  349. {
  350. Writer w = new Writer( chooser.getSelectedFile().getAbsolutePath() );
  351. w.writeOutputGraph( graph );
  352. }
  353. }
  354. });
  355. pseudoTree.setBackground(RenderHelper.BACKGROUND_COLOR);
  356. tree.setController( controller );
  357. pseudoTree.setModel( new DefaultTreeModel( tree ) );
  358. pseudoTree.setCellRenderer( new PseudoCodeRenderer() );
  359. pseudoTree.setSelectionModel( null );
  360. pseudoTree.setToolTipText("");
  361. pseudoTree.putClientProperty("JTree.lineStyle", "Angled");
  362. pseudoTree.addMouseListener( new MouseAdapter() {
  363. public void mousePressed(MouseEvent e) {
  364. TreePath selPath = pseudoTree.getPathForLocation(e.getX(), e.getY());
  365. if( selPath != null && e.getClickCount() == 3 ) {
  366. ((PseudoCodeNode)selPath.getLastPathComponent()).setBreakPoint( !((PseudoCodeNode)selPath.getLastPathComponent()).hasBreakPoint() );
  367. if( !pseudoTree.isExpanded( selPath ) )
  368. {
  369. pseudoTree.collapsePath( selPath );
  370. pseudoTree.expandPath( selPath );
  371. }
  372. else
  373. {
  374. pseudoTree.expandPath( selPath );
  375. pseudoTree.collapsePath( selPath );
  376. }
  377. pseudoTree.repaint();
  378. frame.repaint();
  379. }
  380. if( e.getButton() == MouseEvent.BUTTON3 )
  381. {
  382. JPopupMenu menu = new JPopupMenu();
  383. JMenu expandM = new JMenu( "expand ..." );
  384. JMenuItem exAll = new JMenuItem( "all" );
  385. exAll.addActionListener( new ActionListener() {
  386. @Override
  387. public void actionPerformed(ActionEvent e) {
  388. for( int i = 0; i < pseudoTree.getRowCount(); i++ )
  389. pseudoTree.expandRow( i );
  390. }
  391. });
  392. expandM.add( exAll );
  393. JMenuItem exTop = new JMenuItem( "top level lines" );
  394. exTop.addActionListener( new ActionListener() {
  395. @Override
  396. public void actionPerformed(ActionEvent e) {
  397. for( int i = 0; i < pseudoTree.getRowCount(); i++ )
  398. {
  399. if( pseudoTree.getPathForRow( i ).getPathCount() < 3 )
  400. pseudoTree.expandRow( i );
  401. }
  402. }
  403. });
  404. expandM.add( exTop );
  405. JMenuItem exSec = new JMenuItem( "second level lines" );
  406. exSec.addActionListener( new ActionListener() {
  407. @Override
  408. public void actionPerformed(ActionEvent e) {
  409. for( int i = 0; i < pseudoTree.getRowCount(); i++ )
  410. {
  411. if( pseudoTree.getPathForRow( i ).getPathCount() < 4 )
  412. pseudoTree.expandRow( i );
  413. }
  414. }
  415. });
  416. expandM.add( exSec );
  417. JMenuItem exThi = new JMenuItem( "third level lines" );
  418. exThi.addActionListener( new ActionListener() {
  419. @Override
  420. public void actionPerformed(ActionEvent e) {
  421. for( int i = 0; i < pseudoTree.getRowCount(); i++ )
  422. {
  423. if( pseudoTree.getPathForRow( i ).getPathCount() < 5 )
  424. pseudoTree.expandRow( i );
  425. }
  426. }
  427. });
  428. expandM.add( exThi );
  429. menu.add( expandM );
  430. JMenu collapsM = new JMenu( "collapse ..." );
  431. JMenuItem colAll = new JMenuItem( "all" );
  432. colAll.addActionListener( new ActionListener() {
  433. @Override
  434. public void actionPerformed(ActionEvent e) {
  435. for( int i = pseudoTree.getRowCount() - 1; i > 0; i-- )
  436. pseudoTree.collapseRow( i );
  437. }
  438. });
  439. collapsM.add( colAll );
  440. JMenuItem colTop = new JMenuItem( "top level lines" );
  441. colTop.addActionListener( new ActionListener() {
  442. @Override
  443. public void actionPerformed(ActionEvent e) {
  444. for( int i = pseudoTree.getRowCount() - 1; i > 0; i-- )
  445. {
  446. if( pseudoTree.getPathForRow( i ).getPathCount() >= 2 )
  447. pseudoTree.collapseRow( i );
  448. }
  449. }
  450. });
  451. collapsM.add( colTop );
  452. JMenuItem colSec = new JMenuItem( "second level lines" );
  453. colSec.addActionListener( new ActionListener() {
  454. @Override
  455. public void actionPerformed(ActionEvent e) {
  456. for( int i = pseudoTree.getRowCount() - 1; i > 0; i-- )
  457. {
  458. if( pseudoTree.getPathForRow( i ).getPathCount() >= 3 )
  459. pseudoTree.collapseRow( i );
  460. }
  461. }
  462. });
  463. collapsM.add( colSec );
  464. JMenuItem colThi = new JMenuItem( "third level lines" );
  465. colThi.addActionListener( new ActionListener() {
  466. @Override
  467. public void actionPerformed(ActionEvent e) {
  468. for( int i = pseudoTree.getRowCount() - 1; i > 0; i-- )
  469. {
  470. if( pseudoTree.getPathForRow( i ).getPathCount() >= 4 )
  471. pseudoTree.collapseRow( i );
  472. }
  473. }
  474. });
  475. collapsM.add( colThi );
  476. menu.add( collapsM );
  477. menu.show( e.getComponent(), e.getX(), e.getY() );
  478. }
  479. }
  480. } );
  481. pseudoTree.setRowHeight(15);
  482. ((PseudoCodeRenderer)pseudoTree.getCellRenderer()).setMemory( processor.getMemory());
  483. JScrollPane treeView = new JScrollPane( pseudoTree );
  484. PseudoCodeLines lineView = new PseudoCodeLines( pseudoTree );
  485. treeView.setRowHeaderView( lineView );
  486. treeView.setBounds( 10, 110, 390, 380 );
  487. JTextArea debugText = new JTextArea();
  488. debugText.setFont( RenderHelper.font );
  489. debugText.setEditable( false );
  490. debugText.setBackground( RenderHelper.BACKGROUND_COLOR );
  491. debugText.setForeground( RenderHelper.FOREGROUND_COLOR );
  492. JScrollPane debugView = new JScrollPane( debugText );
  493. debugView.setBounds( treeView.getX(), treeView.getY() + 500, treeView.getWidth(), 250 );
  494. frame.setSize( (int)graph.getWidth( LayoutType.LEFTMOST_UPPER ) * 2 + 450, (int)graph.getHeight( LayoutType.LEFTMOST_UPPER ) * 2 + 50 );
  495. frame.setLocation( 100, 100 );
  496. frame.setDefaultCloseOperation( JFrame.DISPOSE_ON_CLOSE );
  497. frame.setVisible( true );
  498. LegendView statusPanel = new LegendView();
  499. statusPanel.setBorder(new BevelBorder(BevelBorder.LOWERED));
  500. frame.add(statusPanel, BorderLayout.SOUTH);
  501. JLayeredPane layne = new JLayeredPane();
  502. layne.setLayout( new BorderLayout() );
  503. JPanel pl = new JPanel();
  504. GridLayout grout = new GridLayout( 2, 2, 10, 10 );
  505. pl.setLayout( grout );
  506. pl.setLocation( 0, 0 );
  507. pl.setSize( frame.getSize() );
  508. NodeView topLeft = createNodeView( graph, LayoutType.LEFTMOST_UPPER );
  509. NodeView topRight = createNodeView( graph, LayoutType.RIGHTMOST_UPPER );
  510. NodeView bottomLeft = createNodeView( graph, LayoutType.LEFTMOST_LOWER );
  511. NodeView bottomRight = createNodeView( graph, LayoutType.RIGHTMOST_LOWER );
  512. pl.add( topLeft );
  513. pl.add( topRight );
  514. pl.add( bottomLeft );
  515. pl.add( bottomRight );
  516. NodeView combined = createNodeView( graph, LayoutType.COMBINED );
  517. combined.setSize( 500, 500 );
  518. layne.add( combined, 0 );
  519. layne.add( pl, 1 );
  520. JSplitPane spane = new JSplitPane( JSplitPane.HORIZONTAL_SPLIT );
  521. spane.setLeftComponent( layne );
  522. spane.setResizeWeight(0.5);
  523. JPanel menue = new JPanel();
  524. menue.setLayout( null );
  525. menue.setPreferredSize( new Dimension( 410, 500 ) );
  526. menue.setMinimumSize( new Dimension( 410, 300 ) );
  527. menue.add( stepForward );
  528. menue.add( stepForwardInto );
  529. menue.add( stepForwardOut );
  530. menue.add( runForward );
  531. menue.add( pause );
  532. menue.add( debug );
  533. menue.add( stepBackward );
  534. menue.add( delayText );
  535. menue.add( delay );
  536. menue.add( stepBackwardInto );
  537. menue.add( stepBackwardOut );
  538. menue.add( runBackward );
  539. menue.add( randomGraph );
  540. menue.add( save );
  541. menue.add( load );
  542. menue.add( options );
  543. JSplitPane spane2 = new JSplitPane( JSplitPane.VERTICAL_SPLIT );
  544. spane2.setBounds( 10, 110, 390, 650 );
  545. spane2.setTopComponent( treeView );
  546. spane2.setBottomComponent( debugView );
  547. spane2.setDividerLocation( 390 );
  548. spane2.setResizeWeight(0.5);
  549. menue.add( spane2 );
  550. spane.setRightComponent( menue);
  551. spane.setContinuousLayout( true );
  552. spane.setDividerLocation( frame.getWidth() - 430 );
  553. spane.addPropertyChangeListener(JSplitPane.DIVIDER_LOCATION_PROPERTY, new PropertyChangeListener() {
  554. @Override
  555. public void propertyChange(PropertyChangeEvent evt) {
  556. frame.getComponentListeners()[ 0 ].componentResized( null );
  557. }
  558. });
  559. frame.add( spane );
  560. frame.revalidate();
  561. frame.repaint();
  562. Stage old = algorithm.getAlgorithmState();
  563. frame.addComponentListener(new ComponentAdapter()
  564. {
  565. public void componentResized(ComponentEvent evt) {
  566. menue.setSize( menue.getWidth(), layne.getHeight() );
  567. spane2.setSize( menue.getWidth() - 20, menue.getHeight() - 120 );
  568. if( graph.getColor( null ) == null )
  569. {
  570. grout.setHgap( 10 );
  571. grout.setVgap( 10 );
  572. combined.setVisible( false );
  573. }
  574. else
  575. {
  576. grout.setHgap( layne.getWidth() / 3 );
  577. grout.setVgap( layne.getHeight() / 3 );
  578. combined.setVisible( true );
  579. combined.doLayout();
  580. }
  581. combined.setSize( layne.getWidth() / 3, layne.getHeight() / 3 );
  582. combined.setLocation( layne.getWidth() / 3, layne.getHeight() / 3 );
  583. debugText.setText( processor.getDebugOutput().trim() );
  584. layne.remove( pl );
  585. layne.add( pl, 1 );
  586. if( optionsDialog != null && optionsDialog.getLayerDisplayOption() == 1 && old != algorithm.getAlgorithmState() )
  587. {
  588. pl.remove( topLeft );
  589. pl.remove( topRight );
  590. pl.remove( bottomLeft );
  591. pl.remove( bottomRight );
  592. pl.remove( combined );
  593. switch( algorithm.getAlgorithmState() )
  594. {
  595. case CONFLICT_DETECTION:
  596. pl.add( topLeft );
  597. break;
  598. case LEFTMOST_UPPER:
  599. pl.add( topLeft );
  600. break;
  601. case RIGHTMOST_UPPER:
  602. pl.add( topRight );
  603. break;
  604. case LEFTMOST_LOWER:
  605. pl.add( bottomLeft );
  606. break;
  607. case RIGHTMOST_LOWER:
  608. pl.add( bottomRight );
  609. break;
  610. case COMBINE:
  611. pl.add( combined );
  612. break;
  613. default:
  614. assert false;
  615. break;
  616. }
  617. pl.revalidate();
  618. }
  619. treeView.revalidate();
  620. frame.repaint();
  621. }
  622. });
  623. frame.setSize( frame.getWidth() + 1, frame.getHeight() );
  624. frame.setSize( frame.getWidth() - 1, frame.getHeight() );
  625. if( frame.getHeight() < (int)graph.getHeight( LayoutType.LEFTMOST_UPPER ) * 2 + 50 )
  626. {
  627. double factor = (graph.getHeight( LayoutType.LEFTMOST_UPPER ) * 2) / (frame.getHeight()-50);
  628. frame.setSize( (int)((frame.getWidth() - 450) / factor) + 450, frame.getHeight() );
  629. spane.setDividerLocation( frame.getWidth() - 430 );
  630. }
  631. optionsDialog = new OptionsDialog();
  632. optionsDialog.addActionListener( new ActionListener() {
  633. @Override
  634. public void actionPerformed(ActionEvent e) {
  635. controller.setStepOption( optionsDialog.getRunStepsOption() );
  636. RenderHelper.font = new Font( "Monospaced", Font.PLAIN, optionsDialog.getFontSize() );
  637. debugText.setFont( RenderHelper.font );
  638. pseudoTree.setFont( RenderHelper.font );
  639. pseudoTree.setRowHeight( (int)(15.0/12 * optionsDialog.getFontSize() ) );
  640. pl.remove( topLeft );
  641. pl.remove( topRight );
  642. pl.remove( bottomLeft );
  643. pl.remove( bottomRight );
  644. pl.remove( combined );
  645. layne.remove( combined );
  646. if( optionsDialog.getLayerDisplayOption() == 0)
  647. {
  648. pl.setLayout( grout );
  649. pl.add( topLeft );
  650. pl.add( topRight );
  651. pl.add( bottomLeft );
  652. pl.add( bottomRight );
  653. layne.add( combined, 0 );
  654. }
  655. else
  656. {
  657. pl.setLayout( new BorderLayout() );
  658. switch( algorithm.getAlgorithmState() )
  659. {
  660. case CONFLICT_DETECTION:
  661. pl.add( topLeft );
  662. break;
  663. case LEFTMOST_UPPER:
  664. pl.add( topLeft );
  665. break;
  666. case RIGHTMOST_UPPER:
  667. pl.add( topRight );
  668. break;
  669. case LEFTMOST_LOWER:
  670. pl.add( bottomLeft );
  671. break;
  672. case RIGHTMOST_LOWER:
  673. pl.add( bottomRight );
  674. break;
  675. case COMBINE:
  676. pl.add( combined );
  677. break;
  678. default:
  679. assert false;
  680. break;
  681. }
  682. }
  683. pl.revalidate();
  684. layne.revalidate();
  685. for( ComponentListener l : frame.getComponentListeners() )
  686. l.componentResized( new ComponentEvent( frame, 0 ) );
  687. }
  688. });
  689. processor.start(); // start running the algorithm
  690. }
  691. private NodeView createNodeView( LayeredGraphNode gNode, LayoutType lt )
  692. {
  693. NodeView graphView = new NodeView( gNode, lt, frame );
  694. ((LayeredNode)gNode).setView( graphView, lt );
  695. graphView.setLayout( null );
  696. graphView.setOpaque( true );
  697. for( LayeredGraphNode n : gNode.getContainedNodes() )
  698. {
  699. NodeView nv = createNodeView( n, lt );
  700. nv.setBounds( nv.getX(), nv.getY(), nv.getWidth(), nv.getHeight() );
  701. graphView.add( nv );
  702. }
  703. for( LayeredGraphEdge e : gNode.getContainedEdges() )
  704. {
  705. EdgeView ev = new EdgeView( e, lt );
  706. ev.setOpaque( true );
  707. graphView.add( ev );
  708. }
  709. return graphView;
  710. }
  711. }