source: josm/trunk/src/org/openstreetmap/josm/data/osm/visitor/paint/StyledMapRenderer.java@ 4327

Last change on this file since 4327 was 4327, checked in by xeen, 13 years ago

updates visual appearance of highlights and adds them to select and delete action

in more detail:

  • add target highlighting to select action
  • add target cursor to select action
  • add target highlighting to delete action
  • unify ctrl/alt/shift modifier detection in MapMode actions
  • highlights are now a halo around the way/node instead of a color change
  • default highlight color is now the same as the select color (red)
  • ability to highlight WaySegments and VirtualNodes
  • various style/whitespace nits
  • fixes #2411

This patch touches a lot of areas, so please report any regressions in the map mode
tools. Also please add a comment to #2411 if you find to highlighting in select
mode distracting, so it can be fine tuned (or turned off by default).

  • Property svn:eol-style set to native
File size: 9.0 KB
Line 
1// License: GPL. Copyright 2007 by Immanuel Scholz and others
2package org.openstreetmap.josm.data.osm.visitor.paint;
3
4import java.awt.Graphics2D;
5import java.awt.RenderingHints;
6import java.util.ArrayList;
7import java.util.Collection;
8import java.util.Collections;
9import java.util.List;
10
11import org.openstreetmap.josm.Main;
12import org.openstreetmap.josm.data.Bounds;
13import org.openstreetmap.josm.data.osm.BBox;
14import org.openstreetmap.josm.data.osm.DataSet;
15import org.openstreetmap.josm.data.osm.Node;
16import org.openstreetmap.josm.data.osm.OsmPrimitive;
17import org.openstreetmap.josm.data.osm.Relation;
18import org.openstreetmap.josm.data.osm.Way;
19import org.openstreetmap.josm.data.osm.WaySegment;
20import org.openstreetmap.josm.gui.NavigatableComponent;
21import org.openstreetmap.josm.gui.mappaint.AreaElemStyle;
22import org.openstreetmap.josm.gui.mappaint.ElemStyle;
23import org.openstreetmap.josm.gui.mappaint.ElemStyles;
24import org.openstreetmap.josm.gui.mappaint.MapPaintStyles;
25import org.openstreetmap.josm.gui.mappaint.NodeElemStyle;
26import org.openstreetmap.josm.gui.mappaint.StyleCache.StyleList;
27
28/**
29 * <p>A map renderer which renders a map according to style rules in a set of style sheets.</p>
30 *
31 */
32public class StyledMapRenderer extends AbstractMapRenderer{
33
34 private ElemStyles styles;
35 private double circum;
36 private MapPainter painter;
37 private MapPaintSettings paintSettings;
38
39 private static int FLAG_NORMAL = 0;
40 private static int FLAG_DISABLED = 1;
41 private static int FLAG_SELECTED = 2;
42 private static int FLAG_MEMBER_OF_SELECTED = 4;
43
44 private static class StyleRecord implements Comparable<StyleRecord> {
45 final ElemStyle style;
46 final OsmPrimitive osm;
47 final int flags;
48
49 public StyleRecord(ElemStyle style, OsmPrimitive osm, int flags) {
50 this.style = style;
51 this.osm = osm;
52 this.flags = flags;
53 }
54
55 @Override
56 public int compareTo(StyleRecord other) {
57 if ((this.flags & FLAG_DISABLED) != 0 && (other.flags & FLAG_DISABLED) == 0)
58 return -1;
59 if ((this.flags & FLAG_DISABLED) == 0 && (other.flags & FLAG_DISABLED) != 0)
60 return 1;
61 float z_index1 = this.style.z_index;
62 if ((this.flags & FLAG_SELECTED) != 0) {
63 z_index1 += 700f;
64 } else if ((this.flags & FLAG_MEMBER_OF_SELECTED) != 0) {
65 z_index1 += 600f;
66 }
67 float z_index2 = other.style.z_index;
68 if ((other.flags & FLAG_SELECTED) != 0) {
69 z_index2 += 700f;
70 } else if ((other.flags & FLAG_MEMBER_OF_SELECTED) != 0) {
71 z_index2 += 600f;
72 }
73
74 int d1 = Float.compare(z_index1, z_index2);
75 if (d1 != 0)
76 return d1;
77
78 // simple node on top of icons and shapes
79 if (this.style == NodeElemStyle.SIMPLE_NODE_ELEMSTYLE && other.style != NodeElemStyle.SIMPLE_NODE_ELEMSTYLE)
80 return 1;
81 if (this.style != NodeElemStyle.SIMPLE_NODE_ELEMSTYLE && other.style == NodeElemStyle.SIMPLE_NODE_ELEMSTYLE)
82 return -1;
83
84 // newer primitives to the front
85 long id = this.osm.getUniqueId() - other.osm.getUniqueId();
86 if (id > 0)
87 return 1;
88 if (id < 0)
89 return -1;
90
91 return Float.compare(this.style.object_z_index, other.style.object_z_index);
92 }
93 }
94
95 private class StyleCollector {
96 private final boolean drawArea;
97 private final boolean drawMultipolygon;
98 private final boolean drawRestriction;
99
100 private final List<StyleRecord> styleElems;
101
102 public StyleCollector(boolean drawArea, boolean drawMultipolygon, boolean drawRestriction) {
103 this.drawArea = drawArea;
104 this.drawMultipolygon = drawMultipolygon;
105 this.drawRestriction = drawRestriction;
106 styleElems = new ArrayList<StyleRecord>();
107 }
108
109 public void add(Node osm, int flags) {
110 StyleList sl = styles.get(osm, circum, nc);
111 for (ElemStyle s : sl) {
112 styleElems.add(new StyleRecord(s, osm, flags));
113 }
114 }
115
116 public void add(Way osm, int flags) {
117 StyleList sl = styles.get(osm, circum, nc);
118 for (ElemStyle s : sl) {
119 if (!(drawArea && (flags & FLAG_DISABLED) == 0) && s instanceof AreaElemStyle) {
120 continue;
121 }
122 styleElems.add(new StyleRecord(s, osm, flags));
123 }
124 }
125
126 public void add(Relation osm, int flags) {
127 StyleList sl = styles.get(osm, circum, nc);
128 for (ElemStyle s : sl) {
129 if (drawMultipolygon && drawArea && s instanceof AreaElemStyle && (flags & FLAG_DISABLED) == 0) {
130 styleElems.add(new StyleRecord(s, osm, flags));
131 } else if (drawRestriction && s instanceof NodeElemStyle) {
132 styleElems.add(new StyleRecord(s, osm, flags));
133 }
134 }
135 }
136
137 public void drawAll() {
138 Collections.sort(styleElems);
139 for (StyleRecord r : styleElems) {
140 r.style.paintPrimitive(
141 r.osm,
142 paintSettings,
143 painter,
144 (r.flags & FLAG_SELECTED) != 0,
145 (r.flags & FLAG_MEMBER_OF_SELECTED) != 0
146 );
147 }
148 }
149 }
150
151 /**
152 * {@inheritDoc}
153 */
154 public StyledMapRenderer(Graphics2D g, NavigatableComponent nc, boolean isInactiveMode) {
155 super(g, nc, isInactiveMode);
156 }
157
158 private void collectNodeStyles(DataSet data, StyleCollector sc, BBox bbox) {
159 for (final Node n: data.searchNodes(bbox)) {
160 if (n.isDrawable()) {
161 if (n.isDisabled()) {
162 sc.add(n, FLAG_DISABLED);
163 } else if (data.isSelected(n)) {
164 sc.add(n, FLAG_SELECTED);
165 } else if (n.isMemberOfSelected()) {
166 sc.add(n, FLAG_MEMBER_OF_SELECTED);
167 } else {
168 sc.add(n, FLAG_NORMAL);
169 }
170 }
171 }
172 }
173
174 private void collectWayStyles(DataSet data, StyleCollector sc, BBox bbox) {
175 for (final Way w : data.searchWays(bbox)) {
176 if (w.isDrawable()) {
177 if (w.isDisabled()) {
178 sc.add(w, FLAG_DISABLED);
179 } else if (data.isSelected(w)) {
180 sc.add(w, FLAG_SELECTED);
181 } else if (w.isMemberOfSelected()) {
182 sc.add(w, FLAG_MEMBER_OF_SELECTED);
183 } else {
184 sc.add(w, FLAG_NORMAL);
185 }
186 }
187 }
188 }
189
190 private void collectRelationStyles(DataSet data, StyleCollector sc, BBox bbox) {
191 for (Relation r: data.searchRelations(bbox)) {
192 if (r.isDrawable()) {
193 if (r.isDisabled()) {
194 sc.add(r, FLAG_DISABLED);
195 } else if (data.isSelected(r)) {
196 sc.add(r, FLAG_SELECTED);
197 } else {
198 sc.add(r, FLAG_NORMAL);
199 }
200 }
201 }
202 }
203
204 @Override
205 public void render(final DataSet data, boolean renderVirtualNodes, Bounds bounds) {
206 //long start = System.currentTimeMillis();
207 BBox bbox = new BBox(bounds);
208
209 styles = MapPaintStyles.getStyles();
210
211 this.paintSettings = MapPaintSettings.INSTANCE;
212
213 circum = nc.getDist100Pixel();
214 boolean drawArea = circum <= Main.pref.getInteger("mappaint.fillareas", 10000000);
215 boolean drawMultipolygon = drawArea && Main.pref.getBoolean("mappaint.multipolygon", true);
216 styles.setDrawMultipolygon(drawMultipolygon);
217 boolean drawRestriction = Main.pref.getBoolean("mappaint.restriction", true);
218 boolean leftHandTraffic = Main.pref.getBoolean("mappaint.lefthandtraffic", false);
219
220 g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
221 Main.pref.getBoolean("mappaint.use-antialiasing", true) ?
222 RenderingHints.VALUE_ANTIALIAS_ON : RenderingHints.VALUE_ANTIALIAS_OFF);
223
224 Collection<WaySegment> hws = data.getHighlightedWaySegments();
225
226 this.painter = new MapPainter(paintSettings, g, isInactiveMode, nc, renderVirtualNodes, circum, leftHandTraffic, hws);
227
228 StyleCollector sc = new StyleCollector(drawArea, drawMultipolygon, drawRestriction);
229 collectNodeStyles(data, sc, bbox);
230 collectWayStyles(data, sc, bbox);
231 collectRelationStyles(data, sc, bbox);
232 //long phase1 = System.currentTimeMillis();
233 sc.drawAll();
234 sc = null;
235 painter.drawVirtualNodes(data.searchWays(bbox), data.getHighlightedVirtualNodes());
236
237 //long now = System.currentTimeMillis();
238 //System.err.println(String.format("PAINTING TOOK %d [PHASE1 took %d] (at scale %s)", now - start, phase1 - start, circum));
239 }
240}
Note: See TracBrowser for help on using the repository browser.