Ticket #6150: mapcss-parent_tag-improvement.patch

File mapcss-parent_tag-improvement.patch, 9.9 KB (added by Gubaer, 15 years ago)

Updated patch

  • src/org/openstreetmap/josm/gui/mappaint/Environment.java

     
    11// License: GPL. For details, see LICENSE file.
    22package org.openstreetmap.josm.gui.mappaint;
    33
     4import java.util.List;
     5
    46import org.openstreetmap.josm.data.osm.OsmPrimitive;
     7import org.openstreetmap.josm.gui.mappaint.mapcss.Instruction;
     8import org.openstreetmap.josm.gui.mappaint.mapcss.Selector;
    59
     10
    611public class Environment {
    7    
     12
    813    public OsmPrimitive osm;
    914    public MultiCascade mc;
    1015    public String layer;
    1116    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;
    1224
    1325    public Environment(OsmPrimitive osm, MultiCascade mc, String layer, StyleSource source) {
    1426        this.osm = osm;
     
    1729        this.source = source;
    1830    }
    1931
     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    }
    2048}
  • src/org/openstreetmap/josm/gui/mappaint/mapcss/Expression.java

     
    1616import org.openstreetmap.josm.actions.search.SearchCompiler.Match;
    1717import org.openstreetmap.josm.actions.search.SearchCompiler.ParseError;
    1818import org.openstreetmap.josm.data.osm.OsmPrimitive;
    19 import org.openstreetmap.josm.data.osm.Relation;
    2019import org.openstreetmap.josm.gui.mappaint.Cascade;
    2120import org.openstreetmap.josm.gui.mappaint.Environment;
    2221import org.openstreetmap.josm.tools.CheckParameterUtil;
     
    173172                return env.osm.get(key);
    174173            }
    175174
    176             // FIXME: respect parent selector chain
    177175            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) {
    179178                    String value = parent.get(key);
    180179                    if (value != null) return value;
    181180                }
  • src/org/openstreetmap/josm/gui/mappaint/mapcss/MapCSSStyleSource.java

     
    109109        Environment env = new Environment(n, mc, "default", this);
    110110
    111111        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                            }
    121126                        }
    122                         for (Instruction i : r.declaration) {
    123                             i.execute(env);
    124                         }
    125127                    }
    126128                }
    127129            }
    128         }
    129130        return mc.getCascade("default");
    130131    }
    131132
     
    138139    public void apply(MultiCascade mc, OsmPrimitive osm, double scale, OsmPrimitive multipolyOuterWay, boolean pretendWayIsClosed) {
    139140        Environment env = new Environment(osm, mc, null, this);
    140141        for (MapCSSRule r : rules) {
     142            env.forgetMatchingReferrers();
    141143            for (Selector s : r.selectors) {
    142144                if (s.applies(env)) {
    143145                    if (s.getRange().contains(scale)) {
     
    152154                        sub = "default";
    153155                    }
    154156
     157                    env.rememberMatchingReferrers(s);
    155158                    if (sub.equals("*")) {
    156159                        for (Entry<String, Cascade> entry : mc.getLayers()) {
    157160                            env.layer = entry.getKey();
  • src/org/openstreetmap/josm/gui/mappaint/mapcss/Selector.java

     
    11// License: GPL. For details, see LICENSE file.
    22package org.openstreetmap.josm.gui.mappaint.mapcss;
    33
     4import java.util.ArrayList;
    45import java.util.List;
    56
    67import org.openstreetmap.josm.data.osm.Node;
     
    1415import org.openstreetmap.josm.tools.Utils;
    1516
    1617public interface Selector {
    17    
     18
    1819    public boolean applies(Environment e);
    1920
    2021    public String getSubpart();
    2122    public Range getRange();
    2223
     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     */
    2349    public static class DescendentSelector implements Selector {
    2450        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;
    2655
     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         */
    2763        public DescendentSelector(Selector a, Selector b, boolean child) {
    2864            this.a = a;
    2965            this.b = b;
    30             this.child = child;
     66            this.inverseNotation = !child;
    3167        }
    3268
    3369        @Override
     
    3672                return false;
    3773
    3874            Environment e2 = new Environment(null, e.mc, e.layer, e.source);
    39             if (child) {
     75            if (!inverseNotation) {
    4076                for (OsmPrimitive osm : e.osm.getReferrers()) {
    4177                    e2.osm = osm;
    4278                    if (a.applies(e2))
     
    69105        public Range getRange() {
    70106            return b.getRange();
    71107        }
     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        }
    72133    }
    73134
    74135    public static class GeneralSelector implements Selector {
     
    155216        public String toString() {
    156217            return base + (range == null ? "" : range) + Utils.join("", conds) + (subpart != null ? ("::" + subpart) : "");
    157218        }
     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        }
    158228    }
    159229}