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 }