001 // License: GPL. Copyright 2007 by Immanuel Scholz and others
002 package org.openstreetmap.josm.gui.preferences.display;
003
004 import static org.openstreetmap.josm.tools.I18n.tr;
005
006 import java.awt.Color;
007 import java.awt.Component;
008 import java.awt.Dimension;
009 import java.awt.GridBagLayout;
010 import java.awt.event.ActionEvent;
011 import java.awt.event.ActionListener;
012 import java.util.ArrayList;
013 import java.util.HashMap;
014 import java.util.Map;
015 import java.util.Map.Entry;
016 import java.util.TreeMap;
017 import java.util.Vector;
018
019 import javax.swing.BorderFactory;
020 import javax.swing.Box;
021 import javax.swing.JButton;
022 import javax.swing.JColorChooser;
023 import javax.swing.JLabel;
024 import javax.swing.JOptionPane;
025 import javax.swing.JPanel;
026 import javax.swing.JScrollPane;
027 import javax.swing.JTable;
028 import javax.swing.ListSelectionModel;
029 import javax.swing.event.ListSelectionEvent;
030 import javax.swing.table.DefaultTableModel;
031 import javax.swing.table.TableCellRenderer;
032
033 import org.openstreetmap.josm.Main;
034 import org.openstreetmap.josm.data.osm.visitor.paint.PaintColors;
035 import org.openstreetmap.josm.data.validation.Severity;
036 import org.openstreetmap.josm.gui.MapScaler;
037 import org.openstreetmap.josm.gui.conflict.ConflictColors;
038 import org.openstreetmap.josm.gui.dialogs.ConflictDialog;
039 import org.openstreetmap.josm.gui.layer.GpxLayer;
040 import org.openstreetmap.josm.gui.layer.ImageryLayer;
041 import org.openstreetmap.josm.gui.layer.OsmDataLayer;
042 import org.openstreetmap.josm.gui.layer.markerlayer.MarkerLayer;
043 import org.openstreetmap.josm.gui.preferences.PreferenceSetting;
044 import org.openstreetmap.josm.gui.preferences.PreferenceSettingFactory;
045 import org.openstreetmap.josm.gui.preferences.PreferenceTabbedPane;
046 import org.openstreetmap.josm.gui.preferences.SubPreferenceSetting;
047 import org.openstreetmap.josm.gui.preferences.TabPreferenceSetting;
048 import org.openstreetmap.josm.tools.ColorHelper;
049 import org.openstreetmap.josm.tools.GBC;
050
051 public class ColorPreference implements SubPreferenceSetting {
052
053 public static class Factory implements PreferenceSettingFactory {
054 public PreferenceSetting createPreferenceSetting() {
055 return new ColorPreference();
056 }
057 }
058
059 private DefaultTableModel tableModel;
060 private JTable colors;
061 private ArrayList<String> del = new ArrayList<String>();
062
063 JButton colorEdit;
064 JButton defaultSet;
065 JButton remove;
066
067 /**
068 * Set the colors to be shown in the preference table. This method creates a table model if
069 * none exists and overwrites all existing values.
070 * @param colorMap the map holding the colors
071 * (key = color id (without prefixes, so only <code>background</code>; not <code>color.background</code>),
072 * value = html representation of the color.
073 */
074 public void setColorModel(Map<String, String> colorMap) {
075 if(tableModel == null) {
076 tableModel = new DefaultTableModel();
077 tableModel.addColumn(tr("Name"));
078 tableModel.addColumn(tr("Color"));
079 }
080
081 // clear old model:
082 while(tableModel.getRowCount() > 0) {
083 tableModel.removeRow(0);
084 }
085 // fill model with colors:
086 Map<String, String> colorKeyList = new TreeMap<String, String>();
087 Map<String, String> colorKeyList_mappaint = new TreeMap<String, String>();
088 Map<String, String> colorKeyList_layer = new TreeMap<String, String>();
089 for(String key : colorMap.keySet()) {
090 if(key.startsWith("layer ")) {
091 colorKeyList_layer.put(getName(key), key);
092 } else if(key.startsWith("mappaint.")) {
093 /* use getName(key)+key, as getName() may be ambiguous */
094 colorKeyList_mappaint.put(getName(key)+key, key);
095 } else {
096 colorKeyList.put(getName(key), key);
097 }
098 }
099 for (Entry<String, String> k : colorKeyList.entrySet()) {
100 Vector<Object> row = new Vector<Object>(2);
101 row.add(k.getValue());
102 row.add(ColorHelper.html2color(colorMap.get(k.getValue())));
103 tableModel.addRow(row);
104 }
105 for (Entry<String, String> k : colorKeyList_mappaint.entrySet()) {
106 Vector<Object> row = new Vector<Object>(2);
107 row.add(k.getValue());
108 row.add(ColorHelper.html2color(colorMap.get(k.getValue())));
109 tableModel.addRow(row);
110 }
111 for (Entry<String, String> k : colorKeyList_layer.entrySet()) {
112 Vector<Object> row = new Vector<Object>(2);
113 row.add(k.getValue());
114 row.add(ColorHelper.html2color(colorMap.get(k.getValue())));
115 tableModel.addRow(row);
116 }
117 if(this.colors != null) {
118 this.colors.repaint();
119 }
120 }
121
122 /**
123 * Returns a map with the colors in the table (key = color name without prefix, value = html color code).
124 * @return a map holding the colors.
125 */
126 public Map<String, String> getColorModel() {
127 String key;
128 String value;
129 Map<String, String> colorMap = new HashMap<String, String>();
130 for(int row = 0; row < tableModel.getRowCount(); ++row) {
131 key = (String)tableModel.getValueAt(row, 0);
132 value = ColorHelper.color2html((Color)tableModel.getValueAt(row, 1));
133 colorMap.put(key, value);
134 }
135 return colorMap;
136 }
137
138 private String getName(String o)
139 {
140 return Main.pref.getColorName(o);
141 }
142
143 public void addGui(final PreferenceTabbedPane gui) {
144 fixColorPrefixes();
145 setColorModel(Main.pref.getAllColors());
146
147 colorEdit = new JButton(tr("Choose"));
148 colorEdit.addActionListener(new ActionListener(){
149 public void actionPerformed(ActionEvent e) {
150 int sel = colors.getSelectedRow();
151 JColorChooser chooser = new JColorChooser((Color)colors.getValueAt(sel, 1));
152 int answer = JOptionPane.showConfirmDialog(
153 gui, chooser,
154 tr("Choose a color for {0}", getName((String)colors.getValueAt(sel, 0))),
155 JOptionPane.OK_CANCEL_OPTION,
156 JOptionPane.PLAIN_MESSAGE);
157 if (answer == JOptionPane.OK_OPTION) {
158 colors.setValueAt(chooser.getColor(), sel, 1);
159 }
160 }
161 });
162 defaultSet = new JButton(tr("Set to default"));
163 defaultSet.addActionListener(new ActionListener(){
164 public void actionPerformed(ActionEvent e) {
165 int sel = colors.getSelectedRow();
166 String name = (String)colors.getValueAt(sel, 0);
167 Color c = Main.pref.getDefaultColor(name);
168 if (c != null) {
169 colors.setValueAt(c, sel, 1);
170 }
171 }
172 });
173 JButton defaultAll = new JButton(tr("Set all to default"));
174 defaultAll.addActionListener(new ActionListener(){
175 public void actionPerformed(ActionEvent e) {
176 for(int i = 0; i < colors.getRowCount(); ++i)
177 {
178 String name = (String)colors.getValueAt(i, 0);
179 Color c = Main.pref.getDefaultColor(name);
180 if (c != null) {
181 colors.setValueAt(c, i, 1);
182 }
183 }
184 }
185 });
186 remove = new JButton(tr("Remove"));
187 remove.addActionListener(new ActionListener(){
188 public void actionPerformed(ActionEvent e) {
189 int sel = colors.getSelectedRow();
190 del.add((String)colors.getValueAt(sel, 0));
191 tableModel.removeRow(sel);
192 }
193 });
194 remove.setEnabled(false);
195 colorEdit.setEnabled(false);
196 defaultSet.setEnabled(false);
197
198 colors = new JTable(tableModel) {
199 @Override public boolean isCellEditable(int row, int column) {
200 return false;
201 }
202 @Override public void valueChanged(ListSelectionEvent e) {
203 super.valueChanged(e);
204 int sel = getSelectedRow();
205 remove.setEnabled(sel >= 0 && isRemoveColor(sel));
206 colorEdit.setEnabled(sel >= 0);
207 defaultSet.setEnabled(sel >= 0);
208 }
209 };
210 colors.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
211 final TableCellRenderer oldColorsRenderer = colors.getDefaultRenderer(Object.class);
212 colors.setDefaultRenderer(Object.class, new TableCellRenderer(){
213 public Component getTableCellRendererComponent(JTable t, Object o, boolean selected, boolean focus, int row, int column) {
214 if (o == null)
215 return new JLabel();
216 if (column == 1) {
217 JLabel l = new JLabel(ColorHelper.color2html((Color)o));
218 l.setBackground((Color)o);
219 l.setOpaque(true);
220 return l;
221 }
222 return oldColorsRenderer.getTableCellRendererComponent(t,getName(o.toString()),selected,focus,row,column);
223 }
224 });
225 colors.getColumnModel().getColumn(1).setWidth(100);
226 colors.setToolTipText(tr("Colors used by different objects in JOSM."));
227 colors.setPreferredScrollableViewportSize(new Dimension(100,112));
228
229 JPanel panel = new JPanel(new GridBagLayout());
230 panel.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
231 JScrollPane scrollpane = new JScrollPane(colors);
232 scrollpane.setBorder(BorderFactory.createEmptyBorder( 0, 0, 0, 0 ));
233 panel.add(scrollpane, GBC.eol().fill(GBC.BOTH));
234 JPanel buttonPanel = new JPanel(new GridBagLayout());
235 panel.add(buttonPanel, GBC.eol().insets(5,0,5,5).fill(GBC.HORIZONTAL));
236 buttonPanel.add(Box.createHorizontalGlue(), GBC.std().fill(GBC.HORIZONTAL));
237 buttonPanel.add(colorEdit, GBC.std().insets(0,5,0,0));
238 buttonPanel.add(defaultSet, GBC.std().insets(5,5,5,0));
239 buttonPanel.add(defaultAll, GBC.std().insets(0,5,0,0));
240 buttonPanel.add(remove, GBC.std().insets(0,5,0,0));
241 gui.getDisplayPreference().displaycontent.addTab(tr("Colors"), panel);
242 }
243
244 Boolean isRemoveColor(int row)
245 {
246 return ((String)colors.getValueAt(row, 0)).startsWith("layer ");
247 }
248
249 /**
250 * Add all missing color entries.
251 */
252 private void fixColorPrefixes() {
253 PaintColors.getColors();
254 ConflictColors.getColors();
255 Severity.getColors();
256 MarkerLayer.getGenericColor();
257 GpxLayer.getGenericColor();
258 OsmDataLayer.getOutsideColor();
259 ImageryLayer.getFadeColor();
260 MapScaler.getColor();
261 ConflictDialog.getColor();
262 }
263
264 public boolean ok() {
265 Boolean ret = false;
266 for(String d : del) {
267 Main.pref.put("color."+d, null);
268 }
269 for (int i = 0; i < colors.getRowCount(); ++i) {
270 String key = (String)colors.getValueAt(i, 0);
271 if(Main.pref.putColor(key, (Color)colors.getValueAt(i, 1)))
272 {
273 if(key.startsWith("mappaint.")) {
274 ret = true;
275 }
276 }
277 }
278 OsmDataLayer.createHatchTexture();
279 return ret;
280 }
281
282 @Override
283 public boolean isExpert() {
284 return false;
285 }
286
287 @Override
288 public TabPreferenceSetting getTabPreferenceSetting(final PreferenceTabbedPane gui) {
289 return gui.getDisplayPreference();
290 }
291 }