001// License: GPL. For details, see LICENSE file. 002package org.openstreetmap.josm.gui; 003 004import static org.openstreetmap.josm.tools.I18n.tr; 005 006import java.awt.BorderLayout; 007import java.awt.event.KeyEvent; 008import java.util.Arrays; 009import java.util.Collection; 010import java.util.List; 011import java.util.Objects; 012import java.util.concurrent.Callable; 013 014import org.openstreetmap.gui.jmapviewer.FeatureAdapter; 015import org.openstreetmap.gui.jmapviewer.FeatureAdapter.SettingsAdapter; 016import org.openstreetmap.josm.data.UndoRedoHandler; 017import org.openstreetmap.josm.data.coor.conversion.CoordinateFormatManager; 018import org.openstreetmap.josm.data.coor.conversion.DecimalDegreesCoordinateFormat; 019import org.openstreetmap.josm.data.coor.conversion.ICoordinateFormat; 020import org.openstreetmap.josm.data.validation.OsmValidator; 021import org.openstreetmap.josm.gui.layer.ImageryLayer; 022import org.openstreetmap.josm.gui.layer.Layer; 023import org.openstreetmap.josm.gui.layer.TMSLayer; 024import org.openstreetmap.josm.gui.preferences.imagery.ImageryPreference; 025import org.openstreetmap.josm.gui.preferences.map.MapPaintPreference; 026import org.openstreetmap.josm.gui.tagging.presets.TaggingPresets; 027import org.openstreetmap.josm.gui.util.GuiHelper; 028import org.openstreetmap.josm.io.FileWatcher; 029import org.openstreetmap.josm.io.OsmApi; 030import org.openstreetmap.josm.io.OsmApiInitializationException; 031import org.openstreetmap.josm.io.OsmTransferCanceledException; 032import org.openstreetmap.josm.spi.lifecycle.InitializationSequence; 033import org.openstreetmap.josm.spi.lifecycle.InitializationTask; 034import org.openstreetmap.josm.spi.preferences.Config; 035import org.openstreetmap.josm.tools.I18n; 036import org.openstreetmap.josm.tools.ImageProvider; 037import org.openstreetmap.josm.tools.Logging; 038import org.openstreetmap.josm.tools.OpenBrowser; 039import org.openstreetmap.josm.tools.OverpassTurboQueryWizard; 040import org.openstreetmap.josm.tools.PlatformManager; 041import org.openstreetmap.josm.tools.RightAndLefthandTraffic; 042import org.openstreetmap.josm.tools.Shortcut; 043import org.openstreetmap.josm.tools.Tag2Link; 044import org.openstreetmap.josm.tools.Territories; 045import org.openstreetmap.josm.tools.Utils; 046 047/** 048 * JOSM initialization sequence. 049 * @since 14139 050 */ 051public class MainInitialization implements InitializationSequence { 052 053 private final MainApplication application; 054 055 /** 056 * Constructs a new {@code MainInitialization} 057 * @param application Main application. Must not be null 058 */ 059 public MainInitialization(MainApplication application) { 060 this.application = Objects.requireNonNull(application); 061 } 062 063 @Override 064 public List<InitializationTask> beforeInitializationTasks() { 065 return Arrays.asList( 066 new InitializationTask(tr("Initializing coordinate format"), () -> { 067 ICoordinateFormat fmt = CoordinateFormatManager.getCoordinateFormat(Config.getPref().get("coordinates")); 068 if (fmt == null) { 069 fmt = DecimalDegreesCoordinateFormat.INSTANCE; 070 } 071 CoordinateFormatManager.setCoordinateFormat(fmt); 072 }), 073 new InitializationTask(tr("Starting file watcher"), FileWatcher.getDefaultInstance()::start), 074 new InitializationTask(tr("Executing platform startup hook"), 075 () -> PlatformManager.getPlatform().startupHook(MainApplication::askUpdateJava)), 076 new InitializationTask(tr("Building main menu"), application::initializeMainWindow), 077 new InitializationTask(tr("Updating user interface"), () -> { 078 UndoRedoHandler.getInstance().addCommandQueueListener(application.redoUndoListener); 079 // creating toolbar 080 GuiHelper.runInEDTAndWait(() -> MainApplication.contentPanePrivate.add(MainApplication.toolbar.control, BorderLayout.NORTH)); 081 // help shortcut 082 MainApplication.registerActionShortcut(MainApplication.menu.help, 083 Shortcut.registerShortcut("system:help", tr("Help"), KeyEvent.VK_F1, Shortcut.DIRECT)); 084 }), 085 // This needs to be done before RightAndLefthandTraffic::initialize is called 086 new InitializationTask(tr("Initializing internal boundaries data"), Territories::initialize) 087 ); 088 } 089 090 @Override 091 public Collection<InitializationTask> parallelInitializationTasks() { 092 return Arrays.asList( 093 new InitializationTask(tr("Initializing OSM API"), () -> { 094 OsmApi.addOsmApiInitializationListener(api -> { 095 // This checks if there are any layers currently displayed that are now on the blacklist, and removes them. 096 // This is a rare situation - probably only occurs if the user changes the API URL in the preferences menu. 097 // Otherwise they would not have been able to load the layers in the first place because they would have been disabled 098 if (MainApplication.isDisplayingMapView()) { 099 for (Layer l : MainApplication.getLayerManager().getLayersOfType(ImageryLayer.class)) { 100 if (((ImageryLayer) l).getInfo().isBlacklisted()) { 101 Logging.info(tr("Removed layer {0} because it is not allowed by the configured API.", l.getName())); 102 MainApplication.getLayerManager().removeLayer(l); 103 } 104 } 105 } 106 }); 107 // We try to establish an API connection early, so that any API 108 // capabilities are already known to the editor instance. However 109 // if it goes wrong that's not critical at this stage. 110 try { 111 OsmApi.getOsmApi().initialize(null, true); 112 } catch (OsmTransferCanceledException | OsmApiInitializationException | SecurityException e) { 113 Logging.warn(Logging.getErrorMessage(Utils.getRootCause(e))); 114 } 115 }), 116 new InitializationTask(tr("Initializing internal traffic data"), RightAndLefthandTraffic::initialize), 117 new InitializationTask(tr("Initializing validator"), OsmValidator::initialize), 118 new InitializationTask(tr("Initializing presets"), TaggingPresets::initialize), 119 new InitializationTask(tr("Initializing map styles"), MapPaintPreference::initialize), 120 new InitializationTask(tr("Initializing Tag2Link rules"), Tag2Link::initialize), 121 new InitializationTask(tr("Loading imagery preferences"), ImageryPreference::initialize) 122 ); 123 } 124 125 @Override 126 public List<Callable<?>> asynchronousCallableTasks() { 127 return Arrays.asList( 128 OverpassTurboQueryWizard::getInstance 129 ); 130 } 131 132 @Override 133 public List<Runnable> asynchronousRunnableTasks() { 134 return Arrays.asList( 135 TMSLayer::getCache, 136 OsmValidator::initializeTests 137 ); 138 } 139 140 @Override 141 public List<InitializationTask> afterInitializationTasks() { 142 return Arrays.asList( 143 new InitializationTask(tr("Updating user interface"), () -> GuiHelper.runInEDTAndWait(() -> { 144 // hooks for the jmapviewer component 145 FeatureAdapter.registerBrowserAdapter(OpenBrowser::displayUrl); 146 FeatureAdapter.registerImageAdapter(ImageProvider::read); 147 FeatureAdapter.registerTranslationAdapter(I18n::tr); 148 FeatureAdapter.registerLoggingAdapter(name -> Logging.getLogger()); 149 FeatureAdapter.registerSettingsAdapter(new JosmSettingsAdapter()); 150 // UI update 151 MainApplication.toolbar.refreshToolbarControl(); 152 MainApplication.toolbar.control.updateUI(); 153 MainApplication.contentPanePrivate.updateUI(); 154 })) 155 ); 156 } 157 158 private static class JosmSettingsAdapter implements SettingsAdapter { 159 160 @Override 161 public String get(String key, String def) { 162 return Config.getPref().get(key, def); 163 } 164 165 @Override 166 public boolean put(String key, String value) { 167 return Config.getPref().put(key, value); 168 } 169 } 170}