MainView.java 35 KB

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