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

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

fix Checkstyle issues

  • 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 int keyCode = e.getKeyCode();
94 if (e.getID() == KeyEvent.KEY_PRESSED && keyCode == KeyEvent.VK_ENTER) {
95 fireGotoNextDecision();
96 } else if (e.getID() == KeyEvent.KEY_PRESSED && keyCode == KeyEvent.VK_TAB) {
97 if (e.isShiftDown()) {
98 fireGotoPreviousDecision();
99 } else {
100 fireGotoNextDecision();
101 }
102 } else if (e.getID() == KeyEvent.KEY_PRESSED && keyCode == KeyEvent.VK_DELETE || keyCode == KeyEvent.VK_BACK_SPACE) {
103 if (editorModel.getIndexOf(MultiValueDecisionType.KEEP_NONE) > 0) {
104 editorModel.setSelectedItem(MultiValueDecisionType.KEEP_NONE);
105 fireGotoNextDecision();
106 }
107 } else if (e.getID() == KeyEvent.KEY_PRESSED && keyCode == KeyEvent.VK_ESCAPE) {
108 cancelCellEditing();
109 }
110 super.processKeyEvent(e);
111 }
112 };
113 editor.addFocusListener(
114 new FocusAdapter() {
115 @Override
116 public void focusGained(FocusEvent e) {
117 editor.showPopup();
118 }
119 }
120 );
121 editor.addItemListener(
122 new ItemListener() {
123 @Override
124 public void itemStateChanged(ItemEvent e) {
125 if (e.getStateChange() == ItemEvent.SELECTED)
126 fireEditingStopped();
127 }
128 }
129 );
130 editor.setRenderer(new EditorCellRenderer());
131 listeners = new CopyOnWriteArrayList<>();
132 }
133
134 /**
135 * Populate model with possible values for a decision, and select current choice.
136 * @param decision The {@link MultiValueResolutionDecision} to proceed
137 */
138 protected void initEditor(MultiValueResolutionDecision decision) {
139 editorModel.removeAllElements();
140 if (!decision.isDecided()) {
141 editorModel.addElement(MultiValueDecisionType.UNDECIDED);
142 }
143 for (String value: decision.getValues()) {
144 editorModel.addElement(value);
145 }
146 if (decision.canSumAllNumeric()) {
147 editorModel.addElement(MultiValueDecisionType.SUM_ALL_NUMERIC);
148 }
149 if (decision.canKeepNone()) {
150 editorModel.addElement(MultiValueDecisionType.KEEP_NONE);
151 }
152 if (decision.canKeepAll()) {
153 editorModel.addElement(MultiValueDecisionType.KEEP_ALL);
154 }
155 switch(decision.getDecisionType()) {
156 case UNDECIDED:
157 editor.setSelectedItem(MultiValueDecisionType.UNDECIDED);
158 break;
159 case KEEP_ONE:
160 editor.setSelectedItem(decision.getChosenValue());
161 break;
162 case KEEP_NONE:
163 editor.setSelectedItem(MultiValueDecisionType.KEEP_NONE);
164 break;
165 case KEEP_ALL:
166 editor.setSelectedItem(MultiValueDecisionType.KEEP_ALL);
167 break;
168 case SUM_ALL_NUMERIC:
169 editor.setSelectedItem(MultiValueDecisionType.SUM_ALL_NUMERIC);
170 break;
171 default:
172 Main.error("Unknown decision type in initEditor(): "+decision.getDecisionType());
173 }
174 }
175
176 @Override
177 public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
178 MultiValueResolutionDecision decision = (MultiValueResolutionDecision) value;
179 initEditor(decision);
180 editor.requestFocus();
181 return editor;
182 }
183
184 @Override
185 public Object getCellEditorValue() {
186 return editor.getSelectedItem();
187 }
188
189 /**
190 * The cell renderer used in the edit combo box
191 *
192 */
193 private static class EditorCellRenderer extends JLabel implements ListCellRenderer<Object> {
194
195 /**
196 * Construct a new {@link EditorCellRenderer}.
197 */
198 EditorCellRenderer() {
199 setOpaque(true);
200 }
201
202 /**
203 * Set component color.
204 * @param selected true if is selected
205 */
206 protected void renderColors(boolean selected) {
207 if (selected) {
208 setForeground(UIManager.getColor("ComboBox.selectionForeground"));
209 setBackground(UIManager.getColor("ComboBox.selectionBackground"));
210 } else {
211 setForeground(UIManager.getColor("ComboBox.foreground"));
212 setBackground(UIManager.getColor("ComboBox.background"));
213 }
214 }
215
216 /**
217 * Set text for a value
218 * @param value {@link String} or {@link MultiValueDecisionType}
219 */
220 protected void renderValue(Object value) {
221 setFont(UIManager.getFont("ComboBox.font"));
222 if (String.class.isInstance(value)) {
223 setText(String.class.cast(value));
224 } else if (MultiValueDecisionType.class.isInstance(value)) {
225 switch(MultiValueDecisionType.class.cast(value)) {
226 case UNDECIDED:
227 setText(tr("Choose a value"));
228 setFont(UIManager.getFont("ComboBox.font").deriveFont(Font.ITALIC + Font.BOLD));
229 break;
230 case KEEP_NONE:
231 setText(tr("none"));
232 setFont(UIManager.getFont("ComboBox.font").deriveFont(Font.ITALIC + Font.BOLD));
233 break;
234 case KEEP_ALL:
235 setText(tr("all"));
236 setFont(UIManager.getFont("ComboBox.font").deriveFont(Font.ITALIC + Font.BOLD));
237 break;
238 case SUM_ALL_NUMERIC:
239 setText(tr("sum"));
240 setFont(UIManager.getFont("ComboBox.font").deriveFont(Font.ITALIC + Font.BOLD));
241 break;
242 default:
243 // don't display other values
244 }
245 }
246 }
247
248 @Override
249 public Component getListCellRendererComponent(JList<?> list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
250 renderColors(isSelected);
251 renderValue(value);
252 return this;
253 }
254 }
255}
Note: See TracBrowser for help on using the repository browser.