001// License: GPL. For details, see LICENSE file.
002package org.openstreetmap.josm.gui.preferences.map;
003
004import static org.openstreetmap.josm.tools.I18n.marktr;
005import static org.openstreetmap.josm.tools.I18n.tr;
006
007import java.awt.GridBagLayout;
008import java.util.ArrayList;
009import java.util.Collection;
010import java.util.List;
011
012import javax.swing.BorderFactory;
013import javax.swing.JCheckBox;
014import javax.swing.JPanel;
015
016import org.openstreetmap.josm.data.preferences.sources.ExtendedSourceEntry;
017import org.openstreetmap.josm.data.preferences.sources.MapPaintPrefHelper;
018import org.openstreetmap.josm.data.preferences.sources.SourceEntry;
019import org.openstreetmap.josm.data.preferences.sources.SourceProvider;
020import org.openstreetmap.josm.data.preferences.sources.SourceType;
021import org.openstreetmap.josm.gui.MainApplication;
022import org.openstreetmap.josm.gui.mappaint.MapPaintStyles;
023import org.openstreetmap.josm.gui.mappaint.mapcss.MapCSSStyleSource;
024import org.openstreetmap.josm.gui.preferences.PreferenceSetting;
025import org.openstreetmap.josm.gui.preferences.PreferenceSettingFactory;
026import org.openstreetmap.josm.gui.preferences.PreferenceTabbedPane;
027import org.openstreetmap.josm.gui.preferences.SourceEditor;
028import org.openstreetmap.josm.gui.preferences.SubPreferenceSetting;
029import org.openstreetmap.josm.gui.preferences.TabPreferenceSetting;
030import org.openstreetmap.josm.spi.preferences.Config;
031import org.openstreetmap.josm.tools.GBC;
032import org.openstreetmap.josm.tools.Logging;
033
034/**
035 * Preference settings for map paint styles.
036 */
037public class MapPaintPreference implements SubPreferenceSetting {
038    private SourceEditor sources;
039    private JCheckBox enableIconDefault;
040
041    private static final List<SourceProvider> styleSourceProviders = new ArrayList<>();
042
043    /**
044     * Registers a new additional style source provider.
045     * @param provider The style source provider
046     * @return {@code true}, if the provider has been added, {@code false} otherwise
047     */
048    public static boolean registerSourceProvider(SourceProvider provider) {
049        if (provider != null)
050            return styleSourceProviders.add(provider);
051        return false;
052    }
053
054    /**
055     * Factory used to create a new {@code MapPaintPreference}.
056     */
057    public static class Factory implements PreferenceSettingFactory {
058        @Override
059        public PreferenceSetting createPreferenceSetting() {
060            return new MapPaintPreference();
061        }
062    }
063
064    @Override
065    public void addGui(PreferenceTabbedPane gui) {
066        enableIconDefault = new JCheckBox(tr("Enable built-in icon defaults"),
067                Config.getPref().getBoolean("mappaint.icon.enable-defaults", true));
068
069        sources = new MapPaintSourceEditor();
070
071        final JPanel panel = new JPanel(new GridBagLayout());
072        panel.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0));
073
074        panel.add(sources, GBC.eol().fill(GBC.BOTH));
075        panel.add(enableIconDefault, GBC.eol().insets(11, 2, 5, 0));
076
077        final MapPreference mapPref = gui.getMapPreference();
078        mapPref.addSubTab(this, tr("Map Paint Styles"), panel);
079        sources.deferLoading(mapPref, panel);
080    }
081
082    static class MapPaintSourceEditor extends SourceEditor {
083
084        private static final String ICONPREF = "mappaint.icon.sources";
085
086        MapPaintSourceEditor() {
087            super(SourceType.MAP_PAINT_STYLE, Config.getUrls().getJOSMWebsite()+"/styles", styleSourceProviders, true);
088        }
089
090        @Override
091        public Collection<? extends SourceEntry> getInitialSourcesList() {
092            return MapPaintPrefHelper.INSTANCE.get();
093        }
094
095        @Override
096        public boolean finish() {
097            return doFinish(MapPaintPrefHelper.INSTANCE, ICONPREF);
098        }
099
100        @Override
101        public Collection<ExtendedSourceEntry> getDefault() {
102            return MapPaintPrefHelper.INSTANCE.getDefault();
103        }
104
105        @Override
106        public Collection<String> getInitialIconPathsList() {
107            return Config.getPref().getList(ICONPREF, null);
108        }
109
110        @Override
111        public String getStr(I18nString ident) {
112            switch (ident) {
113            case AVAILABLE_SOURCES:
114                return tr("Available styles:");
115            case ACTIVE_SOURCES:
116                return tr("Active styles:");
117            case NEW_SOURCE_ENTRY_TOOLTIP:
118                return tr("Add a new style by entering filename or URL");
119            case NEW_SOURCE_ENTRY:
120                return tr("New style entry:");
121            case REMOVE_SOURCE_TOOLTIP:
122                return tr("Remove the selected styles from the list of active styles");
123            case EDIT_SOURCE_TOOLTIP:
124                return tr("Edit the filename or URL for the selected active style");
125            case ACTIVATE_TOOLTIP:
126                return tr("Add the selected available styles to the list of active styles");
127            case RELOAD_ALL_AVAILABLE:
128                return marktr("Reloads the list of available styles from ''{0}''");
129            case LOADING_SOURCES_FROM:
130                return marktr("Loading style sources from ''{0}''");
131            case FAILED_TO_LOAD_SOURCES_FROM:
132                return marktr("<html>Failed to load the list of style sources from<br>"
133                        + "''{0}''.<br>"
134                        + "<br>"
135                        + "Details (untranslated):<br>{1}</html>");
136            case FAILED_TO_LOAD_SOURCES_FROM_HELP_TOPIC:
137                return "/Preferences/Styles#FailedToLoadStyleSources";
138            case ILLEGAL_FORMAT_OF_ENTRY:
139                return marktr("Warning: illegal format of entry in style list ''{0}''. Got ''{1}''");
140            default: throw new AssertionError();
141            }
142        }
143
144        @Override
145        protected String getTitleForSourceEntry(SourceEntry entry) {
146            final String title = getTitleFromSourceEntry(entry);
147            return title != null ? title : super.getTitleForSourceEntry(entry);
148        }
149    }
150
151    /**
152     * Returns title from a source entry.
153     * @param entry source entry
154     * @return title
155     * @see MapCSSStyleSource#title
156     */
157    public static String getTitleFromSourceEntry(SourceEntry entry) {
158        try {
159            final MapCSSStyleSource css = new MapCSSStyleSource(entry);
160            css.loadStyleSource();
161            if (css.title != null && !css.title.isEmpty()) {
162                return css.title;
163            }
164        } catch (RuntimeException ignore) { // NOPMD
165            Logging.debug(ignore);
166        }
167        return null;
168    }
169
170    @Override
171    public boolean ok() {
172        boolean reload = Config.getPref().putBoolean("mappaint.icon.enable-defaults", enableIconDefault.isSelected());
173        reload |= sources.finish();
174        if (reload) {
175            MapPaintStyles.readFromPreferences();
176        }
177        if (MainApplication.isDisplayingMapView()) {
178            MapPaintStyles.getStyles().clearCached();
179        }
180        return false;
181    }
182
183    /**
184     * Initialize the styles
185     */
186    public static void initialize() {
187        MapPaintStyles.readFromPreferences();
188    }
189
190    @Override
191    public boolean isExpert() {
192        return false;
193    }
194
195    @Override
196    public TabPreferenceSetting getTabPreferenceSetting(final PreferenceTabbedPane gui) {
197        return gui.getMapPreference();
198    }
199}