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

Last change on this file since 3848 was 3848, checked in by bastiK, 13 years ago

Experimental mapcss support. All *.java files in the gui/mappaint/mapcss/parser folder are generated from the javacc source file MapCSSParser.jj in the same folder. The generated code sums up to 2700 lines, there is no further build dependency.

  • Property svn:eol-style set to native
File size: 11.3 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;
5
6import java.awt.Dimension;
7import java.awt.Font;
8import java.awt.GridBagLayout;
9import java.util.Collection;
10import java.util.List;
11
12import javax.swing.event.ChangeEvent;
13import javax.swing.JPanel;
14import javax.swing.JScrollPane;
15import javax.swing.JTabbedPane;
16import javax.swing.JTextArea;
17import javax.swing.SingleSelectionModel;
18import javax.swing.event.ChangeListener;
19
20import org.openstreetmap.josm.Main;
21import org.openstreetmap.josm.gui.ExtendedDialog;
22import org.openstreetmap.josm.data.osm.DataSet;
23import org.openstreetmap.josm.tools.SubclassFilteredCollection;
24import org.openstreetmap.josm.data.osm.Node;
25import org.openstreetmap.josm.data.osm.OsmPrimitive;
26import org.openstreetmap.josm.data.osm.Relation;
27import org.openstreetmap.josm.data.osm.RelationMember;
28import org.openstreetmap.josm.data.osm.User;
29import org.openstreetmap.josm.data.osm.Way;
30import org.openstreetmap.josm.gui.DefaultNameFormatter;
31import org.openstreetmap.josm.gui.NavigatableComponent;
32import org.openstreetmap.josm.gui.mappaint.ElemStyle;
33import org.openstreetmap.josm.gui.mappaint.ElemStyles;
34import org.openstreetmap.josm.gui.mappaint.MapPaintStyles;
35import org.openstreetmap.josm.gui.mappaint.MultiCascade;
36import org.openstreetmap.josm.gui.mappaint.StyleCache.StyleList;
37import org.openstreetmap.josm.gui.mappaint.StyleSource;
38import org.openstreetmap.josm.gui.mappaint.mapcss.MapCSSStyleSource;
39import org.openstreetmap.josm.gui.mappaint.xml.XmlStyleSource;
40import org.openstreetmap.josm.tools.DateUtils;
41import org.openstreetmap.josm.tools.GBC;
42
43/**
44 * Panel to inspect one or more OsmPrimitives.
45 *
46 * Gives an unfiltered view of the object's internal state.
47 * Might be useful for power users to give more detailed bug reports and
48 * to better understand the JOSM data representation.
49 *
50 * TODO: show conflicts
51 */
52public class InspectPrimitiveDialog extends ExtendedDialog {
53 protected Collection<OsmPrimitive> primitives;
54 private JTextArea txtData;
55 private JTextArea txtMappaint;
56 boolean mappaintTabLoaded;
57
58 public InspectPrimitiveDialog(Collection<OsmPrimitive> primitives) {
59 super(Main.parent, tr("Advanced object info"), new String[] {"Close"});
60 this.primitives = primitives;
61 setPreferredSize(new Dimension(750, 550));
62
63 setButtonIcons(new String[] {"ok.png"});
64 final JTabbedPane tabs = new JTabbedPane();
65 JPanel pData = buildDataPanel();
66 tabs.addTab(tr("data"), pData);
67 final JPanel pMapPaint = new JPanel();
68 tabs.addTab(tr("map style"), pMapPaint);
69 tabs.getModel().addChangeListener(new ChangeListener() {
70
71 @Override
72 public void stateChanged(ChangeEvent e) {
73 if (!mappaintTabLoaded && ((SingleSelectionModel) e.getSource()).getSelectedIndex() == 1) {
74 mappaintTabLoaded = true;
75 buildMapPaintPanel(pMapPaint);
76 createMapPaintText();
77 }
78 }
79 });
80 txtData.setText(buildDataText());
81 setContent(tabs, false);
82 }
83
84 protected JPanel buildDataPanel() {
85 JPanel p = new JPanel(new GridBagLayout());
86 txtData = new JTextArea();
87 txtData.setFont(new Font("Monospaced", txtData.getFont().getStyle(), txtData.getFont().getSize()));
88 txtData.setEditable(false);
89
90 JScrollPane scroll = new JScrollPane(txtData);
91
92 p.add(scroll, GBC.std().fill());
93 return p;
94 }
95
96 protected String buildDataText() {
97 StringBuilder s = new StringBuilder();
98 for (Node n : new SubclassFilteredCollection<OsmPrimitive, Node>(primitives, OsmPrimitive.nodePredicate)) {
99 s.append("Node id="+n.getUniqueId());
100 if (!checkDataSet(n)) {
101 s.append(" not in data set");
102 continue;
103 }
104 if (n.isIncomplete()) {
105 s.append(" incomplete\n");
106 addWayReferrer(s, n);
107 addRelationReferrer(s, n);
108 continue;
109 }
110 s.append(String.format(" lat=%s lon=%s (projected: x=%s, y=%s); ",
111 Double.toString(n.getCoor().lat()), Double.toString(n.getCoor().lon()),
112 Double.toString(n.getEastNorth().east()), Double.toString(n.getEastNorth().north())));
113 addCommon(s, n);
114 addAttributes(s, n);
115 addWayReferrer(s, n);
116 addRelationReferrer(s, n);
117 s.append('\n');
118 }
119
120 for (Way w : new SubclassFilteredCollection<OsmPrimitive, Way>(primitives, OsmPrimitive.wayPredicate)) {
121 s.append("Way id="+ w.getUniqueId());
122 if (!checkDataSet(w)) {
123 s.append(" not in data set");
124 continue;
125 }
126 if (w.isIncomplete()) {
127 s.append(" incomplete\n");
128 addRelationReferrer(s, w);
129 continue;
130 }
131 s.append(String.format(" %d nodes; ", w.getNodes().size()));
132 addCommon(s, w);
133 addAttributes(s, w);
134 addRelationReferrer(s, w);
135
136 s.append(" nodes:\n");
137 for (Node n : w.getNodes()) {
138 s.append(String.format(" %d\n", n.getUniqueId()));
139 }
140 s.append('\n');
141 }
142
143 for (Relation r : new SubclassFilteredCollection<OsmPrimitive, Relation>(primitives, OsmPrimitive.relationPredicate)) {
144 s.append("Relation id="+r.getUniqueId());
145 if (!checkDataSet(r)) {
146 s.append(" not in data set");
147 continue;
148 }
149 if (r.isIncomplete()) {
150 s.append(" incomplete\n");
151 addRelationReferrer(s, r);
152 continue;
153 }
154 s.append(String.format(" %d members; ",r.getMembersCount()));
155 addCommon(s, r);
156 addAttributes(s, r);
157 addRelationReferrer(s, r);
158
159 s.append(" members:\n");
160 for (RelationMember m : r.getMembers() ) {
161 s.append(String.format(" %s%d '%s'\n", m.getMember().getType().getAPIName().substring(0,1), m.getMember().getUniqueId(), m.getRole()));
162 }
163 s.append('\n');
164 }
165
166 return s.toString().trim();
167 }
168
169 protected void addCommon(StringBuilder s, OsmPrimitive o) {
170 s.append(String.format("Data set: %X; User: [%s]; ChangeSet id: %H; Timestamp: %s, Version: %d",
171 o.getDataSet().hashCode(),
172 userString(o.getUser()),
173 o.getChangesetId(),
174 DateUtils.fromDate(o.getTimestamp()),
175 o.getVersion()));
176
177 /* selected state is left out: not interesting as it is always selected */
178 if (o.isDeleted()) {
179 s.append("; deleted");
180 }
181 if (!o.isVisible()) {
182 s.append("; deleted-on-server");
183 }
184 if (o.isModified()) {
185 s.append("; modified");
186 }
187 if (o.isDisabledAndHidden()) {
188 s.append("; filtered/hidden");
189 }
190 if (o.isDisabled()) {
191 s.append("; filtered/disabled");
192 }
193 if (o.hasDirectionKeys()) {
194 s.append("; has direction keys");
195 if (o.reversedDirection()) {
196 s.append(" (reversed)");
197 }
198 }
199 s.append("\n");
200 }
201
202 protected void addAttributes(StringBuilder s, OsmPrimitive o) {
203 if (o.hasKeys()) {
204 s.append(" tags:\n");
205 for (String key: o.keySet()) {
206 s.append(String.format(" \"%s\"=\"%s\"\n", key, o.get(key)));
207 }
208 }
209 }
210
211 protected void addWayReferrer(StringBuilder s, Node n) {
212 // add way referrer
213 List<OsmPrimitive> refs = n.getReferrers();
214 Collection<Way> wayRefs = new SubclassFilteredCollection<OsmPrimitive, Way>(refs, OsmPrimitive.wayPredicate);
215 if (wayRefs.size() > 0) {
216 s.append(" way referrer:\n");
217 for (Way w : wayRefs) {
218 s.append(" "+w.getUniqueId()+"\n");
219 }
220 }
221 }
222
223 protected void addRelationReferrer(StringBuilder s, OsmPrimitive o) {
224 List<OsmPrimitive> refs = o.getReferrers();
225 Collection<Relation> relRefs = new SubclassFilteredCollection<OsmPrimitive, Relation>(refs, OsmPrimitive.relationPredicate);
226 if (relRefs.size() > 0) {
227 s.append(" relation referrer:\n");
228 for (Relation r : relRefs) {
229 s.append(" "+r.getUniqueId()+"\n");
230 }
231 }
232 }
233
234 /**
235 * See if primitive is in a data set properly.
236 * This does not hold for primitives that are new and deleted.
237 */
238 protected boolean checkDataSet(OsmPrimitive o) {
239 DataSet ds = o.getDataSet();
240 if (ds == null)
241 return false;
242 return ds.getPrimitiveById(o) != null;
243 }
244
245 protected String userString(User user) {
246 if (user == null)
247 return "<null>";
248
249 List<String> names = user.getNames();
250
251 StringBuilder us = new StringBuilder();
252
253 us.append("id:"+user.getId());
254 if (names.size() == 1) {
255 us.append(" name:"+user.getName());
256 }
257 else if (names.size() > 1) {
258 us.append(String.format(" %d names:%s", names.size(), user.getName()));
259 }
260 return us.toString();
261 }
262
263 protected void buildMapPaintPanel(JPanel p) {
264 p.setLayout(new GridBagLayout());
265 txtMappaint = new JTextArea();
266 txtMappaint.setFont(new Font("Monospaced", txtMappaint.getFont().getStyle(), txtMappaint.getFont().getSize()));
267 txtMappaint.setEditable(false);
268
269 p.add(new JScrollPane(txtMappaint), GBC.std().fill());
270 }
271
272 protected void createMapPaintText() {
273 final Collection<OsmPrimitive> sel = Main.main.getCurrentDataSet().getSelected();
274 ElemStyles elemstyles = MapPaintStyles.getStyles();
275 NavigatableComponent nc = Main.map.mapView;
276 double scale = nc.getDist100Pixel();
277
278 for (OsmPrimitive osm : sel) {
279 txtMappaint.append("Styles Cache for \""+osm.getDisplayName(DefaultNameFormatter.getInstance())+"\":");
280
281 MultiCascade mc = new MultiCascade();
282
283 for (StyleSource s : elemstyles.getStyleSources()) {
284 if (s.active) {
285 txtMappaint.append("\n\n> applying "+getSort(s)+" style \""+s.getDisplayString()+"\n");
286 s.apply(mc, osm, scale, null, false);
287 txtMappaint.append("\nRange:"+mc.range);
288 for (String key : mc.keySet()) {
289 txtMappaint.append("\n "+key+": \n"+mc.get(key));
290 }
291 } else {
292 txtMappaint.append("\n\n> skipping \""+s.getDisplayString()+"\" (not active)");
293 }
294 }
295 txtMappaint.append("\n\nList of generated Styles:\n");
296 StyleList sl = elemstyles.get(osm, scale, nc);
297 for (ElemStyle s : sl) {
298 txtMappaint.append(" * "+s+"\n");
299 }
300 txtMappaint.append("\n\n");
301 }
302 }
303
304 private String getSort(StyleSource s) {
305 if (s instanceof XmlStyleSource)
306 return "xml";
307 if (s instanceof MapCSSStyleSource)
308 return "mapcss";
309 return "unkown";
310 }
311
312}
Note: See TracBrowser for help on using the repository browser.