source: josm/trunk/src/org/openstreetmap/josm/gui/dialogs/InspectPrimitiveDialog.java@ 13691

Last change on this file since 13691 was 13636, checked in by Don-vip, 6 years ago

extract style methods to a new Stylable interface

  • Property svn:eol-style set to native
File size: 8.7 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.gui.dialogs;
3
4import static org.openstreetmap.josm.tools.I18n.tr;
5import static org.openstreetmap.josm.tools.I18n.trn;
6
7import java.awt.Dimension;
8import java.awt.GridBagLayout;
9import java.text.Collator;
10import java.util.ArrayList;
11import java.util.Collection;
12import java.util.List;
13import java.util.Locale;
14import java.util.Map;
15import java.util.Map.Entry;
16import java.util.TreeMap;
17
18import javax.swing.JPanel;
19import javax.swing.JScrollPane;
20import javax.swing.JTabbedPane;
21import javax.swing.SingleSelectionModel;
22
23import org.openstreetmap.josm.Main;
24import org.openstreetmap.josm.data.osm.DataSet;
25import org.openstreetmap.josm.data.osm.DefaultNameFormatter;
26import org.openstreetmap.josm.data.osm.OsmPrimitive;
27import org.openstreetmap.josm.data.osm.OsmPrimitiveComparator;
28import org.openstreetmap.josm.gui.ExtendedDialog;
29import org.openstreetmap.josm.gui.MainApplication;
30import org.openstreetmap.josm.gui.NavigatableComponent;
31import org.openstreetmap.josm.gui.mappaint.Cascade;
32import org.openstreetmap.josm.gui.mappaint.ElemStyles;
33import org.openstreetmap.josm.gui.mappaint.MapPaintStyles;
34import org.openstreetmap.josm.gui.mappaint.MultiCascade;
35import org.openstreetmap.josm.gui.mappaint.StyleCache;
36import org.openstreetmap.josm.gui.mappaint.StyleElementList;
37import org.openstreetmap.josm.gui.mappaint.StyleSource;
38import org.openstreetmap.josm.gui.mappaint.mapcss.MapCSSStyleSource;
39import org.openstreetmap.josm.gui.mappaint.styleelement.StyleElement;
40import org.openstreetmap.josm.gui.util.GuiHelper;
41import org.openstreetmap.josm.gui.util.WindowGeometry;
42import org.openstreetmap.josm.gui.widgets.JosmTextArea;
43import org.openstreetmap.josm.tools.GBC;
44
45/**
46 * Panel to inspect one or more OsmPrimitives.
47 *
48 * Gives an unfiltered view of the object's internal state.
49 * Might be useful for power users to give more detailed bug reports and
50 * to better understand the JOSM data representation.
51 */
52public class InspectPrimitiveDialog extends ExtendedDialog {
53
54 protected transient List<OsmPrimitive> primitives;
55 private boolean mappaintTabLoaded;
56 private boolean editcountTabLoaded;
57
58 /**
59 * Constructs a new {@code InspectPrimitiveDialog}.
60 * @param primitives collection of primitives
61 * @param data data set
62 * @since 12672 (signature)
63 */
64 public InspectPrimitiveDialog(final Collection<OsmPrimitive> primitives, DataSet data) {
65 super(Main.parent, tr("Advanced object info"), tr("Close"));
66 this.primitives = new ArrayList<>(primitives);
67 setRememberWindowGeometry(getClass().getName() + ".geometry",
68 WindowGeometry.centerInWindow(Main.parent, new Dimension(750, 550)));
69
70 setButtonIcons("ok");
71 final JTabbedPane tabs = new JTabbedPane();
72
73 tabs.addTab(tr("data"), genericMonospacePanel(new JPanel(), buildDataText(data, this.primitives)));
74
75 final JPanel pMapPaint = new JPanel();
76 tabs.addTab(tr("map style"), pMapPaint);
77 tabs.getModel().addChangeListener(e -> {
78 if (!mappaintTabLoaded && ((SingleSelectionModel) e.getSource()).getSelectedIndex() == 1) {
79 mappaintTabLoaded = true;
80 genericMonospacePanel(pMapPaint, buildMapPaintText());
81 }
82 });
83
84 final JPanel pEditCounts = new JPanel();
85 tabs.addTab(tr("edit counts"), pEditCounts);
86 tabs.getModel().addChangeListener(e -> {
87 if (!editcountTabLoaded && ((SingleSelectionModel) e.getSource()).getSelectedIndex() == 2) {
88 editcountTabLoaded = true;
89 genericMonospacePanel(pEditCounts, buildListOfEditorsText(primitives));
90 }
91 });
92
93 setContent(tabs, false);
94 }
95
96 protected static JPanel genericMonospacePanel(JPanel p, String s) {
97 p.setLayout(new GridBagLayout());
98 JosmTextArea jte = new JosmTextArea();
99 jte.setFont(GuiHelper.getMonospacedFont(jte));
100 jte.setEditable(false);
101 jte.append(s);
102 jte.setCaretPosition(0);
103 p.add(new JScrollPane(jte), GBC.std().fill());
104 return p;
105 }
106
107 protected static String buildDataText(DataSet data, List<OsmPrimitive> primitives) {
108 InspectPrimitiveDataText dt = new InspectPrimitiveDataText(data);
109 primitives.stream()
110 .sorted(OsmPrimitiveComparator.orderingWaysRelationsNodes().thenComparing(OsmPrimitiveComparator.comparingNames()))
111 .forEachOrdered(dt::addPrimitive);
112 return dt.toString();
113 }
114
115 protected static String buildMapPaintText() {
116 final Collection<OsmPrimitive> sel = MainApplication.getLayerManager().getActiveDataSet().getAllSelected();
117 ElemStyles elemstyles = MapPaintStyles.getStyles();
118 NavigatableComponent nc = MainApplication.getMap().mapView;
119 double scale = nc.getDist100Pixel();
120
121 final StringBuilder txtMappaint = new StringBuilder();
122 MapCSSStyleSource.STYLE_SOURCE_LOCK.readLock().lock();
123 try {
124 for (OsmPrimitive osm : sel) {
125 txtMappaint.append(tr("Styles Cache for \"{0}\":", osm.getDisplayName(DefaultNameFormatter.getInstance())));
126
127 MultiCascade mc = new MultiCascade();
128
129 for (StyleSource s : elemstyles.getStyleSources()) {
130 if (s.active) {
131 txtMappaint.append(tr("\n\n> applying {0} style \"{1}\"\n", getSort(s), s.getDisplayString()));
132 s.apply(mc, osm, scale, false);
133 txtMappaint.append(tr("\nRange:{0}", mc.range));
134 for (Entry<String, Cascade> e : mc.getLayers()) {
135 txtMappaint.append("\n ").append(e.getKey()).append(": \n").append(e.getValue());
136 }
137 } else {
138 txtMappaint.append(tr("\n\n> skipping \"{0}\" (not active)", s.getDisplayString()));
139 }
140 }
141 txtMappaint.append(tr("\n\nList of generated Styles:\n"));
142 StyleElementList sl = elemstyles.get(osm, scale, nc);
143 for (StyleElement s : sl) {
144 txtMappaint.append(" * ").append(s).append('\n');
145 }
146 txtMappaint.append("\n\n");
147 }
148 } finally {
149 MapCSSStyleSource.STYLE_SOURCE_LOCK.readLock().unlock();
150 }
151 if (sel.size() == 2) {
152 List<OsmPrimitive> selList = new ArrayList<>(sel);
153 StyleCache sc1 = selList.get(0).getCachedStyle();
154 StyleCache sc2 = selList.get(1).getCachedStyle();
155 if (sc1 == sc2) {
156 txtMappaint.append(tr("The 2 selected objects have identical style caches."));
157 }
158 if (!sc1.equals(sc2)) {
159 txtMappaint.append(tr("The 2 selected objects have different style caches."));
160 }
161 if (sc1 != sc2 && sc1.equals(sc2)) {
162 txtMappaint.append(tr("Warning: The 2 selected objects have equal, but not identical style caches."));
163 }
164 }
165 return txtMappaint.toString();
166 }
167
168 /* Future Ideas:
169 Calculate the most recent edit date from o.getTimestamp().
170 Sort by the count for presentation, so the most active editors are on top.
171 Count only tagged nodes (so empty way nodes don't inflate counts).
172 */
173 protected static String buildListOfEditorsText(Iterable<OsmPrimitive> primitives) {
174 final Map<String, Integer> editCountByUser = new TreeMap<>(Collator.getInstance(Locale.getDefault()));
175
176 // Count who edited each selected object
177 for (OsmPrimitive o : primitives) {
178 if (o.getUser() != null) {
179 String username = o.getUser().getName();
180 Integer oldCount = editCountByUser.get(username);
181 if (oldCount == null) {
182 editCountByUser.put(username, 1);
183 } else {
184 editCountByUser.put(username, oldCount + 1);
185 }
186 }
187 }
188
189 // Print the count in sorted order
190 final StringBuilder s = new StringBuilder(48)
191 .append(trn("{0} user last edited the selection:", "{0} users last edited the selection:",
192 editCountByUser.size(), editCountByUser.size()))
193 .append("\n\n");
194 for (Map.Entry<String, Integer> entry : editCountByUser.entrySet()) {
195 final String username = entry.getKey();
196 final Integer editCount = entry.getValue();
197 s.append(String.format("%6d %s", editCount, username)).append('\n');
198 }
199 return s.toString();
200 }
201
202 private static String getSort(StyleSource s) {
203 if (s instanceof MapCSSStyleSource) {
204 return tr("mapcss");
205 } else {
206 return tr("unknown");
207 }
208 }
209}
Note: See TracBrowser for help on using the repository browser.