001// License: GPL. For details, see LICENSE file.
002package org.openstreetmap.josm.gui.mappaint;
003
004import java.awt.event.ActionEvent;
005import java.util.Arrays;
006
007import javax.swing.AbstractAction;
008import javax.swing.Action;
009import javax.swing.JCheckBoxMenuItem;
010import javax.swing.JMenu;
011
012import org.openstreetmap.josm.Main;
013
014/**
015 * Setting to customize a MapPaint style.
016 *
017 * Can be changed by the user in the right click menu of the mappaint style
018 * dialog.
019 *
020 * Defined in the MapCSS style, e.g.
021 * <pre>
022 * setting::highway_casing {
023 *   type: boolean;
024 *   label: tr("Draw highway casing");
025 *   default: true;
026 * }
027 *
028 * way[highway][setting("highway_casing")] {
029 *   casing-width: 2;
030 *   casing-color: white;
031 * }
032 * </pre>
033 */
034public interface StyleSetting {
035
036    void addMenuEntry(JMenu menu);
037
038    Object getValue();
039
040    /**
041     * A style setting for boolean value (yes / no).
042     */
043    class BooleanStyleSetting implements StyleSetting {
044        public final StyleSource parentStyle;
045        public final String prefKey;
046        public final String label;
047        public final boolean def;
048
049        public BooleanStyleSetting(StyleSource parentStyle, String prefKey, String label, boolean def) {
050            this.parentStyle = parentStyle;
051            this.prefKey = prefKey;
052            this.label = label;
053            this.def = def;
054        }
055
056        @Override
057        public void addMenuEntry(JMenu menu) {
058            final JCheckBoxMenuItem item = new JCheckBoxMenuItem();
059            Action a = new AbstractAction(label) {
060                @Override
061                public void actionPerformed(ActionEvent e) {
062                    boolean b = item.isSelected();
063                    if (b == def) {
064                        Main.pref.put(prefKey, null);
065                    } else {
066                        Main.pref.put(prefKey, b);
067                    }
068                    Main.worker.submit(new MapPaintStyles.MapPaintStyleLoader(Arrays.asList(parentStyle)));
069                }
070            };
071            item.setAction(a);
072            item.setSelected((boolean) getValue());
073            menu.add(item);
074        }
075
076        public static BooleanStyleSetting create(Cascade c, StyleSource parentStyle, String key) {
077            String label = c.get("label", null, String.class);
078            if (label == null) {
079                Main.warn("property 'label' required for boolean style setting");
080                return null;
081            }
082            Boolean def = c.get("default", null, Boolean.class);
083            if (def == null) {
084                Main.warn("property 'default' required for boolean style setting");
085                return null;
086            }
087            String prefKey = parentStyle.url + ":boolean:" + key;
088            return new BooleanStyleSetting(parentStyle, prefKey, label, def);
089        }
090
091        @Override
092        public Object getValue() {
093            String val = Main.pref.get(prefKey, null);
094            if (val == null) return def;
095            return Boolean.valueOf(val);
096        }
097    }
098}