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}