/* * Licensed Materials - Property of Perforce Software, Inc. * © Copyright Perforce Software, Inc. 2014, 2021 * © Copyright IBM Corp. 2009, 2014 * © Copyright ILOG 1996, 2009 * All Rights Reserved. * * Note to U.S. Government Users Restricted Rights: * The Software and Documentation were developed at private expense and * are "Commercial Items" as that term is defined at 48 CFR 2.101, * consisting of "Commercial Computer Software" and * "Commercial Computer Software Documentation", as such terms are * used in 48 CFR 12.212 or 48 CFR 227.7202-1 through 227.7202-4, * as applicable. */ import java.awt.BorderLayout; import java.awt.Color; import java.awt.ComponentOrientation; import java.awt.FlowLayout; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.SystemColor; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.text.MessageFormat; import java.util.Locale; import javax.swing.JComboBox; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JRootPane; import javax.swing.JTextField; import javax.swing.SwingUtilities; import ilog.views.IlvGrapher; import ilog.views.IlvHandlesSelection; import ilog.views.IlvManagerView; import ilog.views.IlvPoint; import ilog.views.IlvRect; import ilog.views.IlvTransformer; 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.IlvLinkClipInterface; import ilog.views.graphlayout.IlvRotatedGraphModel; import ilog.views.graphlayout.grid.IlvGridLayout; import ilog.views.graphlayout.hierarchical.IlvHierarchicalLayout; import ilog.views.graphlayout.topologicalmesh.IlvTopologicalMeshLayout; import ilog.views.graphlayout.tree.IlvTreeLayout; import ilog.views.interactor.IlvSelectInteractor; import ilog.views.interactor.IlvZoomViewInteractor; import ilog.views.linkconnector.IlvClippingUtil; 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.IlvJComboBox; 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 rotated layout. It shows how to use the * rotated graph model in applications that are not based on CSS styling. */ public class RotatedLayoutApp extends JRootPane { 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); /** The layout instances */ IlvGraphLayout[] layouts; /** The display names of the samples */ String[] sampleNames; /** The file names of the samples */ String[] fileNames; /** The rotated graph model */ IlvRotatedGraphModel rotatedModel; /** The grapher adapter encapsulated in the rotated graph model. */ IlvGrapherAdapter adapter; /** The current layout */ IlvGraphLayout layout; /** The link clipper */ IlvLinkClipInterface linkClipper; /** The shear modes: the values must be the index in the combo box. */ final static int UNSHEARED = 0; final static int SHEAR_X = 1; final static int SHEAR_Y = 2; /** Whether the rotation is a shear in X direction. */ int shearMode = UNSHEARED; /** A text field to display messages */ JTextField msgLine = new JTextField(); /** The default angle */ static final double DEFAULT_ANGLE = 30.; /** Fields for the offset parameters */ IlvJSpinnerDecimalNumberField rotationAngleSelector = new IlvJSpinnerDecimalNumberField(-45, 45, DEFAULT_ANGLE, false, 6, 1); /** * Initializes the application. */ public void init() { showMessage(getString("InitMessage")); // create a rotated graph model of a grapher adapter adapter = new IlvGrapherAdapter(grapher); rotatedModel = new IlvRotatedGraphModel(adapter, false, new IlvPoint(), 30); // initialize the layouts initLayouts(); // create the scroll manager view IlvJScrollManagerView scrollManView = new IlvJScrollManagerView(mgrview); // 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.002, 10.0); mgrview.setWheelZoomingEnabled(true); scrollManView.setWheelScrollingEnabled(true); // Settings parameters for selection handles IlvHandlesSelection.defaultHandleColor = Color.blue; IlvHandlesSelection.defaultHandleBackgroundColor = Color.pink; IlvHandlesSelection.defaultHandleShape = IlvHandlesSelection.SQUARE_SHAPE; // create the standard control bar IlvJManagerViewControlBar controlBar = new IlvJManagerViewControlBar(); controlBar.setView(mgrview); // modify the interactors such that the demo looks better ((IlvSelectInteractor) controlBar.getSelectInteractor()).setOpaqueMove(true); ((IlvZoomViewInteractor) controlBar.getZoomViewInteractor()).setPermanent(true); // set the initial interactor mgrview.setInteractor(controlBar.getSelectInteractor()); // create the graph selector SuppressWarnings("unchecked") JComboBox<String> fileSelector = new IlvJComboBox(); for (int i = 0; i < sampleNames.length; i++) fileSelector.addItem(sampleNames[i]); fileSelector.setToolTipText(getString("FileSelector.Tooltip")); fileSelector.addActionListener(new ActionListener() { Override public void actionPerformed(ActionEvent event) { SuppressWarnings("unchecked") JComboBox<String> comboBox = (JComboBox<String>) event.getSource(); String sampleName = (String) comboBox.getSelectedItem(); for (int i = 0; i < sampleNames.length; i++) if (sampleNames[i].equals(sampleName)) loadGrapher(i); } }); // create the top panel with the toolbar and the file selector JPanel topPanel = new JPanel(); topPanel.setLayout(new FlowLayout(FlowLayout.LEADING)); topPanel.add(controlBar); JLabel label = new JLabel(getString("FileSelector.Label")); label.setToolTipText(getString("FileSelector.Tooltip")); topPanel.add(label); topPanel.add(fileSelector); // create the layout parameter panels JPanel normalPanel = createParameterPanel(); // create the bottom panel with the layout buttons and the message line JPanel bottomPanel = new JPanel(); bottomPanel.setLayout(new BorderLayout()); bottomPanel.add(normalPanel, BorderLayout.CENTER); bottomPanel.add(msgLine, BorderLayout.SOUTH); msgLine.setEditable(false); // put manager view, top panel and bottom panel together getContentPane().setLayout(new BorderLayout(0, 0)); getContentPane().add(scrollManView, BorderLayout.CENTER); getContentPane().add(topPanel, BorderLayout.NORTH); getContentPane().add(bottomPanel, BorderLayout.SOUTH); // set the component orientation according to the locale Locale loc = IlvSwingUtil.getDefaultLocale(); ComponentOrientation co = ComponentOrientation.getOrientation(loc); getContentPane().applyComponentOrientation(co); // load a sample grapher loadGrapher(0); mgrview.fitTransformerToContent(true); } /** * Initialize the information about the samples. */ private void initLayouts() { layouts = new IlvGraphLayout[4]; sampleNames = new String[4]; fileNames = new String[4]; layouts[0] = new IlvTreeLayout(); sampleNames[0] = getString("Sample.TreeLayout"); fileNames[0] = "tree.ivl"; layouts[1] = new IlvHierarchicalLayout(); sampleNames[1] = getString("Sample.HierarchicalLayout"); fileNames[1] = "hierarchical.ivl"; layouts[2] = new IlvGridLayout(); sampleNames[2] = getString("Sample.GridLayout"); fileNames[2] = "grid.ivl"; layouts[3] = new IlvTopologicalMeshLayout(); sampleNames[3] = getString("Sample.TMLLayout"); fileNames[3] = "tml.ivl"; // From the rotated model, we can obtain a link // clipper the works with the rotated model. linkClipper = rotatedModel.getLinkClipInterface(new LinkClipper()); for (int i = 0; i < layouts.length; i++) { layouts[i].attach(rotatedModel); } layout = layouts[0]; } /** * Creates the layout parameter panel. */ private JPanel createParameterPanel() { JPanel panel = new JPanel(); GridBagLayout gridbag = new GridBagLayout(); GridBagConstraints c = new GridBagConstraints(); c.fill = GridBagConstraints.HORIZONTAL; c.anchor = GridBagConstraints.LINE_END; panel.setLayout(gridbag); // rotation angle parameter c.gridx = 0; c.gridy = 0; JLabel label = new JLabel(getString("RotationAngle.Label")); label.setToolTipText(getString("RotationAngle.Tooltip")); panel.add(label, c); c.gridx = 1; panel.add(rotationAngleSelector, c); rotationAngleSelector.setToolTipText(getString("RotationAngle.Tooltip")); rotationAngleSelector.addActionListener(new ActionListener() { Override public void actionPerformed(ActionEvent e) { setRotationAngle((IlvJSpinnerDecimalNumberField) e.getSource()); } }); // spacer c.gridx = 2; panel.add(new JLabel(" ")); // rotation angle parameter c.gridx = 3; label = new JLabel(getString("ShearMode.Label")); label.setToolTipText(getString("ShearMode.Tooltip")); panel.add(label, c); c.gridx = 4; SuppressWarnings("unchecked") JComboBox<String> shearModeSelector = new IlvJComboBox(); shearModeSelector.addItem(getString("ShearMode.Unsheared")); shearModeSelector.addItem(getString("ShearMode.ShearX")); shearModeSelector.addItem(getString("ShearMode.ShearY")); shearModeSelector.setToolTipText(getString("ShearMode.Tooltip")); shearModeSelector.addActionListener(new ActionListener() { Override public void actionPerformed(ActionEvent event) { SuppressWarnings("unchecked") JComboBox<String> comboBox = (JComboBox<String>) event.getSource(); shearMode = comboBox.getSelectedIndex(); setRotationAngle(rotationAngleSelector); } }); panel.add(shearModeSelector, c); // set the component orientation according to the locale Locale loc = IlvSwingUtil.getDefaultLocale(); ComponentOrientation co = ComponentOrientation.getOrientation(loc); panel.applyComponentOrientation(co); return panel; } /** * Sets the rotation angle of the rotated model. */ private void setRotationAngle(IlvJSpinnerDecimalNumberField valueSelector) { double D; double angle = valueSelector.getDoubleValue(); IlvTransformer t = new IlvTransformer(new IlvPoint(), angle); switch (shearMode) { case SHEAR_X: t.setValues(t.getx11(), 0, t.getx21(), t.getx22(), t.getx0(), t.gety0()); D = t.getDeterminant(); t.setValues(t.getx11() / D, t.getx12() / D, t.getx21() / D, t.getx22() / D, t.getx0(), t.gety0()); break; case SHEAR_Y: t.setValues(t.getx11(), t.getx12(), 0, t.getx22(), t.getx0(), t.gety0()); D = t.getDeterminant(); t.setValues(t.getx11() / D, t.getx12() / D, t.getx21() / D, t.getx22() / D, t.getx0(), t.gety0()); } rotatedModel.setTransformer(t); layout(layout, grapher); } /** * Performs the layout of the graph. */ private void layout(IlvGraphLayout layout, IlvGrapher grapher) { // the layout report instance; this is an object in which // the layout algorithm stores information about its behavior IlvGraphLayoutReport layoutReport = null; showMessage(getString("LayoutStartMessage")); try { // perform the layout and get the layout report layoutReport = layout.performLayout(true, false); // print the code from the layout report showMessage(getString("LayoutDoneMessage"), layoutReport.codeToString(layoutReport.getCode(), IlvLocaleUtil.getCurrentULocale())); } catch (IlvGraphLayoutException e) { // e.printStackTrace(); showMessage(e.getMessage()); } finally { if (layoutReport != null && layoutReport.getCode() != IlvGraphLayoutReport.NOT_NEEDED) { // show all mgrview.fitTransformerToContent(); mgrview.repaint(); } } } /** * Load a sample IVL file. * * @param index * The index of the sample file. */ private void loadGrapher(int index) { layout.setAutoLayout(false); layout = layouts[index]; String fileName = fileNames[index]; try { showMessage(getString("FileReadingStartMessage"), fileName); grapher.deleteAll(false); try { grapher.read(IlvSwingUtil.getRelativeURL(this, "data/" + fileName)); } 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/" + fileName)); } // load the layout parameters rotatedModel.loadParametersFromNamedProperties(layout); // set some global layout parameters if (layout.supportsLinkClipping()) layout.setLinkClipInterface(linkClipper); layout.setAutoLayout(true); layout.setCoordinatesMode(IlvGraphLayout.MANAGER_COORDINATES); // the transformer may have been modified, so // we set the identity transformer mgrview.setTransformer(new IlvTransformer()); showMessage(getString("FileReadingDoneMessage"), fileName); } catch (Exception e) { // e.printStackTrace(); showMessage(e.getMessage()); } layout(layout, grapher); } /** * 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, RotatedLayoutApp.class, IlvLocaleUtil.getCurrentLocale()); } /** * 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() { RotatedLayoutApp app = new RotatedLayoutApp(); app.init(); JFrame frame = new JFrame(getString("Frame.Label")); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setSize(600, 600); frame.getContentPane().add(app); frame.setVisible(true); } }); } // ------------------------------------------------------------------------ // A link clipper that clips at the bounding box. // This link clipper is designed for the unrotated model static class LinkClipper implements IlvLinkClipInterface { /** * Returns the clipped connection point of a link that starts at the * proposed connection point of the node and goes through the auxiliary * control point. * * @param graphModel * The unrotated graph model to which the node belongs. * @param node * The source or target node of the link. * @param currentNodeBox * The current bounding box of the node. * @param link * The link to be clipped. * @param proposedConnectionPoint * The proposed connection point of the link. * @param auxControlPoint * The auxiliary control point. For clipping purposes, the link can * be considered as a ray that starts at the proposed connection * point and goes through the auxiliary control point. * @param origin * <code>true</code> if the node is the source of the link, * <code>false</code> if it is the target of the link. * @return The point to which the link should connect, with respect to the * unrotated model. */ Override public IlvPoint getConnectionPoint(IlvGraphModel graphModel, Object node, IlvRect currentNodeBox, Object link, IlvPoint proposedConnectionPoint, IlvPoint auxControlPoint, boolean origin) { return IlvClippingUtil.getClippedPoint(currentNodeBox, proposedConnectionPoint, auxControlPoint); } } }