/*
* 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.Component;
import java.awt.ComponentOrientation;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.Rectangle;
import java.awt.Shape;
import java.awt.SystemColor;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.KeyEvent;
import java.text.MessageFormat;
import java.util.Enumeration;
import java.util.Locale;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JRootPane;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import ilog.views.IlvGrapher;
import ilog.views.IlvGraphic;
import ilog.views.IlvGrid;
import ilog.views.IlvHandlesSelection;
import ilog.views.IlvManager;
import ilog.views.IlvManagerView;
import ilog.views.IlvPoint;
import ilog.views.IlvRect;
import ilog.views.IlvTransformer;
import ilog.views.accelerator.IlvDeleteSelectionAccelerator;
import ilog.views.event.ManagerContentChangedEvent;
import ilog.views.event.ManagerContentChangedListener;
import ilog.views.event.ManagerSelectionChangedEvent;
import ilog.views.event.ManagerSelectionListener;
import ilog.views.event.ObjectBBoxChangedEvent;
import ilog.views.graphlayout.GraphLayoutEvent;
import ilog.views.graphlayout.GraphLayoutEventListener;
import ilog.views.graphlayout.IlvGraphLayout;
import ilog.views.graphlayout.IlvGraphLayoutException;
import ilog.views.graphlayout.IlvGraphLayoutReport;
import ilog.views.graphlayout.IlvGraphModel;
import ilog.views.graphlayout.IlvGrapherAdapter;
import ilog.views.graphlayout.grid.IlvGridLayout;
import ilog.views.graphlayout.random.IlvRandomLayout;
import ilog.views.interactor.IlvSelectInteractor;
import ilog.views.interactor.IlvZoomViewInteractor;
import ilog.views.swing.IlvJManagerViewControlBar;
import ilog.views.swing.IlvJScrollManagerView;
import ilog.views.util.IlvLocaleUtil;
import ilog.views.util.IlvProductUtil;
import ilog.views.util.IlvResourceUtil;
import ilog.views.util.swing.IlvJSpinnerDecimalNumberField;
import ilog.views.util.swing.IlvSwingUtil;
/**
* This is a very simple application that uses the
* <code>IlvGrapher</code> to perform a grid layout. It shows how to use grid
* layout in applications that are not based on CSS styling.
*/
public class GridLayoutApp extends JRootPane implements ManagerSelectionListener, ManagerContentChangedListener {
static {
// Test code whether the demo works in RTL locales
// Locale newLocale = new Locale("he");
// IlvSwingUtil.setDefaultLocale(newLocale);
}
{
// This sample uses JViews Diagrammer features. When deploying an
// application that includes this code, you need to be in possession
// of a JViews Diagrammer Deployment license.
IlvProductUtil.DeploymentLicenseRequired(IlvProductUtil.JViews_Diagrammer_Deployment);
}
/** The grapher */
IlvGrapher grapher = new IlvGrapher();
/** The view of the grapher */
IlvManagerView mgrview = new IlvManagerView(grapher, null);
/** An IlvGrid object to help understanding the grid mode */
IlvGrid grid = new LineGrid();
/** An instance of the Grid Layout algorithm */
IlvGridLayout layout = new IlvGridLayout();
/** An instance of the Random Layout algorithm */
IlvRandomLayout randomLayout = new IlvRandomLayout();
/** A graph layout event listener */
LayoutIterationListener layoutListener = new LayoutIterationListener();
/** The default offset */
static final double DEFAULT_OFFSET = 80.;
static final int OFFSET_BY_MAX_NODE_SIZE = 0;
static final int OFFSET_BY_MEAN_NODE_SIZE = 1;
static final int OFFSET_AS_SPECIFIED = 2;
int gridOffsetOption = OFFSET_BY_MAX_NODE_SIZE;
/** A text field to display messages */
JTextField msgLine = new JTextField();
/** Text fields for the offset parameters */
IlvJSpinnerDecimalNumberField hGridOffset = new IlvJSpinnerDecimalNumberField(0.1, 300, DEFAULT_OFFSET, true, 5, 5);
IlvJSpinnerDecimalNumberField vGridOffset = new IlvJSpinnerDecimalNumberField(0.1, 300, DEFAULT_OFFSET, true, 5, 5);
JLabel orderSelectorLabel;
JComboBox<String> orderSelector;
ManagerContentChangedEvent previousEvent = null;
int numberOfNodes = 0;
double maxNodeWidth = 0;
double maxNodeHeight = 0;
double totalNodeWidth = 0;
double totalNodeHeight = 0;
boolean nodeSizesUpToDate = false;
/**
* Initializes the application.
*/
public void init() {
showMessage(getString("InitMessage"));
JPanel panel;
// attach the grapher to the layout instances
IlvGrapherAdapter adapter = new IlvGrapherAdapter(grapher);
layout.attach(adapter);
randomLayout.attach(adapter);
// change some default options
layout.setPreserveFixedNodes(true);
layout.setHorizontalGridOffset(DEFAULT_OFFSET);
layout.setVerticalGridOffset(DEFAULT_OFFSET);
// install the layout iteration listener on the layout instance
layout.addGraphLayoutEventListener(layoutListener);
// create the scroll manager view
IlvJScrollManagerView scrollManView = new IlvJScrollManagerView(mgrview);
// listen the selection events
grapher.addManagerSelectionListener(this);
// ... and the content changed events
grapher.addManagerContentChangedListener(this);
// allow the user to delete nodes by pressing the "del" key
grapher.addAccelerator(new IlvDeleteSelectionAccelerator(KeyEvent.KEY_PRESSED, KeyEvent.VK_DELETE, 0));
// Some settings on the manager view and on the scroll manager view
mgrview.setAntialiasing(true);
mgrview.setKeepingAspectRatio(true);
mgrview.setBackground(Color.white);
mgrview.setForeground(SystemColor.windowText);
Color xc = SystemColor.windowText;
xc = new Color(255 - xc.getRed(), 255 - xc.getGreen(), 255 - xc.getBlue());
mgrview.setDefaultXORColor(xc);
mgrview.setDefaultGhostColor(SystemColor.windowText);
mgrview.setZoomFactorRange(0.02, 10.0);
mgrview.setWheelZoomingEnabled(true);
scrollManView.setWheelScrollingEnabled(true);
// help recognition of the grid
grid.setOrigin(new IlvPoint(0, 0));
grid.setColor(new Color(255, 153, 153));
grid.setActive(false);
grid.setVisible(true);
mgrview.setGrid(grid);
// Settings parameters for selection handles
IlvHandlesSelection.defaultHandleColor = Color.black;
IlvHandlesSelection.defaultHandleBackgroundColor = Color.white;
IlvHandlesSelection.defaultHandleShape = IlvHandlesSelection.SQUARE_SHAPE;
// set the layout manager
getContentPane().setLayout(new BorderLayout(0, 0));
// fit so far all together
getContentPane().add("Center", scrollManView);
getContentPane().add("North", panel = new JPanel());
panel.setLayout(new FlowLayout(FlowLayout.LEADING));
// create the standard control bar
IlvJManagerViewControlBar controlBar = new IlvJManagerViewControlBar();
controlBar.setView(mgrview);
panel.add(controlBar);
// modify the interactors such that the demo looks better
((IlvSelectInteractor) controlBar.getSelectInteractor()).setOpaqueMove(true);
((IlvSelectInteractor) controlBar.getSelectInteractor()).setOpaqueResize(true);
((IlvZoomViewInteractor) controlBar.getZoomViewInteractor()).setPermanent(true);
// set the initial interactor
mgrview.setInteractor(controlBar.getSelectInteractor());
// ------------------------------------------------------------------------
// create the graph selector
panel.add(new JLabel(getString("fileChooser.Label")));
JComboBox<String> chooser;
panel.add(chooser = new JComboBox<String>());
chooser.setToolTipText(getString("fileChooser.Tooltip"));
chooser.addItemListener(new ItemListener() {
Override
public void itemStateChanged(ItemEvent event) {
if (event.getStateChange() == ItemEvent.DESELECTED)
return;
loadGrapher((String) event.getItem());
}
});
chooser.addItem("small");
chooser.addItem("medium");
chooser.addItem("large");
// ------------------------------------------------------------------------
// Perform layout buttons
// create the panel on bottom
JPanel bottomPanel = new JPanel();
bottomPanel.setLayout(new BorderLayout());
getContentPane().add("South", bottomPanel);
// create the layout buttons
JButton b;
JPanel layoutPanel = new JPanel();
layoutPanel.setLayout(new FlowLayout());
bottomPanel.add("North", layoutPanel);
layoutPanel.add(b = new JButton(getString("RandomizeButton.Label")));
b.setToolTipText(getString("RandomizeButton.Tooltip"));
b.addActionListener(new ActionListener() {
Override
public void actionPerformed(ActionEvent evt) {
layout(randomLayout, false);
}
});
layoutPanel.add(b = new JButton(getString("LayoutButton.Label")));
b.setToolTipText(getString("LayoutButton.Tooltip"));
b.addActionListener(new ActionListener() {
Override
public void actionPerformed(ActionEvent evt) {
setGridOffset("hgridoffset", hGridOffset);
setGridOffset("vgridoffset", vGridOffset);
// now the layout
preprocess();
grid.setHorizontalSpacing(layout.getHorizontalGridOffset());
grid.setVerticalSpacing(layout.getVerticalGridOffset());
layout(layout, true);
}
});
// ------------------------------------------------------------------------
// Panel for the layout parameters.
JPanel layoutParameters = new JPanel();
layoutParameters.setLayout(new BorderLayout());
bottomPanel.add("Center", layoutParameters);
JPanel layoutParameters1 = new JPanel();
layoutParameters1.setLayout(new GridBagLayout());
JPanel layoutParameters2 = new JPanel();
layoutParameters2.setLayout(new FlowLayout());
final JPanel offsetPanel = new MyPanel();
offsetPanel.setLayout(new GridBagLayout());
layoutParameters.add("Center", new JLabel(" "));
layoutParameters.add("Before", layoutParameters1);
layoutParameters.add("After", offsetPanel);
layoutParameters.add("South", layoutParameters2);
GridBagConstraints c = new GridBagConstraints();
c.fill = GridBagConstraints.HORIZONTAL;
c.anchor = GridBagConstraints.LINE_END;
c.insets = new Insets(2, 0, 2, 0);
// ------------------------------------------------------------------------
// Grid offset
c.gridx = 0;
c.gridy = 0;
offsetPanel.add(new JLabel(getString("gridOffsetMode.Label")), c);
c.gridx = 1;
offsetPanel.add(chooser = new JComboBox<String>(), c);
chooser.setToolTipText(getString("gridOffsetMode.Tooltip"));
chooser.addItemListener(new ItemListener() {
Override
public void itemStateChanged(ItemEvent event) {
if (event.getStateChange() == ItemEvent.DESELECTED)
return;
if ((String) event.getItem() == getString("gridOffsetMode.MeanSizeMode"))
setGridOffsetOption(OFFSET_BY_MEAN_NODE_SIZE);
else if ((String) event.getItem() == getString("gridOffsetMode.MaxSizeMode"))
setGridOffsetOption(OFFSET_BY_MAX_NODE_SIZE);
else if ((String) event.getItem() == getString("gridOffsetMode.AsSpecifiedMode"))
setGridOffsetOption(OFFSET_AS_SPECIFIED);
else
throw new RuntimeException("unsupported item: " + (String) event.getItem());
updateGridOffsets(true);
}
});
chooser.addItem(getString("gridOffsetMode.MaxSizeMode"));
chooser.addItem(getString("gridOffsetMode.MeanSizeMode"));
chooser.addItem(getString("gridOffsetMode.AsSpecifiedMode"));
chooser.setSelectedIndex(0);
setGridOffsetOption(OFFSET_BY_MAX_NODE_SIZE);
c.gridx = 0;
c.gridy = 1;
offsetPanel.add(new JLabel(getString("offsetParameterHeader.Horizontal.Label")), c);
c.gridx = 1;
offsetPanel.add(hGridOffset, c);
c.gridx = 0;
c.gridy = 2;
offsetPanel.add(new JLabel(getString("offsetParameterHeader.Vertical.Label")), c);
c.gridx = 1;
offsetPanel.add(vGridOffset, c);
hGridOffset.setToolTipText(getString("horizontalGridOffset.Tooltip"));
hGridOffset.addActionListener(new ActionListener() {
Override
public void actionPerformed(ActionEvent e) {
setGridOffset("hgridoffset", hGridOffset);
}
});
vGridOffset.setToolTipText(getString("verticalGridOffset.Tooltip"));
vGridOffset.addActionListener(new ActionListener() {
Override
public void actionPerformed(ActionEvent e) {
setGridOffset("vgridoffset", vGridOffset);
}
});
// ------------------------------------------------------------------------
// Layout parameters
JCheckBox incrementalOption = new JCheckBox(getString("incrementalMode.Checkbox.Label"),
layout.isIncrementalMode());
layoutParameters2.add(incrementalOption);
incrementalOption.setToolTipText(getString("incrementalMode.Checkbox.Tooltip"));
incrementalOption.addItemListener(new ItemListener() {
Override
public void itemStateChanged(ItemEvent e) {
if (e.getStateChange() == ItemEvent.SELECTED)
layout.setIncrementalMode(true);
else if (e.getStateChange() == ItemEvent.DESELECTED)
layout.setIncrementalMode(false);
}
});
JCheckBox preserveFixedNodesOption = new JCheckBox(getString("fixSelected.Checkbox.Label"),
layout.isPreserveFixedNodes());
layoutParameters2.add(preserveFixedNodesOption);
preserveFixedNodesOption.setToolTipText(getString("fixSelected.Checkbox.Tooltip"));
preserveFixedNodesOption.addItemListener(new ItemListener() {
Override
public void itemStateChanged(ItemEvent e) {
if (e.getStateChange() == ItemEvent.SELECTED)
layout.setPreserveFixedNodes(true);
else if (e.getStateChange() == ItemEvent.DESELECTED) {
layout.setPreserveFixedNodes(false);
}
}
});
final JCheckBox showGridOption = new JCheckBox(getString("showGrid.Checkbox.Label"), true);
layoutParameters2.add(showGridOption);
showGridOption.setToolTipText(getString("showGrid.Checkbox.Tooltip"));
showGridOption.addItemListener(new ItemListener() {
Override
public void itemStateChanged(ItemEvent e) {
if (e.getStateChange() == ItemEvent.SELECTED)
showGrid(true);
else if (e.getStateChange() == ItemEvent.DESELECTED)
showGrid(false);
}
});
// ------------------------------------------------------------------------
// Alignment
// horizontal global alignment parameter
final JLabel horizAlignmentLabel = new JLabel(getString("horizontalAlignment.Label"));
final JComboBox<String> hAlignmentChooser = new JComboBox<String>();
hAlignmentChooser.setToolTipText(getString("horizontalAlignment.Tooltip"));
hAlignmentChooser.addItemListener(new ItemListener() {
Override
public void itemStateChanged(ItemEvent event) {
if (event.getStateChange() == ItemEvent.DESELECTED)
return;
if ((String) event.getItem() == getString("horizontalAlignment.CenterMode"))
layout.setGlobalHorizontalAlignment(IlvGridLayout.CENTER);
else if ((String) event.getItem() == getString("horizontalAlignment.LeftMode"))
layout.setGlobalHorizontalAlignment(IlvGridLayout.LEFT);
else if ((String) event.getItem() == getString("horizontalAlignment.RightMode"))
layout.setGlobalHorizontalAlignment(IlvGridLayout.RIGHT);
}
});
hAlignmentChooser.addItem(getString("horizontalAlignment.CenterMode"));
hAlignmentChooser.addItem(getString("horizontalAlignment.LeftMode"));
hAlignmentChooser.addItem(getString("horizontalAlignment.RightMode"));
hAlignmentChooser.setSelectedIndex(0);
// vertical global alignment parameter
final JLabel vertAlignmentLabel = new JLabel(getString("verticalAlignment.Label"));
final JComboBox<String> vAlignmentChooser = new JComboBox<String>();
vAlignmentChooser.setToolTipText(getString("verticalAlignment.Tooltip"));
vAlignmentChooser.addItemListener(new ItemListener() {
Override
public void itemStateChanged(ItemEvent event) {
if (event.getStateChange() == ItemEvent.DESELECTED)
return;
if ((String) event.getItem() == getString("verticalAlignment.CenterMode"))
layout.setGlobalVerticalAlignment(IlvGridLayout.CENTER);
else if ((String) event.getItem() == getString("verticalAlignment.TopMode"))
layout.setGlobalVerticalAlignment(IlvGridLayout.TOP);
else if ((String) event.getItem() == getString("verticalAlignment.BottomMode"))
layout.setGlobalVerticalAlignment(IlvGridLayout.BOTTOM);
}
});
vAlignmentChooser.addItem(getString("verticalAlignment.CenterMode"));
vAlignmentChooser.addItem(getString("verticalAlignment.TopMode"));
vAlignmentChooser.addItem(getString("verticalAlignment.BottomMode"));
vAlignmentChooser.setSelectedIndex(0);
// ------------------------------------------------------------------------
// Ordering options
orderSelector = new JComboBox<String>();
orderSelectorLabel = new JLabel(getString("nodeOrderSelector.Label"));
orderSelector.setToolTipText(getString("nodeOrderSelector.Tooltip"));
orderSelector.addItem(getString("nodeOrderSelector.NoneMode"));
orderSelector.addItem(getString("nodeOrderSelector.AutoMode"));
/*
* as the sample IVLs don't have labels, we hide this option
* orderSelector.addItem(getString("nodeOrderSelector.AscLabelMode"));
* orderSelector.addItem(getString("nodeOrderSelector.DescLabelMode"));
*/
orderSelector.addItem(getString("nodeOrderSelector.AscWidthMode"));
orderSelector.addItem(getString("nodeOrderSelector.DescWidthMode"));
orderSelector.addItem(getString("nodeOrderSelector.AscHeightMode"));
orderSelector.addItem(getString("nodeOrderSelector.DescHeightMode"));
orderSelector.addItem(getString("nodeOrderSelector.AscAreaMode"));
orderSelector.addItem(getString("nodeOrderSelector.DescAreaMode"));
orderSelector.setSelectedIndex(2);
orderSelector.addActionListener(new ActionListener() {
Override
public void actionPerformed(ActionEvent event) {
SuppressWarnings("unchecked")
JComboBox<String> comboBox = (JComboBox<String>) event.getSource();
String ordering = (String) comboBox.getSelectedItem();
setOrdering(ordering);
}
});
// ------------------------------------------------------------------------
// Layout mode
c.gridx = 0;
c.gridy = 0;
layoutParameters1.add(new JLabel(getString("layoutModeSelector.Label")), c);
c.gridx = 1;
layoutParameters1.add(chooser = new JComboBox<String>(), c);
c.gridx = 0;
c.gridy = 1;
layoutParameters1.add(horizAlignmentLabel, c);
c.gridx = 1;
layoutParameters1.add(hAlignmentChooser, c);
c.gridx = 0;
c.gridy = 2;
layoutParameters1.add(vertAlignmentLabel, c);
c.gridx = 1;
layoutParameters1.add(vAlignmentChooser, c);
c.gridx = 0;
c.gridy = 3;
layoutParameters1.add(orderSelectorLabel, c);
c.gridx = 1;
layoutParameters1.add(orderSelector, c);
chooser.setToolTipText(getString("layoutModeSelector.Tooltip"));
chooser.addItemListener(new ItemListener() {
Override
public void itemStateChanged(ItemEvent event) {
if (event.getStateChange() == ItemEvent.DESELECTED)
return;
if ((String) event.getItem() == getString("layoutModeSelector.GridWMode"))
setLayoutMode(IlvGridLayout.TILE_TO_GRID_FIXED_WIDTH, offsetPanel, showGridOption, horizAlignmentLabel,
hAlignmentChooser, vertAlignmentLabel, vAlignmentChooser);
else if ((String) event.getItem() == getString("layoutModeSelector.GridHMode"))
setLayoutMode(IlvGridLayout.TILE_TO_GRID_FIXED_HEIGHT, offsetPanel, showGridOption, horizAlignmentLabel,
hAlignmentChooser, vertAlignmentLabel, vAlignmentChooser);
else if ((String) event.getItem() == getString("layoutModeSelector.RowMode"))
setLayoutMode(IlvGridLayout.TILE_TO_ROWS, offsetPanel, showGridOption, horizAlignmentLabel, hAlignmentChooser,
vertAlignmentLabel, vAlignmentChooser);
else if ((String) event.getItem() == getString("layoutModeSelector.ColumnMode"))
setLayoutMode(IlvGridLayout.TILE_TO_COLUMNS, offsetPanel, showGridOption, horizAlignmentLabel,
hAlignmentChooser, vertAlignmentLabel, vAlignmentChooser);
}
});
chooser.addItem(getString("layoutModeSelector.GridWMode"));
chooser.addItem(getString("layoutModeSelector.GridHMode"));
chooser.addItem(getString("layoutModeSelector.RowMode"));
chooser.addItem(getString("layoutModeSelector.ColumnMode"));
chooser.setSelectedIndex(0);
// ------------------------------------------------------------------------
// add the message line to the bottom panel
bottomPanel.add("South", msgLine);
msgLine.setEditable(false);
// set the component orientation according to the locale
Locale loc = IlvSwingUtil.getDefaultLocale();
ComponentOrientation co = ComponentOrientation.getOrientation(loc);
getContentPane().applyComponentOrientation(co);
// load a sample grapher
loadGrapher("small");
}
/**
* Allows you to run the demo as a standalone application.
*/
public static void main(String[] arg) {
// Sun recommends that to put the entire GUI initialization into the
// AWT thread
SwingUtilities.invokeLater(new Runnable() {
Override
public void run() {
GridLayoutApp app = new GridLayoutApp();
app.init();
JFrame frame = new JFrame(getString("Frame.Label"));
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(650, 600);
frame.getContentPane().add(app);
frame.setVisible(true);
}
});
}
/**
* Load a sample IVL file.
*
* @param fileNameBase
* The base of the filename, excluding the path prefix and the
* extension suffix.
*/
private void loadGrapher(String fileNameBase) {
try {
showMessage(getString("FileReadingStartMessage"), fileNameBase);
grapher.deleteAll(false);
try {
grapher.read(IlvSwingUtil.getRelativeURL(this, "data/" + fileNameBase + ".ivl"));
} catch (Exception ex1) {
// This case occurs only when we pack the entire application into
// one jar including the data files, and start as application
grapher.read(getClass().getResource("data/" + fileNameBase + ".ivl"));
}
// the transformer may have been modified, so
// we set the identity transformer
mgrview.setTransformer(new IlvTransformer());
nodeSizesUpToDate = false;
updateGridOffsets(false);
grapher.reDraw();
showMessage(getString("FileReadingDoneMessage"), fileNameBase);
} catch (Exception e) {
// e.printStackTrace();
showMessage(e.getMessage());
}
}
/**
* Sets the layout mode. Depending on the layout mode, some components of the
* GUI are enabled or disabled.
*/
private void setLayoutMode(int mode, JComponent offsetPanel, JCheckBox showGridOption, JComponent horizAlignmentLabel,
JComponent hAlignmentChooser, JComponent vertAlignmentLabel, JComponent vAlignmentChooser) {
switch (mode) {
case IlvGridLayout.TILE_TO_GRID_FIXED_WIDTH:
offsetPanel.setEnabled(true);
hGridOffset.setEnabled(true);
vGridOffset.setEnabled(true);
setGridOffsetOption(getGridOffsetOption());
showGridOption.setEnabled(true);
showGrid(showGridOption.isSelected());
horizAlignmentLabel.setEnabled(true);
hAlignmentChooser.setEnabled(true);
vertAlignmentLabel.setEnabled(true);
vAlignmentChooser.setEnabled(true);
break;
case IlvGridLayout.TILE_TO_GRID_FIXED_HEIGHT:
offsetPanel.setEnabled(true);
hGridOffset.setEnabled(true);
vGridOffset.setEnabled(true);
setGridOffsetOption(getGridOffsetOption());
showGridOption.setEnabled(true);
showGrid(showGridOption.isSelected());
horizAlignmentLabel.setEnabled(true);
hAlignmentChooser.setEnabled(true);
vertAlignmentLabel.setEnabled(true);
vAlignmentChooser.setEnabled(true);
break;
case IlvGridLayout.TILE_TO_ROWS:
offsetPanel.setEnabled(false);
hGridOffset.setEnabled(false);
vGridOffset.setEnabled(false);
showGridOption.setEnabled(false);
showGrid(false);
horizAlignmentLabel.setEnabled(false);
hAlignmentChooser.setEnabled(false);
vertAlignmentLabel.setEnabled(true);
vAlignmentChooser.setEnabled(true);
break;
case IlvGridLayout.TILE_TO_COLUMNS:
offsetPanel.setEnabled(false);
hGridOffset.setEnabled(false);
vGridOffset.setEnabled(false);
showGridOption.setEnabled(false);
showGrid(false);
horizAlignmentLabel.setEnabled(true);
hAlignmentChooser.setEnabled(true);
vertAlignmentLabel.setEnabled(false);
vAlignmentChooser.setEnabled(false);
break;
default:
throw new IllegalArgumentException("unsupported layout mode: " + mode);
}
layout.setLayoutMode(mode);
updateGridOffsets(false);
}
/**
* Sets the order option.
*/
/**
* Sets the node ordering mode.
*/
private void setOrdering(String ordering) {
if (ordering.equals(getString("nodeOrderSelector.NoneMode")))
layout.setNodeComparator(IlvGridLayout.NO_ORDERING);
else if (ordering.equals(getString("nodeOrderSelector.AutoMode")))
layout.setNodeComparator(IlvGridLayout.AUTOMATIC_ORDERING);
/*
* as the samples IVLs don't have labels, we hide this option: else if
* (ordering.equals(getString("nodeOrderSelector.AscLabelMode")))
* layout.setNodeComparator(IlvGridLayout.ASCENDING_INDEX); else if
* (ordering.equals(getString("nodeOrderSelector.DescLabelMode")))
* layout.setNodeComparator(IlvGridLayout.DESCENDING_INDEX);
*/
else if (ordering.equals(getString("nodeOrderSelector.AscWidthMode")))
layout.setNodeComparator(IlvGridLayout.ASCENDING_WIDTH);
else if (ordering.equals(getString("nodeOrderSelector.DescWidthMode")))
layout.setNodeComparator(IlvGridLayout.DESCENDING_WIDTH);
else if (ordering.equals(getString("nodeOrderSelector.AscHeightMode")))
layout.setNodeComparator(IlvGridLayout.ASCENDING_HEIGHT);
else if (ordering.equals(getString("nodeOrderSelector.DescHeightMode")))
layout.setNodeComparator(IlvGridLayout.DESCENDING_HEIGHT);
else if (ordering.equals(getString("nodeOrderSelector.AscAreaMode")))
layout.setNodeComparator(IlvGridLayout.ASCENDING_AREA);
else if (ordering.equals(getString("nodeOrderSelector.DescAreaMode")))
layout.setNodeComparator(IlvGridLayout.DESCENDING_AREA);
else
throw new IllegalArgumentException("unsupported ordering: " + ordering);
}
/**
* Sets the grid offset from the number field.
*/
private void setGridOffset(String property, IlvJSpinnerDecimalNumberField valueSelector) {
double value = valueSelector.getDoubleValue();
if (property.equals("hgridoffset")) {
layout.setHorizontalGridOffset(value);
grid.setHorizontalSpacing(layout.getHorizontalGridOffset());
} else if (property.equals("vgridoffset")) {
layout.setVerticalGridOffset(value);
grid.setVerticalSpacing(layout.getVerticalGridOffset());
}
updateGridOffsets(false);
// redraw the view
mgrview.repaint();
}
/**
* Enables or disabled the display of a grid.
*/
private void showGrid(boolean show) {
boolean visible = grid.isVisible();
if (visible != show) {
grid.setVisible(show);
mgrview.repaint();
}
}
/**
* Performs the layout of the graph.
*/
private void layout(IlvGraphLayout layout, boolean updateGridOffset) {
// the layout report instance; this is an object in which
// the layout algorithm stores information about its behavior
IlvGraphLayoutReport layoutReport;
showMessage(getString("LayoutStartMessage"));
// initialize the iteration listener
// (this will simply empty the message string)
layoutListener.initialize();
boolean mustRepaintAll = false;
if (updateGridOffset)
mustRepaintAll = updateGridOffsets(false);
try {
// Perform the layout.
// If the IlvGrid spacing was changed, we need to redraw the entire view,
// therefore in this case we don't ask the layout to take in charge
// the redrawing
layoutReport = layout.performLayout(false, !mustRepaintAll);
if (mustRepaintAll)
// total redraw of the view because of grid size change
mgrview.repaint();
// print the code from the layout report
showMessage(getString("LayoutDoneMessage"),
layoutReport.codeToString(layoutReport.getCode(), IlvLocaleUtil.getCurrentULocale()));
} catch (IlvGraphLayoutException e) {
// e.printStackTrace();
showMessage(e.getMessage());
}
}
/**
* Implementation of ilog.views.event.ManagerSelectionListener. It allows us
* to change the "fixed" attribute of the nodes according to selection.
*
* @param event
* the "selection changed" event.
* @see IlvManager#addManagerSelectionListener
* @see IlvManager#removeManagerSelectionListener
* @see IlvManager#selectionChanged
*/
Override
public void selectionChanged(ManagerSelectionChangedEvent event) {
IlvGraphic obj = event.getGraphic();
if (grapher.isNode(obj))
layout.setFixed(obj, grapher.isSelected(obj));
}
/**
* This method is called by the manager, to notify content modifications.
*
* @param event
* the "content changed" event.
* @see IlvManager#addManagerContentChangedListener
* @see IlvManager#removeManagerContentChangedListener
*/
Override
public void contentsChanged(ManagerContentChangedEvent event) {
if (nodeSizesUpToDate && event.getType() == ManagerContentChangedEvent.OBJECT_BBOX_CHANGED) {
ObjectBBoxChangedEvent bboxEvent = (ObjectBBoxChangedEvent) event;
IlvRect oldBox = bboxEvent.getOldBoundingBox();
IlvRect newBox = bboxEvent.getNewBoundingBox();
if (oldBox.width != newBox.width || oldBox.height != newBox.height)
nodeSizesUpToDate = false;
}
if (!layout.isLayoutRunning() && !randomLayout.isLayoutRunning() && layout.isPreserveFixedNodes()) { // it
// looks
// funny
// in
// this
// mode
// only
if ((!event.isAdjusting() && event.getType() == ManagerContentChangedEvent.OBJECT_BBOX_CHANGED)
|| (event.getType() == ManagerContentChangedEvent.ADJUSTMENT_END && previousEvent != null
&& previousEvent.getType() == ManagerContentChangedEvent.OBJECT_BBOX_CHANGED))
layout(layout, true);
if (event.getType() != ManagerContentChangedEvent.ADJUSTMENT_END)
previousEvent = event;
}
}
/**
* Displays a message.
*/
void showMessage(String message) {
// the message is displayed in the message line
msgLine.setText(message);
msgLine.paintImmediately(0, 0, msgLine.getWidth(), msgLine.getHeight());
}
void showMessage(String msgformat, Object val) {
Object[] args = { val };
showMessage(MessageFormat.format(msgformat, args));
}
/**
* Returns a string.
*/
static String getString(String key) {
return IlvResourceUtil.getString(key, GridLayoutApp.class, IlvLocaleUtil.getCurrentLocale());
}
/**
* Preprocess graph: Add some local parameters for demonstration purpose.
*/
private void preprocess() {
// nothing currently
}
/**
* Sets how the grid offset is calculated.
*/
private void setGridOffsetOption(int option) {
if (option != OFFSET_BY_MEAN_NODE_SIZE && option != OFFSET_BY_MAX_NODE_SIZE && option != OFFSET_AS_SPECIFIED)
throw new IllegalArgumentException("unsupported grid offset option: " + option);
gridOffsetOption = option;
hGridOffset.setEnabled(option == OFFSET_AS_SPECIFIED);
vGridOffset.setEnabled(option == OFFSET_AS_SPECIFIED);
}
/**
* Returns how the grid offset is calculated.
*/
private int getGridOffsetOption() {
return gridOffsetOption;
}
/**
* Updates the grid offset parameters depending on user's choice. If the user
* has requested an automatic computation of the grid offsets depending on the
* current size of the nodes, this size is taken into account.
*
* @return true if the grid has been changed, false otherwise
*/
private boolean updateGridOffsets(boolean redraw) {
IlvGraphModel graphModel = layout.getGraphModel();
double oldHOffset = layout.getHorizontalGridOffset();
double oldVOffset = layout.getVerticalGridOffset();
computeNodeSizes(graphModel);
double hOffset;
double vOffset;
double totalHorizontalMargin = layout.getLeftMargin() + layout.getRightMargin();
double totalVerticalMargin = layout.getTopMargin() + layout.getBottomMargin();
boolean orderEnabled = false;
switch (getGridOffsetOption()) {
case OFFSET_BY_MEAN_NODE_SIZE:
hOffset = totalNodeWidth / numberOfNodes + totalHorizontalMargin + 1;
vOffset = totalNodeHeight / numberOfNodes + totalVerticalMargin + 1;
orderEnabled = false;
break;
case OFFSET_BY_MAX_NODE_SIZE:
hOffset = maxNodeWidth + totalHorizontalMargin + 1;
vOffset = maxNodeHeight + totalVerticalMargin + 1;
orderEnabled = true;
break;
case OFFSET_AS_SPECIFIED:
// in this case, the offsets always have been set before
hOffset = layout.getHorizontalGridOffset();
vOffset = layout.getVerticalGridOffset();
orderEnabled = hOffset > (maxNodeWidth + totalHorizontalMargin)
&& vOffset > (maxNodeHeight + totalVerticalMargin);
break;
default:
throw new RuntimeException("unsupported grid offset option: " + getGridOffsetOption());
}
// Update if necessary the enabled/disabled state of the node order combo.
// Indeed, the order options are always effective in row or column modes,
// while for
// the grid modes they are effective only if all the nodes fit in one grid
// cell
if (orderSelectorLabel != null && orderSelector != null) {
orderSelectorLabel.setEnabled(orderEnabled);
orderSelector.setEnabled(orderEnabled);
}
boolean isGridChanged = false;
if (hOffset != oldHOffset || vOffset != oldVOffset) {
// set the new values on the layout
layout.setHorizontalGridOffset(hOffset);
layout.setVerticalGridOffset(vOffset);
// update the manager view grid
grid.setHorizontalSpacing(layout.getHorizontalGridOffset());
grid.setVerticalSpacing(layout.getVerticalGridOffset());
hGridOffset.setDoubleValue(layout.getHorizontalGridOffset());
vGridOffset.setDoubleValue(layout.getVerticalGridOffset());
isGridChanged = true;
}
IlvPoint origin = grid.getOrigin();
IlvRect layoutRegion = layout.getCalcLayoutRegion();
if (origin.x != layoutRegion.x || origin.y != layoutRegion.y) {
grid.setOrigin(new IlvPoint(layoutRegion.x, layoutRegion.y));
isGridChanged = true;
}
if (isGridChanged && redraw)
// because of the IlvGrid, we need to repaint
mgrview.repaint();
return isGridChanged;
}
/**
* Computes the total width/height and the maximum width/height of the nodes.
* These values are needed to adapt the grid offset values, if the user
* chooses this option.
*/
private void computeNodeSizes(IlvGraphModel graphModel) {
if (nodeSizesUpToDate)
return;
IlvGraphic node;
IlvRect bbox;
totalNodeWidth = 0;
totalNodeHeight = 0;
maxNodeWidth = 0;
maxNodeHeight = 0;
numberOfNodes = 0;
Enumeration<?> nodes = graphModel.getNodes();
while (nodes.hasMoreElements()) {
node = (IlvGraphic) nodes.nextElement();
numberOfNodes++;
bbox = graphModel.boundingBox(node);
totalNodeWidth += bbox.width;
totalNodeHeight += bbox.height;
if (bbox.width > maxNodeWidth)
maxNodeWidth = bbox.width;
if (bbox.height > maxNodeHeight)
maxNodeHeight = bbox.height;
}
nodeSizesUpToDate = true;
}
/**
* A subclass of ilog.views.IlvGrid that draws lines instead of points.
*/
private class LineGrid extends IlvGrid {
/**
* Creates a new grid. The origin of the grid is the point (0,0). The
* horizontal and verical spacing are 10. The grid is active and visible.
*/
public LineGrid() {
super();
}
/**
* Creates a new grid.
*
* @param color
* the color of the grid points.
* @param origin
* the coordinates of the upper-left corner of the grid in the
* manager coordinates system.
* @param hspacing
* spacing of grid points along the horizontal axis.
* @param vspacing
* spacing of grid points along the vertical axis.
* @param visible
* Specifies whether the grid is visible (<code>true</code>) of
* invisible.
* @param active
* Specifies whether the grid is active (<code>true</code>) of
* inactive.
* @see IlvManagerView#setGrid
*/
SuppressWarnings("unused")
public LineGrid(Color color, IlvPoint origin, double hspacing, double vspacing, boolean visible, boolean active) {
super(color, origin, hspacing, vspacing, visible, active);
}
/**
* Draws the grid. This method is called by the view
* (<code>IlvManagerView</code>) to draw the grid.
*
* @param dst
* the Graphics object to perform the drawing of the grid.
* @param t
* the transformer used to draw to grid.
* @param rect
* The area where the grid will be drawn. Note that the grid is
* drawn only at the intersection of this area with the clipping
* area provided in the <code>dst</code> parameter. When the grid
* is used in an <code>IlvManagerView</code>, this parameter is the
* bounding rectangle of the view.
*/
Override
protected void draw(Graphics dst, IlvTransformer t, Rectangle rect) {
if (!isVisible())
return;
Shape oldclip = dst.getClip();
Rectangle theclip = oldclip.getBounds();
Rectangle areaToDraw = theclip.intersection(rect);
if (areaToDraw.width == 0 || areaToDraw.height == 0)
return;
dst.clipRect(areaToDraw.x, areaToDraw.y, areaToDraw.width, areaToDraw.height);
// the origin
IlvPoint orig = new IlvPoint();
// the spacing parameters
IlvPoint spacing = new IlvPoint(getHorizontalSpacing() * getHorizontalShown(),
getVerticalSpacing() * getHorizontalShown());
if (t != null) {
t.apply(orig);
t.apply(spacing);
}
// in view coords
double spacingX = Math.abs(orig.x - spacing.x);
double spacingY = Math.abs(orig.y - spacing.y);
if (spacingX < 4 || spacingY < 4)
return;
float minX = areaToDraw.x;
float maxX = areaToDraw.x + areaToDraw.width;
float minY = areaToDraw.y;
float maxY = areaToDraw.y + areaToDraw.height;
IlvPoint originPoint = getOrigin();
if (t != null)
t.apply(originPoint);
int nX = (int) Math.ceil((minX - originPoint.x) / spacingX);
int nY = (int) Math.ceil((minY - originPoint.y) / spacingY);
double fromX = originPoint.x + nX * spacingX;
double fromY = originPoint.y + nY * spacingY;
dst.setColor(getColor());
// draw horizontal lines
for (double y = fromY; y <= maxY; y += spacingY)
dst.drawLine((int) Math.floor(minX), (int) Math.floor(y), (int) Math.floor(maxX), (int) Math.floor(y));
// draw vertical lines
for (double x = fromX; x <= maxX; x += spacingX)
dst.drawLine((int) Math.floor(x), (int) Math.floor(minY), (int) Math.floor(x), (int) Math.floor(maxY));
dst.setClip(oldclip);
}
}
/**
* A Panel which enables/disables its components. The purpose of this subclass
* of JPanel is to produce the same graphic effect when enabling or disabling
* with all Java Virtual Machines.
*/
private class MyPanel extends JPanel {
Override
public void setEnabled(boolean enable) {
super.setEnabled(enable);
Component[] components = getComponents();
if (components != null) {
for (int i = 0; i < components.length; i++)
if (components[i] != null)
components[i].setEnabled(enable);
}
setGridOffsetOption(getGridOffsetOption());
}
}
// -------------------------------------------------------------------------
/**
* A graph layout iteration listener. Implementing the interface
* GraphLayoutEventListener gives you the possibility to receive during the
* layout information about the behavior of the layout algorithm. This
* information is contained in the graph layout event.
*
* In our case, we will simply print a dot each time the method
* layoutStepPerformed is called, that is after each iteration of the Bus
* Layout algorithm.
*/
class LayoutIterationListener implements GraphLayoutEventListener {
private String toShow = "";
private static final int MAX_LENGTH = 50;
/**
* This method is automatically called by the layout algorithm.
*/
Override
public void layoutStepPerformed(GraphLayoutEvent event) {
// the status area has a limited width, so we are forced to
// reinitialize the message string
if (toShow.length() > MAX_LENGTH)
toShow = "";
toShow += ".";
showMessage(toShow);
}
/**
* Initialize the listener by reseting the toShow variable. This method must
* be called before the layout is started.
*/
void initialize() {
toShow = "";
}
}
}