package trackerModule.sim.map;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Frame;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.net.MalformedURLException;
import java.net.URL;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.ButtonGroup;
import javax.swing.JButton;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.JViewport;
import javax.swing.ScrollPaneConstants;
import javax.swing.border.CompoundBorder;
import javax.swing.border.TitledBorder;
import trackerModule.core.datastructure.TDB;
import trackerModule.core.datastructure.Unit;
import trackerModule.core.rulestructure.RDB;
import trackerModule.sim.tracker.Ship;
import trackerModule.sim.tracker.World;
import edu.gmu.seor.prognos.simulation.integration.gui.FileChooserDialog;
import groundTruthModule.GTmodule.GTGenerator;
import groundTruthModule.datastructure.DataBase;
/**
* The Class MapFrame.
*/
public class MapFrame extends GeneralFrame {
/** The Constant serialVersionUID. */
private static final long serialVersionUID = 8493843831522229867L;
/** The map. */
GMap map;
/** The frame. */
static public MapFrame frame = null;
/**
* This.
*
* @return the map frame
*/
static public MapFrame This(){
return frame ;
}
/** The tree pane. */
public MapTreePane treePane;
/** The info pane. */
public MapInfoPane infoPane;
/** The scroll pane. */
JScrollPane scrollPane;
/** The Action save. */
Action acSave;
/** The Action load. */
Action acLoad;
/** The Action save as. */
Action acSaveAs;
/** The Action save world. */
Action acSaveWorld;
/** The Action load world. */
Action acLoadWorld;
/** The Action edit mode. */
Action acEditMode;
/** The Action sim mode. */
Action acSimMode;
/** The Action run. */
public Action acRun;
/** The Action stop. */
public Action acStop;
/** The Action reset. */
Action acReset;
/** The Action get soi info. */
Action acGetSOIInfo;
/** The Action show info. */
Action acShowInfo;
/** The Action show ship info. */
Action acShowShipInfo;
/** The Action zoom in. */
Action acZoomIn;
/** The Action zoom out. */
Action acZoomOut;
/** The text zoom. */
JTextField textZoom;
/** The map image. */
String mapImage = "/maps/ArabianSea.bmp";
/** The cur entity. */
Unit curEntity = null;
/** The Action change speed. */
private Action acChangeSpeed;
/** The Action change area. */
private Action acChangeArea;
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Construction
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Instantiates a new map frame.
*
* @param title the title
*/
public MapFrame( String title ) {
super(title);
this.init();
this.pack();
this.setVisible(true);
frame = this;
}
/**
* Instantiates a new map frame.
*
* @param title the title
* @param image the image
*/
public MapFrame( String title, String image ) {
super(title);
frame = this;
mapImage = image;
this.init();
this.pack();
this.setVisible(true);
}
/**
* Initialize.
*/
public void init() {
JScrollPane m = createMap();
JPanel t = createTreePane();
JPanel b = createButtonPane();
JPanel k = createTablePane();
this.add(b, BorderLayout.NORTH);
this.add(m, BorderLayout.CENTER);
this.add(t, BorderLayout.WEST);
this.add(k, BorderLayout.SOUTH);
}
/**
* Sets the cur entity.
*
* @param u the new cur entity
*/
public void setCurEntity( Unit u ){
curEntity = u;
infoPane.tablePane.initTable(null, u);
treePane.selectItem(u);
}
/**
* Gets the cur entity.
*
* @return the cur entity
*/
public Unit getCurEntity(){
return curEntity;
}
/**
* Move viewport.
*
* @param u the unit
*/
public void moveViewport( Unit u ){
if( u != null)
moveToShipsPosition( u.get("X").getDataByInt(), u.get("Y").getDataByInt() );
}
/**
* Move to ships position.
*
* @param x the x
* @param y the y
*/
public void moveToShipsPosition( int x, int y ){
Dimension s = scrollPane.getSize();
JViewport view = scrollPane.getViewport();
int newX = (int)((x-s.width/2)*map.getScale());
int newY = (int)((y-s.height/2)*map.getScale());
if( map.getScaledWidth() < (newX + s.width) )
newX = map.getScaledWidth() - s.width;
if( map.getScaledHeight() < (newY + s.height) )
newY = map.getScaledHeight() - s.height;
if( newX < 0 )
newX = 0;
if( newY < 0 )
newY = 0;
view.setViewPosition(new Point(newX, newY));
}
/**
* Creates the map.
*
* @return the java scroll pane
*/
private JScrollPane createMap() {
map = new GMap(this);
int v = ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED;
int h = ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED;
scrollPane = new JScrollPane(map, v, h);
scrollPane.setWheelScrollingEnabled(true);
URL url = getClass().getResource(mapImage);
if (url == null) {
try {
if (mapImage.trim().charAt(0) == '/') {
mapImage = "." + mapImage;
}
url = new File(mapImage).toURI().toURL();
} catch (MalformedURLException e) {
throw new IllegalArgumentException(e);
}
}
map.setBackgroundImage(url);
return scrollPane;
}
/**
* Creates the button pane.
*
* @return the java panel
*/
private JPanel createButtonPane() {
ButtonGroup group = new ButtonGroup();
// Text Button Panel
JPanel ButtonPanel = new JPanel();
ButtonPanel.setLayout(new BoxLayout(ButtonPanel, BoxLayout.X_AXIS));
ButtonPanel.setBorder(border5);
// File Menu Buttons
JPanel p2 = createHorizontalPanel(false);
ButtonPanel.add(p2);
p2.setBorder(new CompoundBorder(new TitledBorder(null, "File Menu", TitledBorder.LEFT, TitledBorder.TOP), border5));
// Add Button
JButton btn;
btn = createSaveButton();
p2.add(btn);
group.add(btn);
p2.add(Box.createRigidArea(VGAP5));
btn = createLoadlButton();
p2.add(btn);
group.add(btn);
p2.add(Box.createRigidArea(VGAP5));
//btn = createSaveAsButton();
//p2.add(btn);
//group.add(btn);
//p2.add(Box.createRigidArea(VGAP5));
btn = createSaveWorldButton();
p2.add(btn);
group.add(btn);
p2.add(Box.createRigidArea(VGAP5));
btn = createLoadWorldButton();
p2.add(btn);
group.add(btn);
p2.add(Box.createRigidArea(VGAP5));
// Simulation Mode Buttons
p2 = createHorizontalPanel(false);
ButtonPanel.add(p2);
p2.setBorder(new CompoundBorder(new TitledBorder(null, "Mode",
TitledBorder.LEFT, TitledBorder.TOP), border5));
// Add Button
btn = createEditModeButton();
p2.add(btn);
group.add(btn);
p2.add(Box.createRigidArea(VGAP5));
btn = createSimModeButton();
p2.add(btn);
group.add(btn);
p2.add(Box.createRigidArea(VGAP5));
// Simulation Action Buttons
p2 = createHorizontalPanel(false);
ButtonPanel.add(p2);
p2.setBorder(new CompoundBorder(new TitledBorder(null, "Simulation", TitledBorder.LEFT, TitledBorder.TOP), border5));
// Add Button
btn = createRunButton();
p2.add(btn);
group.add(btn);
p2.add(Box.createRigidArea(VGAP5));
btn = createStopButton();
p2.add(btn);
group.add(btn);
p2.add(Box.createRigidArea(VGAP5));
btn = createResetButton();
p2.add(btn);
group.add(btn);
p2.add(Box.createRigidArea(VGAP5));
btn = createSpeedChangeButton();
p2.add(btn);
group.add(btn);
p2.add(Box.createRigidArea(VGAP5));
btn = createAreaChangeButton();
p2.add(btn);
group.add(btn);
p2.add(Box.createRigidArea(VGAP5));
//btn = createGetSOIInfoButton();
//p2.add(btn);
//group.add(btn);
//p2.add(Box.createRigidArea(VGAP5));
// Screen Action Buttons
p2 = createHorizontalPanel(false);
ButtonPanel.add(p2);
p2.setBorder(new CompoundBorder(new TitledBorder(null, "Screen", TitledBorder.LEFT, TitledBorder.TOP), border5));
// Add Button
btn = createShowInfoButton();
p2.add(btn);
group.add(btn);
p2.add(Box.createRigidArea(VGAP5));
btn = createShowShipInfoButton();
p2.add(btn);
group.add(btn);
p2.add(Box.createRigidArea(VGAP5));
btn = createZoomInButton();
p2.add(btn);
group.add(btn);
p2.add(Box.createRigidArea(VGAP5));
btn = createZoomOutButton();
p2.add(btn);
group.add(btn);
p2.add(Box.createRigidArea(VGAP5));
textZoom = new JTextField(5);
p2.add(textZoom);
p2.add(Box.createRigidArea(VGAP5));
textZoom.setText("100%");
textZoom.setEditable(false);
textZoom.setPreferredSize(new Dimension(50,20));
textZoom.setMaximumSize(new Dimension(50,20));
return ButtonPanel;
}
/**
* Creates the tree pane.
*
* @return the java panel
*/
private JPanel createTreePane() {
treePane = new MapTreePane(this);
treePane.setPreferredSize(new Dimension(200, 200));
return treePane;
}
/**
* Creates the table pane.
*
* @return the java panel
*/
private JPanel createTablePane() {
infoPane = new MapInfoPane(this);
return infoPane;
}
// Buttons
/**
* Creates the save button.
*
* @return the java button
*/
private JButton createSaveButton() {
acSave = new AbstractAction("Save Map") {
public void actionPerformed(ActionEvent e) {
World.This().saveWorld();
}
};
return createButton(acSave);
}
/**
* Creates the load button.
*
* @return the java button
*/
private JButton createLoadlButton() {
acLoad = new AbstractAction("Load Map") {
public void actionPerformed(ActionEvent e) {
World.This().loadWorld();
map.repaint();
}
};
return createButton(acLoad);
}
/**
* Creates the save as button.
*
* @return the java button
*/
private JButton createSaveAsButton() {
acSaveAs = new AbstractAction("Save As") {
public void actionPerformed(ActionEvent e) {
World.This().save("World2.map");
}
};
return createButton(acSaveAs);
}
/**
* Creates the save world button.
*
* @return the java button
*/
private JButton createSaveWorldButton() {
acSaveWorld = new AbstractAction("Save World") {
public void actionPerformed(ActionEvent e) {
FileChooserDialog ufd = new FileChooserDialog();
String strfile = ufd.saveFile(new Frame(), "Open...", ".\\", "*.tdb");
int i = strfile.indexOf(".tdb");
if(i < 1)
return;
strfile = strfile.substring(0, i);
World.This().save(strfile+".map");
System.out.println("Saved! [map]: " + strfile+".map");
DataBase.getInstance().save(strfile+".sdb");
System.out.println("Saved! [sdb]: " + strfile+".sdb");
TDB.This().save(strfile+".tdb");
System.out.println("Saved! [tdb]: " + strfile+".tdb");
RDB.This().save(strfile+".rdb");
System.out.println("Saved! [rdb]: " + strfile+".rdb");
JOptionPane.showMessageDialog(null, "The file was saved!");
System.gc();
}
};
return createButton(acSaveWorld);
}
/**
* Load rdb.
*
* @param filename the filename
*/
synchronized public void loadRDB(String filename){
FileInputStream fis = null;
ObjectInputStream in = null;
try
{
fis = new FileInputStream(filename);
in = new ObjectInputStream(fis);
RDB.This().removeAll();
RDB.This().close();
RDB.This().rdb = (RDB)in.readObject();
RDB.This().nTime = (Integer)in.readObject();
in.close();
fis.close();
RDB.This().init();
RDB.This().removeAllMessageObjectForTime();
RDB.This().removeAllMessageObjectForRule();
RDB.This().addMessageObjectForTime(World.This());
RDB.This().addMessageObjectForTime(infoPane.tablePane);
RDB.This().addMessageObjectForTime(map);
RDB.This().addMessageObjectForTime(new GTGenerator());
RDB.This().addMessageObjectForRule(new Ship("Ship0"));
setCurEntity(null);
map.repaint();
}
catch(IOException ex)
{
ex.printStackTrace();
}
catch(ClassNotFoundException ex)
{
ex.printStackTrace();
}
}
/**
* Creates the load world button.
*
* @return the java button
*/
private JButton createLoadWorldButton() {
acLoadWorld = new AbstractAction("Load World") {
public void actionPerformed(ActionEvent e) {
FileChooserDialog ufd = new FileChooserDialog();
try {
loadWorld(ufd.loadFile(new Frame(), "Open...", ".\\", "*.tdb"));
JOptionPane.showMessageDialog(null, "The file was loaded!");
} catch (Exception exc) {
exc.printStackTrace();
JOptionPane.showMessageDialog(null, "Error loading file.");
}
}
};
return createButton(acLoadWorld);
}
/**
* This method loads the configuration of a world from file.
* 4 types of files are going to be loaded: .map (the image of the map),
* .sdb (database with static data), .tdb (database with time-sensitive information),
* and .rdb (database containing some rules related to the world and ships).
*
* @param tdbFileName : file name of the .tdb file. The other 3 files are going to be loaded assuming
* that they have the same prefix. I.e. the file extension (.tdb) of tdbFileName will be removed and
* appended with .map, .sdb, and .rdb in order to load the other 3 files.
* @throws IOException Signals that an I/O exception has occurred.
*/
public void loadWorld(String tdbFileName) throws IOException {
try {
if (tdbFileName == null) {
return;
}
int i = tdbFileName.indexOf(".tdb");
if(i < 1) {
return;
}
tdbFileName = tdbFileName.substring(0, i);
World.This().load(tdbFileName+".map");
System.out.println("Loaded! [map]: " + tdbFileName+".map");
DataBase.getInstance().load(tdbFileName+".sdb");
System.out.println("Loaded! [sdb]: " + tdbFileName+".sdb");
TDB.This().load(tdbFileName+".tdb");
System.out.println("Loaded! [tdb]: " + tdbFileName+".tdb");
loadRDB(tdbFileName+".rdb");
System.out.println("Loaded! [rdb]: " + tdbFileName+".rdb");
treePane.initTree();
System.gc();
} catch (Exception e) {
throw new IOException("Could not load " + tdbFileName, e);
}
}
/**
* Creates the edit mode button.
*
* @return the java button
*/
private JButton createEditModeButton() {
acEditMode = new AbstractAction("Editing") {
public void actionPerformed(ActionEvent e) {
map.setMode(map.MODE_EDIT);
map.repaint();
}
};
return createButton(acEditMode);
}
/**
* Creates the sim mode button.
*
* @return the java button
*/
private JButton createSimModeButton() {
acSimMode = new AbstractAction("Simulation") {
public void actionPerformed(ActionEvent e) {
map.setMode(map.MODE_SIM);
map.repaint();
}
};
return createButton(acSimMode);
}
/**
* Creates the run button.
*
* @return the java button
*/
private JButton createRunButton() {
acRun = new AbstractAction("Run") {
/**
*
*/
private static final long serialVersionUID = 2097392893698604684L;
public void actionPerformed(ActionEvent e) {
if (map.getMode() == GMap.MODE_SIM) {
RDB.This().start();
}
}
};
return createButton(acRun);
}
/**
* Creates the stop button.
*
* @return the java button
*/
private JButton createStopButton() {
acStop = new AbstractAction("Stop") {
public void actionPerformed(ActionEvent e) {
RDB.This().stop();
}
};
return createButton(acStop);
}
/**
* Creates the area change button.
*
* @return the java button
*/
protected JButton createAreaChangeButton() {
acChangeArea = new AbstractAction("Area") {
public void actionPerformed(ActionEvent e) {
try {
String ret = JOptionPane.showInputDialog(MapFrame.this, "Provide the search range for the query of SOI."
+ "\n (10 ~ 100 nautical mile as diameter).",
"" + World.This().getDetectingMile());
if (ret != null) {
World.This().setDetectingMile(Integer.parseInt(ret));
}
} catch (Exception e2) {
e2.printStackTrace();
JOptionPane.showMessageDialog(MapFrame.this, "Invalid nautical mile range.");
}
}
};
JButton button = createButton(acChangeArea);
button.setToolTipText("Change the search range.");
return button;
}
/**
* Creates the speed change button.
*
* @return the java button
*/
protected JButton createSpeedChangeButton() {
acChangeSpeed = new AbstractAction("Speed") {
public void actionPerformed(ActionEvent e) {
try {
String ret = JOptionPane.showInputDialog(MapFrame.this, "Provide the clock tick interval (milliseconds)."
+ "\nLower values result in faster clock (i.e. faster ships).",
"" + RDB.This().getTimeTick());
if (ret != null) {
RDB.This().setTimeTick(Math.abs(Integer.parseInt(ret)));
}
} catch (Exception e2) {
e2.printStackTrace();
JOptionPane.showMessageDialog(MapFrame.this, "Invalid tick range.");
}
}
};
JButton button = createButton(acChangeSpeed);
button.setToolTipText("Change the clock tick interval.");
return button;
}
/**
* Creates the reset button.
*
* @return the java button
*/
private JButton createResetButton() {
acReset = new AbstractAction("Reset") {
public void actionPerformed(ActionEvent e) {
// map.removeAllGEntity();
// RDB.This().resetTime();
// World.This().createShipsByGT();
}
};
return createButton(acReset);
}
/**
* Creates the get soi info button.
*
* @return the java button
*/
private JButton createGetSOIInfoButton() {
acGetSOIInfo = new AbstractAction("Get SOI Info") {
public void actionPerformed(ActionEvent e) {
}
};
return createButton(acGetSOIInfo);
}
/**
* Creates the show info button.
*
* @return the java button
*/
private JButton createShowInfoButton() {
acShowInfo = new AbstractAction("Areas") {
public void actionPerformed(ActionEvent e) {
if (map.getShowInfo() == false)
map.setShowInfo(true);
else
map.setShowInfo(false);
}
};
return createButton(acShowInfo);
}
/**
* Creates the show ship info button.
*
* @return the java button
*/
private JButton createShowShipInfoButton() {
acShowShipInfo = new AbstractAction("Ship info") {
public void actionPerformed(ActionEvent e) {
if (map.getShowShipInfo() == false)
map.setShowShipInfo(true);
else
map.setShowShipInfo(false);
}
};
return createButton(acShowShipInfo);
}
/**
* Creates the zoom in button.
*
* @return the java button
*/
private JButton createZoomInButton() {
acZoomIn = new AbstractAction("Zoom In") {
public void actionPerformed(ActionEvent e) {
Double d = map.getScale();
if( d.equals(0.8) )
map.setScale(1.0);
else
if( d.equals(0.6) )
map.setScale(0.8);
else
if( d.equals(0.4) )
map.setScale(0.6);
else
if( d.equals(0.2) )
map.setScale(0.4);
textZoom.setText((int)(map.getScale()*100)+"%");
}
};
return createButton(acZoomIn);
}
/**
* Creates the zoom out button.
*
* @return the java button
*/
private JButton createZoomOutButton() {
acZoomOut = new AbstractAction("Zoom Out") {
public void actionPerformed(ActionEvent e) {
Double d = map.getScale();
if( d.equals(1.0) )
map.setScale(0.8);
else
if( d.equals(0.8) )
map.setScale(0.6);
else
if( d.equals(0.6) )
map.setScale(0.4);
else
if( d.equals(0.4) )
map.setScale(0.2);
else
if( d.equals(0.4) )
map.setScale(0.2);
textZoom.setText((int)(map.getScale()*100)+"%");
}
};
return createButton(acZoomOut);
}
}