/*
* 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.Container;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Frame;
import java.awt.Point;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import java.net.MalformedURLException;
import java.net.URL;
import java.text.MessageFormat;
import java.util.Iterator;
import java.util.ResourceBundle;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JRootPane;
import javax.swing.JTextField;
import javax.swing.JToolBar;
import javax.swing.SwingUtilities;
import ilog.views.IlvGraphic;
import ilog.views.IlvPoint;
import ilog.views.IlvRect;
import ilog.views.diagrammer.IlvDiagrammer;
import ilog.views.diagrammer.application.IlvDiagrammerAction;
import ilog.views.diagrammer.application.IlvDiagrammerPropertySheet;
import ilog.views.diagrammer.application.IlvDiagrammerViewBar;
import ilog.views.swing.IlvPopupMenuContext;
import ilog.views.swing.IlvPopupMenuManager;
import ilog.views.swing.IlvSimplePopupMenu;
import ilog.views.util.IlvProductUtil;
/**
* This example shows how to extend a Diagrammer project using the SDK.
*/
public class DiagrammerExtension extends JRootPane {
private static final String projectFile = "data/map.idpr";
private ResourceBundle bundle;
// *****************************************
// Creation and initialization of the demo:
// *****************************************
/**
* The constructor: initializes the resource bundle used to get strings.
*/
public DiagrammerExtension() {
// 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("extension");
}
/**
* The main method called when the sample is run as an application.
*/
public static void main(final String[] args) {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
Override
public void run() {
// Create an instance of the demo class.
//
DiagrammerExtension demo = new DiagrammerExtension();
// Create the frame.
//
JFrame frame = new JFrame(demo.getString("FrameTitle"));
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
try {
// Initialize the demo's GUI inside the frame.
//
demo.init(frame.getContentPane(), new URL("file:./"));
} catch (MalformedURLException e) {
e.printStackTrace();
System.exit(1);
}
// Show the frame.
//
frame.setLocation(100, 100);
frame.pack();
frame.setVisible(true);
}
});
}
/**
* Creates all the GUI elements and initializes the extension code.
*/
public void init(Container contentPane, final URL baseURL) {
// Create a simple menu bar:
//
JMenuBar menubar = new JMenuBar();
JMenu fileMenu = new JMenu(getString("FileMenu"));
fileMenu.add(IlvDiagrammerAction.createMenuItem(IlvDiagrammerAction.exit));
menubar.add(fileMenu);
JMenu helpMenu = new JMenu(getString("HelpMenu"));
IlvDiagrammerAction.about.putValue(IlvDiagrammerAction.ABOUT_APPLICATION_NAME,
getString("ApplicationName"));
helpMenu.add(IlvDiagrammerAction.createMenuItem(IlvDiagrammerAction.about));
menubar.add(helpMenu);
((JComponent) contentPane).getRootPane().setJMenuBar(menubar);
// Create the IlvDiagrammer component:
//
final IlvDiagrammer diagrammer = new IlvDiagrammer();
diagrammer.setScrollable(true);
contentPane.add(diagrammer, BorderLayout.CENTER);
// Add a standard Diagrammer toolbar for zooming/panning:
//
IlvDiagrammerViewBar viewBar = new IlvDiagrammerViewBar(JToolBar.VERTICAL);
viewBar.removeAction(IlvDiagrammerAction.select);
contentPane.add(viewBar, BorderLayout.LINE_START);
// Initialize the pop-up menus.
//
initPopupMenus(diagrammer);
// Create the latitude/longitude fields.
//
JPanel panel = createLatLongFields(diagrammer);
contentPane.add(panel, BorderLayout.AFTER_LAST_LINE);
// Load the project.
//
try {
diagrammer.setDataFile(new URL(baseURL, projectFile));
IlvRect bbox = diagrammer.getEngine().getGrapher().computeBBox(null);
diagrammer.setPreferredSize(new Dimension((int) bbox.width + 20, (int) bbox.height + 20));
} catch (Exception ex) {
ex.printStackTrace();
}
}
// *****************************************
// Initialize of the pop-up menu:
// *****************************************
/**
* This method creates the pop-up menus and registers them.
*/
private void initPopupMenus(IlvDiagrammer diagrammer) {
// register the view to handle pop-up menus
IlvPopupMenuManager.registerView(diagrammer.getView());
// Create the node pop-up menu
JPopupMenu nodeMenu = createNodeLinkPopupMenu(diagrammer, true);
// In the CSS, the node pop-up menu is specified in the following way
// node {
// ...
// popupMenuName: "NodePopupMenu";
// }
//
// Hence we must register a pop-up menu with the name "NodePopupMenu"
IlvPopupMenuManager.registerMenu("NodePopupMenu", nodeMenu);
// Create the link pop-up menu
JPopupMenu linkMenu = createNodeLinkPopupMenu(diagrammer, false);
// In the CSS, the link pop-up menu is specified in the following way
// link {
// ...
// popupMenuName: "LinkPopupMenu";
// }
//
// Hence we must register a pop-up menu with the name "LinkPopupMenu"
IlvPopupMenuManager.registerMenu("LinkPopupMenu", linkMenu);
// Register the white space menu for the main grapher.
// Reason: when clicking in the white space, you are in fact clicking
// on the main grapher
JPopupMenu whitespaceMenu = createWhiteSpacePopupMenu(diagrammer);
diagrammer.getEngine().getGrapher().setPopupMenu(whitespaceMenu);
}
/**
* This method creates the pop-up menu for the nodes and links.
*/
private JPopupMenu createNodeLinkPopupMenu(final IlvDiagrammer diagrammer, final boolean isNode) {
IlvSimplePopupMenu popupMenu = new IlvSimplePopupMenu() {
// select only the object that owns the pop-up menu before the pop-up
// menu gets displayed
Override
protected void beforeDisplay(IlvPopupMenuContext context) {
// always call super.beforeDisplay first
super.beforeDisplay(context);
// then the remaining menu preparation
beforeNodeLinkPopupDisplay(this, context, diagrammer, isNode);
}
};
// add a label to contain the title
JLabel label = new JLabel();
label.setBorder(BorderFactory.createEmptyBorder(2, 10, 2, 5));
popupMenu.add(label);
// add the remaining items
popupMenu.addActions(
(isNode
? "- | { DiagrammerExtension.StatusNormal | DiagrammerExtension.StatusWarning | DiagrammerExtension.StatusAlarm } |"
: "") + "- | DiagrammerExtension.Properties",
'|', '{', '}', bundle, new ActionListener() {
Override
public void actionPerformed(ActionEvent e) {
// retrieve the selected menu item
JMenuItem m = (JMenuItem) e.getSource();
// retrieve the graphic that has this pop-up menu
IlvPopupMenuContext context = IlvPopupMenuManager.getPopupMenuContext(m);
if (context == null)
return;
IlvGraphic g = context.getGraphic();
// retrieve the object of the graphic
Object obj = (g == null ? null : diagrammer.getEngine().getObject(g));
if (obj == null)
return;
if (m.getText().equals(getString("StatusNormal")))
diagrammer.setObjectProperty(obj, "status", "Normal");
else if (m.getText().equals(getString("StatusWarning")))
diagrammer.setObjectProperty(obj, "status", "Warning");
else if (m.getText().equals(getString("StatusAlarm")))
diagrammer.setObjectProperty(obj, "status", "Alarm");
else if (m.getText().equals(getString("Properties"))) {
// retrieve the position of the pop-up trigger
IlvPoint p = context.getPoint();
// show the properties
showProperties(diagrammer, obj, (int) p.x, (int) p.y);
}
}
});
return popupMenu;
}
/**
* The actions to be performed before displaying the pop-up menu for nodes or
* links. This configures the pop-up menu to display the actual state.
*/
private void beforeNodeLinkPopupDisplay(IlvSimplePopupMenu popupMenu, IlvPopupMenuContext context,
IlvDiagrammer diagrammer, boolean isNode) {
// deselect all
diagrammer.deselectAll();
// retrieve the graphic
IlvGraphic g = context.getGraphic();
// retrieve the object of the graphic
Object obj = (g == null ? null : diagrammer.getEngine().getObject(g));
// select the object
if (obj != null)
diagrammer.setSelected(obj, true);
// the title label of the menu
String title;
if (isNode) {
title = "";
Object nodeName = diagrammer.getObjectProperty(obj, "name");
title = MessageFormat.format(getString("NodeFormat"), new Object[] {nodeName});
} else {
// fill the label with the name of the link
Object sourceName = diagrammer.getObjectProperty(diagrammer.getSourceNode(obj), "name");
Object targetName = diagrammer.getObjectProperty(diagrammer.getTargetNode(obj), "name");
title = MessageFormat.format(getString("LinkFormat"), new Object[] {sourceName, targetName});
}
// set the title label in the first entry of the menu
JLabel label = (JLabel) popupMenu.getComponent(0);
label.setText(title);
// update the status
if (isNode) {
Object status = diagrammer.getObjectProperty(obj, "status");
if ("Normal".equals(status))
popupMenu.getItemForText(getString("StatusNormal")).setSelected(true);
else if ("Warning".equals(status))
popupMenu.getItemForText(getString("StatusWarning")).setSelected(true);
else if ("Alarm".equals(status))
popupMenu.getItemForText(getString("StatusAlarm")).setSelected(true);
}
}
/**
* This method creates the pop-up menu for the white space.
*/
private JPopupMenu createWhiteSpacePopupMenu(final IlvDiagrammer diagrammer) {
// Create the pop-up menu for the white space. This gets associated to
// the top level manager. No actions associated with this pop-up menu.
// It contains only a text.
IlvSimplePopupMenu popupMenu = new IlvSimplePopupMenu() {
// deselect all objects before the pop-up menu gets displayed
Override
protected void beforeDisplay(IlvPopupMenuContext context) {
// always call super.beforeDisplay first
super.beforeDisplay(context);
// then deselect
diagrammer.deselectAll();
}
};
JLabel label = new JLabel(getString("NoObjectSelected"));
label.setBorder(BorderFactory.createEmptyBorder(2, 10, 2, 5));
popupMenu.add(label);
return popupMenu;
}
private IlvDiagrammerPropertySheet propertySheet;
private JDialog propertySheetDialog;
/**
* Displays a property sheet with all the properties of the selected object.
*/
private void showProperties(final IlvDiagrammer diagrammer, Object object, int x, int y) {
if (propertySheet == null) {
Window window = SwingUtilities.getWindowAncestor(diagrammer);
if (window instanceof Frame)
propertySheetDialog = new JDialog((Frame) window);
else
propertySheetDialog = new JDialog();
propertySheetDialog.setTitle(getString("PropertiesTitle"));
propertySheetDialog.setModal(true);
propertySheet = new IlvDiagrammerPropertySheet();
propertySheetDialog.getContentPane().add(propertySheet);
JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 5, 5));
JButton close = new JButton(getString("Close"));
close.addActionListener(new ActionListener() {
Override
public void actionPerformed(ActionEvent e) {
propertySheetDialog.setVisible(false);
}
});
buttonPanel.add(close);
propertySheetDialog.getContentPane().add(buttonPanel, BorderLayout.AFTER_LAST_LINE);
propertySheetDialog.setSize(300, 300);
}
Point pos = diagrammer.getLocationOnScreen();
propertySheetDialog.setLocation(pos.x + x + 20, pos.y + y + 20);
propertySheetDialog.setVisible(true);
}
// *******************************************
// Creation of the latitude/longitude fields:
// *******************************************
/**
* Creates the latitude/longitude fields, and sets up a listener to update
* them as the suer moves the mouse over the diagram.
*/
private JPanel createLatLongFields(final IlvDiagrammer diagrammer) {
JPanel panel = new JPanel(new FlowLayout(FlowLayout.CENTER, 5, 5));
// Create the latitude field.
//
panel.add(new JLabel(getString("Latitude")));
final JTextField latitudeField = new JTextField();
latitudeField.setColumns(8);
panel.add(latitudeField);
// Create the longitude field.
//
panel.add(new JLabel(getString("Longitude")));
final JTextField longitudeField = new JTextField();
longitudeField.setColumns(8);
panel.add(longitudeField);
// Setup the listener.
//
diagrammer.getView().addMouseMotionListener(new MouseMotionAdapter() {
Override
public void mouseMoved(MouseEvent e) {
if (ax == 0) {
initTransform(diagrammer);
}
IlvPoint p = new IlvPoint(e.getX(), e.getY());
diagrammer.getView().getTransformer().inverse(p);
// p is now in manager coordinates: transform into
// latitude and longitude.
//
double longitude = x0 + ax * p.x;
double latitude = y0 + ay * p.y;
longitudeField.setText(printDegrees(longitude, "W"));
latitudeField.setText(printDegrees(latitude, "N"));
}
});
return panel;
}
// Parameters to transform x/y into latitudes/longitudes:
// longitude = x0 + ax * x;
// latitude = y0 + ay * y;
//
float ax, ay, x0, y0;
/**
* Initializes the latitude/longitude -> x/y transformation parameters.
*/
private void initTransform(final IlvDiagrammer diagrammer) {
// We compute transformation parameters based on the
// positions of the two first nodes.
//
Object node1 = null, node2 = null;
Iterator<?> it = diagrammer.getAllObjects();
while (it.hasNext()) {
Object o = it.next();
if (!diagrammer.isLink(o)) {
if (node1 == null) {
node1 = o;
} else if (node2 == null) {
node2 = o;
break;
}
}
}
float x1 = Float.parseFloat((String) diagrammer.getObjectProperty(node1, "x"));
float y1 = Float.parseFloat((String) diagrammer.getObjectProperty(node1, "y"));
float lon1 = parseDegrees((String) diagrammer.getObjectProperty(node1, "longitude"));
float lat1 = parseDegrees((String) diagrammer.getObjectProperty(node1, "latitude"));
float x2 = Float.parseFloat((String) diagrammer.getObjectProperty(node2, "x"));
float y2 = Float.parseFloat((String) diagrammer.getObjectProperty(node2, "y"));
float lon2 = parseDegrees((String) diagrammer.getObjectProperty(node2, "longitude"));
float lat2 = parseDegrees((String) diagrammer.getObjectProperty(node2, "latitude"));
ax = (lon2 - lon1) / (x2 - x1);
ay = (lat2 - lat1) / (y2 - y1);
x0 = lon1 - ax * x1;
y0 = lat1 - ay * y1;
}
/**
* Parses a string like "45D30'N" into a floating-point number of degrees.
*/
private float parseDegrees(String degreesString) {
int di = degreesString.indexOf('D');
int degrees = Integer.parseInt(degreesString.substring(0, di));
int si = degreesString.indexOf('\'');
int seconds = Integer.parseInt(degreesString.substring(di + 1, si));
return degrees + (float) seconds / 60;
}
/**
* Prints a floating-point number of degrees into a string like "45D30'N".
*/
private String printDegrees(double degrees, String direction) {
return String.valueOf((int) degrees) + "D" + String.valueOf((int) (degrees * 60) % 60) + "'"
+ direction;
}
// *****************
// Utility methods:
// *****************
// Gets a string from the property file.
//
private String getString(String key) {
return bundle.getString("DiagrammerExtension." + key);
}
}