/*
* 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.
*/
package simulation;
import java.awt.AWTEvent;
import java.awt.Container;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.io.IOException;
import java.util.Enumeration;
import java.util.Vector;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JToggleButton;
import javax.swing.JToolBar;
import javax.swing.Timer;
import ilog.views.IlvManagerView;
import ilog.views.IlvManagerViewInteractor;
import ilog.views.IlvPoint;
import ilog.views.IlvTransformer;
import ilog.views.event.InteractorChangedEvent;
import ilog.views.event.InteractorListener;
import ilog.views.interactor.IlvPermanentInteractorInterface;
import ilog.views.maps.IlvCoordinate;
import ilog.views.maps.IlvCoordinateSystemProperty;
import ilog.views.maps.defense.symbology.app6a.IlvApp6aSymbol;
import ilog.views.maps.srs.coordsys.IlvCoordinateSystem;
import ilog.views.maps.srs.coordsys.IlvGeographicCoordinateSystem;
import ilog.views.maps.srs.coordtrans.IlvCoordinateTransformation;
import ilog.views.maps.srs.coordtrans.IlvCoordinateTransformationException;
import ilog.views.sdm.IlvSDMEngine;
import ilog.views.sdm.event.SDMModelEvent;
import ilog.views.sdm.event.SDMModelListener;
import ilog.views.sdm.renderer.IlvStyleSheetRenderer;
import ilog.views.util.IlvImageUtil;
/**
* Illustrates how to log events on the symbology and to replay scenarios.
*/
public class SimulationController extends JToolBar {
final static String NEUTRAL = "Neutral".intern(); //$NON-NLS-1$
final static String FOLLOW = "Follow".intern(); //$NON-NLS-1$
private final IlvSDMEngine symbology;
// final JCheckBox pause = new JCheckBox("Stop Creating Targets");
// //$NON-NLS-1$
// final JCheckBox simulation = new JCheckBox("Run simulation"); //$NON-NLS-1$
final JButton playPauseButton = new JButton();
final JButton stopButton = new JButton();
final JToggleButton followSymbolButton = new JToggleButton();
private boolean isRunning = false;
private boolean needInit = true;
final JComboBox<Integer> mobileCount = new JComboBox<Integer>(new Integer[] { new Integer(10), new Integer(50),
new Integer(100), new Integer(300), new Integer(1000), new Integer(1500) });
final JComboBox<String> speedCombo = new JComboBox<String>(
new String[] { "x10", "x25", "x50", "x75", "x100", "x250" }); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$
final JComboBox<Integer> fpsCombo = new JComboBox<Integer>(
new Integer[] { new Integer(5), new Integer(10), new Integer(25), new Integer(50) });
SimulationContext simulationContext;
Icon playIcon;
Icon pauseIcon;
Icon stopIcon;
Icon followSymbolIcon;
FollowSymbolInteractor followInteractor = new FollowSymbolInteractor();
/**
* Create the replay interface.
*
* @param symbology
*/
public SimulationController(IlvSDMEngine symbology) {
createUserInterface();
this.symbology = symbology;
playPauseButton.addActionListener(new SimulationBoxListener());
SimulationBoxListener listener = new SimulationBoxListener();
stopButton.addActionListener(listener);
followSymbolButton.addActionListener(listener);
// JV-2856
InteractorListener interactorListener = new InteractorListener() {
Override
public void interactorChanged(InteractorChangedEvent event) {
boolean isMyInteractor = (event.getNewValue() == followInteractor);
if (followSymbolButton.isSelected() != isMyInteractor) {
followSymbolButton.setSelected(isMyInteractor);
}
}
};
symbology.getReferenceView().addInteractorListener(interactorListener);
}
private void createUserInterface() {
speedCombo.setSelectedIndex(0);
speedCombo.setToolTipText("Choose simulation speed factor"); //$NON-NLS-1$ (should
// be
// internationalized)
SimulationContext.setTimeAcceleration(10);
speedCombo.addActionListener(new ActionListener() {
Override
public void actionPerformed(ActionEvent e) {
int accel = Integer.parseInt(((String) speedCombo.getSelectedItem()).substring(1));
SimulationContext.setTimeAcceleration(accel);
}
});
fpsCombo.setSelectedIndex(0);
fpsCombo.setToolTipText("Choose target refresh rate for the display"); //$NON-NLS-1$ (should
// be
// internationalized)
SimulationContext.setTargetFPS(((Integer) fpsCombo.getSelectedItem()).intValue());
fpsCombo.addActionListener(new ActionListener() {
Override
public void actionPerformed(ActionEvent e) {
SimulationContext.setTargetFPS(((Integer) fpsCombo.getSelectedItem()).intValue());
}
});
Dimension buttonDim = new Dimension(26, 26);
Dimension comboDim = new Dimension(55, 22);
configureComponentSize(playPauseButton, buttonDim);
playPauseButton.setSelected(false);
add(playPauseButton);
configureComponentSize(stopButton, buttonDim);
add(stopButton);
configureComponentSize(followSymbolButton, buttonDim);
add(followSymbolButton);
// setLayout(new FlowLayout(FlowLayout.LEFT,2,0));
addSeparator();
add(new JLabel("Mobiles ")); //$NON-NLS-1$ (should be internationalized)
// addSeparator();
mobileCount.setToolTipText("Choose number of mobiles"); //$NON-NLS-1$ (should
// be
// internationalized)
configureComponentSize(mobileCount, comboDim);
add(mobileCount);
addSeparator();
add(new JLabel("Speed ")); //$NON-NLS-1$ (should be internationalized)
// addSeparator();
configureComponentSize(speedCombo, comboDim);
add(speedCombo);
addSeparator();
add(new JLabel("Fps ")); //$NON-NLS-1$ (should be internationalized)
// addSeparator();
configureComponentSize(fpsCombo, comboDim);
add(fpsCombo);
mobileCount.setEnabled(true);
// install icons
playIcon = createIcon("right.gif"); //$NON-NLS-1$
pauseIcon = createIcon("pause.gif"); //$NON-NLS-1$
stopIcon = createIcon("stop.gif"); //$NON-NLS-1$
// stopTargetCreationIcon = createIcon("stopTargetCreation.gif");
// //$NON-NLS-1$
// targetCreationIcon = createIcon("targetCreation.gif"); //$NON-NLS-1$
followSymbolIcon = createIcon("target.gif"); //$NON-NLS-1$
playPauseButton.setIcon(playIcon);
playPauseButton.setToolTipText("Run simulation"); //$NON-NLS-1$ (should be
// internationalized)
stopButton.setIcon(stopIcon);
stopButton.setToolTipText("Stop simulation"); //$NON-NLS-1$ (should be
// internationalized)
followSymbolButton.setIcon(followSymbolIcon);
followSymbolButton.setToolTipText("Choose a symbol to follow"); //$NON-NLS-1$ (should
// be
// internationalized)
}
private void configureComponentSize(JComponent comp, Dimension buttonDim) {
comp.setPreferredSize(buttonDim);
comp.setMinimumSize(buttonDim);
comp.setMaximumSize(buttonDim);
}
private Icon createIcon(String iconURL) {
Image image = null;
try {
image = IlvImageUtil.getImageFromFile(SimulationController.class, iconURL);
} catch (IOException e1) {
e1.printStackTrace();
}
if (image != null) {
return new ImageIcon(image);
}
return null;
}
IlvApp6aSymbol dca;
private final class SimulationBoxListener implements ActionListener {
/**
* Called when the button "Run simulation" is pressed.
*
* @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent)
*/
Override
public void actionPerformed(ActionEvent e) {
if (e.getSource() == playPauseButton) {
isRunning = !isRunning;
if (isRunning) {
if (needInit) {
Container c = playPauseButton.getTopLevelAncestor();
Cursor oc = null;
if (c.isCursorSet()) {
oc = c.getCursor();
}
c.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
buildSimulation();
// set triple buffering
IlvStyleSheetRenderer renderer = IlvStyleSheetRenderer.getInstance(symbology);
symbology.getReferenceView().setTripleBufferedLayerCount(renderer.getNodesLayer());
targetProvider.start();
mobileCount.setEnabled(false);
needInit = false;
c.setCursor(oc);
} else {
// resume simulation
if (targetProvider != null)
// targetProvider.start();
Mobile.resume();
}
playPauseButton.setToolTipText("Pause simulation"); //$NON-NLS-1$ (should
// be
// internationalized)
playPauseButton.setIcon(pauseIcon);
} else {
playPauseButton.setToolTipText("Run simulation"); //$NON-NLS-1$ (should
// be
// internationalized)
playPauseButton.setIcon(playIcon);
// pause simulation
isRunning = false;
Mobile.pause();
}
} else if (e.getSource() == stopButton) {
Mobile.resume();
isRunning = false;
stopSimu();
// stop triple buffering
symbology.getReferenceView().setTripleBufferedLayerCount(0);
mobileCount.setEnabled(true);
playPauseButton.setToolTipText("Run simulation"); //$NON-NLS-1$ (should
// be
// internationalized)
playPauseButton.setIcon(playIcon);
playPauseButton.setEnabled(true);
Enumeration<?> roots = symbology.getModel().getObjects();
Vector<Object> v = new Vector<Object>();
while (roots.hasMoreElements()) {
v.add(roots.nextElement());
}
for (int i = 0; i < v.size(); i++) {
symbology.getModel().removeObject(v.get(i));
}
Mobile.allMobiles.clear();
Mobile.currentMobileTask = null;
needInit = true;
} else if (e.getSource() == followSymbolButton) {
IlvManagerView view = symbology.getReferenceView();
if (view != null) {
view.requestFocus();
if (view.getInteractor() == followInteractor) {
view.popInteractor();
} else {
view.pushInteractor(followInteractor);
}
}
}
}
void stopSimu() {
if (targetProvider != null)
// targetProvider.stop();
Mobile.stop();
}
void buildSimulation() {
SimulationContext.setSeed(124);
dca = new IlvApp6aSymbol("SFGPUCFHS--CUS*", 0, 0);//$NON-NLS-1$
double lon = (SimulationContext.getLonMin() + SimulationContext.getLonMax()) / 2;
double lat = (SimulationContext.getLatMin() + SimulationContext.getLatMax()) / 2;
dca.setLocation(symbology, lon, lat);
symbology.getModel().addObject(dca, null, null);
int neutralMobilesCount = ((Integer) (mobileCount.getSelectedItem())).intValue();
// neutral mobiles.
for (int i = 0; i < neutralMobilesCount; i++) {
/* Target t= */new Target(NEUTRAL, symbology);
}
targetProvider.setInitialDelay(100);
double accel = SimulationContext.getTimeAcceleration();
targetProvider.setDelay((int) (50000 / accel));
// targetProvider.start();
Mobile.start();
}
}
Timer targetProvider = new Timer(20000, new ActionListener() {
Override
public void actionPerformed(ActionEvent e) {
if (!Mobile.paused && isRunning == true) {
Target t = new Target(symbology);
t.symbol.setProperty(IlvApp6aSymbol.ID_CODE, "SHAPMHA---FA--A"); //$NON-NLS-1$
new Missile(dca.getLongitude(), dca.getLatitude(), symbology, t);
double accel = SimulationContext.getTimeAcceleration();
int newDelay = (int) (50000 / accel);
if (targetProvider.getDelay() != newDelay) {
targetProvider.setDelay((int) (50000 / accel));
}
}
}
});
final static java.text.DecimalFormat NS = new java.text.DecimalFormat("0 mph"); //$NON-NLS-1$
final static java.text.DecimalFormat FS = new java.text.DecimalFormat("0 ft"); //$NON-NLS-1$
/**
* @author eaullas
*/
private class FollowSymbolInteractor extends IlvManagerViewInteractor implements IlvPermanentInteractorInterface {
/** To save cursor. */
Cursor oldCursor = null;
/** The cursor for this interactor. */
Cursor myCursor = null;
/**
* Creates a new <code>FollowSymbolInteractor</code>.
*/
public FollowSymbolInteractor() {
super();
enableEvents(AWTEvent.MOUSE_EVENT_MASK);
myCursor = new Cursor(Cursor.CROSSHAIR_CURSOR);
}
Override
public boolean isPermanent() {
return false;
}
Override
public void setPermanent(boolean permanent) {
// ignore this.permanent = permanent;
}
/**
* This method is called when the interactor is attached to the specified
* manager view.
*
* @param v
* view to attach to.
*/
Override
protected void attach(IlvManagerView v) {
super.attach(v);
if (!getCursor().equals(v.getCursor())) {
oldCursor = v.getCursor();
v.setCursor(getCursor());
}
}
/**
* This method is called when the interactor is detached from the specified
* manager view.
*/
Override
protected void detach() {
if (oldCursor != null) {
getManagerView().setCursor(oldCursor);
oldCursor = null;
}
if (modelListener != null) {
symbology.getModel().removeSDMModelListener(modelListener);
modelListener = null;
}
modelListener = null;
follow(null);
super.detach();
}
/**
* @return Returns the cursor used for edition.
*/
public Cursor getCursor() {
if (myCursor == null) {
if (getManagerView() != null)
return getManagerView().getCursor();
return Cursor.getDefaultCursor();
}
return myCursor;
}
Override
protected void processMouseEvent(MouseEvent e) {
switch (e.getID()) {
case MouseEvent.MOUSE_RELEASED:
Object dataObject = symbology.getObject(new IlvPoint(e.getX(), e.getY()), getManagerView());
// if(e.getClickCount()>1){
// if(dataObject != null){
// symbPanel.editSelectedSymbol();
// }
// }
if (dataObject instanceof IlvApp6aSymbol) {
follow((IlvApp6aSymbol) dataObject);
} else {
follow(null);
}
break;
}
super.processMouseEvent(e);
}
IlvApp6aSymbol currentSymbol;
SDMModelListener modelListener;
void follow(IlvApp6aSymbol symbol) {
if (currentSymbol != null) {
symbology.getModel().setObjectProperty(currentSymbol, FOLLOW, "0"); //$NON-NLS-1$
}
currentSymbol = symbol;
if (currentSymbol != null) {
symbology.getModel().setObjectProperty(currentSymbol, FOLLOW, "1");//$NON-NLS-1$
}
updateForCurrentSymbol();
if (modelListener == null) {
modelListener = new SDMModelListener() {
Override
public void adjustmentFinished(SDMModelEvent event) {
if (currentSymbol != null) {
updateForCurrentSymbol();
}
}
Override
public void dataChanged(SDMModelEvent event) {
if (event.getObject() == currentSymbol) {
updateForCurrentSymbol();
}
}
Override
public void linkDestinationChanged(SDMModelEvent event) {/* ignore */
}
Override
public void linkSourceChanged(SDMModelEvent event) {/* ignore */
}
Override
public void objectAdded(SDMModelEvent event) {/* ignore */
}
Override
public void objectRemoved(SDMModelEvent event) {
if (event.getObject() == currentSymbol) {
currentSymbol = null;
follow(null);
}
}
};
symbology.getModel().addSDMModelListener(modelListener);
}
}
void updateForCurrentSymbol() {
Object dir = null;
if (currentSymbol != null) {
dir = currentSymbol.getProperty(IlvApp6aSymbol.MODIFIER_DIRECTION_OF_MOVEMENT_INDICATOR);
}
double direction = -90;
if (dir != null) {
direction = Double.parseDouble(dir.toString());
}
IlvManagerView view = getManagerView();
IlvCoordinateSystem system = IlvCoordinateSystemProperty.GetCoordinateSystem(view.getManager());
IlvCoordinateTransformation tr = IlvCoordinateTransformation
.CreateTransformation(IlvGeographicCoordinateSystem.KERNEL, system);
IlvTransformer t = view.getTransformer();
if (currentSymbol != null) {
IlvCoordinate c1 = new IlvCoordinate(currentSymbol.getLongitude(), -currentSymbol.getLatitude());
if (tr != null) {
try {
tr.transform(c1, c1);
} catch (IlvCoordinateTransformationException e) {
e.printStackTrace();
}
}
IlvPoint c = new IlvPoint((float) c1.x, (float) c1.y);
t.apply(c);
t.translate(view.getWidth() / 2 - c.x, view.getHeight() / 2 - c.y);
}
double angle = Math.toDegrees(Math.atan2(t.getx21(), t.getx11()));
double dangle = -90 - direction - angle;
t.rotate(view.getWidth() / 2, view.getHeight() / 2, dangle);
// make sure that an almost 0 rotation is exactly 0 (performance is
// better)
if (Math.abs(t.getx12()) < 1E-4 && Math.abs(t.getx21()) < 1E-4) {// RAZ
// Rotation
// when
// it is
// very
// small.
t.setValues(t.getx11(), 0, 0, t.getx22());
}
view.setTransformer(t);
view.invalidateView();
view.repaint();
}
}
}