/* * 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.SystemColor; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.IOException; import java.io.PrintWriter; import java.io.StringReader; import java.io.StringWriter; import java.net.URL; import javax.swing.JButton; 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 javax.swing.JToolBar; import javax.swing.SwingUtilities; import ilog.views.diagrammer.IlvDiagrammer; import ilog.views.diagrammer.application.IlvDiagrammerAction; import ilog.views.diagrammer.application.IlvDiagrammerToolBar; import ilog.views.diagrammer.application.IlvDiagrammerViewBar; import ilog.views.graphlayout.IlvGraphLayout; import ilog.views.graphlayout.random.IlvRandomLayout; import ilog.views.sdm.IlvSDMEngine; import ilog.views.sdm.renderer.graphlayout.IlvGraphLayoutRenderer; import ilog.views.util.IlvProductUtil; /** * This is a very simple application that shows how to specify * constraints of hierarchical layout in a Diagrammer application. It shows * three variants: - how to specify constraints in the style sheet directly. See * sampleCSS.css in the resources directory of this sample. - how to specify * constraints using a constraints URL. See sampleURL.css and Constraints.txt in * the resources directory of this sample. - how to code constraints * programmatically (even though this rarely makes sense when using CSS. It * makes more sense if CSS is not used at all). */ public class HierarchicalConstraintsApp 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 diagram component */ IlvDiagrammer diagrammer = new IlvDiagrammer(); /** A text field to display messages */ JTextField msgLine = new JTextField(); /** * Initializes the application. */ public void init() { IlvDiagrammerToolBar toolbar = new IlvDiagrammerViewBar(JToolBar.HORIZONTAL); 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); JComboBox<String> styleSheetSelector = new JComboBox<String>(); styleSheetSelector.addItem("CSS"); styleSheetSelector.addItem("URL"); styleSheetSelector.addItem("No Constraints"); styleSheetSelector.setToolTipText("The way constraints are specified"); styleSheetSelector.setSelectedIndex(2); styleSheetSelector.addActionListener(new ActionListener() { Override public void actionPerformed(ActionEvent event) { SuppressWarnings("unchecked") JComboBox<String> comboBox = (JComboBox<String>) event.getSource(); String selection = (String) comboBox.getSelectedItem(); if (selection.equals("No Constraints")) selection = "NoConstraints"; loadStyleSheet(selection); } }); // 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 hierarchical layout"); layoutButton.addActionListener(new ActionListener() { Override public void actionPerformed(ActionEvent evt) { diagrammer.layoutAllNodes(); } }); // 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("Constraints from:")); topPanel.add(styleSheetSelector); // 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(msgLine, BorderLayout.SOUTH); msgLine.setEditable(false); // put diagram component, 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); // tell the actions of the toolbar what the diagram component is. IlvDiagrammerAction.updateActions(getRootPane(), diagrammer); // load the sample data loadDataFile("Sample"); // load the initial style file loadStyleSheet("NoConstraints"); } /** * Called when the app is made visible. */ public void start() { // show everything diagrammer.fitToContents(); } /** * Loads a sample data file. * * @param fileNameBase * The base of the filename, excluding the path prefix and the * extension suffix. */ private void loadDataFile(String fileNameBase) { showMessage("Reading " + fileNameBase + ".xml ..."); try { // first try: reading in an application diagrammer.setDataFile(new URL("file:resources/" + fileNameBase + ".xml")); showMessage("Reading " + fileNameBase + ".xml done."); } catch (Exception e) { showMessage(e.getMessage()); } } /** * Loads a style file. * * @param styleFileBase * The base of the filename of the style file, excluding the path * prefix and the extension suffix. */ private void loadStyleSheet(String fileNameBase) { // load the main style file showMessage("Reading Sample" + fileNameBase + ".css ..."); try { // first try: reading in an application diagrammer.setStyleSheet(new URL("file:resources/Sample" + fileNameBase + ".css")); showMessage("Reading Sample" + fileNameBase + ".css done."); // fit to contents diagrammer.fitToContents(); } catch (Exception e) { showMessage(e.getMessage()); } } /** * 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(); // save the old constraints String constraints = saveConstraints(diagrammer.getEngine()); // tell the diagram component to temporarily use the random layout, which // disables the tree layout. setGraphLayout(randomLayout); // perform the layout diagrammer.layoutAllNodes(); // restore the old layout instance. Unfortunately // all constraints are lost. setGraphLayout(oldLayout); // therefore restore the constraints afterwards restoreConstraints(diagrammer.getEngine(), constraints); } /** * Saves the constraints to a string. */ private String saveConstraints(IlvSDMEngine engine) { StringWriter writer = new StringWriter(); engine.getNodeLayoutRenderer().writeConstraints(new PrintWriter(writer)); try { writer.close(); } catch (IOException ex) { } return writer.toString(); } /** * Restores the constraints from a string. */ private void restoreConstraints(IlvSDMEngine engine, String s) { StringReader reader = new StringReader(s); try { engine.getNodeLayoutRenderer().readConstraints(reader); } catch (IOException ex) { ex.printStackTrace(); } } /** * Returns the graph layout currently used by the diagram component. */ private IlvGraphLayout getGraphLayout() { IlvGraphLayoutRenderer renderer = (IlvGraphLayoutRenderer) diagrammer.getEngine().getNodeLayoutRenderer(); return renderer == null ? null : renderer.getGraphLayout(); } /** * Sets the graph layout currently used by the diagram component. */ 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) { final HierarchicalConstraintsApp app = new HierarchicalConstraintsApp(); app.init(); // Since JDK 1.4, Sun recommends to make the component visible through // invokeLater. SwingUtilities.invokeLater(new Runnable() { Override public void run() { JFrame frame = new JFrame("Tree Layout Example"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setSize(600, 600); frame.getContentPane().add(app); frame.setVisible(true); } }); } }