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