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

Last change on this file since 2655 was 2655, checked in by jttt, 14 years ago

Fixed #4161 Major slowdown in recent versions, used correct pattern for listeners realized using CopyOnWriteArrayList

File size: 6.8 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.KeyEvent;
11import java.util.concurrent.CopyOnWriteArrayList;
12
13import javax.swing.AbstractCellEditor;
14import javax.swing.DefaultComboBoxModel;
15import javax.swing.JComboBox;
16import javax.swing.JLabel;
17import javax.swing.JList;
18import javax.swing.JTable;
19import javax.swing.ListCellRenderer;
20import javax.swing.UIManager;
21import javax.swing.table.TableCellEditor;
22
23/**
24 * This is a table cell editor for selecting a possible tag value from a list of
25 * proposed tag values. The editor also allows to select all proposed valued or
26 * to remove the tag.
27 *
28 * The editor responds intercepts some keys and interprets them as navigation keys. It
29 * forwards navigation events to {@see NavigationListener}s registred with this editor.
30 * You should register the parent table using this editor as {@see NavigationListener}.
31 *
32 * {@see KeyEvent#VK_ENTER} and {@see KeyEvent#VK_TAB} trigger a {@see NavigationListener#gotoNextDecision()}.
33 */
34public class MultiValueCellEditor extends AbstractCellEditor implements TableCellEditor{
35
36 public static interface NavigationListener {
37 void gotoNextDecision();
38 void gotoPreviousDecision();
39 }
40
41 /** the combo box used as editor */
42 private JComboBox editor;
43 private DefaultComboBoxModel editorModel;
44 private CopyOnWriteArrayList<NavigationListener> listeners;
45
46 public void addNavigationListeners(NavigationListener listener) {
47 if (listener != null) {
48 listeners.addIfAbsent(listener);
49 }
50 }
51
52 public void removeavigationListeners(NavigationListener listener) {
53 listeners.remove(listener);
54 }
55
56 protected void fireGotoNextDecision() {
57 for (NavigationListener l: listeners) {
58 l.gotoNextDecision();
59 }
60 }
61
62 protected void fireGotoPreviousDecision() {
63 for (NavigationListener l: listeners) {
64 l.gotoPreviousDecision();
65 }
66 }
67
68 public MultiValueCellEditor() {
69 editorModel = new DefaultComboBoxModel();
70 editor = new JComboBox(editorModel) {
71 @Override
72 public void processKeyEvent(KeyEvent e) {
73 if (e.getID() == KeyEvent.KEY_PRESSED && e.getKeyCode() == KeyEvent.VK_ENTER) {
74 fireGotoNextDecision();
75 } if (e.getID() == KeyEvent.KEY_PRESSED && e.getKeyCode() == KeyEvent.VK_TAB) {
76 if (e.isShiftDown()) {
77 fireGotoPreviousDecision();
78 } else {
79 fireGotoNextDecision();
80 }
81 } else if ( e.getID() == KeyEvent.KEY_PRESSED && e.getKeyCode() == KeyEvent.VK_DELETE || e.getKeyCode() == KeyEvent.VK_BACK_SPACE) {
82 if (editorModel.getIndexOf(MultiValueDecisionType.KEEP_NONE) > 0) {
83 editorModel.setSelectedItem(MultiValueDecisionType.KEEP_NONE);
84 fireGotoNextDecision();
85 }
86 } else if (e.getID() == KeyEvent.KEY_PRESSED && e.getKeyCode() == KeyEvent.VK_ESCAPE) {
87 cancelCellEditing();
88 }
89 super.processKeyEvent(e);
90 }
91 };
92 editor.addFocusListener(
93 new FocusAdapter() {
94 @Override
95 public void focusGained(FocusEvent e) {
96 editor.showPopup();
97 }
98 }
99 );
100 editor.setRenderer(new EditorCellRenderer());
101 listeners = new CopyOnWriteArrayList<NavigationListener>();
102 }
103
104 protected void initEditor(MultiValueResolutionDecision decision) {
105 editorModel.removeAllElements();
106 for (String value: decision.getValues()) {
107 editorModel.addElement(value);
108 }
109 if (decision.canKeepNone()) {
110 editorModel.addElement(MultiValueDecisionType.KEEP_NONE);
111 }
112 if (decision.canKeepAll()) {
113 editorModel.addElement(MultiValueDecisionType.KEEP_ALL);
114 }
115 switch(decision.getDecisionType()) {
116 case UNDECIDED:
117 editor.setSelectedIndex(0);
118 break;
119 case KEEP_ONE:
120 editor.setSelectedItem(decision.getChosenValue());
121 break;
122 case KEEP_NONE:
123 editor.setSelectedItem(MultiValueDecisionType.KEEP_NONE);
124 break;
125 case KEEP_ALL:
126 editor.setSelectedItem(MultiValueDecisionType.KEEP_ALL);
127 }
128 }
129
130 public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
131 MultiValueResolutionDecision decision = (MultiValueResolutionDecision)value;
132 initEditor(decision);
133 editor.requestFocus();
134 return editor;
135 }
136
137 public Object getCellEditorValue() {
138 return editor.getSelectedItem();
139 }
140
141 /**
142 * The cell renderer used in the combo box
143 *
144 */
145 static private class EditorCellRenderer extends JLabel implements ListCellRenderer {
146
147 public EditorCellRenderer() {
148 setOpaque(true);
149 }
150
151 protected void renderColors(boolean selected) {
152 if (selected) {
153 setForeground( UIManager.getColor("ComboBox.selectionForeground"));
154 setBackground(UIManager.getColor("ComboBox.selectionBackground"));
155 } else {
156 setForeground( UIManager.getColor("ComboBox.foreground"));
157 setBackground(UIManager.getColor("ComboBox.background"));
158 }
159 }
160
161 protected void renderValue(Object value) {
162 setFont(UIManager.getFont("ComboBox.font"));
163 if (String.class.isInstance(value)) {
164 setText(String.class.cast(value));
165 } else if (MultiValueDecisionType.class.isInstance(value)) {
166 switch(MultiValueDecisionType.class.cast(value)) {
167 case KEEP_NONE:
168 setText(tr("none"));
169 setFont(UIManager.getFont("ComboBox.font").deriveFont(Font.ITALIC + Font.BOLD));
170 break;
171 case KEEP_ALL:
172 setText(tr("all"));
173 setFont(UIManager.getFont("ComboBox.font").deriveFont(Font.ITALIC + Font.BOLD));
174 break;
175 default:
176 // don't display other values
177 }
178 }
179 }
180
181 public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected,
182 boolean cellHasFocus) {
183 renderColors(isSelected);
184 renderValue(value);
185 return this;
186 }
187 }
188}
Note: See TracBrowser for help on using the repository browser.