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

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

see #8352 - PropertiesDialog: consider table sorting for color preview

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