/*
* Licensed Materials - Property of Rogue Wave Software, Inc.
* © Copyright Rogue Wave Software, Inc. 2014, 2017
* © 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 java.util.logging.Level;
import java.util.logging.Logger;
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 Rogue Wave 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[] { new Integer(nodeCount), new Integer(linkCount), });
nodeLinkCountText.setText(s);
s = MessageFormat.format(nodeLinkCountTooltipFormat,
new Object[] { new Integer(nodeCount), new Integer(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[] { new Integer((int) (ratio * 100)) }));
}
String ratioText;
if (ratio < 1) {
ratioText = MessageFormat.format(ivlRatioFormatFaster, new Object[] { new Float(1 / ratio) });
} else {
ratioText = MessageFormat.format(ivlRatioFormatSlower, new Object[] { new Float(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[] { new Long(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[] { new Integer(usedMegs), new Integer(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 ? "" : "+", new Integer(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[] { new Long(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[] { new Integer(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[] { new Integer(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;
}
}