/* This file is part of RouteConverter. RouteConverter is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. RouteConverter 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 General Public License for more details. You should have received a copy of the GNU General Public License along with RouteConverter; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Copyright (C) 2007 Christian Pesch. All Rights Reserved. */ package slash.navigation.converter.gui; import com.intellij.uiDesigner.core.GridConstraints; import com.intellij.uiDesigner.core.GridLayoutManager; import slash.common.log.LoggingHelper; import slash.common.system.Version; import slash.navigation.babel.BabelException; import slash.navigation.base.NavigationFormatRegistry; import slash.navigation.base.RouteCharacteristics; import slash.navigation.columbus.ColumbusV1000Device; import slash.navigation.common.BoundingBox; import slash.navigation.common.DistanceAndTime; import slash.navigation.common.NavigationPosition; import slash.navigation.common.NumberPattern; import slash.navigation.common.NumberingStrategy; import slash.navigation.common.SimpleNavigationPosition; import slash.navigation.converter.gui.actions.CheckForUpdateAction; import slash.navigation.converter.gui.actions.CompleteFlightPlanAction; import slash.navigation.converter.gui.actions.ConvertRouteToTrackAction; import slash.navigation.converter.gui.actions.ConvertTrackToRouteAction; import slash.navigation.converter.gui.actions.DeletePositionsAction; import slash.navigation.converter.gui.actions.FindPlaceAction; import slash.navigation.converter.gui.actions.InsertPositionsAction; import slash.navigation.converter.gui.actions.MoveSplitPaneDividersAction; import slash.navigation.converter.gui.actions.RevertPositionListAction; import slash.navigation.converter.gui.actions.SendErrorReportAction; import slash.navigation.converter.gui.actions.ShowAboutRouteConverterAction; import slash.navigation.converter.gui.actions.ShowDownloadsAction; import slash.navigation.converter.gui.actions.ShowOptionsAction; import slash.navigation.converter.gui.dnd.PanelDropHandler; import slash.navigation.converter.gui.helpers.ApplicationMenu; import slash.navigation.converter.gui.helpers.AudioPlayer; import slash.navigation.converter.gui.helpers.AutomaticElevationService; import slash.navigation.converter.gui.helpers.AutomaticGeocodingService; import slash.navigation.converter.gui.helpers.ChecksumSender; import slash.navigation.converter.gui.helpers.DownloadNotifier; import slash.navigation.converter.gui.helpers.ElevationServiceFacade; import slash.navigation.converter.gui.helpers.FrameMenu; import slash.navigation.converter.gui.helpers.GeoTagger; import slash.navigation.converter.gui.helpers.GeocodingServiceFacade; import slash.navigation.converter.gui.helpers.GoogleDirectionsService; import slash.navigation.converter.gui.helpers.InsertPositionFacade; import slash.navigation.converter.gui.helpers.MapViewCallbackImpl; import slash.navigation.converter.gui.helpers.MapViewImplementation; import slash.navigation.converter.gui.helpers.PositionAugmenter; import slash.navigation.converter.gui.helpers.ReopenMenuSynchronizer; import slash.navigation.converter.gui.helpers.RouteServiceOperator; import slash.navigation.converter.gui.helpers.RoutingServiceFacade; import slash.navigation.converter.gui.helpers.TagStrategy; import slash.navigation.converter.gui.helpers.UndoMenuSynchronizer; import slash.navigation.converter.gui.helpers.UpdateChecker; import slash.navigation.converter.gui.models.BooleanModel; import slash.navigation.converter.gui.models.ColorModel; import slash.navigation.converter.gui.models.FixMapModeModel; import slash.navigation.converter.gui.models.GoogleMapsServerModel; import slash.navigation.converter.gui.models.ProfileModeModel; import slash.navigation.converter.gui.models.TimeZoneModel; import slash.navigation.converter.gui.models.UnitSystemModel; import slash.navigation.converter.gui.models.UrlDocument; import slash.navigation.converter.gui.panels.BrowsePanel; import slash.navigation.converter.gui.panels.ConvertPanel; import slash.navigation.converter.gui.panels.PanelInTab; import slash.navigation.converter.gui.panels.PhotoPanel; import slash.navigation.converter.gui.panels.PointOfInterestPanel; import slash.navigation.converter.gui.profileview.ProfileView; import slash.navigation.converter.gui.profileview.XAxisModeMenu; import slash.navigation.converter.gui.profileview.YAxisModeMenu; import slash.navigation.datasources.DataSource; import slash.navigation.datasources.DataSourceManager; import slash.navigation.download.Download; import slash.navigation.download.DownloadManager; import slash.navigation.download.FileAndChecksum; import slash.navigation.feedback.domain.RouteFeedback; import slash.navigation.geonames.GeoNamesService; import slash.navigation.googlemaps.GoogleMapsAPIKey; import slash.navigation.googlemaps.GoogleMapsService; import slash.navigation.gui.Application; import slash.navigation.gui.SingleFrameApplication; import slash.navigation.gui.actions.ActionManager; import slash.navigation.gui.actions.ExitAction; import slash.navigation.gui.actions.FrameAction; import slash.navigation.gui.actions.HelpTopicsAction; import slash.navigation.gui.actions.SingletonDialogAction; import slash.navigation.hgt.HgtFiles; import slash.navigation.hgt.HgtFilesService; import slash.navigation.mapview.AbstractMapViewListener; import slash.navigation.mapview.MapView; import slash.navigation.mapview.MapViewCallback; import slash.navigation.nominatim.NominatimService; import slash.navigation.photon.PhotonService; import slash.navigation.rest.Credentials; import slash.navigation.routing.RoutingService; import javax.swing.*; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import javax.xml.bind.UnmarshalException; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.io.File; import java.io.IOException; import java.io.PrintWriter; import java.io.StringWriter; import java.net.URL; import java.text.MessageFormat; import java.util.ArrayList; import java.util.Arrays; import java.util.EventObject; import java.util.HashMap; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.ResourceBundle; import java.util.TimeZone; import java.util.logging.Logger; import java.util.prefs.Preferences; import static com.intellij.uiDesigner.core.GridConstraints.ANCHOR_CENTER; import static com.intellij.uiDesigner.core.GridConstraints.FILL_BOTH; import static com.intellij.uiDesigner.core.GridConstraints.SIZEPOLICY_CAN_GROW; import static com.intellij.uiDesigner.core.GridConstraints.SIZEPOLICY_CAN_SHRINK; import static java.awt.event.KeyEvent.VK_F1; import static java.awt.event.KeyEvent.VK_HELP; import static java.lang.Integer.MAX_VALUE; import static java.util.Arrays.asList; import static java.util.Locale.CHINA; import static java.util.Locale.FRANCE; import static java.util.Locale.GERMANY; import static java.util.Locale.ITALY; import static java.util.Locale.US; import static javax.help.CSH.setHelpIDString; import static javax.swing.JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT; import static javax.swing.JOptionPane.ERROR_MESSAGE; import static javax.swing.JOptionPane.QUESTION_MESSAGE; import static javax.swing.JOptionPane.WARNING_MESSAGE; import static javax.swing.JOptionPane.showMessageDialog; import static javax.swing.JSplitPane.DIVIDER_LOCATION_PROPERTY; import static javax.swing.KeyStroke.getKeyStroke; import static javax.swing.SwingUtilities.invokeLater; import static slash.common.helpers.ExceptionHelper.getLocalizedMessage; import static slash.common.helpers.LocaleHelper.CROATIA; import static slash.common.helpers.LocaleHelper.CZECH; import static slash.common.helpers.LocaleHelper.DENMARK; import static slash.common.helpers.LocaleHelper.NEDERLANDS; import static slash.common.helpers.LocaleHelper.POLAND; import static slash.common.helpers.LocaleHelper.PORTUGAL; import static slash.common.helpers.LocaleHelper.RUSSIA; import static slash.common.helpers.LocaleHelper.SERBIA; import static slash.common.helpers.LocaleHelper.SLOVAKIA; import static slash.common.helpers.LocaleHelper.SPAIN; import static slash.common.io.Directories.getApplicationDirectory; import static slash.common.io.Files.findExistingPath; import static slash.common.io.Files.printArrayToDialogString; import static slash.common.io.Files.recursiveDelete; import static slash.common.io.Files.shortenPath; import static slash.common.io.Files.toUrls; import static slash.common.system.Platform.getJava; import static slash.common.system.Platform.getMaximumMemory; import static slash.common.system.Platform.getPlatform; import static slash.common.system.Platform.isJavaFX7; import static slash.common.system.Platform.isJavaFX8; import static slash.common.system.Platform.isMac; import static slash.common.system.Version.parseVersionFromManifest; import static slash.feature.client.Feature.initializePreferences; import static slash.navigation.common.NumberPattern.Number_Space_Then_Description; import static slash.navigation.common.NumberingStrategy.Absolute_Position_Within_Position_List; import static slash.navigation.converter.gui.helpers.ExternalPrograms.startBrowserForTranslation; import static slash.navigation.converter.gui.helpers.ExternalPrograms.startMail; import static slash.navigation.converter.gui.helpers.MapViewImplementation.EclipseSWT; import static slash.navigation.converter.gui.helpers.MapViewImplementation.JavaFX7; import static slash.navigation.converter.gui.helpers.MapViewImplementation.JavaFX8; import static slash.navigation.converter.gui.helpers.TagStrategy.Create_Backup_In_Subdirectory; import static slash.navigation.converter.gui.models.LocalActionConstants.POSITIONS; import static slash.navigation.datasources.DataSourceManager.FORMAT_XML; import static slash.navigation.datasources.DataSourceManager.V1; import static slash.navigation.download.Action.Copy; import static slash.navigation.gui.helpers.UIHelper.patchUIManager; import static slash.navigation.gui.helpers.UIHelper.startWaitCursor; import static slash.navigation.gui.helpers.UIHelper.stopWaitCursor; /** * A small graphical user interface for the route conversion. * * @author Christian Pesch */ public class RouteConverter extends SingleFrameApplication { protected static final Logger log = Logger.getLogger(RouteConverter.class.getName()); private static final Preferences preferences = Preferences.userNodeForPackage(RouteConverter.class); public static void main(String[] args) { launch(RouteConverter.class, new String[]{RouteConverter.class.getPackage().getName() + ".Untranslated", RouteConverter.class.getName()}, args); } public static RouteConverter getInstance() { return (RouteConverter) Application.getInstance(); } public static ResourceBundle getBundle() { return getInstance().getContext().getBundle(); } public static Preferences getPreferences() { return preferences; } public static String getTitle() { Version version = parseVersionFromManifest(); return MessageFormat.format(getBundle().getString("title"), RouteConverter.getInstance().getEdition(), version.getVersion(), version.getDate()); } protected String getProduct() { return "RouteConverter"; } public String getEdition() { return "RouteConverter Online Edition"; } public String getEditionId() { return "online"; } private static final String MAP_VIEW_PREFERENCE = "mapView"; private static final String SHOW_ALL_POSITIONS_AFTER_LOADING_PREFERENCE = "showAllPositionsAfterLoading"; private static final String RECENTER_AFTER_ZOOMING_PREFERENCE = "recenterAfterZooming"; private static final String SHOW_COORDINATES_PREFERENCE = "showCoordinates"; private static final String SHOW_WAYPOINT_DESCRIPTION_PREFERENCE = "showWaypointDescription"; private static final String TIME_ZONE_PREFERENCE = "timeZone"; private static final String NUMBER_PATTERN_PREFERENCE = "numberPattern"; private static final String NUMBERING_STRATEGY_PREFERENCE = "numberingStrategy"; private static final String SELECT_BY_DISTANCE_PREFERENCE = "selectByDistance"; private static final String SELECT_BY_ORDER_PREFERENCE = "selectByOrder"; private static final String SELECT_BY_SIGNIFICANCE_PREFERENCE = "selectBySignificance"; private static final String FIND_PLACE_PREFERENCE = "findPlace"; private static final String PHOTO_TIMEZONE_PREFERENCE = "photoTimeZone"; private static final String TAG_STRATEGY_PREFERENCE = "tagStrategy"; private static final String MAP_DIVIDER_LOCATION_PREFERENCE = "mapDividerLocation"; private static final String PROFILE_DIVIDER_LOCATION_PREFERENCE = "profileDividerLocation"; private static final String USERNAME_PREFERENCE = "userName"; private static final String PASSWORD_PREFERENCE = "userAuthentication"; private static final String CATEGORY_PREFERENCE = "category"; private static final String ADD_PHOTO_PREFERENCE = "addPhoto"; private static final String ADD_AUDIO_PREFERENCE = "addAudio"; private static final String UPLOAD_ROUTE_PREFERENCE = "uploadRoute"; private static final String DEBUG_PREFERENCE = "debug"; private static final String SHOWED_MISSING_TRANSLATOR_PREFERENCE = "showedMissingTranslator-2.20"; // versioned preference public static final String AUTOMATIC_UPDATE_CHECK_PREFERENCE = "automaticUpdateCheck-2.20"; private NavigationFormatRegistry navigationFormatRegistry = new NavigationFormatRegistry(); private RouteServiceOperator routeServiceOperator; private UpdateChecker updateChecker; private DataSourceManager dataSourceManager; private HgtFilesService hgtFilesService; private ElevationServiceFacade elevationServiceFacade = new ElevationServiceFacade(); private GeocodingServiceFacade geocodingServiceFacade = new GeocodingServiceFacade(); private RoutingServiceFacade routingServiceFacade = new RoutingServiceFacade(); private InsertPositionFacade insertPositionFacade = new InsertPositionFacade(); private BooleanModel showAllPositionsAfterLoading = new BooleanModel(SHOW_ALL_POSITIONS_AFTER_LOADING_PREFERENCE, true); private BooleanModel recenterAfterZooming = new BooleanModel(RECENTER_AFTER_ZOOMING_PREFERENCE, true); private BooleanModel showCoordinates = new BooleanModel(SHOW_COORDINATES_PREFERENCE, false); private BooleanModel showWaypointDescription = new BooleanModel(SHOW_WAYPOINT_DESCRIPTION_PREFERENCE, false); private TimeZoneModel timeZoneModel = new TimeZoneModel(TIME_ZONE_PREFERENCE, TimeZone.getDefault()); private TimeZoneModel photoTimeZoneModel = new TimeZoneModel(PHOTO_TIMEZONE_PREFERENCE, timeZoneModel.getTimeZone()); private FixMapModeModel fixMapModeModel = new FixMapModeModel(); private ColorModel routeColorModel = new ColorModel("route", "C86CB1F3"); // "6CB1F3" w 0.8 alpha private ColorModel trackColorModel = new ColorModel("track", "FF0033FF"); // "0033FF" w 1.0 alpha private UnitSystemModel unitSystemModel = new UnitSystemModel(); private GoogleMapsServerModel googleMapsServerModel = new GoogleMapsServerModel(); private ProfileModeModel profileModeModel = new ProfileModeModel(); protected JPanel contentPane; private JSplitPane mapSplitPane, profileSplitPane; private JTabbedPane tabbedPane; private JPanel convertPanel, pointOfInterestPanel, photoPanel, browsePanel, mapPanel, profilePanel; private MapView mapView; private ProfileView profileView; private static final GridConstraints MAP_PANEL_CONSTRAINTS = new GridConstraints(0, 0, 1, 1, ANCHOR_CENTER, FILL_BOTH, SIZEPOLICY_CAN_SHRINK | SIZEPOLICY_CAN_GROW, SIZEPOLICY_CAN_SHRINK | SIZEPOLICY_CAN_GROW, new Dimension(0, 0), new Dimension(0, 0), new Dimension(MAX_VALUE, MAX_VALUE), 0, true); private static final GridConstraints PROFILE_PANEL_CONSTRAINTS = new GridConstraints(0, 0, 1, 1, ANCHOR_CENTER, FILL_BOTH, SIZEPOLICY_CAN_SHRINK | SIZEPOLICY_CAN_GROW, SIZEPOLICY_CAN_SHRINK | SIZEPOLICY_CAN_GROW, new Dimension(0, 0), new Dimension(0, 0), new Dimension(MAX_VALUE, 300), 0, true); private LazyTabInitializer tabInitializer; private CalculatedDistanceNotifier calculatedDistanceNotifier = new CalculatedDistanceNotifier(); // application lifecycle callbacks protected void startup() { initializeLogging(); show(); checkForMissingTranslator(); updateChecker.implicitCheck(getFrame()); } protected void parseInitialArgs(String[] args) { log.info("Processing initial arguments: " + Arrays.toString(args)); if (args.length > 0) { List<URL> urls = toUrls(args); log.info("Processing urls: " + urls); getConvertPanel().openUrls(urls); } else { getConvertPanel().newFile(); } } protected void parseNewActivationArgs(final String[] args) { log.info("Processing new activation arguments: " + Arrays.toString(args)); if (args.length > 0) { invokeLater(new Runnable() { public void run() { List<URL> urls = toUrls(args); log.info("Processing urls: " + urls); getConvertPanel().openUrls(urls); frame.setVisible(true); frame.toFront(); } }); } } // helper private void initializeLogging() { LoggingHelper loggingHelper = LoggingHelper.getInstance(); loggingHelper.logToFile(); if (preferences.getBoolean(DEBUG_PREFERENCE, false)) { loggingHelper.logToConsole(); } log.info("Started " + getTitle() + " for " + parseVersionFromManifest().getOperationSystem() + " with locale " + Locale.getDefault() + " on " + getJava() + " and " + getPlatform() + " with " + getMaximumMemory() + " MByte heap"); } private List<String> getLanguagesWithActiveTranslators() { List<Locale> localesOfActiveTranslators = asList(CHINA, CROATIA, CZECH, DENMARK, FRANCE, GERMANY, ITALY, NEDERLANDS, POLAND, PORTUGAL, RUSSIA, SERBIA, SLOVAKIA, SPAIN, US); List<String> results = new ArrayList<>(); for (Locale locale : localesOfActiveTranslators) { results.add(locale.getLanguage()); } return results; } private void checkForMissingTranslator() { List<String> activeLanguages = getLanguagesWithActiveTranslators(); String language = Locale.getDefault().getLanguage(); if (!activeLanguages.contains(language) && !preferences.getBoolean(SHOWED_MISSING_TRANSLATOR_PREFERENCE, false)) { JLabel labelTranslatorMissing = new JLabel(MessageFormat.format(getBundle().getString("translator-missing"), language)); labelTranslatorMissing.addMouseListener(new MouseAdapter() { public void mouseClicked(MouseEvent me) { startBrowserForTranslation(frame); } }); showMessageDialog(frame, labelTranslatorMissing, frame.getTitle(), QUESTION_MESSAGE); preferences.putBoolean(SHOWED_MISSING_TRANSLATOR_PREFERENCE, true); } } private void show() { patchUIManager(getBundle(), "OptionPane.yesButtonText", "OptionPane.noButtonText", "OptionPane.cancelButtonText", "FileChooser.openButtonText", "FileChooser.saveButtonText", "FileChooser.cancelButtonText", "FileChooser.acceptAllFileFilterText"); initializePreferences(preferences); addExitListener(new ExitListener() { public boolean canExit(EventObject event) { return getConvertPanel().confirmDiscard(); } public void willExit(EventObject event) { } }); tabInitializer = new LazyTabInitializer(); tabbedPane.addChangeListener(tabInitializer); openFrame(); initializeServices(); initializeActions(); initializeDatasources(); openMapView(); openProfileView(); initializeHelp(); getContext().getActionManager().logUsage(); GoogleMapsAPIKey.logUsage(); } private MapView createMapView(String className) { try { Class<?> aClass = Class.forName(className); return (MapView) aClass.newInstance(); } catch (Throwable t) { log.info("Cannot create " + className + ": " + t); return null; } } private void openFrame() { createFrame(getTitle(), "/slash/navigation/converter/gui/" + getProduct() + ".png", contentPane, null, new FrameMenu().createMenuBar()); if (isMac()) new ApplicationMenu().addApplicationMenuItems(); new Thread(new Runnable() { public void run() { invokeLater(new Runnable() { public void run() { openFrame(contentPane); } }); } }, "FrameOpener").start(); } private void openMapView() { mapSplitPane.addPropertyChangeListener(new MapSplitPaneListener()); try { File file = new File(getApplicationDirectory("tileservers"), "default.xml"); getDownloadManager().executeDownload("RouteConverter Tile Servers", getApiUrl() + V1 + "tileservers/" + FORMAT_XML, Copy, file, new Runnable() { public void run() { invokeLater(new Runnable() { public void run() { setMapView(getMapViewPreference()); } }); } }); } catch (Exception e) { log.warning("Could not download tile servers: " + e); } } public synchronized void setMapView(MapViewImplementation mapViewImplementation) { log.info("Using map view " + mapViewImplementation); setMapViewPreference(mapViewImplementation); if (isMapViewAvailable()) { mapView.removeMapViewListener(calculatedDistanceNotifier); mapPanel.removeAll(); mapView.dispose(); } mapView = createMapView(mapViewImplementation.getClassName()); if (mapView != null) { mapView.addMapViewListener(calculatedDistanceNotifier); } getMapView().initialize(getConvertPanel().getPositionsModel(), getConvertPanel().getPositionsSelectionModel(), getConvertPanel().getCharacteristicsModel(), getMapViewCallback(), getShowAllPositionsAfterLoading(), getRecenterAfterZooming(), getShowCoordinates(), getShowWaypointDescription(), getFixMapModeModel(), getRouteColorModel(), getTrackColorModel(), getUnitSystemModel(), getGoogleMapsServerModel()); @SuppressWarnings({"ThrowableResultOfMethodCallIgnored"}) Throwable cause = getMapView().getInitializationCause(); if (getMapView().getComponent() == null || cause != null) { StringWriter stackTrace = new StringWriter(); cause.printStackTrace(new PrintWriter(stackTrace)); mapPanel.add(new JLabel(MessageFormat.format(getBundle().getString("initialize-map-error"), stackTrace.toString().replaceAll("\n", "<p>"))), MAP_PANEL_CONSTRAINTS); } else { mapPanel.add(getMapView().getComponent(), MAP_PANEL_CONSTRAINTS); } mapPanel.setVisible(true); int location = preferences.getInt(MAP_DIVIDER_LOCATION_PREFERENCE, -1); if (location < 1) { location = 300; } mapSplitPane.setDividerLocation(location); log.fine("Initialized map divider to " + location); } public MapView getMapView() { return mapView; } private void openProfileView() { invokeLater(new Runnable() { public void run() { profileView = new ProfileView(); profileView.initialize(getConvertPanel().getPositionsModel(), getConvertPanel().getPositionsSelectionModel(), getUnitSystemModel(), getProfileModeModel()); profilePanel.add(profileView.getComponent(), PROFILE_PANEL_CONSTRAINTS); profilePanel.setTransferHandler(new PanelDropHandler()); profilePanel.setVisible(true); int location = preferences.getInt(PROFILE_DIVIDER_LOCATION_PREFERENCE, -1); if (location < 2) { location = 888; } profileSplitPane.setDividerLocation(location); log.info("Initialized profile divider to " + location); profileSplitPane.addPropertyChangeListener(new ProfileSplitPaneListener(location)); } }); } protected void shutdown() { if (isMapViewAvailable()) { getMapView().dispose(); } getConvertPanel().dispose(); getHgtFilesService().dispose(); if (positionAugmenter != null) positionAugmenter.dispose(); if (audioPlayer != null) audioPlayer.dispose(); if (geoTagger != null) geoTagger.dispose(); getDataSourceManager().dispose(); getDownloadManager().saveQueue(); super.shutdown(); log.info("Shutdown " + getTitle() + " for " + parseVersionFromManifest().getOperationSystem() + " with locale " + Locale.getDefault() + " on " + getJava() + " and " + getPlatform() + " with " + getMaximumMemory() + " MByte heap"); } public double getSelectByDistancePreference() { return preferences.getDouble(SELECT_BY_DISTANCE_PREFERENCE, 1000); } public void setSelectByDistancePreference(double selectByDistancePreference) { preferences.putDouble(SELECT_BY_DISTANCE_PREFERENCE, selectByDistancePreference); } public int getSelectByOrderPreference() { return preferences.getInt(SELECT_BY_ORDER_PREFERENCE, 5); } public void setSelectByOrderPreference(int selectByOrderPreference) { preferences.putInt(SELECT_BY_ORDER_PREFERENCE, selectByOrderPreference); } public double getSelectBySignificancePreference() { return preferences.getDouble(SELECT_BY_SIGNIFICANCE_PREFERENCE, 20); } public void setSelectBySignificancePreference(double selectBySignificancePreference) { preferences.putDouble(SELECT_BY_SIGNIFICANCE_PREFERENCE, selectBySignificancePreference); } public String getFindPlacePreference() { return preferences.get(FIND_PLACE_PREFERENCE, ""); } public void setFindPlacePreference(String searchPositionPreference) { preferences.put(FIND_PLACE_PREFERENCE, searchPositionPreference); } public Credentials getCredentials() { // important: return the current values since the Credentials is passed to the RemoteCatalog return new Credentials() { public String getUserName() { return preferences.get(USERNAME_PREFERENCE, ""); } public String getPassword() { return new String(preferences.getByteArray(PASSWORD_PREFERENCE, new byte[0])); } }; } public void setUserNamePreference(String userNamePreference, String passwordPreference) { preferences.put(USERNAME_PREFERENCE, userNamePreference); preferences.putByteArray(PASSWORD_PREFERENCE, passwordPreference.getBytes()); } public File getUploadRoutePreference() { File path = new File(preferences.get(UPLOAD_ROUTE_PREFERENCE, "")); return findExistingPath(path); } public void setUploadRoutePreference(File path) { preferences.put(UPLOAD_ROUTE_PREFERENCE, path.getPath()); } public File getAddPhotoPreference() { File path = new File(preferences.get(ADD_PHOTO_PREFERENCE, "")); return findExistingPath(path); } public void setAddPhotoPreference(File path) { preferences.put(ADD_PHOTO_PREFERENCE, path.getPath()); } public File getAddAudioPreference() { File path = new File(preferences.get(ADD_AUDIO_PREFERENCE, "")); return findExistingPath(path); } public void setAddAudioPreference(File path) { preferences.put(ADD_AUDIO_PREFERENCE, path.getPath()); } public TagStrategy getTagStrategyPreference() { try { return TagStrategy.valueOf(preferences.get(TAG_STRATEGY_PREFERENCE, Create_Backup_In_Subdirectory.toString())); } catch (IllegalArgumentException e) { return Create_Backup_In_Subdirectory; } } public void setTagStrategyPreference(TagStrategy tagStrategy) { preferences.put(TAG_STRATEGY_PREFERENCE, tagStrategy.toString()); } public String getCategoryPreference() { return preferences.get(CATEGORY_PREFERENCE, ""); } public void setCategoryPreference(String category) { preferences.put(CATEGORY_PREFERENCE, category); } public NumberPattern getNumberPatternPreference() { try { return NumberPattern.valueOf(preferences.get(NUMBER_PATTERN_PREFERENCE, Number_Space_Then_Description.toString())); } catch (IllegalArgumentException e) { return Number_Space_Then_Description; } } public void setNumberPatternPreference(NumberPattern numberPattern) { preferences.put(NUMBER_PATTERN_PREFERENCE, numberPattern.toString()); } public NumberingStrategy getNumberingStrategyPreference() { try { return NumberingStrategy.valueOf(preferences.get(NUMBERING_STRATEGY_PREFERENCE, Absolute_Position_Within_Position_List.toString())); } catch (IllegalArgumentException e) { return Absolute_Position_Within_Position_List; } } public void setNumberingStrategyPreference(NumberingStrategy numberingStrategy) { preferences.put(NUMBERING_STRATEGY_PREFERENCE, numberingStrategy.toString()); } // helpers for external components public NavigationFormatRegistry getNavigationFormatRegistry() { return navigationFormatRegistry; } public RouteServiceOperator getRouteServiceOperator() { return routeServiceOperator; } public FixMapModeModel getFixMapModeModel() { return fixMapModeModel; } public ColorModel getRouteColorModel() { return routeColorModel; } public ColorModel getTrackColorModel() { return trackColorModel; } public UnitSystemModel getUnitSystemModel() { return unitSystemModel; } public GoogleMapsServerModel getGoogleMapsServerModel() { return googleMapsServerModel; } private ProfileModeModel getProfileModeModel() { return profileModeModel; } // dialogs for external components public void handleBabelError(final BabelException e) { invokeLater(new Runnable() { public void run() { showMessageDialog(frame, MessageFormat.format(getBundle().getString("babel-error"), e.getBabelPath()), frame.getTitle(), ERROR_MESSAGE); } }); } public void handleOpenError(final Throwable throwable, final String path) { invokeLater(new Runnable() { public void run() { StringWriter stackTrace = new StringWriter(); throwable.printStackTrace(new PrintWriter(stackTrace)); log.severe("Open error from " + path + ": " + throwable + "\n" + stackTrace.toString()); JLabel labelOpenError = new JLabel(MessageFormat.format(getBundle().getString("open-error"), shortenPath(path, 60), getLocalizedMessage(throwable))); labelOpenError.addMouseListener(new MouseAdapter() { public void mouseClicked(MouseEvent me) { startMail(frame); } }); showMessageDialog(frame, labelOpenError, frame.getTitle(), ERROR_MESSAGE); } }); } public void handleOpenError(final Throwable throwable, final List<URL> urls) { invokeLater(new Runnable() { public void run() { StringWriter stackTrace = new StringWriter(); throwable.printStackTrace(new PrintWriter(stackTrace)); String dialogUrls = printArrayToDialogString(urls.toArray(new URL[urls.size()])); log.severe("Open error from " + dialogUrls + ": " + throwable + "\n" + stackTrace.toString()); JLabel labelOpenError = new JLabel(MessageFormat.format(getBundle().getString("open-error"), dialogUrls, getLocalizedMessage(throwable))); labelOpenError.addMouseListener(new MouseAdapter() { public void mouseClicked(MouseEvent me) { startMail(frame); } }); showMessageDialog(frame, labelOpenError, frame.getTitle(), ERROR_MESSAGE); } }); } public void handleUnsupportedFormat(final String path) { invokeLater(new Runnable() { public void run() { log.severe("Unsupported format: " + path); showMessageDialog(frame, MessageFormat.format(getBundle().getString("unsupported-format"), shortenPath(path, 60)), frame.getTitle(), WARNING_MESSAGE); } }); } public void handleFileNotFound(final String path) { invokeLater(new Runnable() { public void run() { log.severe("File not found: " + path); showMessageDialog(frame, MessageFormat.format(getBundle().getString("file-not-found"), shortenPath(path, 60)), frame.getTitle(), WARNING_MESSAGE); } }); } // helpers for external components public void sendErrorReport(final String log, final String description, final File file) { getRouteServiceOperator().executeOperation(new RouteServiceOperator.Operation() { public String getName() { return "SendErrorReport"; } public void run() throws IOException { getRouteServiceOperator().getRouteFeedback().sendErrorReport(log, description, file); } }); } public void sendChecksums(final Download download) { final DataSource dataSource = RouteConverter.getInstance().getDataSourceManager(). getDataSourceService().getDataSourceByUrlPrefix(download.getUrl()); if (dataSource == null) { return; } final Map<FileAndChecksum, List<FileAndChecksum>> fileToFragments = new HashMap<>(); fileToFragments.put(download.getFile(), download.getFragments()); getRouteServiceOperator().executeOperation(new RouteServiceOperator.Operation() { public String getName() { return "SendChecksums"; } public void run() throws IOException { getRouteServiceOperator().getRouteFeedback().sendChecksums(dataSource, fileToFragments, download.getUrl()); } }); } public void openPositionList(List<URL> urls, boolean selectConvertPanel) { if (selectConvertPanel) tabbedPane.setSelectedComponent(convertPanel); getConvertPanel().openPositionList(urls); } public UrlDocument getUrlModel() { return getConvertPanel().getUrlModel(); } public void revertPositions() { getConvertPanel().getPositionsModel().revert(); getConvertPanel().clearSelection(); } public void renamePositionList(String name) { getConvertPanel().renamePositionList(name); } public void setRouteCharacteristics(RouteCharacteristics characteristics) { getConvertPanel().getCharacteristicsModel().setSelectedItem(characteristics); } public void selectPositionsInMap(int[] selectedPositions) { if (isMapViewAvailable()) { getMapView().setSelectedPositions(selectedPositions, true); } if (profileView != null) { profileView.setSelectedPositions(selectedPositions, true); } } public void selectPositionsInMap(List<NavigationPosition> selectedPositions) { if (isMapViewAvailable()) { getMapView().setSelectedPositions(selectedPositions); } } public ElevationServiceFacade getElevationServiceFacade() { return elevationServiceFacade; } public GeocodingServiceFacade getGeocodingServiceFacade() { return geocodingServiceFacade; } public InsertPositionFacade getInsertPositionFacade() { return insertPositionFacade; } public RoutingServiceFacade getRoutingServiceFacade() { return routingServiceFacade; } protected HgtFilesService getHgtFilesService() { return hgtFilesService; } public DataSourceManager getDataSourceManager() { return dataSourceManager; } public DownloadManager getDownloadManager() { return getDataSourceManager().getDownloadManager(); } private PositionAugmenter positionAugmenter = null; public synchronized PositionAugmenter getPositionAugmenter() { if (positionAugmenter == null) { positionAugmenter = new PositionAugmenter(getConvertPanel().getPositionsView(), getConvertPanel().getPositionsModel(), getFrame()); } return positionAugmenter; } private AudioPlayer audioPlayer = null; public synchronized AudioPlayer getAudioPlayer() { if (audioPlayer == null) { audioPlayer = new AudioPlayer(getFrame()); } return audioPlayer; } private GeoTagger geoTagger = null; public GeoTagger getGeoTagger() { if (geoTagger == null) { geoTagger = new GeoTagger(getPhotoPanel().getPhotosView(), getPhotoPanel().getPhotosModel(), getFrame()); } return geoTagger; } public TimeZoneModel getPhotoTimeZone() { return photoTimeZoneModel; } protected MapViewCallback getMapViewCallback() { return new MapViewCallbackImpl(); } public int selectPositionsWithinDistanceToPredecessor(double distance) { return getConvertPanel().selectPositionsWithinDistanceToPredecessor(distance); } public int[] selectAllButEveryNthPosition(int order) { return getConvertPanel().selectAllButEveryNthPosition(order); } public int selectInsignificantPositions(double threshold) { return getConvertPanel().selectInsignificantPositions(threshold); } public void clearSelection() { getConvertPanel().clearSelection(); } // map view related helpers public boolean isMapViewAvailable() { return getMapView() != null; } public NavigationPosition getMapCenter() { return isMapViewAvailable() ? getMapView().getCenter() : new SimpleNavigationPosition(-41.0, 41.0); } public BooleanModel getShowAllPositionsAfterLoading() { return showAllPositionsAfterLoading; } public BooleanModel getRecenterAfterZooming() { return recenterAfterZooming; } public BooleanModel getShowCoordinates() { return showCoordinates; } public BooleanModel getShowWaypointDescription() { return showWaypointDescription; } public TimeZoneModel getTimeZone() { return timeZoneModel; } public void showMapBorder(BoundingBox mapBoundingBox) { if (isMapViewAvailable()) { getMapView().showMapBorder(mapBoundingBox); } } public List<MapViewImplementation> getAvailableMapViews() { List<MapViewImplementation> result = new ArrayList<>(); if (isJavaFX8()) { result.add(JavaFX8); } else if (isJavaFX7()) { result.add(JavaFX7); } if (!isMac()) result.add(EclipseSWT); return result; } private MapViewImplementation getPreferredMapView() { return getAvailableMapViews().get(0); } public MapViewImplementation getMapViewPreference() { MapViewImplementation preferred = getPreferredMapView(); try { MapViewImplementation mapView = MapViewImplementation.valueOf(getPreferences().get(MAP_VIEW_PREFERENCE, preferred.toString())); if (getAvailableMapViews().contains(mapView)) { return mapView; } } catch (IllegalArgumentException e) { // intentionally left empty } // really want the first available map view return RouteConverter.this.getPreferredMapView(); } private void setMapViewPreference(MapViewImplementation mapView) { getPreferences().put(MAP_VIEW_PREFERENCE, mapView.name()); } // tab related helpers public boolean isConvertPanelSelected() { return tabbedPane.getSelectedComponent().equals(convertPanel); } protected boolean isPointsOfInterestEnabled() { return false; } public boolean isPointsOfInterestPanelSelected() { return tabbedPane.getSelectedComponent().equals(pointOfInterestPanel); } protected boolean isPhotosEnabled() { return false; } public boolean isPhotosPanelSelected() { return tabbedPane.getSelectedComponent().equals(photoPanel); } public boolean isBrowsePanelSelected() { return tabbedPane.getSelectedComponent().equals(browsePanel); } public ConvertPanel getConvertPanel() { return tabInitializer.getConvertPanel(); } public PointOfInterestPanel getPointOfInterestPanel() { return tabInitializer.getPointsOfInterestPanel(); } public PhotoPanel getPhotoPanel() { return tabInitializer.getPhotoPanel(); } public BrowsePanel getBrowsePanel() { return tabInitializer.getBrowsePanel(); } { // GUI initializer generated by IntelliJ IDEA GUI Designer // >>> IMPORTANT!! <<< // DO NOT EDIT OR ADD ANY CODE HERE! $$$setupUI$$$(); } /** * Method generated by IntelliJ IDEA GUI Designer * >>> IMPORTANT!! <<< * DO NOT edit this method OR call it in your code! * * @noinspection ALL */ private void $$$setupUI$$$() { contentPane = new JPanel(); contentPane.setLayout(new GridLayoutManager(1, 1, new Insets(0, 0, 0, 0), -1, -1)); profileSplitPane = new JSplitPane(); profileSplitPane.setContinuousLayout(true); profileSplitPane.setDividerLocation(888); profileSplitPane.setDividerSize(10); profileSplitPane.setOneTouchExpandable(true); profileSplitPane.setOrientation(0); profileSplitPane.setResizeWeight(0.0); contentPane.add(profileSplitPane, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, null, null, null, 0, false)); mapSplitPane = new JSplitPane(); mapSplitPane.setContinuousLayout(true); mapSplitPane.setDividerLocation(341); mapSplitPane.setDividerSize(10); mapSplitPane.setMinimumSize(new Dimension(-1, -1)); mapSplitPane.setOneTouchExpandable(true); mapSplitPane.setOpaque(true); mapSplitPane.setResizeWeight(1.0); profileSplitPane.setLeftComponent(mapSplitPane); mapPanel = new JPanel(); mapPanel.setLayout(new GridLayoutManager(1, 1, new Insets(0, 0, 0, 0), -1, -1)); mapPanel.setMinimumSize(new Dimension(-1, -1)); mapPanel.setPreferredSize(new Dimension(300, 560)); mapPanel.setVisible(false); mapSplitPane.setLeftComponent(mapPanel); tabbedPane = new JTabbedPane(); tabbedPane.setTabPlacement(1); mapSplitPane.setRightComponent(tabbedPane); convertPanel = new JPanel(); convertPanel.setLayout(new BorderLayout(0, 0)); tabbedPane.addTab(ResourceBundle.getBundle("slash/navigation/converter/gui/RouteConverter").getString("convert-tab"), convertPanel); pointOfInterestPanel = new JPanel(); pointOfInterestPanel.setLayout(new BorderLayout(0, 0)); tabbedPane.addTab(ResourceBundle.getBundle("slash/navigation/converter/gui/RouteConverter").getString("points-of-interest-tab"), pointOfInterestPanel); photoPanel = new JPanel(); photoPanel.setLayout(new BorderLayout(0, 0)); tabbedPane.addTab(ResourceBundle.getBundle("slash/navigation/converter/gui/RouteConverter").getString("photos-tab"), photoPanel); browsePanel = new JPanel(); browsePanel.setLayout(new BorderLayout(0, 0)); tabbedPane.addTab(ResourceBundle.getBundle("slash/navigation/converter/gui/RouteConverter").getString("browse-tab"), browsePanel); profilePanel = new JPanel(); profilePanel.setLayout(new GridLayoutManager(1, 1, new Insets(0, 0, 0, 0), -1, -1)); profilePanel.setMinimumSize(new Dimension(0, 0)); profilePanel.setPreferredSize(new Dimension(0, 0)); profilePanel.setVisible(false); profileSplitPane.setRightComponent(profilePanel); } /** * @noinspection ALL */ public JComponent $$$getRootComponent$$$() { return contentPane; } private class LazyTabInitializer implements ChangeListener { private Map<Component, Runnable> lazyInitializers = new HashMap<>(); private Map<Component, PanelInTab> initialized = new HashMap<>(); LazyTabInitializer() { lazyInitializers.put(convertPanel, new Runnable() { public void run() { PanelInTab panel = new ConvertPanel(); convertPanel.add(panel.getRootComponent()); initialized.put(convertPanel, panel); } }); addTab(pointOfInterestPanel, PointOfInterestPanel.class, isPointsOfInterestEnabled()); addTab(photoPanel, PhotoPanel.class, isPhotosEnabled()); lazyInitializers.put(browsePanel, new Runnable() { public void run() { PanelInTab panel = new BrowsePanel(); browsePanel.add(panel.getRootComponent()); initialized.put(browsePanel, panel); } }); } private void addTab(final JPanel panel, final Class<? extends PanelInTab> panelInTabClass, boolean includePanel) { if (includePanel) lazyInitializers.put(panel, new Runnable() { public void run() { PanelInTab panelInTab; try { panelInTab = panelInTabClass.newInstance(); } catch (InstantiationException | IllegalAccessException e) { throw new RuntimeException(e); } panel.add(panelInTab.getRootComponent()); initialized.put(panel, panelInTab); } }); else { for (int i = 0; i < tabbedPane.getTabCount(); i++) { if (tabbedPane.getComponentAt(i) == panel) { tabbedPane.removeTabAt(i); break; } } } } private synchronized ConvertPanel getConvertPanel() { initialize(convertPanel); return (ConvertPanel) initialized.get(convertPanel); } private synchronized PointOfInterestPanel getPointsOfInterestPanel() { initialize(pointOfInterestPanel); return (PointOfInterestPanel) initialized.get(pointOfInterestPanel); } private synchronized PhotoPanel getPhotoPanel() { initialize(photoPanel); return (PhotoPanel) initialized.get(photoPanel); } private synchronized BrowsePanel getBrowsePanel() { initialize(browsePanel); return (BrowsePanel) initialized.get(browsePanel); } private void initialize(Component selected) { Runnable runnable = lazyInitializers.get(selected); if (runnable != null) { lazyInitializers.remove(selected); startWaitCursor(frame.getRootPane()); try { runnable.run(); } finally { stopWaitCursor(frame.getRootPane()); } } } public void stateChanged(ChangeEvent e) { Component selected = ((JTabbedPane) e.getSource()).getSelectedComponent(); initialize(selected); final PanelInTab panel = initialized.get(selected); final ActionManager actionManager = getContext().getActionManager(); actionManager.setLocalName(panel.getLocalName()); frame.getRootPane().setDefaultButton(panel.getDefaultButton()); panel.initializeSelection(); invokeLater(new Runnable() { public void run() { panel.getFocusComponent().grabFocus(); panel.getFocusComponent().requestFocus(); } }); } } private class MapSplitPaneListener implements PropertyChangeListener { private int location = -1; public void propertyChange(PropertyChangeEvent e) { if (!isMapViewAvailable()) { return; } if (e.getPropertyName().equals(DIVIDER_LOCATION_PROPERTY)) { if (mapSplitPane.getDividerLocation() != location) { location = mapSplitPane.getDividerLocation(); getMapView().resize(); preferences.putInt(MAP_DIVIDER_LOCATION_PREFERENCE, mapSplitPane.getDividerLocation()); log.fine("Changed map divider to " + mapSplitPane.getDividerLocation()); enableActions(); } } } private void enableActions() { ActionManager actionManager = getContext().getActionManager(); actionManager.enable("maximize-map", location < mapSplitPane.getMaximumDividerLocation() - 10); actionManager.enable("maximize-positionlist", location > mapSplitPane.getMinimumDividerLocation() + 10); actionManager.enable("show-map-and-positionlist", location == 1 || location > mapSplitPane.getMaximumDividerLocation() + tabbedPane.getMinimumSize().width - 1); } } private class ProfileSplitPaneListener implements PropertyChangeListener { private int location; private ProfileSplitPaneListener(int location) { this.location = location; enableActions(); } public void propertyChange(PropertyChangeEvent e) { if (e.getPropertyName().equals(DIVIDER_LOCATION_PROPERTY)) { if (profileSplitPane.getDividerLocation() != location) { location = profileSplitPane.getDividerLocation(); if (isMapViewAvailable()) { // make sure the one touch expandable to minimize the map works fine if (location == 1) { getMapView().getComponent().setVisible(false); } else if ((Integer) e.getOldValue() == 1) { getMapView().getComponent().setVisible(true); } getMapView().resize(); } preferences.putInt(PROFILE_DIVIDER_LOCATION_PREFERENCE, profileSplitPane.getDividerLocation()); log.finer("Changed profile divider to " + profileSplitPane.getDividerLocation()); enableActions(); } } } private void enableActions() { ActionManager actionManager = getContext().getActionManager(); actionManager.enable("maximize-map", location < frame.getHeight() - 10); actionManager.enable("maximize-positionlist", location < frame.getHeight() - 10); actionManager.enable("show-profile", location > frame.getHeight() - 80); } } private class CalculatedDistanceNotifier extends AbstractMapViewListener { public void calculatedDistances(Map<Integer, DistanceAndTime> indexToDistanceAndTime) { getConvertPanel().calculatedDistanceFromRouting(indexToDistanceAndTime); } } protected void initializeServices() { System.setProperty("rest", parseVersionFromManifest().getVersion()); RouteFeedback routeFeedback = new RouteFeedback(System.getProperty("feedback", "http://www.routeconverter.com/feedback/"), getApiUrl(), RouteConverter.getInstance().getCredentials()); routeServiceOperator = new RouteServiceOperator(getFrame(), routeFeedback); updateChecker = new UpdateChecker(routeFeedback); DownloadManager downloadManager = new DownloadManager(new File(getApplicationDirectory(), "download-queue.xml")); downloadManager.addDownloadListener(new ChecksumSender()); downloadManager.addDownloadListener(new DownloadNotifier()); dataSourceManager = new DataSourceManager(downloadManager); hgtFilesService = new HgtFilesService(dataSourceManager); timeZoneModel.addChangeListener(new ChangeListener() { public void stateChanged(ChangeEvent e) { ColumbusV1000Device.setTimeZone(timeZoneModel.getTimeZoneId()); } }); } protected void initializeActions() { ActionManager actionManager = getContext().getActionManager(); actionManager.setLocalName(POSITIONS); actionManager.register("exit", new ExitAction()); actionManager.register("print-map", new PrintMapAction(false)); actionManager.register("print-map-and-route", new PrintMapAction(true)); actionManager.register("print-profile", new PrintProfileAction()); actionManager.register("find-place", new FindPlaceAction()); actionManager.register("show-map-and-positionlist", new ShowMapAndPositionListAction()); actionManager.register("show-profile", new ShowProfileAction()); actionManager.register("maximize-map", new MoveSplitPaneDividersAction(mapSplitPane, MAX_VALUE, profileSplitPane, MAX_VALUE)); actionManager.register("maximize-positionlist", new MoveSplitPaneDividersAction(mapSplitPane, 0, profileSplitPane, MAX_VALUE)); actionManager.register("show-all-positions-on-map", new ShowAllPositionsOnMapAction()); actionManager.registerGlobal("delete"); actionManager.register("insert-positions", new InsertPositionsAction()); actionManager.register("delete-positions", new DeletePositionsAction()); actionManager.register("revert-positions", new RevertPositionListAction()); actionManager.register("convert-route-to-track", new ConvertRouteToTrackAction()); actionManager.register("convert-track-to-route", new ConvertTrackToRouteAction()); actionManager.register("show-downloads", new ShowDownloadsAction()); actionManager.register("show-options", new ShowOptionsAction()); actionManager.register("complete-flight-plan", new CompleteFlightPlanAction()); actionManager.register("help-topics", new HelpTopicsAction()); actionManager.register("check-for-update", new CheckForUpdateAction(updateChecker)); actionManager.register("send-error-report", new SendErrorReportAction()); actionManager.register("show-about", createAboutAction()); new XAxisModeMenu(getContext().getMenuBar(), getProfileModeModel()); new YAxisModeMenu(getContext().getMenuBar(), getProfileModeModel()); new UndoMenuSynchronizer(getContext().getMenuBar(), getContext().getUndoManager()); new ReopenMenuSynchronizer(getContext().getMenuBar(), getConvertPanel().getRecentUrlsModel()); } protected SingletonDialogAction createAboutAction() { return new ShowAboutRouteConverterAction(); } private void initializeHelp() { getContext().setHelpBrokerUrl(System.getProperty("help", "http://www.routeconverter.com/javahelp.hs")); // delay JavaHelp initialization ActionListener actionListener = new ActionListener() { public void actionPerformed(ActionEvent event) { getContext().getActionManager().run("help-topics", event); } }; frame.getRootPane().registerKeyboardAction(actionListener, getKeyStroke(VK_HELP, 0), WHEN_ANCESTOR_OF_FOCUSED_COMPONENT); frame.getRootPane().registerKeyboardAction(actionListener, getKeyStroke(VK_F1, 0), WHEN_ANCESTOR_OF_FOCUSED_COMPONENT); setHelpIDString(frame.getRootPane(), "home"); setHelpIDString(browsePanel, "browse-route-catalog"); setHelpIDString(convertPanel, "convert-gps-data"); setHelpIDString(mapPanel, "map"); setHelpIDString(profilePanel, "profile-graph"); } public String getApiUrl() { return System.getProperty("api", "https://api.routeconverter.com/"); } public File getTileServersDirectory() { return getApplicationDirectory("tileservers"); } private File getDataSourcesDirectory() { return getApplicationDirectory("datasources"); } private void initializeDatasources() { try { getDataSourceManager().initialize(getEditionId(), getDataSourcesDirectory()); } catch (Exception e) { log.warning("Could not initialize datasource manager: " + e); getContext().getNotificationManager().showNotification(MessageFormat.format( getBundle().getString("datasource-initialization-error"), getLocalizedMessage(e)), null); if (e instanceof UnmarshalException) { log.info("Deleting old datasources"); try { recursiveDelete(getDataSourcesDirectory()); } catch (IOException e2) { log.warning("Could not delete old datasources: " + e2); } } } initializeElevationServices(); initializeGeocodingServices(); initializeRoutingServices(); // make sure the queue is loaded before any components uses it try { getDownloadManager().loadQueue(); } catch (Exception e) { log.warning("Could not load download manager queue: " + e); getContext().getNotificationManager().showNotification(MessageFormat.format( getBundle().getString("datasource-initialization-error"), getLocalizedMessage(e)), null); } new Thread(new Runnable() { public void run() { scanLocalMapsAndThemes(); try { getDataSourceManager().update(getEditionId(), getApiUrl(), getDataSourcesDirectory()); } catch (Exception e) { log.warning("Could not update datasource manager: " + e); getContext().getNotificationManager().showNotification(MessageFormat.format( getBundle().getString("datasource-update-error"), getLocalizedMessage(e)), null); } updateElevationServices(); updateRoutingServices(); scanRemoteMapsAndThemes(); scanForFilesMissingInQueue(); scanForOutdatedFilesInQueue(); } }, "DataSourceUpdater").start(); } protected void initializeElevationServices() { AutomaticElevationService automaticElevationService = new AutomaticElevationService(getElevationServiceFacade()); getElevationServiceFacade().addElevationService(automaticElevationService); getElevationServiceFacade().setPreferredElevationService(automaticElevationService); getElevationServiceFacade().addElevationService(new GeoNamesService()); getElevationServiceFacade().addElevationService(new GoogleMapsService()); getHgtFilesService().initialize(); for (HgtFiles hgtFile : getHgtFilesService().getHgtFiles()) { getElevationServiceFacade().addElevationService(hgtFile); } } protected void updateElevationServices() { getHgtFilesService().dispose(); getHgtFilesService().initialize(); for (HgtFiles hgtFile : getHgtFilesService().getHgtFiles()) { getElevationServiceFacade().addElevationService(hgtFile); } } protected void initializeGeocodingServices() { AutomaticGeocodingService automaticGeocodingService = new AutomaticGeocodingService(getGeocodingServiceFacade()); getGeocodingServiceFacade().addGeocodingService(automaticGeocodingService); getGeocodingServiceFacade().setPreferredGeocodingService(automaticGeocodingService); getGeocodingServiceFacade().addGeocodingService(new GeoNamesService()); getGeocodingServiceFacade().addGeocodingService(new GoogleMapsService()); getGeocodingServiceFacade().addGeocodingService(new NominatimService()); getGeocodingServiceFacade().addGeocodingService(new PhotonService()); } protected void initializeRoutingServices() { RoutingService service = new GoogleDirectionsService(); getRoutingServiceFacade().addRoutingService(service); getRoutingServiceFacade().setPreferredRoutingService(service); } protected void updateRoutingServices() { } protected void scanLocalMapsAndThemes() { } protected void scanRemoteMapsAndThemes() { } private void scanForFilesMissingInQueue() { // scan for files that are not in the queue but in the file system and put them in the queue if they're in a datasource try { getDataSourceManager().scanForFilesMissingInQueue(); } catch (IOException e) { log.warning("Could not scan for files missing in queue: " + e); getContext().getNotificationManager().showNotification(MessageFormat.format( getBundle().getString("scan-error"), getLocalizedMessage(e)), null); } } private void scanForOutdatedFilesInQueue() { // scan over queue to search for downloads that need to be updated and mark them as outdated try { getDownloadManager().scanForOutdatedFilesInQueue(); } catch (IOException e) { log.warning("Could not scan for outdates files in queue: " + e); getContext().getNotificationManager().showNotification(MessageFormat.format( getBundle().getString("scan-error"), getLocalizedMessage(e)), null); } } private class PrintMapAction extends FrameAction { private boolean withRoute; private PrintMapAction(boolean withRoute) { this.withRoute = withRoute; } public void run() { String title = getConvertPanel().getUrlModel().getShortUrl() + " / " + getConvertPanel().getFormatAndRoutesModel().getSelectedRoute().getName(); getMapView().print(title, withRoute); } } private class ShowMapAndPositionListAction extends FrameAction { public void run() { mapSplitPane.setDividerLocation(getConvertPanel().getRootComponent().getMinimumSize().width); profileSplitPane.setDividerLocation(preferences.getInt(PROFILE_DIVIDER_LOCATION_PREFERENCE, -1)); } } private class ShowProfileAction extends FrameAction { public void run() { int location = preferences.getInt(PROFILE_DIVIDER_LOCATION_PREFERENCE, -1); if (location > frame.getHeight() - 200) { location = frame.getHeight() - 200; } profileSplitPane.setDividerLocation(location); } } private class ShowAllPositionsOnMapAction extends FrameAction { public void run() { if (isMapViewAvailable()) { getMapView().showAllPositions(); } } } private class PrintProfileAction extends FrameAction { public void run() { profileView.print(); } } }