View Javadoc
1 /*** 2 * GraphView.java 3 * 4 * Project: Dependency Tool 5 * 6 * WHEN WHO WHAT 7 * 06.06.2003 pko initial public release 8 * 22.07.2002 ctr modification 9 * 18.04.2002 ctr modification 10 * 22.01.2002 ctr modification 11 * 08.01.2002 ctr creation 12 * 13 * Copyright 2003 ELCA Informatique SA 14 * Av. de la Harpe 22-24, 1000 Lausanne 13, Switzerland 15 * www.elca.ch 16 * 17 * This library is free software; you can redistribute it and/or 18 * modify it under the terms of the GNU Lesser General Public License 19 * as published by the Free Software Foundation; either version 2.1 of 20 * the License, or (at your option) any later version. 21 * 22 * This library is distributed in the hope that it will be useful, but 23 * WITHOUT ANY WARRANTY; without even the implied warranty of 24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 25 * Lesser General Public License for more details. 26 * 27 * You should have received a copy of the GNU Lesser General Public 28 * License along with this library; if not, write to the Free Software 29 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 30 * USA 31 */ 32 33 package ch.elca.dependency.view; 34 35 import att.grappa.Edge; 36 import att.grappa.Element; 37 import att.grappa.Graph; 38 import att.grappa.Grappa; 39 import att.grappa.GrappaPoint; 40 import att.grappa.GrappaConstants; 41 import att.grappa.GrappaPanel; 42 import att.grappa.Node; 43 import ch.elca.dependency.adapter.grappa.GrappaSupport; 44 import ch.elca.dependency.core.DependencyContext; 45 import ch.elca.dependency.core.DependencyModel; 46 import ch.elca.dependency.graph.Perspective; 47 import ch.elca.dependency.gui.*; 48 import ch.elca.dependency.util.IOManager; 49 import ch.elca.dependency.util.IconGrabber; 50 import info.clearthought.layout.TableLayout; 51 import java.awt.*; 52 import java.awt.event.*; 53 import java.awt.event.InputEvent; 54 import java.io.File; 55 import java.io.FileOutputStream; 56 import java.net.URL; 57 import java.net.URLConnection; 58 import java.util.*; 59 import javax.swing.*; 60 import org.apache.log4j.Logger; 61 import sun.misc.BASE64Encoder; 62 63 /*** 64 * This view is responsible for visualizing the graph representation of the 65 * analyzed data. A graph containing all the packages of the project as vertices 66 * and the dependencies of these packages as edges is displayed. 67 * The user can change the layout of this graph by dragging and dropping the 68 * vertices contained by the graph. The classes belonging to this 69 * <code>GraphView</code> class are reponsible that such changes can be 70 * performed properly. 71 * 72 * The display method of the <code>View</code> class is implemented here. It 73 * gets the needed data from the model and displays it in order to this view. 74 * For enabling this several listener classes are used. 75 * 76 * @see ch.elca.dependency.view.View 77 * 78 * @author Christoph Trutmann 79 * @author Pawel Kowalski 80 * @version 1.0-beta 81 */ 82 public final class GraphView extends View implements GrappaConstants, ActionListener { 83 84 //****************************************************************************************/ 85 // singleton part 86 //****************************************************************************************/ 87 88 private static GraphView m_instance = null; 89 90 /*** 91 * Returns the last created instance of the GraphView or null if 92 * none has been created yet. 93 * 94 * @return a <code>GraphView</code> value 95 */ 96 public static GraphView singleton() { 97 return m_instance; 98 } 99 100 //****************************************************************************************/ 101 // static fields 102 //****************************************************************************************/ 103 104 /*** 105 * Log4j Logger. 106 */ 107 private final static Logger LOG = Logger.getLogger(GraphView.class); 108 109 /*** 110 * Title used for this Frame. 111 */ 112 private final static String FRAME_TITLE = "Graph View"; 113 114 /*** 115 * Zoomfactor for zooming in. 116 */ 117 private final static double s_positiveZoomFact = 0.5d; 118 119 /*** 120 * Zoomfactor for zooming out. 121 */ 122 private final static double s_negativeZoomFact = (s_positiveZoomFact * 2) / 3; 123 124 /*** 125 * Available formats for saving a graph. The current version of 126 * dot.exe can't save graphs as postscripts correctly, it only 127 * saves the firs page of a graph. Therefore the functionality to 128 * save the graph as ps has been abandoned. 129 */ 130 // private static final String[] s_formats = new String[] { "dot", "gif", "jpg", "ps", "svg" }; 131 private static final String[] s_formats = new String[] { "dot", "gif", "jpg", "svg" }; 132 133 //****************************************************************************************/ 134 // instance fields 135 //****************************************************************************************/ 136 137 /*** 138 * Instance of the <code>Graph</code> object to visualize. 139 */ 140 private Graph m_graph = null; 141 142 /*** 143 * Scrollpane wrapping the graph canvas. 144 */ 145 private JScrollPane m_scrollPane = null; 146 147 /*** 148 * Enables some features on the graph. 149 */ 150 private MyGrappaAdapter m_adapter = null; 151 152 /*** 153 * Pointer to the GrappaPanel. 154 */ 155 private GrappaPanel m_gPanel = null; 156 157 /*** 158 * Dialog for showing the dependency information on the edges. 159 */ 160 private DependencyDetails m_depDetails = null; 161 162 /*** 163 * Temporary list storing the current selection in the graph. This list is 164 * needed when the layout is changed by the user. 165 */ 166 private ArrayList m_selectListTmp = new ArrayList(); 167 168 /*** 169 * Proxy used for layouting over the web. 170 */ 171 private String m_proxy = null; 172 173 /*** 174 * Os is windows? 175 */ 176 private boolean m_noWin = false; 177 178 private Perspective m_perspective = Perspective.DEFAULT_PERSPECTIVE; 179 180 //****************************************************************************************/ 181 // create a GraphView 182 //****************************************************************************************/ 183 184 /*** 185 * Creates a new <code>GraphView</code> instance. 186 * 187 * @param dependencyModel a <code>DependencyModel</code> value 188 */ 189 public GraphView(DependencyModel dependencyModel) { 190 super(dependencyModel, FRAME_TITLE); 191 setDefaultBounds(new Rectangle(4, 3, 657, 553)); 192 recallConfig(); 193 194 m_instance = this; 195 } 196 197 protected void internalInitData() { 198 199 // get data from the dependency context 200 // 201 DependencyContext dependencyCtx = m_dependencyModel.getDependencyContext(); 202 m_noWin = ((Boolean)dependencyCtx.get(DependencyContext.NOWIN_KEY)).booleanValue(); 203 m_proxy = ((String)dependencyCtx.get(DependencyContext.PROXY_KEY)); 204 } 205 206 protected void initView() { 207 208 // create the MenuBar 209 // 210 final JMenuBar menuBar = new JMenuBar(); 211 setJMenuBar(menuBar); 212 213 // ============================= Zoom Menu BEGIN 214 // 215 JMenu zoomMenu = new JMenu("Zoom"); 216 zoomMenu.setMnemonic(KeyEvent.VK_Z); 217 menuBar.add(zoomMenu); 218 219 // menu item for zoom in 220 // 221 JMenuItem zoomInItem = new JMenuItem(new ZoomInAction()); 222 zoomMenu.add(zoomInItem); 223 224 // menu item for zoom out 225 // 226 JMenuItem zoomOutItem = new JMenuItem(new ZoomOutAction()); 227 zoomMenu.add(zoomOutItem); 228 229 // menu item for rectangle zoom 230 // 231 JMenuItem zoomSweepItem = new JMenuItem(new RectangleZoomAction()); 232 zoomMenu.add(zoomSweepItem); 233 234 // menu item for resetting zoom 235 // 236 JMenuItem zoomOutlineItem = new JMenuItem(new ResetZoomAction()); 237 zoomOutlineItem.setMargin(new Insets(100, 116, 100, 100)); 238 zoomMenu.add(zoomOutlineItem); 239 // 240 // ============================= Zoom Menu END 241 242 // ============================= Perspectives Menu BEGIN 243 // 244 JMenu perspectivesMenu = new JMenu("Perspectives"); 245 perspectivesMenu.setMnemonic(KeyEvent.VK_P); 246 menuBar.add(perspectivesMenu); 247 248 // button group for the checkboxes 249 // 250 ButtonGroup perspectivesButtonGroup = new ButtonGroup(); 251 JRadioButtonMenuItem perspectiveMenuItem = null; 252 Perspective[] perspectives = m_dependencyModel.getPerspectives(); 253 for (int i = 0; i < perspectives.length; i++) { 254 perspectiveMenuItem = new JRadioButtonMenuItem(new PerspectiveAction(perspectives[i])); 255 perspectivesButtonGroup.add(perspectiveMenuItem); 256 perspectivesMenu.add(perspectiveMenuItem); 257 258 // select the default perspective which exists in any case 259 // 260 if (i == 0) { 261 perspectiveMenuItem.setSelected(true); 262 } 263 } 264 // 265 // ============================= Perspectives Menu END 266 267 // ============================= Output Menu BEGIN 268 // 269 JMenu outputMenu = new JMenu("Output"); 270 outputMenu.setMnemonic(KeyEvent.VK_O); 271 272 JMenuItem saveAsFormatItem = null; 273 for (int i = 0; i < s_formats.length; i++) { 274 saveAsFormatItem = new JMenuItem(new SaveGraphAction(s_formats[i])); 275 outputMenu.add(saveAsFormatItem); 276 } 277 278 menuBar.add(outputMenu); 279 // 280 // ============================= Output Menu END 281 282 // configure TableLayout 283 // 284 double border = 10; 285 double fill = TableLayout.FILL; 286 double pref = TableLayout.PREFERRED; 287 double size[][] = 288 {{border, fill, border}, // Columns 289 {border, fill, border}}; // Rows 290 291 292 getContentPane().setLayout(new TableLayout(size)); 293 294 // scroll pane with the graph 295 // 296 m_scrollPane = new JScrollPane(); 297 m_scrollPane.getViewport().setScrollMode(JViewport.BACKINGSTORE_SCROLL_MODE); 298 299 // add the scroll pane to the frame 300 // 301 getContentPane().add(m_scrollPane, "1, 1, F, F"); 302 303 // set the parameters of the internal frame 304 // 305 setBackground(menuBar.getBackground()); 306 307 Frame mainFrame = (Frame)m_dependencyModel.get(DependencyModel.MAIN_FRAME_KEY); 308 m_depDetails = new DependencyDialog(mainFrame, m_dependencyModel); 309 310 setVisible(true); 311 validate(); 312 } 313 314 //****************************************************************************************/ 315 // work with a GraphView 316 //****************************************************************************************/ 317 318 /*** 319 * Implementation of the abstract display method declared in 320 * the <code>View</code> class. Gets the changed data from the 321 * model and displays it. 322 * 323 * @tbd remove hack with background color 324 */ 325 public void display() { 326 327 LOG.debug("Displaying GraphView"); 328 329 super.setCursor(new Cursor(Cursor.WAIT_CURSOR)); 330 331 // get the filtered model 332 // 333 if (m_perspective != null) { 334 m_graph = m_perspective.process(m_dependencyModel.getFilteredGraph()); 335 } else { 336 m_graph = m_dependencyModel.getFilteredGraph(); 337 } 338 339 // figure out to do this differently 340 // 341 m_graph.setGrappaAttribute(GRAPPA_BACKGROUND_COLOR_ATTR,"white"); 342 343 // panel with the graph 344 // 345 m_gPanel = new GrappaPanel(m_graph); 346 347 // create and reference adapter add the listeners to the panel 348 // 349 m_adapter = new MyGrappaAdapter(); 350 m_adapter.setZoomFactor(s_positiveZoomFact, s_negativeZoomFact); 351 m_adapter.reference(m_dependencyModel, m_depDetails); 352 m_gPanel.addGrappaListener(m_adapter); 353 354 // by default the tool tips are enabled 355 // 356 String tip = m_graph.getToolTipText(); 357 if (tip == null) { 358 tip = Grappa.getToolTipText(); 359 } 360 m_gPanel.setToolTipText(tip); 361 362 // viewport is the panel 363 // 364 m_scrollPane.setViewportView(m_gPanel); 365 366 // do layout with dot 367 // 368 if ( ! m_noWin ) { 369 doLayoutWithDot(); 370 select(m_selectListTmp); 371 } else { 372 doLayoutOverWeb(); 373 select(m_selectListTmp); 374 } 375 376 validate(); 377 super.setCursor(new Cursor(Cursor.DEFAULT_CURSOR)); 378 } 379 380 /*** 381 * Selects all the packages in the specified list for all the views 382 * implementing the <code>Observer</code> interface. 383 * 384 * @param selectList List containing all the selected packages. 385 */ 386 public void select(ArrayList selectList) { 387 388 if (LOG.isDebugEnabled()) { 389 StringBuffer buf = new StringBuffer(); 390 for (Iterator iter = selectList.iterator(); iter.hasNext();) { 391 Object obj = iter.next(); 392 buf.append(obj.getClass().getName() + ":" + obj.toString()); 393 } 394 LOG.debug("Select called with: " + buf.toString()); 395 } 396 397 // doesn't work either 398 // 399 // if (selectList.size() > 0) { 400 // for (Enumeration enum = m_graph.nodeElements(); enum.hasMoreElements(); ) { 401 // Node node = (Node)enum.nextElement(); 402 // if (node.getName().indexOf(selectList.get(selectList.size()-1).toString()) != -1) { 403 // LOG.debug("grappa click simulation: " + node.getName()); 404 // m_adapter.grappaClicked(m_graph, node, new GrappaPoint(), 405 // InputEvent.BUTTON1_MASK, 1, m_gPanel); 406 // break; 407 // } 408 // } 409 // } 410 411 // m_selectListTmp = selectList; 412 // for (Enumeration enum = m_graph.elements(); enum.hasMoreElements(); ) { 413 // Element elem = (att.grappa.Element)enum.nextElement(); 414 // LOG.debug("unhighlighted element: " + elem.toString()); 415 // GrappaSupport.setHighlight(elem, 0, HIGHLIGHT_OFF); 416 // } 417 // m_graph.getGraph().repaint(); 418 // m_graph.repaint(); 419 // m_gPanel.repaint(); 420 // m_graph.currentSelection = null; 421 422 // clear the old selection 423 // 424 // Iterator lastIter = m_dependencyModel.getLastSelection().iterator(); 425 // while ( lastIter.hasNext() ) { 426 // String tmp = (String)lastIter.next(); 427 // Node nodeTmp = m_graph.findNodeByName(tmp); 428 // // clear selection of the node 429 // // 430 // if ( nodeTmp != null ) { 431 // GrappaSupport.setHighlight(nodeTmp, 0, HIGHLIGHT_OFF); 432 // // clear selection of all the outgoing edges 433 // // 434 // Enumeration outEnum = nodeTmp.outEdgeElements(); 435 // while ( outEnum.hasMoreElements() ) { 436 // Edge edgeTmp = (Edge)outEnum.nextElement(); 437 // if ( edgeTmp != null ) { 438 // GrappaSupport.setHighlight(edgeTmp, 0, HIGHLIGHT_OFF); 439 // } 440 // } 441 // } 442 // } 443 444 // add the new selection 445 // 446 // ListIterator selectIter = m_selectListTmp.listIterator(); 447 // int count = 0; 448 // Vector sel = new Vector(); 449 // Node nodeTmp = null; 450 // while (selectIter.hasNext() ) { 451 // count++; 452 // String name = (String)selectIter.next(); 453 // nodeTmp = m_graph.findNodeByName(name); 454 // if ( nodeTmp != null ) { 455 // nodeTmp.highlight |= SELECTION_MASK; 456 // sel.add(nodeTmp); 457 // // select all the outgoing edges 458 // // 459 // Enumeration outEdgeEnum = nodeTmp.outEdgeElements(); 460 // while ( outEdgeEnum.hasMoreElements() ) { 461 // Edge edgeTmp = (Edge)outEdgeEnum.nextElement(); 462 // edgeTmp.highlight |= SELECTION_MASK; 463 // } 464 // } 465 // } 466 // if ( count == 1 ) { 467 // m_graph.currentSelection = nodeTmp; 468 // } 469 // else if ( count > 1 ) { 470 // m_graph.currentSelection = sel; 471 // } 472 473 m_graph.repaint(); 474 m_scrollPane.repaint(); 475 } 476 477 /*** 478 * Clears all the selections in all the views. 479 */ 480 public void clearSelection(){ 481 m_selectListTmp.clear(); 482 m_adapter.clearSelection(m_gPanel, m_graph); 483 } 484 485 /*** 486 * Return the currently used Perspective. 487 * 488 * @return a <code>Perspective</code> value 489 */ 490 public Perspective getCurrentPerspective() { 491 return m_perspective; 492 } 493 494 /*** 495 * Set the Perspective to be used. 496 * 497 * @param perspective a <code>Perspective</code> value 498 */ 499 private void setPerspective(Perspective perspective) { 500 m_perspective = perspective; 501 update(m_dependencyModel); 502 } 503 504 /*** 505 * Uses the dot.exe local. 506 * @tbd error message in case the user chooses: nowindows, or if 507 * the dot layout doesn't work for some reason. 508 */ 509 private void doLayoutWithDot() { 510 LOG.debug("Layouting graph with dot.exe"); 511 String message = ""; 512 String errorMessage = "dot.exe not available, could not layout graph!"; 513 m_statusListenerSupport.postMessage("layouting graph..."); 514 515 try { 516 Process connector = (Process)Runtime.getRuntime().exec(IOManager.getDotExe()); 517 if( !GrappaSupport.filterGraph(m_graph, connector) ) { 518 LOG.error("Can't layout the graph with dot.exe!"); 519 message = errorMessage; 520 } 521 m_graph.repaint(); 522 } catch (Exception ex) { 523 ex.printStackTrace(); 524 message = errorMessage; 525 } 526 m_statusListenerSupport.postMessage(message); 527 } 528 529 /*** 530 * Layout provided from the at&t over the web. 531 */ 532 private void doLayoutOverWeb() { 533 LOG.info("Start doing the graph layout over the web..."); 534 535 m_statusListenerSupport.postMessage("layouting graph over web..."); 536 537 String proxyMachineName = null, port = null, user = null, 538 password = null, auth = null; 539 540 if ( ! m_proxy.equals("") ) { 541 StringTokenizer tokenizer 542 = new StringTokenizer(m_proxy, ":,", false); 543 544 int i = 0; 545 while ( tokenizer.hasMoreTokens() ) { 546 String tmp = tokenizer.nextToken(); 547 548 switch ( i ) { 549 // proxy machine name 550 case 0: 551 proxyMachineName = tmp; 552 break; 553 // port 554 case 1: 555 port = tmp; 556 break; 557 // user name 558 case 2: 559 user = tmp; 560 break; 561 // password 562 case 3: 563 password = tmp; 564 break; 565 } 566 i++; 567 } 568 569 // set system properties 570 // 571 System.getProperties().put("proxySet", "true"); 572 System.getProperties().put("proxyHost", proxyMachineName); 573 System.getProperties().put("proxyPort", port); 574 575 if ( ! (user == null) && ! (password == null) ) { 576 String authStr = user.concat(":" + password); 577 auth = "Basic " + new BASE64Encoder().encode(authStr.getBytes()); 578 } 579 } 580 581 Object connector = null; 582 try { 583 connector = (new URL("http://www.research.att.com/~john/cgi-bin/format-graph")).openConnection(); 584 URLConnection urlConn = (URLConnection)connector; 585 urlConn.setDoInput(true); 586 urlConn.setDoOutput(true); 587 urlConn.setUseCaches(false); 588 589 // do the autorisaton for the proxy 590 // 591 if ( (! m_proxy.equals("")) 592 && (! (user == null) && ! (password == null)) ) { 593 594 urlConn.setRequestProperty("Proxy-Authorisation", auth); 595 } 596 urlConn.setRequestProperty("Content-Type","application/x-www-form-urlencoded"); 597 598 } catch ( Exception ex ) { 599 System.err.println("Exception while setting up URLConnection: " + ex.getMessage() + "\nLayout not performed."); 600 connector = null; 601 } 602 603 String message = ""; 604 String errorMessage = "could not layout the graph remotely!"; 605 m_statusListenerSupport.postMessage("layouting graph..."); 606 607 if ( connector != null ) { 608 if( ! GrappaSupport.filterGraph(m_graph, connector) ) { 609 LOG.error(errorMessage); 610 message = errorMessage; 611 } 612 connector = null; 613 } 614 m_graph = m_perspective.process(m_graph); 615 m_graph.repaint(); 616 617 m_statusListenerSupport.postMessage(message); 618 } 619 620 /*** 621 * Handles the action events generated from the menus. 622 * 623 * @param e Action event generated from a menu. 624 */ 625 public void actionPerformed(ActionEvent e) { 626 } 627 628 //****************************************************************************************/ 629 // Actions 630 //****************************************************************************************/ 631 632 class ZoomInAction extends AbstractAction { 633 public ZoomInAction() { 634 super("Zoom In", IconGrabber.getIcon("zoomIn.gif")); 635 putValue(Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_I, InputEvent.CTRL_MASK)); 636 putValue(Action.MNEMONIC_KEY, new Integer(KeyEvent.VK_I)); 637 } 638 public void actionPerformed(ActionEvent event) { 639 640 LOG.debug("PRE ZoomInAction"); 641 642 m_gPanel.multiplyScaleFactor(1d + s_positiveZoomFact); 643 m_gPanel.clearOutline(); 644 m_gPanel.repaint(); 645 646 LOG.debug("POST ZoomInAction"); 647 648 } 649 } 650 651 class ZoomOutAction extends AbstractAction { 652 public ZoomOutAction() { 653 super("Zoom Out", IconGrabber.getIcon("zoomOut.gif")); 654 putValue(Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_O, InputEvent.CTRL_MASK)); 655 putValue(Action.MNEMONIC_KEY, new Integer(KeyEvent.VK_O)); 656 } 657 public void actionPerformed(ActionEvent event) { 658 659 LOG.debug("PRE ZoomOutAction"); 660 661 m_gPanel.multiplyScaleFactor(1d - s_negativeZoomFact); 662 m_gPanel.clearOutline(); 663 m_gPanel.repaint(); 664 665 LOG.debug("POST ZoomOutAction"); 666 667 } 668 } 669 670 class RectangleZoomAction extends AbstractAction { 671 public RectangleZoomAction() { 672 super("Zoom to sweep", IconGrabber.getIcon("zoom.gif")); 673 putValue(Action.MNEMONIC_KEY, new Integer(KeyEvent.VK_E)); 674 } 675 public void actionPerformed(ActionEvent event) { 676 m_gPanel.zoomToOutline(); 677 m_gPanel.clearOutline(); 678 } 679 } 680 681 class ResetZoomAction extends AbstractAction { 682 public ResetZoomAction() { 683 super("Reset Zoom", IconGrabber.getIcon("null.png")); 684 putValue(Action.MNEMONIC_KEY, new Integer(KeyEvent.VK_R)); 685 } 686 public void actionPerformed(ActionEvent event) { 687 m_gPanel.resetZoom(); 688 m_gPanel.clearOutline(); 689 } 690 } 691 692 class PerspectiveAction extends AbstractAction { 693 private Perspective m_perspective = null; 694 public PerspectiveAction(Perspective perspective) { 695 super(perspective.getName(), IconGrabber.getIcon("perspective.gif")); 696 m_perspective = perspective; 697 } 698 public void actionPerformed(ActionEvent event) { 699 GraphView.this.setPerspective(m_perspective); 700 } 701 } 702 703 class SaveGraphAction extends AbstractAction { 704 705 private final JFileChooser m_fileChooser = new JFileChooser("."); 706 private final String m_dotSuffix = "dot"; 707 private String m_formatSuffix = null; 708 709 public SaveGraphAction(String formatSuffix) { 710 super("Save Graph in " + formatSuffix + " format", IconGrabber.getIcon("save.gif")); 711 m_formatSuffix = formatSuffix; 712 m_fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY); 713 m_fileChooser.setFileFilter(MyFileFilter.getFileFilter(m_formatSuffix)); 714 } 715 716 public void actionPerformed(ActionEvent event) { 717 718 File saveFile = null; 719 String fileName = null; 720 int dialogResult = 0; 721 722 // ask user for the file, where to save the graph 723 // if this file exists already, ask whether to overwrite. 724 // 725 while (true) { 726 dialogResult = m_fileChooser.showSaveDialog(GraphView.this); 727 if (dialogResult == JFileChooser.CANCEL_OPTION) { 728 return; 729 } 730 saveFile = m_fileChooser.getSelectedFile(); 731 m_fileChooser.setCurrentDirectory(saveFile); 732 733 if ((saveFile.exists() && saveFile.getName().endsWith(m_formatSuffix)) 734 || new File(saveFile.getAbsolutePath() + "." + m_formatSuffix).exists()) { 735 dialogResult = JOptionPane.showConfirmDialog(GraphView.this, "Overwrite existing file?"); 736 if (dialogResult == JOptionPane.CANCEL_OPTION) { 737 return; 738 } else if (dialogResult == JOptionPane.YES_OPTION) { 739 break; 740 } else if (dialogResult == JOptionPane.NO_OPTION) { 741 continue; 742 } 743 } else { 744 break; 745 } 746 } 747 748 // append m_filesuffix if its not there already 749 // 750 fileName = saveFile.toString(); 751 if (!fileName.endsWith("." + m_formatSuffix)) { 752 fileName = fileName + "." + m_formatSuffix; 753 } 754 755 try { 756 saveGraph(fileName); 757 LOG.info("Graph saved successfully: " + fileName); 758 } catch (Exception e) { 759 LOG.error("Could not save graph: " + e.getClass().getName() + ": " + e.getMessage()); 760 } 761 } 762 763 private void saveGraph(String fileName) throws Exception { 764 765 String tempFile = null; 766 767 if (m_formatSuffix.equals(m_dotSuffix)) { 768 printGraph(fileName); 769 } else { 770 tempFile = printGraph(fileName + "." + m_dotSuffix); 771 reformatGraph(fileName, tempFile); 772 } 773 } 774 775 private void reformatGraph(String outputFile, final String dotFile) throws Exception { 776 String dotExePath = IOManager.getDotExe(); 777 String commandString = dotExePath + " -T" + m_formatSuffix + " " 778 + "\"" + dotFile + "\"" + " -o " + "\"" + outputFile + "\""; 779 780 final Process reformatter = Runtime.getRuntime().exec(commandString); 781 782 // this Thread allows to delete a temporary file we don't need 783 // without making the gui wait for termination of the reformatter process 784 // 785 new Thread() { 786 public void run() { 787 try { 788 reformatter.waitFor(); 789 new File(dotFile).delete(); 790 } catch (InterruptedException e) { 791 LOG.error("Could not delete temporary File: " + dotFile); 792 } 793 } 794 }.start(); 795 } 796 797 private String printGraph(String fileName) throws Exception { 798 799 File tempFile = new File(fileName); 800 if (tempFile.exists()) { 801 tempFile.delete(); 802 } 803 804 FileOutputStream fos = new FileOutputStream(tempFile); 805 m_graph.printGraph(fos); 806 fos.close(); 807 return fileName; 808 } 809 } 810 }

This page was automatically generated by Maven