add browser help links for map features
[potlatch2.git] / net / systemeD / potlatch2 / TagViewer.mxml
1 <?xml version="1.0" encoding="utf-8"?>
2 <mx:VBox
3         xmlns:mx="http://www.adobe.com/2006/mxml"
4         xmlns:flexlib="flexlib.containers.*"
5     backgroundColor="white"
6     initialize="loadFeatures()">
7
8   <mx:ViewStack id="stack" width="100%" height="100%">
9   <mx:VBox width="100%" height="100%" label="Simple">
10     <mx:HBox borderStyle="inset" verticalAlign="middle" width="100%" paddingLeft="3" id="iconContainer">
11         <mx:Image id="iconImage"/>
12         <mx:VBox width="100%" verticalGap="1">
13           <mx:PopUpButton id="popupChange" creationComplete="initFeatureBox()" openAlways="true" width="100%"/>
14           <mx:Text condenseWhite="true" width="100%" id="iconText"/>
15         </mx:VBox>
16         <mx:LinkButton label="?" click="openDescription()" id="helpLabel"/>
17     </mx:HBox>
18     <flexlib:SuperTabNavigator id="editorStack" width="100%" height="100%" paddingLeft="2" paddingRight="2"
19         allowTabSqueezing="false" minTabWidth="10" closePolicy="close_never"
20         scrollSpeed="20"/>
21   </mx:VBox>
22
23   <mx:VBox width="100%" height="100%" label="Advanced" initialize="checkAdvanced()" verticalGap="1">
24     <mx:Label id="advancedID">
25       <mx:htmlText><![CDATA[<i>No Selection</i>]]></mx:htmlText>
26     </mx:Label>
27
28     <mx:DataGrid editable="true" width="100%" height="75%" id="advancedTagGrid">
29             <mx:columns>
30                 <mx:DataGridColumn editable="true" dataField="key" headerText="Key"/>
31                 <mx:DataGridColumn editable="true" dataField="value" headerText="Value"/>
32             </mx:columns>
33     </mx:DataGrid>
34
35     <mx:HBox horizontalAlign="right" width="100%">
36       <mx:LinkButton label="Delete" click="removeTag()"/>
37       <mx:LinkButton label="Add" click="addNewTag()"/>
38     </mx:HBox>
39     
40     <mx:DataGrid editable="true" width="100%" height="25%" id="relationsGrid"
41         doubleClickEnabled="true"
42         itemDoubleClick="editRelation(ListEvent(event).rowIndex)">
43         <mx:columns>
44             <mx:DataGridColumn editable="false" dataField="description" headerText="Relation"/>
45             <mx:DataGridColumn editable="false" dataField="id" headerText="ID"/>
46             <mx:DataGridColumn editable="true" dataField="role" headerText="Role"/>
47         </mx:columns>
48     </mx:DataGrid>
49
50     <mx:HBox horizontalAlign="right" width="100%">
51       <mx:LinkButton label="Remove from" click="removeFromRelation()"/>
52       <mx:LinkButton label="Add to" click="addToRelation()"/>
53     </mx:HBox>
54
55   </mx:VBox>
56
57   </mx:ViewStack>
58
59   <mx:LinkBar dataProvider="{stack}"/>
60
61   <mx:Script><![CDATA[
62       import net.systemeD.halcyon.connection.*;
63       import net.systemeD.potlatch2.mapfeatures.*;
64
65       import mx.collections.*;
66       import mx.containers.*;
67       import mx.events.*;
68       import mx.core.*;
69       import mx.managers.PopUpManager;
70       import flash.geom.Point;
71       import flash.net.*;
72       
73       private var mapFeatures:MapFeatures;
74       private var selectedEntity:Entity;
75       private var tagDataProvider:ArrayCollection;
76       private var tw:CategorySelector = null;
77       private var feature:Feature = null;
78
79       public function setEntity(entity:Entity):void {
80           if ( selectedEntity != entity ) {
81               if ( selectedEntity != null )
82                   selectedEntity.removeEventListener(Connection.TAG_CHANGE, tagChanged);
83               selectedEntity = entity;
84               if ( selectedEntity != null )
85                   selectedEntity.addEventListener(Connection.TAG_CHANGE, tagChanged);
86           }
87
88           if ( advancedID != null )
89               setupAdvanced(entity);
90
91           refreshFeatureIcon();
92       }
93
94       private function refreshFeatureIcon():void {
95           var oldFeature:Feature = feature;
96           feature = selectedEntity == null ? null : mapFeatures.findMatchingFeature(selectedEntity);
97           if ( feature != oldFeature )
98               initialiseEditors();
99
100           if ( feature != null )
101               setFeatureIcon(selectedEntity, feature);
102           else
103               blankFeatureIcon(selectedEntity);
104       }
105
106       private function setFeatureIcon(entity:Entity, feature:Feature):void {
107           //blankFeatureIcon(entity);
108           
109           iconImage.source = feature.image;
110
111           var txt:String = feature.htmlDetails(entity);
112           iconText.htmlText = txt;
113           popupChange.label = feature.name;
114           setLimitTypes(entity);
115           tw.setSelectedFeature(feature);
116           helpLabel.visible = feature.hasHelpURL();
117       }
118       
119       private function setLimitTypes(entity:Entity):void {
120           var type:String = null;
121           if ( entity is Node )
122               type = "point";
123           else if ( entity is Way )
124               type = Way(entity).isArea() ? "area" : "line";
125           else if ( entity is Relation )
126               type = "relation";
127           tw.setLimitTypes(type);
128       }
129
130       private function blankFeatureIcon(entity:Entity):void {
131           iconImage.source = null;
132           iconText.htmlText = entity == null ?
133                "<i>Nothing selected</i>" :
134                "<b>Not recognised</b><br/>Try looking at the tags under the advanced properties";
135           popupChange.label = "unknown";
136           setLimitTypes(entity);
137           tw.setSelectedFeature(null);
138           helpLabel.visible = false;
139       }
140
141       private function initialiseEditors():void {
142           editorStack.removeAllChildren();
143           if ( selectedEntity == null || feature == null )
144               return;
145           
146           var editorBox:VBox = createEditorBox();
147           editorBox.label = "Basic";
148           editorStack.addChild(editorBox);
149           
150           var tabs:Object = {};
151           
152           for each (var factory:EditorFactory in feature.editors) {
153               if ( factory.presence.isEditorPresent(factory, selectedEntity, null) ) {
154                   var editor:DisplayObject = factory.createEditorInstance(selectedEntity);
155                   if ( editor != null )
156                       editorBox.addChild(editor);
157               }
158               var category:String = factory.category;
159               var tab:VBox = tabs[category];
160               if ( tab == null ) {
161                   tab = createEditorBox();
162                   tab.label = category;
163                   editorStack.addChild(tab);
164                   tabs[category] = tab;
165               }
166               var catEditor:DisplayObject = factory.createEditorInstance(selectedEntity);
167               if ( catEditor != null )
168                   tab.addChild(catEditor);
169           }
170       }
171       
172       private function createEditorBox():VBox {
173           var box:VBox = new VBox();
174           box.percentWidth = 100;
175           box.percentHeight = 100;
176           return box;
177       }
178
179       private function checkAdvanced():void {
180           if ( selectedEntity != null )
181              setupAdvanced(selectedEntity);
182       }
183
184       private function setupAdvanced(entity:Entity):void {
185           if ( tagDataProvider == null ) {
186               tagDataProvider = new ArrayCollection();
187               advancedTagGrid.dataProvider = tagDataProvider;
188           }
189
190           tagDataProvider.removeAll();
191           
192           if ( entity == null ) {
193               advancedID.htmlText = "";
194           } else {
195               var entityText:String = "xx";
196               if ( entity is Node ) entityText = "Node";
197               else if ( entity is Way ) entityText = "Way";
198               else if ( entity is Relation ) entityText = "Relation";
199               advancedID.htmlText = entityText+": <b>"+entity.id+"</b>";
200
201               var tags:Array = entity.getTagArray();
202               tags.sortOn("key");
203               for each(var tag:Tag in tags)
204                   tagDataProvider.addItem(tag);
205           }
206           
207           if ( entity == null ) {
208               relationsGrid.dataProvider = null;
209           } else {
210               var relations:Array = [];
211               for each( var rel:Relation in entity.parentRelations ) {
212                   var props:Object = {};
213                   props["relation"] = rel;
214                   props["id"] = rel.id;
215                   var memberIndex:uint = rel.findEntityMemberIndex(entity);
216                   props["role"] = rel.getMember(memberIndex).role;
217                   
218                   var desc:String = "";
219                   var relTags:Object = rel.getTagsHash();
220                   if ( relTags["type"] ) {
221                       desc = relTags["type"];
222                       if ( relTags[desc] )
223                           desc += " " + relTags[desc];
224                   }
225                   if ( relTags["ref"] )
226                       desc += " " + relTags["ref"];
227                   if ( relTags["name"] )
228                       desc += " " + relTags["name"];
229                   props["description"] = desc;
230                   
231                   relations.push(props);
232               }
233               relationsGrid.dataProvider = relations;
234           }
235       }
236
237       private function editRelation(index:uint):void {
238           trace("edit relation "+index+" "+selectedEntity.parentRelations[index]);
239           var panel:RelationEditorPanel = RelationEditorPanel(
240               PopUpManager.createPopUp(Application(Application.application), RelationEditorPanel, true));
241           panel.setRelation(selectedEntity.parentRelations[index]);
242           PopUpManager.centerPopUp(panel);
243       }
244       
245       private function tagChanged(event:TagEvent):void {
246           refreshFeatureIcon();
247           
248           if ( tagDataProvider != null ) {
249               // check to see if the key is already in our list
250               var exists:Boolean = false;
251               var tag:Tag = null;
252               var i:uint;
253               for ( i = 0; i < tagDataProvider.length && !exists; i++ ) {
254                   tag = Tag(tagDataProvider.getItemAt(i));
255                   exists = tag.key == event.key;
256               }
257               if ( !exists ) {
258                   tag = new Tag(selectedEntity, event.key, event.newValue);
259                   tagDataProvider.addItem(tag);
260                   tagDataProvider.refresh();
261               } else {
262                   if ( event.newValue == null ) {
263                       tagDataProvider.removeItemAt(i-1);
264                       tagDataProvider.refresh();
265                   } else {
266                       tagDataProvider.itemUpdated(tag, "value");
267                   }
268               }
269           }
270       }
271
272       public function loadFeatures():void {
273           mapFeatures = MapFeatures.getInstance();
274       }
275
276       public function openDescription():void {
277           trace("open description here");
278           if ( feature != null && feature.hasHelpURL() )
279               navigateToURL(new URLRequest(feature.helpURL), "potlatch_help");
280       }
281
282       public function addNewTag():void {
283           var newKey:String = "(new tag)";
284           var newTag:Tag = new Tag(selectedEntity, newKey, "(new value)");
285           tagDataProvider.addItem(newTag);
286           advancedTagGrid.editedItemPosition = {rowIndex: tagDataProvider.getItemIndex(newTag), columnIndex: 0};
287       }
288
289       public function removeTag():void {
290           var k:String = advancedTagGrid.selectedItem.key;
291           selectedEntity.setTag(k, null);
292       }
293       
294       public function addToRelation():void {
295       }
296       
297       public function removeFromRelation():void {
298       }
299       
300       public function initFeatureBox():void {
301           tw = new CategorySelector();
302           tw.addEventListener("selectedType", changeFeatureType);
303           popupChange.popUp = tw;
304       }
305       
306       public function changeFeatureType(event:Event):void {
307           if ( selectedEntity == null )
308               return;
309
310           var newFeature:Feature = tw.selectedType;
311           
312           // remove tags from the current feature
313           if ( feature != null ) {
314               for each( var oldtag:Object in feature.tags ) {
315                   selectedEntity.setTag(oldtag["k"], null);
316               }
317           }
318           
319           // set tags for new feature
320           if ( newFeature != null ) {
321               for each( var newtag:Object in newFeature.tags ) {
322                   selectedEntity.setTag(newtag["k"], newtag["v"]);
323               }
324           }
325           
326           popupChange.close();
327       }
328   ]]></mx:Script>
329 </mx:VBox>
330