- to enable multiple Maps to be shown on-screen (e.g. for junction editor)
- to bring Connection and VectorLayer code together
-Current status:
-- it loads a map and lets you edit it!
-- VectorLayers (of any shape) will not work - lots of them are commented out
+Current known problems:
+- pull-through creates the way, but doesn't draw it
+- AttentionEvents don't work
+
+To check:
+- MapDust
+- VectorLayers from GPX
+- VectorLayers from shapefiles
- Save/OAuth not tested
+- removeLayer in MapPaint.as should blank - does it?
== Changes overall ==
Map.as becomes a collection of MapPaint objects, all with the same lat/long/scale
(plus a backdrop sprite and a background imagery sprite)
+
Map.editableLayer returns a reference to the single MapPaint object where isBackground is false
MapPaint.as gains a reference to a Connection - i.e. the source data for this layer
-== Stuff to look at ==
+== Code tidying ==
There are lots more of these throughout the code, marked with fixmes of the form '>>>> REFACTOR'
-MapPaint.as
-- wayuis, nodeuis etc. should ideally be private
-- removeLayer should blank
-
-Global changes:
- remove all back-references to Map except where necessary for lat/long/scale
- getParam is messy - stuff sent via flashvars needs somewhere to live: currently in Globals which is ugly
-- AttentionEvents are derelict and commented out
- tileset/setbackground stuff is screwed up again and needs refactoring a little
/** The MapCSS rules used for drawing entities. */
public var ruleset:RuleSet;
/** WayUI objects attached to Way entities that are currently visible. */
- public var wayuis:Object=new Object(); // sprites for ways and (POI/tagged) nodes
+ private var wayuis:Object=new Object();
/** NodeUI objects attached to POI/tagged node entities that are currently visible. */
- // confirm this - it seems to me all nodes in ways get nodeuis? --Steve B
- public var nodeuis:Object=new Object();
+ private var nodeuis:Object=new Object();
/** MarkerUI objects attached to Marker entities that are currently visible. */
- public var markeruis:Object=new Object();
+ private var markeruis:Object=new Object();
/** Is this a background layer or the core paint object? */
public var isBackground:Boolean = true;
/** Hash of index->position */
return s;
}
+ /** Redraw all entities */
public function redraw():void {
for each (var w:WayUI in wayuis) { w.recalculate(); w.invalidateStyleList(); w.redraw(); }
/* sometimes (e.g. in Map.setStyle) Mappaint.redrawPOIs() is called immediately afterwards anyway. FIXME? */
for each (var m:MarkerUI in markeruis) { m.invalidateStyleList(); m.redraw(); }
}
- /** Redraw nodes and markers */
+ /** Redraw nodes and markers only */
public function redrawPOIs():void {
for each (var p:NodeUI in nodeuis) { p.invalidateStyleList(); p.redraw(); }
for each (var m:MarkerUI in markeruis) { m.invalidateStyleList(); m.redraw(); }
}
+ /** Redraw a single entity if it exists */
+ public function redrawEntity(e:Entity):Boolean {
+ if (e is Way && wayuis[e.id]) wayuis[e.id].redraw();
+ else if (e is Node && nodeuis[e.id]) nodeuis[e.id].redraw();
+ else if (e is Marker && markeruis[e.id]) markeruis[e.id].redraw();
+ else return false;
+ return true;
+ }
+
/** Switch to new MapCSS. */
public function setStyle(url:String):void {
style = url;
// ==================== End of code moved from Map.as
+ /** Find all ways whose WayUI passes a given screen co-ordinate. */
+
+ public function findWaysAtPoint(x:Number, y:Number, ignore:Way=null):Array {
+ var ways:Array=[]; var w:Way;
+ for each (var wayui:WayUI in wayuis) {
+ w=wayui.hitTest(x,y);
+ if (w && w!=ignore) { ways.push(w); }
+ }
+ return ways;
+ }
+
/**
* Transfers an entity from this layer into another layer
* @param entity The entity from this layer that you want to transfer.
if (!event.node.hasParent(event.way)) {
event.node.removeEventListener(Connection.NODE_MOVED, nodeMoved);
}
- if (paint.nodeuis[event.node.id]) {
- paint.nodeuis[event.node.id].redraw();
- }
+ paint.redrawEntity(event.node);
recalculate();
redraw();
redrawMultis();
for each (var m:Relation in multis) {
var outers:Array=m.findMembersByRole('outer');
for each (var e:Entity in outers) {
- if (e is Way && paint.wayuis[e.id]) {
- paint.wayuis[e.id].redraw();
- }
+ paint.redrawEntity(e);
}
}
}
public function setHighlightOnNodes(settings:Object):void {
for (var i:uint = 0; i < Way(entity).length; i++) {
var node:Node = Way(entity).getNode(i);
- if (paint.nodeuis[node.id]) {
- // Speed things up a bit by only setting the highlight if it's either:
- // a) an "un-highlight" (so we don't leave mess behind when scrolling)
- // b) currently onscreen
- // Currently this means if you highlight an object then scroll, nodes will scroll
- // into view that should be highlighted but aren't.
- if (settings.hoverway==false ||
- settings.selectedway==false ||
- node.lat >= paint.map.edge_b && node.lat <= paint.map.edge_t &&
- node.lon >= paint.map.edge_l && node.lon <= paint.map.edge_r) {
- paint.nodeuis[node.id].setHighlight(settings); // Triggers redraw if required
- }
- if (settings.selectedway || settings.hoverway)
- nodehighlightsettings=settings;
- else
- nodehighlightsettings={};
+ // Speed things up a bit by only setting the highlight if it's either:
+ // a) an "un-highlight" (so we don't leave mess behind when scrolling)
+ // b) currently onscreen
+ // Currently this means if you highlight an object then scroll, nodes will scroll
+ // into view that should be highlighted but aren't.
+ if (settings.hoverway==false ||
+ settings.selectedway==false ||
+ node.within(paint.map.edge_l, paint.map.edge_r, paint.map.edge_t, paint.map.edge_b)) {
+ paint.setHighlight(node,settings); // Triggers redraw if required
}
+ if (settings.selectedway || settings.hoverway)
+ nodehighlightsettings=settings;
+ else
+ nodehighlightsettings={};
}
}
}
private function addNode(selectedWay:Way,event:MouseEvent):int {
- // find which other ways are under the mouse
- var ways:Array=[]; var w:Way;
- for each (var wayui:WayUI in editableLayer.wayuis) {
- w=wayui.hitTest(event.stageX, event.stageY);
- if (w && w!=selectedWay) { ways.push(w); }
- }
-
+ var ways:Array = editableLayer.findWaysAtPoint(event.stageX, event.stageY, selectedWay);
var lat:Number = controller.map.coord2lat(event.localY);
var lon:Number = controller.map.coord2lon(event.localX);
var undo:CompositeUndoableAction = new CompositeUndoableAction("Insert node");
var node:Node = selectedWay.connection.createNode({}, lat, lon, undo.push);
var index:int = selectedWay.insertNodeAtClosestPosition(node, true, undo.push);
- for each (w in ways) { w.insertNodeAtClosestPosition(node, true, undo.push); }
+ for each (var w:Way in ways) { w.insertNodeAtClosestPosition(node, true, undo.push); }
MainUndoStack.getGlobalStack().addAction(undo);
return index;
}
import flash.geom.Point;
import flash.ui.Keyboard;
- import net.systemeD.halcyon.WayUI;
import net.systemeD.halcyon.connection.*;
import net.systemeD.potlatch2.tools.Quadrilateralise;
import net.systemeD.potlatch2.tools.Simplify;
if (!clicked || (wayList && wayList.length<2)) { return this; }
if (!wayList) {
- wayList=[initWay];
- for each (var wayui:WayUI in editableLayer.wayuis) {
- var w:Way=wayui.hitTest(clicked.x, clicked.y);
- if (w && w!=initWay) { wayList.push(w); }
- }
+ wayList=[initWay].concat(editableLayer.findWaysAtPoint(clicked.x,clicked.y,initWay));
}
wayList=wayList.slice(1).concat(wayList[0]);
// Find the new way's index of the currently "selected" node, to facilitate keyboard navigation
/** Attempt to either merge the currently selected node with another very nearby node, or failing that,
* attach it mid-way along a very nearby way. */
+ // FIXME: why are we only merging one node at once? after all, shift-click to insert a node adds into all ways
public function join():ControllerState {
var p:Point = new Point(controller.map.lon2coord(Node(firstSelected).lon),
controller.map.latp2coord(Node(firstSelected).latp));
var q:Point = map.localToGlobal(p);
// First, look for POI nodes in 20x20 pixel box around the current node
+ // FIXME: why aren't we using a hitTest for this?
var hitnodes:Array = editableLayer.connection.getObjectsByBbox(
map.coord2lon(p.x-10),
map.coord2lon(p.x+10),
}
}
- var ways:Array=[]; var w:Way;
- for each (var wayui:WayUI in editableLayer.wayuis) {
- w=wayui.hitTest(q.x, q.y);
- if (w && w!=selectedWay) {
+ var ways:Array=editableLayer.findWaysAtPoint(q.x, q.y, selectedWay);
+ for each (var w:Way in ways) {
// hit a way, now let's see if we hit a specific node
- for (var i:uint = 0; i < w.length; i++) {
- n = w.getNode(i);
- var x:Number = map.lon2coord(n.lon);
- var y:Number = map.latp2coord(n.latp);
- if (n != selectedNode && Math.abs(x-p.x) + Math.abs(y-p.y) < 10) {
- return doMergeNodes(n);
- }
- }
- ways.push(w);
- }
+ for (var i:uint = 0; i < w.length; i++) {
+ n = w.getNode(i);
+ var x:Number = map.lon2coord(n.lon);
+ var y:Number = map.latp2coord(n.latp);
+ if (n != selectedNode && Math.abs(x-p.x) + Math.abs(y-p.y) < 10) {
+ return doMergeNodes(n);
+ }
+ }
}
// No nodes hit, so join our node onto any overlapping ways.
// only merge one node at a time - too confusing otherwise?
var msg:String = "Nodes merged."
if (MergeNodesAction.lastProblemTags) {
+ // FIXME: ugh, just ugh.
msg += " *Warning* The following tags conflicted and need attention: " + MergeNodesAction.lastProblemTags;
}
// somethingorother.dispatchEvent(new AttentionEvent(AttentionEvent.ALERT, null, msg));