jsattrak.gui.JSatTrak.java Source code

Java tutorial

Introduction

Here is the source code for jsattrak.gui.JSatTrak.java

Source

/*
 * ======= JSatTrak's main GUI interface================================
 * JSatTrak.java  - Shawn E. Gano,  shawn@gano.name
 * =====================================================================
 * Copyright (C) 2007-2009 Shawn E. Gano
 *
 * This file is part of JSatTrak.
 *
 * JSatTrak is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * JSatTrak is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with JSatTrak.  If not, see <http://www.gnu.org/licenses/>.
 * =====================================================================
 *
 * Created Using the NetBeans IDE
 *
 * when building for distrbution include these directories:
 *  data/
 *  plugins/
 *  and for windows use launch4j to make .exe and include in the root: gluegen-rt.dll, jogl.dll, jogl_awt.dll, jogl_cg.dll
 *
 * Using the license feature in netbeans: (use template file: license-JSatTrak.txt)
 * http://bigallan.blogspot.com/2008/02/using-license-functionality-in-netbeans.html
 *
 * Similar Apps:
 * Nasa online tracker for shuttle/ISS:
 * http://spaceflight.nasa.gov/realdata/tracking/
 *
 * J-Track:
 * http://science.nasa.gov/realtime/jtrack/Spacecraft.html
 *
 * good site that has STS TLE for alll mission (past/preset/future planned)
 * http://spaceflight.nasa.gov/realdata/sightings/SSapplications/Post/JavaSSOP/orbit/SHUTTLE/SVPOST.html
 *
 * real time data: (add this main link to website)
 * http://spaceflight.nasa.gov/realdata/
 *
 * Created on July 23, 2007, 4:24 PM
 *
 *  Version 1.1 -- Added low precision position of sun (day/night) 26 Aug 2007
 *  Version 1.2 -- bug fix, uses MOD positions for lat/long calculations instead of J2000 (for satellites and sun)
 *  Version 1.3 -- Abilitiy to draw regions on 2d Map, fixed time rounding errors in time (new Time Classes), code refactored some.
 *  Version 2.0 -- Added 3D Window using WorldWind Java, movie creating tool (new icons)
 *  Version 2.1 -- Added Ground stations and tracking tool, tracking polar plot, pass predictions
 *              4Jan08 - added visibility - Visible/Radar-Night/Sun  -- Elevation constraints working in tracking tool
 *              5Jan  - connected dots in polar plot, go to pass in pass predictor, lat/long lines layer in 3D added
 *                    - scenario epoch setting,
 *  Version 3.0 25Jan - Custom Sats, Mission Designer, Solver Loops
 *              28Jan - Popogator stopping conditions (apogee/perigee)
 *      (final) 9Feb - XML saving, general bug fixes updates, export of custom sat
 *       3.0.1 - 13 Feb2008 - fixed decimal seperator issue, in SDP4
 *       3.0.2 - 13 Feb2008 - fixed problem when missing only some of TLE data files (program freezes)
 *       3.0.3 - 14 Feb2008 - fixed issues of custom sat dialog not closing when unpropogated
 *
 *  Version 3.1.0 - 22 Mar2008 - added bean shell - plugins and command line interface and remote command server / client
 *                               from the command you can access jsattrak object to have access to all of its methods to change things on the fly
 *          3.1.1 - 20 April2008 - updated to swingx 0.9.2 compatibility -removed deleted features (table highlighters). Added Ground Station browser button to toolbar
 *          3.1.2 - 21 April08 - added polical boundaries layer for 3D globe
 *          3.2   - 9 May 2008 - Earth Coverage anylsis, added ability to create movies of any window or entire app, update to WWJ 0.5 (removed WWJ source), set custom clipping plane distances (sim properties)
 *          3.2.1 - (22 May 2008) - unsucessful try to remove dependency on JMF
 *                  ? view following sat (very preliminary) and 3D models?
 *             // bug - does CoverageAnalyzer save and open in 2d window correctly?? use dialog maybe to fix this?
 *  Version 3.5.0 - 7 August 2008 -- Added 3D models, added model view mode - fixed bug: 3d view in ECI reverted back to North up when time advanced (J3DEarthPanel.java, and internal)
 *                                  added full screen exclusive mode, GUI updates - double click on object opens properties, Custom Sat icons in new locations.
 *                                  added nimbus look and feel choice, if java6u10 or greater! (updated" jgoodies, swingx, xstream)
 *                                  Added ability to choose any 2D map image.
 *                                  Added 2D Earth Lights night image effect
 *                                  Added FPS info (press f when a 2D window is active), added memory status bar (+plugin)
 *                                  -- bug? 3d model only stays in full screen mode if two 3d windows are open before? - some quirks with the model view
 *          3.5.1  26 Sept 2008 -- Bug fix - repaint groundtrack when jumping to a time in the mission designer for a custom satellite
 *                                           fixed 3d cone, added get/set slices and stacks parameters, improved 2d window performance by>30% (removed most drawline calls), improved land mass drawing performance
 *                                           added tle-new.txt (new sats), sphere rednering still a bottleneck but reduced divions from 20 to 8, gained 25% performance
 *          3.6 13 Nov 2008    --  Added capibility to run JSatTrak script without starting GUI via passing a command line argument (plus script ability to save images of 2D plot and polar plots)
 *                                 Added app look and feel chooser to the help menu
 *                                  "C:\Documents and Settings\sgano\Desktop\JSatTrak\JSatTrak\noGUIscript.bsh"
 *                              KNOWN ISSUE:  Stored satellites reference Name this may not be unique (and many cases it isn't)! Need to store it by NORAD ID or if a custom sat some other ID
 *          3.6.1 22 Dec 2008  - Marvin joined team - started in on UI improvements drag of 2D zoomed in map, mouse wheel zoom (18 Dec 2008)
 *                    Better compression settings for JPG screenshots and movie creation (22 Dec 2008 - SEG)
 *          3.6.2 11 Jan 2009 -- added a menu to the satellite browser - to load custom satellite TLE data, and create a custom sat
 *          3.7    16 Jan 2009 (unreleased) -- Updates for helping oberservers (based on feed back from Dave Ortiz) - added TLE_user directory for custom tle files that are automatically loaded (with options for category specification)
 *                                                              - Updates to tracking form: polar plot-print,invert colors,limit to horizon, compass points, pass prediction-rize/set Az degrees/compass points, save as csv
 *          3.7.5 23 Mar 2009 -- Change 2D sun terminator resolution to 61 - 51 was reported by a user to cause some unwanted jumps as to which side was filled in, still has issues at times (even for higher res)
 *                               Integrated NASA World Wind Java V0.6 - plus a few new layers (like controls), redid some swing worker routines for thread safteyness
 *                               added substance look and feel (default Raven until Nimbus can work again),
 *                               fixed: saving of 2D coverage windows, 2D night light effects, and main app window location and size saved.
 *                               - 3D external windows now decorated to match look and feel (if avaiblilble)
 *                                   known issue: 3D internal window doesn't work with v0.6 (nimubs Look and feel only)
 *                                   known issue: webstart cannot save movies (no fix)
 *          3.7.6 24 Mar 2009 -- resize fix on 3D external window (in 3.7.5 they could only be made bigger) - set min size on globe panel (0,0) preferred size(50,50)
 *          3.7.7 2 April 2009 -- added Microsfot virtual earth layer/yahoo/open maps from WWJ Experimental code
 *          3.7.8 26 May 2009 - bug fix, close app by file->exit doesn't close process - fixed (bug found by Horst Meyerdierks - SGP4 author)
 *          4.0  21 June 2009 - added sun shading effects in latest WWJ verion of the day. See posts:
 *                                    http://forum.worldwindcentral.com/showthread.php?t=21021&highlight=sun+shading
 *                                    http://patmurris.blogspot.com/2009/04/sunlight-package-for-worldwind-java.html
 *                                  (VOTD - WWJ Broke COLOR OF 3D ORBIT TRACE - fixed - disabled 2D textures in OrbitModelRenderable and EFEFModelRenderable)
 *                                  - Increased precision of GeoFunctions.GeodeticLLA
 *                                  - CORRECTED error in treating SGP4 data as MOD not TEME of date! fixed (and transformation to J2000.0 - found stk prob uses 24 terms in nutation calc)
 *                                  - CORRECTED error in using MOD position for LLA instead of TEME of date (corrected)
 *                                  - added name.gano.astro.coordinates.J2kCoordinateConversion for better coordinate transformations! (phase out old transformations)
 *                                  - now SGP4 prop matches STK very closely (~1m for ISS) and HPROP was compared as well and preformed just as well.
 *                                  - added smooth changes to the 3D view options
 *                                  - coordinate system selection for sat info dialog (J2k, TEME, MOD, TOD)
 *                                  - REPLACED SDP4 (GPL license, see references.txt) with my own coversion of CSSI's SGP4 propagator (name.gano.astro.propogators.sgp4_cssi) (ver: 3 Nov 2008) (same one used in STK 9.0)
 *                                     Note: the above change of SGP4 props and other changes in this release make the saved files from older versions not compatible! Files should now be smaller! (why it gets promoted to v4)
 *                                  - RELICENCED JSatTrak as LGPL!
 *                                  - FILE FORMAT: changes to use zip compression! files are now much smaller!
 *          4.1  10 July 2009    - added AutoClipBasicOrbit view for dynamic clipping plane calculations (23 June)
 *                               - ECI grid, and gui options for grid and clipping planes (moved from sim properties to each 3D window)
 *                               - fixed bug (that surfaced in v4.0) for using the autorun in the coverage tool - needed to make SGP4SatData.java serializable (9 July 2009)
 *                               - Added read ephemeris from file to Custom Satellite Builder (also ability to delete "ini conditions" and add ini conditions nodes (always to top)) (10 Junly 2009)
 *                               - fixed bug where null values were no cloned properly in CustomSatellite - creating exceptions in OrbitModelRenderable/ECI rendering layer
 *          4.1.1 21 Aug 2009    -  Added the current look and feel to the save file / and open file
 *
 *          4.2   - in progress  TODO - fixes and ideas from: Christopher Suski
 *                                      - in the 3D window the sun shading terminator line doesn't wrap around the earth properly when the camera is set to follow an object rather than the earth
 *                                      - a viewport from the ground station to the sat
 *                                      - if you can make room on the Ground station browser button should probably be one the object list window
 *
 *
 *                              Ideas for next versions: (no particular order)
 *                                  - Vectors tool (make them seperate objects) axis, grids, lines, arrows (data providers)
 *                                  - DATA out! - Reports and graphs and exporting of data out of program
 *                                  - 3D "Earth Night Lights" mask / 1/2 sphere transparent night shell
 *                                  - Add Objects (Abstract Satellites) like Moon, Sun, Panets maybe (can set view to center on them as well)?
 *                                  - Satellite Orbit Lifetime Estimator
 *                                  - Launch Vehicle "Simple Ascent" (or missile - Ballistic)
 *                                  - Orbit Dertermination tool
 *                                  - track aircraft? (does this mean I need to rename the app?)
 *                                  - swath planning
 *                                  - dyanmic changing of clipping planes when in different viewing modes -- and Exponential zooming! (see my jogl 3d soloar system)
 *        
 */
// notes: not good to use rk78 in a solver loop because direvatives inaccurate, because solution changes slightly near end.?
//
// NOTE: in beanshell jar (i.e. bsh-2.0b4.jar) need to replace desktop.bsh, with one included with this source -- it allows bean shell desktop to be reopened
//       THIS BEANSHELL problem may be fixed in a newer version as I wrote the authore about this and gave him my solution
//
// run from linux: add to VM Options
// -Djava.library.path="/home/sgano/Desktop/sgano/Java/Libraries/"
//
// To make jogl display correctly in Ubuntu Linux:
// sudo apt-get install driconf
// run driconf and set "Enable S3TC"
//
// =====================
// changes to WWJ to make internal windows work:
// http://forum.worldwindcentral.com/showthread.php?t=12360&highlight=WorldWindowGLJPanel
//  in (WorldWindowGLAutoDrawable.initDrawable()) comment line: this.drawable.setAutoSwapBufferMode(fals e);
// TerrainProfileLayer:  -- works now my bug reports and fixes are in the release!
// - Fix clipping plane problem:
// in AbstractView.java (gov.nasa.worldwind.view)  --  change the code to this:
// private static final double MIN_FAR_CLIP_DISTANCE = 10000000000d;
// THIS SHOULD BE FIXED in WWJ >v0.4.1 (see: http://issues.worldwind.arc.nasa.gov/browse/WWJ-9)
//  I STILL WANT LIGHTING ADDED TO WWJ - SO I CAN SIMULATE sun/dark side of earth!!
//  - and also views for model centric views... but I think that will work in the next release too.
//
// Jar signing commands:
// NOTE: to unsign a jar (such as worldwind.jar) - open jar in winzip and delete everything in the meta-inf directory
//        then resign -- fixed issue with "web start complaining about jars signed with multiple keys)
// /usr/java/jdk1.6.0_01/bin/keytool -genkey -keystore myKeys -alias jdc
// /usr/java/jdk1.6.0_01/bin/jarsigner -keystore myKeys JSatTrak.jar jdc
package jsattrak.gui;

import static name.gano.file.FileUtilities.getExtension;
import edu.cusat.gs.gui.GroundSystemsPanel;

//unused imports
/*import edu.cusat.gs.rfgateway.Callsign;
import edu.cusat.gs.rfgateway.GatewayMgr;
import edu.cusat.gs.rfgateway.GatewayMgrListener;
import edu.cusat.gs.ts2000.KenwoodTs2kController;*/

import edu.cusat.gs.util.LogFileWriter;
import gov.nasa.worldwind.awt.WorldWindowGLCanvas;

import java.awt.AWTException;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Robot;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.awt.image.BufferedImage;
import java.beans.PropertyVetoException;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.Serializable;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Set;
import java.util.TimeZone;
import java.util.Vector;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;

import javax.swing.AbstractAction;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JDesktopPane;
import javax.swing.JDialog;
import javax.swing.JFileChooser;
import javax.swing.JInternalFrame;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JRootPane;
import javax.swing.JSeparator;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.event.InternalFrameEvent;
import javax.swing.event.InternalFrameListener;
import javax.swing.filechooser.FileNameExtensionFilter;

import jguiserver.GuiServer;
import jsattrak.about.AboutDialog;
import jsattrak.coverage.CoverageAnalyzer;
import jsattrak.coverage.JSatTrakTimeDependent;
import jsattrak.objects.AbstractSatellite;
import jsattrak.objects.CustomSatellite;
import jsattrak.objects.GroundStation;
import jsattrak.objects.SatelliteTleSGP4;
import jsattrak.objects.SunSat;
import jsattrak.utilities.ConsoleDialog;
import jsattrak.utilities.GsListener;
import jsattrak.utilities.J2DEarthPanelSave;
import jsattrak.utilities.J3DEarthComponent;
import jsattrak.utilities.J3DEarthlPanelSave;
import jsattrak.utilities.JstSaveClass;
import jsattrak.utilities.LafChanger;
import jsattrak.utilities.SatListener;
import jsattrak.utilities.SatPropertyPanelSave;
import jsattrak.utilities.TLE;
import jsattrak.utilities.TLEDownloader;
import name.gano.astro.bodies.Sun;
import name.gano.astro.time.Time;
import name.gano.file.FileTypeFilter;
import name.gano.file.SaveImageFile;
import bsh.Interpreter;
import bsh.util.JConsole;
import bsh.util.NameCompletionTable;

import com.jgoodies.looks.plastic.PlasticLookAndFeel;
import com.jgoodies.looks.plastic.theme.ExperienceBlue;
import com.thoughtworks.xstream.XStream;
import commandclient.CommandClientGUI;

/**
 * 
 * @author Shawn E. Gano, shawn@gano.name
 */
