* Reopen?
* Handle errors when closing bugs (especially nickname-based errors)
-== Code tidying ==
-
-* The imagery and stylesheet collections should each be singletons, rather than clogging up the EditController and application
-
Requested enhancements
----------------------
urlReq.data = upload.toXMLString();
urlReq.contentType = "text/xml";
var loader:URLLoader = new URLLoader();
+ loader.dataFormat = URLLoaderDataFormat.BINARY;
loader.addEventListener(Event.COMPLETE, diffUploadComplete);
loader.addEventListener(IOErrorEvent.IO_ERROR, diffUploadError);
loader.addEventListener(HTTPStatusEvent.HTTP_STATUS, recordStatus);
horizontalAlign="center"
width="500" height="300" verticalGap="0">
- <mx:DataGrid editable="true" width="100%" height="100%" id="dataGrid">
+ <mx:DataGrid editable="true" width="100%" height="100%" id="dataGrid" itemEditEnd="updateSource()">
<mx:columns>
<mx:DataGridColumn editable="true" dataField="name" headerText="Name"/>
<mx:DataGridColumn editable="true" dataField="url" headerText="URL"/>
public var dataCollection:ArrayCollection;
private var menu:List;
+ private var collection:Object;
- public function init(title:String, menu:List, source:Array):void {
+ public function init(title:String, menu:List, source:Object):void {
this.title=title;
this.menu=menu;
- dataCollection=new ArrayCollection(source);
+ collection=source;
+ dataCollection=new ArrayCollection(source.collection);
PopUpManager.addPopUp(this, Application(Application.application), true);
PopUpManager.centerPopUp(this);
this.addEventListener(CloseEvent.CLOSE, backgroundDialog_close);
private function removeSource():void {
dataCollection.removeItemAt(dataGrid.selectedIndex);
}
+ public function updateSource():void {
+ collection.dispatchEvent(new Event("collection_changed"));
+ }
]]>
</mx:Script>
<mx:List width="100%" height="100%" id="background" verticalScrollPolicy="on"
labelField="name"
- change="Application.application.bgButton.close(); Application.application.setBackground(background.selectedItem);"
- dataProvider="{Application.application.getAvailableImagery()}" />
+ change="Application.application.bgButton.close(); Imagery.instance().setBackground(background.selectedItem);"
+ dataProvider="{Imagery.instance().getAvailableImagery()}" />
<mx:HBox>
<mx:CheckBox width="100%" label="Dim" selected="true" id="dim"
change="Application.application.theMap.setDimming(dim.selected); Application.application.yahoo.alpha = dim.selected ? 0.5 : 1" />
</mx:HBox>
<mx:HBox>
- <mx:Button label="Edit..." click="Application.application.bgButton.close(); new BackgroundDialog().init('Background imagery',background,Application.application.theController.imagery);" />
+ <mx:Button label="Edit..." click="Application.application.bgButton.close(); new BackgroundDialog().init('Background imagery',background,Imagery.instance());" />
<mx:Button label="Vector file..." click="Application.application.bgButton.close(); new VectorSourceDialog().init();" />
</mx:HBox>
import net.systemeD.halcyon.*;
import net.systemeD.halcyon.connection.*;
import net.systemeD.potlatch2.*;
+ import net.systemeD.potlatch2.collections.Imagery;
import mx.core.*;
import mx.collections.ArrayCollection;
import mx.managers.PopUpManager;
private var keys:Object={};
public var clipboards:Object={};
- public var imagery:Array=[];
- public var imagerySelected:Object={};
- public var stylesheets:Array=[];
public var cursorsEnabled:Boolean=true;
[Embed(source="../../../embedded/pen.png")] public var pen:Class;
<mx:List width="100%" height="100%" id="mapStyle"
labelField="name"
change="Application.application.styleButton.close(); Application.application.setStylesheet(mapStyle.selectedItem.name, mapStyle.selectedItem.url);"
- dataProvider="{Application.application.theController.stylesheets}" />
+ dataProvider="{Stylesheets.instance().getCollection()}" />
- <mx:Button label="Edit..." click="new BackgroundDialog().init('Map style',mapStyle,Application.application.theController.stylesheets);" />
+ <mx:Button label="Edit..." click="new BackgroundDialog().init('Map style',mapStyle,Stylesheets.instance());" />
<mx:Script><![CDATA[
import net.systemeD.halcyon.*;
import net.systemeD.halcyon.connection.*;
import net.systemeD.potlatch2.*;
+ import net.systemeD.potlatch2.collections.Stylesheets;
import mx.core.*;
]]></mx:Script>
</mx:VBox>
import net.systemeD.potlatch2.utils.KmlImporter;
import net.systemeD.potlatch2.utils.ShpImporter;
import net.systemeD.potlatch2.utils.OsmImporter;
+ import net.systemeD.potlatch2.collections.Stylesheets;
import mx.managers.PopUpManager;
import mx.events.DataGridEvent;
import mx.events.CloseEvent;
[Bindable(event="bogus")]
public function get styles():ArrayCollection {
- return new ArrayCollection(Application.application.theController.stylesheets);
+ return new ArrayCollection(Stylesheets.instance().collection);
}
[Bindable(event="layers_changed")]
--- /dev/null
+package net.systemeD.potlatch2.collections {
+
+ import flash.events.EventDispatcher;
+ import flash.events.Event;
+ import flash.net.*;
+ import net.systemeD.halcyon.DebugURLRequest;
+ import net.systemeD.halcyon.Map;
+ import net.systemeD.potlatch2.FunctionKeyManager;
+ import net.systemeD.potlatch2.Yahoo;
+ import mx.collections.ArrayCollection;
+
+ /*
+ There's lots of further tidying we can do:
+ - remove all the horrid Yahoo stuff
+ - remove the backreferences to _map and send events instead
+ but this will do for now and help remove the clutter from potlatch2.mxml.
+ */
+
+ public class Imagery extends EventDispatcher {
+
+ private static const GLOBAL_INSTANCE:Imagery = new Imagery();
+ public static function instance():Imagery { return GLOBAL_INSTANCE; }
+
+ public var collection:Array=[];
+ public var selected:Object={};
+ private var _yahooDefault:Boolean=false;
+ private var _map:Map;
+ private var _yahoo:Yahoo;
+
+ /* Load catalogue file */
+
+ public function init(map:Map,yahoo:Yahoo,yahooDefault:Boolean):void {
+ _map = map;
+ _yahoo = yahoo;
+ _yahooDefault = yahooDefault;
+ var request:DebugURLRequest = new DebugURLRequest("imagery.xml");
+ var loader:URLLoader = new URLLoader();
+ loader.addEventListener(Event.COMPLETE, onImageryLoad);
+ loader.load(request.request);
+ }
+
+ private function onImageryLoad(event:Event):void {
+ var xml:XML = new XML(URLLoader(event.target).data);
+ var saved:Object;
+ if (SharedObject.getLocal("user_state").data['background_url']) {
+ saved={ name: SharedObject.getLocal("user_state").data['background_name'],
+ url: SharedObject.getLocal("user_state").data['background_url' ] };
+ } else {
+ saved={ url: ''};
+ }
+
+ var isSet:Boolean=false;
+ var backgroundSet:Boolean = false;
+
+ collection=new Array(
+ { name: "None", url: "" },
+ { name: "Yahoo", url: "yahoo", sourcetag: "Yahoo" } );
+ for each(var set:XML in xml.set) {
+ var obj:Object={};
+ var a:XML;
+ for each (a in set.@*) { obj[a.name().localName]=a.toString(); }
+ for each (a in set.* ) { obj[a.name() ]=a.toString(); }
+ collection.push(obj);
+ if ((obj.url ==saved.url) ||
+ (obj.name==saved.name && obj.name!='Custom')) { isSet=true; }
+ }
+
+ if (!isSet && saved.name && saved.url && saved.url!='' && saved.url!='yahoo') {
+ collection.push(saved);
+ isSet=true;
+ }
+
+ for each (var bg:Object in collection) {
+ if (bg.name==saved.name || bg.url==saved.url) {
+ setBackground(bg);
+ backgroundSet = true;
+ }
+ }
+
+ // For most contributors it's useful to set the background to yahoo by default, I reckon, but lets make it a config
+ if (!backgroundSet && _yahooDefault) {
+ setBackground(collection[1]);
+ }
+ FunctionKeyManager.instance().registerListener('Background imagery',
+ function(o:String):void { setBackground(findBackgroundWithName(o)); });
+ dispatchEvent(new Event("collection_changed"));
+ }
+
+ public function setBackground(bg:Object):void {
+ if (bg.url=='yahoo') { _map.setBackground({url:''}); _yahoo.show(); }
+ else { _map.setBackground(bg ); _yahoo.hide(); }
+ selected=bg;
+ var obj:SharedObject = SharedObject.getLocal("user_state");
+ obj.setProperty('background_url' ,String(bg.url));
+ obj.setProperty('background_name',String(bg.name));
+ obj.flush();
+ }
+
+ private function findBackgroundWithName(name:String):Object {
+ for each (var bg:Object in collection) {
+ if (bg.name==name) { return bg; }
+ }
+ return { url:'' };
+ }
+
+ [Bindable(event="collection_changed")]
+ public function getAvailableImagery():ArrayCollection {
+ var available:Array=[];
+ for each (var bg:Object in collection) {
+ if (bg.minlon) {
+ // if there's a bbox, check the current viewport intersects it
+ if (((_map.edge_l>bg.minlon && _map.edge_l<bg.maxlon) ||
+ (_map.edge_r>bg.minlon && _map.edge_r<bg.maxlon) ||
+ (_map.edge_l<bg.minlon && _map.edge_r>bg.maxlon)) &&
+ ((_map.edge_b>bg.minlat && _map.edge_b<bg.maxlat) ||
+ (_map.edge_t>bg.minlat && _map.edge_t<bg.maxlat) ||
+ (_map.edge_b<bg.minlat && _map.edge_t>bg.maxlat))) {
+ available.push(bg);
+ }
+ } else {
+ // if there's no bbox (i.e. global set), include it anyway
+ available.push(bg);
+ }
+ }
+ return new ArrayCollection(available);
+ }
+
+ }
+
+}
--- /dev/null
+package net.systemeD.potlatch2.collections {
+
+ import flash.events.EventDispatcher;
+ import flash.events.Event;
+ import flash.net.*;
+ import net.systemeD.halcyon.DebugURLRequest;
+ import net.systemeD.halcyon.Map;
+ import net.systemeD.potlatch2.FunctionKeyManager;
+ import net.systemeD.potlatch2.Yahoo;
+ import mx.collections.ArrayCollection;
+
+ public class Stylesheets extends EventDispatcher {
+
+ private static const GLOBAL_INSTANCE:Stylesheets = new Stylesheets();
+ public static function instance():Stylesheets { return GLOBAL_INSTANCE; }
+
+ public var collection:Array=[];
+ public var selected:Object={};
+ private var _map:Map;
+
+ /* Load catalogue file */
+
+ public function init(map:Map):void {
+ _map=map;
+ var request:DebugURLRequest = new DebugURLRequest("stylesheets.xml");
+ var loader:URLLoader = new URLLoader();
+ loader.addEventListener(Event.COMPLETE, onStylesheetsLoad);
+ loader.load(request.request);
+ }
+
+ private function onStylesheetsLoad(event:Event):void {
+ var xml:XML = new XML(URLLoader(event.target).data);
+ var saved_url:String = SharedObject.getLocal("user_state").data['stylesheet_url'];
+ var saved_name:String= SharedObject.getLocal("user_state").data['stylesheet_name'];
+ var isInMenu:Boolean=false, isSet:Boolean=false;
+
+ // first, build the menu from the stylesheet list.
+ // Also ensure the saved_url is in the menu (might be either saved from before, or supplied via loaderInfo)
+ collection=new Array();
+ for each(var set:XML in xml.stylesheet) {
+ var obj:Object={};
+ for (var a:String in set.children()) {
+ obj[set.child(a).name()]=set.child(a);
+ }
+ collection.push(obj);
+ if (obj.url==saved_url || (obj.name==saved_name && obj.name!='Custom')) { isInMenu=true; }
+ }
+ if (saved_url && !isInMenu) { collection.push({ name:saved_name, url:saved_url }); }
+
+ // pick a stylesheet to be set. It should be the saved one, if it is in the menu
+ // or alternatively the first one on the menu,
+ // or finally try 'potlatch.css'
+ for each (var ss:Object in collection) {
+ if (ss.name==saved_nameĀ || ss.url==saved_url) {
+ setStylesheet(ss.name, ss.url);
+ isSet = true;
+ break;
+ }
+ }
+ if (!isSet) {
+ if(collection.length > 0) {
+ var s:Object = collection[0];
+ setStylesheet(s.name, s.url);
+ } else {
+ //hit and hope. FIXME should this be an error state?
+ collection.push({ name:'Potlatch', url:'potlatch.css'});
+ setStylesheet('Potlatch','potlatch.css');
+ }
+ }
+ FunctionKeyManager.instance().registerListener('Map style',
+ function(o:String):void { setStylesheet(o,findStylesheetURLWithName(o)); });
+ dispatchEvent(new Event("collection_changed"));
+ }
+
+ public function setStylesheet(name:String,url:String):void {
+ _map.setStyle(url);
+ var obj:SharedObject = SharedObject.getLocal("user_state");
+ obj.setProperty("stylesheet_url",url);
+ obj.setProperty("stylesheet_name",name);
+ obj.flush();
+ }
+
+ private function findStylesheetURLWithName(name:String):String {
+ for each (var ss:Object in collection) {
+ if (ss.name==name) { return ss.url; }
+ }
+ return '';
+ }
+
+ [Bindable(event="collection_changed")]
+ public function getCollection():ArrayCollection {
+ return new ArrayCollection(collection);
+ }
+
+ }
+}
import net.systemeD.halcyon.Map;
import net.systemeD.halcyon.MapPaint;
import net.systemeD.halcyon.connection.*;
+ import net.systemeD.potlatch2.collections.Imagery;
import net.systemeD.potlatch2.EditController;
import net.systemeD.halcyon.Globals;
import net.systemeD.potlatch2.save.SaveManager;
protected function setSourceTag():void {
if (selectCount!=1) { return; }
- if (controller.imagerySelected && controller.imagerySelected.sourcetag) {
- firstSelected.setTag('source',controller.imagerySelected.sourcetag, MainUndoStack.getGlobalStack().addAction);
+ if (Imagery.instance().selected && Imagery.instance().selected.sourcetag) {
+ firstSelected.setTag('source',Imagery.instance().selected.sourcetag, MainUndoStack.getGlobalStack().addAction);
}
}
import net.systemeD.halcyon.connection.*;
import net.systemeD.potlatch2.*;
import net.systemeD.potlatch2.save.SaveManager;
+ import net.systemeD.potlatch2.collections.*;
import net.systemeD.potlatch2.controller.*;
import net.systemeD.potlatch2.help.*;
import net.systemeD.potlatch2.options.*;
}
if (objChanged) { obj.flush(); }
- // load imagery and style XML
- var request:DebugURLRequest = new DebugURLRequest("imagery.xml");
- var loader:URLLoader = new URLLoader();
- loader.addEventListener(Event.COMPLETE, onImageryLoad);
- loader.load(request.request);
-
- var request2:DebugURLRequest = new DebugURLRequest("stylesheets.xml");
- var loader2:URLLoader = new URLLoader();
- loader2.addEventListener(Event.COMPLETE, onStylesheetsLoad);
- loader2.load(request2.request);
-
// map backdrop object
var w:uint = map_area.width;
var h:uint = map_area.height;
Globals.vars.map_area.addEventListener(MouseEvent.MOUSE_MOVE, theMap.mouseMoveHandler);
Globals.vars.map_area.addEventListener(MouseEvent.MOUSE_DOWN, theMap.mouseDownHandler);
+ // initialise imagery and stylesheets
+ Imagery.instance().init(theMap,yahoo,loaderInfo.parameters['yahoo_default'] == 'true');
+ Stylesheets.instance().init(theMap);
+
// keyboard event attached to stage
stage.addEventListener(KeyboardEvent.KEY_UP, theMap.keyUpHandler);
}
}
- private function onImageryLoad(event:Event):void {
- var xml:XML = new XML(URLLoader(event.target).data);
- var saved:Object;
- if (SharedObject.getLocal("user_state").data['background_url']) {
- saved={ name: SharedObject.getLocal("user_state").data['background_name'],
- url: SharedObject.getLocal("user_state").data['background_url' ] };
- } else {
- saved={ url: ''};
- }
-
- var isSet:Boolean=false;
- var backgroundSet:Boolean = false;
-
- theController.imagery=new Array(
- { name: "None", url: "" },
- { name: "Yahoo", url: "yahoo", sourcetag: "Yahoo" } );
- for each(var set:XML in xml.set) {
- var obj:Object={};
- var a:XML;
- for each (a in set.@*) { obj[a.name().localName]=a.toString(); }
- for each (a in set.* ) { obj[a.name() ]=a.toString(); }
- theController.imagery.push(obj);
- if ((obj.url ==saved.url) ||
- (obj.name==saved.name && obj.name!='Custom')) { isSet=true; }
- }
-
- if (!isSet && saved.name && saved.url && saved.url!='' && saved.url!='yahoo') {
- theController.imagery.push(saved);
- isSet=true;
- }
-
- for each (var bg:Object in theController.imagery) {
- if (bg.name==saved.name || bg.url==saved.url) {
- setBackground(bg);
- backgroundSet = true;
- }
- }
-
- // For most contributors it's useful to set the background to yahoo by default, I reckon, but lets make it a config
- if (!backgroundSet && loaderInfo.parameters['yahoo_default'] == 'true') {
- setBackground(theController.imagery[1]);
- }
- FunctionKeyManager.instance().registerListener('Background imagery',
- function(o:String):void { setBackground(findBackgroundWithName(o)); });
- }
-
- public function setBackground(bg:Object):void {
- if (bg.url=='yahoo') { theMap.setBackground({url:''}); yahoo.show(); }
- else { theMap.setBackground(bg ); yahoo.hide(); }
- theController.imagerySelected=bg;
- var obj:SharedObject = SharedObject.getLocal("user_state");
- obj.setProperty('background_url' ,String(bg.url));
- obj.setProperty('background_name',String(bg.name));
- obj.flush();
- }
-
- private function findBackgroundWithName(name:String):Object {
- for each (var bg:Object in theController.imagery) {
- if (bg.name==name) { return bg; }
- }
- return { url:'' };
- }
-
- public function getAvailableImagery():Array {
- var available:Array=[];
- for each (var bg:Object in theController.imagery) {
- if (bg.minlon) {
- // if there's a bbox, check the current viewport intersects it
- if (((theMap.edge_l>bg.minlon && theMap.edge_l<bg.maxlon) ||
- (theMap.edge_r>bg.minlon && theMap.edge_r<bg.maxlon) ||
- (theMap.edge_l<bg.minlon && theMap.edge_r>bg.maxlon)) &&
- ((theMap.edge_b>bg.minlat && theMap.edge_b<bg.maxlat) ||
- (theMap.edge_t>bg.minlat && theMap.edge_t<bg.maxlat) ||
- (theMap.edge_b<bg.minlat && theMap.edge_t>bg.maxlat))) {
- available.push(bg);
- }
- } else {
- // if there's no bbox (i.e. global set), include it anyway
- available.push(bg);
- }
- }
- return available;
- }
-
- private function onStylesheetsLoad(event:Event):void {
- var xml:XML = new XML(URLLoader(event.target).data);
- var saved_url:String = SharedObject.getLocal("user_state").data['stylesheet_url'];
- var saved_name:String= SharedObject.getLocal("user_state").data['stylesheet_name'];
- var isInMenu:Boolean=false, isSet:Boolean=false;
-
- // first, build the menu from the stylesheet list.
- // Also ensure the saved_url is in the menu (might be either saved from before, or supplied via loaderInfo)
- theController.stylesheets=new Array();
- for each(var set:XML in xml.stylesheet) {
- var obj:Object={};
- for (var a:String in set.children()) {
- obj[set.child(a).name()]=set.child(a);
- }
- theController.stylesheets.push(obj);
- if (obj.url==saved_url || (obj.name==saved_name && obj.name!='Custom')) { isInMenu=true; }
- }
- if (saved_url && !isInMenu) { theController.stylesheets.push({ name:saved_name, url:saved_url }); }
-
- // pick a stylesheet to be set. It should be the saved one, if it is in the menu
- // or alternatively the first one on the menu,
- // or finally try 'potlatch.css'
- for each (var ss:Object in theController.stylesheets) {
- if (ss.name==saved_nameĀ || ss.url==saved_url) {
- setStylesheet(ss.name, ss.url);
- isSet = true;
- break;
- }
- }
- if (!isSet) {
- if(theController.stylesheets.length > 0) {
- var s:Object = theController.stylesheets[0];
- setStylesheet(s.name, s.url);
- } else {
- //hit and hope. FIXME should this be an error state?
- theController.stylesheets.push({ name:'Potlatch', url:'potlatch.css'});
- setStylesheet('Potlatch','potlatch.css');
- }
- }
- FunctionKeyManager.instance().registerListener('Map style',
- function(o:String):void { setStylesheet(o,findStylesheetURLWithName(o)); });
- }
-
- public function setStylesheet(name:String,url:String):void {
- theMap.setStyle(url);
- var obj:SharedObject = SharedObject.getLocal("user_state");
- obj.setProperty("stylesheet_url",url);
- obj.setProperty("stylesheet_name",name);
- obj.flush();
- }
- private function findStylesheetURLWithName(name:String):String {
- for each (var ss:Object in theController.stylesheets) {
- if (ss.name==name) { return ss.url; }
- }
- return '';
- }
private function scaleHandler(event:MapEvent):void {
dispatchEvent(new Event("rescale"));