fix some random bugs + do something a bit cooler with maxspeed
authorDave Stubbs <osm@randomjunk.co.uk>
Thu, 10 Sep 2009 20:16:15 +0000 (20:16 +0000)
committerDave Stubbs <osm@randomjunk.co.uk>
Thu, 10 Sep 2009 20:16:15 +0000 (20:16 +0000)
13 files changed:
embedded/restriction.svg [new file with mode: 0644]
net/systemeD/potlatch2/TagViewer.mxml
net/systemeD/potlatch2/mapfeatures/EditorFactory.as
net/systemeD/potlatch2/mapfeatures/Feature.as
net/systemeD/potlatch2/mapfeatures/editors/Choice.as [new file with mode: 0644]
net/systemeD/potlatch2/mapfeatures/editors/ChoiceComboBox.as
net/systemeD/potlatch2/mapfeatures/editors/ChoiceEditor.mxml
net/systemeD/potlatch2/mapfeatures/editors/ChoiceEditorFactory.as
net/systemeD/potlatch2/mapfeatures/editors/RestrictionRenderer.mxml [new file with mode: 0644]
net/systemeD/potlatch2/mapfeatures/editors/SpeedChoice.as [new file with mode: 0644]
net/systemeD/potlatch2/mapfeatures/editors/SpeedEditor.mxml [new file with mode: 0644]
net/systemeD/potlatch2/mapfeatures/editors/SpeedEditorFactory.as [new file with mode: 0644]
resources/map_features.xml

diff --git a/embedded/restriction.svg b/embedded/restriction.svg
new file mode 100644 (file)
index 0000000..6e44d67
--- /dev/null
@@ -0,0 +1,79 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   width="50"
+   height="50"
+   id="svg2"
+   sodipodi:version="0.32"
+   inkscape:version="0.46"
+   version="1.0"
+   sodipodi:docname="restriction.svg"
+   inkscape:output_extension="org.inkscape.output.svg.inkscape">
+  <defs
+     id="defs4">
+    <inkscape:perspective
+       sodipodi:type="inkscape:persp3d"
+       inkscape:vp_x="0 : 526.18109 : 1"
+       inkscape:vp_y="0 : 1000 : 0"
+       inkscape:vp_z="744.09448 : 526.18109 : 1"
+       inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
+       id="perspective10" />
+  </defs>
+  <sodipodi:namedview
+     id="base"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     gridtolerance="10000"
+     guidetolerance="10"
+     objecttolerance="10"
+     inkscape:pageopacity="0.0"
+     inkscape:pageshadow="2"
+     inkscape:zoom="2.47"
+     inkscape:cx="50"
+     inkscape:cy="21.862348"
+     inkscape:document-units="px"
+     inkscape:current-layer="layer1"
+     showgrid="false"
+     inkscape:window-width="1003"
+     inkscape:window-height="723"
+     inkscape:window-x="-5"
+     inkscape:window-y="24" />
+  <metadata
+     id="metadata7">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <g
+     inkscape:label="Layer 1"
+     inkscape:groupmode="layer"
+     id="layer1">
+    <path
+       sodipodi:type="arc"
+       style="fill:#ffffff;fill-opacity:0.82352942;stroke-width:1.29100001000000009;stroke-miterlimit:4;stroke-dasharray:none"
+       id="path2385"
+       sodipodi:cx="53.846153"
+       sodipodi:cy="56.680161"
+       sodipodi:rx="42.51012"
+       sodipodi:ry="42.51012"
+       d="M 96.356274,56.680161 A 42.51012,42.51012 0 1 1 11.336033,56.680161 A 42.51012,42.51012 0 1 1 96.356274,56.680161 z"
+       transform="matrix(0.5880952,0,0,0.5880952,-6.666667,-8.333333)" />
+    <path
+       style="fill:#ff0000;fill-opacity:1;stroke-width:1.29100001;stroke-miterlimit:4;stroke-dasharray:none"
+       d="M 25,0 C 11.2,0 2.4725014e-15,11.2 0,25 C -1.1564823e-18,38.8 11.2,50 25,50 C 38.8,50 50,38.8 50,25 C 50,11.2 38.8,0 25,0 z M 25,5 C 36.04,5 45,13.96 45,25 C 45,36.04 36.04,45 25,45 C 13.96,45 5,36.04 5,25 C 5,13.96 13.96,5 25,5 z"
+       id="path3157" />
+  </g>
+</svg>
index cb0ae37..064cd25 100644 (file)
@@ -1,7 +1,6 @@
 <?xml version="1.0" encoding="utf-8"?>
 <mx:VBox
        xmlns:mx="http://www.adobe.com/2006/mxml" 
