/*
* 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.Container;
import java.awt.event.ActionEvent;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.ResourceBundle;
import ilog.views.IlvRect;
import ilog.views.diagrammer.IlvDiagrammer;
import ilog.views.diagrammer.application.IlvDiagrammerAction;
import ilog.views.diagrammer.application.IlvDiagrammerFrame;
import ilog.views.diagrammer.application.IlvDiagrammerToolBar;
import ilog.views.sdm.IlvSDMModel;
import ilog.views.sdm.modeltools.IlvContentController;
import ilog.views.sdm.modeltools.IlvContentHandler;
import ilog.views.sdm.modeltools.IlvVisibleAreaListener;
import ilog.views.util.IlvProductUtil;
/**
* This example shows how to use content on demand tool.
*
* @since JViews 8.0
* @proofread
*/
public class ContentDemo extends IlvDiagrammerFrame {
////////////////////////////////////////////////////
// The following fields are interesting to modify,
/** Number of nodes */
public int _nodeNumber = 100; // best between 100 and 10 000
/** Offset between nodes, in the grid */
public long _delta = 40;
/** Size of the cache */
public int _cacheSize = _nodeNumber / 2; // 0 is also an interesting value
/**
* Show nodes in cache. This is less realistic, slower, but it shows how the
* cache is working.
*/
public boolean _showCachedNodes = true;
////////////////////////////////////////////////////
private static final String CODstatus = "detailsOnDemand";
private static final String LOCKED = new String("locked");
private static final String LOADED = new String("loaded");
private static final String UNLOADED = new String("unloaded");
private static final String CONTENT = "content";
private IlvContentController _controller;
// entry point
public static void main(final String[] args) {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
Override
public void run() {
new ContentDemo().init(args);
}
});
}
// constructor
public ContentDemo() {
super(new String[] { "-data", "data/grid.idpr", "-simple" });
// This sample uses JViews Diagrammer features. When deploying an
// application that includes this code, you need to be in possession
// of a Perforce JViews Diagrammer Deployment license.
IlvProductUtil.DeploymentLicenseRequired(IlvProductUtil.JViews_Diagrammer_Deployment);
}
// init GUI
Override
public void init(Container contentPane) {
super.init(contentPane);
ResourceBundle rb;
rb = ResourceBundle.getBundle("main");
// add actions
IlvDiagrammerToolBar tb = getViewToolBar();
tb.addAction(new MoveAreaAction(rb));
IlvDiagrammerToolBar toolbar = new IlvDiagrammerToolBar();
toolbar.addAction(new Lock(rb));
toolbar.addAction(new Load(rb));
toolbar.addAction(new Unload(rb));
contentPane.add(toolbar, BorderLayout.NORTH);
}
// GUI is ready, init application
Override
public void ready() {
super.ready();
// redo the diagram
populateDiagram(_nodeNumber);
final IlvDiagrammer diagrammer = getDiagrammers()[0];
// initialize the content controler
_controller = new IlvContentController();
_controller.setCacheSize(_cacheSize);
_controller.setSDMEngine(diagrammer.getEngine());
_controller.setContentHandler(new IlvContentHandler() {
// callback for loading content. Could be done in a separate thread, too.
Override
public void loadContent(IlvContentController source, Object[] objects) {
// prevent too much notifications
diagrammer.setAdjusting(true);
// loop over objects to load
for (int i = 0; i < objects.length; i++) {
loadObject(objects[i], true);
}
diagrammer.setAdjusting(false);
}
// callback for unloading content
Override
public void unloadContent(IlvContentController source, Object[] objects) {
diagrammer.setAdjusting(true);
for (int i = 0; i < objects.length; i++) {
loadObject(objects[i], false);
}
diagrammer.setAdjusting(false);
}
});
// install view listener to lock objects in visible area.
diagrammer.getView().fitTransformerToContent();
IlvVisibleAreaListener val = new IlvVisibleAreaListener(_controller) {
// here we subclass only to check nodes in cache
Override
public int requestAreaToLock(IlvRect area) {
int result = super.requestAreaToLock(area);
// check whether some nodes goes to cache
if (_showCachedNodes) {
updateStates();
}
return result;
}
};
val.installListener(_controller.getSDMEngine().getReferenceView());
}
///////////////////////////////
// make "pop" different nodes, in a grid
private void populateDiagram(int pop) {
IlvDiagrammer d = getDiagrammers()[0];
d.setAdjusting(true);
IlvSDMModel model = d.getEngine().getModel();
model.clear();
long width = (long) Math.sqrt(pop) * _delta;
long x = 0;
long y = 0;
for (int i = 0; i < pop; i++) {
Object node = model.createNode("form");
model.setObjectProperty(node, "name", Integer.valueOf(i));
model.setObjectProperty(node, "x", Long.valueOf(x));
model.setObjectProperty(node, "y", Long.valueOf(y));
x += _delta;
if (x >= width) {
x = 0;
y += _delta;
}
// all nodes are unloaded
model.setObjectProperty(node, CODstatus, UNLOADED);
model.addObject(node, null, null);
}
d.setAdjusting(false);
}
// callback from lock/load/unload actions
private void workOnSelection(int action) {
IlvDiagrammer d = getDiagrammers()[0];
// loop on selected objects
Iterator<?> selected = d.getSelectedObjects();
_controller.processObjects(selected, action);
// check whether some nodes goes to cache
if (_showCachedNodes) {
updateStates();
}
}
/**
* Callback from RectangleInteractor
*
* @param area
* the area to lock
*/
void lockArea(IlvRect area) {
_controller.lockArea(area, IlvContentController.OVERRIDE);
// check whether some nodes goes to cache
if (_showCachedNodes) {
updateStates();
}
}
// the exact status of objects, including in cache. This is slow, because
// we need to check state of all objects.
private void updateStates() {
getDiagrammers()[0].setAdjusting(true);
IlvSDMModel model = getDiagrammers()[0].getEngine().getModel();
// loop over all objects
Enumeration<?> e = getDiagrammers()[0].getEngine().getAllObjects();
while (e.hasMoreElements()) {
Object node = e.nextElement();
String expected = statToString(_controller.getObjectStatus(node));
if (model.getObjectProperty(node, CODstatus) != expected) { // == is ok,
// here
model.setObjectProperty(node, CODstatus, expected);
}
}
getDiagrammers()[0].setAdjusting(false);
}
/**
* Loads or unloads an object
*
* @param node
* the object
* @param load
* the action
*/
private void loadObject(Object node, boolean load) {
IlvSDMModel model = getDiagrammers()[0].getEngine().getModel();
if (load) {
// here we simulate the loading of node contents
// it can be also interesting to put a sleep() command here, or loading a
// huge value.
model.setObjectProperty(node, CONTENT, "content should be more complex than this string");
} else {
// unload values
model.setObjectProperty(node, CONTENT, null);
}
// adjust state. It's use only to have an accurate visual feedback in the
// CSS
model.setObjectProperty(node, CODstatus, statToString(_controller.getObjectStatus(node)));
}
/**
* Converts content status to a string that is simpler to match in the CSS.
*
* @param objectStatus
* the loaded state
* @return a string
*/
private String statToString(int objectStatus) {
switch (objectStatus) {
case IlvContentController.LOCK:
return LOCKED;
case IlvContentController.LOAD:
return LOADED;
case IlvContentController.UNLOAD:
return UNLOADED;
}
return null;
}
/////////////////////////////////
// inner classes
/**
* The action that locks selected objects.
*/
private class Lock extends IlvDiagrammerAction {
public Lock(ResourceBundle rb) {
super("Lock", rb);
}
Override
public void perform(ActionEvent e, IlvDiagrammer source) {
workOnSelection(IlvContentController.LOCK);
}
Override
protected boolean isEnabled(IlvDiagrammer diagrammer) throws Exception {
return true;
}
}
/**
* The action that load in cache selected objects.
*/
private class Load extends IlvDiagrammerAction {
public Load(ResourceBundle rb) {
super("Load", rb);
}
Override
public void perform(ActionEvent e, IlvDiagrammer source) {
workOnSelection(IlvContentController.LOAD);
}
Override
protected boolean isEnabled(IlvDiagrammer diagrammer) throws Exception {
return true;
}
}
/**
* The action that unloads selected objects.
*/
private class Unload extends IlvDiagrammerAction {
public Unload(ResourceBundle rb) {
super("Unload", rb);
}
Override
protected boolean isEnabled(IlvDiagrammer diagrammer) throws Exception {
return true;
}
Override
public void perform(ActionEvent e, IlvDiagrammer source) {
workOnSelection(IlvContentController.UNLOAD);
}
}
/**
* An action that controls the content on demand through a visible area.
*/
private class MoveAreaAction extends IlvDiagrammerAction.ToggleAction {
/**
* @param bundle
*/
protected MoveAreaAction(ResourceBundle bundle) {
super("MoveArea", bundle);
}
/*
* (non-Javadoc)
*
* @see ilog.views.diagrammer.application.IlvDiagrammerAction.ToggleAction#
* isSelected(ilog.views.diagrammer.IlvDiagrammer)
*/
Override
protected boolean isSelected(IlvDiagrammer diagrammer) throws Exception {
return diagrammer != null && diagrammer.getView().getInteractor() instanceof RectangleInteractor;
}
/*
* (non-Javadoc)
*
* @see ilog.views.diagrammer.application.IlvDiagrammerAction.ToggleAction#
* setSelected(ilog.views.diagrammer.IlvDiagrammer, boolean)
*/
Override
protected void setSelected(IlvDiagrammer diagrammer, boolean selected) throws Exception {
if (selected) {
diagrammer.getView().pushInteractor(new RectangleInteractor(ContentDemo.this));
} else {
diagrammer.getView().popInteractor();
}
}
/*
* (non-Javadoc)
*
* @see
* ilog.views.diagrammer.application.IlvDiagrammerAction#isEnabled(ilog.
* views.diagrammer.IlvDiagrammer)
*/
Override
protected boolean isEnabled(IlvDiagrammer diagrammer) throws Exception {
return diagrammer != null;
}
}
}