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