source: josm/trunk/src/org/openstreetmap/josm/gui/mappaint/Environment.java@ 18757

Last change on this file since 18757 was 18757, checked in by taylor.smock, 15 months ago

Fix #17669, #22096: Allow placeholders in more locations in MapCSS

  • Property svn:eol-style set to native
File size: 11.7 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.gui.mappaint;
3
4import java.awt.geom.Area;
5import java.util.LinkedHashSet;
6import java.util.List;
7import java.util.Map;
8import java.util.Set;
9
10import org.openstreetmap.josm.data.osm.IPrimitive;
11import org.openstreetmap.josm.data.osm.Relation;
12import org.openstreetmap.josm.data.osm.Way;
13import org.openstreetmap.josm.data.osm.WaySegment;
14import org.openstreetmap.josm.gui.mappaint.mapcss.Condition.Context;
15import org.openstreetmap.josm.gui.mappaint.mapcss.Selector;
16import org.openstreetmap.josm.gui.mappaint.mapcss.Selector.LinkSelector;
17import org.openstreetmap.josm.tools.CheckParameterUtil;
18
19/**
20 * Environment is a data object to provide access to various "global" parameters.
21 * It is used during processing of MapCSS rules and for the generation of
22 * style elements.
23 */
24public class Environment {
25
26 /**
27 * The primitive that is currently evaluated
28 */
29 public IPrimitive osm;
30
31 /**
32 * The cascades that are currently evaluated
33 */
34 public MultiCascade mc;
35 /**
36 * The current MapCSS layer
37 */
38 public String layer;
39 /**
40 * The style source that is evaluated
41 */
42 public StyleSource source;
43 private Context context = Context.PRIMITIVE;
44
45 /** The selector that is currently being evaluated */
46 private final Selector selector;
47
48 /**
49 * The name of the default layer. It is used if no layer is specified in the MapCSS rule
50 */
51 public static final String DEFAULT_LAYER = "default";
52
53 /**
54 * If not null, this is the matching parent object if a condition or an expression
55 * is evaluated in a {@link LinkSelector} (within a child selector)
56 */
57 public IPrimitive parent;
58
59 /**
60 * The same for parent selector. Only one of the 2 fields (parent or child) is not null in any environment.
61 */
62 public IPrimitive child;
63
64 /**
65 * index of node in parent way or member in parent relation. Must be != null in LINK context.
66 */
67 public Integer index;
68
69 /**
70 * count of nodes in parent way or members in parent relation. Must be != null in LINK context.
71 */
72 public Integer count;
73
74 /**
75 * Set of matched children filled by ContainsFinder and CrossingFinder, null if nothing matched
76 */
77 public Set<IPrimitive> children;
78
79 /**
80 * Crossing ways result from CrossingFinder, filled for incomplete ways/relations
81 */
82 public Map<IPrimitive, Map<List<Way>, List<WaySegment>>> crossingWaysMap;
83
84 /**
85 * Intersection areas (only filled with CrossingFinder if children is not null)
86 */
87 public Map<IPrimitive, Area> intersections;
88
89 /**
90 * Cache for multipolygon areas, can be null, used with CrossingFinder
91 */
92 public Map<IPrimitive, Area> mpAreaCache;
93
94 /**
95 * Can be null, may contain primitives when surrounding objects of the primitives are tested
96 */
97 public Set<IPrimitive> toMatchForSurrounding;
98
99 /**
100 * Creates a new uninitialized environment.
101 */
102 public Environment() {
103 // environment can be initialized later through with* methods
104 this.selector = null;
105 }
106
107 /**
108 * Creates a new environment.
109 * @param osm OSM primitive
110 * @since 8415
111 * @since 13810 (signature)
112 */
113 public Environment(IPrimitive osm) {
114 this(osm, null, null, null);
115 }
116
117 /**
118 * Creates a new environment.
119 * @param osm OSM primitive
120 * @param mc multi cascade
121 * @param layer layer
122 * @param source style source
123 * @since 13810 (signature)
124 */
125 public Environment(IPrimitive osm, MultiCascade mc, String layer, StyleSource source) {
126 this.osm = osm;
127 this.mc = mc;
128 this.layer = layer;
129 this.source = source;
130 this.selector = null;
131 }
132
133 /**
134 * Creates a clone of the environment {@code other}.
135 *
136 * @param other the other environment. Must not be null.
137 * @throws IllegalArgumentException if {@code param} is {@code null}
138 */
139 public Environment(Environment other) {
140 this(other, other.selector);
141 }
142
143 /**
144 * Creates a clone of the environment {@code other}.
145 *
146 * @param other the other environment. Must not be null.
147 * @param selector the selector for this environment. May be null.
148 * @throws IllegalArgumentException if {@code param} is {@code null}
149 */
150 private Environment(Environment other, Selector selector) {
151 CheckParameterUtil.ensureParameterNotNull(other);
152 this.osm = other.osm;
153 this.mc = other.mc;
154 this.layer = other.layer;
155 this.parent = other.parent;
156 this.child = other.child;
157 this.source = other.source;
158 this.index = other.index;
159 this.count = other.count;
160 this.context = other.getContext();
161 this.children = other.children == null ? null : new LinkedHashSet<>(other.children);
162 this.intersections = other.intersections;
163 this.crossingWaysMap = other.crossingWaysMap;
164 this.mpAreaCache = other.mpAreaCache;
165 this.toMatchForSurrounding = other.toMatchForSurrounding;
166 this.selector = selector;
167 }
168
169 /**
170 * Creates a clone of this environment, with the specified primitive.
171 * @param osm OSM primitive
172 * @return A clone of this environment, with the specified primitive
173 * @see #osm
174 * @since 13810 (signature)
175 */
176 public Environment withPrimitive(IPrimitive osm) {
177 Environment e = new Environment(this);
178 e.osm = osm;
179 return e;
180 }
181
182 /**
183 * Creates a clone of this environment, with the specified parent.
184 * @param parent the matching parent object
185 * @return A clone of this environment, with the specified parent
186 * @see #parent
187 * @since 13810 (signature)
188 */
189 public Environment withParent(IPrimitive parent) {
190 Environment e = new Environment(this);
191 e.parent = parent;
192 return e;
193 }
194
195 /**
196 * Creates a clone of this environment, with the specified parent, index, and context set to {@link Context#LINK}.
197 * @param parent the matching parent object
198 * @param index index of node in parent way or member in parent relation
199 * @param count count of nodes in parent way or members in parent relation
200 * @return A clone of this environment, with the specified parent, index, and context set to {@link Context#LINK}
201 * @see #parent
202 * @see #index
203 * @since 6175
204 * @since 13810 (signature)
205 */
206 public Environment withParentAndIndexAndLinkContext(IPrimitive parent, int index, int count) {
207 Environment e = new Environment(this);
208 e.parent = parent;
209 e.index = index;
210 e.count = count;
211 e.context = Context.LINK;
212 return e;
213 }
214
215 /**
216 * Creates a clone of this environment, with the specified child.
217 * @param child the matching child object
218 * @return A clone of this environment, with the specified child
219 * @see #child
220 * @since 13810 (signature)
221 */
222 public Environment withChild(IPrimitive child) {
223 Environment e = new Environment(this);
224 e.child = child;
225 return e;
226 }
227
228 /**
229 * Creates a clone of this environment, with the specified child, index, and context set to {@link Context#LINK}.
230 * @param child the matching child object
231 * @param index index of node in parent way or member in parent relation
232 * @param count count of nodes in parent way or members in parent relation
233 * @return A clone of this environment, with the specified child, index, and context set to {@code Context#LINK}
234 * @see #child
235 * @see #index
236 * @since 6175
237 * @since 13810 (signature)
238 */
239 public Environment withChildAndIndexAndLinkContext(IPrimitive child, int index, int count) {
240 Environment e = new Environment(this);
241 e.child = child;
242 e.index = index;
243 e.count = count;
244 e.context = Context.LINK;
245 return e;
246 }
247
248 /**
249 * Creates a clone of this environment, with the specified index.
250 * @param index index of node in parent way or member in parent relation
251 * @param count count of nodes in parent way or members in parent relation
252 * @return A clone of this environment, with the specified index
253 * @see #index
254 */
255 public Environment withIndex(int index, int count) {
256 Environment e = new Environment(this);
257 e.index = index;
258 e.count = count;
259 return e;
260 }
261
262 /**
263 * Creates a clone of this environment, with the specified {@link Context}.
264 * @param context context
265 * @return A clone of this environment, with the specified {@code Context}
266 */
267 public Environment withContext(Context context) {
268 Environment e = new Environment(this);
269 e.context = context == null ? Context.PRIMITIVE : context;
270 return e;
271 }
272
273 /**
274 * Creates a clone of this environment, with context set to {@link Context#LINK}.
275 * @return A clone of this environment, with context set to {@code Context#LINK}
276 */
277 public Environment withLinkContext() {
278 Environment e = new Environment(this);
279 e.context = Context.LINK;
280 return e;
281 }
282
283 /**
284 * Creates a clone of this environment, with the selector set
285 * @param selector The selector to use
286 * @return A clone of this environment, with the specified selector
287 * @since xxx
288 */
289 public Environment withSelector(Selector selector) {
290 return new Environment(this, selector);
291 }
292
293 /**
294 * Determines if the context of this environment is {@link Context#LINK}.
295 * @return {@code true} if the context of this environment is {@code Context#LINK}, {@code false} otherwise
296 */
297 public boolean isLinkContext() {
298 return Context.LINK == context;
299 }
300
301 /**
302 * Determines if this environment has a relation as parent.
303 * @return {@code true} if this environment has a relation as parent, {@code false} otherwise
304 * @see #parent
305 */
306 public boolean hasParentRelation() {
307 return parent instanceof Relation;
308 }
309
310 /**
311 * Replies the current context.
312 *
313 * @return the current context
314 */
315 public Context getContext() {
316 return context == null ? Context.PRIMITIVE : context;
317 }
318
319 /**
320 * Gets the role of the matching primitive in the relation
321 * @return The role
322 */
323 public String getRole() {
324 if (getContext() == Context.PRIMITIVE)
325 return null;
326
327 if (parent instanceof Relation)
328 return ((Relation) parent).getMember(index).getRole();
329 if (child != null && osm instanceof Relation)
330 return ((Relation) osm).getMember(index).getRole();
331 return null;
332 }
333
334 /**
335 * Get the selector for this environment
336 * @return The selector. May be {@code null}.
337 * @since xxx
338 */
339 public Selector selector() {
340 return this.selector;
341 }
342
343 /**
344 * Clears all matching context information
345 * @return this
346 */
347 public Environment clearSelectorMatchingInformation() {
348 parent = null;
349 child = null;
350 index = null;
351 count = null;
352 children = null;
353 intersections = null;
354 crossingWaysMap = null;
355 return this;
356 }
357
358 /**
359 * Gets the current cascade for the current layer of this environment
360 * @return The cascade
361 */
362 public Cascade getCascade() {
363 return getCascade(null);
364 }
365
366 /**
367 * Gets the current cascade for a given layer
368 * @param layer The layer to use, <code>null</code> to use the layer of the {@link Environment}
369 * @return The cascade
370 */
371 public Cascade getCascade(String layer) {
372 return mc == null ? null : mc.getCascade(layer == null ? this.layer : layer);
373 }
374}
Note: See TracBrowser for help on using the repository browser.