1 package net.systemeD.halcyon.styleparser {
3 import net.systemeD.halcyon.connection.Entity;
4 import net.systemeD.halcyon.ImageBank;
6 public class StyleChooser {
9 A StyleChooser object is equivalent to one CSS selector+declaration.
11 Its ruleChains property is an array of all the selectors, which would
12 traditionally be comma-separated. For example:
16 Each RuleChain is itself an array of nested selectors. So the above
17 example would roughly be encoded as:
19 ^^ ^^ ^^ ^^ each of these is a Rule
20 ^^^^ ^^^^ ^^^^^^^ each of these is a RuleChain
22 The styles property is an array of all the style objects to be drawn
23 if any of the ruleChains evaluate to true.
27 public var ruleChains:Array; // array of RuleChains (each one an array of Rules)
28 public var styles:Array=[]; // array of ShapeStyle/ShieldStyle/TextStyle/PointStyle
29 public var zoomSpecific:Boolean=false; // are any of the rules zoom-specific?
31 private var rcpos:uint;
32 private var stylepos:uint=0;
34 public function StyleChooser():void {
35 ruleChains=[new RuleChain()];
39 public function get currentChain():RuleChain {
40 return ruleChains[rcpos];
43 // Update the current StyleList from this StyleChooser
45 public function updateStyles(obj:Entity, tags:Object, sl:StyleList, zoom:uint):void {
46 if (zoomSpecific) { sl.validAt=zoom; }
48 // Are any of the ruleChains fulfilled?
50 for each (var c:RuleChain in ruleChains) {
51 if (c.test(-1,obj,tags,zoom)) {
52 sl.addSubpart(c.subpart);
55 for (var i:uint=0; i<styles.length; i++) {
56 var r:Style=styles[i];
58 if (r is ShapeStyle) {
60 if (ShapeStyle(r).width>sl.maxwidth && !r.evals['width']) { sl.maxwidth=ShapeStyle(r).width; }
61 } else if (r is ShieldStyle) {
63 } else if (r is TextStyle) {
65 } else if (r is PointStyle) {
68 if (PointStyle(r).icon_width && !PointStyle(r).evals['icon_width']) {
69 // ** FIXME: we should check this is the bit being used for 'square', 'circle' etc.
70 w=PointStyle(r).icon_width;
71 } else if (PointStyle(r).icon_image && ImageBank.getInstance().hasImage(PointStyle(r).icon_image)) {
72 w=ImageBank.getInstance().getWidth(PointStyle(r).icon_image);
74 if (w>sl.maxwidth) { sl.maxwidth=w; }
75 } else if (r is InstructionStyle) {
76 if (InstructionStyle(r).breaker) { return; }
77 InstructionStyle(r).assignSetTags(tags);
80 if (r.drawn) { tags[':drawn']='yes'; }
81 tags['_width']=sl.maxwidth;
85 // If there's already a style on this sublayer, then merge them
86 // (making a deep copy if necessary to avoid altering the root style)
87 if (!a[c.subpart].merged) { a[c.subpart]=a[c.subpart].deepCopy(); }
88 a[c.subpart].mergeWith(r);
90 // Otherwise, just assign it
98 /** Cut-down version of updateStyles that runs InstructionStyles only - for CSSTransform usage. */
100 public function runInstructions(obj:Entity, tags:Object):Object {
101 for each (var c:RuleChain in ruleChains) {
102 if (c.test(-1,obj,tags,10)) {
103 for (var i:uint=0; i<styles.length; i++) {
104 var r:Style=styles[i];
105 if (r is InstructionStyle) {
106 if (InstructionStyle(r).breaker) { return tags; }
107 InstructionStyle(r).assignSetTags(tags);
117 // ---------------------------------------------------------------------------------------------
118 // Methods to add properties (used by parsers such as MapCSS)
120 // newRuleChain <- starts a new ruleChain in this.ruleChains
121 public function newRuleChain():void {
122 if (ruleChains[rcpos].length>0) {
123 ruleChains[++rcpos]=new RuleChain();
127 public function addStyles(a:Array):void {
128 styles=styles.concat(a);