New RuleChain object to replace previous nested array within StyleChooser
[potlatch2.git] / net / systemeD / halcyon / styleparser / StyleChooser.as
1 package net.systemeD.halcyon.styleparser {
2
3         import net.systemeD.halcyon.connection.Entity;
4
5         public class StyleChooser {
6
7                 /*
8                         A StyleChooser object is equivalent to one CSS selector+declaration.
9
10                         Its ruleChains property is an array of all the selectors, which would
11                         traditionally be comma-separated. For example:
12                                 h1, h2, h3 em
13                         is three RuleChains.
14                         
15                         Each RuleChain is itself an array of nested selectors. So the above 
16                         example would roughly be encoded as:
17                                 [[h1],[h2],[h3,em]]
18                                   ^^   ^^   ^^ ^^   each of these is a Rule
19                                  ^^^^ ^^^^ ^^^^^^^  each of these is a RuleChain
20                                 
21                         The styles property is an array of all the style objects to be drawn
22                         if any of the ruleChains evaluate to true.
23
24                 */
25
26                 public var ruleChains:Array;                            // array of RuleChains (each one an array of Rules)
27                 public var styles:Array=[];                                     // array of ShapeStyle/ShieldStyle/TextStyle/PointStyle
28                 public var zoomSpecific:Boolean=false;          // are any of the rules zoom-specific?
29
30                 private var rcpos:uint;
31                 private var stylepos:uint=0;
32
33                 public function StyleChooser():void {
34                         ruleChains=[new RuleChain()];
35                         rcpos=0;
36                 }
37
38                 public function get currentChain():RuleChain {
39                         return ruleChains[rcpos];
40                 }
41
42                 // Update the current StyleList from this StyleChooser
43
44                 public function updateStyles(obj:Entity, tags:Object, sl:StyleList, imageWidths:Object, zoom:uint):void {
45                         if (zoomSpecific) { sl.validAt=zoom; }
46
47                         // Are any of the ruleChains fulfilled?
48                         var w:Number;
49                         var fulfilled:Boolean=false;
50                         for each (var c:RuleChain in ruleChains) {
51                                 if (c.test(-1,obj,tags,zoom)) {
52                                         fulfilled=true; break;
53                                 }
54                         }
55                         if (!fulfilled) { return; }
56
57                         // Update StyleList
58                         for each (var r:Style in styles) {
59                                 var a:*;
60                                 if (r is ShapeStyle) {
61                                         a=sl.shapeStyles;
62                                         if (ShapeStyle(r).width>sl.maxwidth && !r.evals['width']) { sl.maxwidth=ShapeStyle(r).width; }
63                                 } else if (r is ShieldStyle) {
64                                         a=sl.shieldStyles;
65                                 } else if (r is TextStyle) { 
66                                         a=sl.textStyles;
67                                 } else if (r is PointStyle) { 
68                                         a=sl.pointStyles;
69                                         w=0;
70                                         if (PointStyle(r).icon_width && !PointStyle(r).evals['icon_width']) {
71                                                 w=PointStyle(r).icon_width;
72                                         } else if (PointStyle(r).icon_image && imageWidths[PointStyle(r).icon_image]) {
73                                                 w=imageWidths[PointStyle(r).icon_image];
74                                         }
75                                         if (w>sl.maxwidth) { sl.maxwidth=w; }
76                                 } else if (r is InstructionStyle) {
77                                         if (InstructionStyle(r).breaker) { return; }
78                                         if (InstructionStyle(r).set_tags) {
79                                                 for (var k:String in InstructionStyle(r).set_tags) { tags[k]=InstructionStyle(r).set_tags[k]; }
80                                         }
81                                         continue;
82                                 }
83                                 if (r.drawn) { tags[':drawn']='yes'; }
84                                 tags['_width']=sl.maxwidth;
85                                 
86                                 r.runEvals(tags);
87                                 sl.addSublayer(r.sublayer);
88                                 if (a[r.sublayer]) {
89                                         // If there's already a style on this sublayer, then merge them
90                                         // (making a deep copy if necessary to avoid altering the root style)
91                                         if (!a[r.sublayer].merged) { a[r.sublayer]=a[r.sublayer].deepCopy(); }
92                                         a[r.sublayer].mergeWith(r);
93                                 } else {
94                                         // Otherwise, just assign it
95                                         a[r.sublayer]=r;
96                                 }
97                         }
98                 }
99                 
100                 
101                 // ---------------------------------------------------------------------------------------------
102                 // Methods to add properties (used by parsers such as MapCSS)
103                 
104                 // newRuleChain         <- starts a new ruleChain in this.ruleChains
105                 public function newRuleChain():void {
106                         if (ruleChains[rcpos].length>0) {
107                                 ruleChains[++rcpos]=new RuleChain();
108                         }
109                 }
110
111                 // addStyles    <- adds to this.styles
112                 public function addStyles(a:Array):void {
113                         styles=styles.concat(a);
114                 }
115                 
116         }
117 }