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