/** * Navigation Information Display Panel for Moving Map package * @author Robert J Morton * @version 16 December 1997 */ import javax.swing.*; // Java Swing GUI utilities import java.awt.*; // Java Abstract Windowing Toolkit class navpanel extends JPanel implements navconst { private static final long serialVersionUID = 10L; // what the hell this is for, I don't know! private int fh, // font height (height of a line of text) ne, // end position of numeric field (excluding sign) VY = 3, // top margin for start of text vy, // start height of first numeric value fn; // field number index for the above array private boolean podePaint = false; // can paint/repaint nav data when true private String VALS[] = new String[11], // array for field values SIGN[] = new String[11], // array for corresponding signs wpname = "", // waypoint name buffer sign = ""; // sign of the displayed field value private Color fg; // foreground colour for printing private Font font; // reference to a text font (or typeface) private FontMetrics fm; // type-face dimensions etc. private aircraft ac; // reference to (current) aircraft object private movmap MM; // reference to the movmap applet class private loader ld; // reference to the loader object private static navpanel np; // reference to this nav panel's own object navpanel(movmap MM, Color fg, aircraft ac) { this.MM = MM; // reference to current instance of movmap applet this.fg = fg; // foreground colour this.ac = ac; // reference to (current) aircraft object np = this; // reference to nav panel object // Create a general font for screen lettering and get its dimensions. font = new Font("Serif",Font.BOLD,12); fm = getFontMetrics(font); /* Find the width of the numeric display field comprising the number format, a + or - sign and the field inset distance. */ ne = fm.stringWidth("000:00.00") + fm.stringWidth("+") + 15; fh = 18; // full height of a line of text [leading] } void setLoader(loader ld) {this.ld = ld;} /* RE-DRAW THE PANEL IN THE EVENT OF IT BEING ECLIPSED OR UPDATED The navigational data can be painted only after the background image, the route names and the waypoints of the default route have all been loaded. Painting before this time would mean painting data from variables within class instances that had not yet been created. DefaultsLoaded() returns true when both route names and a full set of default waypoints exist with- in the system. The local flag podePaint is set true once DefaultsLoaed() has returned true for the first time. If it goes false later during the loading of another route's waypoints, repainting of the navigational data can still take place without any problems. */ public void paint(Graphics g) { if(!podePaint) { // if display permission flag is false if(!ld.DefaultsLoaded()) // then if downloading is as yet incomplete return; // exit without doing anything further podePaint = true; // otherwise set the display permission flag } // draw panel's background photograph g.drawImage(movmap.IMG3,0,0,this); vy = VY + fh + fh; // go to line height of first field value g.setFont(font); // activate the required font g.setColor(fg); // set text colour g.drawString(wpname,15,vy); // display the name of the current waypoint vy += fh; // advance down a line for(int i = 0; i < 11; i++) { // for each of the nav data fields if(i == 5) // if this is line 5 vy += fh + fh + 2; // skip 2 lines String v = VALS[i]; // numeric value of this navigation data field /* Display the value and its sign right justified within the numeric field at the proper vertical position for this display line. */ g.drawString(v + SIGN[i],ne - fm.stringWidth(v),vy); vy += fh; // advance downwards to the next line } } /* It is necessary to update the nav data on the run() thread, independently of graphics because otherwise it will upset the repainting of the route selector drop-down list. */ void atualizar() { waypnt wp = waypnt.getCurrent(); // reference of current waypoint object wpname = wp.getName(); // name of current waypoint fn = 0; // waypoint: VALS[0] = convert(wp.getLat(),true); SIGN[0] = sign; // latitude VALS[1] = convert(wp.getLng(),true); SIGN[1] = sign; // longitude VALS[2] = convert(wp.getDst(),false); SIGN[2] = sign; // distance VALS[3] = convert(wp.getrBrg(),false); SIGN[3] = sign; // bearing VALS[4] = convert(wp.getOutRad(),false); // selected outbound radial SIGN[4] = sign; // aircraft VALS[5] = convert(ac.getLat(),true); SIGN[5] = sign; // latitude VALS[6] = convert(ac.getLng(),true); SIGN[6] = sign; // longitude VALS[7] = convert(ac.getSpd(),false); SIGN[7] = sign; // speed VALS[8] = convert(ac.getHdg(),false); SIGN[8] = sign; // heading VALS[9] = convert(ac.getRqH(),false); SIGN[9] = sign; // requ'd hdg VALS[10] = convert(ac.getROT(),false); // rate of turn radians/minute SIGN[10] = sign; repaint(); } private String convert(double c, boolean b) { String v = ""; // display string if(fn == 2) // if it is the third display field v = getDist(c); // field #2 is 'waypoint distance' else if(fn == 7) // else if it is the 8th display field v = getSpeed(c); // field #7 is 'aircraft speed' else if(b) // if flag set it is a latitude or longitude v = getLatLng(c,fn); // so display it as a latitude or longitude else // else it must be a 'bearing' value v = getBrg(c,fn); // so display it in the format of a bearing fn++; // drop to the next dosplay field return v; // return the appropriate display string } // CONVERT AIRCRAFT SPEED FROM DOUBLE TO STRING private String getSpeed(double s) { sign = ""; // speed is always positive // find the number of whole kilometres per hour return "" + (int)Math.floor(s * KphRps); } // CONVERT WAYPOINT DISTANCE FROM DOUBLE TO STRING private String getDist(double c) { double x; if(wpenc.getCurrent().getToFlag()) { x = -c; // if the aircraft receding from the waypoint, sign = "-"; // reverse the sign of the distance } else { // else [aircraft the is receding from the waypoint] x = +c; // so display the distance as positive sign = "+"; } // compute the number of whole kilometres int d = (int)Math.floor(c *= KPR); // Form it into a display string and tack on the tenths of a kilometre. return "" + d + "." + (int)Math.floor(10 * (c - d)); } //CONVERT A LATITUDE OR LONGITUDE INTO A DISPLAY STRING private String getLatLng(double c, int fn) { boolean sc = true; // the sign of c if(c < 0) { // if c is negative c = -c; // make it positive sc = false; // and set its sign negative } // compute the integral number of degrees int d = (int)Math.floor(c *= DPR); // if it is the first or sixth display field, it 'c' is a latitude if(fn == 0 || fn == 5) if(sc) // so if 'c' is positive sign = "N"; // it is North else // else 'c' must be negative sign = "S"; // so it is South else // otherwise, it is a longitude if(sc) // so if 'c' is positive sign = "E"; // it is East else // else 'c' must be negative sign = "W"; // so it is West // compute the residual number of whole minutes of arc int m = (int)Math.floor(c = 60 * (c - d)); String ms = ms = ":" + m; // assume initially that it fits without padding if(m < 10) // but if the number is less than 10 ms = ":0" + m; // pad it with a leading '0' // compute the residual number of hundredths of a minutes of arc int f = (int)Math.floor(100 * (c - m)); String fs = "." + f; // prefix it with a decimal point if(f < 10) // if the number is less than 10 fs = ".0" + f; // pad it with a leading '0' return "" + d + ms + fs; // form it all into a string } // STRING OF A BEARING FIELD IN DEGREES AND THENTHS OF A DEGREE private String getBrg(double c, int fn) { if(fn == 10) { // if displaying [bipolar] rate of turn c *= 60; // convert to degrees per minute if(c < 0) { // if 'c' is negative sign = "-"; // give it a negative sign character c = -c; // and reverse its numeric value to make it positive } else // else the rate of turn is positive sign = "+"; // so give it a '+' sign } else { // otherwise we are displaying a bearing sign = ""; // so it is signless in the range 0-360 if(c < 0) // so if 'c' is negative c += Twoπ; // add 2π to make it a positive value 0-360 } // compute the number of integral degrees int d = (int)Math.floor(c *= DPR); // form it into a string and tack on the tenths of a degree return "" + d + "." + (int)Math.floor(10 * (c - d)); } }