Changeset 4011 in josm for trunk


Ignore:
Timestamp:
2011-03-30T22:25:20+02:00 (14 years ago)
Author:
bastiK
Message:

applied #6150 - mapcss - improve parent_tag (based on patch by Gubaer)

Location:
trunk/src/org/openstreetmap/josm/gui/mappaint
Files:
7 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/org/openstreetmap/josm/gui/mappaint/Environment.java

    r3893 r4011  
    22package org.openstreetmap.josm.gui.mappaint;
    33
     4import java.util.Collection;
     5import java.util.List;
     6
    47import org.openstreetmap.josm.data.osm.OsmPrimitive;
     8import org.openstreetmap.josm.gui.mappaint.mapcss.Instruction;
    59
    610public class Environment {
    7    
     11
    812    public OsmPrimitive osm;
    913    public MultiCascade mc;
    1014    public String layer;
    1115    public StyleSource source;
     16
     17    /**
     18     * <p>When matching a child selector, the matching referrers will be stored.
     19     * They can be accessed in {@link Instruction#execute(Environment)} to access
     20     * tags from parent objects.</p>
     21     */
     22    private List<OsmPrimitive> matchingReferrers = null;
    1223
    1324    public Environment(OsmPrimitive osm, MultiCascade mc, String layer, StyleSource source) {
     
    1829    }
    1930
     31    public Collection<OsmPrimitive> getMatchingReferrers() {
     32        return matchingReferrers;
     33    }
     34
     35    public void setMatchingReferrers(List<OsmPrimitive> refs) {
     36        matchingReferrers = refs;
     37    }
     38
     39    public void clearMatchingReferrers() {
     40        matchingReferrers = null;
     41    }
    2042}
  • trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/Expression.java

    r4008 r4011  
    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;
     
    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)) {
    179                     String value = parent.get(key);
    180                     if (value != null) return value;
    181                 }
    182                 return null;
     176                if (env.getMatchingReferrers() == null) {
     177                    // we don't have a matched parent, so just search all referrers
     178                    for (OsmPrimitive parent : env.osm.getReferrers()) {
     179                        String value = parent.get(key);
     180                        if (value != null)
     181                            return value;
     182                    }
     183                    return null;
     184                }
     185                if (env.getMatchingReferrers().isEmpty())
     186                    return null;
     187                // use always the first matching referrer to have consistency
     188                // in an expression and declaration block
     189                return env.getMatchingReferrers().iterator().next().get(key);
    183190            }
    184191
  • trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/MapCSSStyleSource.java

    r3987 r4011  
    140140        for (MapCSSRule r : rules) {
    141141            for (Selector s : r.selectors) {
    142                 if (s.applies(env)) {
     142                env.clearMatchingReferrers();
     143                if (s.matches(env)) { // as side effect env.matchingReferrers will be set (if s is a child selector)
    143144                    if (s.getRange().contains(scale)) {
    144145                        mc.range = Range.cut(mc.range, s.getRange());
  • trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/Selector.java

    r3902 r4011  
    22package org.openstreetmap.josm.gui.mappaint.mapcss;
    33
     4import java.util.ArrayList;
    45import java.util.List;
    56
     
    1516
    1617public interface Selector {
    17    
    18     public boolean applies(Environment e);
     18
     19    /**
     20     * Apply the selector to the primitive and check if it matches.
     21     *
     22     * @param env the Environment. env.mc and env.layer are read-only when matching a selector.
     23     * env.source is not needed. This method will set the matchingReferrers field of env as
     24     * a side effect! Make sure to clear it before invoking this method.
     25     * @return true, if the selector applies
     26     */
     27    public boolean matches(Environment env);
    1928
    2029    public String getSubpart();
     30
    2131    public Range getRange();
    2232
    23     public static class DescendentSelector implements Selector {
     33    /**
     34     * <p>Represents a child selector or a parent selector.</p>
     35     *
     36     * <p>In addition to the standard CSS notation for child selectors, JOSM also supports
     37     * an "inverse" notation:</p>
     38     * <pre>
     39     *    selector_a > selector_b { ... }       // the standard notation (child selector)
     40     *    relation[type=route] > way { ... }    // example (all ways of a route)
     41     *
     42     *    selector_a < selector_b { ... }       // the inverse notation (parent selector)
     43     *    node[traffic_calming] < way { ... }   // example (way that has a traffic calming node)
     44     * </pre>
     45     *
     46     */
     47    public static class ChildOrParentSelector implements Selector {
    2448        Selector a, b;
    25         boolean child;
     49        /** true, if this represents a parent selector (otherwise it is a child selector)
     50         */
     51        private final boolean parentSelector;
    2652
    27         public DescendentSelector(Selector a, Selector b, boolean child) {
     53        /**
     54         *
     55         * @param a the first selector
     56         * @param b the second selector
     57         * @param parentSelector if true, this is a parent selector; otherwise a child selector
     58         */
     59        public ChildOrParentSelector(Selector a, Selector b, boolean parentSelector) {
    2860            this.a = a;
    2961            this.b = b;
    30             this.child = child;
     62            this.parentSelector = parentSelector;
    3163        }
    3264
    3365        @Override
    34         public boolean applies(Environment e) {
    35             if (!b.applies(e))
     66        public boolean matches(Environment e) {
     67            if (!b.matches(e))
    3668                return false;
    3769
    3870            Environment e2 = new Environment(null, e.mc, e.layer, e.source);
    39             if (child) {
    40                 for (OsmPrimitive osm : e.osm.getReferrers()) {
    41                     e2.osm = osm;
    42                     if (a.applies(e2))
    43                         return true;
     71            List<OsmPrimitive> matchingRefs = new ArrayList<OsmPrimitive>();
     72            if (!parentSelector) {
     73                for (OsmPrimitive ref : e.osm.getReferrers()) {
     74                    e2.osm = ref;
     75                    if (a.matches(e2)) {
     76                        matchingRefs.add(ref);
     77                    }
     78                }
     79                if (!matchingRefs.isEmpty()) {
     80                    e.setMatchingReferrers(matchingRefs);
     81                    return true;
    4482                }
    4583            } else {
     
    4785                    for (OsmPrimitive chld : ((Relation) e.osm).getMemberPrimitives()) {
    4886                        e2.osm = chld;
    49                         if (a.applies(e2))
     87                        if (a.matches(e2))
    5088                            return true;
    5189                    }
     
    5391                    for (Node n : ((Way) e.osm).getNodes()) {
    5492                        e2.osm = n;
    55                         if (a.applies(e2))
     93                        if (a.matches(e2))
    5694                            return true;
    5795                    }
     
    104142
    105143        @Override
    106         public boolean applies(Environment e) {
     144        public boolean matches(Environment e) {
    107145            if (!baseApplies(e.osm))
    108146                return false;
  • trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/parser/MapCSSParser.java

    r3971 r4011  
    1515import org.openstreetmap.josm.gui.mappaint.mapcss.Expression.FunctionExpression;
    1616import org.openstreetmap.josm.gui.mappaint.mapcss.Expression.LiteralExpression;
    17 import org.openstreetmap.josm.gui.mappaint.mapcss.Selector.DescendentSelector;
     17import org.openstreetmap.josm.gui.mappaint.mapcss.Selector.ChildOrParentSelector;
    1818import org.openstreetmap.josm.gui.mappaint.mapcss.Selector.GeneralSelector;
    1919import org.openstreetmap.josm.tools.Pair;
     
    275275
    276276  final public Selector child_selector() throws ParseException {
    277     boolean child = false;
     277    boolean parentSelector = false;
    278278    Selector sel1, sel2 = null;
    279279    sel1 = selector();
     
    285285      case GREATER:
    286286        jj_consume_token(GREATER);
    287                       child = true;
     287                      parentSelector = false;
    288288        break;
    289289      case LESS:
    290290        jj_consume_token(LESS);
    291                                                  child = false;
     291                                                           parentSelector = true;
    292292        break;
    293293      default:
     
    304304      ;
    305305    }
    306       {if (true) return sel2 != null ? new DescendentSelector(sel1, sel2, child) : sel1;}
     306      {if (true) return sel2 != null ? new ChildOrParentSelector(sel1, sel2, parentSelector) : sel1;}
    307307    throw new Error("Missing return statement in function");
    308308  }
  • trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/parser/MapCSSParser.jj

    r3971 r4011  
    2020import org.openstreetmap.josm.gui.mappaint.mapcss.Expression.FunctionExpression;
    2121import org.openstreetmap.josm.gui.mappaint.mapcss.Expression.LiteralExpression;
    22 import org.openstreetmap.josm.gui.mappaint.mapcss.Selector.DescendentSelector;
     22import org.openstreetmap.josm.gui.mappaint.mapcss.Selector.ChildOrParentSelector;
    2323import org.openstreetmap.josm.gui.mappaint.mapcss.Selector.GeneralSelector;
    2424import org.openstreetmap.josm.tools.Pair;
     
    251251Selector child_selector() :
    252252{
    253     boolean child = false;
     253    boolean parentSelector = false;
    254254    Selector sel1, sel2 = null;
    255255}
     
    257257    sel1=selector() w()
    258258    (
    259         ( <GREATER> { child = true; } | <LESS> { child = false; } ) w()
     259        ( <GREATER> { parentSelector = false; } | <LESS> { parentSelector = true; } ) w()
    260260        sel2=selector() w()
    261261    )?
    262     { return sel2 != null ? new DescendentSelector(sel1, sel2, child) : sel1; }
     262    { return sel2 != null ? new ChildOrParentSelector(sel1, sel2, parentSelector) : sel1; }
    263263}
    264264
  • trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/parser/MapCSSParserTokenManager.java

    r3967 r4011  
    1313import org.openstreetmap.josm.gui.mappaint.mapcss.Expression.FunctionExpression;
    1414import org.openstreetmap.josm.gui.mappaint.mapcss.Expression.LiteralExpression;
    15 import org.openstreetmap.josm.gui.mappaint.mapcss.Selector.DescendentSelector;
     15import org.openstreetmap.josm.gui.mappaint.mapcss.Selector.ChildOrParentSelector;
    1616import org.openstreetmap.josm.gui.mappaint.mapcss.Selector.GeneralSelector;
    1717import org.openstreetmap.josm.tools.Pair;
Note: See TracChangeset for help on using the changeset viewer.