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

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

see #15182 - deprecate Main.getLayerManager(). Replacement: gui.MainApplication.getLayerManager()

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