/* * 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.Container; import java.awt.Cursor; import java.awt.Dimension; import java.awt.FlowLayout; import java.awt.Frame; import java.awt.Graphics2D; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.Insets; import java.awt.Point; import java.awt.Window; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.ItemEvent; import java.awt.event.ItemListener; import java.awt.image.BufferedImage; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.FileWriter; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.net.MalformedURLException; import java.net.URL; import java.text.MessageFormat; import java.util.ArrayList; import java.util.Enumeration; import java.util.ResourceBundle; import java.util.Vector; import javax.swing.Action; import javax.swing.BorderFactory; import javax.swing.Icon; import javax.swing.ImageIcon; import javax.swing.JButton; import javax.swing.JCheckBox; import javax.swing.JComboBox; import javax.swing.JComponent; import javax.swing.JDialog; import javax.swing.JEditorPane; import javax.swing.JFileChooser; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JMenuBar; import javax.swing.JPanel; import javax.swing.JProgressBar; import javax.swing.JRootPane; import javax.swing.JScrollPane; import javax.swing.JSeparator; import javax.swing.JSplitPane; import javax.swing.JTextField; import javax.swing.JToolBar; import javax.swing.SwingUtilities; import javax.swing.Timer; import javax.swing.border.Border; import javax.swing.event.HyperlinkEvent; import javax.swing.event.HyperlinkListener; import javax.swing.filechooser.FileFilter; import javax.swing.text.html.HTMLEditorKit; import ilog.views.IlvGrapher; import ilog.views.IlvManagerView; import ilog.views.IlvRect; import ilog.views.IlvTransformer; import ilog.views.diagrammer.IlvDiagrammer; import ilog.views.diagrammer.application.IlvDiagrammerAction; import ilog.views.diagrammer.application.IlvDiagrammerHelpMenu; import ilog.views.diagrammer.application.IlvDiagrammerMenu; import ilog.views.diagrammer.application.IlvDiagrammerToolBar; import ilog.views.diagrammer.application.IlvDiagrammerViewBar; import ilog.views.diagrammer.datasource.IlvXMLDataSource; import ilog.views.diagrammer.project.IlvDiagrammerProject; import ilog.views.sdm.IlvSDMEngine; import ilog.views.sdm.IlvSDMModel; import ilog.views.sdm.event.SDMGraphLayoutRendererEvent; import ilog.views.sdm.event.SDMGraphLayoutRendererListener; import ilog.views.sdm.model.IlvDefaultSDMModel; import ilog.views.sdm.model.IlvPreorderEnumeration; import ilog.views.sdm.renderer.graphlayout.IlvLinkLayoutRenderer; import ilog.views.sdm.util.IlvXMLConnector; import ilog.views.swing.IlvJScrollManagerView; import ilog.views.util.IlvImageUtil; import ilog.views.util.IlvProductUtil; import ilog.views.util.convert.IlvConvert; import ilog.views.util.internal.IlvURLUtil; import ilog.views.util.swing.IlvSwingUtil; /** * This sample shows the performances of the Diagrammer component when loading * graphs of various sizes and using various graphic features. It also compares * the performances of the SDM engine with the Graphic Framework API. */ public class DiagrammerBench extends JRootPane { private static final int coldStartCount = 3; private static final String tmpIVLFile = "data/tmp.ivl"; private JFrame frame; private String titleFormat; private ResourceBundle bundle; private URL baseURL; private IlvDiagrammer diagrammer; private JButton createButton; private IlvManagerView gfView; private IlvJScrollManagerView gfScrollView; private Container contentPane; private int graphSize = 3; // 10^3 = 1000; private boolean subgraphs; private boolean intergraphLinks; private String nodeLinkCountFormat; private String nodeLinkCountTooltipFormat; private String sizeFormat; private String timeFormat; private String speedFormat; private String percentFormat; private String memoryFormat; private String memoryBarFormat; private String ivlRatioPercentFormat; private String ivlRatioFormatFaster; private String ivlRatioFormatSlower; private String emptyBarString; private String emptyTextString; private String runningString; private int nodeCount; private int linkCount; private JTextField nodeLinkCountText; private JTextField memoryText; private long memoryBefore; private JProgressBar memoryBar; private Color normalMemoryColor; private Color fullMemoryColor; private Counter graphCreationCounter; private Counter renderingCounter; private Counter nodeLayoutCounter; private Counter linkLayoutCounter; private Counter paintingCounter; private Counter totalCounter; private Counter ivlCounter; private Counter ivlReadCounter; private Counter ivlPaintCounter; private JTextField ivlPercentText; private boolean usePercentText = false; private JTextField ivlRatioText; private JTextField messageText; private Color normalMessageColor; private Color errorMessageColor; private JComboBox<String> fillCombo; private JComboBox<String> strokeCombo; private JComboBox<String> glinkCombo; private JCheckBox intergraphLinksCheckBox; /* * private JCheckBox savePositionsCheckBox; private JCheckBox * layoutOnZoomCheckBox; private JCheckBox connectToShapeNodesCheckBox; * private JCheckBox connectToShapeLinksCheckBox; */ private JCheckBox compareWithIVLCheckBox; private boolean loadFromXML = true; private boolean compareWithIVL = true; private Icon nomarkIcon; private Icon markIcon; private IlvDiagrammerProject project; private JFileChooser fileChooser; private URL[] savedCSS; private int autoGCCount = 2; private Window helpWindow; private JEditorPane helpPane; private ByteArrayOutputStream ivlByteStream; // private sun.misc.Perf perf; // private long frequency; private long[] rab; private Cursor busyCursor; private boolean ivlError; private boolean running; private GraphData graphData = new GraphData(); /** * The main method, used when the sample is launched as an application. */ public static void main(String[] args) { javax.swing.SwingUtilities.invokeLater(new Runnable() { Override public void run() { DiagrammerBench bench = new DiagrammerBench(); JFrame frame = new JFrame(); bench.frame = frame; bench.setFrameTitle(bench.getString("NoDiagram")); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); try { bench.init(frame.getContentPane(), new URL("file:./")); } catch (MalformedURLException mue) { bench.error(mue); } frame.pack(); frame.setLocation(100, 100); frame.setVisible(true); } }); } private void setFrameTitle(String s) { if (frame != null) { frame.setTitle(MessageFormat.format(titleFormat, new Object[] { s })); } } /** * Constructor. Initializes strings, icons. */ public DiagrammerBench() { // 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); bundle = ResourceBundle.getBundle("bench"); titleFormat = getString("TitleFormat"); sizeFormat = getString("SizeFormat"); nodeLinkCountFormat = getString("NodeLinkCountFormat"); nodeLinkCountTooltipFormat = getString("NodeLinkCountTooltipFormat"); timeFormat = getString("TimeFormat"); speedFormat = getString("SpeedFormat"); percentFormat = getString("PercentFormat"); memoryFormat = getString("MemoryFormat"); memoryBarFormat = getString("MemoryBarFormat"); ivlRatioPercentFormat = getString("IVLRatioPercentFormat"); ivlRatioFormatFaster = getString("IVLRatioFormatFaster"); ivlRatioFormatSlower = getString("IVLRatioFormatSlower"); emptyBarString = getString("EmptyBar"); emptyTextString = getString("EmptyText"); runningString = getString("Running"); try { nomarkIcon = new ImageIcon(IlvImageUtil.getImageFromFile(getClass(), "nomark.gif")); markIcon = new ImageIcon(IlvImageUtil.getImageFromFile(getClass(), "mark.gif")); } catch (IOException e) { error(e); } busyCursor = Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR); } /** * Utility method to read an internationalized message. */ private String getString(String key) { return bundle.getString("DiagrammerBench." + key); } /** * Initializes the GUI. * * @param contentPane * The container of the application. */ public void init(Container contentPane, URL baseURL) { if (Runtime.getRuntime().maxMemory() < 200 * 1024 * 1024) { IlvSwingUtil.showErrorDialog(null, getString("MaxMemoryNotSet")); System.exit(1); } JPanel panel; JLabel label; JComboBox<String> combo; JTextField text; this.contentPane = contentPane; this.baseURL = baseURL; contentPane.setLayout(new BorderLayout(2, 2)); // Create the menu bar. // JMenuBar menubar = new JMenuBar(); // We reuse some Diagrammer actions, just to reuse the strings and // icons, but we redefine the actual action listener code. // IlvDiagrammerMenu fileMenu = new IlvDiagrammerMenu("Diagrammer.Menu.File"); fileMenu.addAction(IlvDiagrammerAction.open); fileMenu.addAction(IlvDiagrammerAction.saveAs); fileMenu.addAction(IlvDiagrammerAction.refresh); fileMenu.addSeparator(); fileMenu.addAction(IlvDiagrammerAction.exit); menubar.add(fileMenu); IlvDiagrammerAction.open.setHandler(new IlvDiagrammerAction.Handler() { Override public void perform(IlvDiagrammerAction action, IlvDiagrammer diagrammer, ActionEvent event) throws Exception { if (fileChooser == null) { fileChooser = new JFileChooser(); fileChooser.setFileFilter(new FileFilter() { Override public boolean accept(File f) { return f.isDirectory() || f.getName().endsWith(IlvDiagrammerProject.suffix); } Override public String getDescription() { return getString("IDPRFileDescription"); } }); fileChooser.setCurrentDirectory(new File(".")); } if (fileChooser.showOpenDialog(DiagrammerBench.this.contentPane) == JFileChooser.APPROVE_OPTION) { URL url = fileChooser.getSelectedFile().toURI().toURL(); project = new IlvDiagrammerProject(url); if (!(project.getDataSource() instanceof IlvXMLDataSource)) { throw new RuntimeException(getString("NotAnXMLDataSource")); } createGraph(); } } Override public void update(IlvDiagrammerAction action, IlvDiagrammer diagrammer) throws Exception { action.setEnabled(true); } }); IlvDiagrammerAction.saveAs.setHandler(new IlvDiagrammerAction.Handler() { Override public void perform(IlvDiagrammerAction action, IlvDiagrammer diagrammer, ActionEvent event) throws Exception { IlvDiagrammerProject project = DiagrammerBench.this.project; if (project == null) { project = new IlvDiagrammerProject(); URL dataURL = getDataFile(false); IlvXMLDataSource dataSource = new IlvXMLDataSource(); dataSource.setDataURL(dataURL); project.setDataSource(dataSource); URL[] styleSheets = diagrammer.getStyleSheets(); if (styleSheets.length > 0) { project.setStyleSheet(styleSheets[0]); for (int i = 1; i < styleSheets.length; i++) { project.addStyleSheet(styleSheets[i]); } } } diagrammer.setProject(project); super.perform(action, diagrammer, event); // Re-save XML and full CSS with the same base name as the // project. // URL projectURL = project.getProjectURL(); String base = projectURL.toExternalForm(); int dot = base.lastIndexOf('.'); if (dot > 0) { base = base.substring(0, dot); } URL xmlURL = new URL(base + ".xml"); ((IlvXMLDataSource) project.getDataSource()).setDataURL(xmlURL); project.getDataSource().write(diagrammer); URL cssURL = new URL(base + ".css"); BufferedWriter out = new BufferedWriter(new FileWriter(cssURL.getFile())); URL[] css = project.getStyleSheets(); for (int i = 0; i < css.length; i++) { copyCSS(out, css[i]); } out.close(); project.setStyleSheet(cssURL); project.write(projectURL); diagrammer.setProject(null); } private void copyCSS(BufferedWriter out, URL css) throws IOException { BufferedReader in = new BufferedReader(new InputStreamReader(IlvURLUtil.prepare(css).openStream())); out.write("// " + css.toExternalForm() + "\n\n"); String line; while ((line = in.readLine()) != null) { line = line.trim(); if (line.startsWith("import")) { String importName = line.substring(7).trim(); if (importName.startsWith("\"")) importName = importName.substring(1); if (importName.endsWith("\"")) importName = importName.substring(0, importName.length() - 1); URL importCSS = new URL(css, importName); copyCSS(out, importCSS); } else { out.write(line); } out.write("\n"); } in.close(); out.write("\n"); } Override public void update(IlvDiagrammerAction action, IlvDiagrammer diagrammer) throws Exception { action.setEnabled(diagrammer != null && diagrammer.canPrint()); } }); IlvDiagrammerAction.exit.setHandler(new IlvDiagrammerAction.Handler() { Override public void update(IlvDiagrammerAction action, IlvDiagrammer diagrammer) throws Exception { action.setEnabled(true); } }); IlvDiagrammerAction.refresh.setHandler(new IlvDiagrammerAction.Handler() { Override public void perform(IlvDiagrammerAction action, IlvDiagrammer diagrammer, ActionEvent event) throws Exception { createGraph(); } }); IlvDiagrammerMenu helpMenu = new IlvDiagrammerHelpMenu(); menubar.add(helpMenu); IlvDiagrammerAction.help.setHandler(new IlvDiagrammerAction.Handler() { Override public void perform(IlvDiagrammerAction action, IlvDiagrammer diagrammer, ActionEvent event) throws Exception { showHelp("top"); } }); IlvDiagrammerAction.about.putValue(IlvDiagrammerAction.ABOUT_APPLICATION_NAME, getString("AboutApplicationName")); ((JComponent) contentPane).getRootPane().setJMenuBar(menubar); // Create the SDM view: // JPanel sdmPanel = new JPanel(new BorderLayout()); panel = new JPanel(new BorderLayout()); sdmPanel.add(panel, BorderLayout.CENTER); JLabel sdmTitle = new JLabel(getString("SDMViewTitle")); sdmTitle.setToolTipText(getString("SDMView.ToolTip")); JPanel sdmTitlePanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 0, 0)); sdmTitlePanel.add(sdmTitle); panel.add(sdmTitlePanel, BorderLayout.NORTH); diagrammer = new IlvDiagrammer(); try { diagrammer.setStyleSheet(getClass().getResource("default.css")); } catch (Exception e) { error(e); } diagrammer.setScrollable(true); diagrammer.setPreferredSize(new Dimension(500, 200)); panel.add(diagrammer, BorderLayout.CENTER); IlvDiagrammerViewBar sdmToolbar = new IlvDiagrammerViewBar(JToolBar.VERTICAL); sdmToolbar.removeAction(IlvDiagrammerAction.select); sdmToolbar.setFloatable(false); panel.add(sdmToolbar, BorderLayout.WEST); // Create the GF view: // JPanel gfPanel = new JPanel(new BorderLayout()); panel = new JPanel(new BorderLayout()); gfPanel.add(panel, BorderLayout.CENTER); JLabel gfTitle = new JLabel(getString("GFViewTitle")); gfTitle.setToolTipText(getString("GFView.ToolTip")); JPanel gfTitlePanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 0, 0)); gfTitlePanel.add(gfTitle); panel.add(gfTitlePanel, BorderLayout.NORTH); IlvDiagrammer gfDiagrammer = new IlvDiagrammer(); gfDiagrammer.setScrollable(true); gfView = gfDiagrammer.getView(); gfScrollView = (IlvJScrollManagerView) gfView.getParent(); gfDiagrammer.setPreferredSize(new Dimension(500, 200)); panel.add(gfDiagrammer, BorderLayout.CENTER); GFToolBar gfToolbar = new GFToolBar(sdmToolbar.getActions(), gfDiagrammer); gfToolbar.setFloatable(false); panel.add(gfToolbar, BorderLayout.WEST); // The splitter that contains the SDM and GF views: // JSplitPane splitter = new JSplitPane(JSplitPane.VERTICAL_SPLIT, sdmPanel, gfPanel); splitter.setDividerSize(2); contentPane.add(splitter, BorderLayout.CENTER); splitter.setDividerLocation(0.5); // Create the parameter panel,that lets the user choose the graph size and // style. // JPanel paramPanel = new JPanel(new GridBagLayout()); contentPane.add(paramPanel, BorderLayout.NORTH); GridBagConstraints c = new GridBagConstraints(); c.gridx = 0; c.gridy = 0; c.insets = new Insets(3, 3, 3, 3); c.weightx = 1; c.weighty = 1; c.fill = GridBagConstraints.NONE; // ********************************* // First line of parameters panel: // ********************************* // The Create Graph button: // createButton = new JButton(getString("Create")); createButton.setToolTipText(getString("Create.ToolTip")); try { createButton.setIcon(new ImageIcon(IlvImageUtil.getImageFromFile(getClass(), "go.gif"))); } catch (IOException e) { error(e); } createButton.addActionListener(new ActionListener() { Override public void actionPerformed(ActionEvent e) { project = null; createGraph(); } }); c.fill = GridBagConstraints.BOTH; c.gridheight = 2; paramPanel.add(createButton, c); c.gridheight = 1; c.fill = GridBagConstraints.NONE; c.gridx++; // Column headers: // label = new JLabel(getString("GraphData")); label.setToolTipText(getString("GraphData.ToolTip")); paramPanel.add(label, c); c.gridx++; label = new JLabel(getString("Nodes")); label.setToolTipText(getString("Nodes.ToolTip")); paramPanel.add(label, c); c.gridx++; label = new JLabel(getString("Links")); label.setToolTipText(getString("Links.ToolTip")); paramPanel.add(label, c); c.gridx++; label = new JLabel(getString("NodeLayout")); label.setToolTipText(getString("NodeLayout.ToolTip")); paramPanel.add(label, c); c.gridx++; label = new JLabel(getString("LinkLayout")); label.setToolTipText(getString("LinkLayout.ToolTip")); paramPanel.add(label, c); c.fill = GridBagConstraints.HORIZONTAL; c.gridy++; c.gridx = 1; // First column = create button. // The graph size combo: // final JComboBox<String> sizeCombo = new JComboBox<String>( new String[] { MessageFormat.format(sizeFormat, new Object[] { "10" }), MessageFormat.format(sizeFormat, new Object[] { "100" }), MessageFormat.format(sizeFormat, new Object[] { "1000" }), MessageFormat.format(sizeFormat, new Object[] { "10000" }), /* * Too big. MessageFormat.format(sizeFormat, new Object[] { "100000" }), */ }); int maxSize = 10000; // Used to compute size of node/link count text field. sizeCombo.setToolTipText(getString("Size.ToolTip")); sizeCombo.setSelectedIndex(graphSize - 1); sizeCombo.addItemListener(new ItemListener() { Override public void itemStateChanged(ItemEvent e) { if (e.getStateChange() == ItemEvent.SELECTED) { graphSize = sizeCombo.getSelectedIndex() + 1; } } }); paramPanel.add(sizeCombo, c); c.gridx++; // The main node style combo: // final JComboBox<String> nodeCombo = combo = createStyleCombo( new String[] { "Rectangle", "Text", "Shape", "GeneralNode", "Composite" }, new String[] { "rect.css", "text.css", "shape.css", "gnode.css", "composite.css" }); nodeCombo.setToolTipText(getString("NodeType.ToolTip")); combo.addItemListener(new ItemListener() { Override public void itemStateChanged(ItemEvent e) { SuppressWarnings("unchecked") int selIdx = ((JComboBox<String>) e.getSource()).getSelectedIndex(); if (e.getStateChange() == ItemEvent.SELECTED && selIdx == 0) { if (fillCombo.getSelectedIndex() > 1) fillCombo.setSelectedIndex(1); } if (e.getStateChange() == ItemEvent.SELECTED && selIdx < 2) { strokeCombo.setSelectedIndex(0); strokeCombo.setEnabled(false); } else { strokeCombo.setEnabled(true); } } }); paramPanel.add(combo, c); c.gridx++; // The main link style combo: // final JComboBox<String> linkCombo = combo = createStyleCombo(new String[] { "Polyline", "GeneralLink" }, new String[] { "polylink.css", "glink.css" }); linkCombo.setToolTipText(getString("LinkType.ToolTip")); combo.addItemListener(new ItemListener() { Override SuppressWarnings("unchecked") public void itemStateChanged(ItemEvent e) { if (e.getStateChange() == ItemEvent.SELECTED && ((JComboBox<String>) e.getSource()).getSelectedIndex() == 0) { if (glinkCombo.getSelectedIndex() > 1) glinkCombo.setSelectedIndex(1); } } }); paramPanel.add(combo, c); c.gridx++; // The node layout combo: // final JComboBox<String> nodeLayoutCombo = combo = createStyleCombo(new String[] { "None", "Hierarchical", "Tree" }, new String[] { "nonodelayout.css", "hierarchical.css", "tree.css", }); nodeLayoutCombo.setToolTipText(getString("NodeLayoutType.ToolTip")); /* * combo.addItemListener(new ItemListener() { public void * itemStateChanged(ItemEvent e) { if (e.getStateChange() == * ItemEvent.SELECTED && ((JComboBox) e.getSource()).getSelectedIndex() == * 0) { savePositionsCheckBox.setEnabled(false); * connectToShapeNodesCheckBox.setEnabled(false); //if * (!diagrammer.isAutomaticLinkLayout()) // * compareWithIVLCheckBox.setEnabled(true); } else { * savePositionsCheckBox.setEnabled(true); * connectToShapeNodesCheckBox.setEnabled(true); * //compareWithIVLCheckBox.setSelected(false); * //compareWithIVLCheckBox.setEnabled(false); } } }); */ paramPanel.add(combo, c); c.gridx++; // The link layout combo: // final JComboBox<String> linkLayoutCombo = combo = createStyleCombo( new String[] { "None", "Hierarchical", "Short", "Long" }, new String[] { "nolinklayout.css", "hlink.css", "shortlink.css", "longlinks.css", }); linkLayoutCombo.setToolTipText(getString("LinkLayoutType.ToolTip")); /* * combo.addItemListener(new ItemListener() { public void * itemStateChanged(ItemEvent e) { if (e.getStateChange() == * ItemEvent.SELECTED && ((JComboBox) e.getSource()).getSelectedIndex() == * 0) { layoutOnZoomCheckBox.setEnabled(false); * connectToShapeLinksCheckBox.setEnabled(false); //if * (!diagrammer.isAutomaticNodeLayout()) // * compareWithIVLCheckBox.setEnabled(true); } else { * layoutOnZoomCheckBox.setEnabled(true); * connectToShapeLinksCheckBox.setEnabled(true); * //compareWithIVLCheckBox.setSelected(false); * //compareWithIVLCheckBox.setEnabled(false); } } }); */ paramPanel.add(combo, c); // Hierarchical link routing works only if node layout is hierarchical. // linkLayoutCombo.addItemListener(new ItemListener() { Override public void itemStateChanged(ItemEvent e) { if (e.getStateChange() == ItemEvent.SELECTED && linkLayoutCombo.getSelectedIndex() == 1 && nodeLayoutCombo.getSelectedIndex() == 2) { nodeLayoutCombo.setSelectedIndex(1); } } }); c.gridy++; c.gridx = 0; // ********************************* // Second line of parameters panel: // ********************************* // The "Load from XML" check box: // JComboBox<String> loadXML = new JComboBox<String>( new String[] { getString("LoadFromXML"), getString("CreateByCode") }); loadXML.setToolTipText(getString("LoadFromXML.ToolTip")); loadXML.setSelectedIndex(loadFromXML ? 0 : 1); loadXML.addItemListener(new ItemListener() { Override SuppressWarnings("unchecked") public void itemStateChanged(ItemEvent e) { if (e.getStateChange() == ItemEvent.SELECTED) { loadFromXML = ((JComboBox<String>) e.getSource()).getSelectedIndex() == 0; if (loadFromXML) graphCreationCounter.setLabel("XMLReading"); else graphCreationCounter.setLabel("Creation"); } } }); paramPanel.add(loadXML, c); c.gridx++; // The subgraphs check box: // JCheckBox subgraphsCheckBox = createStyleCheckBox("SubGraphs", "subgraph.css"); subgraphsCheckBox.setToolTipText(getString("SubGraphs.ToolTip")); subgraphsCheckBox.addItemListener(new ItemListener() { Override public void itemStateChanged(ItemEvent e) { subgraphs = e.getStateChange() == ItemEvent.SELECTED; intergraphLinksCheckBox.setEnabled(subgraphs); } }); paramPanel.add(subgraphsCheckBox, c); c.gridx++; // The fill style combo for nodes: // fillCombo = combo = createStyleCombo(new String[] { "NoColoring", "ColorFill", "GradientFill", }, new String[] { "nocolor.css", "colorfill.css", "gradientfill.css", }); fillCombo.setToolTipText(getString("NodeFill.ToolTip")); fillCombo.addItemListener(new ItemListener() { Override public void itemStateChanged(ItemEvent e) { if (e.getStateChange() == ItemEvent.SELECTED && nodeCombo.getSelectedIndex() == 0 && fillCombo.getSelectedIndex() > 1) { IlvSwingUtil.showInformationDialog(DiagrammerBench.this.contentPane, getString("InvalidCombination")); fillCombo.setSelectedIndex(1); } } }); combo.setSelectedIndex(1); paramPanel.add(combo, c); c.gridx++; // The link mode combo: // glinkCombo = combo = createStyleCombo(new String[] { "NoColoring", "UnicolorMode", "GradientMode", "NeonMode", }, new String[] { "nocolorl.css", "unicolorglink.css", "gradientglink.css", "neonglink.css", }); glinkCombo.setToolTipText(getString("LinkFill.ToolTip")); glinkCombo.addItemListener(new ItemListener() { Override public void itemStateChanged(ItemEvent e) { if (e.getStateChange() == ItemEvent.SELECTED && linkCombo.getSelectedIndex() == 0 && glinkCombo.getSelectedIndex() > 1) { IlvSwingUtil.showInformationDialog(DiagrammerBench.this.contentPane, getString("InvalidCombination")); glinkCombo.setSelectedIndex(1); } } }); combo.setSelectedIndex(1); paramPanel.add(combo, c); c.gridx++; /* * // The "Update X/Y" check box for node layout: // savePositionsCheckBox = * createStyleCheckBox("SavePositions", "savepositions.css"); * savepositionsCheckBox.setToolTipText(getString("SavePositions.ToolTip")); * savePositionsCheckBox.setEnabled(false); * paramPanel.add(savePositionsCheckBox, c); */ c.gridx++; /* * // The "perform layout on zoom" check box for link layout: // * layoutOnZoomCheckBox = createStyleCheckBox("LayoutOnZoom", * "layoutonzoom.css"); * layoutOnZoomCheckBox.setToolTipText(getString("LayoutOnZoom.ToolTip")); * layoutOnZoomCheckBox.setEnabled(false); * paramPanel.add(layoutOnZoomCheckBox, c); */ c.gridy++; c.gridx = 0; // ********************************* // Thrid line of parameters panel: // ********************************* // The "Compare with GF" check box: // compareWithIVLCheckBox = new JCheckBox(getString("CompareWithIVL")); compareWithIVLCheckBox.setToolTipText(getString("CompareWithIVL.ToolTip")); compareWithIVLCheckBox.setSelected(compareWithIVL); compareWithIVLCheckBox.addItemListener(new ItemListener() { Override public void itemStateChanged(ItemEvent e) { compareWithIVL = e.getStateChange() == ItemEvent.SELECTED; } }); paramPanel.add(compareWithIVLCheckBox, c); c.gridx++; // The check box for intergraph links: // intergraphLinksCheckBox = new JCheckBox(getString("IntergraphLinks")); intergraphLinksCheckBox.setToolTipText(getString("IntergraphLinks.ToolTip")); intergraphLinksCheckBox.addItemListener(new ItemListener() { Override public void itemStateChanged(ItemEvent e) { intergraphLinks = e.getStateChange() == ItemEvent.SELECTED; } }); intergraphLinksCheckBox.setEnabled(false); paramPanel.add(intergraphLinksCheckBox, c); c.gridx++; // The node stroke combo: // strokeCombo = combo = createStyleCombo(new String[] { "DefaultStroke", "ThickStroke", "DashedStroke", }, new String[] { "defaultstroke.css", "thickstroke.css", "dashedstroke.css", }); strokeCombo.setToolTipText(getString("NodeStroke.ToolTip")); strokeCombo.setEnabled(false); paramPanel.add(combo, c); c.gridx++; // The link width combo: // combo = createStyleCombo(new String[] { "DefaultLink", "LinkWidth5", "LinkWidth10", }, new String[] { "defaultlinkwidth.css", "linkwidth5.css", "linkwidth10.css", }); combo.setToolTipText(getString("LinkWidth.ToolTip")); paramPanel.add(combo, c); c.gridx++; /* * // "Connect to shape" for node layout: // connectToShapeNodesCheckBox = * createStyleCheckBox("ConnectToShape", "connecttoshapenodes.css"); * connectToShapeNodesCheckBox.setToolTipText(getString( * "ConnectToShape.ToolTip")); * connectToShapeNodesCheckBox.setEnabled(false); * paramPanel.add(connectToShapeNodesCheckBox, c); */ c.gridx++; /* * // "Connect to shape" for link layout: // connectToShapeLinksCheckBox = * createStyleCheckBox("ConnectToShape", "connecttoshapelinks.css"); * connectToShapeLinksCheckBox.setToolTipText(getString( * "ConnectToShape.ToolTip")); * connectToShapeLinksCheckBox.setEnabled(false); * paramPanel.add(connectToShapeLinksCheckBox, c); */ // ************************* // End of parameters panel // ************************* // Status field: // JPanel bottomPanel = new JPanel(new GridBagLayout()); contentPane.add(bottomPanel, BorderLayout.SOUTH); c.gridx = 0; c.gridy = 0; messageText = new JTextField(); messageText.setEditable(false); c.weightx = 1; bottomPanel.add(messageText, c); c.weightx = 0; normalMessageColor = messageText.getForeground(); try { errorMessageColor = (Color) IlvConvert.convert(getString("ErrorMessageColor"), Color.class); } catch (Exception ex) { errorMessageColor = Color.red; } c.gridx++; // Number of nodes/links: // text = new JTextField(); text.setEditable(false); bottomPanel.add(text, c); nodeLinkCountText = text; nodeCount = maxSize; linkCount = maxSize; displayCounts(); text.setPreferredSize(text.getPreferredSize()); nodeCount = 0; linkCount = 0; displayCounts(); c.gridx++; // Memory field: // label = new JLabel(getString("Memory")); bottomPanel.add(label, c); c.gridx++; text = new JTextField(); text.setToolTipText(getString("MemoryText.ToolTip")); text.setEditable(false); text.setColumns(3); bottomPanel.add(text, c); memoryText = text; c.gridx++; memoryBar = new JProgressBar(); memoryBar.setToolTipText(getString("MemoryBar.ToolTip")); memoryBar.setStringPainted(true); bottomPanel.add(createHelpPanel(memoryBar, "memory"), c); try { normalMemoryColor = (Color) IlvConvert.convert(getString("NormalMemoryColor"), Color.class); } catch (Exception ex) { normalMemoryColor = memoryBar.getForeground(); } try { fullMemoryColor = (Color) IlvConvert.convert(getString("FullMemoryColor"), Color.class); } catch (Exception ex) { fullMemoryColor = Color.red; } c.gridx++; JButton gcButton = new JButton(getString("RunGC")); gcButton.setToolTipText(getString("RunGC.ToolTip")); gcButton.addActionListener(new ActionListener() { Override public void actionPerformed(ActionEvent e) { showMessage("GarbageCollecting"); System.gc(); updateMemory(); showMessage("Ready"); } }); bottomPanel.add(gcButton, c); c.gridx++; JCheckBox autoGCCheckBox = new JCheckBox(getString("AutoGC")); autoGCCheckBox.setToolTipText(getString("AutoGC.ToolTip")); autoGCCheckBox.setSelected(autoGCCount > 0); autoGCCheckBox.addItemListener(new ItemListener() { Override public void itemStateChanged(ItemEvent e) { autoGCCount = e.getStateChange() == ItemEvent.SELECTED ? 2 : 0; } }); bottomPanel.add(autoGCCheckBox, c); c.weightx = 1; // ***************** // Results panel: // ***************** JPanel resultPanel, sdmResultPanel, gfResultPanel; Border resultBorder = BorderFactory.createEmptyBorder(0, 3, 0, 0); // ***************** // - SDM section: // ***************** sdmResultPanel = resultPanel = new JPanel(new GridBagLayout()); resultPanel.setBorder(resultBorder); sdmPanel.add(resultPanel, BorderLayout.EAST); JSeparator sep; c.gridx = 0; c.gridy = 0; // SDM section: // label = new JLabel(getString("UsingSDM")); label.setToolTipText(getString("UsingSDM.ToolTip")); c.gridwidth = GridBagConstraints.REMAINDER; resultPanel.add(label, c); c.gridwidth = 1; c.gridx = 0; c.gridy++; // Total time counter (created now, but added at the end). // totalCounter = new Counter(); // Graph reading/creation counter: // graphCreationCounter = new Counter().add((loadFromXML ? "XMLReading" : "Creation"), resultPanel, c, totalCounter); c.gridx = 0; c.gridy++; // Rendering counter: // renderingCounter = new Counter().add("Rendering", resultPanel, c, totalCounter); c.gridx = 0; c.gridy++; // Node layout counter: // nodeLayoutCounter = new Counter().add("NodeLayoutCounter", resultPanel, c, totalCounter); c.gridx = 0; c.gridy++; // Link layout counter: // linkLayoutCounter = new Counter().add("LinkLayoutCounter", resultPanel, c, totalCounter); c.gridx = 0; c.gridy++; // Painting counter: // paintingCounter = new Counter().add("Painting", resultPanel, c, totalCounter); c.gridx = 0; c.gridy++; // Add the total counter for SDM: // totalCounter.add("SDMTotal", resultPanel, c, 10000); // ***************** // - GF section: // ***************** gfResultPanel = resultPanel = new JPanel(new GridBagLayout()); resultPanel.setBorder(resultBorder); gfPanel.add(resultPanel, BorderLayout.EAST); c.gridx = 0; c.gridy = 0; label = new JLabel(getString("UsingGF")); label.setToolTipText(getString("UsingGF.ToolTip")); c.gridwidth = GridBagConstraints.REMAINDER; resultPanel.add(label, c); c.gridwidth = 1; c.gridx = 0; c.gridy++; // Total GF time counter: // ivlCounter = new Counter(); // IVL reading counter: // ivlReadCounter = new Counter().add("IVLReading", resultPanel, c, ivlCounter); c.gridx = 0; c.gridy++; // IVL painting counter: // ivlPaintCounter = new Counter().add("Painting", resultPanel, c, ivlCounter); c.gridx = 0; c.gridy++; ivlCounter.add("GFTotal", resultPanel, c, 10000); c.gridx = 0; c.gridy++; sep = new JSeparator(JSeparator.HORIZONTAL); c.gridwidth = GridBagConstraints.REMAINDER; resultPanel.add(sep, c); c.gridwidth = 1; c.gridx = 0; c.gridy++; // SDM/GF ratio: // label = new JLabel(getString("SDMGFRatio")); label.setToolTipText(getString("SDMGFRatio.ToolTip")); resultPanel.add(label, c); if (usePercentText) { c.gridx++; ivlPercentText = new JTextField(); ivlPercentText.setEditable(false); resultPanel.add(ivlPercentText, c); } c.gridx++; ivlRatioText = new JTextField(); ivlRatioText.setToolTipText(getString("SDMGFRatio.ToolTip")); ivlRatioText.setEditable(false); c.gridwidth = GridBagConstraints.REMAINDER; resultPanel.add(createHelpPanel(ivlRatioText, "comparing_sdm_and_gf"), c); c.gridwidth = 1; c.gridx = 0; c.gridy++; // Make sure both result panels have the same width. // Dimension sdmSize = sdmResultPanel.getPreferredSize(); Dimension gfSize = gfResultPanel.getPreferredSize(); int w = Math.max(sdmSize.width, gfSize.width); sdmSize.width = gfSize.width = w; sdmResultPanel.setPreferredSize(sdmSize); gfResultPanel.setPreferredSize(gfSize); // ********************* // End of GUI creation. // ********************* // Cold start: we load the graph a few times // at startup, to "heat" the JIT. // if (coldStartCount > 0) { // System.out.print("cold starting..."); for (int i = 0; i < coldStartCount; i++) { System.out.print("."); coldStart(); autoGC(); } deleteIVLFile(); System.out.println(""); clear(); autoGC(); } updateMemory(); showMessage("Ready"); } private void displayCounts() { String s; s = MessageFormat.format(nodeLinkCountFormat, new Object[] { Integer.valueOf(nodeCount), Integer.valueOf(linkCount), }); nodeLinkCountText.setText(s); s = MessageFormat.format(nodeLinkCountTooltipFormat, new Object[] { Integer.valueOf(nodeCount), Integer.valueOf(linkCount), }); nodeLinkCountText.setToolTipText(s); } /** * Creates a check box to add/remove a style sheet. */ private JCheckBox createStyleCheckBox(String labelKey, final String css) { JCheckBox subgraphsCheckBox = new JCheckBox(getString(labelKey)); subgraphsCheckBox.addItemListener(new ItemListener() { Override public void itemStateChanged(ItemEvent e) { URL url = getClass().getResource(css); IlvSDMModel model = diagrammer.getEngine().getModel(); diagrammer.getEngine().setModel(null, false); try { if (e.getStateChange() == ItemEvent.SELECTED) { diagrammer.addStyleSheet(url); } else { diagrammer.removeStyleSheet(url); } } catch (Exception e1) { error(e1); } finally { diagrammer.getEngine().setModel(model, false); } } }); return subgraphsCheckBox; } /** * Creates a combo box to add/remove one of several style sheets. */ private JComboBox<String> createStyleCombo(String[] keys, final String[] css) { final Vector<String> v = new Vector<String>(); for (int i = 0; i < keys.length; i++) { v.add(getString(keys[i])); } JComboBox<String> combo = new JComboBox<String>(v); combo.addItemListener(new ItemListener() { Override public void itemStateChanged(final ItemEvent e) { IlvSDMModel model = diagrammer.getEngine().getModel(); try { diagrammer.getEngine().setModel(null, false); int index = v.indexOf(e.getItem()); URL url = getClass().getResource(css[index]); if (e.getStateChange() == ItemEvent.SELECTED) { diagrammer.addStyleSheet(url); } else { diagrammer.removeStyleSheet(url); } } catch (Exception ex) { error(ex); } finally { diagrammer.getEngine().setModel(model, false); } } }); try { diagrammer.addStyleSheet(getClass().getResource(css[0])); } catch (Exception e) { error(e); } return combo; } /** * Displays a message or a message in the status field. */ private void showMessage(String key, boolean error) { messageText.setText(getString(key + "Message")); if (error) messageText.setForeground(errorMessageColor); else messageText.setForeground(normalMessageColor); messageText.setCaretPosition(0); messageText.setToolTipText(messageText.getText()); paintImmediately(messageText); } /** * Displays a message in the status field. */ private void showMessage(String key) { showMessage(key, false); } /** * Displays an error in the status field. */ private void showError(String key) { showMessage(key, true); } /** * A listener used to "spy" the node/link layout renderers. */ private class LayoutListener implements SDMGraphLayoutRendererListener { Override public void performLayoutStarted(SDMGraphLayoutRendererEvent event) { if (renderingCounter.startTime != 0) { renderingCounter.after(); } if (event.getSource() instanceof IlvLinkLayoutRenderer) { showMessage("LinkLayout"); linkLayoutCounter.before(); } else { showMessage("NodeLayout"); nodeLayoutCounter.before(); } } Override public void performLayoutEnded(SDMGraphLayoutRendererEvent event) { if (event.getSource() instanceof IlvLinkLayoutRenderer) { linkLayoutCounter.after(); } else { nodeLayoutCounter.after(); } } } /** * The core method that creates the graph and measures the time spent in the * successive steps. */ private void createGraph() { // Avoid restarting while we are waiting for the paint to be // finished. // if (running) return; running = true; ((JComponent) contentPane).getRootPane().setCursor(busyCursor); // Set frame title: // if (project != null) { setFrameTitle(project.getProjectURL().toExternalForm()); } else { int n = (int) Math.pow(10, graphSize); setFrameTitle(MessageFormat.format(sizeFormat, new Object[] { String.valueOf(n) })); } // Allocate a bit of memory, to make sure we have some // spare memory if we hit an OutOfMemoryError. // rab = new long[1024 * 1024]; rab[0] = 0; try { // Clear current graphs. // clear(); // If we loaded a project last time, reset the CSS as defined by // the parameters panel. // if (savedCSS != null) restoreCSS(); savedCSS = null; // Reset counters, clear extr fields. // resetAllCounters(); nodeLinkCountText.setText(""); paintImmediately(nodeLinkCountText); /* * memoryText.setText(""); paintImmediately(memoryText); */ autoGC(); IlvSDMModel model = new IlvDefaultSDMModel(); if (loadFromXML && project == null) { getDataFile(true); // creates the file if necessary } // Record time at the beginning of everything. // totalCounter.before(); if (loadFromXML || project != null) { if (project != null) { // Reading a project: read the style sheets // (Note that we don't measure this, but it is fast). // showMessage("ReadingCSS"); savedCSS = diagrammer.getStyleSheets(); URL[] styleSheets = project.getStyleSheets(); if (styleSheets != null && styleSheets.length > 0) { diagrammer.setStyleSheet(styleSheets[0]); for (int i = 1; i < styleSheets.length; i++) { diagrammer.addStyleSheet(styleSheets[i]); } } } // Read the XML data file: we use a separate XML connector, // not the Diagrammer's, because we want to measure just // the time spent reading the XML, and not yet the time spent // to render the graph. // showMessage("ReadingXML"); IlvXMLConnector connector = new IlvXMLConnector(); graphCreationCounter.before(); URL dataURL; if (project == null) { // We are not loading a project: the data file is something like // "data/1000.xml". dataURL = getDataFile(true); } else { // We are loading a project: the data file is the project's data // source // file. dataURL = ((IlvXMLDataSource) project.getDataSource()).getDataURL(); } // Read the file... // InputStream in = IlvURLUtil.prepare(dataURL).openStream(); if (project == null) { connector.readXML(model, new BufferedReader(new InputStreamReader(in)), false, null); } else { IlvSDMEngine tmpEngine = new IlvSDMEngine(new IlvGrapher(), model); tmpEngine.setRenderer(null); tmpEngine.readXML(new BufferedReader(new InputStreamReader(in))); model = tmpEngine.getModel(); tmpEngine.setModel(null, false); } graphCreationCounter.after(); // Count the nodes and links. // nodeCount = 0; linkCount = 0; Enumeration<?> objs = new IlvPreorderEnumeration(model); while (objs.hasMoreElements()) { Object o = objs.nextElement(); if (diagrammer.isLink(o)) linkCount++; else nodeCount++; } } else { // Not reading from XML (i.e., creating graph in-memory): // showMessage("Creating"); graphCreationCounter.before(); // Call the external GraphData class to create the graph. // graphData.createGraph(model, graphSize, subgraphs, intergraphLinks); graphCreationCounter.after(); nodeCount = graphData.getNodeCount(); linkCount = graphData.getLinkCount(); } // Display the number of nodes/links: // displayCounts(); paintImmediately(nodeLinkCountText); // Install the layout listeners to be notified when the layouts // start/end. // final LayoutListener layoutListener = new LayoutListener(); if (diagrammer.getEngine().getNodeLayoutRenderer() != null) { diagrammer.getEngine().getNodeLayoutRenderer().addGraphLayoutRendererListener(layoutListener); } if (diagrammer.getEngine().getLinkLayoutRenderer() != null) { diagrammer.getEngine().getLinkLayoutRenderer().addGraphLayoutRendererListener(layoutListener); } // OK, now we have a data model. // Next, perform and measure the creation of graphic objects. // showMessage("Rendering"); renderingCounter.before(); // Set the data model on the SDM engine. This causes the // engine to actually create the graphic objects that represent // the graph. // diagrammer.getEngine().setModel(model, true); // If there was a node or link layout, the rendering counter // has already been stopped (we know this because startTime has // been reset to 0). If not, stop the rendering counter now. // if (renderingCounter.startTime != 0) renderingCounter.after(); // If node/link layout was not performed, call the counter // anyway to set its time to 0. // if (!diagrammer.isAutomaticNodeLayout()) { nodeLayoutCounter.before(); nodeLayoutCounter.after(); } if (!diagrammer.isAutomaticLinkLayout()) { linkLayoutCounter.before(); linkLayoutCounter.after(); } // Graphic objects are now created. // Next, we want to measure the painting time. // showMessage("Painting"); paintingCounter.before(); // Do a "fit-to-contents" to make sure we paint all graphic objects. // diagrammer.getView().fitTransformerToContent(new Insets(10, 10, 10, 10)); // To measure the painting time, we queue an invokeLater call. // We assume here that the invokeLater call will be handled after // the paint event, which should have been queued already. // SwingUtilities.invokeLater(new Runnable() { Override public void run() { // We get there after the SDM view has been painted. // We can stop the painting counter, // paintingCounter.after(); // .. and also the total time counter (since painting is the last // thing to measure). totalCounter.after(); // Finished for the SDM case! // // let's start the GF case. // ivlError = false; if (compareWithIVL) { try { // Write the SDm graph to an IVL file // (this is not measured). // showMessage("WritingIVL"); OutputStream out = createIVLOutputStream(); diagrammer.getEngine().getGrapher().write(out); // Read back the IVL file (this is what we measure). // showMessage("ReadingIVL"); ivlCounter.before(); ivlReadCounter.before(); InputStream in = createIVLInputStream(); gfView.getManager().read(in); out.close(); in.close(); deleteIVLFile(); gfView.repaint(); ivlReadCounter.after(); // Measure time for painting the IVL view. // showMessage("Painting"); ivlPaintCounter.before(); gfView.fitTransformerToContent(new Insets(10, 10, 10, 10)); gfView.repaint(); } catch (OutOfMemoryError oome) { outOfMemory(); ivlReadCounter.clear(); ivlPaintCounter.clear(); ivlCounter.clear(); } catch (Exception e) { showError("ErrorInIVL"); ivlError = true; ivlReadCounter.clear(); ivlPaintCounter.clear(); ivlCounter.clear(); } } else { ivlReadCounter.clear(); ivlPaintCounter.clear(); ivlCounter.clear(); } // Same trick: we do an invokeLater to continue execution // once all painting has been done. // SwingUtilities.invokeLater(new Runnable() { Override public void run() { if (compareWithIVL && !ivlError) { // We get here after the GF view has been painted. // ivlPaintCounter.after(); ivlCounter.after(); // Compute the ratio between SDM and GF times. // Note that we eliminate the node/link layout times, // which are never performed when we read the IVL. // float ratio = (float) ivlCounter.time / (float) (totalCounter.time - nodeLayoutCounter.time - linkLayoutCounter.time); if (usePercentText) { ivlPercentText.setText( MessageFormat.format(ivlRatioPercentFormat, new Object[] { Integer.valueOf((int) (ratio * 100)) })); } String ratioText; if (ratio < 1) { ratioText = MessageFormat.format(ivlRatioFormatFaster, new Object[] { Float.valueOf(1 / ratio) }); } else { ratioText = MessageFormat.format(ivlRatioFormatSlower, new Object[] { Float.valueOf(ratio) }); } ivlRatioText.setText(ratioText); paintImmediately(ivlRatioText); } // autoGC(); // Cleanup layout renderer listeners: // if (diagrammer.getEngine().getNodeLayoutRenderer() != null) { diagrammer.getEngine().getNodeLayoutRenderer().removeGraphLayoutRendererListener(layoutListener); } if (diagrammer.getEngine().getLinkLayoutRenderer() != null) { diagrammer.getEngine().getLinkLayoutRenderer().removeGraphLayoutRendererListener(layoutListener); } autoGC(); if (!ivlError) showMessage("Ready"); ((JComponent) contentPane).getRootPane().setCursor(null); running = false; updateMemory(); // All done. } }); } }); } catch (OutOfMemoryError oome) { outOfMemory(); return; } catch (Exception ex) { error(ex); } finally { ((JComponent) contentPane).getRootPane().setCursor(null); running = false; } } private void outOfMemory() { // On OutOfmemoryErrors, we try to display an error box. // For this, we free up the spare memory that we reserved // at the beginning: // rab = null; // Try to give the user an idea of how much memory he should // give to the VM: // long needed = 2 * Runtime.getRuntime().maxMemory() / 1024 / 1024; needed = ((needed + 99) / 100) * 100; IlvSwingUtil.showErrorDialog(contentPane, MessageFormat.format(getString("NotEnoughMemory"), new Object[] { Long.valueOf(needed) })); } /** * Restores a set of saved style sheets. */ private void restoreCSS() { try { if (savedCSS != null && savedCSS.length > 0) { diagrammer.setStyleSheet(savedCSS[0]); for (int i = 1; i < savedCSS.length; i++) { diagrammer.addStyleSheet(savedCSS[i]); } } } catch (Exception ioex) { error(ioex); } } /** * Creates a graph without displaying any results. Used at startup to "heat" * the JIT. */ private void coldStart() { try { IlvSDMModel model = new IlvDefaultSDMModel(); graphData.createGraph(model, graphSize, subgraphs, intergraphLinks); IlvXMLConnector connector = new IlvXMLConnector(); URL dataURL = getDataFile(true); InputStream in = dataURL.openStream(); connector.readXML(model, new BufferedReader(new InputStreamReader(in)), false, null); diagrammer.getEngine().setModel(model, true); OutputStream ivlout = createIVLOutputStream(); diagrammer.getEngine().getGrapher().write(ivlout); ivlout.close(); InputStream ivlin = createIVLInputStream(); gfView.getManager().read(ivlin); ivlin.close(); BufferedImage image = new BufferedImage(500, 200, BufferedImage.TYPE_INT_ARGB); IlvTransformer t = new IlvTransformer(); IlvTransformer.computeTransformer(diagrammer.getEngine().getGrapher().computeBBox(null), new IlvRect(0, 0, 500, 200), t); Graphics2D imageGraphics = image.createGraphics(); diagrammer.getEngine().getGrapher().draw(imageGraphics, t); IlvTransformer.computeTransformer(gfView.getManager().computeBBox(null), new IlvRect(0, 0, 500, 200), t); gfView.getManager().draw(imageGraphics, t); } catch (Exception e) { } } /** * Updates the memory fields. */ private void updateMemory() { Timer t = new Timer(500, new ActionListener() { Override public void actionPerformed(ActionEvent e) { long total = Runtime.getRuntime().totalMemory(); long free = Runtime.getRuntime().freeMemory(); int totalMegs = (int) (total / (1024 * 1024)); int usedMegs = (int) ((total - free) / (1024 * 1024)); memoryBar.setMaximum(totalMegs); memoryBar.setValue(usedMegs); memoryBar.setString( MessageFormat.format(memoryBarFormat, new Object[] { Integer.valueOf(usedMegs), Integer.valueOf(totalMegs) })); if ((float) usedMegs / (float) totalMegs > 0.8) memoryBar.setForeground(fullMemoryColor); else memoryBar.setForeground(normalMemoryColor); if (memoryBefore == 0) memoryBefore = total - free; long memory = total - free - memoryBefore; if (memory < 0) { memoryBefore += memory; memory = 0; } int megs = (int) (memory / (1024 * 1024)); String memText = MessageFormat.format(memoryFormat, new Object[] { megs < 0 ? "" : "+", Integer.valueOf(megs) }); memoryText.setText(memText); } }); t.setRepeats(false); t.start(); } /** * Clears the views. */ private void clear() { showMessage("Clearing"); diagrammer.getEngine().setModel(new IlvDefaultSDMModel()); paintImmediately(diagrammer); gfView.getManager().deleteAll(true); paintImmediately(gfScrollView); } /** * Displays an error box. */ private void error(Throwable t) { IlvSwingUtil.showErrorDialog(contentPane, t); } /** * This class represents a counter. There are master counters, and * sub-counters that are used to measure times of individual steps. */ private class Counter { private long startTime; private long time; private JLabel label; private JTextField text; private JProgressBar bar; private Counter total; private ArrayList<Counter> percents = new ArrayList<Counter>(); /** * Adds the Swing components for a counter: this is the version for a * sub-counter. The "total" parameter is the master counter. */ public Counter add(String labelKey, Container panel, GridBagConstraints c, Counter total) { add(labelKey, panel, c, 100); this.total = total; total.percents.add(this); label.setPreferredSize(label.getPreferredSize()); return this; } /** * Adds the Swing components for a counter: this is the version for a master * counter. */ public Counter add(String labelKey, Container panel, GridBagConstraints c, int max) { allCounters.add(this); label = new JLabel(getString(labelKey)); label.setIcon(nomarkIcon); String tooltip = getString(labelKey + ".ToolTip"); label.setToolTipText(tooltip); panel.add(label, c); c.gridx++; text = new JTextField(); text.setToolTipText(tooltip); text.setEditable(false); text.setColumns(6); panel.add(text, c); c.gridx++; bar = new JProgressBar(0, max); bar.setToolTipText(tooltip); bar.setStringPainted(true); try { String barColor = getString(labelKey + "Color"); Color color = (Color) IlvConvert.convert(barColor, Color.class); bar.setForeground(color); } catch (Exception ex) { } panel.add(bar, c); return this; } /** * This method is called to record the time before executing the task * measured by this counter. */ private void before() { if (total != null) mark(); startTime = getCurrentTime(); time = -1; } /** * Displays the mark in the counter's label, to show that the counter is * active. */ private void mark() { label.setIcon(markIcon); paintImmediately(label); } /** * Sets the label of the counter. */ private void setLabel(String key) { label.setText(getString(key)); paintImmediately(label); String tooltip = getString(key + ".ToolTip"); label.setToolTipText(tooltip); text.setToolTipText(tooltip); bar.setToolTipText(tooltip); } /** * This method must be called after executing the task measured by this * counter. It measures the time, and updates the Swing components of the * counter. If this is a master counter, it also updates the percentages of * all sub-counters. */ private void after() { if (total != null) { time = getCurrentTime() - startTime; if (total.time == -1) total.time = time; else total.time += time; } String s = MessageFormat.format(timeFormat, new Object[] { Long.valueOf(time) }); text.setText(s); paintImmediately(text); if (total == null) { if (time == 0) { bar.setValue(Integer.MAX_VALUE); bar.setString(getString("TooFast")); } else { int speed = (int) ((nodeCount + linkCount) * 1000 / time); bar.setValue(speed); s = MessageFormat.format(speedFormat, new Object[] { Integer.valueOf(speed) }); bar.setString(s); for (int i = 0; i < percents.size(); i++) { Counter counter = (Counter) percents.get(i); counter.percentOfTotal(); } } paintImmediately(bar); } startTime = 0; if (total != null) unmark(); } /** * Hides the mark in the counter's label, to show that the counter is not * active any more. */ private void unmark() { label.setIcon(nomarkIcon); paintImmediately(label); } /** * Displays the percentage of time spent in a sub-counter with respect to * its master counter. */ private void percentOfTotal() { if (total != null) { if (!text.getText().equals(emptyTextString)) { int percent = (int) (time * 100 / total.time); bar.setValue(percent); String s = MessageFormat.format(percentFormat, new Object[] { Integer.valueOf(percent) }); bar.setString(s); } else { bar.setValue(0); bar.setString(emptyBarString); } paintImmediately(bar); } } /** * Resets the counter. */ private void reset() { text.setText(emptyTextString); paintImmediately(text); bar.setValue(0); bar.setString(runningString); paintImmediately(bar); startTime = 0; time = 0; } /** * Clears the counter. */ private void clear() { unmark(); text.setText(emptyTextString); paintImmediately(text); bar.setValue(0); bar.setString(emptyBarString); paintImmediately(bar); startTime = 0; time = 0; } } private static ArrayList<Counter> allCounters = new ArrayList<Counter>(); /** * Resets all the counters. */ void resetAllCounters() { for (int i = 0; i < allCounters.size(); i++) { Counter counter = (Counter) allCounters.get(i); counter.reset(); } if (usePercentText) { ivlPercentText.setText(""); paintImmediately(ivlPercentText); } ivlRatioText.setText(""); paintImmediately(ivlRatioText); } /** * Clears all the counters. */ void clearAllCounters() { for (int i = 0; i < allCounters.size(); i++) { Counter counter = (Counter) allCounters.get(i); counter.clear(); } if (usePercentText) { ivlPercentText.setText(""); paintImmediately(ivlPercentText); } ivlRatioText.setText(""); paintImmediately(ivlRatioText); } /** * Utility method to "paint immediately" a Swing component. */ private void paintImmediately(JComponent c) { c.paintImmediately(0, 0, c.getWidth(), c.getHeight()); } /** * Runs the GC "autoGCCount" times. */ private void autoGC() { if (autoGCCount > 0) { if (!ivlError) showMessage("GarbageCollecting"); for (int i = 0; i < autoGCCount; i++) { System.gc(); } } } // Displays the Help window. // private void showHelp(final String anchor) { if (helpWindow == null) { Frame frame = (Frame) SwingUtilities.getAncestorOfClass(Frame.class, contentPane); helpWindow = new JDialog(frame, getString("HelpTitle")); helpPane = new JEditorPane(); helpPane.setEditorKit(new HTMLEditorKit()); helpPane.setEditable(false); URL helpURL = getClass().getResource(getString("HelpFile")); try { helpURL = new URL(helpURL.toExternalForm() + "#" + anchor); helpPane.setPage(helpURL); } catch (IOException e) { error(e); } helpPane.addHyperlinkListener(new HyperlinkListener() { Override public void hyperlinkUpdate(HyperlinkEvent e) { if (e.getEventType() == HyperlinkEvent.EventType.ACTIVATED) { String anchor = e.getURL().toExternalForm(); int sharp = anchor.lastIndexOf('#'); if (sharp >= 0) anchor = anchor.substring(sharp + 1); helpPane.scrollToReference(anchor); } } }); JScrollPane scroller = new JScrollPane(helpPane); ((JDialog) helpWindow).getContentPane().add(scroller); helpWindow.setSize(600, 500); Point p = contentPane.getLocationOnScreen(); helpWindow.setLocation(p.x + 200, p.y + 100); } helpPane.scrollToReference(anchor); helpWindow.setVisible(true); } private JPanel createHelpPanel(JComponent component, final String anchor) { JPanel panel = new JPanel(new GridBagLayout()); GridBagConstraints c2 = new GridBagConstraints(); c2.gridx = 0; c2.gridy = 0; c2.weightx = 1; c2.insets = new Insets(0, 0, 0, 5); c2.fill = GridBagConstraints.HORIZONTAL; panel.add(component, c2); c2.gridx++; c2.weightx = 0; c2.insets = new Insets(0, 0, 0, 0); IlvDiagrammerAction.help.init(); JButton button = new JButton((Icon) IlvDiagrammerAction.help.getValue(Action.SMALL_ICON)); button.setToolTipText(getString("ExplainThis")); button.setMargin(new Insets(0, 0, 0, 0)); button.addActionListener(new ActionListener() { Override public void actionPerformed(ActionEvent e) { showHelp(anchor); } }); panel.add(button, c2); return panel; } /** * Returns the current time in milliseconds. */ private long getCurrentTime() { // More precise timings could be obtained with System.nanoTime(). return System.currentTimeMillis(); } private OutputStream createIVLOutputStream() throws IOException { OutputStream out; if (loadFromXML) out = new FileOutputStream(tmpIVLFile); else out = ivlByteStream = new ByteArrayOutputStream(); return new BufferedOutputStream(out); } private InputStream createIVLInputStream() throws IOException { InputStream in; if (loadFromXML) in = new FileInputStream(tmpIVLFile); else in = new ByteArrayInputStream(ivlByteStream.toString().getBytes()); return new BufferedInputStream(in); } private void deleteIVLFile() { if (loadFromXML) { try { new File(tmpIVLFile).delete(); } catch (Throwable t) { } } else { ivlByteStream = null; } } /** * This class implements a Diagrammer view bar that acts on the Graphic * Framework view. */ private class GFToolBar extends IlvDiagrammerToolBar { GFToolBar(Action[] sdmActions, final IlvDiagrammer gfDiagrammer) { super(null, JToolBar.VERTICAL); addAction(new IlvDiagrammerAction(null) { Override public void perform(ActionEvent e, IlvDiagrammer diagrammer) throws Exception { gfDiagrammer.zoomIn(); } Override protected boolean isEnabled(IlvDiagrammer diagrammer) throws Exception { return gfDiagrammer.canZoomIn(); } }); addAction(new IlvDiagrammerAction(null) { Override public void perform(ActionEvent e, IlvDiagrammer diagrammer) throws Exception { gfDiagrammer.zoomOut(); } Override protected boolean isEnabled(IlvDiagrammer diagrammer) throws Exception { return gfDiagrammer.canZoomOut(); } }); addAction(new IlvDiagrammerAction.ToggleAction(null) { Override protected boolean isSelected(IlvDiagrammer diagrammer) throws Exception { return gfDiagrammer.isZoomMode(); } Override protected void setSelected(IlvDiagrammer diagrammer, boolean selected) throws Exception { gfDiagrammer.setZoomMode(selected); } Override protected boolean isEnabled(IlvDiagrammer diagrammer) throws Exception { return true; } }); addAction(new IlvDiagrammerAction(null) { Override public void perform(ActionEvent e, IlvDiagrammer diagrammer) throws Exception { gfDiagrammer.resetZoom(); } Override protected boolean isEnabled(IlvDiagrammer diagrammer) throws Exception { return gfDiagrammer.canResetZoom(); } }); addAction(new IlvDiagrammerAction(null) { Override public void perform(ActionEvent e, IlvDiagrammer diagrammer) throws Exception { gfDiagrammer.fitToContents(); } Override protected boolean isEnabled(IlvDiagrammer diagrammer) throws Exception { return true; } }); addAction(new IlvDiagrammerAction.ToggleAction(null) { Override protected boolean isSelected(IlvDiagrammer diagrammer) throws Exception { return gfDiagrammer.isPanMode(); } Override protected void setSelected(IlvDiagrammer diagrammer, boolean selected) throws Exception { gfDiagrammer.setPanMode(selected); } Override protected boolean isEnabled(IlvDiagrammer diagrammer) throws Exception { return true; } }); Action[] actions = getActions(); for (int i = 0; i < actions.length; i++) { actions[i].getValue(Action.SMALL_ICON); actions[i].putValue(Action.SMALL_ICON, sdmActions[i].getValue(Action.SMALL_ICON)); actions[i].putValue(Action.SHORT_DESCRIPTION, sdmActions[i].getValue(Action.SHORT_DESCRIPTION)); actions[i].putValue(Action.LONG_DESCRIPTION, sdmActions[i].getValue(Action.LONG_DESCRIPTION)); } } } private URL getDataFile(boolean create) throws Exception { URL dataURL = new URL(DiagrammerBench.this.baseURL, "data/" + (int) Math.pow(10, graphSize) + (subgraphs ? "s" : "") + (subgraphs && intergraphLinks ? "i" : "") + ".xml"); if (create) { try { dataURL.openStream().close(); } catch (Exception ex) { // File does not exist, try to create it: // showMessage("GeneratingDataFile"); graphData.generateGraphFile(graphSize, subgraphs, intergraphLinks); } } return dataURL; } }