source: josm/trunk/src/org/openstreetmap/josm/gui/preferences/display/ColorPreference.java@ 12950

Last change on this file since 12950 was 12950, checked in by bastiK, 7 years ago

see #15410 - add custom table model

  • Property svn:eol-style set to native
File size: 12.4 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.gui.preferences.display;
3
4import static org.openstreetmap.josm.tools.I18n.tr;
5
6import java.awt.Color;
7import java.awt.Component;
8import java.awt.Dimension;
9import java.awt.GridBagLayout;
10import java.awt.event.MouseAdapter;
11import java.awt.event.MouseEvent;
12import java.util.ArrayList;
13import java.util.HashMap;
14import java.util.List;
15import java.util.Map;
16import java.util.TreeMap;
17
18import javax.swing.BorderFactory;
19import javax.swing.Box;
20import javax.swing.JButton;
21import javax.swing.JColorChooser;
22import javax.swing.JLabel;
23import javax.swing.JOptionPane;
24import javax.swing.JPanel;
25import javax.swing.JScrollPane;
26import javax.swing.JTable;
27import javax.swing.ListSelectionModel;
28import javax.swing.event.ListSelectionEvent;
29import javax.swing.table.AbstractTableModel;
30import javax.swing.table.DefaultTableCellRenderer;
31
32import org.openstreetmap.josm.Main;
33import org.openstreetmap.josm.data.osm.visitor.paint.PaintColors;
34import org.openstreetmap.josm.data.validation.Severity;
35import org.openstreetmap.josm.gui.MapScaler;
36import org.openstreetmap.josm.gui.MapStatus;
37import org.openstreetmap.josm.gui.conflict.ConflictColors;
38import org.openstreetmap.josm.gui.dialogs.ConflictDialog;
39import org.openstreetmap.josm.gui.layer.OsmDataLayer;
40import org.openstreetmap.josm.gui.layer.gpx.GpxDrawHelper;
41import org.openstreetmap.josm.gui.layer.markerlayer.MarkerLayer;
42import org.openstreetmap.josm.gui.preferences.PreferenceSetting;
43import org.openstreetmap.josm.gui.preferences.PreferenceSettingFactory;
44import org.openstreetmap.josm.gui.preferences.PreferenceTabbedPane;
45import org.openstreetmap.josm.gui.preferences.SubPreferenceSetting;
46import org.openstreetmap.josm.gui.preferences.TabPreferenceSetting;
47import org.openstreetmap.josm.gui.util.GuiHelper;
48import org.openstreetmap.josm.tools.ColorHelper;
49import org.openstreetmap.josm.tools.GBC;
50import org.openstreetmap.josm.tools.Logging;
51
52/**
53 * Color preferences.
54 */
55public class ColorPreference implements SubPreferenceSetting {
56
57 /**
58 * Factory used to create a new {@code ColorPreference}.
59 */
60 public static class Factory implements PreferenceSettingFactory {
61 @Override
62 public PreferenceSetting createPreferenceSetting() {
63 return new ColorPreference();
64 }
65 }
66
67 private ColorTableModel tableModel;
68 private JTable colors;
69
70 private JButton colorEdit;
71 private JButton defaultSet;
72 private JButton remove;
73
74 private static class ColorEntry {
75 String key;
76 Color color;
77 }
78
79 private static class ColorTableModel extends AbstractTableModel {
80
81 private final List<ColorEntry> data;
82 private final List<ColorEntry> deleted;
83
84 public ColorTableModel() {
85 this.data = new ArrayList<>();
86 this.deleted = new ArrayList<>();
87 }
88
89 public void addEntry(ColorEntry entry) {
90 data.add(entry);
91 }
92
93 public void removeEntry(int row) {
94 deleted.add(data.get(row));
95 data.remove(row);
96 fireTableDataChanged();
97 }
98
99 public List<ColorEntry> getData() {
100 return data;
101 }
102
103 public List<ColorEntry> getDeleted() {
104 return deleted;
105 }
106
107 public void clear() {
108 data.clear();
109 deleted.clear();
110 }
111
112 @Override
113 public int getRowCount() {
114 return data.size();
115 }
116
117 @Override
118 public int getColumnCount() {
119 return 2;
120 }
121
122 @Override
123 public Object getValueAt(int rowIndex, int columnIndex) {
124 return columnIndex == 0 ? getName(data.get(rowIndex).key) : data.get(rowIndex).color;
125 }
126
127 @Override
128 public String getColumnName(int column) {
129 return column == 0 ? tr("Name") : tr("Color");
130 }
131
132 @Override
133 public boolean isCellEditable(int rowIndex, int columnIndex) {
134 return false;
135 }
136
137 @Override
138 public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
139 if (columnIndex == 1 && aValue instanceof Color) {
140 data.get(rowIndex).color = (Color) aValue;
141 fireTableCellUpdated(rowIndex, columnIndex);
142 }
143 }
144 }
145
146 /**
147 * Set the colors to be shown in the preference table. This method creates a table model if
148 * none exists and overwrites all existing values.
149 * @param colorMap the map holding the colors
150 * (key = color id (without prefixes, so only <code>background</code>; not <code>color.background</code>),
151 * value = html representation of the color.
152 */
153 public void setColorModel(Map<String, String> colorMap) {
154 if (tableModel == null) {
155 tableModel = new ColorTableModel();
156 }
157
158 tableModel.clear();
159 // fill model with colors:
160 Map<String, String> colorKeyList = new TreeMap<>();
161 Map<String, String> colorKeyListMappaint = new TreeMap<>();
162 Map<String, String> colorKeyListLayer = new TreeMap<>();
163 for (String key : colorMap.keySet()) {
164 if (key.startsWith("layer.")) {
165 colorKeyListLayer.put(getName(key), key);
166 } else if (key.startsWith("mappaint.")) {
167 // use getName(key)+key, as getName() may be ambiguous
168 colorKeyListMappaint.put(getName(key)+key, key);
169 } else {
170 colorKeyList.put(getName(key), key);
171 }
172 }
173 addColorRows(colorMap, colorKeyList);
174 addColorRows(colorMap, colorKeyListMappaint);
175 addColorRows(colorMap, colorKeyListLayer);
176 if (this.colors != null) {
177 this.colors.repaint();
178 }
179 }
180
181 private void addColorRows(Map<String, String> colorMap, Map<String, String> keyMap) {
182 for (String value : keyMap.values()) {
183 ColorEntry entry = new ColorEntry();
184 String html = colorMap.get(value);
185 Color color = ColorHelper.html2color(html);
186 if (color == null) {
187 Logging.warn("Unable to get color from '"+html+"' for color preference '"+value+'\'');
188 }
189 entry.key = value;
190 entry.color = color;
191 tableModel.addEntry(entry);
192 }
193 }
194
195 /**
196 * Returns a map with the colors in the table (key = color name without prefix, value = html color code).
197 * @return a map holding the colors.
198 */
199 public Map<String, String> getColorModel() {
200 Map<String, String> colorMap = new HashMap<>();
201 for (ColorEntry e : tableModel.getData()) {
202 colorMap.put(e.key, ColorHelper.color2html(e.color));
203 }
204 return colorMap;
205 }
206
207 private static String getName(String o) {
208 return Main.pref.getColorName(o);
209 }
210
211 @Override
212 public void addGui(final PreferenceTabbedPane gui) {
213 fixColorPrefixes();
214 setColorModel(Main.pref.getAllColors());
215
216 colorEdit = new JButton(tr("Choose"));
217 colorEdit.addActionListener(e -> {
218 int sel = colors.getSelectedRow();
219 JColorChooser chooser = new JColorChooser((Color) colors.getValueAt(sel, 1));
220 int answer = JOptionPane.showConfirmDialog(
221 gui, chooser,
222 tr("Choose a color for {0}", getName((String) colors.getValueAt(sel, 0))),
223 JOptionPane.OK_CANCEL_OPTION,
224 JOptionPane.PLAIN_MESSAGE);
225 if (answer == JOptionPane.OK_OPTION) {
226 colors.setValueAt(chooser.getColor(), sel, 1);
227 }
228 });
229 defaultSet = new JButton(tr("Set to default"));
230 defaultSet.addActionListener(e -> {
231 int sel = colors.getSelectedRow();
232 String name = (String) colors.getValueAt(sel, 0);
233 Color c = Main.pref.getDefaultColor(name);
234 if (c != null) {
235 colors.setValueAt(c, sel, 1);
236 }
237 });
238 JButton defaultAll = new JButton(tr("Set all to default"));
239 defaultAll.addActionListener(e -> {
240 for (int i = 0; i < colors.getRowCount(); ++i) {
241 String name = (String) colors.getValueAt(i, 0);
242 Color c = Main.pref.getDefaultColor(name);
243 if (c != null) {
244 colors.setValueAt(c, i, 1);
245 }
246 }
247 });
248 remove = new JButton(tr("Remove"));
249 remove.addActionListener(e -> {
250 int sel = colors.getSelectedRow();
251 tableModel.removeEntry(sel);
252 });
253 remove.setEnabled(false);
254 colorEdit.setEnabled(false);
255 defaultSet.setEnabled(false);
256
257 colors = new JTable(tableModel) {
258 @Override public void valueChanged(ListSelectionEvent e) {
259 super.valueChanged(e);
260 int sel = getSelectedRow();
261 remove.setEnabled(sel >= 0 && isRemoveColor(sel));
262 colorEdit.setEnabled(sel >= 0);
263 defaultSet.setEnabled(sel >= 0);
264 }
265 };
266 colors.addMouseListener(new MouseAdapter() {
267 @Override
268 public void mousePressed(MouseEvent me) {
269 if (me.getClickCount() == 2) {
270 colorEdit.doClick();
271 }
272 }
273 });
274 colors.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
275 colors.getColumnModel().getColumn(1).setCellRenderer(new DefaultTableCellRenderer() {
276 @Override
277 public Component getTableCellRendererComponent(
278 JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
279 Component comp = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
280 if (value != null && comp instanceof JLabel) {
281 JLabel label = (JLabel) comp;
282 Color c = (Color) value;
283 label.setText(ColorHelper.color2html(c));
284 GuiHelper.setBackgroundReadable(label, c);
285 label.setOpaque(true);
286 return label;
287 }
288 return comp;
289 }
290 });
291 colors.getColumnModel().getColumn(1).setWidth(100);
292 colors.setToolTipText(tr("Colors used by different objects in JOSM."));
293 colors.setPreferredScrollableViewportSize(new Dimension(100, 112));
294
295 JPanel panel = new JPanel(new GridBagLayout());
296 panel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
297 JScrollPane scrollpane = new JScrollPane(colors);
298 scrollpane.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0));
299 panel.add(scrollpane, GBC.eol().fill(GBC.BOTH));
300 JPanel buttonPanel = new JPanel(new GridBagLayout());
301 panel.add(buttonPanel, GBC.eol().insets(5, 0, 5, 5).fill(GBC.HORIZONTAL));
302 buttonPanel.add(Box.createHorizontalGlue(), GBC.std().fill(GBC.HORIZONTAL));
303 buttonPanel.add(colorEdit, GBC.std().insets(0, 5, 0, 0));
304 buttonPanel.add(defaultSet, GBC.std().insets(5, 5, 5, 0));
305 buttonPanel.add(defaultAll, GBC.std().insets(0, 5, 0, 0));
306 buttonPanel.add(remove, GBC.std().insets(0, 5, 0, 0));
307 gui.getDisplayPreference().addSubTab(this, tr("Colors"), panel);
308 }
309
310 Boolean isRemoveColor(int row) {
311 return tableModel.getData().get(row).key.startsWith("layer.");
312 }
313
314 /**
315 * Add all missing color entries.
316 */
317 private static void fixColorPrefixes() {
318 PaintColors.values();
319 ConflictColors.getColors();
320 Severity.getColors();
321 MarkerLayer.getGenericColor();
322 GpxDrawHelper.getGenericColor();
323 OsmDataLayer.getOutsideColor();
324 MapScaler.getColor();
325 MapStatus.getColors();
326 ConflictDialog.getColor();
327 }
328
329 @Override
330 public boolean ok() {
331 boolean ret = false;
332 for (ColorEntry d : tableModel.getDeleted()) {
333 Main.pref.putColor(d.key, null);
334 }
335 for (ColorEntry e : tableModel.getData()) {
336 if (Main.pref.putColor(e.key, e.color) && e.key.startsWith("mappaint.")) {
337 ret = true;
338 }
339 }
340 OsmDataLayer.createHatchTexture();
341 return ret;
342 }
343
344 @Override
345 public boolean isExpert() {
346 return false;
347 }
348
349 @Override
350 public TabPreferenceSetting getTabPreferenceSetting(final PreferenceTabbedPane gui) {
351 return gui.getDisplayPreference();
352 }
353}
Note: See TracBrowser for help on using the repository browser.