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