source: josm/trunk/src/org/openstreetmap/josm/gui/QuadStateCheckBox.java @ 5241

Revision 2512, 6.9 KB checked in by stoecker, 2 years ago (diff)

i18n updated, fixed files to reduce problems when applying patches, fix #4017

  • Property svn:eol-style set to native
Line 
1// License: GPL. Copyright 2008 by Frederik Ramm and others
2package org.openstreetmap.josm.gui;
3
4import static org.openstreetmap.josm.tools.I18n.tr;
5
6import java.awt.event.ActionEvent;
7import java.awt.event.ActionListener;
8import java.awt.event.ItemListener;
9import java.awt.event.MouseAdapter;
10import java.awt.event.MouseEvent;
11import java.awt.event.MouseListener;
12
13import javax.swing.AbstractAction;
14import javax.swing.ActionMap;
15import javax.swing.ButtonGroup;
16import javax.swing.ButtonModel;
17import javax.swing.Icon;
18import javax.swing.JCheckBox;
19import javax.swing.SwingUtilities;
20import javax.swing.event.ChangeListener;
21import javax.swing.plaf.ActionMapUIResource;
22
23public class QuadStateCheckBox extends JCheckBox {
24
25    public enum State { NOT_SELECTED, SELECTED, UNSET, PARTIAL }
26
27    private final QuadStateDecorator model;
28    private State[] allowed;
29
30    public QuadStateCheckBox(String text, Icon icon, State initial, State[] allowed) {
31        super(text, icon);
32        this.allowed = allowed;
33        // Add a listener for when the mouse is pressed
34        super.addMouseListener(new MouseAdapter() {
35            @Override public void mousePressed(MouseEvent e) {
36                grabFocus();
37                model.nextState();
38            }
39        });
40        // Reset the keyboard action map
41        ActionMap map = new ActionMapUIResource();
42        map.put("pressed", new AbstractAction() {
43            public void actionPerformed(ActionEvent e) {
44                grabFocus();
45                model.nextState();
46            }
47        });
48        map.put("released", null);
49        SwingUtilities.replaceUIActionMap(this, map);
50        // set the model to the adapted model
51        model = new QuadStateDecorator(getModel());
52        setModel(model);
53        setState(initial);
54    }
55    public QuadStateCheckBox(String text, State initial, State[] allowed) {
56        this(text, null, initial, allowed);
57    }
58
59    /** Do not let anyone add mouse listeners */
60    @Override public void addMouseListener(MouseListener l) { }
61    /**
62     * Set the new state.
63     */
64    public void setState(State state) { model.setState(state); }
65    /** Return the current state, which is determined by the
66     * selection status of the model. */
67    public State getState() { return model.getState(); }
68    @Override public void setSelected(boolean b) {
69        if (b) {
70            setState(State.SELECTED);
71        } else {
72            setState(State.NOT_SELECTED);
73        }
74    }
75
76    private class QuadStateDecorator implements ButtonModel {
77        private final ButtonModel other;
78        private QuadStateDecorator(ButtonModel other) {
79            this.other = other;
80        }
81        private void setState(State state) {
82            if (state == State.NOT_SELECTED) {
83                other.setArmed(false);
84                other.setPressed(false);
85                other.setSelected(false);
86                setToolTipText(tr("false: the property is explicitly switched off"));
87            } else if (state == State.SELECTED) {
88                other.setArmed(false);
89                other.setPressed(false);
90                other.setSelected(true);
91                setToolTipText(tr("true: the property is explicitly switched on"));
92            } else if (state == State.PARTIAL) {
93                other.setArmed(true);
94                other.setPressed(true);
95                other.setSelected(true);
96                setToolTipText(tr("partial: different selected objects have different values, do not change"));
97            } else {
98                other.setArmed(true);
99                other.setPressed(true);
100                other.setSelected(false);
101                setToolTipText(tr("unset: do not set this property on the selected objects"));
102            }
103        }
104        /**
105         * The current state is embedded in the selection / armed
106         * state of the model.
107         *
108         * We return the SELECTED state when the checkbox is selected
109         * but not armed, PARTIAL state when the checkbox is
110         * selected and armed (grey) and NOT_SELECTED when the
111         * checkbox is deselected.
112         */
113        private State getState() {
114            if (isSelected() && !isArmed()) {
115                // normal black tick
116                return State.SELECTED;
117            } else if (isSelected() && isArmed()) {
118                // don't care grey tick
119                return State.PARTIAL;
120            } else if (!isSelected() && !isArmed()) {
121                return State.NOT_SELECTED;
122            } else {
123                return State.UNSET;
124            }
125        }
126        /** Rotate to the next allowed state.*/
127        private void nextState() {
128            State current = getState();
129            for (int i = 0; i < allowed.length; i++) {
130                if (allowed[i] == current) {
131                    setState((i == allowed.length-1) ? allowed[0] : allowed[i+1]);
132                    break;
133                }
134            }
135        }
136        /** Filter: No one may change the armed/selected/pressed status except us. */
137        public void setArmed(boolean b) { }
138        public void setSelected(boolean b) { }
139        public void setPressed(boolean b) { }
140        /** We disable focusing on the component when it is not
141         * enabled. */
142        public void setEnabled(boolean b) {
143            setFocusable(b);
144            other.setEnabled(b);
145        }
146        /** All these methods simply delegate to the "other" model
147         * that is being decorated. */
148        public boolean isArmed() { return other.isArmed(); }
149        public boolean isSelected() { return other.isSelected(); }
150        public boolean isEnabled() { return other.isEnabled(); }
151        public boolean isPressed() { return other.isPressed(); }
152        public boolean isRollover() { return other.isRollover(); }
153        public void setRollover(boolean b) { other.setRollover(b); }
154        public void setMnemonic(int key) { other.setMnemonic(key); }
155        public int getMnemonic() { return other.getMnemonic(); }
156        public void setActionCommand(String s) {
157            other.setActionCommand(s);
158        }
159        public String getActionCommand() {
160            return other.getActionCommand();
161        }
162        public void setGroup(ButtonGroup group) {
163            other.setGroup(group);
164        }
165        public void addActionListener(ActionListener l) {
166            other.addActionListener(l);
167        }
168        public void removeActionListener(ActionListener l) {
169            other.removeActionListener(l);
170        }
171        public void addItemListener(ItemListener l) {
172            other.addItemListener(l);
173        }
174        public void removeItemListener(ItemListener l) {
175            other.removeItemListener(l);
176        }
177        public void addChangeListener(ChangeListener l) {
178            other.addChangeListener(l);
179        }
180        public void removeChangeListener(ChangeListener l) {
181            other.removeChangeListener(l);
182        }
183        public Object[] getSelectedObjects() {
184            return other.getSelectedObjects();
185        }
186    }
187}
Note: See TracBrowser for help on using the repository browser.