From 26b9e06fef2b9f9b06eb45f2468879ae504fb346 Mon Sep 17 00:00:00 2001 From: Richard Fairhurst Date: Fri, 17 Jun 2011 16:48:50 +0100 Subject: [PATCH] Prevent single-node ways from being created by undo. Could be polished more but the undo system makes it enough of a brainfuck that this'll do for now. --- .../halcyon/connection/MainUndoStack.as | 13 +++++++ net/systemeD/halcyon/connection/Way.as | 4 +- .../connection/actions/AddNodeToWayAction.as | 37 +++++++++++++++++-- .../connection/actions/DeleteWayAction.as | 2 +- .../potlatch2/controller/NoSelection.as | 1 + potlatch2.mxml | 3 +- 6 files changed, 52 insertions(+), 8 deletions(-) diff --git a/net/systemeD/halcyon/connection/MainUndoStack.as b/net/systemeD/halcyon/connection/MainUndoStack.as index be75b6dc..38f87ff0 100644 --- a/net/systemeD/halcyon/connection/MainUndoStack.as +++ b/net/systemeD/halcyon/connection/MainUndoStack.as @@ -103,6 +103,12 @@ package net.systemeD.halcyon.connection { return false; } } + + public function removeLastIfAction(action:Class):void { + if (undoActions.length && undoActions[undoActions.length-1] is action) { + undoActions.pop(); + } + } [Bindable(event="new_undo_item")] public function getUndoDescription():String { @@ -111,6 +117,13 @@ package net.systemeD.halcyon.connection { return null; } + [Bindable(event="new_redo_item")] + public function getRedoDescription():String { + if (redoActions.length==0) return null; + if (redoActions[redoActions.length-1].name) return redoActions[redoActions.length-1].name; + return null; + } + /** * Takes the action most recently undone, does it, and adds it to the undo stack */ diff --git a/net/systemeD/halcyon/connection/Way.as b/net/systemeD/halcyon/connection/Way.as index d5f991cf..0f97958b 100644 --- a/net/systemeD/halcyon/connection/Way.as +++ b/net/systemeD/halcyon/connection/Way.as @@ -94,12 +94,12 @@ package net.systemeD.halcyon.connection { } public function appendNode(node:Node, performAction:Function):uint { - if (node!=getLastNode()) performAction(new AddNodeToWayAction(this, node, nodes, -1)); + insertNode(nodes.length, node, performAction); return nodes.length + 1; } public function prependNode(node:Node, performAction:Function):uint { - if (node!=getFirstNode()) performAction(new AddNodeToWayAction(this, node, nodes, 0)); + insertNode(0, node, performAction); return nodes.length + 1; } diff --git a/net/systemeD/halcyon/connection/actions/AddNodeToWayAction.as b/net/systemeD/halcyon/connection/actions/AddNodeToWayAction.as index 7e291e93..185bf559 100644 --- a/net/systemeD/halcyon/connection/actions/AddNodeToWayAction.as +++ b/net/systemeD/halcyon/connection/actions/AddNodeToWayAction.as @@ -6,6 +6,7 @@ package net.systemeD.halcyon.connection.actions { private var node:Node; private var nodeList:Array; private var index:int; + private var firstNode:Node; public function AddNodeToWayAction(way:Way, node:Node, nodeList:Array, index:int) { super(way, "Add node "+node.id+" to"); @@ -16,8 +17,17 @@ package net.systemeD.halcyon.connection.actions { public override function doAction():uint { var way:Way = entity as Way; - if ( index == -1 ) - index = nodeList.length; + + // undelete way if it was deleted before (only happens on redo) + if (way.deleted) { + way.setDeletedState(false); + if (!firstNode.hasParentWays) firstNode.connection.unregisterPOI(firstNode); + firstNode.addParent(way); + way.connection.dispatchEvent(new EntityEvent(Connection.NEW_WAY, way)); + } + + // add node + if ( index == -1 ) index = nodeList.length; node.addParent(way); nodeList.splice(index, 0, node); markDirty(); @@ -29,13 +39,32 @@ package net.systemeD.halcyon.connection.actions { public override function undoAction():uint { var way:Way = entity as Way; + + // ** FIXME: if the user undoes adding the 2nd node, then we delete the way and create a POI from the + // one remaining node (see below). _However_, when we delete the way, we also need to remove + // it from any relations... and to do that, this needs to be a CompositeUndoableAction. + // Which it isn't (because we want all the markDirty/markClean stuff). So, for now, we'll + // simply refuse to undo adding the 2nd node if the way is in any relations. (This should + // be a vanishingly small case anyway, because usually the AddMemberToRelationAction will + // have been undone already.) + if (way.length==2 && way.parentRelations.length) return FAIL; + + // remove node var removed:Array=nodeList.splice(index, 1); if (nodeList.indexOf(removed[0])==-1) { removed[0].removeParent(way); } markClean(); way.dispatchEvent(new WayNodeEvent(Connection.WAY_NODE_REMOVED, removed[0], way, index)); - return SUCCESS; + // delete way if it's now 1-length, and convert the one remaining node to a POI + if (way.length==1) { + way.setDeletedState(true); + way.dispatchEvent(new EntityEvent(Connection.WAY_DELETED, way)); + firstNode=way.getNode(0); + firstNode.removeParent(way); + if (!firstNode.hasParentWays) firstNode.connection.registerPOI(firstNode); + MainUndoStack.getGlobalStack().removeLastIfAction(BeginWayAction); + } + return SUCCESS; } } } - diff --git a/net/systemeD/halcyon/connection/actions/DeleteWayAction.as b/net/systemeD/halcyon/connection/actions/DeleteWayAction.as index 331826a8..f2fd1bc6 100644 --- a/net/systemeD/halcyon/connection/actions/DeleteWayAction.as +++ b/net/systemeD/halcyon/connection/actions/DeleteWayAction.as @@ -57,7 +57,7 @@ package net.systemeD.halcyon.connection.actions { markClean(); } entity.connection.dispatchEvent(new EntityEvent(Connection.NEW_WAY, way)); - effects.undoAction(); + if (effects) effects.undoAction(); for each(var node:Node in oldNodeList) { nodeList.push(node); node.addParent(way); diff --git a/net/systemeD/potlatch2/controller/NoSelection.as b/net/systemeD/potlatch2/controller/NoSelection.as index 5c5072d2..b780bd25 100644 --- a/net/systemeD/potlatch2/controller/NoSelection.as +++ b/net/systemeD/potlatch2/controller/NoSelection.as @@ -25,6 +25,7 @@ package net.systemeD.potlatch2.controller { if (event.type==MouseEvent.MOUSE_UP && (focus==null || (paint && paint.isBackground)) && map.dragstate!=map.DRAGGING) { map.dragstate=map.NOT_DRAGGING; + // ** FIXME: BeginWayAction ought to be a discrete class var undo:CompositeUndoableAction = new BeginWayAction(); var conn:Connection = layer.connection; var startNode:Node = conn.createNode( diff --git a/potlatch2.mxml b/potlatch2.mxml index 055f0a6f..4754b11b 100644 --- a/potlatch2.mxml +++ b/potlatch2.mxml @@ -51,7 +51,8 @@ enabled="{MainUndoStack.getGlobalStack().canUndo()}" toolTip="{MainUndoStack.getGlobalStack().getUndoDescription() ? 'Undo '+MainUndoStack.getGlobalStack().getUndoDescription() : 'Undo last action'}" /> + enabled="{MainUndoStack.getGlobalStack().canRedo()}" + toolTip="{MainUndoStack.getGlobalStack().getRedoDescription() ? 'Redo '+MainUndoStack.getGlobalStack().getRedoDescription() : 'Redo last action'}" /> -- 2.36.1