public var ruleset:RuleSet; // rules
public var wayuis:Object=new Object(); // sprites for ways and (POI/tagged) nodes
public var nodeuis:Object=new Object(); // |
+ public var markeruis:Object=new Object();
public var isBackground:Boolean = true; // is it a background layer or the core paint object?
public var sublayerIndex:Object={}; // hash of index->position
return ((o as Sprite).getChildAt(sublayerIndex[sublayer]) as Sprite);
}
+ /**
+ * Update, and if necessary, create / remove UIs for the given objects.
+ * The object is effectively lists of objects split into inside/outside pairs, e.g.
+ * { waysInside: [], waysOutside: [] } where each is a array of entities either inside
+ * or outside this current view window. UIs for the entities on "inside" lists will be created if necessary.
+ * Flags control redrawing existing entities and removing UIs from entities no longer in view.
+ *
+ * @param o The object containing all the relevant entites.
+ * @param redraw If true, all UIs for entities on "inside" lists will be redrawn
+ * @param remove If true, all UIs for entites on "outside" lists will be removed. The purgable flag on UIs
+ can override this, for example for selected objects.
+ */
public function updateEntityUIs(o:Object, redraw:Boolean, remove:Boolean):void {
- var way:Way, poi:Node;
+ var way:Way, poi:Node, marker:Marker;
for each (way in o.waysInside) {
if (!wayuis[way.id]) { createWayUI(way); }
}
}
}
+
+ for each (marker in o.markersInside) {
+ if (!markeruis[marker.id]) { createMarkerUI(marker); }
+ else if (redraw) { markeruis[marker.id].redraw(); }
+ }
+
+ if (remove) {
+ for each (marker in o.markersOutside) {
+ if (markeruis[marker.id] && !markeruis[marker.id].purgable) {
+ if (redraw) { markeruis[marker.id].redraw(); }
+ } else {
+ deleteMarkerUI(marker);
+ }
+ }
+ }
}
public function createWayUI(way:Way):WayUI {
nodeuis[node.id].removeEventListeners();
delete nodeuis[node.id];
}
+
+ public function createMarkerUI(marker:Marker,rotation:Number=0,layer:int=NO_LAYER,stateClasses:Object=null):MarkerUI {
+ if (!markeruis[marker.id]) {
+ markeruis[marker.id]=new MarkerUI(marker,this,rotation,layer,stateClasses);
+ marker.addEventListener(Connection.NODE_DELETED, markerDeleted);
+ } else {
+ for (var state:String in stateClasses) {
+ markeruis[marker.id].setStateClass(state,stateClasses[state]);
+ }
+ markeruis[marker.id].redraw();
+ }
+ return markeruis[marker.id];
+ }
+
+ public function markerDeleted(event:EntityEvent):void {
+ deleteMarkerUI(event.entity as Marker);
+ }
+
+ public function deleteMarkerUI(marker:Marker):void {
+ if (!markeruis[marker.id]) { return; }
+ marker.removeEventListener(Connection.NODE_DELETED, markerDeleted);
+ markeruis[marker.id].removeSprites();
+ markeruis[marker.id].removeEventListeners();
+ delete markeruis[marker.id];
+ }
public function renumberWayUI(way:Way,oldID:Number):void {
if (!wayuis[oldID]) { return; }
--- /dev/null
+package net.systemeD.halcyon {
+
+ import flash.display.*;
+ import flash.events.*;
+ import flash.text.AntiAliasType;
+ import flash.text.GridFitType;
+ import flash.text.TextField;
+ import flash.text.TextFormat;
+ import flash.geom.Matrix;
+ import flash.geom.Point;
+ import net.systemeD.halcyon.styleparser.*;
+ import net.systemeD.halcyon.connection.*;
+ import net.systemeD.halcyon.Globals;
+
+ public class MarkerUI extends EntityUI {
+
+ public var loaded:Boolean=false;
+ private var iconnames:Object={}; // name of icon on each sublayer
+ private var heading:Number=0; // heading within way
+ private var rotation:Number=0; // rotation applied to this POI
+ private static const NO_LAYER:int=-99999;
+
+ public function MarkerUI(marker:Marker, paint:MapPaint, heading:Number=0, layer:int=NO_LAYER, stateClasses:Object=null) {
+ super(marker,paint);
+ if (layer==NO_LAYER) { this.layer=paint.maxlayer; } else { this.layer=layer; }
+ this.heading = heading;
+ if (stateClasses) {
+ for (var state:String in stateClasses) {
+ if (stateClasses[state]) { this.stateClasses[state]=stateClasses[state]; }
+ }
+ }
+ entity.addEventListener(Connection.NODE_MOVED, markerMoved);
+ entity.addEventListener(Connection.NODE_ALTERED, markerAltered);
+ attachRelationListeners();
+ redraw();
+ }
+
+ public function removeEventListeners():void {
+ removeGenericEventListeners();
+ entity.removeEventListener(Connection.NODE_MOVED, markerMoved);
+ entity.removeEventListener(Connection.NODE_ALTERED, markerAltered);
+ }
+
+ public function markerMoved(event:Event):void {
+ updatePosition();
+ }
+
+ private function markerAltered(event:Event):void {
+ redraw();
+ }
+
+ override public function doRedraw():Boolean {
+ if (!paint.ready) { return false; }
+ if (entity.deleted) { return false; }
+
+ var tags:Object = entity.getTagsCopy();
+ setStateClass('poi', !entity.hasParentWays);
+ setStateClass('hasTags', entity.hasInterestingTags());
+ tags=applyStateClasses(tags);
+ if (!styleList || !styleList.isValidAt(paint.map.scale)) {
+ styleList=paint.ruleset.getStyles(entity,tags,paint.map.scale);
+ }
+
+ var suggestedLayer:Number=styleList.layerOverride();
+ if (!isNaN(suggestedLayer)) { layer=suggestedLayer; }
+
+ var inWay:Boolean=entity.hasParentWays;
+ var hasStyles:Boolean=styleList.hasStyles();
+
+ removeSprites(); iconnames={};
+ return renderFromStyle(tags);
+ }
+
+ private function renderFromStyle(tags:Object):Boolean {
+ var r:Boolean=false; // ** rendered
+ var maxwidth:Number=4; // biggest width
+ var w:Number;
+ var icon:Sprite;
+ interactive=false;
+ for each (var sublayer:Number in styleList.sublayers) {
+
+ if (styleList.pointStyles[sublayer]) {
+ var s:PointStyle=styleList.pointStyles[sublayer];
+ interactive||=s.interactive;
+ r=true;
+ if (s.rotation) { rotation=s.rotation; }
+ if (s.icon_image!=iconnames[sublayer]) {
+ if (s.icon_image=='square') {
+ // draw square
+ icon=new Sprite();
+ addToLayer(icon,STROKESPRITE,sublayer);
+ w=styleIcon(icon,sublayer);
+ icon.graphics.drawRect(0,0,w,w);
+ if (s.interactive) { maxwidth=Math.max(w,maxwidth); }
+ iconnames[sublayer]='_square';
+
+ } else if (s.icon_image=='circle') {
+ // draw circle
+ icon=new Sprite();
+ addToLayer(icon,STROKESPRITE,sublayer);
+ w=styleIcon(icon,sublayer);
+ icon.graphics.drawCircle(w,w,w);
+ if (s.interactive) { maxwidth=Math.max(w,maxwidth); }
+ iconnames[sublayer]='_circle';
+
+ } else if (paint.ruleset.images[s.icon_image]) {
+ // 'load' icon (actually just from library)
+ var loader:ExtendedLoader = new ExtendedLoader();
+ loader.info['sublayer']=sublayer;
+ loader.contentLoaderInfo.addEventListener(Event.COMPLETE, loadedIcon);
+ loader.loadBytes(paint.ruleset.images[s.icon_image]);
+ iconnames[sublayer]=s.icon_image;
+ }
+ }
+ }
+
+ // name sprite
+ var a:String='', t:TextStyle;
+ if (styleList.textStyles[sublayer]) {
+ t=styleList.textStyles[sublayer];
+ interactive||=t.interactive;
+ a=tags[t.text];
+ }
+
+ if (a) {
+ var name:Sprite=new Sprite();
+ addToLayer(name,NAMESPRITE);
+ t.writeNameLabel(name,a,0,0);
+ loaded=true;
+ }
+ }
+ if (!r) { return false; }
+ if (interactive) { addHitSprite(maxwidth); }
+ updatePosition();
+ return true;
+ }
+
+
+ private function styleIcon(icon:Sprite, sublayer:Number):Number {
+ loaded=true;
+
+ // get colours
+ if (styleList.shapeStyles[sublayer]) {
+ var s:ShapeStyle=styleList.shapeStyles[sublayer];
+ if (!isNaN(s.color)) { icon.graphics.beginFill(s.color);
+ }
+ if (s.casing_width || !isNaN(s.casing_color)) {
+ icon.graphics.lineStyle(s.casing_width ? s.casing_width : 1,
+ s.casing_color ? s.casing_color : 0,
+ s.casing_opacity ? s.casing_opacity : 1);
+ }
+ }
+
+ // return width
+ return styleList.pointStyles[sublayer].icon_width;
+ }
+
+ private function addHitSprite(w:uint):void {
+ hitzone = new Sprite();
+ hitzone.graphics.lineStyle(4, 0x000000, 1, false, "normal", CapsStyle.ROUND, JointStyle.ROUND);
+ hitzone.graphics.beginFill(0);
+ hitzone.graphics.drawRect(0,0,w,w);
+ hitzone.visible = false;
+ setListenSprite();
+ }
+
+ private function loadedIcon(event:Event):void {
+ var icon:Sprite=new Sprite();
+ var sublayer:Number=event.target.loader.info['sublayer'];
+ addToLayer(icon,STROKESPRITE,sublayer);
+ icon.addChild(Bitmap(event.target.content));
+ addHitSprite(icon.width);
+ loaded=true;
+ updatePosition();
+ }
+
+ private function updatePosition():void {
+ if (!loaded) { return; }
+
+ for (var i:uint=0; i<sprites.length; i++) {
+ var d:DisplayObject=sprites[i];
+ d.x=0; d.y=0; d.rotation=0;
+
+ var m:Matrix=new Matrix();
+ m.translate(-d.width/2,-d.height/2);
+ m.rotate(rotation);
+ m.translate(paint.map.lon2coord(Marker(entity).lon),paint.map.latp2coord(Marker(entity).latp));
+ d.transform.matrix=m;
+ }
+ }
+ }
+}