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