import net.systemeD.potlatch2.EditController;
import net.systemeD.halcyon.Globals;
import net.systemeD.potlatch2.save.SaveManager;
+ import flash.ui.Keyboard;
+ /** 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.
+ *
+ * This abstract class has some behaviour that applies in most states, and lots of 'null' behaviour.
+ * */
public class ControllerState {
protected var controller:EditController;
return true;
}
+ /** When triggered by a mouse action such as a click, perform an action on the given entity, then move to a new state. */
public function processMouseEvent(event:MouseEvent, entity:Entity):ControllerState {
return this;
}
-
+
+ /** When triggered by a keypress, perform an action on the given entity, then move to a new state. */
public function processKeyboardEvent(event:KeyboardEvent):ControllerState {
return this;
}
public function enterState():void {}
public function exitState(newState:ControllerState):void {}
+ /** Represent the state in text for debugging. */
public function toString():String {
return "(No state)";
}
-
+ /** Default behaviour for the current state that should be called if state-specific action has been taken care of or ruled out. */
protected function sharedKeyboardEvents(event:KeyboardEvent):ControllerState {
switch (event.keyCode) {
case 66: setSourceTag(); break; // B - set source tag for current object
case 84: controller.tagViewer.togglePanel(); return null; // T - toggle tags panel
case 90: MainUndoStack.getGlobalStack().undo(); return null; // Z - undo
case 187: controller.tagViewer.addNewTag(); return null; // + - add tag
- case 107: controller.tagViewer.addNewTag(); return null; // numpad + - add tag
+ case Keyboard.NUMPAD_ADD: controller.tagViewer.addNewTag(); return null; // numpad + - add tag
}
return null;
}
+ /** Default behaviour for the current state that should be called if state-specific action has been taken care of or ruled out. */
protected function sharedMouseEvents(event:MouseEvent, entity:Entity):ControllerState {
var paint:MapPaint = getMapPaint(DisplayObject(event.target));
var focus:Entity = getTopLevelFocusEntity(entity);
return null;
}
+ /** Gets the way that the selected node is part of, if that makes sense. If not, return the node, or the way, or nothing. */
public static function getTopLevelFocusEntity(entity:Entity):Entity {
if ( entity is Node ) {
for each (var parent:Entity in entity.parentWays) {
return null;
}
+ /** Create a "repeat tags" action on the current entity, if possible. */
protected function repeatTags(object:Entity):void {
if (!controller.clipboards[object.getType()]) { return; }
object.suspend();
}
+ /** Create an action to add "source=*" tag to current entity based on background imagery. This is a convenient shorthand for users. */
protected function setSourceTag():void {
if (selectCount!=1) { return; }
if (Imagery.instance().selected && Imagery.instance().selected.sourcetag) {
import net.systemeD.halcyon.WayUI;
import net.systemeD.halcyon.Globals;
+ /** Behaviour that takes place while a way is selected includes: adding a node to the way, straightening/reshaping the way, dragging it... */
public class SelectedWay extends ControllerState {
+ /** The selected way itself. */
protected var initWay:Way;
private var clicked:Point; // did the user enter this state by clicking at a particular point?
private var wayList:Array; // list of ways to cycle through with '/' keypress
+ /**
+ * @param way The way that is now selected.
+ * @param point The location that was clicked.
+ * @param ways An ordered list of ways sharing a node, to make "way cycling" work. */
public function SelectedWay(way:Way, point:Point=null, ways:Array=null) {
initWay = way;
clicked = point;
wayList = ways;
}
+ /** Make this way selected, and update UI appropriately. */
protected function selectWay(way:Way):void {
if ( firstSelected is Way && Way(firstSelected)==way )
return;
initWay = way;
}
+ /** Tidy up UI as we transition to a new state without the current selection. */
protected function clearSelection(newState:ControllerState):void {
if ( selectCount ) {
controller.map.setHighlight(firstSelected, { selected: false, hover: false });
}
}
+ /** Behaviour includes: start drawing a new way, insert a node within this way, select an additional way */
override public function processMouseEvent(event:MouseEvent, entity:Entity):ControllerState {
if (event.type==MouseEvent.MOUSE_MOVE || event.type==MouseEvent.ROLL_OVER || event.type==MouseEvent.MOUSE_OUT) { return this; }
var focus:Entity = getTopLevelFocusEntity(entity);
return cs ? cs : this;
}
+ /** Behaviour includes: parallel way, repeat tags, reverse direction, simplify, cycle way selection, delete */
override public function processKeyboardEvent(event:KeyboardEvent):ControllerState {
switch (event.keyCode) {
- case 80: return new SelectedParallelWay(firstSelected as Way);
- case 82: repeatTags(firstSelected); return this;
- case 86: Way(firstSelected).reverseNodes(MainUndoStack.getGlobalStack().addAction); return this;
- case 89: Simplify.simplify(firstSelected as Way, controller.map, true); return this;
- case 191: return cycleWays();
- case Keyboard.BACKSPACE: if (event.shiftKey) { return deleteWay(); } break;
+ case 80: /* P */ return new SelectedParallelWay(firstSelected as Way);
+ case 82: /* R */ repeatTags(firstSelected); return this;
+ case 86: /* V */ Way(firstSelected).reverseNodes(MainUndoStack.getGlobalStack().addAction); return this;
+ case 89: /* Y */ Simplify.simplify(firstSelected as Way, controller.map, true); return this;
+ case 191: /* / */ return cycleWays();
+ case Keyboard.BACKSPACE:
case Keyboard.DELETE: if (event.shiftKey) { return deleteWay(); } break;
}
var cs:ControllerState = sharedKeyboardEvents(event);
return new SelectedWay(wayList[0], clicked, wayList);
}
+ /** Perform deletion of currently selected way. */
public function deleteWay():ControllerState {
controller.map.setHighlightOnNodes(firstSelected as Way, {selectedway: false});
selectedWay.remove(MainUndoStack.getGlobalStack().addAction);
return new NoSelection();
}
+ /** Officially enter this state by marking the previously nominated way as selected. */
override public function enterState():void {
selectWay(initWay);
controller.map.setPurgable(selection,false);
Globals.vars.root.addDebug("**** -> "+this+" "+firstSelected.id);
}
+ /** Officially leave the state, remembering the current way's tags for future repeats. */
+ // TODO: tweak this so that repeat tags aren't remembered if you only select a way in order to branch off it. (a la PL1)
override public function exitState(newState:ControllerState):void {
if (firstSelected.hasTags()) {
controller.clipboards['way']=firstSelected.getTagsCopy();
Globals.vars.root.addDebug("**** <- "+this);
}
+ /** @return "SelectedWay" */
override public function toString():String {
return "SelectedWay";
}