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

Last change on this file since 10491 was 10446, checked in by Don-vip, 8 years ago

see #13001 - replace calls to Main.main.getCurrentDataSet() by Main.getLayerManager().getEditDataSet()

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