== Core geometry ==
+* P1-style J (join) / shift-J (unjoin)
* Make parallelise properly undoable
* Make Quadralatalawhatsit properly undoable
* Splitway + undo leaves way marked dirty
== Rendering (Halcyon) ==
-** { interactive: no; } - stop items being clicked on (and their maxwidth being taken into account)
* halcyon_viewer needs updating for new tileurl stuff
* Shields
* More line decoration (cliffs etc.), and implied values for 'dashes' if not supplied
protected var listenSprite:Sprite=new Sprite(); // clickable sprite to receive events
protected var stateClasses:Object=new Object(); // special context-sensitive classes, e.g. :hover
protected var layer:int=0; // map layer
- protected var interactive:Boolean=true; // does it respond to connection events?
protected var suspended:Boolean=false; // suspend redrawing?
protected var redrawDue:Boolean=false; // redraw called while suspended?
protected var redrawStyleList:StyleList; // stylelist to be used when redrawing?
public var paint:MapPaint; // reference to parent MapPaint
public var ruleset:RuleSet; // reference to ruleset in operation
+ public var interactive:Boolean=true; // does object respond to clicks?
protected const FILLSPRITE:uint=0;
protected const CASINGSPRITE:uint=1;
protected const STROKESPRITE:uint=2;
protected const NAMESPRITE:uint=3;
- protected const NODESPRITE:uint=4;
- protected const CLICKSPRITE:uint=5;
+ protected const WAYCLICKSPRITE:uint=4;
+ protected const NODECLICKSPRITE:uint=5;
public static const DEFAULT_TEXTFIELD_PARAMS:Object = {
embedFonts: true,
gridFitType: GridFitType.NONE
};
- public function EntityUI(entity:Entity, paint:MapPaint, interactive:Boolean) {
+ public function EntityUI(entity:Entity, paint:MapPaint) {
this.entity=entity;
this.paint=paint;
- this.interactive=interactive;
entity.addEventListener(Connection.TAG_CHANGED, tagChanged);
entity.addEventListener(Connection.ADDED_TO_RELATION, relationAdded);
entity.addEventListener(Connection.REMOVED_FROM_RELATION, relationRemoved);
}
}
- protected function setListenSprite(hitzone:Sprite):void {
- if (!listenSprite.parent) { addToLayer(listenSprite, CLICKSPRITE); }
- listenSprite.hitArea = hitzone;
- listenSprite.buttonMode = true;
- listenSprite.mouseChildren = true;
- listenSprite.mouseEnabled = true;
+ protected function setListenSprite(spriteContainer:uint, hitzone:Sprite):void {
+ if (hitzone) {
+ if (!listenSprite.parent) { addToLayer(listenSprite, spriteContainer); }
+ listenSprite.hitArea = hitzone;
+ listenSprite.buttonMode = true;
+ listenSprite.mouseChildren = true;
+ listenSprite.mouseEnabled = true;
+ } else {
+ if (listenSprite.parent) { listenSprite.parent.removeChild(listenSprite); }
+ }
}
public function setHighlight(stateType:String, isOn:*):void {
t.addChild(getPaintSprite()); // | | sublayer
s.addChild(t); // | |
s.addChild(getPaintSprite()); // | 3 names
- s.addChild(getPaintSprite()); // | 4 nodes
- s.addChild(getHitSprite()); // | 5 entity hit tests
+ s.addChild(getHitSprite()); // | 4 way hit tests
+ s.addChild(getHitSprite()); // | 5 node hit tests
addChild(s); // |
}
addChild(getPaintSprite()); // name sprite
}
public function createWayUI(way:Way):WayUI {
- if (!wayuis[way.id]) { wayuis[way.id]=new WayUI(way,this,false); }
+ if (!wayuis[way.id]) { wayuis[way.id]=new WayUI(way,this); }
return wayuis[way.id];
}
public function createNodeUI(node:Node):NodeUI {
- if (!nodeuis[node.id]) { nodeuis[node.id]=new NodeUI(node,this,0,false); }
+ if (!nodeuis[node.id]) { nodeuis[node.id]=new NodeUI(node,this,0); }
return nodeuis[node.id];
}
private var iconname:String=''; // name of icon
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 NodeUI(node:Node, paint:MapPaint, heading:Number=0, interactive:Boolean=true, sl:StyleList=null) {
- super(node,paint,interactive);
+ public function NodeUI(node:Node, paint:MapPaint, heading:Number=0, layer:int=NO_LAYER, sl:StyleList=null) {
+ super(node,paint);
+ if (layer==NO_LAYER) { this.layer=paint.maxlayer; } else { this.layer=layer; }
this.heading = heading;
entity.addEventListener(Connection.TAG_CHANGED, tagChanged);
entity.addEventListener(Connection.NODE_MOVED, nodeMoved);
}
private function renderFromStyle(sl:StyleList,tags:Object):Boolean {
- var r:Boolean=false; // ** rendered
+ var r:Boolean=false; // ** rendered
+ var maxwidth:Number=4; // biggest width
var w:Number;
var icon:Sprite;
- layer=paint.maxlayer;
+ interactive=false;
for each (var sublayer:Number in sl.sublayers) {
if (sl.pointStyles[sublayer]) {
var s:PointStyle=sl.pointStyles[sublayer];
+ interactive||=s.interactive;
r=true;
if (s.rotation) { rotation=s.rotation; }
addToLayer(icon,STROKESPRITE,sublayer);
w=styleIcon(icon,sl,sublayer);
icon.graphics.drawRect(0,0,w,w);
- addHitSprite(w);
- updatePosition();
+ if (s.interactive) { maxwidth=Math.max(w,maxwidth); }
iconname='_square';
} else if (s.icon_image=='circle') {
addToLayer(icon,STROKESPRITE,sublayer);
w=styleIcon(icon,sl,sublayer);
icon.graphics.drawCircle(w,w,w);
- addHitSprite(w);
- updatePosition();
+ if (s.interactive) { maxwidth=Math.max(w,maxwidth); }
iconname='_circle';
} else if (paint.ruleset.images[s.icon_image]) {
loader.loadBytes(paint.ruleset.images[s.icon_image]);
iconname=s.icon_image;
}
- } else {
- // already loaded, so just reposition
- updatePosition();
}
}
var a:String='', t:TextStyle;
if (sl.textStyles[sublayer]) {
t=sl.textStyles[sublayer];
+ interactive||=t.interactive;
a=tags[t.text];
}
t.writeNameLabel(name,a,0,0);
}
}
- return r;
+ if (!r) { return false; }
+ if (interactive) { addHitSprite(maxwidth); }
+ updatePosition();
+ return true;
}
// get colours
if (sl.shapeStyles[sublayer]) {
var s:ShapeStyle=sl.shapeStyles[sublayer];
- if (s.color) { icon.graphics.beginFill(s.color); }
+ if (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,
}
// return width
- return sl.pointStyles[sublayer].icon_width ? sl.pointStyles[sublayer].icon_width : 4;
+ return sl.pointStyles[sublayer].icon_width;
}
private function addHitSprite(w:uint):void {
hitzone.graphics.lineStyle(4, 0x000000, 1, false, "normal", CapsStyle.ROUND, JointStyle.ROUND);
hitzone.graphics.beginFill(0);
hitzone.graphics.drawRect(0,0,w,w);
- addToLayer(hitzone, CLICKSPRITE);
+ addToLayer(hitzone, NODECLICKSPRITE);
hitzone.visible = false;
- setListenSprite(hitzone);
+ setListenSprite(NODECLICKSPRITE, hitzone);
}
private function loadedIcon(event:Event,sublayer:uint):void {
private const NODESIZE:uint=6;
- public function WayUI(way:Way, paint:MapPaint, interactive:Boolean=true) {
- super(way,paint,interactive);
+ public function WayUI(way:Way, paint:MapPaint) {
+ super(way,paint);
entity.addEventListener(Connection.WAY_NODE_ADDED, wayNodeAdded);
entity.addEventListener(Connection.WAY_NODE_REMOVED, wayNodeRemoved);
entity.addEventListener(Connection.WAY_REORDERED, wayReordered);
// Redraw
override public function doRedraw(sl:StyleList):Boolean {
+ interactive=false;
removeSprites();
if (Way(entity).length==0) { return false; }
if (!paint.ready) { return false; }
var stroke:Shape, fill:Shape, casing:Shape, roadname:Sprite;
var x0:Number=paint.map.lon2coord(Way(entity).getNode(0).lon);
var y0:Number=paint.map.latp2coord(Way(entity).getNode(0).latp);
+ interactive||=s.interactive;
// Stroke
if (s.width) {
if (s.line_style) { lineDecoration(stroke.graphics,s,segments); }
} else { solidLines(stroke.graphics,inners); }
drawn=true;
- maxwidth=Math.max(maxwidth,s.width);
+ if (s.interactive) { maxwidth=Math.max(maxwidth,s.width); }
}
// Fill
if (s.casing_dashes && s.casing_dashes.length>0) { dashedLine(casing.graphics,s.casing_dashes); }
else { solidLines(casing.graphics,inners); }
drawn=true;
- maxwidth=Math.max(maxwidth,s.casing_width);
+ if (s.interactive) { maxwidth=Math.max(maxwidth,s.casing_width); }
}
}
if (sl.textStyles[sublayer]) {
var t:TextStyle=sl.textStyles[sublayer];
+ interactive||=t.interactive;
roadname=new Sprite(); addToLayer(roadname,NAMESPRITE);
nameformat = t.getTextFormat();
var a:String=tags[t.text];
if (paint.nodeuis[node.id]) {
paint.nodeuis[node.id].redraw(sl);
} else {
- paint.nodeuis[node.id]=new NodeUI(node,paint,r,true,sl);
+ paint.nodeuis[node.id]=new NodeUI(node,paint,r,layer,sl);
}
} else if (paint.nodeuis[node.id]) {
paint.nodeuis[node.id].removeSprites();
if (!drawn) { return false; }
// create a generic "way" hitzone sprite
- hitzone = new Sprite();
- hitzone.graphics.lineStyle(maxwidth, 0x000000, 1, false, "normal", CapsStyle.ROUND, JointStyle.ROUND);
- solidLines(hitzone.graphics,[]);
- addToLayer(hitzone, CLICKSPRITE);
- hitzone.visible = false;
- setListenSprite(hitzone);
+ if (interactive && drawn) {
+ hitzone = new Sprite();
+ hitzone.graphics.lineStyle(maxwidth, 0x000000, 1, false, "normal", CapsStyle.ROUND, JointStyle.ROUND);
+ solidLines(hitzone.graphics,[]);
+ addToLayer(hitzone, WAYCLICKSPRITE);
+ hitzone.visible = false;
+ setListenSprite(WAYCLICKSPRITE, hitzone);
+ }
return true;
}
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 = {
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 request:URLRequest=new URLRequest(str+"?"+Math.random());
var loader:URLLoader=new URLLoader();
request.method=URLRequestMethod.GET;
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
+ 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]; }
public var merged:Boolean=false;
public var edited:Boolean=false; // true once a property has been set from a string
public var sublayer:uint=5;
+ public var interactive:Boolean=true;
public var evals:Object={}; // compiled SWFs for each eval. We keep it here, not in the property
// | itself, so that we can retain typing for each property