Local file vector import (not .shp yet)
[potlatch2.git] / net / systemeD / potlatch2 / dialogs / VectorSourceDialog.mxml
1 <?xml version="1.0" encoding="utf-8"?>
2 <mx:TitleWindow
3         xmlns:fx="http://ns.adobe.com/mxml/2009"
4         xmlns:mx="library://ns.adobe.com/flex/mx"
5                 xmlns:s="library://ns.adobe.com/flex/spark"
6         layout="vertical" showCloseButton="true"
7         horizontalAlign="center" title="Load vector file"
8         width="630" height="450" verticalGap="0">
9
10         <mx:DataGrid editable="true" width="100%" height="100%" id="dataGrid" 
11                 dataProvider="{vectorLayers}" itemEditEnd="dataEdited(event)">
12             <mx:columns>
13                 <mx:DataGridColumn editable="false" dataField="visible" headerText="Show?" width="45">
14                                 <mx:itemRenderer>
15                                         <fx:Component>
16                                                 <mx:CheckBox selectedField="isSelected"
17                                                                          click="data.isSelected=!data.isSelected; this.parent.parent.dispatchEvent(new Event('visibility_changed'));" 
18                                                                          paddingLeft="5"/>
19                                         </fx:Component>
20                                 </mx:itemRenderer>
21                         </mx:DataGridColumn>
22                 <mx:DataGridColumn editable="false" dataField="interactive" headerText="Select?" width="45">
23                                 <mx:itemRenderer>
24                                         <!-- There should really be a way to hide this for the editable layer. See
25                                              http://stackoverflow.com/questions/6329895/how-do-i-change-the-style-of-one-individual-cell-in-a-flex-datagrid 
26                                              Leave it as a FIXME until we move to Flex 4 -->
27                                         <fx:Component>
28                                                 <mx:CheckBox selectedField="isInteractive"
29                                                                          click="data.isInteractive=!data.isInteractive; this.parent.parent.dispatchEvent(new Event('interactive_changed'));" 
30                                                              paddingLeft="5"/>
31                                         </fx:Component>
32                                 </mx:itemRenderer>
33                         </mx:DataGridColumn>
34                 <mx:DataGridColumn editable="true"  dataField="name"  headerText="Name"/>
35                 <mx:DataGridColumn editable="false" dataField="url"   headerText="URL"/>
36                 <mx:DataGridColumn editable="false" dataField="style" headerText="Style">
37                                 <mx:itemRenderer>
38                                         <fx:Component>
39                                         <mx:ComboBox
40                                                         selectedItem="{outerDocument.whichStyle(data)}"
41                                                 change="outerDocument.styleEdited(data.name,selectedItem.url)"
42                                                 dataProvider="{outerDocument.styles}" 
43                                                         labelField="name" />
44                                         </fx:Component>
45                                 </mx:itemRenderer>
46                         </mx:DataGridColumn>
47             </mx:columns>
48         </mx:DataGrid>
49         <mx:HBox horizontalAlign="right" width="100%">
50                 <mx:LinkButton label="Delete" click="removeLayer()" enabled="{dataGrid.selectedItem != null &amp;&amp; dataGrid.selectedItem.isBackground}"/>
51         </mx:HBox>
52
53         <fx:Declarations>
54                 <s:RadioButtonGroup id="filetype" />
55         </fx:Declarations>
56         <s:Form id="addlayer" width="100%">
57                 <s:FormHeading label="Add new vector layer" />
58
59                 <s:FormItem label="File type:">
60                         <s:HGroup>
61                                 <s:RadioButton groupName="filetype" value="gpx" id="gpx" label="GPX" selected="true" />
62                                 <s:RadioButton groupName="filetype" value="kml" id="kml" label="KML" />
63                                 <s:RadioButton groupName="filetype" value="osm" id="osm" label="OSM" />
64                                 <s:RadioButton groupName="filetype" value="shp" id="shp" label="Shapefile" />
65                         </s:HGroup>
66                         <s:helpContent><s:Label text="Type of data to load"/></s:helpContent>
67                 </s:FormItem>
68
69                 <s:FormItem label="Projection:">
70                         <s:DropDownList id="projection" selectedIndex="0" width="200"> 
71                                 <s:ArrayCollection>
72                                         <fx:Object label="Lat/long (EPSG:4326)" data="" />
73                                         <fx:Object label="Ordnance Survey GB" data="EPSG:27700" />
74                                         <fx:Object label="NAD83" data="EPSG:4269" />
75                                 </s:ArrayCollection>
76                         </s:DropDownList>
77                         <s:helpContent><s:Label text="Shapefiles only"/></s:helpContent>
78                 </s:FormItem>
79
80                 <s:FormItem label="Simplify:">
81                         <s:CheckBox label="Enabled" id="simplify" />
82                         <s:helpContent><s:Label text="Reduce points in paths"/></s:helpContent>
83                 </s:FormItem>
84
85         <s:FormItem label="File:">
86                         <s:HGroup>
87                                 <s:Button label="Open..." click="loadFileLocal()" />
88                                 <s:Rect width="20" height="1" />
89                     <s:TextInput id="src" text="" change="selectByExtension()" />
90                                 <s:Button label="Fetch" click="loadFiles(src.text);" enabled="{src.text == '' ? false : true}"/>
91                         </s:HGroup>
92             <s:helpContent><s:Label text="URL of file to load" /></s:helpContent>
93         </s:FormItem>
94
95         <s:FormItem label="Tag transform:">
96                         <s:HGroup>
97                                 <s:Button label="Open..." />
98                                 <s:Rect width="20" height="1" />
99                                 <s:TextInput id="transformsrc" text="{CSSTransform.getInstance().url}"/>
100                                 <s:Button label="Fetch" click="loadTransform(transformsrc.text);" enabled="{transformsrc.text == '' ? false : true}"/>
101                                 <s:Button label="Clear" click="clearTransform();"                 enabled="{transformsrc.text == '' ? false : true}"/>
102                         </s:HGroup>
103             <s:helpContent><s:Label text="MapCSS transformation file" /></s:helpContent>
104         </s:FormItem>
105
106         </s:Form>
107
108   <fx:Script><![CDATA[
109
110         import net.systemeD.halcyon.Map;
111         import net.systemeD.halcyon.MapPaint;
112         import net.systemeD.halcyon.Globals;
113         import net.systemeD.halcyon.connection.Connection;
114         import net.systemeD.halcyon.styleparser.CSSTransform;
115         import net.systemeD.potlatch2.utils.*;
116         import net.systemeD.potlatch2.collections.Stylesheets;
117     import mx.managers.PopUpManager;
118     import mx.events.DataGridEvent;
119     import mx.events.CloseEvent;
120     import mx.core.Application;
121     import mx.core.FlexGlobals;
122         import mx.collections.ArrayCollection;
123         import mx.controls.Alert;
124
125         private var map:Map;
126         private var localFileReference:FileReference;
127
128         public function styleEdited(name:String,stylesheet:String):void {
129                 map.findLayer(name).setStyle(stylesheet);
130         }
131
132
133     public function init():void {
134         PopUpManager.addPopUp(this, Application(FlexGlobals.topLevelApplication), true);
135         PopUpManager.centerPopUp(this);
136         this.addEventListener(CloseEvent.CLOSE, vectorDialog_close);
137                 dataGrid.addEventListener("visibility_changed", toggleVisibility);
138                 dataGrid.addEventListener("interactive_changed", toggleInteractive);
139                 map = Globals.vars.root;
140                 dispatchEvent(new Event("layers_changed"));
141     }
142
143         public function whichStyle(item:Object):Object {
144                 for each (var style:Object in styles) {
145                         if (style.url==item.style) { return style; }
146                 }
147                 return {};
148         }
149
150         [Bindable(event="bogus")]
151         public function get styles():ArrayCollection {
152                 return new ArrayCollection(Stylesheets.instance().collection);
153         }
154
155         [Bindable(event="layers_changed")]
156         private function get vectorLayers():Array {
157         var v:Array=[];
158         for each (var a:MapPaint in map.getLayers() ) {
159             v.push( { name:a.connection.name, visible:a.visible, interactive:a.interactive, url:a.connection.apiBase, style:a.style, isBackground:a.isBackground } );
160         }
161                 return v;
162         }
163         
164         private function get selectedType():String {
165                 return filetype.selectedValue.toString();
166         }
167         
168         private function toggleVisibility(event:Event):void {
169                 map.findLayer(dataGrid.selectedItem.name).visible = !map.findLayer(dataGrid.selectedItem.name).visible;
170         }
171
172         private function toggleInteractive(event:Event):void {
173                 map.findLayer(dataGrid.selectedItem.name).interactive = !map.findLayer(dataGrid.selectedItem.name).interactive;
174         }
175         
176         private function dataEdited(event:DataGridEvent):void {
177                 if (event.dataField=='name') {
178                         // Rename field
179                         var a:String=dataGrid.selectedItem.name;
180                         var b:String=dataGrid.itemEditorInstance['text'];       // this is, unbelievably, how you get data within an itemEditEnd event
181                         if (a==b || map.findLayer(b)) {
182                                 event.preventDefault();
183                         } else {
184                                 map.findLayer(a).connection.name = b;
185                         }
186                         dispatchEvent(new Event("layers_changed"));
187                 }
188         }
189
190         private function removeLayer():void {
191                 map.removeLayerByName(dataGrid.selectedItem.name);
192                 dispatchEvent(new Event("layers_changed"));
193         }
194     
195         private function selectByExtension():void {
196                 if      (src.text.match(/\.shp$/i)) filetype.selectedValue='shp'
197                 else if (src.text.match(/\.osm$/i)) filetype.selectedValue='osm'
198                 else if (src.text.match(/\.gpx$/i)) filetype.selectedValue='gpx'
199                 else if (src.text.match(/\.kml$/i)) filetype.selectedValue='kml'
200         }
201
202     private function vectorDialog_close(evt:CloseEvent):void {
203         PopUpManager.removePopUp(this);
204     }
205
206         /** Launch importer for remotely hosted files. */
207         private function loadFiles(url:String):void {
208                 var names:Array=url.split('/'); var name:String=names[names.length-1];
209                 var connection:Connection = new Connection(name, url, null, null, CSSTransform.getInstance());
210                 var importer:Importer = findImporter(connection);
211                 if (selectedType=='shp') {
212                         importer.importFromRemoteFiles([url]);
213                 } else {
214                         var re:RegExp=/.shp$/i; url=url.replace(re,'');
215                         importer.importFromRemoteFiles([url+".shp",url+".shx",url+".dbf"]);
216                 }
217         }
218         
219         /** Present an 'Open File' dialogue. */
220         private function loadFileLocal():void {
221                 // note scoping issues - http://blog.wrench.com.au/2010/06/16/filereferenceload-keep-it-in-scope/
222                 localFileReference=new FileReference(); 
223                 var fileTypes:FileFilter=new FileFilter("*."+selectedType, "*."+selectedType); 
224                 localFileReference.browse([fileTypes]); 
225                 localFileReference.addEventListener(Event.SELECT, selectFileLocal);
226         }
227         
228         /** The user has chosen a file in the local 'Open File' dialogue. */
229         private function selectFileLocal(event:Event):void {
230                 var connection:Connection = new Connection(localFileReference.name, '', null, null, CSSTransform.getInstance());
231                 var importer:Importer = findImporter(connection);
232                 importer.importFromLocalFile(localFileReference);
233         }
234         
235         /** Create an Importer object of the type selected by the user. */
236         private function findImporter(connection:Connection):Importer {
237                 var simplifyPath:Boolean=simplify.selected;
238                 var reproject:String=projection.selectedItem.data;
239                 var stylesheet:String="stylesheets/potlatch.css"; if (selectedType=='gpx') { stylesheet="stylesheets/gpx.css"; }
240
241                 switch (selectedType) {
242                         case 'gpx':     return new GpxImporter(connection, map, filesLoaded, simplifyPath, { stylesheet: stylesheet });
243                         case 'kml':     return new KmlImporter(connection, map, filesLoaded, simplifyPath, { stylesheet: stylesheet });
244                         case 'osm': return new OsmImporter(connection, map, filesLoaded, simplifyPath, { stylesheet: stylesheet });
245                         case 'shp': return new ShpImporter(connection, map, filesLoaded, simplifyPath, { stylesheet: stylesheet, projection: reproject });
246                 }
247                 return null;
248         }
249         
250         /** Callback routine when import has completed. */
251         private function filesLoaded(connection:Connection,options:Object,success:Boolean,message:String=null):void {
252                 if (success) {
253                         var paint:MapPaint = map.addLayer(connection, options['stylesheet']);
254                         paint.updateEntityUIs(false, false);
255                         dispatchEvent(new Event("layers_changed"));
256                 } else {
257                         Alert.show(message, 'Error', mx.controls.Alert.OK);
258                 }
259         }
260         
261         private function loadTransform(url:String):void {
262                 CSSTransform.getInstance().loadFromUrl(url);
263         }
264         private function clearTransform():void {
265                 CSSTransform.getInstance().clear();
266         }
267
268               ]]>
269   </fx:Script>
270 </mx:TitleWindow>