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

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

checkstyle

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