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

Last change on this file since 15064 was 15064, checked in by GerdP, 6 years ago

fix #12627,#14287,#14289,#17695

  • let CrossingFinder and ContainsFinder find all objects instead of stopping at first match
  • if objects are selected, make sure that ContainsFinder is called for enclosing objects which are not in the selection
  • enable corresponding unit tests

Draw back: MapCSSTagChecker is a bit slower.

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