public var scale:uint=14;
/** current scaling factor for lon/latp */
public var scalefactor:Number=MASTERSCALE;
- public var bigedge_l:Number= 999999; // area of largest whichways
- public var bigedge_r:Number=-999999; // |
- public var bigedge_b:Number= 999999; // |
- public var bigedge_t:Number=-999999; // |
public var edge_l:Number; // current bounding box
public var edge_r:Number; // |
*/
public function download():void {
this.dispatchEvent(new MapEvent(MapEvent.DOWNLOAD, {minlon:edge_l, maxlon:edge_r, maxlat:edge_t, minlat:edge_b} ));
-
- if (edge_l>=bigedge_l && edge_r<=bigedge_r &&
- edge_b>=bigedge_b && edge_t<=bigedge_t) { return; } // we have already loaded this area, so ignore
- bigedge_l=edge_l; bigedge_r=edge_r;
- bigedge_b=edge_b; bigedge_t=edge_t;
- if (connection.waycount>1000) {
- connection.purgeOutside(edge_l,edge_r,edge_t,edge_b);
- }
connection.loadBbox(edge_l,edge_r,edge_t,edge_b);
// Do the same for vector layers
private var traces:Array = [];
private var nodePositions:Object = {};
protected var traces_loaded:Boolean = false;
+ private var loadedBboxes:Array = [];
+
+ /** maximum number of ways to keep in memory before purging */
+ protected const MAXWAYS:uint=3000;
protected function get nextNegative():Number {
return negativeID--;
return modified;
}
+ // Keep track of the bboxes we've loaded
+
+ /** Has the data within this bbox already been loaded? */
+ protected function isBboxLoaded(left:Number,right:Number,top:Number,bottom:Number):Boolean {
+ var l:Number,r:Number,t:Number,b:Number;
+ for each (var box:Array in loadedBboxes) {
+ l=box[0]; r=box[1]; t=box[2]; b=box[3];
+ if (left>=l && left<=r && right>=l && right<=r && top>=b && top<=t && bottom>=b && bottom<=t) {
+ return true;
+ }
+ }
+ return false;
+ }
+ /** Mark that bbox is loaded */
+ protected function markBboxLoaded(left:Number,right:Number,top:Number,bottom:Number):void {
+ if (isBboxLoaded(left,right,top,bottom)) return;
+ loadedBboxes.push([left,right,top,bottom]);
+ }
+ /** Purge all data if number of ways exceeds limit */
+ public function purgeIfFull(left:Number,right:Number,top:Number,bottom:Number):void {
+ if (waycount<=MAXWAYS) return;
+ purgeOutside(left,right,top,bottom);
+ loadedBboxes=([left,right,top,bottom]);
+ }
+
// Changeset tracking
protected function setActiveChangeset(changeset:Changeset):void {
}
}
+ markBboxLoaded(minlon,maxlon,maxlat,minlat);
registerPOINodes();
dispatchEvent(new Event(LOAD_COMPLETED));
}
override public function loadBbox(left:Number,right:Number,
top:Number,bottom:Number):void {
+ purgeIfFull(left,right,top,bottom);
+ if (isBboxLoaded(left,right,top,bottom)) return;
+
+ // enlarge bbox by 20% on each edge
+ var xmargin:Number=(right-left)/5;
+ var ymargin:Number=(top-bottom)/5;
+ left-=xmargin; right+=xmargin;
+ bottom-=ymargin; top+=ymargin;
+
var mapVars:URLVariables = new URLVariables();
mapVars.bbox= left+","+bottom+","+right+","+top;
/** Assign a new selected Entity, and update editing controls appropriately. */
public function init(entity:Entity):void {
+ if (selectedEntity==entity) return;
+ if (selectedEntity) selectedEntity.removeEventListener(Connection.TAG_CHANGED, tagChanged);
+
+ selectedEntity=entity;
+ if (!selectedEntity) return;
+ selectedEntity.addEventListener(Connection.TAG_CHANGED, tagChanged, false, 0, true);
+
if ( tagDataProvider == null ) {
tagDataProvider = new ArrayCollection();
dataProvider = tagDataProvider;
+ } else {
+ tagDataProvider.removeAll();
}
- if (selectedEntity==entity) return;
- selectedEntity=entity;
- updateTagDataProvider(true);
- }
-
- private function updateTagDataProvider(force:Boolean=false):void {
- if (editedItemPosition && !force) return;
-
- tagDataProvider.removeAll();
- if (selectedEntity==null) { return; }
var tags:Array = selectedEntity.getTagArray();
tags.sortOn("key");
for each(var tag:Tag in tags) { tagDataProvider.addItem(tag); }
}
+ /** Update dataProvider in response to a tag being edited or removed */
+ private function tagChanged(event:TagEvent):void {
+ var set:Boolean=false;
+ for (var i:uint=0; i<tagDataProvider.length; i++) {
+ if (tagDataProvider[i].key==event.oldKey) {
+ if (event.newValue && event.key) {
+ if (!set) {
+ // this entry in the dataProvider has changed
+ tagDataProvider[i].key=event.key;
+ tagDataProvider[i].value=event.newValue;
+ set=true;
+ } else {
+ // trap duplicate tags
+ tagDataProvider.removeItemAt(i);
+ }
+ } else {
+ // this entry in the dataProvider has been deleted
+ tagDataProvider.removeItemAt(i);
+ }
+ }
+ }
+ // tell Flex to redraw the grid because we've changed a tag
+ invalidateList();
+ }
+
/** Create editing controls for a new key/value pair, with default values. */
public function addNewTag():void {
var newKey:String = "(new tag)";
public function removeTag():void {
var k:String = selectedItem.key;
selectedEntity.setTag(k, null, MainUndoStack.getGlobalStack().addAction);
- updateTagDataProvider();
}
/** Return the type ("node", "way", "relation") of the selected entity. */
}
private function tagChanged(event:TagEvent):void {
- if(selectedEntity != null && selectedEntity is EntityCollection) {
- setupMultiAdvanced(selectedEntity);
- return;
- }
-
refreshFeatureIcon();
- // ** FIXME - changing tags on Advanced tab should update simple view
- // (but putting initialiseEditors here breaks other stuff, because it causes
- // the Basic pane to be selected)
-
- // if the advancedTagGrid has already been set up, it needs to be refreshed.
- // FIXME make this better, maybe advancedTagGrid should be event listening.
- if(advancedContainer.initialized) {
- checkAdvanced();
- }
}
public function loadFeatures():void {