if (!wayuis[way.id]) {
wayuis[way.id]=new WayUI(way,this);
way.addEventListener(Connection.WAY_DELETED, wayDeleted);
+ } else {
+ wayuis[way.id].redraw();
}
return wayuis[way.id];
}
import flash.events.Event;
import net.systemeD.halcyon.Globals;
import net.systemeD.halcyon.connection.actions.*;
+ import net.systemeD.halcyon.AttentionEvent;
import net.systemeD.halcyon.MapEvent;
public class Connection extends EventDispatcher {
no: cancelUpload }));
}
- public function retryUpload():void { uploadChanges(); }
- public function cancelUpload():void { return; }
+ public function retryUpload(e:Event=null):void {
+ removeEventListener(LOAD_COMPLETED,retryUpload);
+ uploadChanges();
+ }
+ public function cancelUpload():void {
+ return;
+ }
public function retryUploadWithNewChangeset():void {
// ** FIXME: we need to move the create-changeset-then-upload logic out of SaveDialog
}
public function goToEntity(entity:Entity):void {
- dispatchEvent(new MapEvent(MapEvent.ATTENTION, { entity: entity }));
+ dispatchEvent(new AttentionEvent(AttentionEvent.ATTENTION, entity));
}
public function revertBeforeUpload(entity:Entity):void {
- // ** FIXME: implement a 'revert entity' method, then retry upload on successful download
+ addEventListener(LOAD_COMPLETED,retryUpload);
+ loadEntity(entity);
}
public function deleteBeforeUpload(entity:Entity):void {
var a:CompositeUndoableAction = new CompositeUndoableAction("Delete refs");
public function loadBbox(left:Number, right:Number,
top:Number, bottom:Number):void {
}
-
+ public function loadEntity(entity:Entity):void {}
public function setAuthToken(id:Object):void {}
public function setAccessToken(key:String, secret:String):void {}
public function createChangeset(tags:Object):void {}
}
protected function loadedMap(event:Event):void {
- dispatchEvent(new Event(LOAD_COMPLETED));
-
var map:XML = new XML(URLLoader(event.target).data);
var id:Number;
var version:uint;
var node:Node, newNode:Node;
var unusedNodes:Object={};
- var minlon:Number=map.bounds.@minlon;
- var maxlon:Number=map.bounds.@maxlon;
- var minlat:Number=map.bounds.@minlat;
- var maxlat:Number=map.bounds.@maxlat;
+ var minlon:Number, maxlon:Number, minlat:Number, maxlat:Number;
+ var singleEntityRequest:Boolean=true;
+ if (map.bounds.@minlon.length()) {
+ minlon=map.bounds.@minlon;
+ maxlon=map.bounds.@maxlon;
+ minlat=map.bounds.@minlat;
+ maxlat=map.bounds.@maxlat;
+ singleEntityRequest=false;
+ }
for each(var relData:XML in map.relation) {
id = Number(relData.@id);
Number(nodeData.@uid),
nodeData.@timestamp);
- if ( node == null || !node.loaded) {
+ if ( singleEntityRequest ) {
+ // it's a revert request, so create/update the node
+ setOrUpdateNode(newNode, true);
+ } else if ( node == null || !node.loaded) {
+ // the node didn't exist before, so create/update it
newNode.parentsLoaded=newNode.within(minlon,maxlon,minlat,maxlat);
setOrUpdateNode(newNode, true);
} else {
timestamp = data.@timestamp;
var way:Way = getWay(id);
- if ( way == null || !way.loaded ) {
+ if ( way == null || !way.loaded || singleEntityRequest) {
var nodes:Array = [];
for each(var nd:XML in data.nd) {
var nodeid:Number=Number(nd.@ref)
}
registerPOINodes();
+ dispatchEvent(new Event(LOAD_COMPLETED));
}
protected function registerPOINodes():void {
import flash.net.*;
import org.iotashan.oauth.*;
+ import net.systemeD.halcyon.AttentionEvent;
import net.systemeD.halcyon.MapEvent;
/**
var mapRequest:URLRequest = new URLRequest(Connection.apiBaseURL+"map");
mapRequest.data = mapVars;
- var mapLoader:URLLoader = new URLLoader();
- mapLoader.addEventListener(Event.COMPLETE, loadedMap);
- mapLoader.addEventListener(IOErrorEvent.IO_ERROR, errorOnMapLoad);
- mapLoader.addEventListener(HTTPStatusEvent.HTTP_STATUS, mapLoadStatus);
- mapLoader.load(mapRequest);
- dispatchEvent(new Event(LOAD_STARTED));
+ sendLoadRequest(mapRequest);
+ }
+
+ override public function loadEntity(entity:Entity):void {
+ var url:String=Connection.apiBaseURL + entity.getType() + "/" + entity.id;
+ if (entity is Relation || entity is Way) url+="/full";
+ sendLoadRequest(new URLRequest(url));
+ }
+
+ private function sendLoadRequest(request:URLRequest):void {
+ var mapLoader:URLLoader = new URLLoader();
+ mapLoader.addEventListener(Event.COMPLETE, loadedMap);
+ mapLoader.addEventListener(IOErrorEvent.IO_ERROR, errorOnMapLoad);
+ mapLoader.addEventListener(HTTPStatusEvent.HTTP_STATUS, mapLoadStatus);
+ mapLoader.load(request);
+ dispatchEvent(new Event(LOAD_STARTED));
}
private function errorOnMapLoad(event:Event):void {
closeActiveChangeset();
}
- private function changesetCloseComplete(event:Event):void { }
- private function changesetCloseError(event:Event):void { }
- // ** TODO: when we get little floating warnings, we can send a happy or sad one up
+ private function changesetCloseComplete(event:Event):void {
+ dispatchEvent(new AttentionEvent(AttentionEvent.ALERT, null, "Changeset closed"));
+ }
+ private function changesetCloseError(event:Event):void {
+ dispatchEvent(new AttentionEvent(AttentionEvent.ALERT, null, "Couldn't close changeset", 1));
+ }
private function signedOAuthURL(url:String, method:String):String {
// method should be PUT, GET, POST or DELETE
case '409 Conflict':
if (message.match(/changeset/i)) { throwChangesetError(message); return; }
matches=message.match(/mismatch.+had: (\d+) of (\w+) (\d+)/i);
- if (matches) { throwConflictError(findEntity(matches[3],matches[2]), Number(matches[1]), message); return; }
+ if (matches) { throwConflictError(findEntity(matches[2],matches[3]), Number(matches[1]), message); return; }
break;
case '410 Gone':
import net.systemeD.halcyon.Globals;
import net.systemeD.potlatch2.save.SaveManager;
import flash.ui.Keyboard;
+ import mx.controls.Alert;
+ import mx.events.CloseEvent;
+
/** Represents a particular state of the controller, such as "dragging a way" or "nothing selected". Key methods are
* processKeyboardEvent and processMouseEvent which take some action, and return a new state for the controller.
*
case 83: SaveManager.saveChanges(); break; // S - save
case 84: controller.tagViewer.togglePanel(); return null; // T - toggle tags panel
case 90: MainUndoStack.getGlobalStack().undo(); return null; // Z - undo
+ case Keyboard.ESCAPE: revertSelection(); break; // ESC - revert to server version
case Keyboard.NUMPAD_ADD: // + - add tag
case 187: controller.tagViewer.selectAdvancedPanel(); // |
controller.tagViewer.addNewTag(); return null; // |
controller.updateSelectionUI();
}
+ /** Revert all selected items to previously saved state, via a dialog box. */
+ protected function revertSelection():void {
+ if (selectCount==0) return;
+ Alert.show("Revert selected items to the last saved version, discarding your changes?","Are you sure?",Alert.YES | Alert.CANCEL,null,revertHandler);
+ }
+ protected function revertHandler(event:CloseEvent):void {
+ if (event.detail==Alert.CANCEL) return;
+ for each (var item:Entity in _selection) {
+ controller.connection.loadEntity(item);
+ }
+ }
+
// Selection getters
public function get selectCount():uint {