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

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

see #15229 - deprecate Main.parent and Main itself

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