MainView.java 36 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822
  1. package view;
  2. import java.awt.BorderLayout;
  3. import java.awt.Color;
  4. import java.awt.Dimension;
  5. import java.awt.Font;
  6. import java.awt.GridBagConstraints;
  7. import java.awt.GridBagLayout;
  8. import java.awt.GridLayout;
  9. import java.awt.event.ActionEvent;
  10. import java.awt.event.ActionListener;
  11. import java.awt.event.ComponentAdapter;
  12. import java.awt.event.ComponentEvent;
  13. import java.awt.event.FocusEvent;
  14. import java.awt.event.FocusListener;
  15. import java.awt.event.KeyEvent;
  16. import java.awt.event.MouseAdapter;
  17. import java.awt.event.MouseEvent;
  18. import javax.swing.JButton;
  19. import javax.swing.JDialog;
  20. import javax.swing.JFileChooser;
  21. import javax.swing.JFrame;
  22. import javax.swing.JLabel;
  23. import javax.swing.JLayeredPane;
  24. import javax.swing.JOptionPane;
  25. import javax.swing.JPanel;
  26. import javax.swing.JScrollPane;
  27. import javax.swing.JTextArea;
  28. import javax.swing.JTextField;
  29. import javax.swing.JTree;
  30. import javax.swing.event.DocumentEvent;
  31. import javax.swing.event.DocumentListener;
  32. import javax.swing.filechooser.FileNameExtensionFilter;
  33. import javax.swing.tree.DefaultTreeModel;
  34. import javax.swing.tree.TreePath;
  35. import org.eclipse.elk.graph.ElkNode;
  36. import animation.Action;
  37. import animation.AnimationController;
  38. import animation.PseudoCodeNode;
  39. import bk.BKNodePlacement;
  40. import bk.ExtremalLayoutCalc.LayoutType;
  41. import graph.InitializeNodePositions;
  42. import graph.LayeredGraphEdge;
  43. import graph.LayeredGraphNode;
  44. import graph.LayeredNode;
  45. import graph.RandomGraphGenerator;
  46. import graph.io.Reader;
  47. import graph.io.Writer;
  48. import lib.SweepCrossingMinimizer;
  49. import lib.TextLayoutHelper;
  50. /**
  51. * The main window of the application.
  52. * There should only be one instance of this class at the same time.
  53. * The JFrame of that single instance can be accessed by the static field {code MainView.frame}.
  54. * @author kolja
  55. *
  56. */
  57. public class MainView {
  58. /**
  59. * The 'frame' of the main window.
  60. * The reason why there can only be one instance of this class.
  61. */
  62. private static int frameCounter = 0;
  63. private JFrame frame;
  64. private AnimationController controller;
  65. private JButton stepForward;
  66. private JButton stepForwardInto;
  67. private JButton stepForwardOut;
  68. private JButton stepBackward;
  69. private JButton stepBackwardInto;
  70. private JButton stepBackwardOut;
  71. private JButton runForward;
  72. private JButton runBackward;
  73. private JButton pause;
  74. private JButton load;
  75. private JButton save;
  76. private JButton debug;
  77. private JButton randomGraph;
  78. private JLabel delayText;
  79. private JTextField delay;
  80. public JTree pseudoTree;
  81. private LayeredGraphNode graph;
  82. private String debugInfo()
  83. {
  84. String info = "Debug Information Table: \n";
  85. info += "_______________________________________________________________________________________________________________________________________________________________________________________________________________________\n";
  86. 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";
  87. info += "|___________________________________________________| |___________________________________________________| |___________________________________________________| |___________________________________________________|\n";
  88. 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";
  89. for( LayeredGraphNode n : graph.getContainedNodes() )
  90. {
  91. info += "|" + TextLayoutHelper.strToLen( n.getName(), 6 ) +
  92. "|" + TextLayoutHelper.strToLen( n.getShift( LayoutType.TOP_BOTTOM_LEFT ) + "", 7 ) +
  93. "|" + TextLayoutHelper.strToLen( n.getSink( LayoutType.TOP_BOTTOM_LEFT ).getName(), 6 ) +
  94. "|" + TextLayoutHelper.strToLen( n.getRoot( LayoutType.TOP_BOTTOM_LEFT ).getName(), 6 ) +
  95. "|" + TextLayoutHelper.strToLen( n.getAlign( LayoutType.TOP_BOTTOM_LEFT ).getName(), 7 ) +
  96. "|" + TextLayoutHelper.strToLen( n.getX( LayoutType.TOP_BOTTOM_LEFT ) + "", 5 ) +
  97. "|" + TextLayoutHelper.strToLen( !n.isXUndefined( LayoutType.TOP_BOTTOM_LEFT ) + "", 8 ) + "| " +
  98. "|" + TextLayoutHelper.strToLen( n.getName(), 6 ) +
  99. "|" + TextLayoutHelper.strToLen( n.getShift( LayoutType.TOP_BOTTOM_RIGHT ) + "", 7 ) +
  100. "|" + TextLayoutHelper.strToLen( n.getSink( LayoutType.TOP_BOTTOM_RIGHT ).getName(), 6 ) +
  101. "|" + TextLayoutHelper.strToLen( n.getRoot( LayoutType.TOP_BOTTOM_RIGHT ).getName(), 6 ) +
  102. "|" + TextLayoutHelper.strToLen( n.getAlign( LayoutType.TOP_BOTTOM_RIGHT ).getName(), 7 ) +
  103. "|" + TextLayoutHelper.strToLen( n.getX( LayoutType.TOP_BOTTOM_RIGHT ) + "", 5 ) +
  104. "|" + TextLayoutHelper.strToLen( !n.isXUndefined( LayoutType.TOP_BOTTOM_RIGHT ) + "", 8 ) + "| " +
  105. "|" + TextLayoutHelper.strToLen( n.getName(), 6 ) +
  106. "|" + TextLayoutHelper.strToLen( n.getShift( LayoutType.BOTTOM_TOP_LEFT ) + "", 7 ) +
  107. "|" + TextLayoutHelper.strToLen( n.getSink( LayoutType.BOTTOM_TOP_LEFT ).getName(), 6 ) +
  108. "|" + TextLayoutHelper.strToLen( n.getRoot( LayoutType.BOTTOM_TOP_LEFT ).getName(), 6 ) +
  109. "|" + TextLayoutHelper.strToLen( n.getAlign( LayoutType.BOTTOM_TOP_LEFT ).getName(), 7 ) +
  110. "|" + TextLayoutHelper.strToLen( n.getX( LayoutType.BOTTOM_TOP_LEFT ) + "", 5 ) +
  111. "|" + TextLayoutHelper.strToLen( !n.isXUndefined( LayoutType.BOTTOM_TOP_LEFT ) + "", 8 ) + "| " +
  112. "|" + TextLayoutHelper.strToLen( n.getName(), 6 ) +
  113. "|" + TextLayoutHelper.strToLen( n.getShift( LayoutType.BOTTOM_TOP_RIGHT ) + "", 7 ) +
  114. "|" + TextLayoutHelper.strToLen( n.getSink( LayoutType.BOTTOM_TOP_RIGHT ).getName(), 6 ) +
  115. "|" + TextLayoutHelper.strToLen( n.getRoot( LayoutType.BOTTOM_TOP_RIGHT ).getName(), 6 ) +
  116. "|" + TextLayoutHelper.strToLen( n.getAlign( LayoutType.BOTTOM_TOP_RIGHT ).getName(), 7 ) +
  117. "|" + TextLayoutHelper.strToLen( n.getX( LayoutType.BOTTOM_TOP_RIGHT ) + "", 5 ) +
  118. "|" + TextLayoutHelper.strToLen( !n.isXUndefined( LayoutType.BOTTOM_TOP_RIGHT ) + "", 8 ) + "|\n";
  119. }
  120. info += "-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------";
  121. return info;
  122. }
  123. private void showDebugInfo()
  124. {
  125. JFrame debugFrame = new JFrame();
  126. JTextArea info = new JTextArea();
  127. info.setEditable( false );
  128. info.setFont( new Font( Font.MONOSPACED, Font.PLAIN, 11 ) );
  129. String infoS = debugInfo();
  130. info.setText( infoS );
  131. JScrollPane view = new JScrollPane( info );
  132. debugFrame.add( view );
  133. debugFrame.setSize( frame.getWidth(), frame.getHeight() );
  134. debugFrame.setVisible( true );
  135. System.out.println( infoS );
  136. }
  137. public MainView( ElkNode graph )
  138. {
  139. this( LayeredNode.convertToLayeredGraph( graph ) );
  140. }
  141. /**
  142. * Initialize the window and its contents.
  143. * @param graph the graph that is displayed in this window.
  144. */
  145. public MainView( LayeredGraphNode graph )
  146. {
  147. frameCounter++;
  148. this.graph = graph;
  149. controller = new AnimationController();
  150. controller.setTimeBetween( 50 );
  151. frame = new JFrame( "NodeShuffler" );
  152. frame.addWindowListener(new java.awt.event.WindowAdapter() {
  153. @Override
  154. public void windowClosing(java.awt.event.WindowEvent windowEvent) {
  155. frameCounter--;
  156. if( frameCounter == 0 )
  157. System.exit( 0 );
  158. }
  159. });
  160. BKNodePlacement algorithm = new BKNodePlacement( controller, graph, frame );
  161. // Create Menu GUI
  162. stepForward = new NiceButton( "stepForward" );
  163. stepForward.setLocation( 10, 10 );
  164. stepForward.setMnemonic( KeyEvent.VK_DOWN );
  165. stepForward.setToolTipText( "Forward step over (alt + down arrow key)" );
  166. stepForward.addActionListener( new ActionListener() {
  167. @Override
  168. public void actionPerformed(ActionEvent e) {
  169. controller.setContinuous( false );
  170. controller.setNextAction( Action.FORWARD_OVER );
  171. }
  172. });
  173. stepForwardInto = new NiceButton( "stepForwardInto" );
  174. stepForwardInto.setLocation( 60, 10 );
  175. stepForwardInto.setMnemonic( KeyEvent.VK_RIGHT );
  176. stepForwardInto.setToolTipText( "Forward step into (alt + right arrow key)" );
  177. stepForwardInto.addActionListener( new ActionListener() {
  178. @Override
  179. public void actionPerformed(ActionEvent e) {
  180. controller.setContinuous( false );
  181. controller.setNextAction( Action.FORWARD );
  182. }
  183. });
  184. stepForwardOut = new NiceButton( "stepForwardOut" );
  185. stepForwardOut.setLocation( 110, 10 );
  186. stepForwardOut.setMnemonic( KeyEvent.VK_PAGE_DOWN );
  187. stepForwardOut.setToolTipText( "Forward step out (alt + page down key)" );
  188. stepForwardOut.addActionListener( new ActionListener() {
  189. @Override
  190. public void actionPerformed(ActionEvent e) {
  191. controller.setContinuous( false );
  192. controller.setNextAction( Action.FORWARD_OUT );
  193. }
  194. });
  195. runForward = new NiceButton( "runForward" );
  196. runForward.setLocation( 160, 10 );
  197. runForward.setMnemonic( KeyEvent.VK_P );
  198. runForward.setToolTipText( "Run forwards (alt + p)" );
  199. runForward.addActionListener( new ActionListener() {
  200. @Override
  201. public void actionPerformed(ActionEvent e) {
  202. controller.setContinuous( true );
  203. controller.setNextAction( Action.FORWARD );
  204. }
  205. });
  206. runBackward = new NiceButton( "runBackward" );
  207. runBackward.setLocation( 160, 60 );
  208. runBackward.setMnemonic( KeyEvent.VK_R );
  209. runBackward.setToolTipText( "Run backwards (alt + r)" );
  210. runBackward.addActionListener( new ActionListener() {
  211. @Override
  212. public void actionPerformed(ActionEvent e) {
  213. controller.setContinuous( true );
  214. controller.setNextAction( Action.BACKWARD );
  215. }
  216. });
  217. stepBackward = new NiceButton( "stepBackward" );
  218. stepBackward.setLocation( 10, 60 );
  219. stepBackward.setMnemonic( KeyEvent.VK_UP );
  220. stepBackward.setToolTipText( "Backward step over (alt + up arrow key)" );
  221. stepBackward.addActionListener( new ActionListener() {
  222. @Override
  223. public void actionPerformed(ActionEvent e) {
  224. controller.setContinuous( false );
  225. controller.setNextAction( Action.BACKWARD_OVER );
  226. }
  227. });
  228. stepBackwardInto = new NiceButton( "stepBackwardInto" );
  229. stepBackwardInto.setLocation( 60, 60 );
  230. stepBackwardInto.setMnemonic( KeyEvent.VK_LEFT );
  231. stepBackwardInto.setToolTipText( "Backward step into (alt + left arrow key)" );
  232. stepBackwardInto.addActionListener( new ActionListener() {
  233. @Override
  234. public void actionPerformed(ActionEvent e) {
  235. controller.setContinuous( false );
  236. controller.setNextAction( Action.BACKWARD );
  237. }
  238. });
  239. stepBackwardOut = new NiceButton( "stepBackwardOut" );
  240. stepBackwardOut.setLocation( 110, 60 );
  241. stepBackwardOut.setMnemonic( KeyEvent.VK_PAGE_UP );
  242. stepBackwardOut.setToolTipText( "Backward step out (alt + page up)" );
  243. stepBackwardOut.addActionListener( new ActionListener() {
  244. @Override
  245. public void actionPerformed(ActionEvent e) {
  246. controller.setContinuous( false );
  247. controller.setNextAction( Action.BACKWARD_OUT );
  248. }
  249. });
  250. pause = new NiceButton( "pause" );
  251. pause.setLocation( 210, 10 );
  252. pause.setMnemonic( KeyEvent.VK_PAUSE );
  253. pause.setToolTipText( "Pause (alt + pause)" );
  254. pause.addActionListener( new ActionListener() {
  255. @Override
  256. public void actionPerformed(ActionEvent e) {
  257. controller.setContinuous( false );
  258. }
  259. });
  260. debug = new NiceButton( "debug" );
  261. debug.setLocation( 360, 10 );
  262. debug.setMnemonic( KeyEvent.VK_D );
  263. debug.setToolTipText( "Show debug info (alt + d)" );
  264. debug.addActionListener( new ActionListener() {
  265. @Override
  266. public void actionPerformed(ActionEvent e) {
  267. showDebugInfo();
  268. }
  269. });
  270. randomGraph = new NiceButton( "random" );
  271. randomGraph.setLocation( 360, 60 );
  272. randomGraph.setMnemonic( KeyEvent.VK_G );
  273. randomGraph.setToolTipText( "Generate random graph (alt + g)" );
  274. randomGraph.addActionListener( new ActionListener() {
  275. @Override
  276. public void actionPerformed(ActionEvent e) {
  277. JDialog diag = new JDialog( frame, "Generate random graph" );
  278. diag.setLayout( new GridBagLayout() );
  279. GridBagConstraints c = new GridBagConstraints();
  280. c.gridx = 0;
  281. c.gridy = 0;
  282. diag.add( new JLabel( "P(subgraph exists)"), c );
  283. c = new GridBagConstraints();
  284. c.gridx = 1;
  285. c.gridy = 0;
  286. JTextField pSubgraph = new JTextField( "0.1" );
  287. pSubgraph.setPreferredSize( new Dimension( 100, 20 ) );
  288. pSubgraph.addFocusListener( new FocusListener() {
  289. @Override
  290. public void focusGained(FocusEvent e) {
  291. pSubgraph.setBackground( Color.WHITE );
  292. }
  293. @Override
  294. public void focusLost(FocusEvent e) {
  295. try {
  296. double d = Double.parseDouble( pSubgraph.getText() );
  297. if( d > 1 || d < 0 )
  298. pSubgraph.setBackground( Color.RED );
  299. } catch( Exception e1 )
  300. {
  301. pSubgraph.setBackground( Color.RED );
  302. }
  303. }
  304. });
  305. diag.add( pSubgraph, c );
  306. c = new GridBagConstraints();
  307. c.gridx = 0;
  308. c.gridy = 1;
  309. diag.add( new JLabel( "P(edge exists)"), c );
  310. c = new GridBagConstraints();
  311. c.gridx = 1;
  312. c.gridy = 1;
  313. JTextField pEdge = new JTextField( "0.3" );
  314. pEdge.setPreferredSize( new Dimension( 100, 20 ) );
  315. pEdge.addFocusListener( new FocusListener() {
  316. @Override
  317. public void focusGained(FocusEvent e) {
  318. pEdge.setBackground( Color.WHITE );
  319. }
  320. @Override
  321. public void focusLost(FocusEvent e) {
  322. try {
  323. double d = Double.parseDouble( pEdge.getText() );
  324. if( d > 1 || d < 0 )
  325. pEdge.setBackground( Color.RED );
  326. } catch( Exception e1 )
  327. {
  328. pEdge.setBackground( Color.RED );
  329. }
  330. }
  331. });
  332. diag.add( pEdge, c );
  333. c = new GridBagConstraints();
  334. c.gridx = 0;
  335. c.gridy = 2;
  336. diag.add( new JLabel( "min. num. layers"), c );
  337. c = new GridBagConstraints();
  338. c.gridx = 1;
  339. c.gridy = 2;
  340. JTextField minLayers = new JTextField( "5" );
  341. JTextField maxLayers = new JTextField( "5" );
  342. minLayers.setPreferredSize( new Dimension( 100, 20 ) );
  343. minLayers.addFocusListener( new FocusListener() {
  344. @Override
  345. public void focusGained(FocusEvent e) {
  346. minLayers.setBackground( Color.WHITE );
  347. }
  348. @Override
  349. public void focusLost(FocusEvent e) {
  350. try {
  351. int i = Integer.parseInt( minLayers.getText() );
  352. int max = Integer.parseInt( maxLayers.getText() );
  353. if( i < 1 || i > max )
  354. minLayers.setBackground( Color.RED );
  355. else
  356. maxLayers.setBackground( Color.WHITE );
  357. } catch( Exception e1 )
  358. {
  359. minLayers.setBackground( Color.RED );
  360. }
  361. }
  362. });
  363. diag.add( minLayers, c );
  364. c = new GridBagConstraints();
  365. c.gridx = 0;
  366. c.gridy = 3;
  367. diag.add( new JLabel( "max. num. layers"), c );
  368. c = new GridBagConstraints();
  369. c.gridx = 1;
  370. c.gridy = 3;
  371. maxLayers.setPreferredSize( new Dimension( 100, 20 ) );
  372. maxLayers.addFocusListener( new FocusListener() {
  373. @Override
  374. public void focusGained(FocusEvent e) {
  375. maxLayers.setBackground( Color.WHITE );
  376. }
  377. @Override
  378. public void focusLost(FocusEvent e) {
  379. try {
  380. int i = Integer.parseInt( maxLayers.getText() );
  381. int min = Integer.parseInt( minLayers.getText() );
  382. if( i < min )
  383. maxLayers.setBackground( Color.RED );
  384. else if( min > 0 )
  385. minLayers.setBackground( Color.WHITE );
  386. } catch( Exception e1 )
  387. {
  388. maxLayers.setBackground( Color.RED );
  389. }
  390. }
  391. });
  392. diag.add( maxLayers, c );
  393. c = new GridBagConstraints();
  394. c.gridx = 0;
  395. c.gridy = 4;
  396. diag.add( new JLabel( "min. num. nodes"), c );
  397. c = new GridBagConstraints();
  398. c.gridx = 1;
  399. c.gridy = 4;
  400. JTextField minNodes = new JTextField( "5" );
  401. JTextField maxNodes = new JTextField( "5" );
  402. minNodes.setPreferredSize( new Dimension( 100, 20 ) );
  403. minNodes.setToolTipText( "between 1 and 'min. num. nodes'" );
  404. minNodes.addFocusListener( new FocusListener() {
  405. @Override
  406. public void focusGained(FocusEvent e) {
  407. minNodes.setBackground( Color.WHITE );
  408. }
  409. @Override
  410. public void focusLost(FocusEvent e) {
  411. try {
  412. int i = Integer.parseInt( minNodes.getText() );
  413. int max = Integer.parseInt( maxNodes.getText() );
  414. if( i < 1 || i > max )
  415. minNodes.setBackground( Color.RED );
  416. else
  417. minNodes.setBackground( Color.WHITE );
  418. } catch( Exception e1 )
  419. {
  420. minNodes.setBackground( Color.RED );
  421. }
  422. }
  423. });
  424. diag.add( minNodes, c );
  425. c = new GridBagConstraints();
  426. c.gridx = 0;
  427. c.gridy = 5;
  428. diag.add( new JLabel( "max. num. nodes"), c );
  429. c = new GridBagConstraints();
  430. c.gridx = 1;
  431. c.gridy = 5;
  432. maxNodes.setPreferredSize( new Dimension( 100, 20 ) );
  433. maxNodes.setToolTipText( "between 'min. num. nodes' and +Inf" );
  434. maxNodes.addFocusListener( new FocusListener() {
  435. @Override
  436. public void focusGained(FocusEvent e) {
  437. maxNodes.setBackground( Color.WHITE );
  438. }
  439. @Override
  440. public void focusLost(FocusEvent e) {
  441. try {
  442. int i = Integer.parseInt( maxNodes.getText() );
  443. int min = Integer.parseInt( minNodes.getText() );
  444. if( i < min )
  445. maxNodes.setBackground( Color.RED );
  446. else if( min > 0 )
  447. minNodes.setBackground( Color.WHITE );
  448. } catch( Exception e1 )
  449. {
  450. maxNodes.setBackground( Color.RED );
  451. }
  452. }
  453. });
  454. diag.add( maxNodes, c );
  455. c = new GridBagConstraints();
  456. c.gridx = 0;
  457. c.gridy = 6;
  458. diag.add( new JLabel( "max. hier. depth"), c );
  459. c = new GridBagConstraints();
  460. c.gridx = 1;
  461. c.gridy = 6;
  462. JTextField maxDepth = new JTextField( "1" );
  463. maxDepth.setPreferredSize( new Dimension( 100, 20 ) );
  464. maxDepth.setToolTipText( "between 1 and +Inf" );
  465. maxDepth.addFocusListener( new FocusListener() {
  466. @Override
  467. public void focusGained(FocusEvent e) {
  468. maxDepth.setBackground( Color.WHITE );
  469. }
  470. @Override
  471. public void focusLost(FocusEvent e) {
  472. try {
  473. int i = Integer.parseInt( maxDepth.getText() );
  474. if( i < 1 )
  475. maxDepth.setBackground( Color.RED );
  476. } catch( Exception e1 )
  477. {
  478. maxDepth.setBackground( Color.RED );
  479. }
  480. }
  481. });
  482. diag.add( maxDepth, c );
  483. c = new GridBagConstraints();
  484. c.gridx = 0;
  485. c.gridy = 7;
  486. c.gridwidth = 2;
  487. JButton gen = new JButton( "generate");
  488. gen.addActionListener( new ActionListener() {
  489. @Override
  490. public void actionPerformed(ActionEvent e) {
  491. double pSubGraphD = Double.parseDouble( pSubgraph.getText() );
  492. double pEdgeD = Double.parseDouble( pEdge.getText() );
  493. int minLayerI = Integer.parseInt( minLayers.getText() );
  494. int maxLayerI = Integer.parseInt( maxLayers.getText() );
  495. int minNodeI = Integer.parseInt( minNodes.getText() );
  496. int maxNodeI = Integer.parseInt( maxNodes.getText() );
  497. int maxDepthI = Integer.parseInt( maxDepth.getText() );
  498. boolean ok = true;
  499. if( pSubGraphD < 0 || pSubGraphD > 1 )
  500. {
  501. pSubgraph.setBackground( Color.RED );
  502. ok = false;
  503. }
  504. if( pEdgeD < 0 || pEdgeD > 1 )
  505. {
  506. pEdge.setBackground( Color.RED );
  507. ok = false;
  508. }
  509. if( minLayerI < 1 )
  510. {
  511. minLayers.setBackground( Color.RED );
  512. ok = false;
  513. }
  514. if( maxLayerI < minLayerI )
  515. {
  516. maxLayers.setBackground( Color.RED );
  517. ok = false;
  518. }
  519. if( minNodeI < 1 )
  520. {
  521. minNodes.setBackground( Color.RED );
  522. ok = false;
  523. }
  524. if( maxNodeI < minNodeI )
  525. {
  526. maxNodes.setBackground( Color.RED );
  527. ok = false;
  528. }
  529. if( maxDepthI < 1 )
  530. {
  531. maxDepth.setBackground( Color.RED );
  532. ok = false;
  533. }
  534. if( ok )
  535. {
  536. RandomGraphGenerator r = new RandomGraphGenerator( pSubGraphD, pEdgeD, minLayerI, maxLayerI, minNodeI, maxNodeI, maxDepthI );
  537. try {
  538. LayeredGraphNode graph = r.createRandomNode( null, 0, true );
  539. SweepCrossingMinimizer cminzer = new SweepCrossingMinimizer();
  540. for( int i = 0; i < 10; i++ )
  541. cminzer.minimizeCrossings( graph );
  542. InitializeNodePositions.placeNodes( graph );
  543. new MainView( graph );
  544. diag.setVisible( false );
  545. } catch( Exception e1 )
  546. {
  547. JOptionPane.showMessageDialog(frame, e1.getMessage(), "Error", JOptionPane.ERROR_MESSAGE);
  548. }
  549. }
  550. }
  551. });
  552. diag.add( gen, c );
  553. diag.setSize( 270, 220 );
  554. diag.setLocation( frame.getX() + frame.getWidth() / 2 - diag.getWidth() / 2, frame.getY() + frame.getHeight() / 2 - diag.getHeight() / 2 );
  555. diag.setVisible( true );
  556. }
  557. });
  558. delayText = new JLabel( "Delay (ms)" );
  559. delayText.setBounds( 260, 10, 80, 20 );
  560. delay = new JTextField( "50" );
  561. delay.setBounds( 260, 30, 90, 20 );
  562. delay.getDocument().addDocumentListener( new DocumentListener() {
  563. @Override
  564. public void insertUpdate(DocumentEvent e) {
  565. try
  566. {
  567. controller.setTimeBetween( Integer.parseInt( delay.getText() ) );
  568. delay.setBackground( Color.WHITE );
  569. } catch( Exception e1 )
  570. {
  571. delay.setBackground( Color.RED );
  572. }
  573. }
  574. @Override
  575. public void removeUpdate(DocumentEvent e) {
  576. try
  577. {
  578. controller.setTimeBetween( Integer.parseInt( delay.getText() ) );
  579. delay.setBackground( Color.WHITE );
  580. } catch( Exception e1 )
  581. {
  582. delay.setBackground( Color.RED );
  583. }
  584. }
  585. @Override
  586. public void changedUpdate(DocumentEvent e) {
  587. try
  588. {
  589. controller.setTimeBetween( Integer.parseInt( delay.getText() ) );
  590. delay.setBackground( Color.WHITE );
  591. } catch( Exception e1 )
  592. {
  593. delay.setBackground( Color.RED );
  594. }
  595. }
  596. });
  597. load = new NiceButton( "load" );
  598. load.setLocation( 230, 60 );
  599. load.setMnemonic( KeyEvent.VK_L );
  600. load.setToolTipText( "Load a graph (alt + l)" );
  601. load.addActionListener( new ActionListener() {
  602. @Override
  603. public void actionPerformed(ActionEvent e) {
  604. JFileChooser chooser = new JFileChooser();
  605. chooser.setFileFilter( new FileNameExtensionFilter("Json Graph", "json") );
  606. chooser.showOpenDialog( frame );
  607. if( chooser.getSelectedFile() != null )
  608. {
  609. Reader r = new Reader( chooser.getSelectedFile().getAbsolutePath() );
  610. LayeredGraphNode graph = r.readInputGraph();
  611. InitializeNodePositions.placeNodes( graph );
  612. new MainView( graph );
  613. }
  614. }
  615. });
  616. save = new NiceButton( "save" );
  617. save.setLocation( 295, 60 );
  618. save.setMnemonic( KeyEvent.VK_S );
  619. save.setToolTipText( "Save graph (alt + s)" );
  620. save.addActionListener( new ActionListener() {
  621. @Override
  622. public void actionPerformed(ActionEvent e) {
  623. JFileChooser chooser = new JFileChooser();
  624. chooser.setFileFilter( new FileNameExtensionFilter("Json Graph", "json") );
  625. chooser.showSaveDialog( frame );
  626. if( chooser.getSelectedFile() != null )
  627. {
  628. Writer w = new Writer( chooser.getSelectedFile().getAbsolutePath() );
  629. w.writeOutputGraph( graph );
  630. }
  631. }
  632. });
  633. pseudoTree = new JTree();
  634. pseudoTree.setBackground(RenderHelper.BACKGROUND_COLOR);
  635. PseudoCodeNode tree = algorithm.createPseudocodeTree( pseudoTree );
  636. tree.setController( controller );
  637. pseudoTree.setModel( new DefaultTreeModel( tree ) );
  638. pseudoTree.setCellRenderer( new PseudoCodeRenderer() );
  639. pseudoTree.setSelectionModel( null );
  640. pseudoTree.addMouseListener( new MouseAdapter() {
  641. public void mousePressed(MouseEvent e) {
  642. TreePath selPath = pseudoTree.getPathForLocation(e.getX(), e.getY());
  643. if( selPath != null && e.getClickCount() == 3 ) {
  644. ((PseudoCodeNode)selPath.getLastPathComponent()).setBreakPoint( !((PseudoCodeNode)selPath.getLastPathComponent()).hasBreakPoint() );
  645. if( !pseudoTree.isExpanded( selPath ) )
  646. {
  647. pseudoTree.collapsePath( selPath );
  648. pseudoTree.expandPath( selPath );
  649. }
  650. else
  651. {
  652. pseudoTree.expandPath( selPath );
  653. pseudoTree.collapsePath( selPath );
  654. }
  655. pseudoTree.repaint();
  656. frame.repaint();
  657. }
  658. }
  659. } );
  660. pseudoTree.setRowHeight(15);
  661. JScrollPane treeView = new JScrollPane( pseudoTree );
  662. treeView.setBounds( 10, 110, 390, 380 );
  663. JTextArea debugText = new JTextArea();
  664. debugText.setFont( new Font( "Monospaced", Font.PLAIN, 12 ) );
  665. debugText.setEditable( false );
  666. debugText.setBackground( RenderHelper.BACKGROUND_COLOR );
  667. debugText.setForeground( RenderHelper.FOREGROUND_COLOR );
  668. JScrollPane debugView = new JScrollPane( debugText );
  669. debugView.setBounds( treeView.getX(), treeView.getY() + 500, treeView.getWidth(), 250 );
  670. frame.setSize( (int)graph.getWidth( LayoutType.TOP_BOTTOM_LEFT ) * 2 + 575, (int)graph.getHeight( LayoutType.TOP_BOTTOM_LEFT ) * 2 + 200 );
  671. frame.setLocation( 100, 100 );
  672. frame.setDefaultCloseOperation( JFrame.DISPOSE_ON_CLOSE );
  673. frame.setVisible( true );
  674. JLayeredPane layne = new JLayeredPane();
  675. JPanel pl = new JPanel();
  676. GridLayout grout = new GridLayout( 2, 2, 10, 10 );
  677. pl.setLayout( grout );
  678. pl.setLocation( 0, 0 );
  679. pl.setSize( frame.getSize() );
  680. NodeView topLeft = createNodeView( graph, LayoutType.TOP_BOTTOM_LEFT );
  681. NodeView topRight = createNodeView( graph, LayoutType.TOP_BOTTOM_RIGHT );
  682. NodeView bottomLeft = createNodeView( graph, LayoutType.BOTTOM_TOP_LEFT );
  683. NodeView bottomRight = createNodeView( graph, LayoutType.BOTTOM_TOP_RIGHT );
  684. pl.add( topLeft );
  685. pl.add( topRight );
  686. pl.add( bottomLeft );
  687. pl.add( bottomRight );
  688. layne.add( pl, 1 );
  689. NodeView combined = createNodeView( graph, LayoutType.COMBINED );
  690. combined.setSize( 500, 500 );
  691. layne.add( combined, 0 );
  692. frame.add( layne );
  693. JPanel menue = new JPanel();
  694. menue.setLayout( null );
  695. menue.setPreferredSize( new Dimension( 410, 500 ) );
  696. menue.add( stepForward );
  697. menue.add( stepForwardInto );
  698. menue.add( stepForwardOut );
  699. menue.add( runForward );
  700. menue.add( pause );
  701. menue.add( debug );
  702. menue.add( stepBackward );
  703. menue.add( delayText );
  704. menue.add( delay );
  705. menue.add( treeView );
  706. menue.add( stepBackwardInto );
  707. menue.add( stepBackwardOut );
  708. menue.add( runBackward );
  709. menue.add( randomGraph );
  710. menue.add( save );
  711. menue.add( load );
  712. menue.add( debugView );
  713. frame.add( menue, BorderLayout.EAST );
  714. frame.setSize( frame.getWidth() + 1, frame.getHeight() );
  715. frame.setSize( frame.getWidth() - 1, frame.getHeight() );
  716. frame.validate();
  717. frame.repaint();
  718. frame.addComponentListener(new ComponentAdapter()
  719. {
  720. public void componentResized(ComponentEvent evt) {
  721. pl.setSize( layne.getSize() );
  722. menue.setSize( menue.getWidth(), layne.getHeight() );
  723. treeView.setSize( treeView.getWidth(), layne.getHeight() - 370 );
  724. debugView.setBounds( treeView.getX(), treeView.getY() + treeView.getHeight() + 10, treeView.getWidth(), 240 );
  725. if( graph.getColor( LayoutType.COMBINED ) == null )
  726. {
  727. grout.setHgap( 10 );
  728. grout.setVgap( 10 );
  729. }
  730. else
  731. {
  732. grout.setHgap( layne.getWidth() / 3 );
  733. grout.setVgap( layne.getHeight() / 3 );
  734. }
  735. combined.setSize( layne.getWidth() / 3, layne.getHeight() / 3 );
  736. combined.setLocation( layne.getWidth() / 3, layne.getHeight() / 3 );
  737. debugText.setText( algorithm.getDebugString() );
  738. layne.remove( pl );
  739. layne.add( pl, 1 );
  740. frame.repaint();
  741. }
  742. });
  743. algorithm.start();
  744. }
  745. private NodeView createNodeView( LayeredGraphNode gNode, LayoutType lt )
  746. {
  747. NodeView graphView = new NodeView( gNode, lt );
  748. graphView.setLayout( null );
  749. graphView.setOpaque( true );
  750. for( LayeredGraphNode n : gNode.getContainedNodes() )
  751. {
  752. NodeView nv = createNodeView( n, lt );
  753. nv.setBounds( nv.getX(), nv.getY(), nv.getWidth(), nv.getHeight() );
  754. graphView.add( nv );
  755. }
  756. for( LayeredGraphEdge e : gNode.getContainedEdges() )
  757. {
  758. EdgeView ev = new EdgeView( e, lt );
  759. ev.setOpaque( true );
  760. graphView.add( ev );
  761. }
  762. return graphView;
  763. }
  764. }