/* * Licensed Materials - Property of Perforce Software, Inc. * © Copyright Perforce Software, Inc. 2014, 2021 * © Copyright IBM Corp. 2009, 2014 * © Copyright ILOG 1996, 2009 * All Rights Reserved. * * Note to U.S. Government Users Restricted Rights: * The Software and Documentation were developed at private expense and * are "Commercial Items" as that term is defined at 48 CFR 2.101, * consisting of "Commercial Computer Software" and * "Commercial Computer Software Documentation", as such terms are * used in 48 CFR 12.212 or 48 CFR 227.7202-1 through 227.7202-4, * as applicable. */ import java.awt.BorderLayout; import java.awt.Color; import java.awt.FlowLayout; import java.awt.Graphics; import java.awt.GridLayout; import java.awt.Rectangle; import java.awt.Shape; import java.awt.SystemColor; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.ItemEvent; import java.awt.event.ItemListener; import javax.swing.JButton; import javax.swing.JCheckBox; import javax.swing.JComboBox; import javax.swing.JComponent; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JRootPane; import javax.swing.JTextField; import ilog.views.IlvGrid; import ilog.views.IlvManagerView; import ilog.views.IlvPoint; import ilog.views.IlvTransformer; import ilog.views.diagrammer.IlvDiagrammer; import ilog.views.diagrammer.application.IlvDiagrammerViewBar; import ilog.views.graphlayout.GraphLayoutEvent; import ilog.views.graphlayout.GraphLayoutEventListener; import ilog.views.graphlayout.IlvGraphLayout; import ilog.views.graphlayout.IlvGraphLayoutReport; import ilog.views.graphlayout.random.IlvRandomLayout; import ilog.views.sdm.renderer.graphlayout.IlvGraphLayoutRenderer; import ilog.views.sdm.util.IlvSDMMutableStyleSheet; import ilog.views.util.IlvProductUtil; import ilog.views.util.swing.IlvSwingUtil; /** * This is a very simple application that uses the * <code>IlvDiagrammer</code> to perform a grid layout. It loads a style sheet * containing the grid layout specification. It allows to set various grid * layout parameters by using the <code>IlvSDMMutableStyleSheet</code>. */ public class GridLayoutApp extends JRootPane { { // This sample uses JViews Diagrammer features. When deploying an // application that includes this code, you need to be in possession // of a Perforce JViews Diagrammer Deployment license. IlvProductUtil.DeploymentLicenseRequired(IlvProductUtil.JViews_Diagrammer_Deployment); } /** The diagrammer */ IlvDiagrammer diagrammer = new IlvDiagrammer(); /** A graph layout event listener */ LayoutIterationListener layoutListener = new LayoutIterationListener(); /** The style sheet for temporary changes */ IlvSDMMutableStyleSheet styleSheet = new IlvSDMMutableStyleSheet(diagrammer.getEngine(), true, false); /** An IlvGrid object to help understanding the grid mode */ IlvGrid grid = new LineGrid(); /** The default offset */ static final double DEFAULT_OFFSET = 80.; /** Text fields for the offset parameters */ JTextField hGridOffset = new JTextField("" + DEFAULT_OFFSET, 5); JTextField vGridOffset = new JTextField("" + DEFAULT_OFFSET, 5); /** A text field to display messages */ JTextField msgLine = new JTextField(); /** * Initializes the application. */ public void init() { // we use the standard diagrammer toolbar IlvDiagrammerViewBar toolbar = new IlvDiagrammerViewBar(); // various settings of the diagrammer diagrammer.setSelectMode(true); diagrammer.setScrollable(true); diagrammer.setEditingAllowed(true); diagrammer.setMinimumZoom(0.02); diagrammer.setMaximumZoom(10); diagrammer.getView().setBackground(Color.white); diagrammer.getView().setForeground(SystemColor.windowText); // help recognition of the grid diagrammer.getView().setGrid(grid); grid.setOrigin(new IlvPoint(0, 0)); grid.setColor(new Color(255, 153, 153)); grid.setHorizontalSpacing(80); grid.setVerticalSpacing(80); grid.setActive(false); grid.setVisible(true); // create the file selector JComboBox<String> fileSelector = new JComboBox<String>(); fileSelector.addItem("small"); fileSelector.addItem("medium"); fileSelector.addItem("large"); fileSelector.setToolTipText("Select a sample graph"); fileSelector.addActionListener(new ActionListener() { Override public void actionPerformed(ActionEvent event) { SuppressWarnings("unchecked") JComboBox<String> comboBox = (JComboBox<String>) event.getSource(); String fileName = (String) comboBox.getSelectedItem(); loadDataFile(fileName); } }); // create the randomize button JButton randomizeButton = new JButton("Random"); randomizeButton.setToolTipText("Randomize the node positions"); randomizeButton.addActionListener(new ActionListener() { Override public void actionPerformed(ActionEvent evt) { randomize(); } }); // create the layout button JButton layoutButton = new JButton("Layout"); layoutButton.setToolTipText("Perform a grid layout"); layoutButton.addActionListener(new ActionListener() { Override public void actionPerformed(ActionEvent evt) { // before performing layout, make sure that the values in the text // fields are transfered to the style sheet styleSheet.setAdjusting(true); try { setOffset("horizontalGridOffset", hGridOffset); setOffset("verticalGridOffset", vGridOffset); } finally { styleSheet.setAdjusting(false); } performLayout(); } }); // create the panel for the layout buttons JPanel layoutButtonPanel = new JPanel(); layoutButtonPanel.setLayout(new FlowLayout()); layoutButtonPanel.add(randomizeButton); layoutButtonPanel.add(layoutButton); // create the top panel with the toolbar and the file selector JPanel topPanel = new JPanel(); topPanel.setLayout(new FlowLayout(FlowLayout.LEFT)); topPanel.add(toolbar); topPanel.add(new JLabel("Select graph:")); topPanel.add(fileSelector); // create the bottom panel with the layout buttons and the message line JPanel bottomPanel = new JPanel(); bottomPanel.setLayout(new BorderLayout()); bottomPanel.add(layoutButtonPanel, BorderLayout.NORTH); bottomPanel.add(createParameterPanel(), BorderLayout.CENTER); bottomPanel.add(msgLine, BorderLayout.SOUTH); msgLine.setEditable(false); // put diagrammer, top panel and bottom panel together getContentPane().setLayout(new BorderLayout(0, 0)); getContentPane().add(diagrammer, BorderLayout.CENTER); getContentPane().add(topPanel, BorderLayout.NORTH); getContentPane().add(bottomPanel, BorderLayout.SOUTH); try { // load the main style file diagrammer.setStyleSheet(IlvSwingUtil.getRelativeURL(this, "data/grid.css")); // load a mutable style file that we use for temporary style changes diagrammer.getEngine().setStyleSheets(1, styleSheet.toString()); } catch (Exception e) { showMessage(e.getMessage()); } // load the initial sample grapher loadDataFile("small"); // add the layout listener to the current graph layout. This must be done // here after reading the style file, because before reading the style file, // the layout instance is not yet instantiated. getGraphLayout().addGraphLayoutEventListener(layoutListener); } /** * Creates the layout parameter panel. */ private JPanel createParameterPanel() { JPanel panel = new JPanel(); panel.setLayout(new BorderLayout()); // - - - - - - - - - - - - - - - - - // the offset panel with all offsets JPanel offsetPanel = new JPanel(); offsetPanel.setLayout(new GridLayout(2, 2)); // the horizontal grid offsets final JLabel hGridOffsetLabel = new JLabel(" Horizontal:"); offsetPanel.add(hGridOffsetLabel); offsetPanel.add(hGridOffset); hGridOffset.setToolTipText("Select the horizontal grid offset"); hGridOffset.addActionListener(new ActionListener() { Override public void actionPerformed(ActionEvent e) { setOffset("horizontalGridOffset", (JTextField) e.getSource()); } }); // the vertical grid offsets final JLabel vGridOffsetLabel = new JLabel(" Vertical:"); offsetPanel.add(vGridOffsetLabel); offsetPanel.add(vGridOffset); vGridOffset.setToolTipText("Select the vertical grid offset"); vGridOffset.addActionListener(new ActionListener() { Override public void actionPerformed(ActionEvent e) { setOffset("verticalGridOffset", (JTextField) e.getSource()); } }); // - - - - - - - - - - - - - - - - - // the panel with check boxes JPanel checkBoxPanel = new JPanel(); JCheckBox incrementalOption = new JCheckBox("Incremental", false); checkBoxPanel.add(incrementalOption); incrementalOption.setToolTipText("Enable or disable the incremental mode"); incrementalOption.addItemListener(new ItemListener() { Override public void itemStateChanged(ItemEvent e) { setIncrementalMode(e.getStateChange() == ItemEvent.SELECTED); } }); JCheckBox preserveFixedNodesOption = new JCheckBox("Fix Selected", false); checkBoxPanel.add(preserveFixedNodesOption); preserveFixedNodesOption.setToolTipText("Enable or disable that selected nodes don't move"); preserveFixedNodesOption.addItemListener(new ItemListener() { Override public void itemStateChanged(ItemEvent e) { setSelectedAreFixed(e.getStateChange() == ItemEvent.SELECTED); } }); final JCheckBox showGridOption = new JCheckBox("Show grid", true); checkBoxPanel.add(showGridOption); showGridOption.setToolTipText("Display or hide the grid"); showGridOption.addItemListener(new ItemListener() { Override public void itemStateChanged(ItemEvent e) { showGrid(e.getStateChange() == ItemEvent.SELECTED); } }); // - - - - - - - - - - - - - - - - - // the panel with choice boxes JPanel selectionPanel = new JPanel(); selectionPanel.setLayout(new GridLayout(3, 2)); // horizontal global alignment parameter final JLabel horizAlignmentLabel = new JLabel("Horizontal Alignment:"); final JComboBox<String> hAlignmentChooser = new JComboBox<String>(); selectionPanel.add(horizAlignmentLabel); selectionPanel.add(hAlignmentChooser); hAlignmentChooser.addItem("Center "); hAlignmentChooser.addItem("Left"); hAlignmentChooser.addItem("Right"); hAlignmentChooser.setSelectedIndex(0); hAlignmentChooser.setToolTipText("Select the horizontal alignment mode"); hAlignmentChooser.addActionListener(new ActionListener() { Override public void actionPerformed(ActionEvent event) { SuppressWarnings("unchecked") JComboBox<String> comboBox = (JComboBox<String>) event.getSource(); String mode = (String) comboBox.getSelectedItem(); setGlobalHorizontalAlignment(mode); } }); // vertical global alignment parameter final JLabel vertAlignmentLabel = new JLabel("Vertical Alignment:"); final JComboBox<String> vAlignmentChooser = new JComboBox<String>(); selectionPanel.add(vertAlignmentLabel); selectionPanel.add(vAlignmentChooser); vAlignmentChooser.addItem("Center"); vAlignmentChooser.addItem("Top"); vAlignmentChooser.addItem("Bottom"); vAlignmentChooser.setSelectedIndex(0); vAlignmentChooser.setToolTipText("Select the vertical alignment mode"); vAlignmentChooser.addActionListener(new ActionListener() { Override public void actionPerformed(ActionEvent event) { SuppressWarnings("unchecked") JComboBox<String> comboBox = (JComboBox<String>) event.getSource(); String mode = (String) comboBox.getSelectedItem(); setGlobalVerticalAlignment(mode); } }); // layout mode JComboBox<String> layoutModeSelector = new JComboBox<String>(); selectionPanel.add(new JLabel("Layout Mode:")); selectionPanel.add(layoutModeSelector); layoutModeSelector.addItem("Grid (fixed width)"); layoutModeSelector.addItem("Grid (fixed height)"); layoutModeSelector.addItem("Rows"); layoutModeSelector.addItem("Columns"); layoutModeSelector.setSelectedIndex(0); layoutModeSelector.setToolTipText("Select the layout mode"); layoutModeSelector.addActionListener(new ActionListener() { Override public void actionPerformed(ActionEvent event) { SuppressWarnings("unchecked") JComboBox<String> comboBox = (JComboBox<String>) event.getSource(); String mode = (String) comboBox.getSelectedItem(); setLayoutMode(mode, showGridOption, vGridOffsetLabel, vGridOffset, hGridOffsetLabel, hGridOffset, horizAlignmentLabel, hAlignmentChooser, vertAlignmentLabel, vAlignmentChooser); } }); // - - - - - - - - - - - - - - - - - // put all together panel.add(selectionPanel, BorderLayout.WEST); panel.add(offsetPanel, BorderLayout.EAST); panel.add(checkBoxPanel, BorderLayout.SOUTH); return panel; } /** * Load a sample data file. * * @param fileNameBase * The base of the filename, excluding the path prefix and the * extension suffix. */ private void loadDataFile(String fileNameBase) { try { showMessage("Reading " + fileNameBase + ".xml ..."); diagrammer.setDataFile(IlvSwingUtil.getRelativeURL(this, "data/" + fileNameBase + ".xml")); showMessage("Reading " + fileNameBase + ".xml done."); } catch (Exception e) { showMessage(e.getMessage()); } } /** * Sets the horizontal or vertical offset from a textfield. */ private void setOffset(String property, JTextField valueSelector) { try { // get the value of the parameter from the valueSelector double value = Double.valueOf(valueSelector.getText().trim()).doubleValue(); // write again to be sure the right value is shown valueSelector.setText("" + value); // set the new value of the layout property styleSheet.setDeclaration("GraphLayout", property, "" + value); // sets the grid offset also in the visible grid if (property.equals("horizontalGridOffset")) grid.setHorizontalSpacing(value); if (property.equals("verticalGridOffset")) grid.setVerticalSpacing(value); // redraw the view diagrammer.getView().repaint(); } catch (Exception ex) { showMessage("Illegal " + property + ": " + ex.getMessage()); } } /** * Sets the incremental mode. */ private void setIncrementalMode(boolean flag) { styleSheet.setDeclaration("GraphLayout", "incrementalMode", (flag ? "true" : "false")); } /** * Sets whether nodes specified as fixes (that is, nodes that are selected) * are really fixed. */ private void setSelectedAreFixed(boolean flag) { // don't set preserveFixedNodes because it is automatically set by // the graph layout renderer depending on the existence of the Fixed // property on a node. styleSheet.setDeclaration("node:selected", "Fixed", (flag ? "true" : "false")); } /** * Enables or disabled the display of a grid. */ private void showGrid(boolean show) { boolean visible = grid.isVisible(); if (visible != show) { grid.setVisible(show); diagrammer.getView().repaint(); } } /** * Sets the horizontal alignment. */ private void setGlobalHorizontalAlignment(String mode) { if (mode.equals("Center")) { styleSheet.setDeclaration("GraphLayout", "globalHorizontalAlignment", "CENTER"); } else if (mode.equals("Left")) { styleSheet.setDeclaration("GraphLayout", "globalHorizontalAlignment", "LEFT"); } else if (mode.equals("Right")) { styleSheet.setDeclaration("GraphLayout", "globalHorizontalAlignment", "RIGHT"); } } /** * Sets the vertical alignment. */ private void setGlobalVerticalAlignment(String mode) { if (mode.equals("Center")) { styleSheet.setDeclaration("GraphLayout", "globalVerticalAlignment", "CENTER"); } else if (mode.equals("Top")) { styleSheet.setDeclaration("GraphLayout", "globalVerticalAlignment", "TOP"); } else if (mode.equals("Bottom")) { styleSheet.setDeclaration("GraphLayout", "globalVerticalAlignment", "BOTTOM"); } } /** * Sets the layout mode. */ private void setLayoutMode(String mode, JCheckBox showGridOption, JComponent vGridOffsetLabel, JComponent vGridOffset, JComponent hGridOffsetLabel, JComponent hGridOffset, JComponent horizAlignmentLabel, JComponent hAlignmentChooser, JComponent vertAlignmentLabel, JComponent vAlignmentChooser) { if (mode.equals("Grid (fixed width)")) { vGridOffsetLabel.setEnabled(true); vGridOffset.setEnabled(true); hGridOffsetLabel.setEnabled(true); hGridOffset.setEnabled(true); showGridOption.setEnabled(true); showGrid(showGridOption.isSelected()); horizAlignmentLabel.setEnabled(true); hAlignmentChooser.setEnabled(true); vertAlignmentLabel.setEnabled(true); vAlignmentChooser.setEnabled(true); styleSheet.setDeclaration("GraphLayout", "layoutMode", "TILE_TO_GRID_FIXED_WIDTH"); } else if (mode.equals("Grid (fixed height)")) { vGridOffsetLabel.setEnabled(true); vGridOffset.setEnabled(true); hGridOffsetLabel.setEnabled(true); hGridOffset.setEnabled(true); showGridOption.setEnabled(true); showGrid(showGridOption.isSelected()); horizAlignmentLabel.setEnabled(true); hAlignmentChooser.setEnabled(true); vertAlignmentLabel.setEnabled(true); vAlignmentChooser.setEnabled(true); styleSheet.setDeclaration("GraphLayout", "layoutMode", "TILE_TO_GRID_FIXED_HEIGHT"); } else if (mode.equals("Rows")) { vGridOffsetLabel.setEnabled(false); vGridOffset.setEnabled(false); hGridOffsetLabel.setEnabled(false); hGridOffset.setEnabled(false); showGridOption.setEnabled(false); showGrid(false); horizAlignmentLabel.setEnabled(false); hAlignmentChooser.setEnabled(false); vertAlignmentLabel.setEnabled(true); vAlignmentChooser.setEnabled(true); styleSheet.setDeclaration("GraphLayout", "layoutMode", "TILE_TO_ROWS"); } else if (mode.equals("Columns")) { vGridOffsetLabel.setEnabled(false); vGridOffset.setEnabled(false); hGridOffsetLabel.setEnabled(false); hGridOffset.setEnabled(false); showGridOption.setEnabled(false); showGrid(false); horizAlignmentLabel.setEnabled(true); hAlignmentChooser.setEnabled(true); vertAlignmentLabel.setEnabled(false); vAlignmentChooser.setEnabled(false); styleSheet.setDeclaration("GraphLayout", "layoutMode", "TILE_TO_COLUMNS"); } } /** * Performs the grid layout. The layout type is stored in the CSS file, * therefore we don't need to set the grid layout explicitely. After loading * the graph and the CSS style sheet, the grid layout is already instantiated. */ private void performLayout() { showMessage("Layout started..."); // initialize the iteration listener layoutListener.initialize(getGraphLayout()); // Perform Grid Layout as node layout. Grid layout always handles nodes // and links at the same time, therefore a separate link layout is not // necessary. if (diagrammer.isNodeLayoutAvailable()) { // perform the layout diagrammer.layoutAllNodes(); // show the layout report information about the return code IlvGraphLayoutReport report = getGraphLayout().getLayoutReport(); if (report != null) { showMessage(report.codeToString(report.getCode()) + "."); } } } /** * Randomize the node positions. */ private void randomize() { // clear previous message showMessage(""); // create a new random layout IlvRandomLayout randomLayout = new IlvRandomLayout(); // save the old layout instance IlvGraphLayout oldLayout = getGraphLayout(); // tell the diagrammer to temporarily use the random layout, which // disabled the grid layout. setGraphLayout(randomLayout); if (diagrammer.isNodeLayoutAvailable()) { // perform the layout diagrammer.layoutAllNodes(); } // restore the old layout instance setGraphLayout(oldLayout); } /** * Returns the graph layout currently used by the diagrammer. */ private IlvGraphLayout getGraphLayout() { IlvGraphLayoutRenderer renderer = (IlvGraphLayoutRenderer) diagrammer.getEngine().getNodeLayoutRenderer(); return renderer == null ? null : renderer.getGraphLayout(); } /** * Sets the graph layout currently used by the diagrammer. */ private void setGraphLayout(IlvGraphLayout layout) { IlvGraphLayoutRenderer renderer = (IlvGraphLayoutRenderer) diagrammer.getEngine().getNodeLayoutRenderer(); if (renderer == null) return; renderer.setGraphLayout(layout); } /** * Displays a message. */ void showMessage(String message) { // the message is displayed in the message line msgLine.setText(message); msgLine.paintImmediately(0, 0, msgLine.getWidth(), msgLine.getHeight()); } /** * Allows you to run the demo as a standalone application. */ public static void main(String[] args) { javax.swing.SwingUtilities.invokeLater(new Runnable() { Override public void run() { GridLayoutApp app = new GridLayoutApp(); app.init(); JFrame frame = new JFrame("Grid Layout Example"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setSize(500, 600); frame.getContentPane().add(app); frame.setVisible(true); } }); } // -------------------------------------------------------------------------- /** * A subclass of ilog.views.IlvGrid that draws lines instead of points. */ private class LineGrid extends IlvGrid { /** * Creates a new grid. The origin of the grid is the point (0,0). The * horizontal and verical spacing are 10. The grid is active and visible. */ public LineGrid() { super(); } /** * Creates a new grid. * * @param color * the color of the grid points. * @param origin * the coordinates of the upper-left corner of the grid in the * manager coordinates system. * @param hspacing * spacing of grid points along the horizontal axis. * @param vspacing * spacing of grid points along the vertical axis. * @param visible * Specifies whether the grid is visible (<code>true</code>) of * invisible. * @param active * Specifies whether the grid is active (<code>true</code>) of * inactive. * @see IlvManagerView#setGrid */ SuppressWarnings("unused") public LineGrid(Color color, IlvPoint origin, double hspacing, double vspacing, boolean visible, boolean active) { super(color, origin, hspacing, vspacing, visible, active); } /** * Draws the grid. This method is called by the view * (<code>IlvManagerView</code>) to draw the grid. * * @param dst * the Graphics object to perform the drawing of the grid. * @param t * the transformer used to draw to grid. * @param rect * The area where the grid will be drawn. Note that the grid is * drawn only at the intersection of this area with the clipping * area provided in the <code>dst</code> parameter. When the grid * is used in an <code>IlvManagerView</code>, this parameter is the * bounding rectangle of the view. */ Override protected void draw(Graphics dst, IlvTransformer t, Rectangle rect) { if (!isVisible()) return; Shape oldclip = dst.getClip(); Rectangle theclip = oldclip.getBounds(); Rectangle areaToDraw = theclip.intersection(rect); if (areaToDraw.width == 0 || areaToDraw.height == 0) return; dst.clipRect(areaToDraw.x, areaToDraw.y, areaToDraw.width, areaToDraw.height); // the origin IlvPoint orig = new IlvPoint(); // the spacing parameters IlvPoint spacing = new IlvPoint(getHorizontalSpacing() * getHorizontalShown(), getVerticalSpacing() * getHorizontalShown()); if (t != null) { t.apply(orig); t.apply(spacing); } // in view coords double spacingX = Math.abs(orig.x - spacing.x); double spacingY = Math.abs(orig.y - spacing.y); if (spacingX < 4 || spacingY < 4) return; float minX = areaToDraw.x; float maxX = areaToDraw.x + areaToDraw.width; float minY = areaToDraw.y; float maxY = areaToDraw.y + areaToDraw.height; IlvPoint originPoint = getOrigin(); if (t != null) t.apply(originPoint); int nX = (int) Math.ceil((minX - originPoint.x) / spacingX); int nY = (int) Math.ceil((minY - originPoint.y) / spacingY); double fromX = originPoint.x + nX * spacingX; double fromY = originPoint.y + nY * spacingY; dst.setColor(getColor()); // draw horizontal lines for (double y = fromY; y <= maxY; y += spacingY) dst.drawLine((int) Math.floor(minX), (int) Math.floor(y), (int) Math.floor(maxX), (int) Math.floor(y)); // draw vertical lines for (double x = fromX; x <= maxX; x += spacingX) dst.drawLine((int) Math.floor(x), (int) Math.floor(minY), (int) Math.floor(x), (int) Math.floor(maxY)); dst.setClip(oldclip); } } // -------------------------------------------------------------------------- /** * A graph layout iteration listener. Implementing the interface * GraphLayoutEventListener gives you the possibility to receive during the * layout information about the behavior of the layout algorithm. This * information is contained in the graph layout event. * * In our case, we will simply print a dot each time the method * layoutStepPerformed is called, that is after each iteration of the Bus * Layout algorithm. */ class LayoutIterationListener implements GraphLayoutEventListener { private IlvGraphLayout layout; private String toShow = ""; private static final int MAX_LENGTH = 50; /** * This method is automatically called by the layout algorithm. */ Override public void layoutStepPerformed(GraphLayoutEvent event) { // the status area has a limited width, so we are forced to // reinitialize the message string if (toShow.length() > MAX_LENGTH) toShow = ""; toShow += "."; showMessage(toShow); } /** * Initialize the listener. This method must be called before the layout is * started. */ void initialize(IlvGraphLayout l) { if (layout != l) { if (layout != null) layout.removeGraphLayoutEventListener(this); layout = l; if (layout != null) layout.addGraphLayoutEventListener(this); } toShow = ""; } } }