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

Last change on this file since 3747 was 2512, checked in by stoecker, 14 years ago

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

  • Property svn:eol-style set to native
File size: 6.9 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 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.