MainView.java 36 KB

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