/* * 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.ComponentOrientation; import java.awt.FlowLayout; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.Insets; import java.awt.SystemColor; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.text.MessageFormat; import java.util.Locale; import javax.swing.JButton; import javax.swing.JCheckBox; import javax.swing.JComboBox; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JRootPane; import javax.swing.JTextField; 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.IlvLocaleUtil; import ilog.views.util.IlvProductUtil; import ilog.views.util.IlvResourceUtil; import ilog.views.util.swing.IlvSwingUtil; /** * This is a very simple application that uses the * <code>IlvDiagrammer</code> to perform a tree layout. It loads a style sheet * containing the tree layout specification. It allows to set various tree * layout parameters by using the <code>IlvSDMMutableStyleSheet</code>. */ public class TreeLayoutApp 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(); /** A text field to display messages */ JTextField msgLine = new JTextField(); /** The style sheet for temporary changes */ IlvSDMMutableStyleSheet styleSheet = new IlvSDMMutableStyleSheet(diagrammer.getEngine(), true, false); /** The flow direction selector */ JComboBox<String> flowDirectionSelector = new JComboBox<String>(); /** The link style selector */ JComboBox<String> linkStyleSelector = new JComboBox<String>(); /** The layout mode selector */ JComboBox<String> layoutModeSelector = new JComboBox<String>(); /** The default offset */ static final double DEFAULT_OFFSET = 20.; /** Text fields for the offset parameters */ NumberField branchOffsetSelector = new NumberField(0, 200, DEFAULT_OFFSET, true, 6, 5); NumberField siblingOffsetSelector = new NumberField(0, 200, DEFAULT_OFFSET, true, 6, 5); NumberField parentOffsetSelector = new NumberField(0, 200, DEFAULT_OFFSET, true, 6, 5); NumberField startAngleSelector = new NumberField(0, 360, 0, false, 3, 2); NumberField rootAngleRangeSelector = new NumberField(1, 360, 360, false, 3, 10); NumberField innerAngleRangeSelector = new NumberField(1, 360, 360, false, 3, 10); NumberField leafAngleRangeSelector = new NumberField(1, 360, 360, false, 3, 10); /** Whether to use automatic layout */ boolean autoLayout = false; /** Whether to do fit to view after layout */ boolean autoFit = true; /** Layout parameter panels. */ JPanel normalPanel; JPanel balloonPanel; /** * 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); // create the file selector JComboBox<String> fileSelector = new JComboBox<String>(); fileSelector.addItem("small"); fileSelector.addItem("medium"); fileSelector.addItem("large"); fileSelector.addItem("balloonSmall"); fileSelector.addItem("balloonMedium"); fileSelector.addItem("balloonLarge"); fileSelector.setToolTipText(getString("FileSelector.Tooltip")); 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(getString("RandomLayout.Button.Label")); randomizeButton.setToolTipText(getString("RandomLayout.Button.Tooltip")); randomizeButton.addActionListener(new ActionListener() { Override public void actionPerformed(ActionEvent evt) { randomize(); } }); // create the layout button JButton layoutButton = new JButton(getString("TreeLayout.Button.Label")); layoutButton.setToolTipText(getString("TreeLayout.Button.Tooltip")); 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 { setOffsetOrAngle("branchOffset", branchOffsetSelector); setOffsetOrAngle("siblingOffset", siblingOffsetSelector); setOffsetOrAngle("parentChildOffset", parentOffsetSelector); setOffsetOrAngle("balloonStartAngle", startAngleSelector); setOffsetOrAngle("balloonRootChildrenAngle", rootAngleRangeSelector); setOffsetOrAngle("balloonInnerChildrenAngle", innerAngleRangeSelector); setOffsetOrAngle("balloonLeafChildrenAngle", leafAngleRangeSelector); } finally { styleSheet.setAdjusting(false); } performLayout(); } }); JCheckBox fitToViewBox = new JCheckBox(getString("AutoFit.CheckBox.Label"), autoFit); fitToViewBox.setToolTipText(getString("AutoFit.CheckBox.Tooltip")); fitToViewBox.addActionListener(new ActionListener() { Override public void actionPerformed(ActionEvent evt) { autoFit = ((JCheckBox) evt.getSource()).isSelected(); } }); JCheckBox autoLayoutBox = new JCheckBox(getString("AutoLayout.CheckBox.Label"), autoLayout); autoLayoutBox.setToolTipText(getString("AutoLayout.CheckBox.Tooltip")); autoLayoutBox.addActionListener(new ActionListener() { Override public void actionPerformed(ActionEvent evt) { autoLayout = ((JCheckBox) evt.getSource()).isSelected(); } }); // create the panel for the layout buttons JPanel layoutButtonPanel = new JPanel(); layoutButtonPanel.setLayout(new FlowLayout()); layoutButtonPanel.add(new JLabel(" ")); layoutButtonPanel.add(autoLayoutBox); layoutButtonPanel.add(randomizeButton); layoutButtonPanel.add(layoutButton); layoutButtonPanel.add(fitToViewBox); // create the top panel with the toolbar and the file selector JPanel topPanel = new JPanel(); topPanel.setLayout(new FlowLayout(FlowLayout.LEADING)); topPanel.add(toolbar); JLabel label = new JLabel(getString("FileSelector.Label")); label.setToolTipText(getString("FileSelector.Tooltip")); topPanel.add(label); topPanel.add(fileSelector); // create the layout parameter panels normalPanel = createNormalParameterPanel(); balloonPanel = createBalloonParameterPanel(); // 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(normalPanel, 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); // set the component orientation according to the locale Locale loc = IlvSwingUtil.getDefaultLocale(); ComponentOrientation co = ComponentOrientation.getOrientation(loc); getContentPane().applyComponentOrientation(co); try { // load the main style file diagrammer.setStyleSheet(IlvSwingUtil.getRelativeURL(this, "data/tree.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 for balloon mode. */ private JPanel createBalloonParameterPanel() { JPanel panel = new JPanel(); GridBagLayout gridbag = new GridBagLayout(); GridBagConstraints c = new GridBagConstraints(); c.fill = GridBagConstraints.HORIZONTAL; c.anchor = GridBagConstraints.EAST; panel.setLayout(gridbag); // layout mode parameter c.gridx = 0; c.gridy = 0; JLabel label = new JLabel(getString("LayoutMode.Label")); label.setToolTipText(getString("LayoutMode.Tooltip")); panel.add(label, c); // angle spacing parameter c.gridx = 0; c.gridy = 1; label = new JLabel(getString("AngleSpacing.Label")); label.setToolTipText(getString("AngleSpacing.Tooltip")); panel.add(label, c); c.gridx = 1; JComboBox<String> balloonAngleSpacingSelector = new JComboBox<String>(); panel.add(balloonAngleSpacingSelector, c); balloonAngleSpacingSelector.addItem(getString("AngleSpacing.RegularMode")); balloonAngleSpacingSelector.addItem(getString("AngleSpacing.FastPropMode")); balloonAngleSpacingSelector.addItem(getString("AngleSpacing.SlowPropMode")); balloonAngleSpacingSelector.setSelectedIndex(2); balloonAngleSpacingSelector.setToolTipText(getString("AngleSpacing.Tooltip")); balloonAngleSpacingSelector.addActionListener(new ActionListener() { Override public void actionPerformed(ActionEvent event) { SuppressWarnings("unchecked") JComboBox<String> comboBox = (JComboBox<String>) event.getSource(); String mode = (String) comboBox.getSelectedItem(); setBalloonAngleSpacing(mode); } }); // radius mode parameter c.gridx = 0; c.gridy = 2; label = new JLabel(getString("RadiusMode.Label")); label.setToolTipText(getString("RadiusMode.Tooltip")); panel.add(label, c); c.gridx = 1; JComboBox<String> balloonRadiusModeSelector = new JComboBox<String>(); panel.add(balloonRadiusModeSelector, c); balloonRadiusModeSelector.addItem(getString("RadiusMode.VarMode")); balloonRadiusModeSelector.addItem(getString("RadiusMode.OptVarMode")); balloonRadiusModeSelector.addItem(getString("RadiusMode.UniLfMode")); balloonRadiusModeSelector.addItem(getString("RadiusMode.OptUniLfMode")); balloonRadiusModeSelector.addItem(getString("RadiusMode.UniMode")); balloonRadiusModeSelector.setSelectedIndex(3); balloonRadiusModeSelector.setToolTipText(getString("RadiusMode.Tooltip")); balloonRadiusModeSelector.addActionListener(new ActionListener() { Override public void actionPerformed(ActionEvent event) { SuppressWarnings("unchecked") JComboBox<String> comboBox = (JComboBox<String>) event.getSource(); String mode = (String) comboBox.getSelectedItem(); setBalloonRadiusMode(mode); } }); // branch offset = node offset c.gridx = 0; c.gridy = 3; c.insets = new Insets(5, 0, 0, 0); label = new JLabel(getString("NodeOffset.Label")); label.setToolTipText(getString("SiblingOffset.Tooltip")); panel.add(label, c); // branch offset = node offset c.gridx = 2; c.gridy = 0; c.insets = new Insets(0, 25, 0, 0); label = new JLabel(getString("StartAngle.Label")); label.setToolTipText(getString("StartAngle.Tooltip")); panel.add(label, c); c.gridy = 1; label = new JLabel(getString("RootAngleRange.Label")); label.setToolTipText(getString("RootAngleRange.Tooltip")); panel.add(label, c); c.gridy = 2; label = new JLabel(getString("InnerAngleRange.Label")); label.setToolTipText(getString("InnerAngleRange.Tooltip")); panel.add(label, c); c.gridy = 3; label = new JLabel(getString("LeafAngleRange.Label")); label.setToolTipText(getString("LeafAngleRange.Tooltip")); panel.add(label, c); c.gridx = 3; c.gridy = 0; panel.add(startAngleSelector, c); c.gridy = 1; panel.add(rootAngleRangeSelector, c); c.gridy = 2; panel.add(innerAngleRangeSelector, c); c.gridy = 3; panel.add(leafAngleRangeSelector, c); startAngleSelector.setToolTipText(getString("StartAngle.Tooltip")); startAngleSelector.addActionListener(new ActionListener() { Override public void actionPerformed(ActionEvent e) { setOffsetOrAngle("balloonStartAngle", (NumberField) e.getSource()); } }); rootAngleRangeSelector.setToolTipText(getString("RootAngleRange.Tooltip")); rootAngleRangeSelector.addActionListener(new ActionListener() { Override public void actionPerformed(ActionEvent e) { setOffsetOrAngle("balloonRootChildrenAngle", (NumberField) e.getSource()); } }); innerAngleRangeSelector.setToolTipText(getString("InnerAngleRange.Tooltip")); innerAngleRangeSelector.addActionListener(new ActionListener() { Override public void actionPerformed(ActionEvent e) { setOffsetOrAngle("balloonInnerChildrenAngle", (NumberField) e.getSource()); } }); leafAngleRangeSelector.setToolTipText(getString("LeafAngleRange.Tooltip")); leafAngleRangeSelector.addActionListener(new ActionListener() { Override public void actionPerformed(ActionEvent e) { setOffsetOrAngle("balloonLeafChildrenAngle", (NumberField) e.getSource()); } }); // set the component orientation according to the locale Locale loc = IlvSwingUtil.getDefaultLocale(); ComponentOrientation co = ComponentOrientation.getOrientation(loc); panel.applyComponentOrientation(co); return panel; } /** * Creates the layout parameter panel for normal mode. */ private JPanel createNormalParameterPanel() { JPanel panel = new JPanel(); GridBagLayout gridbag = new GridBagLayout(); GridBagConstraints c = new GridBagConstraints(); c.fill = GridBagConstraints.HORIZONTAL; c.anchor = GridBagConstraints.EAST; panel.setLayout(gridbag); // layout mode parameter c.gridx = 0; c.gridy = 0; JLabel label = new JLabel(getString("LayoutMode.Label")); label.setToolTipText(getString("LayoutMode.Tooltip")); panel.add(label, c); c.gridx = 1; layoutModeSelector = new JComboBox<String>(); panel.add(layoutModeSelector, c); layoutModeSelector.addItem(getString("LayoutMode.FreeMode")); layoutModeSelector.addItem(getString("LayoutMode.LevelMode")); layoutModeSelector.addItem(getString("LayoutMode.TipOverMode")); layoutModeSelector.addItem(getString("LayoutMode.BalloonMode")); layoutModeSelector.addItem(getString("LayoutMode.RadialMode")); layoutModeSelector.addItem(getString("LayoutMode.AltRadialMode")); layoutModeSelector.setSelectedIndex(0); layoutModeSelector.setToolTipText(getString("LayoutMode.Tooltip")); 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); } }); // flow direction parameter c.gridx = 0; c.gridy = 1; label = new JLabel(getString("FlowDirection.Label")); label.setToolTipText(getString("FlowDirection.Tooltip")); panel.add(label, c); c.gridx = 1; panel.add(flowDirectionSelector, c); flowDirectionSelector.addItem(getString("FlowDirection.Top")); flowDirectionSelector.addItem(getString("FlowDirection.Bottom")); flowDirectionSelector.addItem(getString("FlowDirection.Left")); flowDirectionSelector.addItem(getString("FlowDirection.Right")); flowDirectionSelector.setSelectedIndex(1); flowDirectionSelector.setToolTipText(getString("FlowDirection.Tooltip")); flowDirectionSelector.addActionListener(new ActionListener() { Override public void actionPerformed(ActionEvent event) { SuppressWarnings("unchecked") JComboBox<String> comboBox = (JComboBox<String>) event.getSource(); String flow = (String) comboBox.getSelectedItem(); setFlowDirection(flow); } }); // link style parameter c.gridx = 0; c.gridy = 2; label = new JLabel(getString("LinkStyle.Label")); label.setToolTipText(getString("LinkStyle.Tooltip")); panel.add(label, c); c.gridx = 1; panel.add(linkStyleSelector, c); linkStyleSelector.addItem(getString("LinkStyle.Orthogonal")); linkStyleSelector.addItem(getString("LinkStyle.Straight")); linkStyleSelector.addItem(getString("LinkStyle.Mixed")); linkStyleSelector.setSelectedIndex(0); linkStyleSelector.setToolTipText(getString("LinkStyle.Tooltip")); linkStyleSelector.addActionListener(new ActionListener() { Override public void actionPerformed(ActionEvent event) { SuppressWarnings("unchecked") JComboBox<String> comboBox = (JComboBox<String>) event.getSource(); String style = (String) comboBox.getSelectedItem(); setGlobalLinkStyle(style); } }); // alignment parameter c.gridx = 0; c.gridy = 3; label = new JLabel(getString("Alignment.Label")); label.setToolTipText(getString("Alignment.Tooltip")); panel.add(label, c); c.gridx = 1; JComboBox<String> alignmentSelector = new JComboBox<String>(); panel.add(alignmentSelector, c); alignmentSelector.addItem(getString("Alignment.Center")); alignmentSelector.addItem(getString("Alignment.East")); alignmentSelector.addItem(getString("Alignment.West")); alignmentSelector.addItem(getString("Alignment.TipOver")); alignmentSelector.setSelectedIndex(0); alignmentSelector.setToolTipText(getString("Alignment.Tooltip")); alignmentSelector.addActionListener(new ActionListener() { Override public void actionPerformed(ActionEvent event) { SuppressWarnings("unchecked") JComboBox<String> comboBox = (JComboBox<String>) event.getSource(); String alignment = (String) comboBox.getSelectedItem(); setGlobalAlignment(alignment); } }); // tree layout offset parameters c.gridx = 3; c.gridy = 1; panel.add(siblingOffsetSelector, c); c.gridy = 2; panel.add(branchOffsetSelector, c); c.gridy = 3; panel.add(parentOffsetSelector, c); c.gridx = 2; c.gridy = 0; c.insets = new Insets(0, 25, 0, 0); label = new JLabel(getString("OffsetIntro.Label")); panel.add(label, c); c.gridy = 1; label = new JLabel(getString("SiblingOffset.Label")); label.setToolTipText(getString("BranchOffset.Tooltip")); panel.add(label, c); c.gridy = 2; label = new JLabel(getString("BranchOffset.Label")); label.setToolTipText(getString("SiblingOffset.Tooltip")); panel.add(label, c); c.gridy = 3; label = new JLabel(getString("ParentChildOffset.Label")); label.setToolTipText(getString("ParentChildOffset.Tooltip")); panel.add(label, c); branchOffsetSelector.setToolTipText(getString("SiblingOffset.Tooltip")); branchOffsetSelector.addActionListener(new ActionListener() { Override public void actionPerformed(ActionEvent e) { setOffsetOrAngle("branchOffset", (NumberField) e.getSource()); } }); siblingOffsetSelector.setToolTipText(getString("BranchOffset.Tooltip")); siblingOffsetSelector.addActionListener(new ActionListener() { Override public void actionPerformed(ActionEvent e) { setOffsetOrAngle("siblingOffset", (NumberField) e.getSource()); } }); parentOffsetSelector.setToolTipText(getString("ParentChildOffset.Tooltip")); parentOffsetSelector.addActionListener(new ActionListener() { Override public void actionPerformed(ActionEvent e) { setOffsetOrAngle("parentChildOffset", (NumberField) e.getSource()); } }); // set the component orientation according to the locale Locale loc = IlvSwingUtil.getDefaultLocale(); ComponentOrientation co = ComponentOrientation.getOrientation(loc); panel.applyComponentOrientation(co); return panel; } /** * Install the parameter panel. */ private void installParameterPanel(JPanel panel) { if (panel.getParent() != null) return; GridBagConstraints c = new GridBagConstraints(); c.fill = GridBagConstraints.HORIZONTAL; c.anchor = GridBagConstraints.EAST; if (normalPanel.getParent() != null) { JPanel parent = (JPanel) normalPanel.getParent(); parent.remove(normalPanel); normalPanel.remove(layoutModeSelector); c.gridy = 0; c.gridx = 1; panel.add(layoutModeSelector, c); normalPanel.remove(branchOffsetSelector); c.gridy = 3; c.gridx = 1; c.insets = new Insets(5, 0, 0, 0); panel.add(branchOffsetSelector, c); parent.add(panel, BorderLayout.CENTER); parent.revalidate(); parent.repaint(); } else if (balloonPanel.getParent() != null) { JPanel parent = (JPanel) balloonPanel.getParent(); parent.remove(balloonPanel); balloonPanel.remove(layoutModeSelector); c.gridy = 0; c.gridx = 1; panel.add(layoutModeSelector, c); balloonPanel.remove(branchOffsetSelector); c.gridy = 2; c.gridx = 3; panel.add(branchOffsetSelector, c); parent.add(panel, BorderLayout.CENTER); parent.revalidate(); parent.repaint(); } } /** * 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(getString("FileReadingStartMessage"), fileNameBase); diagrammer.setDataFile(IlvSwingUtil.getRelativeURL(this, "data/" + fileNameBase + ".xml")); showMessage(getString("FileReadingDoneMessage"), fileNameBase); } catch (Exception e) { showMessage(e.getMessage()); } } /** * Sets the layout mode. */ private void setLayoutMode(String mode) { styleSheet.setDeclaration("GraphLayout", "aspectRatio", "1.5"); if (mode.equals(getString("LayoutMode.FreeMode"))) { flowDirectionSelector.setEnabled(true); linkStyleSelector.setEnabled(true); styleSheet.setDeclaration("GraphLayout", "layoutMode", "FREE"); installParameterPanel(normalPanel); } else if (mode.equals(getString("LayoutMode.LevelMode"))) { flowDirectionSelector.setEnabled(true); linkStyleSelector.setEnabled(true); styleSheet.setDeclaration("GraphLayout", "layoutMode", "LEVEL"); installParameterPanel(normalPanel); } else if (mode.equals(getString("LayoutMode.TipOverMode"))) { flowDirectionSelector.setEnabled(true); linkStyleSelector.setEnabled(true); styleSheet.setDeclaration("GraphLayout", "layoutMode", "TIP_LEAVES_OVER"); installParameterPanel(normalPanel); } else if (mode.equals(getString("LayoutMode.BalloonMode"))) { flowDirectionSelector.setEnabled(false); linkStyleSelector.setEnabled(false); styleSheet.setDeclaration("GraphLayout", "layoutMode", "BALLOON"); styleSheet.setDeclaration("GraphLayout", "aspectRatio", "1.0"); installParameterPanel(balloonPanel); } else if (mode.equals(getString("LayoutMode.RadialMode"))) { flowDirectionSelector.setEnabled(false); linkStyleSelector.setEnabled(false); styleSheet.setDeclaration("GraphLayout", "layoutMode", "RADIAL"); installParameterPanel(normalPanel); } else if (mode.equals(getString("LayoutMode.AltRadialMode"))) { flowDirectionSelector.setEnabled(false); linkStyleSelector.setEnabled(false); styleSheet.setDeclaration("GraphLayout", "layoutMode", "ALTERNATING_RADIAL"); installParameterPanel(normalPanel); } if (autoLayout) performLayout(); } /** * Sets the flow direction. */ private void setFlowDirection(String flow) { if (flow.equals(getString("FlowDirection.Top"))) styleSheet.setDeclaration("GraphLayout", "flowDirection", "Top"); else if (flow.equals(getString("FlowDirection.Bottom"))) styleSheet.setDeclaration("GraphLayout", "flowDirection", "Bottom"); else if (flow.equals(getString("FlowDirection.Left"))) styleSheet.setDeclaration("GraphLayout", "flowDirection", "Left"); else if (flow.equals(getString("FlowDirection.Right"))) styleSheet.setDeclaration("GraphLayout", "flowDirection", "Right"); if (autoLayout) performLayout(); } /** * Sets the global link style. */ private void setGlobalLinkStyle(String style) { if (style.equals(getString("LinkStyle.Orthogonal"))) styleSheet.setDeclaration("GraphLayout", "globalLinkStyle", "ORTHOGONAL_STYLE"); else if (style.equals(getString("LinkStyle.Straight"))) styleSheet.setDeclaration("GraphLayout", "globalLinkStyle", "STRAIGHT_LINE_STYLE"); else if (style.equals(getString("LinkStyle.Mixed"))) styleSheet.setDeclaration("GraphLayout", "globalLinkStyle", "MIXED_STYLE"); if (autoLayout) performLayout(); } /** * Sets the global alignment. */ private void setGlobalAlignment(String alignment) { if (alignment.equals(getString("Alignment.Center"))) styleSheet.setDeclaration("GraphLayout", "globalAlignment", "CENTER"); else if (alignment.equals(getString("Alignment.East"))) styleSheet.setDeclaration("GraphLayout", "globalAlignment", "EAST"); else if (alignment.equals(getString("Alignment.West"))) styleSheet.setDeclaration("GraphLayout", "globalAlignment", "WEST"); else if (alignment.equals(getString("Alignment.TipOver"))) styleSheet.setDeclaration("GraphLayout", "globalAlignment", "TIP_OVER"); if (autoLayout) performLayout(); } /** * Sets the angle spacing mode in balloon mode. */ private void setBalloonAngleSpacing(String mode) { if (mode.equals(getString("AngleSpacing.RegularMode"))) styleSheet.setDeclaration("GraphLayout", "balloonAngleSpacing", "REGULAR"); else if (mode.equals(getString("AngleSpacing.FastPropMode"))) styleSheet.setDeclaration("GraphLayout", "balloonAngleSpacing", "FAST_PROPORTIONAL"); else if (mode.equals(getString("AngleSpacing.SlowPropMode"))) styleSheet.setDeclaration("GraphLayout", "balloonAngleSpacing", "PROPORTIONAL"); if (autoLayout) performLayout(); } /** * Sets the radius mode in balloon mode. */ private void setBalloonRadiusMode(String mode) { if (mode.equals(getString("RadiusMode.VarMode"))) styleSheet.setDeclaration("GraphLayout", "balloonRadiusMode", "VARIABLE_RADIUS"); else if (mode.equals(getString("RadiusMode.OptVarMode"))) styleSheet.setDeclaration("GraphLayout", "balloonRadiusMode", "OPTIMIZED_VARIABLE_RADIUS"); else if (mode.equals(getString("RadiusMode.UniLfMode"))) styleSheet.setDeclaration("GraphLayout", "balloonRadiusMode", "UNIFORM_LEAVES_RADIUS"); else if (mode.equals(getString("RadiusMode.OptUniLfMode"))) styleSheet.setDeclaration("GraphLayout", "balloonRadiusMode", "OPTIMIZED_UNIFORM_LEAVES_RADIUS"); else if (mode.equals(getString("RadiusMode.UniMode"))) styleSheet.setDeclaration("GraphLayout", "balloonRadiusMode", "UNIFORM_RADIUS"); if (autoLayout) performLayout(); } /** * Sets the sibling, branch or parent/child offset from a textfield. */ private void setOffsetOrAngle(String property, NumberField valueSelector) { try { // get the value of the parameter from the valueSelector double value = valueSelector.getValue(); // set the new value of the layout property if (property.contains("Angle")) styleSheet.setDeclaration("GraphLayout", property, "" + (int) value); else styleSheet.setDeclaration("GraphLayout", property, "" + value); } catch (Exception ex) { showMessage(getString("IllegalPropertyMessage"), property, ex.getMessage()); } if (autoLayout) performLayout(); } /** * Performs the tree layout. The layout type is stored in the CSS file, * therefore we don't need to set the tree layout explicitely. After loading * the graph and the CSS style sheet, the tree layout is already instantiated. */ private void performLayout() { showMessage(getString("LayoutStartMessage")); // initialize the iteration listener layoutListener.initialize(getGraphLayout()); // Perform Tree Layout as node layout. Tree 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(getString("LayoutDoneMessage"), // report.codeToString(report.getCode())); showMessage(""); // if layout was successfully done, fit in the diagrammer's view if (report.getCode() == IlvGraphLayoutReport.LAYOUT_DONE) { if (autoFit) diagrammer.fitToContents(); } } } } /** * 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 tree 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()); } void showMessage(String msgformat, Object... val) { showMessage(MessageFormat.format(msgformat, val)); } /** * Returns a string. */ static String getString(String key) { return IlvResourceUtil.getString(key, TreeLayoutApp.class, IlvLocaleUtil.getCurrentLocale()); } /** * 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() { TreeLayoutApp app = new TreeLayoutApp(); app.init(); JFrame frame = new JFrame(getString("Frame.Label")); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setSize(600, 600); frame.getContentPane().add(app); frame.setVisible(true); } }); } // -------------------------------------------------------------------------- /** * 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 the percentage completed by the layout * each time the method layoutStepPerformed is called, that is after each * iteration of the Tree Layout algorithm. */ class LayoutIterationListener implements GraphLayoutEventListener { IlvGraphLayout layout; private float oldPercentage; /** * This method is automatically called by the layout algorithm. */ Override public void layoutStepPerformed(GraphLayoutEvent event) { float percentage = event.getLayoutReport().getPercentageComplete(); if (percentage != oldPercentage) { showMessage(getString("PercentageCompleteMessage"), percentage); oldPercentage = percentage; } } /** * 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); } oldPercentage = -1.0f; } } }