import flash.net.*;
import net.systemeD.halcyon.ExtendedLoader;
import net.systemeD.halcyon.ExtendedURLLoader;
+ import net.systemeD.halcyon.DebugURLRequest;
import net.systemeD.halcyon.connection.Entity;
import net.systemeD.halcyon.connection.*;
import net.systemeD.halcyon.Globals;
// import bustin.dev.Inspector;
+ /** A set of rules for rendering a map, as retrieved from a MapCSS file. */
public class RuleSet {
- public var loaded:Boolean=false; // has it loaded yet?
- public var images:Object=new Object(); // loaded images
- public var imageWidths:Object=new Object(); // width of each bitmap image
+ /** Has it loaded yet? */
+ public var loaded:Boolean=false;
+ /** Loaded images */
+ public var images:Object=new Object();
+ /** Width of each bitmap image. */
+ public var imageWidths:Object=new Object();
private var redrawCallback:Function=null; // function to call when CSS loaded
private var iconCallback:Function=null; // function to call when all icons loaded
private var iconsToLoad:uint=0; // number of icons left to load (fire iconCallback when ==0)
private static const UNDERLINE:RegExp=/^underline$/i;
private static const CAPS:RegExp=/^uppercase$/i;
private static const CENTER:RegExp=/^center$/i;
+ private static const FALSE:RegExp=/^(no|false|0)$/i;
private static const HEX:RegExp=/^#([0-9a-f]+)$/i;
private static const CSSCOLORS:Object = {
yellow:0xffff00,
yellowgreen:0x9acd32 };
+ /** Constructor */
public function RuleSet(mins:uint,maxs:uint,redrawCall:Function=null,iconLoadedCallback:Function=null):void {
minscale = mins;
maxscale = maxs;
iconCallback = iconLoadedCallback;
}
- // Get styles for an object
+ /** Get styles for an object*/
- public function getStyles(obj:Entity,tags:Object):StyleList {
+ public function getStyles(obj:Entity, tags:Object, zoom:uint):StyleList {
var sl:StyleList=new StyleList();
for each (var sc:StyleChooser in choosers) {
- sc.updateStyles(obj,tags,sl,imageWidths);
+ sc.updateStyles(obj,tags,sl,imageWidths,zoom);
}
return sl;
}
// ---------------------------------------------------------------------------------------------------------
// Loading stylesheet
+ /** Load ruleset the MapCSS file referenced in <code>str</code>.*/
public function loadFromCSS(str:String):void {
if (str.match(/[\s\n\r\t]/)!=null) { parseCSS(str); loaded=true; redrawCallback(); return; }
- var request:URLRequest=new URLRequest(str);
- var loader:URLLoader=new URLLoader();
-
- request.method=URLRequestMethod.GET;
- loader.dataFormat = URLLoaderDataFormat.TEXT;
- loader.addEventListener(Event.COMPLETE, doParseCSS);
- loader.addEventListener(HTTPStatusEvent.HTTP_STATUS, httpStatusHandler);
- loader.addEventListener(SecurityErrorEvent.SECURITY_ERROR, securityErrorHandler);
- loader.addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler);
- loader.load(request);
+ var cssLoader:NestedCSSLoader=new NestedCSSLoader();
+ cssLoader.addEventListener(Event.COMPLETE, doParseCSS);
+ cssLoader.load(str);
}
private function doParseCSS(e:Event):void {
- parseCSS(e.target.data);
+ parseCSS(e.target.css);
}
private function parseCSS(str:String):void {
// ------------------------------------------------------------------------------------------------
- // Load all referenced images
+ /** Load all referenced images*/
// ** will duplicate if referenced twice, shouldn't
public function loadImages():void {
if (filename=='square' || filename=='circle') { continue; }
iconsToLoad++;
- var request:URLRequest=new URLRequest(filename);
+ var request:DebugURLRequest=new DebugURLRequest(filename);
var loader:ExtendedURLLoader=new ExtendedURLLoader();
loader.dataFormat=URLLoaderDataFormat.BINARY;
loader.info['filename']=filename;
loader.addEventListener(Event.COMPLETE, loadedImage, false, 0, true);
loader.addEventListener(HTTPStatusEvent.HTTP_STATUS, httpStatusHandler, false, 0, true);
- loader.addEventListener(SecurityErrorEvent.SECURITY_ERROR, securityErrorHandler, false, 0, true);
- loader.addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler, false, 0, true);
- loader.load(request);
+ loader.addEventListener(SecurityErrorEvent.SECURITY_ERROR, onImageLoadSecurityError, false, 0, true);
+ loader.addEventListener(IOErrorEvent.IO_ERROR, onImageLoadioError, false, 0, true);
+ loader.load(request.request);
}
}
}
imageWidths[fn]=event.target.width;
// ** do we need to explicitly remove the loader object now?
- iconsToLoad--;
- if (iconsToLoad==0 && iconCallback!=null) { iconCallback(); }
+ oneLessImageToLoad();
}
+ private function oneLessImageToLoad():void {
+ iconsToLoad--;
+ if (iconsToLoad<=0 && iconCallback!=null) { iconCallback(); }
+ }
+
+ private function onImageLoadioError ( event:IOErrorEvent ):void {
+ trace("ioerrorevent: "+event.target.info['filename']);
+ oneLessImageToLoad();
+ }
+
+ private function onImageLoadSecurityError ( event:SecurityErrorEvent ):void {
+ trace("securityerrorevent: "+event.target.info['filename']);
+ oneLessImageToLoad();
+ }
+
private function httpStatusHandler( event:HTTPStatusEvent ):void { }
private function securityErrorHandler( event:SecurityErrorEvent ):void { Globals.vars.root.addDebug("securityerrorevent"); }
private function ioErrorHandler( event:IOErrorEvent ):void { Globals.vars.root.addDebug("ioerrorevent"); }
// ------------------------------------------------------------------------------------------------
// Parse CSS
+ /** Parse the given MapCSS file by repeatedly throwing regular expressions at it. */
public function parse(css:String):void {
var previous:uint=0; // what was the previous CSS word?
var sc:StyleChooser=new StyleChooser(); // currently being assembled
private function saveEval(expr:String):Eval {
evalsToLoad++;
var e:Eval=new Eval(expr);
- e.addEventListener("swf_loaded",evalLoaded);
+ e.addEventListener("swf_loaded",evalLoaded, false, 0, true);
evals.push(e);
return e;
}
if (t['z_index']) { sub=Number(t['z_index']); delete t['z_index']; }
ss.sublayer=ps.sublayer=ts.sublayer=hs.sublayer=sub;
xs.sublayer=10;
+
+ // Find "interactive" property - it's true unless explicitly set false.
+ var inter:Boolean=true;
+ if (t['interactive']) { inter=t['interactive'].match(FALSE) ? false : true; delete t['interactive']; }
+ ss.interactive=ps.interactive=ts.interactive=hs.interactive=xs.interactive=inter;
// Munge special values
if (t['font_weight'] ) { t['font_bold' ] = t['font_weight' ].match(BOLD ) ? true : false; delete t['font_weight']; }
// Assign each property to the appropriate style
for (a in t) {
// Parse properties
- // ** also do units, e.g. px/pt
+ // ** also do units, e.g. px/pt/m
if (a.match(COLOR)) { v = parseCSSColor(t[a]); }
else { v = t[a]; }
return null;
}
+ /** Convert a color string given as either descriptive ("blue"), short hex ("#abc") or long hex ("#a0b0c0"), to an integer.
+ * @default 0*/
public static function parseCSSColor(colorStr:String):uint {
colorStr = colorStr.toLowerCase();
if (CSSCOLORS[colorStr]) {
return CSSCOLORS[colorStr];
} else {
var match:Object = HEX.exec(colorStr);
- if ( match ) { return Number("0x"+match[1]); }
+ if ( match ) {
+ if ( match[1].length == 3) {
+ // repeat digits. #abc => 0xaabbcc
+ return Number("0x"+match[1].charAt(0)+match[1].charAt(0)+
+ match[1].charAt(1)+match[1].charAt(1)+
+ match[1].charAt(2)+match[1].charAt(2));
+ } else if ( match[1].length == 6) {
+ return Number("0x"+match[1]);
+ } else {
+ return Number("0x000000"); //as good as any
+ }
+ }
}
return 0;
}