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

Last change on this file since 6113 was 6084, checked in by bastiK, 11 years ago

see #8902 - add missing @Override annotations (patch by shinigami)

  • Property svn:eol-style set to native
File size: 7.2 KB
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 @Override
44 public void actionPerformed(ActionEvent e) {
45 grabFocus();
46 model.nextState();
47 }
48 });
49 map.put("released", null);
50 SwingUtilities.replaceUIActionMap(this, map);
51 // set the model to the adapted model
52 model = new QuadStateDecorator(getModel());
53 setModel(model);
54 setState(initial);
55 }
56 public QuadStateCheckBox(String text, State initial, State[] allowed) {
57 this(text, null, initial, allowed);
58 }
59
60 /** Do not let anyone add mouse listeners */
61 @Override public void addMouseListener(MouseListener l) { }
62 /**
63 * Set the new state.
64 */
65 public void setState(State state) { model.setState(state); }
66 /** Return the current state, which is determined by the
67 * selection status of the model. */
68 public State getState() { return model.getState(); }
69 @Override public void setSelected(boolean b) {
70 if (b) {
71 setState(State.SELECTED);
72 } else {
73 setState(State.NOT_SELECTED);
74 }
75 }
76
77 private class QuadStateDecorator implements ButtonModel {
78 private final ButtonModel other;
79 private QuadStateDecorator(ButtonModel other) {
80 this.other = other;
81 }
82 private void setState(State state) {
83 if (state == State.NOT_SELECTED) {
84 other.setArmed(false);
85 other.setPressed(false);
86 other.setSelected(false);
87 setToolTipText(tr("false: the property is explicitly switched off"));
88 } else if (state == State.SELECTED) {
89 other.setArmed(false);
90 other.setPressed(false);
91 other.setSelected(true);
92 setToolTipText(tr("true: the property is explicitly switched on"));
93 } else if (state == State.PARTIAL) {
94 other.setArmed(true);
95 other.setPressed(true);
96 other.setSelected(true);
97 setToolTipText(tr("partial: different selected objects have different values, do not change"));
98 } else {
99 other.setArmed(true);
100 other.setPressed(true);
101 other.setSelected(false);
102 setToolTipText(tr("unset: do not set this property on the selected objects"));
103 }
104 }
105 /**
106 * The current state is embedded in the selection / armed
107 * state of the model.
108 *
109 * We return the SELECTED state when the checkbox is selected
110 * but not armed, PARTIAL state when the checkbox is
111 * selected and armed (grey) and NOT_SELECTED when the
112 * checkbox is deselected.
113 */
114 private State getState() {
115 if (isSelected() && !isArmed()) {
116 // normal black tick
117 return State.SELECTED;
118 } else if (isSelected() && isArmed()) {
119 // don't care grey tick
120 return State.PARTIAL;
121 } else if (!isSelected() && !isArmed()) {
122 return State.NOT_SELECTED;
123 } else {
124 return State.UNSET;
125 }
126 }
127 /** Rotate to the next allowed state.*/
128 private void nextState() {
129 State current = getState();
130 for (int i = 0; i < allowed.length; i++) {
131 if (allowed[i] == current) {
132 setState((i == allowed.length-1) ? allowed[0] : allowed[i+1]);
133 break;
134 }
135 }
136 }
137 /** Filter: No one may change the armed/selected/pressed status except us. */
138 @Override public void setArmed(boolean b) { }
139 @Override public void setSelected(boolean b) { }
140 @Override public void setPressed(boolean b) { }
141 /** We disable focusing on the component when it is not
142 * enabled. */
143 @Override public void setEnabled(boolean b) {
144 setFocusable(b);
145 other.setEnabled(b);
146 }
147 /** All these methods simply delegate to the "other" model
148 * that is being decorated. */
149 @Override public boolean isArmed() { return other.isArmed(); }
150 @Override public boolean isSelected() { return other.isSelected(); }
151 @Override public boolean isEnabled() { return other.isEnabled(); }
152 @Override public boolean isPressed() { return other.isPressed(); }
153 @Override public boolean isRollover() { return other.isRollover(); }
154 @Override public void setRollover(boolean b) { other.setRollover(b); }
155 @Override public void setMnemonic(int key) { other.setMnemonic(key); }
156 @Override public int getMnemonic() { return other.getMnemonic(); }
157 @Override public void setActionCommand(String s) {
158 other.setActionCommand(s);
159 }
160 @Override public String getActionCommand() {
161 return other.getActionCommand();
162 }
163 @Override public void setGroup(ButtonGroup group) {
164 other.setGroup(group);
165 }
166 @Override public void addActionListener(ActionListener l) {
167 other.addActionListener(l);
168 }
169 @Override public void removeActionListener(ActionListener l) {
170 other.removeActionListener(l);
171 }
172 @Override public void addItemListener(ItemListener l) {
173 other.addItemListener(l);
174 }
175 @Override public void removeItemListener(ItemListener l) {
176 other.removeItemListener(l);
177 }
178 @Override public void addChangeListener(ChangeListener l) {
179 other.addChangeListener(l);
180 }
181 @Override public void removeChangeListener(ChangeListener l) {
182 other.removeChangeListener(l);
183 }
184 @Override public Object[] getSelectedObjects() {
185 return other.getSelectedObjects();
186 }
187 }
188}
Note: See TracBrowser for help on using the repository browser.