add 'interactive:no' property, improve clicking behaviour
authorRichard Fairhurst <richard@systemed.net>
Thu, 1 Jul 2010 08:34:10 +0000 (08:34 +0000)
committerRichard Fairhurst <richard@systemed.net>
Thu, 1 Jul 2010 08:34:10 +0000 (08:34 +0000)
TODO.txt
net/systemeD/halcyon/EntityUI.as
net/systemeD/halcyon/MapPaint.as
net/systemeD/halcyon/NodeUI.as
net/systemeD/halcyon/WayUI.as
net/systemeD/halcyon/styleparser/RuleSet.as
net/systemeD/halcyon/styleparser/Style.as

index 19d2cde..bd79127 100644 (file)
--- a/TODO.txt
+++ b/TODO.txt
@@ -4,6 +4,7 @@ Potlatch 2: main outstanding issues
 
 == Core geometry ==
 
+* P1-style J (join) / shift-J (unjoin)
 * Make parallelise properly undoable
 * Make Quadralatalawhatsit properly undoable
 * Splitway + undo leaves way marked dirty
@@ -58,7 +59,6 @@ Potlatch 2: main outstanding issues
 
 == 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
index 2c82fe7..59552bd 100644 (file)
@@ -16,19 +16,19 @@ package net.systemeD.halcyon {
         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,
@@ -36,10 +36,9 @@ package net.systemeD.halcyon {
                        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);
@@ -123,12 +122,16 @@ package net.systemeD.halcyon {
                        }
                }
 
-               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 {
index ff06729..85d7da6 100644 (file)
@@ -43,8 +43,8 @@ package net.systemeD.halcyon {
                                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
@@ -120,12 +120,12 @@ package net.systemeD.halcyon {
                }
 
                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];
                }
 
index 02ccbb8..fbce463 100644 (file)
@@ -18,9 +18,11 @@ package net.systemeD.halcyon {
                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);
@@ -54,14 +56,16 @@ package net.systemeD.halcyon {
                }
 
                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; }
 
@@ -72,8 +76,7 @@ package net.systemeD.halcyon {
                                                        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') {
@@ -82,8 +85,7 @@ package net.systemeD.halcyon {
                                                        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]) {
@@ -94,9 +96,6 @@ package net.systemeD.halcyon {
                                                        loader.loadBytes(paint.ruleset.images[s.icon_image]);
                                                        iconname=s.icon_image;
                                                }
-                                       } else {
-                                               // already loaded, so just reposition
-                                               updatePosition();
                                        }
                                }
 
@@ -104,6 +103,7 @@ package net.systemeD.halcyon {
                                var a:String='', t:TextStyle;
                                if (sl.textStyles[sublayer]) {
                                        t=sl.textStyles[sublayer];
+                                       interactive||=t.interactive;
                                        a=tags[t.text];
                                }
 
@@ -113,7 +113,10 @@ package net.systemeD.halcyon {
                                        t.writeNameLabel(name,a,0,0);
                                }
                        }
-                       return r;
+                       if (!r) { return false; }
+                       if (interactive) { addHitSprite(maxwidth); }
+                       updatePosition();
+                       return true;
                }
 
 
@@ -123,7 +126,8 @@ package net.systemeD.halcyon {
                        // 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,
@@ -132,7 +136,7 @@ package net.systemeD.halcyon {
                        }
 
                        // 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 {
@@ -140,9 +144,9 @@ package net.systemeD.halcyon {
             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 {
index 7b70fd7..1993819 100755 (executable)
@@ -24,8 +24,8 @@ package net.systemeD.halcyon {
 
                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);
@@ -165,6 +165,7 @@ package net.systemeD.halcyon {
                // Redraw
 
                override public function doRedraw(sl:StyleList):Boolean {
+                       interactive=false;
                        removeSprites();
                        if (Way(entity).length==0) { return false; }
                        if (!paint.ready) { return false; }
@@ -195,6 +196,7 @@ package net.systemeD.halcyon {
                                        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)  {
@@ -206,7 +208,7 @@ package net.systemeD.halcyon {
                                                        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
@@ -228,12 +230,13 @@ package net.systemeD.halcyon {
                                                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];
@@ -272,7 +275,7 @@ package net.systemeD.halcyon {
                                        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();
@@ -282,12 +285,14 @@ package net.systemeD.halcyon {
                        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;
                }
index 3a1fd7a..a617a50 100644 (file)
@@ -73,6 +73,7 @@ package net.systemeD.halcyon.styleparser {
                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 = {
@@ -240,7 +241,7 @@ package net.systemeD.halcyon.styleparser {
                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;
@@ -450,6 +451,11 @@ package net.systemeD.halcyon.styleparser {
                        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']; }
@@ -467,7 +473,7 @@ package net.systemeD.halcyon.styleparser {
                        // 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]; }
                                
index dd60fe3..0c1afdb 100755 (executable)
@@ -8,6 +8,7 @@ package net.systemeD.halcyon.styleparser {
                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