New RuleChain object to replace previous nested array within StyleChooser
authorRichard Fairhurst <richard@systemeD.net>
Sun, 12 Jun 2011 13:42:04 +0000 (14:42 +0100)
committerRichard Fairhurst <richard@systemeD.net>
Sun, 12 Jun 2011 13:42:04 +0000 (14:42 +0100)
net/systemeD/halcyon/styleparser/RuleChain.as [new file with mode: 0644]
net/systemeD/halcyon/styleparser/RuleSet.as
net/systemeD/halcyon/styleparser/StyleChooser.as

diff --git a/net/systemeD/halcyon/styleparser/RuleChain.as b/net/systemeD/halcyon/styleparser/RuleChain.as
new file mode 100644 (file)
index 0000000..cd6c5b4
--- /dev/null
@@ -0,0 +1,65 @@
+package net.systemeD.halcyon.styleparser {
+
+    import net.systemeD.halcyon.connection.*;
+
+       /**     A descendant list of MapCSS selectors (Rules).
+       
+               For example,
+                       relation[type=route] way[highway=primary]
+                       ^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^
+                           first Rule           second Rule
+                              |------------|---------|
+                                           |
+                                    one RuleChain
+
+       */
+
+       public class RuleChain {
+               public var rules:Array=[];              // should eventually become a Vector of Rules
+               public var subpart:String='';   // subpart name, as in way[highway=primary]::centreline
+
+               // Test a ruleChain
+               // - run a set of tests in the chain
+               //              works backwards from at position "pos" in array, or -1  for the last
+               //              separate tags object is required in case they've been dynamically retagged
+               // - if they fail, return false
+               // - if they succeed, and it's the last in the chain, return happily
+               // - if they succeed, and there's more in the chain, rerun this for each parent until success
+               
+               public function test(pos:int, obj:Entity, tags:Object, zoom:uint):Boolean {
+                       if (pos==-1) { pos=rules.length-1; }
+
+                       var r:Rule=rules[pos];
+                       if (!r.test(obj, tags, zoom)) { return false; }
+                       if (pos==0) { return true; }
+                       
+                       var o:Array=obj.parentObjects;
+                       for each (var p:Entity in o) {
+                               if (test(pos-1, p, p.getTagsHash(), zoom)) { return true; }
+                       }
+                       return false;
+               }
+               
+               public function get length():int {
+                       return rules.length;
+               }
+               
+               // ---------------------------------------------------------------------------------------------
+               // Methods to add properties (used by parsers such as MapCSS)
+
+               public function addRule(e:String=''):void {
+                       rules.push(new Rule(e));
+               }
+
+               public function addConditionToLast(c:Condition):void {
+                       rules[rules.length-1].conditions.push(c);
+               }
+
+               public function addZoomToLast(z1:uint,z2:uint):void {
+                       rules[rules.length-1].minZoom=z1;
+                       rules[rules.length-1].maxZoom=z2;
+               }
+
+
+       }
+}
index 33c20b9..0bf9923 100644 (file)
@@ -43,6 +43,7 @@ package net.systemeD.halcyon.styleparser {
                private static const CONDITION:RegExp   =/^ \[(.+?)\] \s* /sx;
                private static const OBJECT:RegExp              =/^ (\w+) \s* /sx;
                private static const DECLARATION:RegExp =/^ \{(.+?)\} \s* /sx;
+               private static const SUBPART:RegExp             =/^ ::(\S+) \s* /sx;
                private static const UNKNOWN:RegExp             =/^ (\S+) \s* /sx;
 
                private static const ZOOM_MINMAX:RegExp =/^ (\d+)\-(\d+) $/sx;
@@ -366,7 +367,7 @@ package net.systemeD.halcyon.styleparser {
                                        if (previous==oDECLARATION) { saveChooser(sc); sc=new StyleChooser(); }
 
                                        css=css.replace(CLASS,'');
-                                       sc.addCondition(new Condition('set',o[1]));
+                                       sc.currentChain.addConditionToLast(new Condition('set',o[1]));
                                        previous=oCONDITION;
 
                                // Not class - !.motorway, !.builtup, !:hover
@@ -374,30 +375,31 @@ package net.systemeD.halcyon.styleparser {
                                        if (previous==oDECLARATION) { saveChooser(sc); sc=new StyleChooser(); }
 
                                        css=css.replace(NOT_CLASS,'');
-                                       sc.addCondition(new Condition('unset',o[1]));
+                                       sc.currentChain.addConditionToLast(new Condition('unset',o[1]));
                                        previous=oCONDITION;
 
                                // Zoom
                                } else if ((o=ZOOM.exec(css))) {
-                                       if (previous!=oOBJECT && previous!=oCONDITION) { sc.newObject(); }
+                                       if (previous!=oOBJECT && previous!=oCONDITION) { sc.currentChain.addRule(); }
 
                                        css=css.replace(ZOOM,'');
                                        var z:Array=parseZoom(o[1]);
-                                       sc.addZoom(z[0],z[1]);
+                                       sc.currentChain.addZoomToLast(z[0],z[1]);
+                                       sc.zoomSpecific=true;
                                        previous=oZOOM;
 
                                // Grouping - just a comma
                                } else if ((o=GROUP.exec(css))) {
                                        css=css.replace(GROUP,'');
-                                       sc.newGroup();
+                                       sc.newRuleChain();
                                        previous=oGROUP;
 
                                // Condition - [highway=primary]
                                } else if ((o=CONDITION.exec(css))) {
                                        if (previous==oDECLARATION) { saveChooser(sc); sc=new StyleChooser(); }
-                                       if (previous!=oOBJECT && previous!=oZOOM && previous!=oCONDITION) { sc.newObject(); }
+                                       if (previous!=oOBJECT && previous!=oZOOM && previous!=oCONDITION) { sc.currentChain.addRule(); }
                                        css=css.replace(CONDITION,'');
-                                       sc.addCondition(parseCondition(o[1]) as Condition);
+                                       sc.currentChain.addConditionToLast(parseCondition(o[1]) as Condition);
                                        previous=oCONDITION;
 
                                // Object - way, node, relation
@@ -405,7 +407,7 @@ package net.systemeD.halcyon.styleparser {
                                        if (previous==oDECLARATION) { saveChooser(sc); sc=new StyleChooser(); }
 
                                        css=css.replace(OBJECT,'');
-                                       sc.newObject(o[1]);
+                                       sc.currentChain.addRule(o[1]);
                                        previous=oOBJECT;
 
                                // Declaration - {...}
index 05b71b8..1a3f86f 100644 (file)
@@ -10,25 +10,35 @@ package net.systemeD.halcyon.styleparser {
                        Its ruleChains property is an array of all the selectors, which would
                        traditionally be comma-separated. For example:
                                h1, h2, h3 em
-                       is three ruleChains.
+                       is three RuleChains.
                        
-                       Each ruleChain is itself an array of nested selectors. So the above 
+                       Each RuleChain is itself an array of nested selectors. So the above 
                        example would roughly be encoded as:
                                [[h1],[h2],[h3,em]]
                                  ^^   ^^   ^^ ^^   each of these is a Rule
-
+                                ^^^^ ^^^^ ^^^^^^^  each of these is a RuleChain
+                               
                        The styles property is an array of all the style objects to be drawn
                        if any of the ruleChains evaluate to true.
 
                */
 
-               public var ruleChains:Array=[[]];                       // array of array of Rules
+               public var ruleChains:Array;                            // array of RuleChains (each one an array of Rules)
                public var styles:Array=[];                                     // array of ShapeStyle/ShieldStyle/TextStyle/PointStyle
                public var zoomSpecific:Boolean=false;          // are any of the rules zoom-specific?
 
-               private var rcpos:uint=0;
+               private var rcpos:uint;
                private var stylepos:uint=0;
 
+               public function StyleChooser():void {
+                       ruleChains=[new RuleChain()];
+                       rcpos=0;
+               }
+
+               public function get currentChain():RuleChain {
+                       return ruleChains[rcpos];
+               }
+
                // Update the current StyleList from this StyleChooser
 
                public function updateStyles(obj:Entity, tags:Object, sl:StyleList, imageWidths:Object, zoom:uint):void {
@@ -37,8 +47,8 @@ package net.systemeD.halcyon.styleparser {
                        // Are any of the ruleChains fulfilled?
                        var w:Number;
                        var fulfilled:Boolean=false;
-                       for each (var c:Array in ruleChains) {
-                               if (testChain(c,-1,obj,tags,zoom)) {
+                       for each (var c:RuleChain in ruleChains) {
+                               if (c.test(-1,obj,tags,zoom)) {
                                        fulfilled=true; break;
                                }
                        }
@@ -86,58 +96,18 @@ package net.systemeD.halcyon.styleparser {
                                }
                        }
                }
-
-
-               // Test a ruleChain
-               // - run a set of tests in the chain
-               //              works backwards from at position "pos" in array, or -1  for the last
-               //              separate tags object is required in case they've been dynamically retagged
-               // - if they fail, return false
-               // - if they succeed, and it's the last in the chain, return happily
-               // - if they succeed, and there's more in the chain, rerun this for each parent until success
-               
-               private function testChain(chain:Array,pos:int,obj:Entity,tags:Object,zoom:uint):Boolean {
-                       if (pos==-1) { pos=chain.length-1; }
-
-                       var r:Rule=chain[pos];
-                       if (!r.test(obj, tags, zoom)) { return false; }
-                       if (pos==0) { return true; }
-                       
-                       var o:Array=obj.parentObjects;
-                       for each (var p:Entity in o) {
-                               if (testChain(chain, pos-1, p, p.getTagsHash(), zoom )) { return true; }
-                       }
-                       return false;
-               }
                
                
                // ---------------------------------------------------------------------------------------------
                // Methods to add properties (used by parsers such as MapCSS)
                
-               // newGroup             <- starts a new ruleChain in this.ruleChains
-               public function newGroup():void {
+               // newRuleChain         <- starts a new ruleChain in this.ruleChains
+               public function newRuleChain():void {
                        if (ruleChains[rcpos].length>0) {
-                               ruleChains[++rcpos]=[];
+                               ruleChains[++rcpos]=new RuleChain();
                        }
                }
 
-               // newObject    <- adds into the current ruleChain (starting a new Rule)
-               public function newObject(e:String=''):void {
-                       ruleChains[rcpos].push(new Rule(e));
-               }
-
-               // addZoom              <- adds into the current ruleChain (existing Rule)
-               public function addZoom(z1:uint,z2:uint):void {
-                       ruleChains[rcpos][ruleChains[rcpos].length-1].minZoom=z1;
-                       ruleChains[rcpos][ruleChains[rcpos].length-1].maxZoom=z2;
-                       zoomSpecific=true;
-               }
-               
-               // addCondition <- adds into the current ruleChain (existing Rule)
-               public function addCondition(c:Condition):void {
-                       ruleChains[rcpos][ruleChains[rcpos].length-1].conditions.push(c);
-               }
-
                // addStyles    <- adds to this.styles
                public function addStyles(a:Array):void {
                        styles=styles.concat(a);