/*
* 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.FlowLayout;
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.util.ArrayList;
import java.util.List;
import java.util.Random;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JRootPane;
import javax.swing.SwingUtilities;
import ilog.views.IlvApplyObject;
import ilog.views.IlvGraphic;
import ilog.views.IlvHandlesSelection;
import ilog.views.IlvManager;
import ilog.views.IlvManagerLayer;
import ilog.views.IlvManagerView;
import ilog.views.IlvPoint;
import ilog.views.IlvRect;
import ilog.views.IlvTransformer;
import ilog.views.graphic.IlvZoomableLabel;
import ilog.views.interactor.IlvSelectInteractor;
import ilog.views.interactor.IlvZoomViewInteractor;
import ilog.views.swing.IlvJManagerViewControlBar;
import ilog.views.swing.IlvJScrollManagerView;
import ilog.views.swing.IlvPopupMenuContext;
import ilog.views.swing.IlvPopupMenuManager;
import ilog.views.swing.IlvSimplePopupMenu;
/**
* This is a very simple application that shows how to use
* Z-ordering with or without the quadtree.
*/
SuppressWarnings("serial")
public class ZOrderingApp extends JRootPane {
IlvManager manager;
IlvManagerView mgrview;
{
// 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);
}
/**
* Initializes the application.
*/
public void init() {
// create a manager
manager = new IlvManager();
// create a manager view
mgrview = new IlvManagerView(manager);
mgrview.setSelectedWhenPopupPreferred(true);
// 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.02, 10.0);
// Settings parameters for selection handles
IlvHandlesSelection.defaultHandleColor = Color.black;
IlvHandlesSelection.defaultHandleBackgroundColor = Color.white;
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());
// -----------------------------------------------------------------------
// Now, fill the manager and set up the pop-up menus
// register view view to the pop-up manager
IlvPopupMenuManager.registerView(mgrview);
// register the menus under different names
IlvPopupMenuManager.registerMenu("MENU1", createMenu());
// fill the manager with graphic objects that use menu1
Random rand = new Random(0);
for (int i = 0; i < 5; i++) {
for (int j = 0; j < 28; j++) {
// double x = rand.nextDouble() * 400;
// double y = rand.nextDouble() * 400;
double x = 5 + i * 100 + (j % 2) * 45;
double y = 5 + j * 15;
IlvZoomableLabel graphic = new IlvZoomableLabel(new IlvPoint(x, y), "Z-Order: " + i, false);
graphic.setAntialiasing(true);
graphic.setLeftMargin(6);
graphic.setRightMargin(6);
graphic.setTopMargin(4);
graphic.setBottomMargin(4);
graphic.setBorderOn(true);
graphic.setBackgroundOn(true);
int r = (int) (80 + rand.nextFloat() * (255 - 80));
int g = (int) (80 + rand.nextFloat() * (255 - 80));
int b = (int) (80 + rand.nextFloat() * (255 - 80));
r = Math.max(0, Math.min(r, 255));
g = Math.max(0, Math.min(g, 255));
b = Math.max(0, Math.min(b, 255));
graphic.setBackgroundPaint(new Color(r, g, b));
// set the pop-up menu or the graphic
graphic.setPopupMenuName("MENU1");
// add the graphic to the manager
manager.addObject(graphic, 0, true);
}
}
// enable Z-Ordering
final IlvManagerLayer layer = manager.getManagerLayer(0);
layer.setZOrdering(true);
// create a checkbox that allows to disable the Z-ordering in the layer
JCheckBox useZOrder = new JCheckBox("Z-Order", true);
useZOrder.setToolTipText("Enable or disable the Z-ordering");
useZOrder.addItemListener(new ItemListener() {
Override
public void itemStateChanged(ItemEvent e) {
if (e.getStateChange() == ItemEvent.SELECTED)
layer.setZOrdering(true);
else if (e.getStateChange() == ItemEvent.DESELECTED)
layer.setZOrdering(false);
manager.reDraw();
}
});
// create a checkbox that allows to disable the quadtree in the layer
JCheckBox useQuadTree = new JCheckBox("Quadtree", true);
useQuadTree.setToolTipText("Enable or disable the quad tree");
useQuadTree.addItemListener(new ItemListener() {
Override
public void itemStateChanged(ItemEvent e) {
if (e.getStateChange() == ItemEvent.SELECTED)
layer.setQuadtreeEnabled(true);
else if (e.getStateChange() == ItemEvent.DESELECTED)
layer.setQuadtreeEnabled(false);
manager.reDraw();
}
});
/**
* To enable benchmarking
*
JButton bench = new JButton("Bench");
bench.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
System.out.println("Quadtree " + layer.isQuadtreeEnabled());
System.out.println("Z-Ordering " + layer.isZOrdering());
long s = System.currentTimeMillis();
for (int i = 0; i < 1000; i++)
manager.getObject(new IlvPoint(i,i), mgrview);
long t = System.currentTimeMillis();
System.out.println("Time for 1000 hittest: " + (t-s) + " ms");
s = System.currentTimeMillis();
IlvApplyObject f = new IlvApplyObject() {
public void apply(IlvGraphic g, Object arg) {}
};
for (int i = 0; i < 1000; i++)
manager.mapIntersects(f, null, new IlvRect(i,i,100,100), new IlvTransformer());
t = System.currentTimeMillis();
System.out.println("Time for 1000 empty mapIntersects: " + (t-s) + " ms");
int n = layer.getCardinal();
s = System.currentTimeMillis();
for (int i = 0; i < 1000; i++)
layer.setIndex(layer.getObject(n-1), i);
t = System.currentTimeMillis();
System.out.println("Time for 1000 setIndex: " + (t-s) + " ms");
s = System.currentTimeMillis();
for (int i = 0; i < 1000; i++)
layer.getIndex(layer.getObject(n-1));
t = System.currentTimeMillis();
System.out.println("Time for 1000 getIndex: " + (t-s) + " ms");
}
});
*/
// create the top panel with the toolbar and the pop-up checkbox
JPanel topPanel = new JPanel();
topPanel.setLayout(new FlowLayout(FlowLayout.LEFT));
topPanel.add(controlBar);
topPanel.add(useZOrder);
topPanel.add(useQuadTree);
// topPanel.add(bench);
// 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);
updateLabelTexts();
}
/**
* Update the text in the label to display the current Z-order.
*/
private void updateLabelTexts() {
manager.applyToObjects(manager.getObjects(), new IlvApplyObject() {
Override
public void apply(IlvGraphic g, Object arg) {
if (g instanceof IlvZoomableLabel) {
IlvManagerLayer layer = manager.getManagerLayer(g);
int zOrder = layer.getIndex(g);
String s;
if (zOrder < 10)
s = "00" + zOrder;
else if (zOrder < 100)
s = "0" + zOrder;
else
s = "" + zOrder;
((IlvZoomableLabel) g).setLabel("Z-Order: " + s);
}
}
}, null, true);
}
/**
* Creates a very simple pop-up menu.
* In principle, you can use any JPopupMenu at the graphic object.
* However, the IlvSimplePopupMenu is very conveniant to configure, hence
* we use it in this sample.
*/
private JPopupMenu createMenu() {
// create the action listener for the pop-up menu
ActionListener actionListener = 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);
IlvGraphic graphic = context.getGraphic();
// do the action
if (IlvSimplePopupMenu.getMenuItemText(m).equals("To front"))
moveToFront(graphic);
else if (IlvSimplePopupMenu.getMenuItemText(m).equals("Forward"))
moveForward(graphic);
else if (IlvSimplePopupMenu.getMenuItemText(m).equals("Backward"))
moveBackward(graphic);
else if (IlvSimplePopupMenu.getMenuItemText(m).equals("To back"))
moveToBack(graphic);
// select the object (just to have a visual feedback which object has
// changed)
manager.deSelectAll(true);
manager.setSelected(graphic, true, true);
}
};
// create a simple pop-up menu
IlvSimplePopupMenu menu = new IlvSimplePopupMenu("Menu1",
"To front | Forward | Backward | To back", null, actionListener);
return menu;
}
/**
* Move a graphic to the top of the Z-order.
*/
private void moveToFront(IlvGraphic g) {
IlvManager manager = (IlvManager) g.getGraphicBag();
IlvManagerLayer layer = manager.getManagerLayer(g);
layer.setIndex(g, layer.getCardinal() - 1);
// this also redraws
updateLabelTexts();
}
/**
* Move a graphic to the bottom of the Z-order.
*/
private void moveToBack(IlvGraphic g) {
IlvManager manager = (IlvManager) g.getGraphicBag();
IlvManagerLayer layer = manager.getManagerLayer(g);
layer.setIndex(g, 0);
// this also redraws
updateLabelTexts();
}
/**
* Move a graphic one step forward in the Z-order
* Well, not quite: if we have 1000 objects, then we would need up to
* 1000 times move forward operations to move the object visible forward.
* But visibly, only something happens at the Z-order of the overlapping
* objects, so we shorten this by moving forward with respect to the
* current overlapping. That is, we move it to the Z-order so that it
* appears on top of the lowest overlapping object that is currently on top
* of the input object
*/
private void moveForward(IlvGraphic g) {
IlvManager manager = (IlvManager) g.getGraphicBag();
IlvManagerLayer layer = manager.getManagerLayer(g);
IlvTransformer t = mgrview.getTransformer();
IlvRect trect = g.boundingBox(t);
IlvRect rect = new IlvRect(trect);
t.boundingBox(rect, true);
IntersectionCollector f = new IntersectionCollector();
layer.mapIntersects(rect, trect, f, null, t);
int zOrder = layer.getIndex(g);
int bestZOrder;
if (f.result.size() <= 1)
// just move one up. Nothing overlaps, so there will not be any
// immediate visual effect
bestZOrder = zOrder + 1;
else {
// search in the result the closest object with higher Z-Order.
// Move to that Z-Order, because this has an immediate visual effect.
bestZOrder = layer.getCardinal();
for (int i = 0; i < f.result.size(); i++) {
IlvGraphic obj = f.result.get(i);
int otherZOrder = layer.getIndex(obj);
if (zOrder < otherZOrder && otherZOrder < bestZOrder)
bestZOrder = otherZOrder;
}
}
layer.setIndex(g, bestZOrder);
// this also redraws
updateLabelTexts();
}
/**
* Move a graphic one step backward in the Z-order
* Well, not quite: if we have 1000 objects, then we would need up to
* 1000 times move backward operations to move the object visible backward.
* But visibly, only something happens at the Z-order of the overlapping
* objects, so we shorten this by moving backward with respect to the
* current overlapping. That is, we move it to the Z-order so that it
* appears below of the highest overlapping object that is currently below
* of the input object
*/
private void moveBackward(IlvGraphic g) {
IlvManager manager = (IlvManager) g.getGraphicBag();
IlvManagerLayer layer = manager.getManagerLayer(g);
IlvTransformer t = mgrview.getTransformer();
IlvRect trect = g.boundingBox(t);
IlvRect rect = new IlvRect(trect);
t.boundingBox(rect, true);
IntersectionCollector f = new IntersectionCollector();
layer.mapIntersects(rect, trect, f, null, t);
int zOrder = layer.getIndex(g);
int bestZOrder;
if (f.result.size() <= 1)
// just move one down. Nothing overlaps, so there will not be any
// immediate visual effect
bestZOrder = zOrder - 1;
else {
// search in the result the closest object with lower Z-Order.
// Move to that Z-Order, because this has an immediate visual effect.
bestZOrder = -1;
for (int i = 0; i < f.result.size(); i++) {
IlvGraphic obj = f.result.get(i);
int otherZOrder = layer.getIndex(obj);
if (bestZOrder < otherZOrder && otherZOrder < zOrder)
bestZOrder = otherZOrder;
}
}
layer.setIndex(g, bestZOrder);
// this also redraws
updateLabelTexts();
}
/**
* A collector apply opject.
*/
class IntersectionCollector implements IlvApplyObject {
List<IlvGraphic> result = new ArrayList<IlvGraphic>();
Override
public void apply(IlvGraphic g, Object arg) {
result.add(g);
}
}
/**
* 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() {
ZOrderingApp app = new ZOrderingApp();
app.init();
JFrame frame = new JFrame("Z-Order Example");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(500, 500);
frame.getContentPane().add(app);
frame.setVisible(true);
}
});
}
}