source: josm/trunk/src/org/openstreetmap/josm/gui/dialogs/properties/PropertiesCellRenderer.java

Last change on this file was 16319, checked in by simon04, 5 years ago

see #8352 - PropertiesDialog: fix 3-char CSS color names such as "red"

  • Property svn:eol-style set to native
File size: 7.8 KB
RevLine 
[7937]1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.gui.dialogs.properties;
3
4import static org.openstreetmap.josm.tools.I18n.marktr;
5import static org.openstreetmap.josm.tools.I18n.tr;
[8170]6import static org.openstreetmap.josm.tools.I18n.trn;
[7937]7
8import java.awt.Color;
9import java.awt.Component;
10import java.awt.Font;
[9149]11import java.util.Collection;
[7937]12import java.util.Map;
[8387]13import java.util.Objects;
[11553]14import java.util.Optional;
[9149]15import java.util.concurrent.CopyOnWriteArrayList;
[7937]16
17import javax.swing.JLabel;
18import javax.swing.JTable;
[10878]19import javax.swing.UIManager;
[7937]20import javax.swing.table.DefaultTableCellRenderer;
[9149]21import javax.swing.table.TableCellRenderer;
[7937]22
[13809]23import org.openstreetmap.josm.data.osm.AbstractPrimitive;
[10878]24import org.openstreetmap.josm.data.preferences.BooleanProperty;
25import org.openstreetmap.josm.data.preferences.CachingProperty;
[12987]26import org.openstreetmap.josm.data.preferences.NamedColorProperty;
[16319]27import org.openstreetmap.josm.gui.mappaint.mapcss.CSSColors;
[16293]28import org.openstreetmap.josm.tools.ColorHelper;
[15501]29import org.openstreetmap.josm.tools.I18n;
30import org.openstreetmap.josm.tools.Pair;
[7937]31
32/**
33 * Cell renderer of tags table.
34 * @since 6314
35 */
36public class PropertiesCellRenderer extends DefaultTableCellRenderer {
37
[10878]38 private static final CachingProperty<Color> SELECTED_FG
[12987]39 = new NamedColorProperty(marktr("Discardable key: selection Foreground"), Color.GRAY).cached();
[10878]40 private static final CachingProperty<Color> SELECTED_BG;
41 private static final CachingProperty<Color> NORMAL_FG
[12987]42 = new NamedColorProperty(marktr("Discardable key: foreground"), Color.GRAY).cached();
[10878]43 private static final CachingProperty<Color> NORMAL_BG;
44 private static final CachingProperty<Boolean> DISCARDABLE
45 = new BooleanProperty("display.discardable-keys", false).cached();
46
47 static {
[12987]48 SELECTED_BG = new NamedColorProperty(marktr("Discardable key: selection Background"),
[11553]49 Optional.ofNullable(UIManager.getColor("Table.selectionBackground")).orElse(Color.BLUE)).cached();
[12987]50 NORMAL_BG = new NamedColorProperty(marktr("Discardable key: background"),
[11553]51 Optional.ofNullable(UIManager.getColor("Table.background")).orElse(Color.WHITE)).cached();
[10878]52 }
53
[9149]54 private final Collection<TableCellRenderer> customRenderer = new CopyOnWriteArrayList<>();
55
[10043]56 private static void setColors(Component c, String key, boolean isSelected) {
[10878]57
[13809]58 if (AbstractPrimitive.getDiscardableKeys().contains(key)) {
[10878]59 c.setForeground((isSelected ? SELECTED_FG : NORMAL_FG).get());
60 c.setBackground((isSelected ? SELECTED_BG : NORMAL_BG).get());
[7937]61 } else {
[11552]62 c.setForeground(UIManager.getColor("Table."+(isSelected ? "selectionF" : "f")+"oreground"));
63 c.setBackground(UIManager.getColor("Table."+(isSelected ? "selectionB" : "b")+"ackground"));
[7937]64 }
65 }
[8365]66
67 @Override
[7937]68 public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
[9149]69 for (TableCellRenderer renderer : customRenderer) {
70 final Component component = renderer.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
71 if (component != null) {
72 return component;
73 }
74 }
[7937]75 if (value == null)
76 return this;
[10878]77 Component c = super.getTableCellRendererComponent(table, value, isSelected, false, row, column);
[7937]78 if (c instanceof JLabel) {
79 String str = null;
80 if (value instanceof String) {
81 str = (String) value;
82 } else if (value instanceof Map<?, ?>) {
83 Map<?, ?> v = (Map<?, ?>) value;
[8170]84 if (v.size() != 1) { // Multiple values: give user a short summary of the values
[8365]85 Integer blankCount;
86 Integer otherCount;
[8170]87 if (v.get("") == null) {
[8365]88 blankCount = 0;
89 otherCount = v.size();
[8170]90 } else {
[8510]91 blankCount = (Integer) v.get("");
[8365]92 otherCount = v.size()-1;
[8170]93 }
[8365]94 StringBuilder sb = new StringBuilder("<");
95 if (otherCount == 1) {
[10878]96 // Find the non-blank value in the map
97 v.entrySet().stream().filter(entry -> !Objects.equals(entry.getKey(), ""))
[10977]98 /* I18n: properties display partial string joined with comma, first is count, second is value */
[10878]99 .findAny().ifPresent(entry -> sb.append(tr("{0} ''{1}''", entry.getValue().toString(), entry.getKey())));
[8170]100 } else {
[8189]101 /* I18n: properties display partial string joined with comma */
[8365]102 sb.append(trn("{0} different", "{0} different", otherCount, otherCount));
[8170]103 }
[8510]104 if (blankCount > 0) {
[8189]105 /* I18n: properties display partial string joined with comma */
[8365]106 sb.append(trn(", {0} unset", ", {0} unset", blankCount, blankCount));
[8170]107 }
[8390]108 sb.append('>');
[8365]109 str = sb.toString();
[7937]110 c.setFont(c.getFont().deriveFont(Font.ITALIC));
[8170]111
[14185]112 } else { // One value: display the value
113 str = (String) v.entrySet().iterator().next().getKey();
[7937]114 }
115 }
[16283]116 boolean enableHTML = false;
[14174]117 if (column == 0 && str != null) {
[15501]118 Pair<String, Boolean> label = I18n.getLocalizedLanguageName(str);
[16283]119 if (label != null && label.b) {
120 enableHTML = true;
121 str = "<html><body>" + str + " <i>&lt;" + label.a + "&gt;</i></body></html>";
[14174]122 }
[16292]123 } else if (column == 1 && str != null && String.valueOf(getKeyInRow(table, row)).contains("colour")) {
[16283]124 enableHTML = true;
125 // U+25A0 BLACK SQUARE
[16293]126 final String color = str.matches("#[0-9A-Fa-f]{3,8}")
127 ? str
[16319]128 : ColorHelper.color2html(CSSColors.get(str));
129 if (color != null) {
130 str = "<html><body><span color='" + color + "'>\u25A0</span> " + str + "</body></html>";
131 }
[14174]132 }
[16283]133 ((JLabel) c).putClientProperty("html.disable", enableHTML ? null : Boolean.TRUE); // Fix #8730
[8510]134 ((JLabel) c).setText(str);
[10878]135 if (DISCARDABLE.get()) {
[7937]136 String key = null;
137 if (column == 0) {
138 key = str;
139 } else if (column == 1) {
[16292]140 Object value0 = getKeyInRow(table, row);
[7937]141 if (value0 instanceof String) {
142 key = (String) value0;
143 }
144 }
145 setColors(c, key, isSelected);
146 }
147 }
148 return c;
149 }
[9149]150
[16292]151 private Object getKeyInRow(JTable table, int row) {
152 return table.getModel().getValueAt(table.convertRowIndexToModel(row), 0);
153 }
154
[9149]155 /**
156 * Adds a custom table cell renderer to render cells of the tags table.
157 *
158 * If the renderer is not capable performing a {@link TableCellRenderer#getTableCellRendererComponent},
159 * it should return {@code null} to fall back to the
160 * {@link PropertiesCellRenderer#getTableCellRendererComponent default implementation}.
161 * @param renderer the renderer to add
162 * @since 9149
163 */
164 public void addCustomRenderer(TableCellRenderer renderer) {
165 customRenderer.add(renderer);
166 }
167
168 /**
169 * Removes a custom table cell renderer.
170 * @param renderer the renderer to remove
171 * @since 9149
172 */
173 public void removeCustomRenderer(TableCellRenderer renderer) {
174 customRenderer.remove(renderer);
175 }
[7937]176}
Note: See TracBrowser for help on using the repository browser.