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

Last change on this file since 7661 was 7015, checked in by Don-vip, 10 years ago

see #8465 - fix generics for JComboBox/JList

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