Show relation index in advanced properties
[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()" enabled="{advancedTagGrid.selectedItem != null? true : false}"/>
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_idx" 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(relationsGrid.selectedItem.id, relationsGrid.selectedItem.index)" 
52                       enabled="{relationsGrid.selectedItem != null? true : false}"/>
53       <mx:LinkButton label="Add to" click="addToRelation()"/>
54     </mx:HBox>
55
56   </mx:VBox>
57
58   </mx:ViewStack>
59
60   <mx:LinkBar dataProvider="{stack}"/>
61
62   <mx:Script><![CDATA[
63       import net.systemeD.halcyon.connection.*;
64       import net.systemeD.potlatch2.mapfeatures.*;
65
66       import mx.collections.*;
67       import mx.containers.*;
68       import mx.events.*;
69       import mx.core.*;
70       import mx.managers.PopUpManager;
71       import flash.geom.Point;
72       import flash.net.*;
73       
74       private var mapFeatures:MapFeatures;
75       private var selectedEntity:Entity;
76       private var tagDataProvider:ArrayCollection;
77       private var tw:CategorySelector = null;
78       private var feature:Feature = null;
79
80       public function setEntity(entity:Entity):void {
81           if ( selectedEntity != entity ) {
82               if ( selectedEntity != null )
83                   selectedEntity.removeEventListener(Connection.TAG_CHANGE, tagChanged);
84               selectedEntity = entity;
85               if ( selectedEntity != null )
86                   selectedEntity.addEventListener(Connection.TAG_CHANGE, tagChanged);
87           }
88
89           if ( advancedID != null )
90               setupAdvanced(entity);
91
92           refreshFeatureIcon();
93       }
94
95       private function refreshFeatureIcon():void {
96           var oldFeature:Feature = feature;
97           feature = selectedEntity == null ? null : mapFeatures.findMatchingFeature(selectedEntity);
98           if ( feature != oldFeature )
99               initialiseEditors();
100
101           if ( feature != null )
102               setFeatureIcon(selectedEntity, feature);
103           else
104               blankFeatureIcon(selectedEntity);
105       }
106
107       private function setFeatureIcon(entity:Entity, feature:Feature):void {
108           //blankFeatureIcon(entity);
109           
110           iconImage.source = feature.image;
111
112           var txt:String = feature.htmlDetails(entity);
113           iconText.htmlText = txt;
114           popupChange.label = feature.name;
115           setLimitTypes(entity);
116           tw.setSelectedFeature(feature);
117           helpLabel.visible = feature.hasHelpURL();
118       }
119       
120       private function setLimitTypes(entity:Entity):void {
121           var type:String = null;
122           if ( entity is Node )
123               type = "point";
124           else if ( entity is Way )
125               type = Way(entity).isArea() ? "area" : "line";
126           else if ( entity is Relation )
127               type = "relation";
128           tw.setLimitTypes(type);
129       }
130
131       private function blankFeatureIcon(entity:Entity):void {
132           iconImage.source = null;
133           iconText.htmlText = entity == null ?
134                "<i>Nothing selected</i>" :
135                "<b>Not recognised</b><br/>Try looking at the tags under the advanced properties";
136           popupChange.label = "unknown";
137           setLimitTypes(entity);
138           tw.setSelectedFeature(null);
139           helpLabel.visible = false;
140       }
141
142       private function initialiseEditors():void {
143           editorStack.removeAllChildren();
144           if ( selectedEntity == null || feature == null )
145               return;
146           
147           var editorBox:VBox = createEditorBox();
148           editorBox.label = "Basic";
149           editorStack.addChild(editorBox);
150           
151           var tabs:Object = {};
152           
153           for each (var factory:EditorFactory in feature.editors) {
154               if ( factory.presence.isEditorPresent(factory, selectedEntity, null) ) {
155                   var editor:DisplayObject = factory.createEditorInstance(selectedEntity);
156                   if ( editor != null )
157                       editorBox.addChild(editor);
158               }
159               var category:String = factory.category;
160               var tab:VBox = tabs[category];
161               if ( tab == null ) {
162                   tab = createEditorBox();
163                   tab.label = category;
164                   editorStack.addChild(tab);
165                   tabs[category] = tab;
166               }
167               var catEditor:DisplayObject = factory.createEditorInstance(selectedEntity);
168               if ( catEditor != null )
169                   tab.addChild(catEditor);
170           }
171       }
172       
173       private function createEditorBox():VBox {
174           var box:VBox = new VBox();
175           box.percentWidth = 100;
176           box.percentHeight = 100;
177           return box;
178       }
179
180       private function checkAdvanced():void {
181           if ( selectedEntity != null )
182              setupAdvanced(selectedEntity);
183       }
184
185       private function setupAdvanced(entity:Entity):void {
186           if ( tagDataProvider == null ) {
187               tagDataProvider = new ArrayCollection();
188               advancedTagGrid.dataProvider = tagDataProvider;
189           }
190
191           tagDataProvider.removeAll();
192           
193           if ( entity == null ) {
194               advancedID.htmlText = "";
195           } else {
196               var entityText:String = "xx";
197               if ( entity is Node ) entityText = "Node";
198               else if ( entity is Way ) entityText = "Way";
199               else if ( entity is Relation ) entityText = "Relation";
200               advancedID.htmlText = entityText+": <b>"+entity.id+"</b>";
201
202               var tags:Array = entity.getTagArray();
203               tags.sortOn("key");
204               for each(var tag:Tag in tags)
205                   tagDataProvider.addItem(tag);
206           }
207           
208           if ( entity == null ) {
209               relationsGrid.dataProvider = null;
210           } else {
211               var relations:Array = [];
212               for each( var rel:Relation in entity.parentRelations ) {
213                   for each( var memberIndex:int in rel.findEntityMemberIndexes(entity)) {
214                     var props:Object = {};
215                     props["relation"] = rel;
216                     props["id"] = rel.id;
217                     props["index"] = memberIndex;
218                     props["role"] = rel.getMember(memberIndex).role;
219                     props["description"] = rel.getDescription();
220                     props["id_idx"] = rel.id + "/"+memberIndex;
221                     
222                     relations.push(props);
223                   }
224               }
225               relationsGrid.dataProvider = relations;
226           }
227       }
228
229       private function editRelation(index:uint):void {
230           trace("edit relation "+index+" "+selectedEntity.parentRelations[index]);
231           var panel:RelationEditorPanel = RelationEditorPanel(
232               PopUpManager.createPopUp(Application(Application.application), RelationEditorPanel, true));
233           panel.setRelation(selectedEntity.parentRelations[index]);
234           PopUpManager.centerPopUp(panel);
235       }
236       
237       private function tagChanged(event:TagEvent):void {
238           refreshFeatureIcon();
239           
240           if ( tagDataProvider != null ) {
241               // check to see if the key is already in our list
242               var exists:Boolean = false;
243               var tag:Tag = null;
244               var i:uint;
245               for ( i = 0; i < tagDataProvider.length && !exists; i++ ) {
246                   tag = Tag(tagDataProvider.getItemAt(i));
247                   exists = tag.key == event.key;
248               }
249               if ( !exists ) {
250                   tag = new Tag(selectedEntity, event.key, event.newValue);
251                   tagDataProvider.addItem(tag);
252                   tagDataProvider.refresh();
253               } else {
254                   if ( event.newValue == null ) {
255                       tagDataProvider.removeItemAt(i-1);
256                       tagDataProvider.refresh();
257                   } else {
258                       tagDataProvider.itemUpdated(tag, "value");
259                   }
260               }
261           }
262       }
263
264       public function loadFeatures():void {
265           mapFeatures = MapFeatures.getInstance();
266       }
267
268       public function openDescription():void {
269           trace("open description here");
270           if ( feature != null && feature.hasHelpURL() )
271               navigateToURL(new URLRequest(feature.helpURL), "potlatch_help");
272       }
273
274       public function addNewTag():void {
275           var newKey:String = "(new tag)";
276           var newTag:Tag = new Tag(selectedEntity, newKey, "(new value)");
277           tagDataProvider.addItem(newTag);
278           advancedTagGrid.editedItemPosition = {rowIndex: tagDataProvider.getItemIndex(newTag), columnIndex: 0};
279       }
280
281       public function removeTag():void {
282           var k:String = advancedTagGrid.selectedItem.key;
283           selectedEntity.setTag(k, null);
284       }
285       
286       public function addToRelation():void {
287           new RelationSelectPanel().init(selectedEntity);        
288       }
289       
290       public function removeFromRelation(id:Number, index:int):void {
291           Connection.getConnectionInstance().getRelation(id).removeMemberByIndex(index);
292       }
293       
294       public function initFeatureBox():void {
295           tw = new CategorySelector();
296           tw.addEventListener("selectedType", changeFeatureType);
297           popupChange.popUp = tw;
298       }
299       
300       public function changeFeatureType(event:Event):void {
301           if ( selectedEntity == null )
302               return;
303
304           var newFeature:Feature = tw.selectedType;
305           
306           // remove tags from the current feature
307           if ( feature != null ) {
308               for each( var oldtag:Object in feature.tags ) {
309                   selectedEntity.setTag(oldtag["k"], null);
310               }
311           }
312           
313           // set tags for new feature
314           if ( newFeature != null ) {
315               for each( var newtag:Object in newFeature.tags ) {
316                   selectedEntity.setTag(newtag["k"], newtag["v"]);
317               }
318           }
319           
320           popupChange.close();
321       }
322   ]]></mx:Script>
323 </mx:VBox>
324