public final class JSatTrak extends javax.swing.JFrame
        implements InternalFrameListener, WindowListener, Serializable {

    /** Version of app **/
    private String versionString = "Version 4.1.1  (21 August 2009)"; // Version of app

    // Vector to store all the 2D windows -- so they can all be updated
    // Vector<J2DEarthPanel> twoDWindowVec = new Vector();
    Vector<J2DEarthPanel> twoDWindowVec = new Vector<J2DEarthPanel>();
    int twoDWindowCount = 0; // running count (for naming)
    // Satellite property vector to store all the windows (so they can be
    // updated)
    Vector<SatPropertyPanel> satPropWindowVec = new Vector<SatPropertyPanel>();
    // 3D windows
    private Vector<J3DEarthInternalPanel> threeDInternalWindowVec = new Vector<J3DEarthInternalPanel>();
    int threeDInternalWindowCount = 0; // running count (for naming)
    private Vector<J3DEarthPanel> threeDWindowVec = new Vector<J3DEarthPanel>();
    int threeDWindowCount = 0; // running count (for naming)

    // Tracking Tool Dialogs
    private Vector<JTrackingPanel> trackingWindowVec = new Vector<JTrackingPanel>();

    // sat panel - show list of satellites
    JObjectListPanel objListPanel;

    //GroundSystemsPanel - allows communication with the satellite
    GroundSystemsPanel groundSystemsPanel;

    // Sun object
    private Sun sun;

    // ----- TIME parameters --------------------
    // UTCG
    // JulianDay currentJulianDate = new JulianDay(); // current sim or real
    // time (Julian Date)
    Time currentJulianDate = new Time(); // current sim or real time (Julian
    // Date)

    // animation parameters
    private Timer playTimer;
    private boolean stopHit = false;
    /** refresh rate for real time animation */
    private int realTimeAnimationRefreshRateMs = 1000;

    /**
     * refresh rate for non-real time animation (current)Milliseconds this
     * should be an option somewhere!! - determines CPU used in animation
     */
    private int nonRealTimeAnimationRefreshRateMs = 50;
    private int animationRefreshRateMs = nonRealTimeAnimationRefreshRateMs; //

    /**
     * dt in Days per animation step/time update
     */
    private double animationSimStepSeconds = 1.0;

    /**
     * 1= forward, -1=backward, =0-no animation step, but can update time
     * (esentially a graphic ini or refresh)
     */
    int currentPlayDirection = 0;

    // these are listed in seconds
    double[] timeStepSpeeds = new double[] { 0.0001, 0.001, 0.01, 0.1, 0.25, 0.5, 1.0, 2.0, 5.0, 10.0, 30.0, 60.0,
            300.0, 600.0, 1800.0, 3600.0, 43200.0, 86400.0, 604800.0, 2419200.0, 31556926.0 };
    private int currentTimeStepSpeedIndex = 11;

    // date formats for displaying and reading in
    public final SimpleDateFormat dateformat = new SimpleDateFormat("dd MMM yyyy HH:mm:ss.SSS z");
    private SimpleDateFormat dateformatShort1 = new SimpleDateFormat("dd MMM y H:m:s.S z");
    private SimpleDateFormat dateformatShort2 = new SimpleDateFormat("dd MMM y H:m:s z"); // no Milliseconds

    // store local time zone for printing
    TimeZone localTZ = TimeZone.getDefault();

    // save file
    private String fileSaveAs = null; // starts out null

    /** boolean to see if 3D is working */
    boolean threeDWorking = true; // assume it is true?

    /**
     * scenario epoch time settings uses current time for scenario epoch (reset
     * button)
     */
    private boolean epochTimeEqualsCurrentTime = true;

    /**
     * scenario epoch if epochTimeisCurrentTime = false
     */
    private Time scenarioEpochDate = new Time();

    // icons for animations
    private final Icon idleIcon;
    private final Icon[] busyIcons = new Icon[15];
    private int busyIconIndex = 0;
    Timer messageTimer;
    Timer busyIconTimer;

    // WWJ online/offline mode
    private boolean wwjOfflineMode = false;

    // console for displaying things written to system.out
    ConsoleDialog console;

    // interpreter for bean shell
    JConsole commandConsole = new JConsole();
    public Interpreter beanShellInterp = new Interpreter(commandConsole);

    // time dependent objects that should be update when time is updated -- NEED
    // TO BE SAVED?
    Vector<JSatTrakTimeDependent> timeDependentObjects = new Vector<JSatTrakTimeDependent>();

    // coverage anaylzer tool (default null, until tool opened)
    private transient CoverageAnalyzer coverageAnalyzer;

    // WorldWindGLCanvas so all 3D windows can share resources like 3D models
    private WorldWindowGLCanvas wwd; // intially null - only created when needed

    // FPS variables
    private long lastFPSms;
    private double fpsAnimation;

    /** Creates new form JSatTrak */
    public JSatTrak() {
        boolean usingNimbus = setLookAndFeel();

        // setup window position and icon
        setLocationByPlatform(true);

        // set icon
        setIconImage(
                Toolkit.getDefaultToolkit().getImage(getClass().getResource("/icons/logo/JSatTrakLogo_32.png")));

        // ini GUI
        initComponents();

        // show shadow behind menus
        // Options.setPopupDropShadowEnabled(true);

        // setup look for toolbars:
        // jToolBar.putClientProperty("JToolBar.isRollover", Boolean.TRUE);

        // make it scroll.. need to be smarter about this though!
        // mainDesktopPane.setPreferredSize(new Dimension(600,200));

        // create Sun object
        sun = new Sun(currentJulianDate.getMJD());

        // create Satelite List Internal Frame (that can never be closed)
        objListPanel = new JObjectListPanel(this);

        // add it to the internal Frame
        satListInternalFrame.setContentPane(objListPanel);

        // // TEST
        // JObjectListInternalFrame t = new
        // JObjectListInternalFrame(satHash,gsHash,this);
        // this.addInternalFrame(t);

        // by default open a new 2D window to start
        createNew2dWindow();

        // first call to update time to current time:
        currentJulianDate.update2CurrentTime(); // update();// =
        // getCurrentJulianDate(); //
        // ini time

        // just a little touch up -- remove the milliseconds from the time
        int mil = currentJulianDate.get(Time.MILLISECOND);
        // remove the milliseconds (so it shows an even second)
        currentJulianDate.add(Time.MILLISECOND, 1000 - mil);

        // set time string format
        currentJulianDate.setDateFormat(dateformat);
        scenarioEpochDate.setDateFormat(dateformat);

        updateTime(); // update plots

        // update gui with timestep
        updateTimeStepsDataGUI();
        groundSystemsPanel = null;
        // auto select local timezon button
        //        localTimeZoneCheckBox.doClick();

        //this.setVisible(true); // only needed to debug if there is a problem below this point in constructor

        // Default sats in list: -- load if TLE data is local
        try {
            TLEDownloader tleDownloader = new TLEDownloader();
            if ((new File(tleDownloader.getLocalPath()).exists())
                    && (new File(tleDownloader.getTleFilePath(0)).exists())) {
                addSat2ListByName("ISS (ZARYA)             ");
                sats.get("ISS (ZARYA)             ").set3DModelPath("isscomplete/iss_complete.3ds");// set default 3d model
            }
        } catch (Exception e) {
            System.err.println("Error loading Local Default TLE Data");
        }

        sats.put("Sun", new SunSat());

        // Add ground stations
        objListPanel.addGS2List(new GroundStation("HB Observatory",
                new double[] { 42F + (27F + 29.25F / 60F) / 60F, -76F - (23F + 4.87F / 60F) / 60F, 530 },
                currentJulianDate.getJulianDate()));
        objListPanel.addGS2List(new GroundStation("Kwajalein, Marshall Islands",
                new double[] { 8F + (43F + 11.46F / 60F) / 60F, +167F + (43F + 24.46F / 60F) / 60F, 5 },
                currentJulianDate.getJulianDate()));
        objListPanel.addGS2List(new GroundStation("Colorado Springs",
                new double[] { 38F + (46F + 45F / 60F) / 60F, -104F - (42F + 6F / 60F) / 60F, 1609 },
                currentJulianDate.getJulianDate()));
        objListPanel.addGS2List(new GroundStation("Redondo Beach, California",
                new double[] { 33F + (53F + 21F / 60F) / 60F, -118F - (22F + 19F / 60F) / 60F, 22 },
                currentJulianDate.getJulianDate()));
        // TEST NOT WORKING!!!!!
        // test if 3d JOGL is working
        // try {
        // new GLCanvas();
        // } catch (Exception e) {
        // System.out.println("3D ERROR!");
        // JOptionPane.showInternalMessageDialog(mainDesktopPane,
        // "3D Error (Check your JOGL Installation):\n " + e.toString(),
        // "ERROR", JOptionPane.ERROR_MESSAGE);
        //
        // threeDWorking = false;
        // update3Dconfig();
        // }

        // create timers for animations and status messages
        int messageTimeout = 60000; // 1 min
        messageTimer = new Timer(messageTimeout, new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                statusLabel.setText("");
            }
        });
        messageTimer.setRepeats(false);

        // set idle busy icons
        idleIcon = new javax.swing.ImageIcon(getClass().getResource("/icons/busyicons/idle-icon.png"));

        // busy-icon0.png
        for (int i = 0; i < 15; i++) {
            busyIcons[i] = new javax.swing.ImageIcon(
                    getClass().getResource("/icons/busyicons/busy-icon" + i + ".png"));
        }

        // create timer for anumation, animation_rate is the first value
        busyIconTimer = new Timer(30, new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                busyIconIndex = (busyIconIndex + 1) % busyIcons.length;
                statusAnimationLabel.setIcon(busyIcons[busyIconIndex]);
            }
        });

        // try it out status messages
        setStatusMessage("Welcome to JSatTrak " + versionString + ", by Shawn E. Gano");

        // save root app to Bean Shell interperator
        try {

            // name completion
            final NameCompletionTable nct = new NameCompletionTable();
            nct.add(beanShellInterp.getNameSpace());
            commandConsole.setNameCompletion(nct);

            // start the interperator in its own thread
            final Thread thread = new Thread(beanShellInterp, "BeanShell");
            thread.setDaemon(true);
            thread.start();

            // new Thread( beanShellInterp ).start();
            beanShellInterp.set("jsattrak", this);

            // set the scope so it is in this object (no need to use jsattrak.
            // all the time)
            // doesn't work this way?
            // beanShellInterp.eval("setNameSpace(jsattrak.namespace)");

            // set this so closing the bean shell Desktop doesn't close the
            // whole app
            beanShellInterp.eval("bsh.system.shutdownOnExit = false;");

            // so bean shell returns values upon evaluation
            // doesn't seem to work
            // beanShellInterp.eval("show();");

        } catch (Exception e) {
            System.out.println("Error saving main object to bean shell:" + e.toString());
        }

        // make the GUI large by default -- Nimbus look and feel needs it!
        this.setSize(this.getWidth(), 765);

        // display window in the center of the screen
        Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();
        // Point p = this.getLocation();
        int x = (dim.width - this.getWidth()) / 2;
        int y = (dim.height - this.getHeight()) / 2;
        // System.out.println("h" + this.getHeight());
        this.setBounds(x, y, this.getWidth(), this.getHeight() + 1);

        // check for plugin scripts
        checkAndInstallPlugins();

        // Debug for coverage module - for now create it and add it to 2D window
        /*        if (false) {
        // start after first step
        coverageAnalyzer = new CoverageAnalyzer(currentJulianDate);
        // CoverageAnalyzer coverageAnalyzer = new
        // CoverageAnalyzer(currentJulianDate,timeStepSpeeds[currentTimeStepSpeedIndex]/(24.0*60*60),satHash);
        // add it to the panel
        twoDWindowVec.get(0).addRenderableObject(coverageAnalyzer);
        coverageAnalyzer
                .addSatToCoverageAnaylsis("ISS (ZARYA)             ");
        // coverageAnalyzer.addSatToCoverageAnaylsis("test");
        // add object to time updates
        timeDependentObjects.add(coverageAnalyzer);
        twoDWindowVec.get(0).setShowLatLonLines(false);
        twoDWindowVec.get(0).setDrawSun(false);
        twoDWindowVec.get(0).setShowDateTime(false);
                }*/

        // fire resize function - to correct
        // "dissapearing or transparent windows" issues
        int sizeJump = 1;
        this.setSize(this.getSize().width + sizeJump, this.getSize().height + sizeJump);
        this.setSize(this.getSize().width - sizeJump, this.getSize().height - sizeJump);

        // DEBUG - testing earht lightsz
        // this.twoDWindowVec.get(0).setShowEarthLightsMask(true);

        // for some reason nimbus has to be reapplied to work correctly
        if (usingNimbus) {
            try {
                UIManager.setLookAndFeel("com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel");
                // apply look and feel over current L&F (otherwise nimbus shows
                // up incorrectly)
                SwingUtilities.updateComponentTreeUI(this);
            } catch (Exception ex) {
                System.out.println("Sorry no Nimbus LookAndFeel needs java 6u10 or higher!");
                // ex.printStackTrace();
            }
        } // if using nimbus

        // create the console
        console = new ConsoleDialog(this, false);
        //Create the logwriter
        new LogFileWriter();

        // Set it in real time mode
        //        realTimeModeCheckBox.setSelected(true);
        //        playButton.doClick();
    } // constructor

    /**
     * @return true if the user has java 6u10 (and therefore Nimbus is
     *         supported/used)
     */
    private boolean setLookAndFeel() {
        boolean usingNimbus = false;
        try {
            // TEMP UNTIL NIMBUS WORKS WITH INTERNAL WINDOWS
            String laf = "org.jvnet.substance.skin.Substance" + "Raven" + "LookAndFeel";
            LafChanger.changeLaf(this, laf);
        } catch (Exception ex2) {
            try {
                UIManager.setLookAndFeel("com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel"); //
                usingNimbus = true;
            } catch (Exception ex1) // default using jgoodies looks plastic
            // theme
            {
                PlasticLookAndFeel.setPlasticTheme(new ExperienceBlue());
                PlasticLookAndFeel.setTabStyle("Metal"); // makes tabes look
                // much better

                try {
                    UIManager.setLookAndFeel(new PlasticLookAndFeel());
                } catch (Exception ex) {
                    ex.printStackTrace();
                }
            }
        }
        return usingNimbus;
    }

    public void checkAndInstallPlugins() {
        // first clean out all current plugins displayed (in case it is
        // refreshed)
        pluginMenu.removeAll();

        // see if plugin directory exisits
        File rootFile = new File("plugins");

        // make sure plugins exist and is a dirctory
        if (rootFile.exists() && rootFile.isDirectory()) {
            System.out.println("Plugin Directory Exists:");

            // create action for plugin menu items
            AbstractAction pluginAction = new AbstractAction() {
                private static final long serialVersionUID = -6485077949996968834L;

                public void actionPerformed(ActionEvent e) {
                    runPluginAction(e);
                }
            };

            // for each file in plugin dir with extension .bsh
            for (String fileName : rootFile.list(new FileTypeFilter("bsh"))) {
                String menuName = fileName.substring(0, fileName.length() - 4);

                JMenuItem newPluginMenuItem = new JMenuItem(menuName);
                pluginMenu.add(newPluginMenuItem);
                System.out.println("Loading plugin: " + fileName);

                newPluginMenuItem.setAction(pluginAction); // add action
                newPluginMenuItem.setText(menuName); // reset name on menu item
                // (since action over
                // writes it)
            }

        } // plugin loading

        // add seperator
        pluginMenu.add(new JSeparator());

        AbstractAction refreshPluginAction = new AbstractAction("Refresh Plugins List") {
            private static final long serialVersionUID = -1949562529486925003L;

            public void actionPerformed(ActionEvent e) {
                checkAndInstallPlugins();
            }
        };
        pluginMenu.add(new JMenuItem(refreshPluginAction));

        // load in all plugins with right file extension

    } // checkAndInstallPlugins

    /**
     * This method is called from within the constructor to initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is always
     * regenerated by the Form Editor.
     */
    // <editor-fold defaultstate="collapsed"
    // <editor-fold defaultstate="collapsed"
    // <editor-fold defaultstate="collapsed"
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        mainPanel = new javax.swing.JPanel();
        mainToolBar = new javax.swing.JToolBar();
        saveButton = new javax.swing.JButton();
        openSatBrowserButton = new javax.swing.JButton();
        openGSbrowser = new javax.swing.JButton();
        jButtonTriton = new javax.swing.JButton();
        resetTimeButton = new javax.swing.JButton();
        playBackButton = new javax.swing.JButton();
        stepBackButton = new javax.swing.JButton();
        stopButton = new javax.swing.JButton();
        stepForwardTimeButton = new javax.swing.JButton();
        playButton = new javax.swing.JButton();
        incrementTimeStepButton = new javax.swing.JButton();
        timeStepLabel = new javax.swing.JLabel();
        decementTimeStepButton = new javax.swing.JButton();
        dateTextField = new javax.swing.JTextField();
        realTimeModeCheckBox = new javax.swing.JCheckBox();
        jLabel2 = new javax.swing.JLabel();
        localTimeZoneCheckBox = new javax.swing.JCheckBox();
        zoomIntoggleButton = new javax.swing.JToggleButton();
        zoomOuttoggleButton = new javax.swing.JToggleButton();
        recenterToggleButton = new javax.swing.JToggleButton();
        screenShotButton = new javax.swing.JButton();
        createMovieButton = new javax.swing.JButton();
        toolbar3DWindowButton = new javax.swing.JButton();
        desktopPanel = new javax.swing.JPanel();
        desktopScrollPane = new javax.swing.JScrollPane();
        mainDesktopPane = new javax.swing.JDesktopPane();
        satListInternalFrame = new javax.swing.JInternalFrame();
        statusPanel = new javax.swing.JPanel();
        jSeparator7 = new javax.swing.JSeparator();
        statusLabel = new javax.swing.JLabel();
        statusProgressBar = new javax.swing.JProgressBar();
        statusAnimationLabel = new javax.swing.JLabel();
        jMenuBar1 = new javax.swing.JMenuBar();
        fileMenu = new javax.swing.JMenu();
        newMenuItem = new javax.swing.JMenuItem();
        openMenuItem = new javax.swing.JMenuItem();
        closeMenuItem = new javax.swing.JMenuItem();
        saveMenuItem = new javax.swing.JMenuItem();
        saveAsMenuItem = new javax.swing.JMenuItem();
        jSeparator2 = new javax.swing.JSeparator();
        exitMenuItem = new javax.swing.JMenuItem();
        simMenu = new javax.swing.JMenu();
        simPropMenuItem = new javax.swing.JMenuItem();
        jSeparator3 = new javax.swing.JSeparator();
        realTimeMenuItem = new javax.swing.JMenuItem();
        nonRealTimeMenuItem = new javax.swing.JMenuItem();
        jSeparator4 = new javax.swing.JSeparator();
        utcTimeMenuItem = new javax.swing.JMenuItem();
        localTimeMenuItem = new javax.swing.JMenuItem();
        utilitiesMenu = new javax.swing.JMenu();
        tleLoaderMenuItem = new javax.swing.JMenuItem();
        jSeparator6 = new javax.swing.JSeparator();
        trackToolMenuItem = new javax.swing.JMenuItem();
        coverageMenuItem = new javax.swing.JMenuItem();
        jSeparator10 = new javax.swing.JSeparator();
        movieWholeAppMenuItem = new javax.swing.JMenuItem();
        jSeparator11 = new javax.swing.JSeparator();
        commandServerMenuItem = new javax.swing.JMenuItem();
        commandClientMenuItem = new javax.swing.JMenuItem();
        new3DwindowMenu = new javax.swing.JMenu();
        showSatBrowser = new javax.swing.JMenuItem();
        showGSBrowserMenuItem = new javax.swing.JMenuItem();
        jSeparator5 = new javax.swing.JSeparator();
        new2DWindowMenuItem = new javax.swing.JMenuItem();
        newInternal3DWindowMenuItem = new javax.swing.JMenuItem();
        newExternal3DWindowMenuItem = new javax.swing.JMenuItem();
        jSeparator1 = new javax.swing.JSeparator();
        twoDwindowPropMenuItem = new javax.swing.JMenuItem();
        jSeparator8 = new javax.swing.JSeparator();
        consoleMenuItem = new javax.swing.JMenuItem();
        jSeparator9 = new javax.swing.JSeparator();
        commandShellMenuItem = new javax.swing.JMenuItem();
        commandShellDesktopMenuItem = new javax.swing.JMenuItem();
        pluginMenu = new javax.swing.JMenu();
        helpMenu = new javax.swing.JMenu();
        sysPropsMenuItem = new javax.swing.JMenuItem();
        lookFeelMenuItem = new javax.swing.JMenuItem();
        aboutMenuItem = new javax.swing.JMenuItem();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        setTitle("JSatTrak"); // NOI18N

        mainPanel.setLayout(new java.awt.BorderLayout());

        mainToolBar.setRollover(true);

        saveButton
                .setIcon(new javax.swing.ImageIcon(getClass().getResource("/icons/gnome_2_18/document-save.png"))); // NOI18N
        saveButton.setToolTipText("Save"); // NOI18N
        saveButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                saveButtonActionPerformed(evt);
            }
        });
        mainToolBar.add(saveButton);

        openSatBrowserButton
                .setIcon(new javax.swing.ImageIcon(getClass().getResource("/icons/custom/sat_icon_tle.png"))); // NOI18N
        openSatBrowserButton.setToolTipText("Open Satellite Browser"); // NOI18N
        openSatBrowserButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                openSatBrowserButtonActionPerformed(evt);
            }
        });
        mainToolBar.add(openSatBrowserButton);

        openGSbrowser
                .setIcon(new javax.swing.ImageIcon(getClass().getResource("/icons/custom/groundStation_obj.png"))); // NOI18N
        openGSbrowser.setToolTipText("Open Ground Station Browser");
        openGSbrowser.setFocusable(false);
        openGSbrowser.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        openGSbrowser.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        openGSbrowser.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                openGSbrowserActionPerformed(evt);
            }
        });
        mainToolBar.add(openGSbrowser);

        //jButtonTriton.setText("Triton");
        jButtonTriton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/icons/custom/Triton_logo.png"))); // NOI18N
        jButtonTriton.setToolTipText("Open Triton"); // NOI18N
        jButtonTriton.setFocusable(false);
        jButtonTriton.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        jButtonTriton.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        jButtonTriton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jButtonTritonActionPerformed(evt);
            }
        });
        mainToolBar.add(jButtonTriton);

        resetTimeButton.setIcon(
                new javax.swing.ImageIcon(getClass().getResource("/icons/gnome_2_18/media-seek-backward.png"))); // NOI18N
        resetTimeButton.setToolTipText("Reset To Current Time or Epoch"); // NOI18N
        resetTimeButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                resetTimeButtonActionPerformed(evt);
            }
        });
        mainToolBar.add(resetTimeButton);

        playBackButton.setIcon(new javax.swing.ImageIcon(
                getClass().getResource("/icons/gnome_2_18/media-playback-playbackwards.png"))); // NOI18N
        playBackButton.setToolTipText("Play Backwards"); // NOI18N
        playBackButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                playBackButtonActionPerformed(evt);
            }
        });
        mainToolBar.add(playBackButton);

        stepBackButton.setIcon(
                new javax.swing.ImageIcon(getClass().getResource("/icons/gnome_2_18/media-skip-backward.png"))); // NOI18N
        stepBackButton.setToolTipText("Step Backwards"); // NOI18N
        stepBackButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                stepBackButtonActionPerformed(evt);
            }
        });
        mainToolBar.add(stepBackButton);

        stopButton.setIcon(
                new javax.swing.ImageIcon(getClass().getResource("/icons/gnome_2_18/media-playback-stop.png"))); // NOI18N
        stopButton.setToolTipText("Stop Animation"); // NOI18N
        stopButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                stopButtonActionPerformed(evt);
            }
        });
        mainToolBar.add(stopButton);

        stepForwardTimeButton.setIcon(
                new javax.swing.ImageIcon(getClass().getResource("/icons/gnome_2_18/media-skip-forward.png"))); // NOI18N
        stepForwardTimeButton.setToolTipText("Step Forwards"); // NOI18N
        stepForwardTimeButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                stepForwardTimeButtonActionPerformed(evt);
            }
        });
        mainToolBar.add(stepForwardTimeButton);

        playButton.setIcon(
                new javax.swing.ImageIcon(getClass().getResource("/icons/gnome_2_18/media-playback-start.png"))); // NOI18N
        playButton.setToolTipText("Play Forwards"); // NOI18N
        playButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                playButtonActionPerformed(evt);
            }
        });
        mainToolBar.add(playButton);

        incrementTimeStepButton.setIcon(
                new javax.swing.ImageIcon(getClass().getResource("/icons/gnome_2_18/view-sort-ascending.png"))); // NOI18N
        incrementTimeStepButton.setToolTipText("Faster"); // NOI18N
        incrementTimeStepButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                incrementTimeStepButtonActionPerformed(evt);
            }
        });
        mainToolBar.add(incrementTimeStepButton);

        timeStepLabel.setForeground(new java.awt.Color(102, 102, 102));
        timeStepLabel.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
        timeStepLabel.setText("10s"); // NOI18N
        timeStepLabel.setToolTipText("Time Step [sec]"); // NOI18N
        timeStepLabel.setMaximumSize(new java.awt.Dimension(40, 14));
        timeStepLabel.setMinimumSize(new java.awt.Dimension(40, 14));
        mainToolBar.add(timeStepLabel);

        decementTimeStepButton.setIcon(
                new javax.swing.ImageIcon(getClass().getResource("/icons/gnome_2_18/view-sort-descending.png"))); // NOI18N
        decementTimeStepButton.setToolTipText("Slower"); // NOI18N
        decementTimeStepButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                decementTimeStepButtonActionPerformed(evt);
            }
        });
        mainToolBar.add(decementTimeStepButton);

        dateTextField.setText("Date/Time"); // NOI18N
        dateTextField.setToolTipText("UTC Date/Time"); // NOI18N
        dateTextField.setPreferredSize(new java.awt.Dimension(200, 27));
        dateTextField.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                dateTextFieldActionPerformed(evt);
            }
        });
        mainToolBar.add(dateTextField);

        realTimeModeCheckBox.setToolTipText("Real Time Mode"); // NOI18N
        realTimeModeCheckBox.setBorder(javax.swing.BorderFactory.createEmptyBorder(0, 0, 0, 0));
        realTimeModeCheckBox.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                realTimeModeCheckBoxActionPerformed(evt);
            }
        });
        mainToolBar.add(realTimeModeCheckBox);

        jLabel2.setIcon(new javax.swing.ImageIcon(getClass().getResource("/icons/other/xclock.png"))); // NOI18N
        jLabel2.setToolTipText("Real Time Mode"); // NOI18N
        mainToolBar.add(jLabel2);

        localTimeZoneCheckBox.setText("Local TZ"); // NOI18N
        localTimeZoneCheckBox.setToolTipText("Display Local Time Zone? (Otherwise UTC)"); // NOI18N
        localTimeZoneCheckBox.setBorder(javax.swing.BorderFactory.createEmptyBorder(0, 0, 0, 0));
        localTimeZoneCheckBox.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                localTimeZoneCheckBoxActionPerformed(evt);
            }
        });
        mainToolBar.add(localTimeZoneCheckBox);

        zoomIntoggleButton
                .setIcon(new javax.swing.ImageIcon(getClass().getResource("/icons/gnome_2_18/zoom-in.png"))); // NOI18N
        zoomIntoggleButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                zoomIntoggleButtonActionPerformed(evt);
            }
        });
        mainToolBar.add(zoomIntoggleButton);

        zoomOuttoggleButton
                .setIcon(new javax.swing.ImageIcon(getClass().getResource("/icons/gnome_2_18/zoom-out.png"))); // NOI18N
        zoomOuttoggleButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                zoomOuttoggleButtonActionPerformed(evt);
            }
        });
        mainToolBar.add(zoomOuttoggleButton);

        recenterToggleButton
                .setIcon(new javax.swing.ImageIcon(getClass().getResource("/icons/gnome_2_18/zoom-best-fit.png"))); // NOI18N
        recenterToggleButton.setToolTipText("2D Recenter"); // NOI18N
        recenterToggleButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                recenterToggleButtonActionPerformed(evt);
            }
        });
        mainToolBar.add(recenterToggleButton);

        screenShotButton.setIcon(
                new javax.swing.ImageIcon(getClass().getResource("/icons/gnome_2_18/applets-screenshooter.png"))); // NOI18N
        screenShotButton.setToolTipText("Take Screen Shot of Current Window"); // NOI18N
        screenShotButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                screenShotButtonActionPerformed(evt);
            }
        });
        mainToolBar.add(screenShotButton);

        createMovieButton.setIcon(
                new javax.swing.ImageIcon(getClass().getResource("/icons/other/applications-multimedia.png"))); // NOI18N
        createMovieButton.setToolTipText("Create Movie of Selected Window");
        createMovieButton.setFocusable(false);
        createMovieButton.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        createMovieButton.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        createMovieButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                createMovieButtonActionPerformed(evt);
            }
        });
        mainToolBar.add(createMovieButton);

        toolbar3DWindowButton
                .setIcon(new javax.swing.ImageIcon(getClass().getResource("/icons/other/emblem-web.png"))); // NOI18N
        toolbar3DWindowButton.setToolTipText("New 3D Window (External)");
        toolbar3DWindowButton.setFocusable(false);
        toolbar3DWindowButton.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        toolbar3DWindowButton.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        toolbar3DWindowButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                toolbar3DWindowButtonActionPerformed(evt);
            }
        });
        mainToolBar.add(toolbar3DWindowButton);

        mainPanel.add(mainToolBar, java.awt.BorderLayout.NORTH);

        desktopPanel.setAutoscrolls(true);

        desktopScrollPane.setAutoscrolls(true);

        mainDesktopPane.setDoubleBuffered(true);

        satListInternalFrame.setIconifiable(true);
        satListInternalFrame.setMaximizable(true);
        satListInternalFrame.setResizable(true);
        satListInternalFrame.setTitle("Object List"); // NOI18N
        satListInternalFrame
                .setFrameIcon(new javax.swing.ImageIcon(getClass().getResource("/icons/logo/JSatTrakLogo_16.png"))); // NOI18N
        satListInternalFrame.setVisible(true);

        javax.swing.GroupLayout satListInternalFrameLayout = new javax.swing.GroupLayout(
                satListInternalFrame.getContentPane());
        satListInternalFrame.getContentPane().setLayout(satListInternalFrameLayout);
        satListInternalFrameLayout.setHorizontalGroup(satListInternalFrameLayout
                .createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING).addGap(0, 184, Short.MAX_VALUE));
        satListInternalFrameLayout.setVerticalGroup(satListInternalFrameLayout
                .createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING).addGap(0, 324, Short.MAX_VALUE));

        satListInternalFrame.setBounds(610, 5, 190, 350);
        mainDesktopPane.add(satListInternalFrame, javax.swing.JLayeredPane.DEFAULT_LAYER);

        desktopScrollPane.setViewportView(mainDesktopPane);

        javax.swing.GroupLayout desktopPanelLayout = new javax.swing.GroupLayout(desktopPanel);
        desktopPanel.setLayout(desktopPanelLayout);
        desktopPanelLayout.setHorizontalGroup(
                desktopPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING).addComponent(
                        desktopScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 814, Short.MAX_VALUE));
        desktopPanelLayout.setVerticalGroup(
                desktopPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING).addComponent(
                        desktopScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 416, Short.MAX_VALUE));

        mainPanel.add(desktopPanel, java.awt.BorderLayout.CENTER);

        getContentPane().add(mainPanel, java.awt.BorderLayout.CENTER);

        statusPanel.setPreferredSize(new java.awt.Dimension(0, 26));

        statusLabel.setForeground(new java.awt.Color(102, 102, 102));

        statusProgressBar.setVisible(false); // start out invisible
        statusProgressBar.setStringPainted(true);

        statusAnimationLabel
                .setIcon(new javax.swing.ImageIcon(getClass().getResource("/icons/busyicons/idle-icon.png"))); // NOI18N

        javax.swing.GroupLayout statusPanelLayout = new javax.swing.GroupLayout(statusPanel);
        statusPanel.setLayout(statusPanelLayout);
        statusPanelLayout.setHorizontalGroup(statusPanelLayout
                .createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                .addComponent(jSeparator7, javax.swing.GroupLayout.Alignment.TRAILING,
                        javax.swing.GroupLayout.DEFAULT_SIZE, 814, Short.MAX_VALUE)
                .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, statusPanelLayout.createSequentialGroup()
                        .addContainerGap()
                        .addComponent(statusLabel, javax.swing.GroupLayout.DEFAULT_SIZE, 614, Short.MAX_VALUE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(statusProgressBar, javax.swing.GroupLayout.PREFERRED_SIZE,
                                javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                        .addComponent(statusAnimationLabel).addContainerGap()));
        statusPanelLayout.setVerticalGroup(statusPanelLayout
                .createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                .addGroup(statusPanelLayout.createSequentialGroup()
                        .addComponent(jSeparator7, javax.swing.GroupLayout.PREFERRED_SIZE, 5,
                                javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addGap(1, 1, 1)
                        .addGroup(statusPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                                .addComponent(statusLabel, javax.swing.GroupLayout.DEFAULT_SIZE, 21,
                                        Short.MAX_VALUE)
                                .addComponent(statusAnimationLabel).addComponent(statusProgressBar,
                                        javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE,
                                        Short.MAX_VALUE))
                        .addContainerGap()));

        getContentPane().add(statusPanel, java.awt.BorderLayout.SOUTH);

        fileMenu.setText("File"); // NOI18N

        newMenuItem.setIcon(new javax.swing.ImageIcon(getClass().getResource("/icons/gnome_2_18/window-new.png"))); // NOI18N
        newMenuItem.setText("New Scenario"); // NOI18N
        newMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                newMenuItemActionPerformed(evt);
            }
        });
        fileMenu.add(newMenuItem);

        openMenuItem
                .setIcon(new javax.swing.ImageIcon(getClass().getResource("/icons/gnome_2_18/folder-open.png"))); // NOI18N
        openMenuItem.setText("Open..."); // NOI18N
        openMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                openMenuItemActionPerformed(evt);
            }
        });
        fileMenu.add(openMenuItem);

        closeMenuItem
                .setIcon(new javax.swing.ImageIcon(getClass().getResource("/icons/gnome_2_18/window-close.png"))); // NOI18N
        closeMenuItem.setText("Close"); // NOI18N
        closeMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                closeMenuItemActionPerformed(evt);
            }
        });
        fileMenu.add(closeMenuItem);

        saveMenuItem.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_S,
                java.awt.event.InputEvent.CTRL_MASK));
        saveMenuItem
                .setIcon(new javax.swing.ImageIcon(getClass().getResource("/icons/gnome_2_18/document-save.png"))); // NOI18N
        saveMenuItem.setText("Save"); // NOI18N
        saveMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                saveMenuItemActionPerformed(evt);
            }
        });
        fileMenu.add(saveMenuItem);

        saveAsMenuItem.setIcon(
                new javax.swing.ImageIcon(getClass().getResource("/icons/gnome_2_18/document-save-as.png"))); // NOI18N
        saveAsMenuItem.setText("Save As..."); // NOI18N
        saveAsMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                saveAsMenuItemActionPerformed(evt);
            }
        });
        fileMenu.add(saveAsMenuItem);
        fileMenu.add(jSeparator2);

        exitMenuItem
                .setIcon(new javax.swing.ImageIcon(getClass().getResource("/icons/gnome_2_18/process-stop.png"))); // NOI18N
        exitMenuItem.setText("Exit"); // NOI18N
        exitMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                exitMenuItemActionPerformed(evt);
            }
        });
        fileMenu.add(exitMenuItem);

        jMenuBar1.add(fileMenu);

        simMenu.setText("Simulation"); // NOI18N

        simPropMenuItem
                .setIcon(new javax.swing.ImageIcon(getClass().getResource("/icons/other/control-center2.png"))); // NOI18N
        simPropMenuItem.setText("Properties"); // NOI18N
        simPropMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                simPropMenuItemActionPerformed(evt);
            }
        });
        simMenu.add(simPropMenuItem);
        simMenu.add(jSeparator3);

        realTimeMenuItem.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_R,
                java.awt.event.InputEvent.CTRL_MASK));
        realTimeMenuItem.setIcon(new javax.swing.ImageIcon(getClass().getResource("/icons/other/xclock.png"))); // NOI18N
        realTimeMenuItem.setText("Real Time Mode"); // NOI18N
        realTimeMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                realTimeMenuItemActionPerformed(evt);
            }
        });
        simMenu.add(realTimeMenuItem);

        nonRealTimeMenuItem.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_R,
                java.awt.event.InputEvent.SHIFT_MASK | java.awt.event.InputEvent.CTRL_MASK));
        nonRealTimeMenuItem.setText("Non-Real Time Mode"); // NOI18N
        nonRealTimeMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                nonRealTimeMenuItemActionPerformed(evt);
            }
        });
        simMenu.add(nonRealTimeMenuItem);
        simMenu.add(jSeparator4);

        utcTimeMenuItem.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_U,
                java.awt.event.InputEvent.CTRL_MASK));
        utcTimeMenuItem.setIcon(
                new javax.swing.ImageIcon(getClass().getResource("/icons/gnome_2_18/appointment-soon.png"))); // NOI18N
        utcTimeMenuItem.setText("UTC Time Zone"); // NOI18N
        utcTimeMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                utcTimeMenuItemActionPerformed(evt);
            }
        });
        simMenu.add(utcTimeMenuItem);

        localTimeMenuItem.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_U,
                java.awt.event.InputEvent.SHIFT_MASK | java.awt.event.InputEvent.CTRL_MASK));
        localTimeMenuItem.setText("Local Time Zone"); // NOI18N
        localTimeMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                localTimeMenuItemActionPerformed(evt);
            }
        });
        simMenu.add(localTimeMenuItem);

        jMenuBar1.add(simMenu);

        utilitiesMenu.setText("Utilities"); // NOI18N
        utilitiesMenu.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                utilitiesMenuActionPerformed(evt);
            }
        });

        tleLoaderMenuItem.setIcon(new javax.swing.ImageIcon(
                getClass().getResource("/icons/tango_blue_materia/network-transmit-receive.png"))); // NOI18N
        tleLoaderMenuItem.setText("Update Satellite TLE Data"); // NOI18N
        tleLoaderMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                tleLoaderMenuItemActionPerformed(evt);
            }
        });
        utilitiesMenu.add(tleLoaderMenuItem);
        utilitiesMenu.add(jSeparator6);

        trackToolMenuItem.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_T,
                java.awt.event.InputEvent.CTRL_MASK));
        trackToolMenuItem
                .setIcon(new javax.swing.ImageIcon(getClass().getResource("/icons/other/network-wireless.png"))); // NOI18N
        trackToolMenuItem.setText("Tracking Tool"); // NOI18N
        trackToolMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                trackToolMenuItemActionPerformed(evt);
            }
        });
        utilitiesMenu.add(trackToolMenuItem);

        coverageMenuItem.setIcon(new javax.swing.ImageIcon(
                getClass().getResource("/icons/other/preferences-system-network-proxy.png"))); // NOI18N
        coverageMenuItem.setText("Coverage Analysis");
        coverageMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                coverageMenuItemActionPerformed(evt);
            }
        });
        utilitiesMenu.add(coverageMenuItem);
        utilitiesMenu.add(jSeparator10);

        movieWholeAppMenuItem.setIcon(
                new javax.swing.ImageIcon(getClass().getResource("/icons/other/applications-multimedia.png"))); // NOI18N
        movieWholeAppMenuItem.setText("Create Movie of Application");
        movieWholeAppMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                movieWholeAppMenuItemActionPerformed(evt);
            }
        });
        utilitiesMenu.add(movieWholeAppMenuItem);
        utilitiesMenu.add(jSeparator11);

        commandServerMenuItem.setIcon(
                new javax.swing.ImageIcon(getClass().getResource("/icons/tango_blue_materia/network-receive.png"))); // NOI18N
        commandServerMenuItem.setText("Command Server");
        commandServerMenuItem.setToolTipText("TCP/IP command server");
        commandServerMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                commandServerMenuItemActionPerformed(evt);
            }
        });
        utilitiesMenu.add(commandServerMenuItem);

        commandClientMenuItem.setText("Command Client");
        commandClientMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                commandClientMenuItemActionPerformed(evt);
            }
        });
        utilitiesMenu.add(commandClientMenuItem);

        jMenuBar1.add(utilitiesMenu);

        new3DwindowMenu.setText("Windows"); // NOI18N
        new3DwindowMenu.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                new3DwindowMenuActionPerformed(evt);
            }
        });

        showSatBrowser.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_B,
                java.awt.event.InputEvent.CTRL_MASK));
        showSatBrowser
                .setIcon(new javax.swing.ImageIcon(getClass().getResource("/icons/custom/folder-open_sat.png"))); // NOI18N
        showSatBrowser.setText("Satellite Browser"); // NOI18N
        showSatBrowser.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                showSatBrowserActionPerformed(evt);
            }
        });
        new3DwindowMenu.add(showSatBrowser);

        showGSBrowserMenuItem.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_G,
                java.awt.event.InputEvent.CTRL_MASK));
        showGSBrowserMenuItem
                .setIcon(new javax.swing.ImageIcon(getClass().getResource("/icons/custom/folder-open_gs.png"))); // NOI18N
        showGSBrowserMenuItem.setText("Ground Station Browser"); // NOI18N
        showGSBrowserMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                showGSBrowserMenuItemActionPerformed(evt);
            }
        });
        new3DwindowMenu.add(showGSBrowserMenuItem);
        new3DwindowMenu.add(jSeparator5);

        new2DWindowMenuItem
                .setIcon(new javax.swing.ImageIcon(getClass().getResource("/icons/other/gnome-mime-image.png"))); // NOI18N
        new2DWindowMenuItem.setText("New 2D Window"); // NOI18N
        new2DWindowMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                new2DWindowMenuItemActionPerformed(evt);
            }
        });
        new3DwindowMenu.add(new2DWindowMenuItem);

        newInternal3DWindowMenuItem
                .setIcon(new javax.swing.ImageIcon(getClass().getResource("/icons/other/emblem-web.png"))); // NOI18N
        newInternal3DWindowMenuItem.setText("New 3D Window (Internal)"); // NOI18N
        newInternal3DWindowMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                newInternal3DWindowMenuItemActionPerformed(evt);
            }
        });
        new3DwindowMenu.add(newInternal3DWindowMenuItem);

        newExternal3DWindowMenuItem
                .setIcon(new javax.swing.ImageIcon(getClass().getResource("/icons/other/emblem-web.png"))); // NOI18N
        newExternal3DWindowMenuItem.setText("New 3D Window (External)"); // NOI18N
        newExternal3DWindowMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                newExternal3DWindowMenuItemActionPerformed(evt);
            }
        });
        new3DwindowMenu.add(newExternal3DWindowMenuItem);
        new3DwindowMenu.add(jSeparator1);

        twoDwindowPropMenuItem
                .setIcon(new javax.swing.ImageIcon(getClass().getResource("/icons/other/preferences-system.png"))); // NOI18N
        twoDwindowPropMenuItem.setText("2D Window Properties"); // NOI18N
        twoDwindowPropMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                twoDwindowPropMenuItemActionPerformed(evt);
            }
        });
        new3DwindowMenu.add(twoDwindowPropMenuItem);
        new3DwindowMenu.add(jSeparator8);

        consoleMenuItem.setIcon(new javax.swing.ImageIcon(getClass().getResource("/icons/other/logviewer.png"))); // NOI18N
        consoleMenuItem.setText("Log Console");
        consoleMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                consoleMenuItemActionPerformed(evt);
            }
        });
        new3DwindowMenu.add(consoleMenuItem);
        new3DwindowMenu.add(jSeparator9);

        commandShellMenuItem.setIcon(new javax.swing.ImageIcon(
                getClass().getResource("/icons/tango_blue_materia/utilities-terminal.png"))); // NOI18N
        commandShellMenuItem.setText("Command Shell");
        commandShellMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                commandShellMenuItemActionPerformed(evt);
            }
        });
        new3DwindowMenu.add(commandShellMenuItem);

        commandShellDesktopMenuItem.setText("Command Shell Desktop");
        commandShellDesktopMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                commandShellDesktopMenuItemActionPerformed(evt);
            }
        });
        new3DwindowMenu.add(commandShellDesktopMenuItem);

        jMenuBar1.add(new3DwindowMenu);

        pluginMenu.setText("Plugins");
        jMenuBar1.add(pluginMenu);

        helpMenu.setText("Help"); // NOI18N

        sysPropsMenuItem.setText("System Properties..."); // NOI18N
        sysPropsMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                sysPropsMenuItemActionPerformed(evt);
            }
        });
        helpMenu.add(sysPropsMenuItem);

        lookFeelMenuItem.setText("App Look and Feel...");
        lookFeelMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                lookFeelMenuItemActionPerformed(evt);
            }
        });
        helpMenu.add(lookFeelMenuItem);

        aboutMenuItem.setText("About..."); // NOI18N
        aboutMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                aboutMenuItemActionPerformed(evt);
            }
        });
        helpMenu.add(aboutMenuItem);

        jMenuBar1.add(helpMenu);

        setJMenuBar(jMenuBar1);

        pack();
    }// </editor-fold>//GEN-END:initComponents

    private void jButtonTritonActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_jButtonTritonActionPerformed
        showTritonInternalFrame();

    }// GEN-LAST:event_jButtonTritonActionPerformed

    private void sysPropsMenuItemActionPerformed(java.awt.event.ActionEvent evt)// GEN-FIRST:event_sysPropsMenuItemActionPerformed
    {// GEN-HEADEREND:event_sysPropsMenuItemActionPerformed
        SystemPropertiesDialog spd = new SystemPropertiesDialog(this, false);
        setLookandFeel(spd);
        spd.setVisible(true);
    }// GEN-LAST:event_sysPropsMenuItemActionPerformed

    private void localTimeMenuItemActionPerformed(java.awt.event.ActionEvent evt)// GEN-FIRST:event_localTimeMenuItemActionPerformed
    {// GEN-HEADEREND:event_localTimeMenuItemActionPerformed
        if (!localTimeZoneCheckBox.isSelected()) {
            localTimeZoneCheckBox.doClick();
        }
    }// GEN-LAST:event_localTimeMenuItemActionPerformed

    private void utcTimeMenuItemActionPerformed(java.awt.event.ActionEvent evt)// GEN-FIRST:event_utcTimeMenuItemActionPerformed
    {// GEN-HEADEREND:event_utcTimeMenuItemActionPerformed

        if (localTimeZoneCheckBox.isSelected()) {
            localTimeZoneCheckBox.doClick();
        }
    }// GEN-LAST:event_utcTimeMenuItemActionPerformed

    private void nonRealTimeMenuItemActionPerformed(java.awt.event.ActionEvent evt)// GEN-FIRST:event_nonRealTimeMenuItemActionPerformed
    {// GEN-HEADEREND:event_nonRealTimeMenuItemActionPerformed
        if (realTimeModeCheckBox.isSelected()) {
            realTimeModeCheckBox.doClick();
        }
    }// GEN-LAST:event_nonRealTimeMenuItemActionPerformed

    private void realTimeMenuItemActionPerformed(java.awt.event.ActionEvent evt)// GEN-FIRST:event_realTimeMenuItemActionPerformed
    {// GEN-HEADEREND:event_realTimeMenuItemActionPerformed
        if (!realTimeModeCheckBox.isSelected()) {
            realTimeModeCheckBox.doClick();
        }
    }// GEN-LAST:event_realTimeMenuItemActionPerformed

    private void newMenuItemActionPerformed(java.awt.event.ActionEvent evt)// GEN-FIRST:event_newMenuItemActionPerformed
    {// GEN-HEADEREND:event_newMenuItemActionPerformed

        // make sure you can close the current senario
        boolean closed = closeScenario(true); // make sure it is okay to close
        // current scenario?

        if (!closed) {
            return;
        }

        // okay now create default layout:
        // by default open a new 2D window to start
        createNew2dWindow();

        // first call to update time to current time:
        currentJulianDate.update2CurrentTime();// .update();// =
        // getCurrentJulianDate(); //
        // ini time
        // set time string format
        currentJulianDate.setDateFormat(dateformat);

        updateTime(); // update plots

        // update gui with timestep
        updateTimeStepsDataGUI();

        // Default sats in list: -- load if TLE data is local
        TLEDownloader tleDownloader = new TLEDownloader();
        if ((new File(tleDownloader.getLocalPath()).exists())
                && (new File(tleDownloader.getTleFilePath(0)).exists())) {
            addSat2ListByName("ISS (ZARYA)             ");
        }

        // set default epoch time to be current time
        epochTimeEqualsCurrentTime = true;
        // other default settings
        realTimeAnimationRefreshRateMs = 1000; // refresh rate for real time
        // animation
        nonRealTimeAnimationRefreshRateMs = 50;

        // reset other options 

    }// GEN-LAST:event_newMenuItemActionPerformed

    private void exitMenuItemActionPerformed(java.awt.event.ActionEvent evt)// GEN-FIRST:event_exitMenuItemActionPerformed
    {// GEN-HEADEREND:event_exitMenuItemActionPerformed
     // how to exit:
        this.dispose(); // close app
        System.exit(0); // SEG added 26 May 2009 bug fix
    }// GEN-LAST:event_exitMenuItemActionPerformed

    private void saveAsMenuItemActionPerformed(java.awt.event.ActionEvent evt)// GEN-FIRST:event_saveAsMenuItemActionPerformed
    {// GEN-HEADEREND:event_saveAsMenuItemActionPerformed
        saveAppAs();
    }// GEN-LAST:event_saveAsMenuItemActionPerformed

    private void saveMenuItemActionPerformed(java.awt.event.ActionEvent evt)// GEN-FIRST:event_saveMenuItemActionPerformed
    {// GEN-HEADEREND:event_saveMenuItemActionPerformed
        if (getFileSaveAs() == null || getFileSaveAs().length() == 0) {
            // then we need to save as
            saveAppAs();
        } else {
            saveApp(getFileSaveAs());
        }
    }// GEN-LAST:event_saveMenuItemActionPerformed

    private void openMenuItemActionPerformed(java.awt.event.ActionEvent evt)// GEN-FIRST:event_openMenuItemActionPerformed
    {// GEN-HEADEREND:event_openMenuItemActionPerformed
        openFile();
    }// GEN-LAST:event_openMenuItemActionPerformed

    private void closeMenuItemActionPerformed(java.awt.event.ActionEvent evt)// GEN-FIRST:event_closeMenuItemActionPerformed
    {// GEN-HEADEREND:event_closeMenuItemActionPerformed
        closeScenario(true);
    }// GEN-LAST:event_closeMenuItemActionPerformed

    private void saveButtonActionPerformed(java.awt.event.ActionEvent evt)// GEN-FIRST:event_saveButtonActionPerformed
    {// GEN-HEADEREND:event_saveButtonActionPerformed

        if (getFileSaveAs() == null || getFileSaveAs().length() == 0) {
            // then we need to save as
            saveAppAs();
        } else {
            saveApp(getFileSaveAs());
        }

    }// GEN-LAST:event_saveButtonActionPerformed

    private void new3DwindowMenuActionPerformed(java.awt.event.ActionEvent evt)// GEN-FIRST:event_new3DwindowMenuActionPerformed
    {// GEN-HEADEREND:event_new3DwindowMenuActionPerformed
     // TODO add your handling code here:
    }// GEN-LAST:event_new3DwindowMenuActionPerformed

    private void simPropMenuItemActionPerformed(java.awt.event.ActionEvent evt)// GEN-FIRST:event_simPropMenuItemActionPerformed
    {// GEN-HEADEREND:event_simPropMenuItemActionPerformed
        SimulationPropPanel propPanel = new SimulationPropPanel(this);

        // create new internal frame window
        JInternalFrame iframe = new JInternalFrame("Simulation Properties", true, true, true, true);

        iframe.setContentPane(propPanel);
        iframe.setSize(305 + 35, 335 + 115); // w, h
        iframe.setLocation(15, 20);

        iframe.setFrameIcon(new javax.swing.ImageIcon(getClass().getResource("/icons/logo/JSatTrakLogo_16.png")));

        // save frame
        propPanel.setInternalFrame(iframe);

        // add close action listener -- to remove window from hash
        iframe.addInternalFrameListener(this);

        iframe.setVisible(true);
        mainDesktopPane.add(iframe);
        try {
            iframe.setSelected(true);
        } catch (java.beans.PropertyVetoException e) {
        }
    }// GEN-LAST:event_simPropMenuItemActionPerformed

    private void twoDwindowPropMenuItemActionPerformed(java.awt.event.ActionEvent evt)// GEN-FIRST:event_twoDwindowPropMenuItemActionPerformed
    {// GEN-HEADEREND:event_twoDwindowPropMenuItemActionPerformed

        // create a new internal window by passing in infor of current panel
        open2dWindowOptions();

    }// GEN-LAST:event_twoDwindowPropMenuItemActionPerformed

    private void screenShotButtonActionPerformed(java.awt.event.ActionEvent evt)// GEN-FIRST:event_screenShotButtonActionPerformed
    {// GEN-HEADEREND:event_screenShotButtonActionPerformed
        createScreenCapture();
    }// GEN-LAST:event_screenShotButtonActionPerformed

    private void openSatBrowserButtonActionPerformed(java.awt.event.ActionEvent evt)// GEN-FIRST:event_openSatBrowserButtonActionPerformed
    {// GEN-HEADEREND:event_openSatBrowserButtonActionPerformed
        showSatBrowserInternalFrame();
    }// GEN-LAST:event_openSatBrowserButtonActionPerformed

    private void recenterToggleButtonActionPerformed(java.awt.event.ActionEvent evt)// GEN-FIRST:event_recenterToggleButtonActionPerformed
    {// GEN-HEADEREND:event_recenterToggleButtonActionPerformed
        zoomIntoggleButton.setSelected(false);
        zoomOuttoggleButton.setSelected(false);
    }// GEN-LAST:event_recenterToggleButtonActionPerformed

    private void zoomOuttoggleButtonActionPerformed(java.awt.event.ActionEvent evt)// GEN-FIRST:event_zoomOuttoggleButtonActionPerformed
    {// GEN-HEADEREND:event_zoomOuttoggleButtonActionPerformed
     // make other zoom button unselected
        zoomIntoggleButton.setSelected(false);
        recenterToggleButton.setSelected(false);
    }

    private void zoomIntoggleButtonActionPerformed(java.awt.event.ActionEvent evt)// GEN-FIRST:event_zoomIntoggleButtonActionPerformed
    {
        // make other zoom button unselected
        zoomOuttoggleButton.setSelected(false); // does this trigger an event on
        // other?, nope
        recenterToggleButton.setSelected(false);
    }

    private void aboutMenuItemActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_aboutMenuItemActionPerformed
    {//GEN-HEADEREND:event_aboutMenuItemActionPerformed
     // Show about menu
        AboutDialog ad = new AboutDialog(versionString, this, gov.nasa.worldwind.Version.getVersion());
        //System.out.println("V:" + gov.nasa.worldwind.Version.getVersion() );

        setLookandFeel(ad);

        ad.setVisible(true);
    }//GEN-LAST:event_aboutMenuItemActionPerformed

    private void localTimeZoneCheckBoxActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_localTimeZoneCheckBoxActionPerformed

        // Set the formatting timezone
        if (localTimeZoneCheckBox.isSelected()) {
            // local time zone
            Time.setTzStringFormat(localTZ);
            // epoch
            Time.setTzStringFormat(localTZ);
        } else {
            // UTC
            Time.setTzStringFormat(TimeZone.getTimeZone("UTC"));
            // epoch
            Time.setTzStringFormat(TimeZone.getTimeZone("UTC"));
        }

        // update date box:
        dateTextField.setText(currentJulianDate.getDateTimeStr());

    }

    private void dateTextFieldActionPerformed(java.awt.event.ActionEvent evt) {
        // save old time
        double prevJulDate = currentJulianDate.getJulianDate();

        // enter hit in date/time box...
        System.out.println("Date Time Changed");

        GregorianCalendar currentTimeDate = new GregorianCalendar(TimeZone.getTimeZone("UTC"));
        // or
        // GregorianCalendar currentTimeDate = new GregorianCalendar();

        boolean dateAccepted = true; // assume date valid at first
        try {
            currentTimeDate.setTime(dateformatShort1.parse(dateTextField.getText()));
            dateTextField.setText(dateformat.format(currentTimeDate.getTime()));
        } catch (Exception e2) {
            try {
                // try reading without the milliseconds
                currentTimeDate.setTime(dateformatShort2.parse(dateTextField.getText()));
                dateTextField.setText(dateformat.format(currentTimeDate.getTime()));
            } catch (Exception e3) {
                // bad date input put back the old date string
                dateTextField.setText(dateformat.format(currentTimeDate.getTime()));
                dateAccepted = false;
                System.out.println(" -- Rejected");
            } // catch 2

        } // catch 1

        if (dateAccepted) {
            // date entered was good...
            System.out.println(" -- Accepted");

            // save
            currentJulianDate.set(currentTimeDate.getTimeInMillis());
            // currentJulianDate.set(currentTimeDate.get(Calendar.YEAR),
            // currentTimeDate.get(Calendar.MONTH),
            // currentTimeDate.get(Calendar.DATE),
            // currentTimeDate.get(Calendar.HOUR_OF_DAY),
            // currentTimeDate.get(Calendar.MINUTE),
            // currentTimeDate.get(Calendar.SECOND));

            // check that time change wasn't too great for resetting ground
            // track
            double timeDiffDays = Math.abs(currentJulianDate.getJulianDate() - prevJulDate); // in days
            checkTimeDiffResetGroundTracks(timeDiffDays);

            // update maps ----------------
            // set animation direction = 0
            currentPlayDirection = 0;
            // update graphics
            updateTime();

        } // if date accepted

    }// GEN-LAST:event_dateTextFieldActionPerformed

    private void decementTimeStepButtonActionPerformed(java.awt.event.ActionEvent evt)// GEN-FIRST:event_decementTimeStepButtonActionPerformed
    {// GEN-HEADEREND:event_decementTimeStepButtonActionPerformed
        currentTimeStepSpeedIndex--;
        updateTimeStepsDataGUI();
    }// GEN-LAST:event_decementTimeStepButtonActionPerformed

    private void incrementTimeStepButtonActionPerformed(java.awt.event.ActionEvent evt)// GEN-FIRST:event_incrementTimeStepButtonActionPerformed
    {// GEN-HEADEREND:event_incrementTimeStepButtonActionPerformed

        currentTimeStepSpeedIndex++;
        updateTimeStepsDataGUI();

    }// GEN-LAST:event_incrementTimeStepButtonActionPerformed

    // updates timestep data and GUI based on current currentTimeStepSpeedIndex
    private void updateTimeStepsDataGUI() {
        // bounds checking
        if (currentTimeStepSpeedIndex > (timeStepSpeeds.length - 1)) {
            currentTimeStepSpeedIndex = (timeStepSpeeds.length - 1);
        } else if (currentTimeStepSpeedIndex < 0) {
            currentTimeStepSpeedIndex = 0;
        }

        double speedInSec = timeStepSpeeds[currentTimeStepSpeedIndex];

        timeStepLabel.setText("" + speedInSec);

        animationSimStepSeconds = speedInSec; // seconds to days
    }

    private void resetTimeButtonActionPerformed(java.awt.event.ActionEvent evt)// GEN-FIRST:event_resetTimeButtonActionPerformed
    {// GEN-HEADEREND:event_resetTimeButtonActionPerformed
     // save old time
        double prevJulDate = currentJulianDate.getJulianDate();

        // set/update current time to current time
        if (epochTimeEqualsCurrentTime) {
            // update to current time
            currentJulianDate.update2CurrentTime(); // update();// =
            // getCurrentJulianDate();
            // // ini time
        } else {
            // update to epoch
            currentJulianDate.set(scenarioEpochDate.getCurrentGregorianCalendar().getTimeInMillis());
        }
        // check to see if large time jump occured
        double timeDiffDays = Math.abs(currentJulianDate.getJulianDate() - prevJulDate); // in days
        checkTimeDiffResetGroundTracks(timeDiffDays);

        // set animation direction = 0
        currentPlayDirection = 0;
        // update graphics
        updateTime();
    }// GEN-LAST:event_resetTimeButtonActionPerformed

    private void playBackButtonActionPerformed(java.awt.event.ActionEvent evt)// GEN-FIRST:event_playBackButtonActionPerformed
    {// GEN-HEADEREND:event_playBackButtonActionPerformed
        currentPlayDirection = -1; // backwards
        runAnimation();
    }// GEN-LAST:event_playBackButtonActionPerformed

    private void stepBackButtonActionPerformed(java.awt.event.ActionEvent evt)// GEN-FIRST:event_stepBackButtonActionPerformed
    {// GEN-HEADEREND:event_stepBackButtonActionPerformed
        currentPlayDirection = -1; // backward in time
        updateTime();
    }// GEN-LAST:event_stepBackButtonActionPerformed

    private void playButtonActionPerformed(java.awt.event.ActionEvent evt)// GEN-FIRST:event_playButtonActionPerformed
    {// GEN-HEADEREND:event_playButtonActionPerformed
        currentPlayDirection = 1; // forwards
        runAnimation(); // perform animation
    }// GEN-LAST:event_playButtonActionPerformed

    private void runAnimation() {
        // useses globally set animation direction and starts animation
        playButton.setEnabled(false);
        stepForwardTimeButton.setEnabled(false);
        stepBackButton.setEnabled(false);
        playBackButton.setEnabled(false);
        resetTimeButton.setEnabled(false);

        stopHit = false;
        // Create a timer.
        lastFPSms = System.currentTimeMillis();
        playTimer = new Timer(animationRefreshRateMs, new ActionListener() {
            public void actionPerformed(ActionEvent evt) {
                // take one time step in the aimation
                updateTime(); // animate
                long stopTime = System.currentTimeMillis();

                fpsAnimation = 1.0 / ((stopTime - lastFPSms) / 1000.0); // fps
                // calculation
                lastFPSms = stopTime;
                // goal FPS:
                // fpsAnimation = 1.0 / (animationRefreshRateMs/1000.0);

                if (stopHit) {
                    playTimer.stop();
                    resetAnimationIcons();
                }

                // SEG - if update took a long time reduce the timers repeat
                // interval

            }
        });
        playTimer.setRepeats(true);
        playTimer.start();
    } // runAnimation

    public void resetAnimationIcons() {
        if (realTimeModeCheckBox.isSelected()) {
            // real time mode
            playButton.setEnabled(true);
            stepForwardTimeButton.setEnabled(true);
            stepBackButton.setEnabled(false);
            playBackButton.setEnabled(false);
            resetTimeButton.setEnabled(false);
        } else { // non-real time mode
            playButton.setEnabled(true);
            stepForwardTimeButton.setEnabled(true);
            stepBackButton.setEnabled(true);
            playBackButton.setEnabled(true);
            resetTimeButton.setEnabled(true);
        }

    } // resetAnimationIcons

    // input change in time in days, checks to see if ground tracks need to be
    // updated
    public void checkTimeDiffResetGroundTracks(double timeDiffDays) {
        if (timeDiffDays > 91.0 / 1440.0) {
            // big time jump
            for (AbstractSatellite sat : sats.values()) {
                if (sat.isGroundTrackShown() && (sat.getPeriod() <= (timeDiffDays * 24.0 * 60.0))) {
                    sat.repaintGroundTrack();
                    // System.out.println(sat.getName()
                    // +" - Groundtrack Iniated");
                }
            }
        }
    } // checkTimeDiffResetGroundTracks

    private void stopButtonActionPerformed(java.awt.event.ActionEvent evt)// GEN-FIRST:event_stopButtonActionPerformed
    {// GEN-HEADEREND:event_stopButtonActionPerformed
     // TODO add your handling code here:
        stopAnimation();
    }// GEN-LAST:event_stopButtonActionPerformed

    public void stopAnimation() {
        stopHit = true; // set flag for next animation step
    }

    private void realTimeModeCheckBoxActionPerformed(java.awt.event.ActionEvent evt)// GEN-FIRST:event_realTimeModeCheckBoxActionPerformed
    {// GEN-HEADEREND:event_realTimeModeCheckBoxActionPerformed

        // first stop animating if animation is in progress
        stopAnimation();

        // turn on/off needed icons
        if (realTimeModeCheckBox.isSelected()) {
            // real time is on
            resetTimeButton.setEnabled(false);
            playBackButton.setEnabled(false);
            stepBackButton.setEnabled(false);

            animationRefreshRateMs = realTimeAnimationRefreshRateMs; // set real
            // time
            // refresh
            // rate
        } else {
            // real time turned off
            resetTimeButton.setEnabled(true);
            playBackButton.setEnabled(true);
            stepBackButton.setEnabled(true);

            animationRefreshRateMs = nonRealTimeAnimationRefreshRateMs; // non
            // real
            // time
            // refresh
            // rate
        }

    }// GEN-LAST:event_realTimeModeCheckBoxActionPerformed

    private void stepForwardTimeButtonActionPerformed(java.awt.event.ActionEvent evt)// GEN-FIRST:event_stepForwardTimeButtonActionPerformed
    {// GEN-HEADEREND:event_stepForwardTimeButtonActionPerformed
        currentPlayDirection = 1; // forward in time
        updateTime();
    }// GEN-LAST:event_stepForwardTimeButtonActionPerformed

    private void new2DWindowMenuItemActionPerformed(java.awt.event.ActionEvent evt)// GEN-FIRST:event_new2DWindowMenuItemActionPerformed
    {// GEN-HEADEREND:event_new2DWindowMenuItemActionPerformed

        createNew2dWindow();

    }// GEN-LAST:event_new2DWindowMenuItemActionPerformed

    private JInternalFrame createNew2dWindow() {

        // create 2D Earth Panel:
        J2DEarthPanel newPanel = new J2DEarthPanel(zoomIntoggleButton, zoomOuttoggleButton, recenterToggleButton,
                currentJulianDate, sun, this);

        twoDWindowCount++; // TODO can't twoDWindowVec.size() be used instead?
        String windowName = "2D Earth Window - " + twoDWindowCount;
        newPanel.setName(windowName);
        twoDWindowVec.add(newPanel);

        // create new internal frame window
        JInternalFrame iframe = new JInternalFrame(windowName, true, true, true, true);

        iframe.setContentPane(newPanel);
        iframe.setSize(600, 350);
        iframe.setLocation(5, 5);

        iframe.setFrameIcon(new javax.swing.ImageIcon(getClass().getResource("/icons/logo/JSatTrakLogo_16.png")));

        // add close action listener -- to remove window from hash
        iframe.addInternalFrameListener(this);

        iframe.setVisible(true);
        mainDesktopPane.add(iframe);
        try {
            iframe.setSelected(true);
        } catch (java.beans.PropertyVetoException e) {
        }

        return iframe; // return it if the user wants to set properties
    }

    private JInternalFrame createNew3DInternalWindow() {
        threeDInternalWindowCount++;
        String windowName = "3D Earth Window - " + threeDInternalWindowCount;

        // create new internal frame window
        JInternalFrame iframe = new JInternalFrame(windowName, true, true, true, true);

        // create 3D Earth Panel:
        J3DEarthInternalPanel newPanel = new J3DEarthInternalPanel(iframe, currentJulianDate.getMJD(), this);
        threeDInternalWindowVec.add(newPanel); // add to vector

        // frame size
        iframe.setContentPane(newPanel);
        iframe.setSize(400, 350);
        Point p = this.getLocation();
        iframe.setLocation(p.x + 15, p.y + 95);

        iframe.setFrameIcon(new javax.swing.ImageIcon(getClass().getResource("/icons/logo/JSatTrakLogo_16.png")));

        // iframe.pack(); // makes wwj slow

        iframe.setVisible(true);

        threeDWorking = true;
        update3Dconfig();

        addInternalFrame(iframe); // add to window-- need to add coordinates!!

        // return iframe; // return it if the user wants to set properties

        // satBrowser.setVisible(true); // show window

        newPanel.setFocusWWJ(); // make wwj respond to keyboard clicks

        return iframe;
    }

    // private JInternalFrame createNew3dWindow()
    private JDialog createNew3dWindow() {
        threeDWindowCount++;
        String windowName = "3D Earth Window - " + threeDWindowCount;

        // create new internal frame window
        // JInternalFrame iframe = new
        // JInternalFrame(windowName,true,true,true,true);
        // JFrame iframe = new JFrame(windowName);
        JDialog iframe = new JDialog(this, windowName, false); // parent, title,
        // modal

        // create 3D Earth Panel:
        J3DEarthPanel newPanel = new J3DEarthPanel(iframe, currentJulianDate.getMJD(), this);
        threeDWindowVec.add(newPanel); // add to vector

        iframe.setContentPane(newPanel);
        iframe.setSize(400, 350);
        Point p = this.getLocation();
        iframe.setLocation(p.x + 15, p.y + 95);

        // add close action listener -- to remove window from hash
        iframe.addWindowListener(this);

        // set icon
        iframe.setIconImage(
                Toolkit.getDefaultToolkit().getImage(getClass().getResource("/icons/logo/JSatTrakLogo_16.png")));

        // //// SEG 23 March 2009 ///////////////////////////////
        // Check look and feel to see if this JDialog should have a deocrated
        // window
        boolean canBeDecoratedByLAF = UIManager.getLookAndFeel().getSupportsWindowDecorations();
        if (canBeDecoratedByLAF != iframe.isUndecorated()) {
            // boolean wasVisible = iframe.isVisible();
            // iframe.setVisible(false);
            iframe.dispose();
            if (!canBeDecoratedByLAF) // || wasOriginallyDecoratedByOS
            {
                // see the java docs under the method
                // JFrame.setDefaultLookAndFeelDecorated(boolean
                // value) for description of these 2 lines:
                iframe.setUndecorated(false);
                iframe.getRootPane().setWindowDecorationStyle(JRootPane.NONE);

            } else {
                iframe.setUndecorated(true);
                iframe.getRootPane().setWindowDecorationStyle(JRootPane.FRAME);
            }
        }
        // /////////////////////////////// window decoration check

        iframe.setVisible(true);

        threeDWorking = true;
        update3Dconfig();

        return iframe; // return it if the user wants to set properties

    } // new 3d window

    public void update3Dconfig() {
        // update the GUI based on info about if 3D is working
        if (threeDWorking) {
            new3DwindowMenu.setEnabled(true);
        } else // not working
        {
            new3DwindowMenu.setEnabled(false);
        }
    } // update3Dconfig

    // update time and take an anmiation step
    public void updateTime() {
        // save old time
        double prevJulDate = currentJulianDate.getJulianDate();

        // Get current simulation time!
        if (realTimeModeCheckBox.isSelected()) {
            // real time mode -- just use real time

            // Get current time in GMT
            // calculate current Juilian Date, update to current time
            currentJulianDate.update2CurrentTime(); // update();// =
            // getCurrentJulianDate();

        } else {
            // non-real time mode add fraction of time to current jul date
            // currentJulianDate += currentPlayDirection*animationSimStepDays;
            currentJulianDate.addSeconds(currentPlayDirection * animationSimStepSeconds);
        }

        // update sun position
        sun.setCurrentMJD(currentJulianDate.getMJD());
        // DEBUG:
        // double [] sunPos = sun.getCurrentPositionJ2K();
        // System.out.println("Sun Pos(J2K) - Date (MJD): " +
        // currentJulianDate.getMJD() + ", <x,y,z> < " +sunPos[0] +", "
        // +sunPos[1] +", "+sunPos[2] +" >");
        // sunPos = sun.getCurrentPositionMOD();
        // System.out.println("Sun Pos(MOD) - Date (MJD): " +
        // currentJulianDate.getMJD() + ", <x,y,z> < " +sunPos[0] +", "
        // +sunPos[1] +", "+sunPos[2] +" >");
        // double[] llaTemp = GeoFunctions.GeodeticJulDate(
        // sun.getCurrentPositionMOD() ,currentJulianDate.getJulianDate());
        // // sun.getCurrentPositionMOD()
        // //double[] llaTemp = GeoFunctions.GeodeticJulDate( new double[]
        // {-1.400954880970050E+08, 5.168955443226393E+07 ,
        // 2.240975286312218E+07} ,currentJulianDate.getJDN());
        // // 01 Sep 2007 00:00:00.000 UTC
        // System.out.println("Sun lat/long :  " + llaTemp[0]*180.0/Math.PI +
        // " , " + llaTemp[1]*180.0/Math.PI);

        // if time jumps by more than 91 minutes check period of sat to see if
        // ground tracks need to be updated
        double timeDiffDays = Math.abs(currentJulianDate.getJulianDate() - prevJulDate); // in days
        checkTimeDiffResetGroundTracks(timeDiffDays);

        // update date box:
        dateTextField.setText(currentJulianDate.getDateTimeStr());// String.format("%tc",cal)
        // );

        // now propogate all satellites to the current time
        for (AbstractSatellite sat : sats.values()) {
            sat.propogate2JulDate(currentJulianDate.getJulianDate());
        } // propgate each sat

        // update ground stations to the current time
        for (GroundStation gs : gses.values()) {
            gs.setCurrentJulianDate(currentJulianDate.getJulianDate());

            // test look angles
            // SatelliteProps sp= satHash.get("ISS (ZARYA)             ");
            // double[] aer = gs.calculate_AER(sp.getJ2000Position());
            //
            // System.out.println("AER: " + aer[0] + ", " + aer[1] + ", " +
            // aer[2]);

        } // propgate each sat

        // update times in 3D windows
        for (J3DEarthPanel threeDPanel : threeDWindowVec) {
            threeDPanel.setMJD(currentJulianDate.getMJD());
        }
        for (J3DEarthInternalPanel threeDPanel : threeDInternalWindowVec) {
            threeDPanel.setMJD(currentJulianDate.getMJD());
        }

        // update any other time dependant objects
        for (JSatTrakTimeDependent tdo : timeDependentObjects) {
            if (tdo != null) {
                tdo.updateTime(currentJulianDate, null, gses);
            }
        }

        forceRepainting(); // repaint 2d/3d earth

        // update any satellite property window that is open
        for (SatPropertyPanel satP : satPropWindowVec) {
            satP.updateProperties();
        }

        // update Tracking windows
        for (JTrackingPanel tp : trackingWindowVec) {
            tp.updateTime(currentJulianDate.getDateTimeStr());
        }

        if (groundSystemsPanel != null)
            groundSystemsPanel.updateTime(currentJulianDate.getJulianDate());

    } // update time

    public void forceRepainting() {
        // force repainting of all 2D windows
        for (J2DEarthPanel twoDPanel : twoDWindowVec) {
            twoDPanel.repaint();
        }

        // repaint 3D windows
        for (J3DEarthPanel threeDPanel : threeDWindowVec) {
            threeDPanel.repaintWWJ();
        }
        for (J3DEarthInternalPanel threeDPanel : threeDInternalWindowVec) {
            threeDPanel.repaintWWJ();
        }

    }// forceRepainting

    public void forceRepainting(boolean updateMapsData) {
        if (updateMapsData) {
            // update maps ----------------
            // set animation direction = 0
            currentPlayDirection = 0;
            // update graphics
            updateTime();
        } else {
            // just do a normal update -- don't regenerate data
            forceRepainting();
        }
    } // forceRepainting

    public double getCurrentJulTime() {
        return currentJulianDate.getJulianDate();
    }

    private void showSatBrowserActionPerformed(java.awt.event.ActionEvent evt)// GEN-FIRST:event_showSatBrowserActionPerformed
    {// GEN-HEADEREND:event_showSatBrowserActionPerformed
        showSatBrowserInternalFrame();
    }// GEN-LAST:event_showSatBrowserActionPerformed

    public void showSatBrowserInternalFrame() {
        // // show satellite browser window
        // JSatBrowser satBrowser = new JSatBrowser(this, false, this); //
        // non-modal version
        //
        // // create new internal frame window
        // String windowName = "Satellite Browser";
        // JInternalFrame iframe = new
        // JInternalFrame(windowName,true,true,true,true);
        //
        // iframe.setContentPane( satBrowser.getContentPane() );
        //
        // if(satBrowser.getJMenuBar() != null)
        // {
        // iframe.setJMenuBar(satBrowser.getJMenuBar()); // get menu bar too!
        // (if there is one)
        // }

        // NEW WAY
        JInternalFrame iframe = new JSatBrowserInternalFrame(this, this);

        iframe.setSize(261, 450); // w,h
        iframe.setLocation(5, 5);

        // add close action listener -- to remove window from hash
        iframe.addInternalFrameListener(this);

        iframe.setVisible(true);
        mainDesktopPane.add(iframe);
        try {
            iframe.setSelected(true);
        } catch (java.beans.PropertyVetoException e) {
        }

    } // showsatBrowserInternalFrame

    private void tleLoaderMenuItemActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_tleLoaderMenuItemActionPerformed

        String windowName = "TLE Downloader";

        // create new internal frame window
        JInternalFrame iframe = new JInternalFrame(windowName, true, true, true, true);

        TleDownloaderPanel newPanel = new TleDownloaderPanel(this, iframe);

        iframe.setContentPane(newPanel); // set contents pane
        iframe.setSize(375, 230); // set size w,h

        iframe.setFrameIcon(new javax.swing.ImageIcon(getClass().getResource("/icons/logo/JSatTrakLogo_16.png")));

        iframe.setVisible(true);
        addInternalFrame(iframe);

    }// GEN-LAST:event_tleLoaderMenuItemActionPerformed

    private void newInternal3DWindowMenuItemActionPerformed(java.awt.event.ActionEvent evt)// GEN-FIRST:event_newInternal3DWindowMenuItemActionPerformed
    {// GEN-HEADEREND:event_newInternal3DWindowMenuItemActionPerformed

        // Easter Egg Sorta -- holding the control key while opening a 3D window
        // opens the window in a dialog - though window is not saved
        // the dialog version uses a faster WWJ rendering class!!!
        if (evt.getModifiers() == 18) // 18 = control key held down (for win at
        // least!) this could be problematic
        {
            createNew3dWindow();
            return;
        }

        // create new window
        createNew3DInternalWindow();

    }// GEN-LAST:event_newInternal3DWindowMenuItemActionPerformed

    private void showGSBrowserMenuItemActionPerformed(java.awt.event.ActionEvent evt)// GEN-FIRST:event_showGSBrowserMenuItemActionPerformed
    {// GEN-HEADEREND:event_showGSBrowserMenuItemActionPerformed
        showGSBrowserInternalFrame();
    }// GEN-LAST:event_showGSBrowserMenuItemActionPerformed

    private void trackToolMenuItemActionPerformed(java.awt.event.ActionEvent evt)// GEN-FIRST:event_trackToolMenuItemActionPerformed
    {// GEN-HEADEREND:event_trackToolMenuItemActionPerformed
        openTrackingToolSelectorWindow(true);
    }// GEN-LAST:event_trackToolMenuItemActionPerformed

    private void newExternal3DWindowMenuItemActionPerformed(java.awt.event.ActionEvent evt)// GEN-FIRST:event_newExternal3DWindowMenuItemActionPerformed
    {// GEN-HEADEREND:event_newExternal3DWindowMenuItemActionPerformed
        createNew3dWindow();
    }// GEN-LAST:event_newExternal3DWindowMenuItemActionPerformed

    private void consoleMenuItemActionPerformed(java.awt.event.ActionEvent evt)// GEN-FIRST:event_consoleMenuItemActionPerformed
    {// GEN-HEADEREND:event_consoleMenuItemActionPerformed
        console.setVisible(true);
    }// GEN-LAST:event_consoleMenuItemActionPerformed

    private void commandShellMenuItemActionPerformed(java.awt.event.ActionEvent evt)// GEN-FIRST:event_commandShellMenuItemActionPerformed
    {// GEN-HEADEREND:event_commandShellMenuItemActionPerformed

        JDialog iframe = new JDialog(this, "Command Shell", false); // parent,
        // title,
        // modal

        // create 3D Earth Panel:

        iframe.setContentPane(commandConsole);

        iframe.setSize(450, 250);
        Point p = this.getLocation();
        iframe.setLocation(p.x + 15, p.y + 95);
        iframe.addWindowListener(this);

        iframe.setVisible(true);

        // set menu item to disabled
        commandShellMenuItem.setEnabled(false);

    }// GEN-LAST:event_commandShellMenuItemActionPerformed

    private void commandShellDesktopMenuItemActionPerformed(java.awt.event.ActionEvent evt)// GEN-FIRST:event_commandShellDesktopMenuItemActionPerformed
    {// GEN-HEADEREND:event_commandShellDesktopMenuItemActionPerformed
     // open the command desktop - all kinds of freatures for editing/testing
     // scripts
     // and a class browser
        try {
            beanShellInterp.eval("desktop();");
        } catch (Exception e) {
        }
    }// GEN-LAST:event_commandShellDesktopMenuItemActionPerformed

    private void commandServerMenuItemActionPerformed(java.awt.event.ActionEvent evt)// GEN-FIRST:event_commandServerMenuItemActionPerformed
    {// GEN-HEADEREND:event_commandServerMenuItemActionPerformed
     // open a command server
        GuiServer guiServer = new GuiServer(beanShellInterp);
        //setLookandFeel(guiServer);
        guiServer.setVisible(true);
    }

    private void commandClientMenuItemActionPerformed(java.awt.event.ActionEvent evt)// GEN-FIRST:event_commandClientMenuItemActionPerformed
    {
        CommandClientGUI client = new CommandClientGUI();
        //setLookandFeel(client);
        client.setVisible(true);
    }

    private void openGSbrowserActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_openGSbrowserActionPerformed
    {//GEN-HEADEREND:event_openGSbrowserActionPerformed
        showGSBrowserInternalFrame();
    }//GEN-LAST:event_openGSbrowserActionPerformed

    private void createMovieButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_createMovieButtonActionPerformed
        JCreateMovieDialog panel;

        // figure out what window is selected (if any), get location on screen /
        // width / height

        // if no frames are selected - use entire application as component
        if (mainDesktopPane.getSelectedFrame() == null) {
            panel = new JCreateMovieDialog(this, false, this.getContentPane(), this, "JSatTrak App");
        } else if (mainDesktopPane.getSelectedFrame().getContentPane() instanceof J3DEarthComponent) { // 3d
            // window

            panel = new JCreateMovieDialog(this, false,
                    (J3DEarthComponent) mainDesktopPane.getSelectedFrame().getContentPane(), this);
        } else if (mainDesktopPane.getSelectedFrame().getContentPane() instanceof J2DEarthPanel) { // if
            // a
            // 2d
            // window

            panel = new JCreateMovieDialog(this, false,
                    (J2DEarthPanel) mainDesktopPane.getSelectedFrame().getContentPane(), this);
        } else // default container
        {
            panel = new JCreateMovieDialog(this, false, mainDesktopPane.getSelectedFrame().getContentPane(), this,
                    mainDesktopPane.getSelectedFrame().getName());
        }

        Point p = this.getLocationOnScreen();
        panel.setLocation(p.x + 15, p.y + 55);
        setLookandFeel(panel);
        panel.setVisible(true);
    }//GEN-LAST:event_createMovieButtonActionPerformed

    private void utilitiesMenuActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_utilitiesMenuActionPerformed

    }//GEN-LAST:event_utilitiesMenuActionPerformed

    private void movieWholeAppMenuItemActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_movieWholeAppMenuItemActionPerformed
        JCreateMovieDialog panel = new JCreateMovieDialog(this, false, this.getContentPane(), this, "JSatTrak App");

        Point p = this.getLocationOnScreen();
        panel.setLocation(p.x + 15, p.y + 55);
        setLookandFeel(panel);
        panel.setVisible(true);
    }

    private void coverageMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_coverageMenuItemActionPerformed

        // check if coverage anaylzer class is null -
        if (coverageAnalyzer == null) {
            coverageAnalyzer = new CoverageAnalyzer(currentJulianDate); // setup
            // new
            // analyzer
            // add coverage analyzer to time update objects
            timeDependentObjects.add(coverageAnalyzer); // add object to time
            // updates

            // update the CA object in any 3D window currently opened
            for (J3DEarthInternalPanel panel : threeDInternalWindowVec) {
                panel.updateCoverageLayerObject(coverageAnalyzer);
            }
            for (J3DEarthPanel panel : threeDWindowVec) {
                panel.updateCoverageLayerObject(coverageAnalyzer);
            }
        }

        // show satellite browser window
        // JTrackingToolSelector trackingBrowser = new
        // JTrackingToolSelector(satHash, gsHash, this); // non-modal version
        JCoverageDialog coverageBrowser = new JCoverageDialog(coverageAnalyzer, currentJulianDate, this,
                twoDWindowVec);

        // create new internal frame window
        String windowName = "Coverage Analysis Options";
        JInternalFrame iframe = new JInternalFrame(windowName, true, true, true, true);

        iframe.setContentPane(coverageBrowser);
        iframe.setSize(530 + 35, 330 + 85); // w,h
        iframe.setLocation(10, 10);

        iframe.setFrameIcon(new javax.swing.ImageIcon(getClass().getResource("/icons/logo/JSatTrakLogo_16.png")));

        coverageBrowser.setIframe(iframe);

        // add close action listener -- to remove window from hash
        iframe.addInternalFrameListener(this);

        iframe.setVisible(true);
        mainDesktopPane.add(iframe);
        try {
            iframe.setSelected(true);
        } catch (java.beans.PropertyVetoException e) {
        }
    }//GEN-LAST:event_coverageMenuItemActionPerformed

    private void toolbar3DWindowButtonActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_toolbar3DWindowButtonActionPerformed
        createNew3dWindow();
    }

    private void lookFeelMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_lookFeelMenuItemActionPerformed
        LookAndFeelJDialog diag = new LookAndFeelJDialog(this, true);
        diag.setLocationRelativeTo(mainDesktopPane);
        setLookandFeel(diag);
        diag.setVisible(true);
    }//GEN-LAST:event_lookFeelMenuItemActionPerformed

    public JTrackingPanel openTrackingToolSelectorWindow(boolean visibility) {
        JTrackingPanel trackingBrowser = new JTrackingPanel(this, currentJulianDate.getDateTimeStr(),
                currentJulianDate, this);

        // add panel to vector for updates
        trackingWindowVec.add(trackingBrowser);

        // create new internal frame window
        String windowName = "Tracking Tool";
        JInternalFrame iframe = new JInternalFrame(windowName, true, true, true, true);

        iframe.setContentPane(trackingBrowser);
        iframe.setSize(400 + 105, 320 + 55); // w,h
        iframe.setLocation(10, 10);

        iframe.setFrameIcon(new javax.swing.ImageIcon(getClass().getResource("/icons/logo/JSatTrakLogo_16.png")));

        // add close action listener -- to remove window from hash
        iframe.addInternalFrameListener(this);

        iframe.setVisible(visibility);
        mainDesktopPane.add(iframe);
        try {
            iframe.setSelected(true);
        } catch (java.beans.PropertyVetoException e) {
        }

        return trackingBrowser;

    } // openTrackingToolSelectorWindow

    public void showGSBrowserInternalFrame() {

        // satBrowser.setVisible(true); // show window

        // create new internal frame window
        String windowName = "Ground Station Browser";
        JInternalFrame iframe = new JInternalFrame(windowName, true, true, true, true);

        // show satellite browser window
        JGroundStationBrowser gsBrowser = new JGroundStationBrowser(this); // non-modal
        // version

        iframe.setContentPane(gsBrowser);
        iframe.setSize(261, 380); // w,h
        iframe.setLocation(5, 5);

        iframe.setFrameIcon(new javax.swing.ImageIcon(getClass().getResource("/icons/logo/JSatTrakLogo_16.png")));

        // add close action listener -- to remove window from hash
        iframe.addInternalFrameListener(this);

        iframe.setVisible(true);
        mainDesktopPane.add(iframe);
        try {
            iframe.setSelected(true);
        } catch (java.beans.PropertyVetoException e) {
        }

    } // showGSBrowserInternalFrame

    /** Open Triton Internal Frame **/
    public void showTritonInternalFrame() {

        // create new internal frame window

        JInternalFrame iframe = new JInternalFrame(GroundSystemsPanel.TITLE, true, true, true, true);
        if (groundSystemsPanel == null) {
            groundSystemsPanel = new GroundSystemsPanel(this); // non-modal
            registerGsListener(groundSystemsPanel);
            registerSatListener(groundSystemsPanel);
        }

        iframe.setContentPane(groundSystemsPanel);
        iframe.setSize(groundSystemsPanel.getPreferredSize()); // w,h
        iframe.setLocation(5, 5);

        iframe.setFrameIcon(new javax.swing.ImageIcon(getClass().getResource("/icons/custom/Triton_logo.png")));

        // add close action listener -- to remove window from hash
        iframe.addInternalFrameListener(this);

        iframe.setVisible(true);
        mainDesktopPane.add(iframe);
        try {
            iframe.setSelected(true);
        } catch (java.beans.PropertyVetoException e) {
        }

    } // showTritonInternalFrame

    public void addInternalFrame(String name, JPanel panel, ImageIcon icon, boolean visibility) {
        String windowName = name;

        JInternalFrame iframe = new JInternalFrame(windowName, true, true, true, true);
        iframe.setContentPane(panel);
        Dimension dim = panel.getPreferredSize();
        dim.setSize(dim.getWidth() + 20, dim.getHeight() + 40);
        iframe.setSize(dim); // w,h

        iframe.setFrameIcon(icon);

        iframe.setLocation(5, 5);
        iframe.setVisible(visibility);

        mainDesktopPane.add(iframe); // TODO: Don't Know how to put it in!!!
        try {
            iframe.setSelected(true);
        } catch (java.beans.PropertyVetoException e) {
        }
    }

    public void addInternalFrame(String name, JInternalFrame frame, ImageIcon icon) {
        String windowName = name;

        JInternalFrame iframe = new JInternalFrame(windowName, true, true, true, true);
        iframe.setContentPane(frame);
        Dimension dim = frame.getPreferredSize();
        dim.setSize(dim.getWidth() + 20, dim.getHeight() + 20);
        iframe.setSize(dim); // w,h

        iframe.setFrameIcon(icon);

        iframe.setLocation(5, 5);
        iframe.setVisible(true);

        mainDesktopPane.add(iframe); // TODO: Don't Know how to put it in!!!
        try {
            iframe.setSelected(true);
        } catch (java.beans.PropertyVetoException e) {
        }
    }

    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JMenuItem aboutMenuItem;
    private javax.swing.JMenuItem closeMenuItem;
    private javax.swing.JMenuItem commandClientMenuItem;
    private javax.swing.JMenuItem commandServerMenuItem;
    private javax.swing.JMenuItem commandShellDesktopMenuItem;
    private javax.swing.JMenuItem commandShellMenuItem;
    private javax.swing.JMenuItem consoleMenuItem;
    private javax.swing.JMenuItem coverageMenuItem;
    private javax.swing.JButton createMovieButton;
    private javax.swing.JTextField dateTextField;
    private javax.swing.JButton decementTimeStepButton;
    private javax.swing.JPanel desktopPanel;
    private javax.swing.JScrollPane desktopScrollPane;
    private javax.swing.JMenuItem exitMenuItem;
    private javax.swing.JMenu fileMenu;
    private javax.swing.JMenu helpMenu;
    private javax.swing.JButton incrementTimeStepButton;
    private javax.swing.JButton jButtonTriton;
    private javax.swing.JLabel jLabel2;
    private javax.swing.JMenuBar jMenuBar1;
    private javax.swing.JSeparator jSeparator1;
    private javax.swing.JSeparator jSeparator10;
    private javax.swing.JSeparator jSeparator11;
    private javax.swing.JSeparator jSeparator2;
    private javax.swing.JSeparator jSeparator3;
    private javax.swing.JSeparator jSeparator4;
    private javax.swing.JSeparator jSeparator5;
    private javax.swing.JSeparator jSeparator6;
    private javax.swing.JSeparator jSeparator7;
    private javax.swing.JSeparator jSeparator8;
    private javax.swing.JSeparator jSeparator9;
    private javax.swing.JMenuItem localTimeMenuItem;
    private javax.swing.JCheckBox localTimeZoneCheckBox;
    private javax.swing.JMenuItem lookFeelMenuItem;
    public javax.swing.JDesktopPane mainDesktopPane;
    private javax.swing.JPanel mainPanel;
    private javax.swing.JToolBar mainToolBar;
    private javax.swing.JMenuItem movieWholeAppMenuItem;
    private javax.swing.JMenuItem new2DWindowMenuItem;
    private javax.swing.JMenu new3DwindowMenu;
    private javax.swing.JMenuItem newExternal3DWindowMenuItem;
    private javax.swing.JMenuItem newInternal3DWindowMenuItem;
    private javax.swing.JMenuItem newMenuItem;
    private javax.swing.JMenuItem nonRealTimeMenuItem;
    private javax.swing.JButton openGSbrowser;
    private javax.swing.JMenuItem openMenuItem;
    private javax.swing.JButton openSatBrowserButton;
    private javax.swing.JButton playBackButton;
    private javax.swing.JButton playButton;
    private javax.swing.JMenu pluginMenu;
    private javax.swing.JMenuItem realTimeMenuItem;
    private javax.swing.JCheckBox realTimeModeCheckBox;
    private javax.swing.JToggleButton recenterToggleButton;
    private javax.swing.JButton resetTimeButton;
    private javax.swing.JInternalFrame satListInternalFrame;
    private javax.swing.JMenuItem saveAsMenuItem;
    private javax.swing.JButton saveButton;
    private javax.swing.JMenuItem saveMenuItem;
    private javax.swing.JButton screenShotButton;
    private javax.swing.JMenuItem showGSBrowserMenuItem;
    private javax.swing.JMenuItem showSatBrowser;
    private javax.swing.JMenu simMenu;
    private javax.swing.JMenuItem simPropMenuItem;
    private javax.swing.JLabel statusAnimationLabel;
    private javax.swing.JLabel statusLabel;
    private javax.swing.JPanel statusPanel;
    private javax.swing.JProgressBar statusProgressBar;
    private javax.swing.JButton stepBackButton;
    private javax.swing.JButton stepForwardTimeButton;
    private javax.swing.JButton stopButton;
    private javax.swing.JMenuItem sysPropsMenuItem;
    private javax.swing.JLabel timeStepLabel;
    private javax.swing.JMenuItem tleLoaderMenuItem;
    private javax.swing.JButton toolbar3DWindowButton;
    private javax.swing.JMenuItem trackToolMenuItem;
    private javax.swing.JMenuItem twoDwindowPropMenuItem;
    private javax.swing.JMenuItem utcTimeMenuItem;
    private javax.swing.JMenu utilitiesMenu;
    private javax.swing.JToggleButton zoomIntoggleButton;
    private javax.swing.JToggleButton zoomOuttoggleButton;

    // End of variables declaration//GEN-END:variables

    // Internal Window Frame Closing Listner
    public void internalFrameClosing(InternalFrameEvent e) {
    }

    public void internalFrameClosed(InternalFrameEvent e) {
        if (!(e.getSource() instanceof JInternalFrame))
            throw new IllegalArgumentException("TODO Better error message");

        Container sourceContainer = ((JInternalFrame) e.getSource()).getContentPane();
        if (sourceContainer instanceof J2DEarthPanel) {
            twoDWindowVec.remove(sourceContainer);
        } else if (sourceContainer instanceof SatPropertyPanel) {
            satPropWindowVec.remove(sourceContainer);
            // System.out.println("Prop window Closed");
        } else if (sourceContainer instanceof SatSettingsPanel) {
            // System.out.println("Settings window Closed");
        } else if (sourceContainer instanceof J3DEarthInternalPanel) {
            threeDInternalWindowVec.remove(sourceContainer);
            // System.out.println("Settings window Closed");
        }

        // System.out.println("2D Windows Open:" + twoDWindowVec.size() );

    } // internalFrameClosed

    @Override
    public void internalFrameOpened(InternalFrameEvent e) {
    }

    @Override
    public void internalFrameIconified(InternalFrameEvent e) {
    }

    @Override
    public void internalFrameDeiconified(InternalFrameEvent e) {
    }

    @Override
    public void internalFrameActivated(InternalFrameEvent e) {
    }

    @Override
    public void internalFrameDeactivated(InternalFrameEvent e) {
    }

    /**
     * addInternalFrame to default location
     */
    public void addInternalFrame(JInternalFrame iframe) {
        addInternalFrame(iframe, 15, 15);
    }

    /**
     * add internal frame to desktop
     */
    public void addInternalFrame(JInternalFrame iframe, int xloc, int yloc) {
        iframe.addInternalFrameListener(this);
        iframe.setLocation(xloc, yloc);
        iframe.setFrameIcon(new javax.swing.ImageIcon(getClass().getResource("/icons/logo/JSatTrakLogo_16.png")));
        iframe.setVisible(true);

        mainDesktopPane.add(iframe);

        // select new frame
        try {
            iframe.setSelected(true);
        } catch (java.beans.PropertyVetoException e) {
        }

        // Figure out which kind of internal frame was added, and add it to
        // Vector
        if (iframe.getContentPane() instanceof SatPropertyPanel) {
            SatPropertyPanel closedPropPanel = (SatPropertyPanel) iframe.getContentPane();
            satPropWindowVec.add(closedPropPanel); // add it to the vector
            closedPropPanel.updateProperties(); // init it
        }

    } // add InternalFrame

    public void updateTleDataInCurrentList() {
        // update TLE data in current list - used mostly after updating TLEs
        JSatBrowser newBrowswer = new JSatBrowser(this, false, this);
        HashMap<String, TLE> tleHash = newBrowswer.getTleHash();

        for (AbstractSatellite sat : sats.values()) {
            if (sat instanceof SatelliteTleSGP4) {
                TLE newTLE = tleHash.get(sat.getName());
                if (newTLE != null) {
                    sat.updateTleData(newTLE);
                }
            }
        } // propgate each sat

        forceRepainting(true);
    } // updateTleDataInCurrentList

    public void addSat2ListByName(String satName) {
        // add sat to list if TLE exsits by name
        JSatBrowser newBrowswer = new JSatBrowser(this, false, this);

        HashMap<String, TLE> tleHash = newBrowswer.getTleHash();

        if (tleHash.containsKey(satName)) {
            // make sat prop object and add it to the list
            try {
                // add sat to list
                SatelliteTleSGP4 prop = new SatelliteTleSGP4(tleHash.get(satName));
                objListPanel.addSat2List(prop);
            } catch (Exception e) {
            }
        }

    } // addSat2ListByName

    // routine to do the screen capture:
    public void createScreenCapture() {
        // just the framePanel // viewsTabbedPane frame3d
        Point pt;
        int width = 0;
        int height = 0;

        // figure out what window is selected (if any), get location on
        // screen / width / height
        if (mainDesktopPane.getSelectedFrame() == null) {
            JOptionPane.showInternalMessageDialog(mainDesktopPane,
                    "A window must be selected to perform a screenshot", "ERROR", JOptionPane.ERROR_MESSAGE);
            return;
        }
        pt = mainDesktopPane.getSelectedFrame().getContentPane().getLocationOnScreen();
        width = mainDesktopPane.getSelectedFrame().getContentPane().getWidth();
        height = mainDesktopPane.getSelectedFrame().getContentPane().getHeight();

        // if a 2d window was selected do a little more math to just get to map
        if (mainDesktopPane.getSelectedFrame().getContentPane() instanceof J2DEarthPanel) {
            // System.out.println("2D WINDOW");
            double aspectRatio = 2.0; // width/height
            int newWidth = 1, newHeight = 1;
            if (height != 0) {
                if (((double) width) / height > aspectRatio) {
                    // label has larger aspect ratio, constraint by height
                    newHeight = height;
                    newWidth = (int) (height * aspectRatio);
                } else {
                    // label has lower aspect ratio
                    newWidth = width;
                    newHeight = (int) (((double) width) / aspectRatio);
                }

                // changes in size
                int deltaW = width - newWidth;
                int deltaH = height - newHeight;

                pt.y = pt.y + (int) (deltaH / 2.0);
                pt.x = pt.x + (int) (deltaW / 2.0);

                width = newWidth;
                height = newHeight;
            } // find scale
        } // if 2D panel

        // not a possible size
        if (height <= 0 || width <= 0) {
            // no screen shot
            JOptionPane.showInternalMessageDialog(mainDesktopPane,
                    "A Screenshot was not possible - too small of size", "ERROR", JOptionPane.ERROR_MESSAGE);
            return;
        }

        // screen shot of just window
        BufferedImage screencapture;
        try {
            screencapture = new Robot().createScreenCapture(new Rectangle(pt.x, pt.y, width, height));
        } catch (AWTException e) {
            System.err.println("ERROR SCREEN CAPTURE:" + e.toString());
            JOptionPane.showInternalMessageDialog(mainDesktopPane, "ERROR SCREEN CAPTURE:" + e.toString(), "ERROR",
                    JOptionPane.ERROR_MESSAGE);
            return;
        }
        try {
            SaveImageFile.saveImageAsType(this, screencapture, "png", "jpg");
        } catch (IOException e) {
            System.out.println("ERROR SCREEN CAPTURE:" + e.toString());
            JOptionPane.showInternalMessageDialog(mainDesktopPane, "ERROR SCREEN CAPTURE:" + e.toString(), "ERROR",
                    JOptionPane.ERROR_MESSAGE);
            return;
        }
    } // createScreenCapture

    public void open2dWindowOptions() {
        if (mainDesktopPane.getSelectedFrame() == null
                || !(mainDesktopPane.getSelectedFrame().getContentPane() instanceof J2DEarthPanel)) {
            JOptionPane.showInternalMessageDialog(mainDesktopPane, "A 2D window must be selected.", "ERROR",
                    JOptionPane.ERROR_MESSAGE);
            return;
        }

        // first check to make sure a 2D window is selected
        // if a 2d window was selected do a little more math to just get to map

        J2DEarthPanel panel = (J2DEarthPanel) mainDesktopPane.getSelectedFrame().getContentPane();

        Point pt = mainDesktopPane.getSelectedFrame().getLocation();

        TwoDViewPropertiesPanel propPanel = new TwoDViewPropertiesPanel(panel, this);

        // create new internal frame window
        JInternalFrame iframe = new JInternalFrame("2D Earth Window Prop.", true, true, true, true);

        iframe.setContentPane(propPanel);
        iframe.setSize(605, 377 + 30); // w, h
        iframe.setLocation(pt.x + 15, pt.y + 20);

        iframe.setFrameIcon(new javax.swing.ImageIcon(getClass().getResource("/icons/logo/JSatTrakLogo_16.png")));

        // save frame
        propPanel.setInternalFrame(iframe);

        // add close action listener -- to remove window from hash
        iframe.addInternalFrameListener(this);

        iframe.setVisible(true);
        mainDesktopPane.add(iframe);
        try {
            iframe.setSelected(true);
        } catch (java.beans.PropertyVetoException e) {
        }

    } // open2dWindowOptions

    public int getRealTimeAnimationRefreshRateMs() {
        return realTimeAnimationRefreshRateMs;
    }

    public void setRealTimeAnimationRefreshRateMs(int realTimeAnimationRefreshRateMs) {
        this.realTimeAnimationRefreshRateMs = realTimeAnimationRefreshRateMs;

        // set refresh rate
        if (realTimeModeCheckBox.isSelected()) {
            animationRefreshRateMs = realTimeAnimationRefreshRateMs; // set real
            // time
            // refresh
            // rate
        } else {
            animationRefreshRateMs = nonRealTimeAnimationRefreshRateMs; // non
            // real
            // time
            // refresh
            // rate
        }

    }

    public int getNonRealTimeAnimationRefreshRateMs() {
        return nonRealTimeAnimationRefreshRateMs;
    }

    public void setNonRealTimeAnimationRefreshRateMs(int nonRealTimeAnimationRefreshRateMs) {
        this.nonRealTimeAnimationRefreshRateMs = nonRealTimeAnimationRefreshRateMs;

        // set refresh rate
        if (realTimeModeCheckBox.isSelected()) {
            animationRefreshRateMs = realTimeAnimationRefreshRateMs; // set real
            // time
            // refresh
            // rate
        } else {
            animationRefreshRateMs = nonRealTimeAnimationRefreshRateMs; // non
            // real
            // time
            // refresh
            // rate
        }
    }

    public void saveApp(String fileName) {

        // testing for now, save the entire application that is running
        // Write to disk with FileOutputStream
        try {
            // Writing UTF-8 Encoded Data
            //BufferedWriter out = new BufferedWriter(new FileWriter(fileName));
            //            Writer out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(fileName), "UTF8"));
            //            XStream xstream = new XStream();
            //            out.write(xstream.toXML(new JstSaveClass(this)));
            //            out.close();

            // SEG - added in version 4.0--- using zip format to save files, files are MUCH SMALLER!
            // try writing to a zipped file
            ZipOutputStream zipOut = new ZipOutputStream(new FileOutputStream(fileName));
            XStream xstream = new XStream();

            // Add ZIP entry to output stream.
            zipOut.putNextEntry(new ZipEntry("JSatTrak.scenario"));

            xstream.toXML(new JstSaveClass(this), zipOut);

            zipOut.closeEntry();
            zipOut.close();

            setStatusMessage("Saved Scenario: " + fileName);

        } catch (Exception e) {
            e.printStackTrace();
            JOptionPane.showMessageDialog(this, "Error Saving File: " + e.toString(), "SAVE ERROR",
                    JOptionPane.ERROR_MESSAGE);
            setStatusMessage("Error Saving File: " + e.toString());
        }

    } // saveApp

    // returns if the scenario was actually closed
    public boolean closeScenario(boolean askIfSure) {
        // close scenario

        // make sure you want to close
        // JOptionPane.showMessageDialog(app, message, "ERROR", JOptionPane.ERROR_MESSAGE);
        if (askIfSure) {
            int answer = JOptionPane.showConfirmDialog(this, "Are you sure you want to close the current scenario?",
                    "Close?", JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE);

            if (answer != JOptionPane.YES_OPTION) {
                return false; // don't close
            }
        }

        // clear satHash
        sats.clear();
        gses.clear();

        // clear console
        console.clearMessages();

        // close all internal windows besides the sat list
        for (JInternalFrame jif : mainDesktopPane.getAllFrames()) {
            if (!(jif.getContentPane() instanceof JObjectListPanel)) {
                jif.dispose(); // don't close sat list
            } else {
                // refresh the list (clear it)
                ((JObjectListPanel) jif.getContentPane()).refreshObjectList();
                jif.setLocation(610, 5); // ini location
            }
        }

        // close all 3D views
        for (J3DEarthPanel panel : threeDWindowVec) {
            panel.closeWindow();
        }

        // clear other window Vectors in case they were not cleared correctly
        twoDWindowVec.clear();
        satPropWindowVec.clear();
        threeDWindowVec.clear();
        threeDInternalWindowVec.clear();

        // reset save file name
        fileSaveAs = null;

        // window count reset
        twoDWindowCount = 0;
        threeDWindowCount = 0;
        threeDInternalWindowCount = 0;

        // clear time dependant objects
        timeDependentObjects.clear();

        // reset coverage analysis
        coverageAnalyzer = null;

        return true;

    } // closeScenario

    /**
     * open file populate scenario
     */
    public void openFile() {

        final JFileChooser fc = new JFileChooser(getFileSaveAs());
        fc.addChoosableFileFilter(new FileNameExtensionFilter("*.jst", "jst"));

        if (fc.showOpenDialog(this) != JFileChooser.APPROVE_OPTION)
            return;
        File file = fc.getSelectedFile();

        // TODO make sure it is okay to close current scenario?
        if (!closeScenario(true))
            return;

        // save file name
        fileSaveAs = file.getAbsolutePath();
        try {
            // before version 4.0 way
            // Read from disk using FileInputStream
            // FileInputStream f_in = new FileInputStream(fileSaveAs);

            // Read object using ObjectInputStream
            // ObjectInputStream obj_in = new JSX.ObjectReader(f_in);// new ObjectInputStream(f_in);  // JSX

            // Read an object
            // Object obj = obj_in.readObject();

            // f_in.close(); // close file

            // BufferedReader in = new BufferedReader(new InputStreamReader(new FileInputStream(getFileSaveAs()), "UTF8"));

            // XStream xstream = new XStream();
            // Object obj = xstream.fromXML(in);

            // v4.0 - use zip file to get data out of the file
            ZipInputStream in = new ZipInputStream(new FileInputStream(getFileSaveAs()));
            ZipEntry entry = in.getNextEntry();
            Object obj = new XStream().fromXML(in);

            if (!(obj instanceof JstSaveClass)) {// it better be
                JOptionPane.showMessageDialog(this,
                        "Error Opening File:" + " Incorrect file format, may be corrupt or an old version",
                        "OPEN ERROR", JOptionPane.ERROR_MESSAGE);
                setStatusMessage("Error Opening File: Incorrect file format");
            }
            // Cast object to a Vector
            JstSaveClass openClass = (JstSaveClass) obj;

            // load satHash carefully
            sats.clear();
            HashMap<String, AbstractSatellite> tempHash = openClass.getSatHash();
            sats.putAll(tempHash);
            for (AbstractSatellite sat : satellites()) {
                // auto-loads 3D models if they are used (call for the side effect)
                sat.setUse3dModel(sat.use3dModel());
            }

            // populate ground station hash
            gses.clear();
            gses.putAll(openClass.getGsHash());

            // update sat List
            objListPanel.refreshObjectList();

            // load other data
            this.currentJulianDate = openClass.getCurrentJulianDate();
            this.realTimeAnimationRefreshRateMs = openClass.getRealTimeAnimationRefreshRateMs();
            this.nonRealTimeAnimationRefreshRateMs = openClass.getNonRealTimeAnimationRefreshRateMs();
            this.currentTimeStepSpeedIndex = openClass.getCurrentTimeStepSpeedIndex();
            this.setLocalTimeModeSelected(openClass.isLocalTimeZoneSelected());
            this.setRealTimeMode(openClass.isRealTimeMode());

            this.epochTimeEqualsCurrentTime = openClass.isEpochTimeEqualsCurrentTime();
            if (!epochTimeEqualsCurrentTime) {
                this.scenarioEpochDate = openClass.getScenarioEpochDate();
            }

            // update parameters based on these new parameters
            updateTimeStepsDataGUI();
            // will reset all internal values correctly for refresh
            setRealTimeAnimationRefreshRateMs(realTimeAnimationRefreshRateMs);

            // location of Object list
            satListInternalFrame.setBounds(openClass.getSatListX(), openClass.getSatListY(),
                    openClass.getSatListWidth(), openClass.getSatListHeight());
            try {
                satListInternalFrame.setSelected(true);
            } catch (PropertyVetoException e) {
                e.printStackTrace();
                JOptionPane.showMessageDialog(this, "Property Vetoed: " + e.toString(), "OPEN ERROR",
                        JOptionPane.ERROR_MESSAGE);
                setStatusMessage("Error Opening File: " + e.toString());
            }

            // wwj offline mode
            this.wwjOfflineMode = openClass.isWwjOfflineMode();
            // set ofline mode
            try {
                gov.nasa.worldwind.WorldWind.getNetworkStatus().setOfflineMode(wwjOfflineMode);
            } catch (Exception ee) {
            }

            // coverage analyzer
            this.coverageAnalyzer = openClass.getCa();
            if (coverageAnalyzer != null) {
                timeDependentObjects.add(coverageAnalyzer);
            }

            // create all the needed 2D windows:
            for (J2DEarthPanelSave j2dp : openClass.getTwoDWindowSaveVec()) {
                // Create new window
                JInternalFrame iframe = createNew2dWindow();
                // get window just created
                J2DEarthPanel newPanel = twoDWindowVec.lastElement();
                // copy settings to this window
                j2dp.copySettings2PanelAndFrame(newPanel, iframe);
            }

            // create all the needed sat prop windows:
            for (SatPropertyPanelSave propPan : openClass.getSatPropWindowSaveVec()) {
                // addInternalFrame(JInternalFrame iframe)
                AbstractSatellite prop = sats.get(propPan.getName());

                // create property Panel:
                SatPropertyPanel newPanel = new SatPropertyPanel(prop);
                // set name - trim excess spaces
                String windowName = prop.getName().trim();

                // create new internal frame window
                JInternalFrame iframe = new JInternalFrame(windowName, true, true, true, true);

                iframe.setContentPane(newPanel); // set contents pane
                iframe.setSize(propPan.getWidth(), propPan.getHeight()); // set
                // size

                iframe.setVisible(true);
                addInternalFrame(iframe, propPan.getXPos(), propPan.getYPos());
            }

            // PUT BEFORE 3D windows so they load correctly though data
            // in them might be funny?
            // update GUI -- this is messing up the 3D views.. they need
            // some time to render
            forceRepainting(true); // force repaint and regeneration of

            // clipping plane distances

            // create all needed 3D windows:

            // create all 3D external windows needed
            for (J3DEarthlPanelSave j3dp : openClass.getThreeDExtWindowSaveVec()) {
                Container iframe = createNew3dWindow();
                // get window just created
                J3DEarthPanel newPanel = threeDWindowVec.lastElement();

                // copy settings to this window
                j3dp.copySettings2PanelAndFrame(newPanel, iframe);
            }
            // create all 3D internal windows needed
            for (J3DEarthlPanelSave j3dp : openClass.getThreeDWindowSaveVec()) {
                JInternalFrame iframe = createNew3DInternalWindow();
                J3DEarthInternalPanel newPanel = threeDInternalWindowVec.lastElement();

                j3dp.copySettings2PanelAndFrame(newPanel, iframe);
            }

            // New 20 March 2009 -- app size and onscreen location
            try {
                this.setLocation(openClass.getScreenLoc());
                this.setSize(openClass.getAppWidth(), openClass.getAppHeight());
                this.repaint();
            } catch (Exception e) {
                System.out.println("Saved File didn't have any information on app size or location.");
            }

            // New 21 August 2009  -- saved look and feel - apply
            try {
                String laf = openClass.getLookFeelString();
                if (laf != null) {
                    LafChanger.changeLaf(this, laf);
                } else {
                    System.out.println("Saved File didn't have any look and feel data.");
                }
            } catch (Exception e) {
                System.out.println("Saved File didn't have any or has invalid look and feel data.");
            }

            setStatusMessage("Opened file: " + file.getAbsolutePath());

            in.close(); //close file
        } catch (Exception e) {
            e.printStackTrace();
            JOptionPane.showMessageDialog(this, "Error Opening File: " + e.toString(), "OPEN ERROR",
                    JOptionPane.ERROR_MESSAGE);
            setStatusMessage("Error Opening File: " + e.toString());
        }
    } // openFile

    /**
     * returns if a file was selected (true) or canceled (false)
     */
    public boolean saveAppAs() {
        final JFileChooser fc = new JFileChooser(getFileSaveAs());
        fc.addChoosableFileFilter(new FileNameExtensionFilter("jst", "jst"));

        if (fc.showSaveDialog(this) == JFileChooser.APPROVE_OPTION) {
            File file = fc.getSelectedFile();

            if (getExtension(file) == null) { // append the extension
                file = new File(file.getAbsolutePath() + ".jst");
            }

            fileSaveAs = file.getAbsolutePath();

            // run save app:
            saveApp(getFileSaveAs());
            return true;
        } // if approve
        return false;
    }// saveAppAs

    public String getVersionString() {
        return versionString;
    }

    public void setVersionString(String versionString) {
        this.versionString = versionString;
    }

    public int getCurrentTimeStepSpeedIndex() {
        return currentTimeStepSpeedIndex;
    }

    public void setCurrentTimeStepSpeedIndex(int currentTimeStepSpeedIndex) {
        this.currentTimeStepSpeedIndex = currentTimeStepSpeedIndex;
    }

    public JDesktopPane getJDesktopPane() {
        return mainDesktopPane;
    }

    public int[] getSatListWHXY() {
        return new int[] { satListInternalFrame.getWidth(), satListInternalFrame.getHeight(),
                satListInternalFrame.getX(), satListInternalFrame.getY() };
    }

    public boolean isRealTimeMode() {
        return realTimeModeCheckBox.isSelected();
    }

    public void setRealTimeMode(boolean bool) {
        if (bool == realTimeModeCheckBox.isSelected()) {
            // already the same
        } else {
            realTimeModeCheckBox.doClick();
        }
    }

    public boolean isLoalTimeModeSelected() {
        return localTimeZoneCheckBox.isSelected();
    }

    public void setLocalTimeModeSelected(boolean bool) {
        if (bool == localTimeZoneCheckBox.isSelected()) {
            // already the same
        } else {
            localTimeZoneCheckBox.doClick();
        }
    }

    // Window Listner Override methods
    public void windowActivated(WindowEvent e) {
    }

    public void windowClosed(WindowEvent e) {
    }

    public void windowDeactivated(WindowEvent e) {
    }

    public void windowDeiconified(WindowEvent e) {
    }

    public void windowIconified(WindowEvent e) {
    }

    public void windowOpened(WindowEvent e) {
    }

    public void windowClosing(WindowEvent e) {

        if (!(e.getSource() instanceof JDialog)) {
            throw new IllegalArgumentException("Source is not a JDialog");
        }
        Container source = ((JDialog) e.getSource()).getContentPane();
        if (source instanceof J3DEarthPanel) {
            threeDWindowVec.remove(source);
            // System.out.println("3D Window Count = " +
            // threeDWindowVec.size());
        } else if (source instanceof JConsole) {
            commandShellMenuItem.setEnabled(true);
        }

    } // windowClosed

    public double getCurrentTimeStep() {
        return timeStepSpeeds[currentTimeStepSpeedIndex];

    }

    public void setTime(long millisecs) {
        currentJulianDate.set(millisecs);

        // update maps ----------------
        // set animation direction = 0
        currentPlayDirection = 0;
        // update graphics
        updateTime();
    }

    /**
     * Set the current time of the app.
     * 
     * @param julianDate
     *            Julian Date
     */
    public void setTime(double julianDate) {
        GregorianCalendar gc = Time.convertJD2Calendar(julianDate);
        setTime(gc.getTimeInMillis());
    }

    public Time getCurrentJulianDate() {
        return currentJulianDate;
    }

    public boolean isEpochTimeEqualsCurrentTime() {
        return epochTimeEqualsCurrentTime;
    }

    public void setEpochTimeEqualsCurrentTime(boolean epochTimeEqualsCurrentTime) {
        this.epochTimeEqualsCurrentTime = epochTimeEqualsCurrentTime;
    }

    public Time getScenarioEpochDate() {
        return scenarioEpochDate;
    }

    public void setScenarioEpochDate(Time scenarioEpochDate) {
        this.scenarioEpochDate = scenarioEpochDate;
    }

    /**
     * Sets the text of the status bar and resets the timer for the message to
     * be erased
     * 
     * @param msg
     *            message to be displayed in the status bar
     */
    public void setStatusMessage(String msg) {
        statusLabel.setText(msg);
        messageTimer.restart();

        // so this shows up in console
        System.out.println(msg);
    }

    /**
     * Starts Statusbar Animation
     */
    public void startStatusAnimation() {
        statusAnimationLabel.setIcon(busyIcons[0]);
        busyIconIndex = 0;
        busyIconTimer.start();
    }

    /**
     * Stops Statusbar Animation
     */
    public void stopStatusAnimation() {
        busyIconTimer.stop();
        statusAnimationLabel.setIcon(idleIcon);
    }

    public void setStatusProgressBarVisible(boolean visiable) {
        statusProgressBar.setVisible(visiable);
    }

    public void setStatusProgressBarText(String txt) {
        statusProgressBar.setString(txt);
    }

    public void setStatusProgressBarValue(int value) {
        statusProgressBar.setValue(value);
    }

    public// running count (for naming)
    Vector<J3DEarthPanel> getThreeDWindowVec() {
        return threeDWindowVec;
    }

    public void setThreeDWindowVec(Vector<J3DEarthPanel> threeDWindowVec) {
        this.threeDWindowVec = threeDWindowVec;
    }

    // WWJ online/offline mode
    public boolean isWwjOfflineMode() {
        return wwjOfflineMode;
    }

    public void setWwjOfflineMode(boolean wwjOfflineMode) {
        this.wwjOfflineMode = wwjOfflineMode;
    }

    /**
     * Display the console window
     * 
     * @param show
     */
    public void showConsoleWindow(boolean show) {
        console.setVisible(show);
    }

    public ConsoleDialog getConsole() {
        return console;
    }

    public String getFileSaveAs() {
        return fileSaveAs;
    }

    // action event for plugins run this method
    protected void runPluginAction(ActionEvent e) {
        String fileName = ((JMenuItem) e.getSource()).getText();
        System.out.println("Running Plugin: " + fileName);

        // runnning bash script
        try {
            beanShellInterp.source("plugins/" + fileName + ".bsh");
        } catch (Exception ee) {
            System.out.println("Error running plugin script: " + ee.toString());
            JOptionPane.showMessageDialog(this, "Error running plugin script: \n" + ee.toString(), "Pluging Error",
                    JOptionPane.ERROR_MESSAGE);
        }
    }

    public CoverageAnalyzer getCoverageAnalyzer() {
        return coverageAnalyzer;
    }

    public void addCustomSat() {
        // start status bar animation
        startStatusAnimation();

        // get a name from the user:
        String name = JOptionPane.showInputDialog(this, "Custom Satellite Name");

        stopStatusAnimation();

        // call overloaded function with name
        addCustomSat(name);
    }

    public void addCustomSat(String name) {
        // add new custom sat to the list
        // is not already in list
        // add to hashTable

        // if nothing given:
        if (name == null || name.equalsIgnoreCase("")) {
            // System.out.println("returned");
            this.setStatusMessage("Custom Satellite Canceled: Either by user or not supplying a name.");
            return;
        }

        CustomSatellite prop = new CustomSatellite(name, this.getScenarioEpochDate());

        sats.put(name, prop);

        // set satellite time to current date
        prop.propogate2JulDate(this.getCurrentJulTime());

        // add item to the Object list tree
        objListPanel.addSat2List(prop);

        // //topSatTreeNode.add( new IconTreeNode(name) );
        // IconTreeNode newNode = new IconTreeNode(name);
        // // assign icon to node
        // newNode.setIcon(new
        // ImageIcon(Toolkit.getDefaultToolkit().getImage(getClass().getResource("/icons/custom/sat_icon_cst.png"))));
        //
        // treeModel.insertNodeInto(newNode, topSatTreeNode,
        // topSatTreeNode.getChildCount());
        //
        //
        // //System.out.println("node added: " + name);
        // objectTree.scrollPathToVisible(getPath(newNode));

        this.setStatusMessage("Custom Satellite Added: " + name);
        // open properties panel
        objListPanel.openCurrentOptions(prop);
    }

    public// 3D windows
    Vector<J3DEarthInternalPanel> getThreeDInternalWindowVec() {
        return threeDInternalWindowVec;
    }

    public// -1 value Means auto adjusting
    // WorldWindGLCanvas so all 3D windows can share resources like 3D models
    WorldWindowGLCanvas getWwd() {
        // if current wwd is null - create one!
        if (wwd == null) {
            wwd = new WorldWindowGLCanvas(); // make first one
        }

        return wwd;
    } // get wwd

    public double getFpsAnimation() {
        return fpsAnimation;
    }

    public Vector<J2DEarthPanel> getTwoDWindowVec() {
        return twoDWindowVec;

    }

    public J2DEarthPanel getNonDisplayed2DEarthPanel(int height) {
        int width = 2 * height;
        // create panel
        J2DEarthPanel earthPanel = new J2DEarthPanel(zoomIntoggleButton, zoomOuttoggleButton, recenterToggleButton,
                currentJulianDate, sun, this);
        // insure that the panel is the correct size and all background painting
        // has been done
        earthPanel.getImageMap().setSize(width, height);
        earthPanel.setSize(width, height);
        earthPanel.rescaleAndSetBackgroundImage();
        // return
        return earthPanel;

    }

    /**
     * @param args
     *            the command line arguments
     *
     *            if run with no command line parameters the GUI is displayed if
     *            run with a command line argument with the path of a script it
     *            will be executed example : java JSatTrak runme.bsh >
     *            satLog.txt (will run the script runme.bsh and save output to
     *            the satLog.txt file)
     */
    public static void main(final String args[]) {

        // no command line arguments
        if (args.length == 0) {

            java.awt.EventQueue.invokeLater(new Runnable() {
                @Override
                public void run() {

                    new JSatTrak().setVisible(true);

                } // run
            });
        } else // no GUI
        {
            // see if command line is a exisiting file (assume it is a .bsh file
            // and try to run it)
            File inScriptFile = new File(args[0]);
            if (inScriptFile.exists()) {
                long t1 = System.currentTimeMillis();
                JSatTrak app = new JSatTrak();
                // runnning bash script
                try {
                    app.beanShellInterp.source(args[0]);
                } catch (Exception ee) {
                    System.err.println("Error running script: " + ee.toString());
                }

                // close JSatTrakApp
                app.dispose();

                long dt = System.currentTimeMillis() - t1;
                System.err.println("Time to Execute (sec): " + dt / 1000.0);

            } // file exsists
            else {
                System.err.println("File does not exist: " + inScriptFile.getAbsolutePath());
            }

            System.exit(0); // exit

        } // program ran with line args
    } // main

    /**
     * @return the sun
     */
    public Sun getSun() {
        return sun;
    }

    // /////////////////////// Satellites /////////////////////////

    /** hastable to store all the statelites currently being processed **/
    private HashMap<String, AbstractSatellite> sats = new HashMap<String, AbstractSatellite>();

    private Set<SatListener> satListeners = new HashSet<SatListener>();

    public void registerSatListener(SatListener sl) {
        satListeners.add(sl);
    }

    public void unRegisterSatListener(SatListener sl) {
        satListeners.remove(sl);
    }

    /**
     * Returns <tt>true</tt> if the app contains a satellite of the given name
     * 
     * @param key
     *            The name whose presence in this app is to be tested
     * @return <tt>true</tt> if this app contains the named satellite
     */
    public boolean containsSat(String name) {
        return sats.containsKey(name);
    }

    /**
     * Returns <tt>true</tt> if this map contains the given satellite
     * 
     * @param sat
     *            satellite whose presence in this app is to be tested
     * @return <tt>true</tt> if this app contains the given satelltie
     */
    public boolean containsSat(AbstractSatellite sat) {
        return sats.containsValue(sat);
    }

    /**
     * Returns the satellite of the given name, or {@code null} if this app
     * contains no satellite of the given name
     */
    public AbstractSatellite getSatellite(String name) {
        return sats.get(name);
    }

    /**
     * Adds a satellite of a given name to the app. The name and satellite must
     * be unique and non-<code>null</code>l
     * 
     * @param name
     *            the name of the satellite to be added
     * @param sat
     *            the satellite to be added
     * @return <code>true</code> if the satellite was successfully added,
     *         <code>false</code> otherwise
     */
    public boolean addSatellite(String name, AbstractSatellite sat) {
        if (name == null || sat == null)
            return false;
        if (sats.containsKey(name) || sats.containsValue(sat))
            return false;
        if (null != sats.put(name, sat))
            return false;
        for (SatListener sl : satListeners) {
            sl.satAdded(sat);
        }
        return true;
    }

    /**
     * Removes the named satellite from the app.
     * 
     * @param name
     *            name of the satellite to be removed
     * @return <code>true</code> if the app previously contained a satellite of
     *         that name
     */
    public boolean removeSatellite(String name) {
        if (sats.containsKey(name)) {
            AbstractSatellite sat = sats.get(name);
            for (SatListener sl : satListeners) {
                sl.satRemoved(sat);
            }
        }
        return sats.remove(name) != null;
    }

    /**
     * Returns all of the satellites currently stored in the app. This
     * collection is 'safe', as in elements can be modified without affecting
     * the app's colelction of satellites
     */
    public Collection<AbstractSatellite> satellites() {
        return new ArrayList<AbstractSatellite>(sats.values());
    }

    /**
     * Returns the names of all satellites currently stored in the app. This
     * collection is 'safe', as in elements can be modified without affecting
     * the app's colelction of satellites
     */
    public Collection<String> getSatNames() {
        return new ArrayList<String>(sats.keySet());
    }

    // /////////////////////// Ground Stations /////////////////////////

    /** hastable to store all the Ground Stations **/
    private HashMap<String, GroundStation> gses = new HashMap<String, GroundStation>();

    private Set<GsListener> gsListeners = new HashSet<GsListener>();

    public void registerGsListener(GsListener gl) {
        gsListeners.add(gl);
    }

    public void unRegisterGsListener(GsListener gl) {
        gsListeners.remove(gl);
    }

    /**
     * Returns <tt>true</tt> if the app contains a ground station of the given
     * name
     * 
     * @param key
     *            The name whose presence in this app is to be tested
     * @return <tt>true</tt> if this app contains the named satellite
     */
    public boolean containsGs(String name) {
        return gses.containsKey(name);
    }

    /**
     * Returns <tt>true</tt> if this map contains the given satellite
     * 
     * @param sat
     *            satellite whose presence in this app is to be tested
     * @return <tt>true</tt> if this app contains the given satelltie
     */
    public boolean containsGs(GroundStation gs) {
        return gses.containsValue(gs);
    }

    /**
     * Returns the ground station of the given name, or {@code null} if this app
     * contains no ground station of the given name
     */
    public GroundStation getGs(String name) {
        return gses.get(name);
    }

    /**
     * Adds a ground station of a given name to the app. The name and ground
     * station must be unique and non-<code>null</code>l
     * 
     * @param name
     *            the name of the ground station to be added
     * @param gs
     *            the ground station to be added
     * @return <code>true</code> if the ground station was successfully added,
     *         <code>false</code> otherwise
     */
    public boolean addGs(String name, GroundStation gs) {
        if (name == null || gs == null)
            return false;
        if (gses.containsKey(name) || gses.containsValue(gs))
            return false;
        if (null != gses.put(name, gs))
            return false;
        for (GsListener gl : gsListeners) {
            gl.gsAdded(gs);
        }
        return true;
    }

    /**
     * Removes the named ground station from the app.
     * 
     * @param name
     *            name of the ground station to be removed
     * @return <code>true</code> if the app previously contained a ground
     *         station of that name
     */
    public boolean removeGs(String name) {
        if (gses.containsKey(name)) {
            GroundStation gs = gses.get(name);
            for (GsListener gl : gsListeners) {
                gl.gsRemoved(gs);
            }
        }
        return gses.remove(name) != null;
    }

    /**
     * Returns all of the ground stations currently stored in the app. This
     * collection is 'safe', as in elements can be modified without affecting
     * the app's colelction of ground stations
     */
    public Collection<GroundStation> groundStations() {
        return new ArrayList<GroundStation>(gses.values());
    }

    /**
     * Returns the names of all ground stations currently stored in the app.
     * This collection is 'safe', as in elements can be modified without
     * affecting the app's colelction of ground stations
     */
    public Collection<String> getGsNames() {
        return new ArrayList<String>(gses.keySet());
    }

    private void setLookandFeel(JDialog iframe) {
        // set icon
        iframe.setIconImage(
                Toolkit.getDefaultToolkit().getImage(getClass().getResource("/icons/logo/JSatTrakLogo_16.png")));
        ////// SEG 23 March 2009 ///////////////////////////////
        // Check look and feel to see if this JDialog should have a deocrated window
        boolean canBeDecoratedByLAF = UIManager.getLookAndFeel().getSupportsWindowDecorations();
        if (canBeDecoratedByLAF != iframe.isUndecorated()) {
            //boolean wasVisible = iframe.isVisible();
            //iframe.setVisible(false);
            iframe.dispose();
            if (!canBeDecoratedByLAF) //|| wasOriginallyDecoratedByOS
            {
                // see the java docs under the method
                // JFrame.setDefaultLookAndFeelDecorated(boolean
                // value) for description of these 2 lines:
                iframe.setUndecorated(false);
                iframe.getRootPane().setWindowDecorationStyle(JRootPane.NONE);

            } else {
                iframe.setUndecorated(true);
                iframe.getRootPane().setWindowDecorationStyle(JRootPane.FRAME);
            }
        }
        ///////////////////////////////// window decoration check
    } // setLookandFeel

}