start of turn restriction editor
[potlatch2.git] / net / systemeD / potlatch2 / mapfeatures / Feature.as
1 package net.systemeD.potlatch2.mapfeatures {
2
3     import flash.events.EventDispatcher;
4     import flash.events.Event;
5     import flash.net.*;
6     import flash.utils.ByteArray;
7     
8     import net.systemeD.halcyon.connection.Entity;
9     import net.systemeD.potlatch2.utils.CachedDataLoader;
10
11         public class Feature extends EventDispatcher {
12         private var mapFeatures:MapFeatures;
13         private var _xml:XML;
14         private static var variablesPattern:RegExp = /[$][{]([^}]+)[}]/g;
15         private var _tags:Array;
16                 private var _withins:Array;
17         private var _editors:Array;
18
19         public function Feature(mapFeatures:MapFeatures, _xml:XML) {
20             this.mapFeatures = mapFeatures;
21             this._xml = _xml;
22             parseConditions();
23             parseEditors();
24         }
25         
26         private function parseConditions():void {
27             _tags = [];
28                         _withins = [];
29             
30                         // parse tags
31             for each(var tag:XML in definition.tag) {
32                 _tags.push( { k:tag.@k, v:tag.@v} );
33             }
34
35                         // parse 'within'
36             for each(var within:XML in definition.within) {
37                                 var obj:Object= { entity:within.@entity, k:within.@k };
38                                 if (within.attribute('v'      ).length()>0) { obj['v'      ]=within.@v;       }
39                                 if (within.attribute('minimum').length()>0) { obj['minimum']=within.@minimum; }
40                                 if (within.attribute('role'   ).length()>0) { obj['role'   ]=within.@role;    }
41                 _withins.push(obj);
42             }
43         }
44         
45         private function parseEditors():void {
46             _editors = new Array();
47             
48             addEditors(definition);
49             
50             _editors.sortOn(["sortOrder", "name"], [Array.DESCENDING | Array.NUMERIC, Array.CASEINSENSITIVE]);
51         }
52         
53         private function addEditors(xml:XML):void {
54             var inputXML:XML;
55             
56             for each(var inputSetRef:XML in xml.inputSet) {
57                 var setName:String = String(inputSetRef.@ref);
58                 for each (inputXML in mapFeatures.definition.inputSet.(@id==setName)) {
59                     addEditors(inputXML);
60                 }
61             }
62             
63             for each(inputXML in xml.input) {
64                 addEditor(inputXML);
65             }
66         }
67         
68         private function addEditor(inputXML:XML):void {
69             var inputType:String = inputXML.@type;
70             var presenceStr:String = inputXML.@presence;
71             var sortOrderStr:String = inputXML.@priority;
72             var editor:EditorFactory = EditorFactory.createFactory(inputType, inputXML);
73             if ( editor != null ) {
74                 editor.presence = Presence.getPresence(presenceStr);
75                 editor.sortOrder = EditorFactory.getPriority(sortOrderStr);
76                 _editors.push(editor);
77             }
78         }
79         
80         public function get editors():Array {
81             return _editors;
82         }
83         
84         public function get definition():XML {
85             return _xml;
86         }
87     
88         [Bindable(event="nameChanged")]
89         public function get name():String {
90                         if (_xml.attribute('name').length()>0) { return _xml.@name; }
91                         return null;
92         }
93     
94         [Bindable(event="imageChanged")]
95         public function get image():ByteArray {
96             var icon:XMLList = _xml.icon;
97             var imageURL:String = null;
98
99             if ( icon.length() > 0 && icon[0].hasOwnProperty("@image") )
100                 imageURL = icon[0].@image;
101             
102             if ( imageURL != null ) {
103                 return CachedDataLoader.loadData(imageURL, imageLoaded);
104             }
105             return null;
106         }
107         
108         private function imageLoaded(url:String, data:ByteArray):void {
109             dispatchEvent(new Event("imageChanged"));
110         }
111         
112         public function htmlDetails(entity:Entity):String {
113             var icon:XMLList = _xml.icon;
114             return makeHTMLIcon(icon, entity);
115         }   
116
117         public static function makeHTMLIcon(icon:XMLList, entity:Entity):String {
118             if ( icon == null )
119                 return "";
120             
121             var txt:String = icon.children().toXMLString();
122             var replaceTag:Function = function():String {
123                 var value:String = entity.getTag(arguments[1]);
124                 return value == null ? "" : htmlEscape(value);
125             };
126             txt = txt.replace(variablesPattern, replaceTag);
127             return txt;
128         }
129         
130         public static function htmlEscape(str:String):String {
131             var newStr:String = str.replace(/&/g, "&");
132             newStr = newStr.replace(/</g, "&lt;");
133             newStr = newStr.replace(/>/g, "&gt;");
134             newStr = newStr.replace(/"/g, "&quot;");    // "
135             newStr = newStr.replace(/'/g, "&apos;");    // '
136             return newStr;
137         }
138       
139
140         public function isInCategory(category:String):Boolean {
141             var cats:XMLList = _xml.category;
142             if ( cats.length() == 0 )
143                 return false;
144                 
145             for each( var cat:XML in cats )
146                 if ( cat.text()[0] == category )
147                     return true;
148             return false;
149         }
150         
151         public function get tags():Array {
152             return _tags;
153         }
154
155         public function get withins():Array {
156             return _withins;
157         }
158         
159         public function findFirstCategory():Category {
160             for each( var cat:Category in mapFeatures.categories ) {
161                 if ( isInCategory(cat.id) )
162                     return cat;
163             }
164             return null;
165         }
166         
167         public function isType(type:String):Boolean {
168             if (type=='area') {
169                             return (_xml.elements(type).length() > 0) || (_xml.elements('line').length() > 0);
170             } else {
171                             return _xml.elements(type).length() > 0;
172                         }
173         }
174         
175         public function hasHelpURL():Boolean {
176             return _xml.help.length() > 0;
177         }
178         
179         public function get helpURL():String {
180             return _xml.help;
181         }
182     }
183 }
184