source: josm/trunk/src/org/openstreetmap/josm/gui/conflict/tags/MultiValueCellEditor.java@ 8512

Last change on this file since 8512 was 8512, checked in by Don-vip, 9 years ago

checkstyle: redundant modifiers

  • Property svn:eol-style set to native
File size: 9.2 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.gui.conflict.tags;
3
4import static org.openstreetmap.josm.tools.I18n.tr;
5
6import java.awt.Component;
7import java.awt.Font;
8import java.awt.event.FocusAdapter;
9import java.awt.event.FocusEvent;
10import java.awt.event.ItemEvent;
11import java.awt.event.ItemListener;
12import java.awt.event.KeyEvent;
13import java.util.concurrent.CopyOnWriteArrayList;
14
15import javax.swing.AbstractCellEditor;
16import javax.swing.DefaultComboBoxModel;
17import javax.swing.JLabel;
18import javax.swing.JList;
19import javax.swing.JTable;
20import javax.swing.ListCellRenderer;
21import javax.swing.UIManager;
22import javax.swing.table.TableCellEditor;
23
24import org.openstreetmap.josm.Main;
25import org.openstreetmap.josm.gui.widgets.JosmComboBox;
26
27/**
28 * This is a table cell editor for selecting a possible tag value from a list of
29 * proposed tag values. The editor also allows to select all proposed valued or
30 * to remove the tag.
31 *
32 * The editor responds intercepts some keys and interprets them as navigation keys. It
33 * forwards navigation events to {@link NavigationListener}s registred with this editor.
34 * You should register the parent table using this editor as {@link NavigationListener}.
35 *
36 * {@link KeyEvent#VK_ENTER} and {@link KeyEvent#VK_TAB} trigger a {@link NavigationListener#gotoNextDecision()}.
37 */
38public class MultiValueCellEditor extends AbstractCellEditor implements TableCellEditor {
39
40 /**
41 * Defines the interface for an object implementing navigation between rows
42 */
43 public interface NavigationListener {
44 /** Call when need to go to next row */
45 void gotoNextDecision();
46 /** Call when need to go to previous row */
47 void gotoPreviousDecision();
48 }
49
50 /** the combo box used as editor */
51 private JosmComboBox<Object> editor;
52 private DefaultComboBoxModel<Object> editorModel;
53 private CopyOnWriteArrayList<NavigationListener> listeners;
54
55 /**
56 * Adds a navigation listener.
57 * @param listener navigation listener to add
58 */
59 public void addNavigationListener(NavigationListener listener) {
60 if (listener != null) {
61 listeners.addIfAbsent(listener);
62 }
63 }
64
65 /**
66 * Removes a navigation listener.
67 * @param listener navigation listener to remove
68 */
69 public void removeNavigationListener(NavigationListener listener) {
70 listeners.remove(listener);
71 }
72
73 protected void fireGotoNextDecision() {
74 for (NavigationListener l: listeners) {
75 l.gotoNextDecision();
76 }
77 }
78
79 protected void fireGotoPreviousDecision() {
80 for (NavigationListener l: listeners) {
81 l.gotoPreviousDecision();
82 }
83 }
84
85 /**
86 * Construct a new {@link MultiValueCellEditor}
87 */
88 public MultiValueCellEditor() {
89 editorModel = new DefaultComboBoxModel<>();
90 editor = new JosmComboBox<Object>(editorModel) {
91 @Override
92 public void processKeyEvent(KeyEvent e) {
93 if (e.getID() == KeyEvent.KEY_PRESSED && e.getKeyCode() == KeyEvent.VK_ENTER) {
94 fireGotoNextDecision();
95 } else if (e.getID() == KeyEvent.KEY_PRESSED && e.getKeyCode() == KeyEvent.VK_TAB) {
96 if (e.isShiftDown()) {
97 fireGotoPreviousDecision();
98 } else {
99 fireGotoNextDecision();
100 }
101 } else if (e.getID() == KeyEvent.KEY_PRESSED && e.getKeyCode() == KeyEvent.VK_DELETE || e.getKeyCode() == KeyEvent.VK_BACK_SPACE) {
102 if (editorModel.getIndexOf(MultiValueDecisionType.KEEP_NONE) > 0) {
103 editorModel.setSelectedItem(MultiValueDecisionType.KEEP_NONE);
104 fireGotoNextDecision();
105 }
106 } else if (e.getID() == KeyEvent.KEY_PRESSED && e.getKeyCode() == KeyEvent.VK_ESCAPE) {
107 cancelCellEditing();
108 }
109 super.processKeyEvent(e);
110 }
111 };
112 editor.addFocusListener(
113 new FocusAdapter() {
114 @Override
115 public void focusGained(FocusEvent e) {
116 editor.showPopup();
117 }
118 }
119 );
120 editor.addItemListener(
121 new ItemListener() {
122 @Override
123 public void itemStateChanged(ItemEvent e) {
124 if (e.getStateChange() == ItemEvent.SELECTED)
125 fireEditingStopped();
126 }
127 }
128 );
129 editor.setRenderer(new EditorCellRenderer());
130 listeners = new CopyOnWriteArrayList<>();
131 }
132
133 /**
134 * Populate model with possible values for a decision, and select current choice.
135 * @param decision The {@link MultiValueResolutionDecision} to proceed
136 */
137 protected void initEditor(MultiValueResolutionDecision decision) {
138 editorModel.removeAllElements();
139 if (!decision.isDecided()) {
140 editorModel.addElement(MultiValueDecisionType.UNDECIDED);
141 }
142 for (String value: decision.getValues()) {
143 editorModel.addElement(value);
144 }
145 if (decision.canSumAllNumeric()) {
146 editorModel.addElement(MultiValueDecisionType.SUM_ALL_NUMERIC);
147 }
148 if (decision.canKeepNone()) {
149 editorModel.addElement(MultiValueDecisionType.KEEP_NONE);
150 }
151 if (decision.canKeepAll()) {
152 editorModel.addElement(MultiValueDecisionType.KEEP_ALL);
153 }
154 switch(decision.getDecisionType()) {
155 case UNDECIDED:
156 editor.setSelectedItem(MultiValueDecisionType.UNDECIDED);
157 break;
158 case KEEP_ONE:
159 editor.setSelectedItem(decision.getChosenValue());
160 break;
161 case KEEP_NONE:
162 editor.setSelectedItem(MultiValueDecisionType.KEEP_NONE);
163 break;
164 case KEEP_ALL:
165 editor.setSelectedItem(MultiValueDecisionType.KEEP_ALL);
166 break;
167 case SUM_ALL_NUMERIC:
168 editor.setSelectedItem(MultiValueDecisionType.SUM_ALL_NUMERIC);
169 break;
170 default:
171 Main.error("Unknown decision type in initEditor(): "+decision.getDecisionType());
172 }
173 }
174
175 @Override
176 public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
177 MultiValueResolutionDecision decision = (MultiValueResolutionDecision) value;
178 initEditor(decision);
179 editor.requestFocus();
180 return editor;
181 }
182
183 @Override
184 public Object getCellEditorValue() {
185 return editor.getSelectedItem();
186 }
187
188 /**
189 * The cell renderer used in the edit combo box
190 *
191 */
192 private static class EditorCellRenderer extends JLabel implements ListCellRenderer<Object> {
193
194 /**
195 * Construct a new {@link EditorCellRenderer}.
196 */
197 public EditorCellRenderer() {
198 setOpaque(true);
199 }
200
201 /**
202 * Set component color.
203 * @param selected true if is selected
204 */
205 protected void renderColors(boolean selected) {
206 if (selected) {
207 setForeground(UIManager.getColor("ComboBox.selectionForeground"));
208 setBackground(UIManager.getColor("ComboBox.selectionBackground"));
209 } else {
210 setForeground(UIManager.getColor("ComboBox.foreground"));
211 setBackground(UIManager.getColor("ComboBox.background"));
212 }
213 }
214
215 /**
216 * Set text for a value
217 * @param value {@link String} or {@link MultiValueDecisionType}
218 */
219 protected void renderValue(Object value) {
220 setFont(UIManager.getFont("ComboBox.font"));
221 if (String.class.isInstance(value)) {
222 setText(String.class.cast(value));
223 } else if (MultiValueDecisionType.class.isInstance(value)) {
224 switch(MultiValueDecisionType.class.cast(value)) {
225 case UNDECIDED:
226 setText(tr("Choose a value"));
227 setFont(UIManager.getFont("ComboBox.font").deriveFont(Font.ITALIC + Font.BOLD));
228 break;
229 case KEEP_NONE:
230 setText(tr("none"));
231 setFont(UIManager.getFont("ComboBox.font").deriveFont(Font.ITALIC + Font.BOLD));
232 break;
233 case KEEP_ALL:
234 setText(tr("all"));
235 setFont(UIManager.getFont("ComboBox.font").deriveFont(Font.ITALIC + Font.BOLD));
236 break;
237 case SUM_ALL_NUMERIC:
238 setText(tr("sum"));
239 setFont(UIManager.getFont("ComboBox.font").deriveFont(Font.ITALIC + Font.BOLD));
240 break;
241 default:
242 // don't display other values
243 }
244 }
245 }
246
247 @Override
248 public Component getListCellRendererComponent(JList<?> list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
249 renderColors(isSelected);
250 renderValue(value);
251 return this;
252 }
253 }
254}
Note: See TracBrowser for help on using the repository browser.