-       xmlns:halcyon="net.systemeD.halcyon.*"
     backgroundColor="white"
     creationComplete="loadFeatures()">
 
                   if ( event.newValue == null ) {
                       collection.removeItemAt(i-1);
                       collection.refresh();
+                  } else {
+                      collection.itemUpdated(tag, "value");
                   }
               }
           }
index 862cd80..4cd9b1d 100644 (file)
@@ -17,6 +17,7 @@ package net.systemeD.potlatch2.mapfeatures {
             
             case "freetext": return new FreeTextEditorFactory(inputXML);
             case "choice": return new ChoiceEditorFactory(inputXML);
+            case "speed": return new SpeedEditorFactory(inputXML);
             
             }
             
index 425768c..2a25052 100644 (file)
@@ -78,12 +78,22 @@ package net.systemeD.potlatch2.mapfeatures {
             var txt:String = icon.children().toXMLString();
             var replaceTag:Function = function():String {
                 var value:String = entity.getTag(arguments[1]);
-                return value == null ? "" : value;
+                return value == null ? "" : htmlEscape(value);
             };
             txt = txt.replace(variablesPattern, replaceTag);
             return txt;
         }
         
+        public static function htmlEscape(str:String):String {
+            var newStr:String = str.replace(/&/g, "&amp;");
+            newStr = newStr.replace(/</g, "&lt;");
+            newStr = newStr.replace(/>/g, "&gt;");
+            newStr = newStr.replace(/"/g, "&quot;");
+            newStr = newStr.replace(/'/g, "&apos;");
+            return newStr;
+        }
+      
+
         public function isInCategory(category:String):Boolean {
             var cats:XMLList = _xml.category;
             if ( cats.length() == 0 )
diff --git a/net/systemeD/potlatch2/mapfeatures/editors/Choice.as b/net/systemeD/potlatch2/mapfeatures/editors/Choice.as
new file mode 100644 (file)
index 0000000..b501b19
--- /dev/null
@@ -0,0 +1,63 @@
+package net.systemeD.potlatch2.mapfeatures.editors {
+
+    import flash.events.*;
+
+       public class Choice extends EventDispatcher {
+
+        private var _label:String = "";
+        private var _description:String = "";
+        private var _value:String = null;
+        private var _icon:String = null;
+        private var _match:RegExp = null;
+        
+        [Bindable(event="valueChange")]
+        public function get label():String { return _label; }
+
+        [Bindable(event="valueChange")]
+        public function get description():String { return _description; }
+
+        [Bindable(event="valueChange")]
+        public function get value():String { return _value; }
+
+        [Bindable(event="valueChange")]
+        public function get icon():String { return _icon; }
+
+        public function set label(l:String):void {
+            _label = l;
+            dispatchEvent(new Event("valueChange"));
+        }
+        
+        public function set description(l:String):void {
+            _description = l;
+            dispatchEvent(new Event("valueChange"));
+        }
+        
+        public function set value(l:String):void {
+            _value = l;
+            dispatchEvent(new Event("valueChange"));
+        }
+        
+        public function set icon(l:String):void {
+            _icon = l;
+            dispatchEvent(new Event("valueChange"));
+        }
+        
+        public function isTagMatch(tagValue:String):Boolean {
+            if ( _match == null )
+                return tagValue == _value;
+            //_match.lastIndex = 0;
+            //var result:Object = _match.exec(tagValue);
+            //return result != null && result.index == 0 && _match.lastIndex == tagValue.length;
+            return _match.test(tagValue);
+        }
+        
+        public function set match(matchStr:String):void {
+            if ( matchStr != null && matchStr != "" ) {
+                _match = new RegExp("^("+matchStr+")$");
+            }
+        }
+    }
+
+}
+
+
index 526443c..ef8c094 100644 (file)
@@ -23,6 +23,8 @@ package net.systemeD.potlatch2.mapfeatures.editors {
                                 //create a new itemRenderer to use in place of the text input
                                 textInputReplacement = itemRenderer.newInstance();
                                 IDataRenderer(textInputReplacement).data = {text: "banana"};
+                                textInputReplacement.mouseChildren = false;
+                                textInputReplacement.mouseEnabled = false;
                                 addChild(textInputReplacement);
                         }
                 }
index bd24994..df8ecbd 100644 (file)
         <mx:Component>
         <mx:HBox toolTip="{data.description}">
           <mx:Image source="{data.icon}"/>
-          <mx:Label text="{data.label}"/>
+          <mx:Label htmlText="{data.label}"/>
         </mx:HBox>
         </mx:Component>
       </edit:itemRenderer>
   </edit:ChoiceComboBox>
 
   <mx:Script><![CDATA[
+      import mx.collections.*;
+      import mx.utils.*;
+      import net.systemeD.potlatch2.mapfeatures.Feature;
+      
+      private var _choices:ArrayCollection = null;
+      private var _unknownChoice:Choice = null;
 
       [Bindable(event="factory_set")]
-      private function get choices():Array {
-          return ChoiceEditorFactory(_factory).choices;
+      private function get choices():ArrayCollection {
+          if ( _choices == null ) {
+              _choices = new ArrayCollection(ChoiceEditorFactory(_factory).choices);
+              _choices.addItem(createUnsetChoice());
+          }
+          return _choices;
       }
       
       [Bindable(event="tag_changed")]
       private function get selectFromTag():Object {
           var tagValue:String = value;
-          for each(var choice:Object in choices) {
-              if ( choice.value == tagValue )
+          for each(var choice:Choice in choices) {
+              if ( choice.isTagMatch(tagValue) )
                   return choice;
           }
           
-          inputBox.prompt = tagValue == null ? "" : tagValue;
-          return null;
+          // set up the unknown choice
+          if ( _unknownChoice == null ) {
+              _unknownChoice = new Choice();
+              _unknownChoice.description = "Unknown value";
+              _choices.addItem(_unknownChoice);
+          }
+          _unknownChoice.label = "<i>Unknown:</i> "+Feature.htmlEscape(tagValue);
+          _unknownChoice.icon = null;
+          _unknownChoice.value = tagValue;
+          
+          return _unknownChoice;
       }
       
+      private function createUnsetChoice():Choice {
+          var choice:Choice = new Choice();
+          choice.icon = null;
+          choice.description = "Field not set";
+          choice.label = "<i>Unset</i>";
+          choice.value = null;
+          return choice;
+      }
   ]]></mx:Script>
 </edit:SingleTagEditor>
 
index b6846a7..acef766 100644 (file)
@@ -12,11 +12,12 @@ package net.systemeD.potlatch2.mapfeatures.editors {
             
             choices = [];
             for each( var choiceXML:XML in inputXML.choice ) {
-                var choice:Object = {};
-                choice["value"] = String(choiceXML.@value);
-                choice["description"] = String(choiceXML.@description);
-                choice["label"] = String(choiceXML.@text);
-                choice["icon"] = choiceXML.hasOwnProperty("@icon") ? String(choiceXML.@icon) : null;
+                var choice:Choice = new Choice();
+                choice.value = String(choiceXML.@value);
+                choice.description = String(choiceXML.@description);
+                choice.label = String(choiceXML.@text);
+                choice.icon = choiceXML.hasOwnProperty("@icon") ? String(choiceXML.@icon) : null;
+                choice.match = String(choiceXML.@match);
                 choices.push(choice);
             }
         }
diff --git a/net/systemeD/potlatch2/mapfeatures/editors/RestrictionRenderer.mxml b/net/systemeD/potlatch2/mapfeatures/editors/RestrictionRenderer.mxml
new file mode 100644 (file)
index 0000000..6a941b5
--- /dev/null
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<mx:Canvas
+       xmlns:mx="http://www.adobe.com/2006/mxml" 
+       xmlns:edit="net.systemeD.potlatch2.mapfeatures.editors.*"
+       width="50" height="50"
+       toolTip="{data.description}" enabled="{data.value != null}"
+       mouseEnabled="false" mouseChildren="false">
+
+    <mx:Image x="0" y="0" source="@Embed('../../../../../embedded/restriction.svg')" />
+    
+    <mx:TextInput id="valueText" text="{data.value==null ? '--' : data.scalar}" editable="{data.isEditable}"
+        backgroundAlpha="0"
+        fontWeight="bold" fontSize="16" textAlign="center" borderStyle="none"
+        width="50" x="0" y="7" />
+    
+    <mx:Label id="unitText" text="{data.unit}"
+        x="0" y="{height - unitText.height - 6}" width="50" textAlign="center" />
+    
+</mx:Canvas>
+
diff --git a/net/systemeD/potlatch2/mapfeatures/editors/SpeedChoice.as b/net/systemeD/potlatch2/mapfeatures/editors/SpeedChoice.as
new file mode 100644 (file)
index 0000000..ad02928
--- /dev/null
@@ -0,0 +1,81 @@
+package net.systemeD.potlatch2.mapfeatures.editors {
+
+    import flash.events.*;
+
+       public class SpeedChoice extends EventDispatcher {
+
+        private static const speedRE:RegExp = /^([0-9.]+)\s*(.*)$/;
+        
+        private var _scalar:Number = -1;
+        private var _unit:String = null;
+        private var _description:String = "";
+        private var _value:String = null;
+        private var _isEditable:Boolean = false;
+        
+        public function SpeedChoice(speedStr:String) {
+            value = speedStr;
+        }
+        
+        private function parseSpeedString(speedStr:String):Object {
+            var match:Object = speedRE.exec(speedStr);
+            if ( match == null )
+                return null;
+            
+            try {
+                var scalar:Number = Number(match[1]);
+                var unit:String = match[2].replace(/\s/g, "");
+                if ( unit == null || unit == "" || unit == "kph" || unit == "kmh" )
+                    unit = "km/h";
+                return {scalar: scalar, unit: unit};
+            } catch ( exception:Object ) {
+                return null;
+            }
+            
+            return null;
+        }
+        
+        [Bindable(event="valueChange")]
+        public function get scalar():String { return String(_scalar); }
+
+        [Bindable(event="valueChange")]
+        public function get description():String { return _description; }
+
+        [Bindable(event="valueChange")]
+        public function get value():String { return _value; }
+
+        [Bindable(event="valueChange")]
+        public function get unit():String { return _unit; }
+
+        [Bindable(event="editableChange")]
+        public function get isEditable():Boolean { return _isEditable; }
+
+        public function set isEditable(editable:Boolean):void {
+            _isEditable = editable;
+            dispatchEvent(new Event("editableChange"));
+        }
+        
+        public function isTagMatch(tagValue:String):Boolean {
+            if ( _value == tagValue )
+                return true;
+            
+            var tagSpeed:Object = parseSpeedString(tagValue);
+            return tagSpeed != null && tagSpeed.scalar == _scalar && tagSpeed.unit == _unit;
+        }
+        
+        public function set value(speedStr:String):void {
+            var speed:Object = parseSpeedString(speedStr);
+            if ( speed != null ) {
+                _scalar = speed.scalar;
+                _unit = speed.unit;
+                _description = String(_scalar) + " "+_unit;
+                _value = String(_scalar) + (_unit == "km/h" ? "":_unit);
+            } else {
+                _value = speedStr;
+            }
+            dispatchEvent(new Event("valueChange"));
+        }
+    }
+
+}
+
+
diff --git a/net/systemeD/potlatch2/mapfeatures/editors/SpeedEditor.mxml b/net/systemeD/potlatch2/mapfeatures/editors/SpeedEditor.mxml
new file mode 100644 (file)
index 0000000..d5180f2
--- /dev/null
@@ -0,0 +1,65 @@
+<?xml version="1.0" encoding="utf-8"?>
+<edit:SingleTagEditor
+       xmlns:mx="http://www.adobe.com/2006/mxml" 
+       xmlns:edit="net.systemeD.potlatch2.mapfeatures.editors.*"
+       verticalGap="0"
+       width="100%"
+       toolTip="{fieldDescription}">
+
+  <mx:Label text="{fieldName}:"/>
+  <edit:ChoiceComboBox id="inputBox" dataProvider="{choices}" selectedItem="{selectFromTag}"
+      dropdownFactory="mx.controls.TileList"
+      width="100%" change="value = inputBox.selectedItem.value"
+      open="inputBox.dropdown.variableRowHeight = true"
+      itemRenderer="net.systemeD.potlatch2.mapfeatures.editors.RestrictionRenderer">
+  </edit:ChoiceComboBox>
+
+  <mx:Script><![CDATA[
+      import mx.collections.*;
+      import mx.utils.*;
+      import net.systemeD.potlatch2.mapfeatures.Feature;
+      
+      private var _choices:ArrayCollection = null;
+      private var _unknownChoice:SpeedChoice = null;
+
+      [Bindable(event="factory_set")]
+      private function get choices():ArrayCollection {
+          if ( _choices == null ) {
+              _choices = new ArrayCollection();
+              for each(var sp:String in
+                  ["5mph", "10mph", "15mph", "20mph", "30mph", "40mph", "50mph", "60mph","70mph",
+                   "10", "20", "50", "60", "90", "100", "110", "130"])
+                  _choices.addItem(new SpeedChoice(sp));
+          }
+          return _choices;
+      }
+      
+      [Bindable(event="tag_changed")]
+      private function get selectFromTag():Object {
+          var tagValue:String = value;
+          for each(var choice:SpeedChoice in choices) {
+              if ( choice.isTagMatch(tagValue) )
+                  return choice;
+          }
+          
+          // set up the unknown choice
+          if ( _unknownChoice == null ) {
+              _unknownChoice = new SpeedChoice(tagValue);
+              _choices.addItem(_unknownChoice);
+          }
+          _unknownChoice.value = tagValue;
+          
+          return _unknownChoice;
+      }
+      
+      private function createUnsetChoice():Choice {
+          var choice:Choice = new Choice();
+          choice.icon = null;
+          choice.description = "Field not set";
+          choice.label = "<i>Unset</i>";
+          choice.value = null;
+          return choice;
+      }
+  ]]></mx:Script>
+</edit:SingleTagEditor>
+
diff --git a/net/systemeD/potlatch2/mapfeatures/editors/SpeedEditorFactory.as b/net/systemeD/potlatch2/mapfeatures/editors/SpeedEditorFactory.as
new file mode 100644 (file)
index 0000000..a2e6320
--- /dev/null
@@ -0,0 +1,20 @@
+package net.systemeD.potlatch2.mapfeatures.editors {
+
+    import net.systemeD.halcyon.connection.*;
+    import net.systemeD.potlatch2.mapfeatures.*;
+    import flash.display.*;
+
+       public class SpeedEditorFactory extends SingleTagEditorFactory {
+        
+        public function SpeedEditorFactory(inputXML:XML) {
+            super(inputXML);
+        }
+        
+        override protected function createSingleTagEditor():SingleTagEditor {
+            return new SpeedEditor();
+        }
+    }
+
+}
+
+
index c14cc4f..5e34c7c 100644 (file)
@@ -72,7 +72,9 @@
       <choice value="-1" match="-1|reverse" text="One way reverse"
         description="Road can be travelled in opposite direction to way" icon="features/oneway__-1.png"/>
     </input>
-        
+    <input type="speed" presence="onTagMatch"
+        name="Speed Limit" category="Restrictions" description="Maximum permitted speed on this road"
+        key="maxspeed"/>
   </feature>
 
   <feature name="Primary Road">