/** * Moving Map Navigator Demonstrator Applet * @author Robert J Morton YE572246C * @version 21 Oct 1997 greatly enhanced 19 Dec 2007 */ /* The central applet class for the Moving Map package */ import javax.swing.*; // Java Swing GUI utilities import java.awt.*; // Java Abstract Windowing Toolkit public class movmap extends JApplet implements Runnable { // what the hell this is for, I don't know! private static final long serialVersionUID = 7L; // for applet background clouds picture static Image AI, IMG1, IMG2, IMG3, IMG4; private boolean FTT = true, // TRUE = first-time-through the program loadingRoutes = true, // TRUE = routes loader not yet finished its task Init2started = false, Init2finished = false; /* TRUE = GUI has now been fully built via Event Dispatching Thread. */ boolean JarredImages = true, // TRUE = get the image files from the jar file JarredRoutes = true; // TRUE = get route data files from the jar file private int Aw = 620, Ah = 530, // width and height of applet window Am = 15, // applet's border width // Origins, widths and heights of: Nx = 15, Ny = 65, Nw = 275, Nh = 300, // navigation data names area Vx = 153, Vy = 65, Vw = 137, Vh = 300, // navigation data variables Px = 15, Py = 377, Pw = 130, Ph = 102, // refresh interval selector Sx = 160, Sy = 377, Sw = 130, Sh = 102, // map Scale selector panel Lx = 15, Ly = 480, Lw = 406, Lh = 35, // message panel Mx = 305, My = 65, Mw = 300, Mh = 300, // map AREA Qx = 105, Qy = 480, Qw = 310, Qh = 35, // area for loading messages fh; // font height private long T, // future system time at which a new plot is due to begin TF = 1000; /* inter-plot time frame (milliseconds) This can be changed by the user. */ private String cb; // code base for applet private Container cp; // instance reference of the JApplet's pane private aircraft ac; // reference to aircraft object private route ROUTE; // object reference of current route private bgimg bi; // background image private navpanel np; // panel which displays the numeric data private butpanel bp; // panel containing the control buttons private findroute fr; // find route text box panel private routesel rs; // drop-down list choice route selector private selwp ws; // drop-down list choice waypoint selector private selmap sm; // reference to map scale selection panel private refreshrate rr; // reference to refresh rate selection panel private airmap am; // reference to air map canvas object private Thread TH; // program thread reference variable private Graphics ai; // graphics context reference for AI private Font font; // general font used for writing on applet canvas private FontMetrics fm; // dimensions of lettering (height, leading etc.) private msgpanel mp; // instance reference for message display panel private imgldr il; // instance reference to the image loader private loader ld; // route loader private selgeoid gs; // geoidal ellipse selector private Color bg = new Color(190,215,255), // background colour fg = new Color(255,255,255); // foreground colour for lettering public void init() { // URL (less file name) from where this applet came cb = getCodeBase().toString(); /* Workaround Hotjava & Microsoft intranet machine names where getCodeBase() wrongly seems to return the document base (cira Nov 1999). */ if(!cb.endsWith("/")) { int x = cb.lastIndexOf('/'); if(x != -1) cb = cb.substring(0,x + 1); } /* General font for screen lettering: get its letter dimen- sions etc., leading and base height of the error message text. */ font = new Font("Serif",Font.BOLD,14); fm = getFontMetrics(font); fh = 19; Qy += ((Qh + fh) >> 1); /* Execute the method installSwingWidgets1() on the event-dispatching thread to create the applet's graphics user interface. Wait until all of the code in installSwingWidgets1() has been executed then resume execution on the applet's initialisation thread. */ try { javax.swing.SwingUtilities.invokeAndWait( new Runnable() { public void run() { installSwingWidgets1(); } } ); } // Any erro caught means that the GUI building process failed. catch(Exception e) { showStatus("creating GUI didn't successfully complete"); } /* Create an instance of the image loader and set the fini- shing time for first pass of the applet's run() thread. */ il = new imgldr(this, mp); T = System.currentTimeMillis() + TF; } /* CREATE THE APPLET'S GRAPHICS USER INTERFACE (PHASE 1) Create the appropriate instances of Swing buttons, selectors and choice menus for the applet. NOTE: this must be done as a separate method (in this case installSwingWidgets1()) that is within the scope-space of the applet itself. This code cannot be executed inside the braces {} of the new Runnable above because in there it would not be able to see the applet's local variables. NB: the order of creating the following objects matters for 2 reasons: firstly to optimise the passing of object references (for instance routesel rs needs to be passed the reference to butpanel bp so bp must be created first) and secondly because the order of creation in Swing determines the sandwich level at which it appears on the applet panel (for instance, the background image panel must be created last because it must appear behind everything else). */ private void installSwingWidgets1() { cp = getContentPane(); // get the content pane of the JApplet cp.setLayout(null); /* allow the following panels to be layed outmanually. */ /* Create a small message panel, add it to the applet's con- tents pane and set its size, locate it at bottom right. */ mp = new msgpanel(this,fg); cp.add(mp); mp.setBounds(Lx,Ly,Lw,Lh); bp = new butpanel(this, cp, mp); // button panel rs = new routesel(this, cp, bp); // route selector fr = new findroute(this, cp, rs); // search field mp ws = new selwp(this, cp, mp, bp); // waypoint selector gs = new selgeoid(this, cp); // geoid selector // for positioning the map and refresh-rate selector panels int x = fh + fh - 12, y = fh + fh + fh; /* Create radio buttons for the refresh rate and map scale selectors, add each to its appropriate panel and set its position and size. */ rr = new refreshrate(this); cp.add(rr); rr.setBounds(Px + 7,Py + x,20,y); sm = new selmap(this); cp.add(sm); sm.setBounds(Sx + 7,Sy + x,20,y); } /* Post a request for the method installSwingWidgets2() to be executed on the event-dispatching thread to create the map and navigation inform- ation panels. Don't wait for installSwingWidgets2() to finish execution. Continue immediately on the run() thread TH. This loop won't continue with loading the route information until installSwingWidgets2() has finished and set the Init2finished flag to "true". Continuing immedi- ately ensures that the run() thread TH will not exceed its normal cycling period. */ private void schedulePhase2init() { Init2started = true; // phase 2 initialisation has been scheduled try { javax.swing.SwingUtilities.invokeLater( new Runnable() { public void run() { installSwingWidgets2(); } } ); } catch(Exception e) { showStatus("createGUI phase 2 didn't successfully complete"); } } /* CREATE THE APPLET'S GRAPHICS USER INTERFACE (PHASE 2) NOTE: this must be done as a separate method (in this case installSwing- Widgets2()) that is within the scope-space of the applet itself. This code cannot be executed inside the braces {} of the new Runnable above because in there it would not be able to see the applet's local vari- ables. This phase of the initialisation can only be done after the back- ground images have been downloaded from the server. It therefore has to be scheduled to be run later on the Event Dispatching Thread by the run() thread TH after the images loader has finished. */ void installSwingWidgets2() { ac = new aircraft(); // create an aircraft object bp.setAircraft(ac); // pass aircraft object ref to button panel /* CREATE THE MAP CANVAS WITH THE APPROPRIATE PART OF THE CLOUDS PHOTO AS BACKGROUND */ /* Create air map panel on which to display the map and add it into the applet's window then morph it to fit map portion of applet window. */ am = new airmap(this,fg,ac,sm); cp.add(am); am.setBounds(Mx,My,Mw,Mh); bp.setAirmap(am); // pass its object reference to the button panel sm.setAirmap(am); // pass airmap reference to the map scale selector ws.setAirmap(am); // pass airmap reference to the waypoint selector /* CREATE THE FLIGHT DATA PANEL WITH ITS APPROP- RIATE PART OF THE CLOUDS PHOTO AS BACKGROUND */ /* Create a new numeric 'display panel' object and add it into the applet's window, then morph it to fit into top left area of the applet window. */ np = new navpanel(this,fg,ac); cp.add(np); np.setBounds(Vx,Vy,Vw,Vh); bp.setNavpanel(np); // pass its object reference to the button panel ws.setNavpanel(np); // and to the waypoint selector /* Create the background image panel, add it to the applet1s content pane and set its size to the size of the applet. */ bi = new bgimg(this, Ny, Am, Sx, Sy, Px, Py, fg); cp.add(bi); bi.setBounds(0,0,Aw,Ah); /* Change from black to white lettering on message panel then repaint in order to repaint the Swing widgets onto the background image. */ mp.changeColour(); repaint(); // Create a new instance of the loader then: ld = new loader(cb,this,mp,rs,ws,ac,am,np,gs,bp); mp.setLoader(ld); // pass loader object reference to message panel rs.setLoader(ld); // pass loader object reference to route selector am.setLoader(ld); // set up airmap references within loader object np.setLoader(ld); // set up navpanel references within loader object ws.setLoader(ld); // pass loader object reference to waypoint selector Init2finished = true; // set the 'finished' flag } public void start() { // Start program thread TH = new Thread(this); // by creating the thread object TH.start(); // and starting it running } // [returns a call to run()] // RUN THE AIRCRAFT TRACKING PROGRAM THREAD public void run() { if(il.awaitingImages()) // Return if background images return; // not yet loaded. while(TH == Thread.currentThread()) { // loop while thread is alive runLoop(); // see the following method // get the time left in current time frame current long s = T - System.currentTimeMillis(); if(s < 20) s = 20; // minimum sleep time = 20 milliseconds try{ Thread.sleep(s); } // make thread sleep for time remaining catch(InterruptedException e){} // ignore any exceptions /* Set next update time to current system time plus the currently appropriate update period. */ T = System.currentTimeMillis() + TF; } // end of while() } private void runLoop() { if(!il.imagesLoaded()) // Exit if background photos return; // not yet finish loadin.g if(!Init2finished) { // If 2nd phase of initialization not finished if(!Init2started) // then if it has not yet started schedulePhase2init(); // request for it to be done on the event- return; // dispatching thread then exit. } if(!ld.routeDataLoaded()) // Return if route and waypoints data return; // has not yet finished loading. if(bp.inFlight()) { // if flight currently in progress /* If the aircraft is no longer advancing along its track, it must have reached its destination, so display appropriate message. */ if(!(route.getCurrent().advance())) mp.showMsg("Reached destination.", true, false); am.atualizar(); // update the Air Map np.atualizar(); // update the nav info panel } } public void stop() { TH = null; } // Stop this a program thread /* RE-LOAD THE BACKGROUND IMAGES by killing the old instance of the image loader and creating a new instance to try to reload the images. */ void imgReload(){ il.killTracker(); il = new imgldr(this,mp); } // set map update refresh rate from refresh rate selector void setRefreshRate(long x) { TF = x; } }