package PamView;
import java.awt.Container;
import java.awt.Frame;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.Serializable;
import java.util.ArrayList;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLayer;
import javax.swing.JMenuItem;
import javax.swing.JPopupMenu;
import PamController.NewModuleDialog;
import PamController.PAMControllerGUI;
import PamController.PamControlledUnit;
import PamController.PamControlledUnitSettings;
import PamController.PamController;
import PamController.PamControllerInterface;
import PamController.PamSettingManager;
import PamController.PamSettings;
import PamModel.PamModel;
import PamModel.PamModuleInfo;
import PamView.panel.PamTabbedPane;
import pamViewFX.pamTask.PamTaskUpdate;
/**
* The GuiFrameManager manages multiple PamGui frames, each
* of which may contain multiple tabs of module information
* and a side panel.
*
* The user can move tabs between the various frames
* and create new frames by right
* clicking on the tabs themselves.
* @see PamGui
*
* @author Doug Gillespie
*
*/
public class GuiFrameManager implements PamSettings, PAMControllerGUI {
private PamController pamController;
private java.util.List frameList = new ArrayList();
private ArrayList pamViewList = new ArrayList();
private int maxFrameNumber = 0;
private GuiFrameSettings guiFrameSettings;
private Image frameIcon;
public GuiFrameManager(PamController pamController) {
super();
this.pamController = pamController;
PamSettingManager.getInstance().registerSettings(this);
String iconLoc = PamIcon.getPAMGuardIconPath(PamIcon.NORMAL);
// switch (PamController.getInstance().getRunMode()){
// case(PamController.RUN_NETWORKRECEIVER):
// iconLoc="Resources/pamguardIconNR.png";
// break;
// case(PamController.RUN_PAMVIEW):
// iconLoc="Resources/pamguardIconV.png";
// break;
// case(PamController.RUN_MIXEDMODE):
// iconLoc="Resources/pamguardIconM.png";
// break;
// default:
// iconLoc="Resources/pamguardIcon.png";
// }
frameIcon = new ImageIcon(ClassLoader.getSystemResource(iconLoc)).getImage();
}
public java.util.List getFrameList() {
return frameList;
}
/**
* Make a list of Gui frames - that is all
* PamView's with a frame number > 0 which indicates
* they are a GUI frame. Other frames, such as the model
* view, have a frame number < 0.
*/
public void makeFrameList() {
frameList.clear();
int f;
for (int i = 0; i < pamViewList.size(); i++) {
f = pamViewList.get(i).getFrameNumber();
if (f >= 0) {
frameList.add(f);
}
}
}
/**
* Get the total number of frames
* @return number of frames.
*/
public int getNumFrames() {
return Math.max(1, frameList.size());
}
/**
* Get a frame
* @param iFrame frame number
* @return frame.
*/
public JFrame getFrame(int iFrame) {
if (iFrame >= pamViewList.size()) {
return null;
}
return pamViewList.get(iFrame).getGuiFrame();
}
/**
* See if a frame exists in the current list. If it doens't,
* then create it.
* @param frameNumber Frame Number
*/
private PamViewInterface createFrame(int frameNumber) {
PamViewInterface frame;
if ((frame = findFrame(frameNumber)) != null) {
return frame;
}
PamGui newGui = new PamGui(pamController, pamController.getModelInterface(), frameNumber);
addView(newGui);
sortFrameTitles();
return newGui;
}
/**
* Closes a PamGui FRame (not the main one)
* All tabs are first moved to the main frame (No. 0)
* then the frame is removed from the list of frames
* then the frame is closed.
* @param pamGui reference to frame to close.
*/
public void closeExtraFrame(PamGui pamGui) {
int nUnits = pamController.getNumControlledUnits();
int iFrame;
PamControlledUnit pamControlledUnit;
for (int i = 0; i < nUnits; i++) {
pamControlledUnit = pamController.getControlledUnit(i);
iFrame = pamControlledUnit.getFrameNumber();
if (iFrame == pamGui.getFrameNumber()) {
moveUnit(pamControlledUnit, pamGui.getFrameNumber(), 0);
}
}
pamGui.frame.dispose();
removeView(pamGui);
sortFrameTitles();
}
/**
* Goes through all open frames before they start closing
* and gets their parameters into the structure
* which will be written to the psf file.
*/
public void getAllFrameParameters(){
PamViewInterface view;
for (int i = 0; i < pamViewList.size(); i++) {
view = pamViewList.get(i);
if (view.getFrameNumber() >= 0) {
((PamGui) view).getGuiParameters();
}
}
}
/**
* See if a real frame exists.
* @param iFrame
* @return true if a frame already exists.
*/
private boolean frameExists(int iFrame) {
return (findFrame(iFrame) != null);
}
/**
* Find the first free frame number that's not in the frame list
* @return an integer.
*/
private int firstFreeFrameNumber() {
makeFrameList();
int iFrame = 0;
while (true) {
if (!frameExists(iFrame)) {
return iFrame;
}
iFrame++;
}
}
/**
* Get a frame GUI. This is a single frame whihc holds a GUI with tabs etc.
* @param iFram e- the frame index to get.
* @return the frame GUI to get.
*/
public PamGui getFrameGui(int iFrame) {
if (iFrame >= pamViewList.size()) {
return null;
}
return (PamGui) pamViewList.get(iFrame);
}
private PamViewInterface findFrame(int iFrame) {
PamViewInterface v;
for (int i = 0; i < pamViewList.size(); i++) {
if ((v = pamViewList.get(i)).getFrameNumber() == iFrame) {
return v;
}
}
return null;
}
private boolean haveFrameInList(int iFrame) {
if (frameList == null) {
return false;
}
for (int i = 0; i < frameList.size(); i++) {
if (frameList.get(i) == iFrame) {
return true;
}
}
return false;
}
private void moveUnit(PamControlledUnit pcu, int currentFrame, int destinationFrame) {
/*
* First see if the destination frame exists, if not create it.
*/
PamGui newGui = (PamGui) createFrame(destinationFrame);
/*
* Then remove the unit from it's current frame
*/
PamGui currentGui = (PamGui) pcu.getPamView();
if (currentGui != null) {
currentGui.removeControlledUnit(pcu);
// currentGui.ShowTabSpecificSettings();
}
/*
* Then give it a new frame index.
*/
pcu.setFrameNumber(destinationFrame);
/*
* Then tell the new frame to add it.
*/
newGui.addControlledUnit(pcu);
}
public JPopupMenu getTabPopupMenu(PamGui pamGui, int tabIndex) {
JPopupMenu pm = new JPopupMenu();
JMenuItem menuItem;
makeFrameList();
PamTabbedPane ptp = pamGui.getMainTab();
String title = ptp.getTitleAt(tabIndex);
PamControlledUnit pcu = pamGui.findControlledUnit(tabIndex);
ClipboardCopier clipboardCopier;
for (int i = 0; i < frameList.size(); i++) {
if (frameList.get(i) == pamGui.getFrameNumber()) {
continue;
}
menuItem = new JMenuItem(String.format("Move %s to %s", title, getMenuFrameName(frameList.get(i))));
menuItem.addActionListener(new TabMover(pcu, pamGui.getFrameNumber(), frameList.get(i)));
pm.add(menuItem);
}
menuItem = new JMenuItem(String.format("Move %s to a new frame", title));
menuItem.addActionListener(new TabMover(pcu, pamGui.getFrameNumber(), firstFreeFrameNumber()));
pm.add(menuItem);
clipboardCopier = pcu.getTabClipCopier();
if (clipboardCopier != null) {
pm.addSeparator();
pm.add(clipboardCopier.getCopyMenuItem("Copy tab content to clipboard"));
}
return pm;
}
public String getMenuFrameName(int iFrame) {
if (iFrame == 0) {
return "the main frame";
}
else {
return String.format("frame %d", iFrame);
}
}
/**
* Get a name for a frame which can be used in their titles
* and in menus, etc.
* @param iFrame frame Number
* @return names String
*/
public String getFrameName(int iFrame) {
if (iFrame == 0) {
return "Main Frame";
}
else {
return String.format("Frame %d", iFrame);
}
}
public void sortFrameTitles() {
PamViewInterface view;
makeFrameList();
int nFrames = frameList.size();
int frameNo;
for (int i = 0; i < pamViewList.size(); i++) {
view = pamViewList.get(i);
frameNo = view.getFrameNumber();
if (frameNo < 0) {
continue;
}
view.setTitle(getFrameTitle(frameNo, nFrames));
}
}
private String getFrameTitle(int frameNo, int nFrames) {
String tit = "PAMGUARD";
switch(pamController.getRunMode()) {
case PamController.RUN_NORMAL:
tit = "PAMGUARD";
break;
case PamController.RUN_NETWORKRECEIVER:
tit = "PAMGUARD Network Receiver";
break;
case PamController.RUN_MIXEDMODE:
tit = "PAMGUARD Mixed Mode";
break;
case PamController.RUN_PAMVIEW:
tit = "PAMGUARD Viewer";
break;
case PamController.RUN_REMOTE:
tit = "PAMGUARD Remote";
break;
}
if (nFrames <= 1) {
// tit = "PAMGUARD";
}
else if (frameNo == 0) {
tit += " Main";
}
else {
tit = String.format("%s Frame %d", tit, frameNo);
}
// now append the name of the psf or database.
String ctrlName = pamController.getPSFName();
if (ctrlName != null) {
tit += " - " + ctrlName;
}
return tit;
}
class TabMover implements ActionListener {
PamControlledUnit pamControlledUnit;
int currentFrame;
int destinationFrame;
public TabMover(PamControlledUnit pamControlledUnit, int currentFrame,
int destinationFrame) {
super();
this.pamControlledUnit = pamControlledUnit;
this.currentFrame = currentFrame;
this.destinationFrame = destinationFrame;
}
@Override
public void actionPerformed(ActionEvent arg0) {
moveUnit(pamControlledUnit, currentFrame, destinationFrame);
}
}
@Override
public void addControlledUnit(PamControlledUnit controlledUnit) {
for (int i = 0; i < pamViewList.size(); i++) {
pamViewList.get(i).addControlledUnit(controlledUnit);
}
}
@Override
public void removeControlledUnit(PamControlledUnit controlledUnit) {
for (int i = 0; i < pamViewList.size(); i++) {
pamViewList.get(i).removeControlledUnit(controlledUnit);
}
}
@Override
public void addView(PamViewInterface newView) {
if (pamViewList == null) {
pamViewList = new ArrayList();
}
pamViewList.add(newView);
}
public void removeView(PamViewInterface oldView) {
if (pamViewList == null) {
pamViewList = new ArrayList();
}
pamViewList.remove(oldView);
}
@Override
public void showControlledUnit(PamControlledUnit unit) {
for (int i = 0; i < pamViewList.size(); i++) {
pamViewList.get(i).showControlledUnit(unit);
}
}
public void pamStart() {
for (int i = 0; i < pamViewList.size(); i++) {
pamViewList.get(i).pamStarted();
}
}
public void pamStop() {
for (int i = 0; i < pamViewList.size(); i++) {
pamViewList.get(i).pamEnded();
}
}
@Override
public void notifyModelChanged(int changeType) {
for (int i = 0; i < pamViewList.size(); i++) {
pamViewList.get(i).modelChanged(changeType);
}
if (changeType == PamControllerInterface.INITIALIZATION_COMPLETE) {
intialiseFrames();
}
if (changeType==PamControllerInterface.ADD_CONTROLLEDUNIT) {
if (this.getFrame(0)!=null) this.getFrame(0).revalidate();
}
if (changeType==PamControllerInterface.REMOVE_CONTROLLEDUNIT) {
if (this.getFrame(0)!=null) this.getFrame(0).revalidate();
}
}
/**
* Called at start up to move various controlled unit panels to different frames of choice.
*/
private void intialiseFrames() {
if (guiFrameSettings == null) {
return;
}
int nUnits = pamController.getNumControlledUnits();
PamControlledUnit pamControlledUnit;
for (int i = 0; i < nUnits; i++) {
pamControlledUnit = pamController.getControlledUnit(i);
int iFrame = guiFrameSettings.getUnitFrameNumber(pamControlledUnit);
if (iFrame > 0) {
moveUnit(pamControlledUnit, 0, iFrame);
}
}
}
@Override
public void destroyModel() {
for (int i = 0; i < pamViewList.size(); i++) {
pamViewList.get(i).modelChanged(PamControllerInterface.DESTROY_EVERYTHING);
}
pamViewList = null;
}
@Override
public Serializable getSettingsReference() {
GuiFrameSettings guiFrameSettings = new GuiFrameSettings();
int nUnits = pamController.getNumControlledUnits();
PamControlledUnit pamControlledUnit;
for (int i = 0; i < nUnits; i++) {
pamControlledUnit = pamController.getControlledUnit(i);
guiFrameSettings.addUnitInfo(pamControlledUnit);
}
return guiFrameSettings;
}
@Override
public long getSettingsVersion() {
return GuiFrameSettings.serialVersionUID;
}
@Override
public String getUnitName() {
return "GUI Frame Settings";
}
@Override
public String getUnitType() {
return "GUI Frame Settings";
}
@Override
public boolean restoreSettings(
PamControlledUnitSettings pamControlledUnitSettings) {
this.guiFrameSettings = ((GuiFrameSettings)(pamControlledUnitSettings.getSettings())).clone();
return true;
}
@Override
public void enableGUIControl(boolean enable) {
for (int i = 0; i < pamViewList.size(); i++) {
// pamViewList.get(i).enableGUIControl(enable);
Container component = pamViewList.get(i).getGuiFrame().getContentPane();
if (JLayer.class.isAssignableFrom(component.getClass())) {
JLayer layer = (JLayer) component;
}
pamViewList.get(i).getGuiFrame().setEnabled(enable);
}
}
public JMenuItem getCollapseMenuItem() {
JMenuItem mi = new JMenuItem("Collapse multi-frames");
mi.setToolTipText("If using multiple frames, collapse all secondary frames into the main display");
mi.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
collapseAllFrames();
}
});
int nFrames = countGuiFrames();
mi.setEnabled(nFrames > 1);
return mi;
}
private int countGuiFrames() {
int n = 0;
for (PamViewInterface pv:pamViewList) {
if (PamGui.class.isAssignableFrom(pv.getClass())) {
n++;
}
}
return n;
}
protected void collapseAllFrames() {
int nView = pamViewList.size();
for (int iV = nView-1; iV > 0; iV--) {
PamViewInterface pv = pamViewList.get(iV);
if (PamGui.class.isAssignableFrom(pv.getClass())) {
PamGui pamGui = (PamGui) pv;
if (pamGui.getFrameNumber() > 0) {
closeExtraFrame(pamGui);
}
}
}
}
@Override
public void notifyLoadProgress(PamTaskUpdate progress) {
// TODO Auto-generated method stub
}
@Override
public PamSettings getInitialSettings() {
// TODO Auto-generated method stub
return null;
}
@Override
public void init() {
// TODO Auto-generated method stub
}
@Override
public boolean hasCallBack() {
return false;
}
@Override
public PamViewInterface initPrimaryView(PamController pamController, PamModel pamModelInterface ) {
return new PamGui(pamController, pamModelInterface, 0);
}
@Override
public String getModuleName(Object parentFrame, PamModuleInfo moduleInfo) {
return NewModuleDialog.showDialog(parentFrame==null ? null : (Frame) parentFrame ,moduleInfo,null);
}
@Override
public void pamStarted() {
pamStart();
}
@Override
public void pamEnded() {
pamStop();
}
@Override
public void modelChanged(int changeType) {
// TODO Auto-generated method stub
}
@Override
public void setTitle(String title) {
// TODO Auto-generated method stub
}
@Override
public int getFrameNumber() {
// TODO Auto-generated method stub
return 0;
}
@Override
public JFrame getGuiFrame() {
// TODO Auto-generated method stub
return null;
}
public void setDefaultFrameIcon(Image frameIcon) {
if (frameIcon != null) {
this.frameIcon = frameIcon;
for (PamViewInterface vi : pamViewList) {
JFrame frame = vi.getGuiFrame();
if (frame != null) {
frame.setIconImage(frameIcon);
}
}
}
}
public Image getDefaultFrameIcon() {
return frameIcon;
}
/**
* Function that can move GUI frames back onto the main window.
* Can be used to recover a GUI if it's on a monitor that is not present.
*/
public void findGUI() {
if (pamViewList == null) {
return;
}
int loc = 10;
for (PamViewInterface view : pamViewList) {
JFrame frame = view.getGuiFrame();
if (frame == null) {
continue;
}
frame.setLocation(loc, loc);
frame.setState(Frame.NORMAL);
frame.setVisible(true);
loc += 20;
}
}
}