/*
* 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 demo.triplebuffering;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.KeyEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.net.URL;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JRootPane;
import javax.swing.JToolBar;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
import javax.swing.border.BevelBorder;
import javax.swing.border.LineBorder;
import ilog.views.IlvApplyObject;
import ilog.views.IlvGraphic;
import ilog.views.IlvManager;
import ilog.views.IlvManagerView;
import ilog.views.IlvPoint;
import ilog.views.IlvRect;
import ilog.views.IlvTransformer;
import ilog.views.swing.IlvJManagerViewControlBar;
/**
* The main class <code>TripleBuffering</code>.
*/
SuppressWarnings("serial")
public class TripleBuffering extends JRootPane {
/**
* Data structure for airline companies.
*/
private static final AirLine[] companies = { new AirLine("AA", "images/airline1.gif"),
new AirLine("AL", "images/airline2.gif"), new AirLine("AM", "images/airline3.gif"),
new AirLine("CP", "images/airline4.gif"), new AirLine("CS", "images/airline5.gif"),
new AirLine("DE", "images/airline6.gif"), new AirLine("FI", "images/airline7.gif"),
new AirLine("IB", "images/airline8.gif"), new AirLine("IT", "images/airline9.gif"),
new AirLine("KL", "images/airline10.gif"), new AirLine("KO", "images/airline1.gif"),
new AirLine("QA", "images/airline2.gif"), new AirLine("SA", "images/airline3.gif"),
new AirLine("SB", "images/airline4.gif"), new AirLine("UN", "images/airline5.gif") };
/**
* Data structure that records the <code>Image</code> objects for the logos of
* the companies.
*/
private static final Image[] companiesLogos = new Image[companies.length];
/**
* Number of animated tracks.
*/
private int maxTracks = 50;
/**
* Array of animated tracks.
*/
private Track[] tracks;
/**
* Bounding box of the background map.
*/
private static IlvRect mapBox;
/**
* Delta for track movements.
*/
private static double delta;
/**
* The manager.
*/
private IlvManager manager;
/**
* The view of the manager.
*/
private IlvManagerView mgrview;
/**
* Timer for animation.
*/
private Timer timer;
/**
* Font of the track symbols.
*/
private Font font = new Font("Helvetica", Font.PLAIN, 10);
/**
* The check boxes.
*/
private JCheckBox showLabelsButton, showLogosButton, lastPositionButton;
private JCheckBox layerCache, tripleBuffer;
/**
* The combo box.
*/
private JComboBox<String> combo;
/**
* To indicate the performance:
*/
private JLabel fpsLabel;
/**
* The layer that contains the tracks.
*/
private int trackLayer;
/**
* The history of fps. We show an average fps to avoid that the ftp flickers
* too much.
*/
private long[] fpsHistory = new long[50];
private int fpsHIndex = 0;
private boolean fpsHistoryFull = false;
/**
* Initializes the sample.
*/
public void init() {
// 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);
// Creates the manager
manager = new IlvManager();
// Creates the view for the manager
mgrview = new IlvManagerView(manager) {
Override
public void paint(Graphics g) {
long time = System.nanoTime();
super.paint(g);
time = System.nanoTime() - time;
if (time == 0)
time = 1;
long fps = 1000000000 / time;
fpsHistory[fpsHIndex++] = fps;
if (fpsHIndex >= fpsHistory.length) {
fpsHistoryFull = true;
fpsHIndex = 0;
}
int max = (fpsHistoryFull ? fpsHistory.length : fpsHIndex);
long sum = 0;
for (int i = 0; i < max; i++) {
sum += fpsHistory[i];
}
fpsLabel.setText("Refresh " + (sum / max) + " fps");
}
};
// Sets the keep aspect ratio on
mgrview.setKeepingAspectRatio(true);
// Sets the background of the view.
// Either a simple color...
// mgrview.setBackground(new Color(88, 210, 221));
// ...or a nice gradient obtained via a background pattern:
try {
URL url = getClass().getResource("images/BackgroundPattern.gif");
mgrview.setBackgroundPatternLocation(url);
} catch (Throwable th) {
System.err.println("Couldn't get file: images/BackgroundPattern.gif");
}
// Reads the background map.
try {
manager.setFileName(getClass().getResource("world.ivl"));
} catch (Exception th) {
System.err.println("Couldn't get file: world.ivl");
}
// Sets the tripple buffering on for the layers of the map.
mgrview.setTripleBufferedLayerCount(manager.getLayersCount());
mapBox = manager.computeBBox(null);
delta = mapBox.width / 200;
getContentPane().setLayout(new BorderLayout(0, 0));
// Tracks will be added in a new layer at the top.
trackLayer = manager.getLayersCount();
// Creates the tracks.
tracks = new Track[maxTracks];
for (int i = 0; i < maxTracks; i++) {
Track track = newRandomTrack(Color.black, Color.blue, Color.yellow);
manager.addObject(track, trackLayer, false);
tracks[i] = track;
}
// Reads the foreground clouds.
try {
manager.read(getClass().getResource("clouds.ivl"));
} catch (Exception th) {
System.err.println("Couldn't get file: clouds.ivl");
}
IlvGraphic template = manager.getObject("cloud");
manager.removeObject(template, false);
for (int i = 0; i < 100; i++) {
manager.addObject(newRandomCloud(template), trackLayer + 1, false);
}
manager.removeObject(manager.getObject("background"), false);
manager.getManagerLayer(trackLayer + 1).setAlpha(0.75F);
mgrview.setLayerCached(trackLayer + 1, true);
getContentPane().add(mgrview, BorderLayout.CENTER);
// Creates a toolbar for basic zoom/unzoom operations.
IlvJManagerViewControlBar toolbar = new IlvJManagerViewControlBar();
toolbar.setFloatable(false);
toolbar.setSelectButtonAvailable(false);
toolbar.setOrientation(JToolBar.VERTICAL);
toolbar.setView(mgrview);
getContentPane().add(toolbar, BorderLayout.WEST);
getContentPane().add(createControlPanel(), BorderLayout.SOUTH);
// Create the timer.
timer = new Timer(66, new Animation());
// true for debugging
Timer.setLogTimers(false);
}
/**
* Creates a random point located somewhere on the map.
*/
public IlvPoint randomPoint() {
IlvPoint randomPt = new IlvPoint(mapBox.x + (Math.random() * mapBox.width),
mapBox.y + (Math.random() * mapBox.height));
return randomPt;
}
/**
* Creates a new track.
*/
public Track newRandomTrack(Color color, Color hilit, Color alt) {
// Company
int companyIndex = (int) (Math.random() * companies.length);
AirLine company = companies[companyIndex];
// Flight name.
String name = company.getName() + " 0" + (100 + (int) (Math.random() * 900));
// Logo image
Image image = getLogoImage(companyIndex, company.getLogoFileName());
// Creates the track.
Track track = new Track(name, image, randomPoint(), randomPoint(), font, color, hilit, alt);
// Random speed [250 - 1500] mph
track.setSpeed(250 + (int) (Math.random() * 1250));
// Random height [5000-55000] ft
track.setAltitude(100 * (50 + (int) (Math.random() * 500)));
track.setWarningDistance(delta * 2);
return track;
}
/**
* Returns the image for the logo of a given company. The image is read only
* once for each company name.
*/
private Image getLogoImage(int companyIndex, String companyLogoFileName) {
Image image = companiesLogos[companyIndex];
if (image != null)
// the image was already read
return image;
// otherwise, read the image
try {
URL url = getClass().getResource(companyLogoFileName);
image = Toolkit.getDefaultToolkit().getImage(url);
} catch (Throwable th) {
System.err.println("Couldn't get file: " + companyLogoFileName);
}
// store it, to avoid reading again next time
companiesLogos[companyIndex] = image;
return image;
}
/**
* Creates a new cloud.
*/
public IlvGraphic newRandomCloud(IlvGraphic template) {
IlvGraphic cloud = template.copy();
cloud.move(randomPoint());
return cloud;
}
/**
* Starts the sample.
*/
public void start() {
mgrview.setTransformer(new IlvTransformer(2.5, 0, 0, 2.5, 250, 150));
timer.start();
}
/**
* Stops the sample.
*/
public void stop() {
timer.stop();
}
/**
* Changes the number of tracks.
*/
private void setNumberOfTracks(int number) {
if (number == maxTracks)
return;
maxTracks = number;
timer.stop();
manager.deleteAll(trackLayer, false);
tracks = new Track[maxTracks];
Track.transparentLastPositions = (maxTracks <= 100);
Track.antialiasedLastPositions = (maxTracks <= 100);
for (int i = 0; i < maxTracks; i++) {
Track track = newRandomTrack(Color.black, Color.blue, Color.yellow);
manager.addObject(track, trackLayer, false);
tracks[i] = track;
}
showLabelsButton.setSelected(true);
showLogosButton.setSelected(true);
lastPositionButton.setSelected(true);
mgrview.repaint();
timer.start();
}
/**
* Shows or hides the last positions.
*/
private void setShowingLastPositions(final boolean value) {
for (int i = 0; i < maxTracks; i++)
manager.applyToObject(tracks[i], new IlvApplyObject() {
Override
public void apply(IlvGraphic obj, Object arg) {
((Track) obj).setShowingLastPositions(value);
}
}, null, false);
mgrview.repaint();
}
/**
* Shows or hides the labels of tracks.
*/
private void setShowingLabels(final boolean value) {
for (int i = 0; i < maxTracks; i++)
manager.applyToObject(tracks[i], new IlvApplyObject() {
Override
public void apply(IlvGraphic obj, Object arg) {
((Track) obj).setShowingLabels(value);
}
}, null, false);
mgrview.repaint();
}
/**
* Shows or hides the logos of tracks.
*/
private void setShowingLogos(final boolean value) {
for (int i = 0; i < maxTracks; i++)
manager.applyToObject(tracks[i], new IlvApplyObject() {
Override
public void apply(IlvGraphic obj, Object arg) {
((Track) obj).setShowingLogo(value);
}
}, null, false);
mgrview.repaint();
}
/**
* Action listener used by the timer to animate the tracks.
*/
private class Animation implements IlvApplyObject, ActionListener {
Override
public void actionPerformed(ActionEvent evt) {
// Update the position of the tracks
for (int i = 0; i < maxTracks; i++)
manager.applyToObject(tracks[i], this, null, false);
// Repaint the entire sample, not only the manager view,
// to avoid delayed repaints of the other components of the sample
TripleBuffering.this.repaint();
}
/**
* The method that moves a track.
*/
Override
public void apply(IlvGraphic obj, Object arg) {
Track track = (Track) obj;
if (track.hasLanded())
track.init(randomPoint(), randomPoint());
else {
IlvPoint destination = track.getDestination();
IlvPoint position = track.getPosition();
double d = (delta * track.getSpeed()) / 800;
double X = destination.x - position.x;
double Y = destination.y - position.y;
double R2 = X * X + Y * Y;
if (R2 <= d * d)
track.land();
else {
double R = Math.sqrt(R2);
double dx = (d * X) / R;
double dy = (d * Y) / R;
track.translatePosition(dx, dy);
}
}
}
}
/**
* Item listener for check boxes.
*/
private class CheckBoxListener implements ItemListener {
Override
public void itemStateChanged(ItemEvent e) {
final boolean selected = e.getStateChange() == ItemEvent.SELECTED;
Object source = e.getItemSelectable();
if (source == tripleBuffer)
mgrview.setTripleBufferedLayerCount(selected ? 1 : 0);
else if (source == layerCache)
mgrview.setLayerCached(2, selected);
else if (source == showLabelsButton)
setShowingLabels(selected);
else if (source == showLogosButton)
setShowingLogos(selected);
else if (source == lastPositionButton)
setShowingLastPositions(selected);
else if (source == combo) {
int value = 50;
try {
value = Integer.parseInt(e.getItem().toString());
} catch (Exception ex) {
}
setNumberOfTracks(value);
}
fpsHIndex = 0;
fpsHistoryFull = false;
}
}
private JComponent createControlPanel() {
JPanel p = new JPanel();
p.setBorder(LineBorder.createGrayLineBorder());
CheckBoxListener listener = new CheckBoxListener();
lastPositionButton = new JCheckBox("Last Positions");
lastPositionButton.setMnemonic(KeyEvent.VK_P);
lastPositionButton.setSelected(true);
lastPositionButton.addItemListener(listener);
p.add(lastPositionButton);
showLabelsButton = new JCheckBox("Labels");
showLabelsButton.setMnemonic(KeyEvent.VK_L);
showLabelsButton.setSelected(true);
showLabelsButton.addItemListener(listener);
p.add(showLabelsButton);
showLogosButton = new JCheckBox("Logos");
showLogosButton.setMnemonic(KeyEvent.VK_G);
showLogosButton.setSelected(true);
showLogosButton.addItemListener(listener);
p.add(showLogosButton);
JPanel trackNumber = new JPanel();
combo = new JComboBox<String>();
combo.addItem("50");
combo.addItem("100");
combo.addItem("300");
combo.addItem("500");
combo.addItemListener(listener);
trackNumber.add(new JLabel("Tracks:"));
trackNumber.add(combo);
p.add(trackNumber);
tripleBuffer = new JCheckBox("Triple Buffer");
tripleBuffer.setMnemonic(KeyEvent.VK_B);
tripleBuffer.setSelected(true);
tripleBuffer.addItemListener(listener);
p.add(tripleBuffer);
layerCache = new JCheckBox("Layer Cache");
layerCache.setMnemonic(KeyEvent.VK_C);
layerCache.setSelected(true);
layerCache.addItemListener(listener);
p.add(layerCache);
fpsLabel = new JLabel();
fpsLabel.setForeground(Color.MAGENTA);
fpsLabel.setBorder(new BevelBorder(1));
fpsLabel.setPreferredSize(new Dimension(130, 20));
p.add(fpsLabel);
return p;
}
/**
* A main method to run the demo as an application.
*/
public static void main(String[] args) {
// Sun recommends that to put the entire GUI initialization into the
// AWT thread
SwingUtilities.invokeLater(new Runnable() {
Override
public void run() {
JFrame frame = new JFrame("Triple Buffering Demo");
frame.addWindowListener(new WindowAdapter() {
Override
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
TripleBuffering app = new TripleBuffering();
frame.getContentPane().add(app);
frame.setSize(790, 480);
app.init();
app.start();
frame.setVisible(true);
}
});
}
/**
* A data structure for airlines.
*/
private static class AirLine {
private String _name;
private String _logoFileName;
AirLine(String name, String logoFileName) {
_name = name;
_logoFileName = logoFileName;
}
String getName() {
return _name;
}
String getLogoFileName() {
return _logoFileName;
}
}
}