X-Git-Url: http://gitweb.fperrin.net/?p=GpsPrune.git;a=blobdiff_plain;f=src%2Ftim%2Fprune%2FGpsPrune.java;fp=src%2Ftim%2Fprune%2FGpsPrune.java;h=f396e9e4fdbc31a4c1ca2deb67cbe24eff7c6b76;hp=0000000000000000000000000000000000000000;hb=ce6f2161b8596f7018d6a76bff79bc9e571f35fd;hpb=2d8cb72e84d5cc1089ce77baf1e34ea3ea2f8465 diff --git a/src/tim/prune/GpsPrune.java b/src/tim/prune/GpsPrune.java new file mode 100644 index 0000000..f396e9e --- /dev/null +++ b/src/tim/prune/GpsPrune.java @@ -0,0 +1,332 @@ +package tim.prune; + +import java.awt.BorderLayout; +import java.awt.Component; +import java.awt.Image; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; +import java.io.File; +import java.io.FileNotFoundException; +import java.util.ArrayList; +import java.util.Locale; +import javax.swing.JFrame; +import javax.swing.JSplitPane; +import javax.swing.JToolBar; +import javax.swing.WindowConstants; + +import tim.prune.config.Config; +import tim.prune.config.ConfigException; +import tim.prune.gui.DetailsDisplay; +import tim.prune.gui.IconManager; +import tim.prune.gui.MenuManager; +import tim.prune.gui.SelectorDisplay; +import tim.prune.gui.SidebarController; +import tim.prune.gui.StatusBar; +import tim.prune.gui.Viewport; +import tim.prune.gui.map.MapCanvas; +import tim.prune.gui.profile.ProfileChart; + +/** + * GpsPrune is a tool to visualize, edit, convert and prune GPS data + * Please see the included readme.txt or https://activityworkshop.net + * This software is copyright activityworkshop.net 2006-2018 and made available through the Gnu GPL version 2. + * For license details please see the included license.txt. + * GpsPrune is the main entry point to the application, including initialisation and launch + */ +public class GpsPrune +{ + /** Version number of application, used in about screen and for version check */ + public static final String VERSION_NUMBER = "19.2"; + /** Build number, just used for about screen */ + public static final String BUILD_NUMBER = "363d"; + /** Static reference to App object */ + private static App APP = null; + + /** Program name, used for Frame title and for Macs also on the system bar */ + private static final String PROGRAM_NAME = "GpsPrune"; + + + /** + * Main method + * @param args command line arguments + */ + public static void main(String[] args) + { + Locale locale = null; + String localeCode = null; + String langFilename = null; + String configFilename = null; + ArrayList dataFiles = new ArrayList(); + boolean showUsage = false; + + // Mac OSX - specific properties (Mac insists that this is done as soon as possible) + if (System.getProperty("mrj.version") != null) { + System.setProperty("apple.laf.useScreenMenuBar", "true"); // menu at top of screen + System.setProperty("com.apple.mrj.application.apple.menu.about.name", PROGRAM_NAME); + } + // Loop over given arguments, if any + for (int i=0; i used to specify a configuration file" + + "\n --lang= used to specify language code such as DE" + + "\n --langfile= used to specify an alternative language file\n"); + } + // Initialise configuration if selected + try + { + if (configFilename != null) { + Config.loadFile(new File(configFilename)); + } + else { + Config.loadDefaultFile(); + } + } + catch (ConfigException ce) { + System.err.println("Failed to load config file: " + configFilename); + } + boolean overrideLang = (locale != null); + if (overrideLang) { + // Make sure Config holds chosen language + Config.setConfigString(Config.KEY_LANGUAGE_CODE, localeCode); + } + else { + // Set locale according to Config's language property + String configLang = Config.getConfigString(Config.KEY_LANGUAGE_CODE); + if (configLang != null) { + Locale configLocale = getLanguage(configLang); + if (configLocale != null) {locale = configLocale;} + } + } + I18nManager.init(locale); + // Load the external language file, either from config file or from command line params + if (langFilename == null && !overrideLang) { + // If langfilename is blank on command line parameters then don't use setting from config + langFilename = Config.getConfigString(Config.KEY_LANGUAGE_FILE); + } + if (langFilename != null) + { + try { + I18nManager.addLanguageFile(langFilename); + Config.setConfigString(Config.KEY_LANGUAGE_FILE, langFilename); + } + catch (FileNotFoundException fnfe) { + System.err.println("Failed to load language file: " + langFilename); + Config.setConfigString(Config.KEY_LANGUAGE_FILE, ""); + } + } + // Set up the window and go + launch(dataFiles); + } + + + /** + * Choose a locale based on the given code + * @param inString code for locale + * @return Locale object if available, otherwise null + */ + private static Locale getLanguage(String inString) + { + if (inString.length() == 2) + { + return new Locale(inString); + } + else if (inString.length() == 5 && inString.charAt(2) == '_') + { + return new Locale(inString.substring(0, 2), inString.substring(3)); + } + System.out.println("Unrecognised locale '" + inString + + "' - value should be eg 'DE' or 'DE_ch'"); + return null; + } + + + /** + * Launch the main application + * @param inDataFiles list of data files to load on startup + */ + private static void launch(ArrayList inDataFiles) + { + // Initialise Frame + JFrame frame = new JFrame(PROGRAM_NAME); + APP = new App(frame); + + // make menu + MenuManager menuManager = new MenuManager(APP, APP.getTrackInfo()); + frame.setJMenuBar(menuManager.createMenuBar()); + APP.setMenuManager(menuManager); + UpdateMessageBroker.addSubscriber(menuManager); + // Make toolbar for buttons + JToolBar toolbar = menuManager.createToolBar(); + + // Make main GUI components and add as listeners + SelectorDisplay leftPanel = new SelectorDisplay(APP.getTrackInfo()); + UpdateMessageBroker.addSubscriber(leftPanel); + DetailsDisplay rightPanel = new DetailsDisplay(APP.getTrackInfo()); + UpdateMessageBroker.addSubscriber(rightPanel); + MapCanvas mapDisp = new MapCanvas(APP, APP.getTrackInfo()); + UpdateMessageBroker.addSubscriber(mapDisp); + Viewport viewport = new Viewport(mapDisp); + APP.setViewport(viewport); + ProfileChart profileDisp = new ProfileChart(APP.getTrackInfo()); + UpdateMessageBroker.addSubscriber(profileDisp); + StatusBar statusBar = new StatusBar(); + UpdateMessageBroker.addSubscriber(statusBar); + UpdateMessageBroker.informSubscribers("GpsPrune v" + VERSION_NUMBER); + + // Arrange in the frame using split panes + JSplitPane midSplit = new JSplitPane(JSplitPane.VERTICAL_SPLIT, mapDisp, profileDisp); + midSplit.setResizeWeight(1.0); // allocate as much space as poss to map + JSplitPane rightSplit = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, midSplit, rightPanel); + rightSplit.setResizeWeight(1.0); // allocate as much space as poss to map + + frame.getContentPane().setLayout(new BorderLayout()); + frame.getContentPane().add(toolbar, BorderLayout.NORTH); + JSplitPane leftSplit = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, leftPanel, rightSplit); + frame.getContentPane().add(leftSplit, BorderLayout.CENTER); + frame.getContentPane().add(statusBar, BorderLayout.SOUTH); + + // add closing listener + frame.addWindowListener(new WindowAdapter() { + public void windowClosing(WindowEvent e) { + APP.exit(); + } + }); + // Avoid automatically shutting down if window closed + frame.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE); + + // set window icons of different resolutions (1.6+) + try + { + ArrayList icons = new ArrayList(); + String[] resolutions = {"_16", "_20", "_22", "_24", "_32", "_36", "_48", "_64", "_72", "_96", "_128"}; + for (String r : resolutions) { + icons.add(IconManager.getImageIcon(IconManager.WINDOW_ICON + r + ".png").getImage()); + } + Class d = java.awt.Window.class; + // This is the same as frame.setIconImages(icons) but is compilable also for java1.5 where this isn't available + d.getDeclaredMethod("setIconImages", new Class[]{java.util.List.class}).invoke(frame, icons); + } + catch (Exception e) + { + // setting a list of icon images didn't work, so try with just one image instead + try { + frame.setIconImage(IconManager.getImageIcon(IconManager.WINDOW_ICON + "_16.png").getImage()); + } + catch (Exception e2) {} + } + + // Set up drag-and-drop handler to accept dropped files + frame.setTransferHandler(new FileDropHandler(APP)); + + // finish off and display frame + frame.pack(); + if (!setFrameBoundsFromConfig(frame)) + { + frame.setSize(650, 450); + } + frame.setVisible(true); + // Set position of map/profile splitter + midSplit.setDividerLocation(0.75); + // Update menu (only needed for recent file list) + UpdateMessageBroker.informSubscribers(); + + // Make a full screen toggler + SidebarController fsc = new SidebarController(new Component[] {leftPanel, profileDisp, rightPanel}, + new JSplitPane[] {leftSplit, midSplit, rightSplit}); + APP.setSidebarController(fsc); + // Finally, give the files to load to the App + APP.loadDataFiles(inDataFiles); + } + + + /** + * Set the frame bounds using the saved config setting + * @param inFrame frame to set the bounds of + * @return true on success + */ + private static boolean setFrameBoundsFromConfig(JFrame inFrame) + { + // Try to get bounds from config + String bounds = Config.getConfigString(Config.KEY_WINDOW_BOUNDS); + try + { + String[] boundValues = bounds.split("x"); + if (boundValues.length == 4) + { + int[] elems = new int[4]; + for (int i=0; i<4; i++) { + elems[i] = Integer.parseInt(boundValues[i]); + } + // Make sure width and height aren't stupid + elems[2] = Math.max(elems[2], 400); + elems[3] = Math.max(elems[3], 300); + inFrame.setBounds(elems[0], elems[1], elems[2], elems[3]); + return true; + } + } + catch (NullPointerException npe) {} // if no entry found in config + catch (NumberFormatException nfe) {} // if string couldn't be parsed + return false; + } + + + /** + * Try to guess whether it's a mistyped parameter or a mistyped filename + * @param inParam command line argument + * @return error message + */ + private static String makeUnknownParameterString(String inParam) + { + File file = new File(inParam); + if (file.exists()) + { + if (file.isDirectory()) return "'" + inParam + "' is a directory"; + if (!file.canRead()) return "Cannot read file '" + inParam + "'"; + return "Something wrong with file '" + inParam + "'"; + } + do + { + String name = file.getName(); + file = file.getParentFile(); + if (file != null && file.exists() && file.canRead()) return "Tried to load file '" + inParam + "' but cannot find '" + name + "'"; + } + while (file != null); + + return "Unknown parameter '" + inParam + "'"; + } +}