Ticket #6150: mapcss-parent_tag-improvement.patch
| File mapcss-parent_tag-improvement.patch, 9.9 KB (added by , 15 years ago) |
|---|
-
src/org/openstreetmap/josm/gui/mappaint/Environment.java
1 1 // License: GPL. For details, see LICENSE file. 2 2 package org.openstreetmap.josm.gui.mappaint; 3 3 4 import java.util.List; 5 4 6 import org.openstreetmap.josm.data.osm.OsmPrimitive; 7 import org.openstreetmap.josm.gui.mappaint.mapcss.Instruction; 8 import org.openstreetmap.josm.gui.mappaint.mapcss.Selector; 5 9 10 6 11 public class Environment { 7 12 8 13 public OsmPrimitive osm; 9 14 public MultiCascade mc; 10 15 public String layer; 11 16 public StyleSource source; 17 /** 18 * <p>after the selectors of a MapCSS rule have been applied to {@code osm}, the matching 19 * parent objects of {@code osm} are remembered in this field. It can be accessed in 20 * {@link Instruction#execute(Environment)} to access tags from parent objects.</p> 21 * 22 */ 23 public List<OsmPrimitive> matchingReferrers = null; 12 24 13 25 public Environment(OsmPrimitive osm, MultiCascade mc, String layer, StyleSource source) { 14 26 this.osm = osm; … … 17 29 this.source = source; 18 30 } 19 31 32 /** 33 * <p>Remembers the referrers to {@link #osm} matching the selector {@code selector}.</p> 34 * 35 * @param selector the selector 36 */ 37 public void rememberMatchingReferrers(Selector selector) { 38 if (selector == null) { 39 this.matchingReferrers = null; 40 } else { 41 this.matchingReferrers = selector.getMatchingReferrers(this); 42 } 43 } 44 45 public void forgetMatchingReferrers() { 46 this.matchingReferrers = null; 47 } 20 48 } -
src/org/openstreetmap/josm/gui/mappaint/mapcss/Expression.java
16 16 import org.openstreetmap.josm.actions.search.SearchCompiler.Match; 17 17 import org.openstreetmap.josm.actions.search.SearchCompiler.ParseError; 18 18 import org.openstreetmap.josm.data.osm.OsmPrimitive; 19 import org.openstreetmap.josm.data.osm.Relation;20 19 import org.openstreetmap.josm.gui.mappaint.Cascade; 21 20 import org.openstreetmap.josm.gui.mappaint.Environment; 22 21 import org.openstreetmap.josm.tools.CheckParameterUtil; … … 173 172 return env.osm.get(key); 174 173 } 175 174 176 // FIXME: respect parent selector chain177 175 public String parent_tag(String key) { 178 for (Relation parent: OsmPrimitive.getFilteredList(env.osm.getReferrers(), Relation.class)) { 176 if (env.matchingReferrers == null) return null; 177 for (OsmPrimitive parent: env.matchingReferrers) { 179 178 String value = parent.get(key); 180 179 if (value != null) return value; 181 180 } -
src/org/openstreetmap/josm/gui/mappaint/mapcss/MapCSSStyleSource.java
109 109 Environment env = new Environment(n, mc, "default", this); 110 110 111 111 NEXT_RULE: 112 for (MapCSSRule r : rules) { 113 for (Selector s : r.selectors) { 114 if ((s instanceof GeneralSelector)) { 115 GeneralSelector gs = (GeneralSelector) s; 116 if (gs.base.equals(type)) 117 { 118 for (Condition cnd : gs.conds) { 119 if (!cnd.applies(env)) 120 continue NEXT_RULE; 112 for (MapCSSRule r : rules) { 113 for (Selector s : r.selectors) { 114 if ((s instanceof GeneralSelector)) { 115 GeneralSelector gs = (GeneralSelector) s; 116 if (gs.base.equals(type)) 117 { 118 for (Condition cnd : gs.conds) { 119 if (!cnd.applies(env)) { 120 continue NEXT_RULE; 121 } 122 } 123 for (Instruction i : r.declaration) { 124 i.execute(env); 125 } 121 126 } 122 for (Instruction i : r.declaration) {123 i.execute(env);124 }125 127 } 126 128 } 127 129 } 128 }129 130 return mc.getCascade("default"); 130 131 } 131 132 … … 138 139 public void apply(MultiCascade mc, OsmPrimitive osm, double scale, OsmPrimitive multipolyOuterWay, boolean pretendWayIsClosed) { 139 140 Environment env = new Environment(osm, mc, null, this); 140 141 for (MapCSSRule r : rules) { 142 env.forgetMatchingReferrers(); 141 143 for (Selector s : r.selectors) { 142 144 if (s.applies(env)) { 143 145 if (s.getRange().contains(scale)) { … … 152 154 sub = "default"; 153 155 } 154 156 157 env.rememberMatchingReferrers(s); 155 158 if (sub.equals("*")) { 156 159 for (Entry<String, Cascade> entry : mc.getLayers()) { 157 160 env.layer = entry.getKey(); -
src/org/openstreetmap/josm/gui/mappaint/mapcss/Selector.java
1 1 // License: GPL. For details, see LICENSE file. 2 2 package org.openstreetmap.josm.gui.mappaint.mapcss; 3 3 4 import java.util.ArrayList; 4 5 import java.util.List; 5 6 6 7 import org.openstreetmap.josm.data.osm.Node; … … 14 15 import org.openstreetmap.josm.tools.Utils; 15 16 16 17 public interface Selector { 17 18 18 19 public boolean applies(Environment e); 19 20 20 21 public String getSubpart(); 21 22 public Range getRange(); 22 23 24 /** 25 * <p>Replies the list of referrers to the primitive {@code env.osm} which 26 * are matched by this selector. 27 * 28 * @param env the environment 29 * @return the list of referrers, or the empty list if there are no matching referrers 30 */ 31 public List<OsmPrimitive> getMatchingReferrers(Environment env); 32 33 34 /** 35 * <p>Despite its name represents a <em>child selector</em>. JOSM doesn't support 36 * descendant selectors yet.</p> 37 * 38 * <p>In addition to the standard CSS notation for child selectors, JOSM also supports 39 * an "inverse" notation:</p> 40 * <pre> 41 * // the standard notation: 42 * parentselector > childselector { ... } 43 * 44 * // the inverse notation: 45 * childselector < parentselector { ... } 46 * </pre> 47 * 48 */ 23 49 public static class DescendentSelector implements Selector { 24 50 Selector a, b; 25 boolean child; 51 /** true, if this represents a child selector in inverse notation 52 * {@code childselector < parentselector} 53 */ 54 boolean inverseNotation; 26 55 56 /** 57 * 58 * @param a the first selector 59 * @param b the second selector 60 * @param child if true {@code a} is the child selector; otherwise, {@code a} 61 * is the parent selector 62 */ 27 63 public DescendentSelector(Selector a, Selector b, boolean child) { 28 64 this.a = a; 29 65 this.b = b; 30 this. child =child;66 this.inverseNotation = !child; 31 67 } 32 68 33 69 @Override … … 36 72 return false; 37 73 38 74 Environment e2 = new Environment(null, e.mc, e.layer, e.source); 39 if ( child) {75 if (!inverseNotation) { 40 76 for (OsmPrimitive osm : e.osm.getReferrers()) { 41 77 e2.osm = osm; 42 78 if (a.applies(e2)) … … 69 105 public Range getRange() { 70 106 return b.getRange(); 71 107 } 108 109 /** 110 * <p>For a child selector in standard notation {@code parentselector > childselector}, 111 * replies the list of matching referrers, if the {@code childselector} matches 112 * {@code env.osm}.</p> 113 * 114 * <p>Otherwise replies an empty list</p> 115 * 116 * @param env the environment 117 * @return the referrers or the empty list if there are not matching referrers 118 */ 119 public List<OsmPrimitive> getMatchingReferrers(Environment env){ 120 List<OsmPrimitive> ret = new ArrayList<OsmPrimitive>(); 121 if (!b.applies(env)) return ret; 122 Environment e2 = new Environment(null, env.mc, env.layer, env.source); 123 if (!inverseNotation) { 124 for (OsmPrimitive osm : env.osm.getReferrers()) { 125 e2.osm = osm; 126 if (a.applies(e2)) { 127 ret.add(osm); 128 } 129 } 130 } 131 return ret; 132 } 72 133 } 73 134 74 135 public static class GeneralSelector implements Selector { … … 155 216 public String toString() { 156 217 return base + (range == null ? "" : range) + Utils.join("", conds) + (subpart != null ? ("::" + subpart) : ""); 157 218 } 219 220 @Override 221 public List<OsmPrimitive> getMatchingReferrers(Environment env) { 222 /* 223 * a general selector doesn't apply filter conditions to the parent 224 * objects. Reply the unfiltered list of referrers. 225 */ 226 return new ArrayList<OsmPrimitive>(env.osm.getReferrers()); 227 } 158 228 } 159 229 }
