Relation selection dialog
[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                   props["description"] = rel.getDescription();
218                   
219                   relations.push(props);
220               }
221               relationsGrid.dataProvider = relations;
222           }
223       }
224
225       private function editRelation(index:uint):void {
226           trace("edit relation "+index+" "+selectedEntity.parentRelations[index]);
227           var panel:RelationEditorPanel = RelationEditorPanel(
228               PopUpManager.createPopUp(Application(Application.application), RelationEditorPanel, true));
229           panel.setRelation(selectedEntity.parentRelations[index]);
230           PopUpManager.centerPopUp(panel);
231       }
232       
233       private function tagChanged(event:TagEvent):void {
234           refreshFeatureIcon();
235           
236           if ( tagDataProvider != null ) {
237               // check to see if the key is already in our list
238               var exists:Boolean = false;
239               var tag:Tag = null;
240               var i:uint;
241               for ( i = 0; i < tagDataProvider.length && !exists; i++ ) {
242                   tag = Tag(tagDataProvider.getItemAt(i));
243                   exists = tag.key == event.key;
244               }
245               if ( !exists ) {
246                   tag = new Tag(selectedEntity, event.key, event.newValue);
247                   tagDataProvider.addItem(tag);
248                   tagDataProvider.refresh();
249               } else {
250                   if ( event.newValue == null ) {
251                       tagDataProvider.removeItemAt(i-1);
252                       tagDataProvider.refresh();
253                   } else {
254                       tagDataProvider.itemUpdated(tag, "value");
255                   }
256               }
257           }
258       }
259
260       public function loadFeatures():void {
261           mapFeatures = MapFeatures.getInstance();
262       }
263
264       public function openDescription():void {
265           trace("open description here");
266           if ( feature != null && feature.hasHelpURL() )
267               navigateToURL(new URLRequest(feature.helpURL), "potlatch_help");
268       }
269
270       public function addNewTag():void {
271           var newKey:String = "(new tag)";
272           var newTag:Tag = new Tag(selectedEntity, newKey, "(new value)");
273           tagDataProvider.addItem(newTag);
274           advancedTagGrid.editedItemPosition = {rowIndex: tagDataProvider.getItemIndex(newTag), columnIndex: 0};
275       }
276
277       public function removeTag():void {
278           var k:String = advancedTagGrid.selectedItem.key;
279           selectedEntity.setTag(k, null);
280       }
281       
282       public function addToRelation():void {
283           new RelationSelectPanel().init(selectedEntity);        
284       }
285       
286       public function removeFromRelation():void {
287       }
288       
289       public function initFeatureBox():void {
290           tw = new CategorySelector();
291           tw.addEventListener("selectedType", changeFeatureType);
292           popupChange.popUp = tw;
293       }
294       
295       public function changeFeatureType(event:Event):void {
296           if ( selectedEntity == null )
297               return;
298
299           var newFeature:Feature = tw.selectedType;
300           
301           // remove tags from the current feature
302           if ( feature != null ) {
303               for each( var oldtag:Object in feature.tags ) {
304                   selectedEntity.setTag(oldtag["k"], null);
305               }
306           }
307           
308           // set tags for new feature
309           if ( newFeature != null ) {
310               for each( var newtag:Object in newFeature.tags ) {
311                   selectedEntity.setTag(newtag["k"], newtag["v"]);
312               }
313           }
314           
315           popupChange.close();
316       }
317   ]]></mx:Script>
318 </mx:VBox>
319