Unify selection ControllerStates so they can work on either background or editable...
[potlatch2.git] / net / systemeD / potlatch2 / controller / SelectedMultiple.as
1 package net.systemeD.potlatch2.controller {
2         import flash.events.*;
3         
4         import net.systemeD.halcyon.AttentionEvent;
5         import net.systemeD.halcyon.connection.*;
6         import net.systemeD.halcyon.connection.actions.MergeWaysAction;
7     import net.systemeD.halcyon.MapPaint;
8
9         public class SelectedMultiple extends ControllerState {
10                 protected var initSelection:Array;
11                 
12                 public function SelectedMultiple(sel:Array, layer:MapPaint=null) {
13                         if (layer) this.layer=layer;
14                         initSelection=sel.concat();
15                 }
16
17                 override public function processMouseEvent(event:MouseEvent, entity:Entity):ControllerState {
18                         if (event.type==MouseEvent.MOUSE_MOVE || event.type==MouseEvent.ROLL_OVER || event.type==MouseEvent.MOUSE_OUT) { return this; }
19                         var focus:Entity = getTopLevelFocusEntity(entity);
20
21                         if ( event.type == MouseEvent.MOUSE_DOWN && entity && event.ctrlKey ) {
22                                 // modify selection
23                                 layer.setHighlight(entity, { selected: toggleSelection(entity) });
24                                 controller.updateSelectionUI();
25
26                                 if (selectCount>1) { return this; }
27                                 return controller.findStateForSelection(selection);
28
29                         } else if ( event.type == MouseEvent.MOUSE_UP && selection.indexOf(focus)>-1 ) {
30                                 return this;
31                         }
32                         var cs:ControllerState = sharedMouseEvents(event, entity);
33                         return cs ? cs : this;
34                 }
35
36                 override public function processKeyboardEvent(event:KeyboardEvent):ControllerState {
37                         if (event.keyCode==74) return mergeWays();      // 'J'
38                         var cs:ControllerState = sharedKeyboardEvents(event);
39                         return cs ? cs : this;
40                 }
41                 
42                 public function mergeWays():ControllerState {
43                         var changed:Boolean;
44                         var waylist:Array=selectedWays;
45                         var conflictTags:Object={}; 
46                         var mergers:uint=0;
47                         do {
48                                 // ** FIXME - we should have one CompositeUndoableAction for the whole caboodle,
49                                 // but that screws up the execution order and can make the merge not work
50                                 var undo:CompositeUndoableAction = new CompositeUndoableAction("Merge ways");
51                                 changed=tryMerge(waylist, undo);
52                                 if (changed)
53                                     mergers ++;
54                 MainUndoStack.getGlobalStack().addAction(undo);
55                 
56                 if (MergeWaysAction.lastProblemTags) {
57                         for each (var t:String in MergeWaysAction.lastProblemTags) {
58                                 conflictTags[t]=t;
59                         }
60                 }
61                                         
62                         } while (changed==true);
63
64             if (mergers>0) {                                    
65                             var msg:String = 1 + mergers + " ways merged."
66                 var conflictTags2:Array = new Array();
67                 // there must be a better way of avoiding duplicates...
68                 for each (var conflict:String in conflictTags) conflictTags2.push(conflict);
69                 if (conflictTags2.length>0)
70                     msg += " *Warning* The following tags conflicted and need attention: " + conflictTags2;
71                 controller.dispatchEvent(new AttentionEvent(AttentionEvent.ALERT, null, msg));
72             }
73
74                         return controller.findStateForSelection(waylist);
75                 }
76                 
77                 private function tryMerge(waylist:Array, undo:CompositeUndoableAction):Boolean {
78                         var way1:Way, way2:Way, del:uint;
79                         for (var i:uint=0; i<waylist.length; i++) {
80                                 for (var j:uint=0; j<waylist.length; j++) {
81                                         if (waylist[i]!=waylist[j]) {
82
83                                                 // Preserve positive IDs if we can
84                                                 if (waylist[i].id < waylist[j].id && waylist[i].id >= 0) {
85                                                         way1=waylist[i]; way2=waylist[j]; del=j;
86                                                 } else {
87                                                         way1=waylist[j]; way2=waylist[i]; del=i;
88                                                 }
89
90                                                 // Merge as appropriate
91                                                 if (way1.getNode(0)==way2.getNode(0)) {
92                                                         waylist.splice(del,1);
93                                                         undo.push(new MergeWaysAction(way1,way2,0,0));
94                                                         return true;
95                                                 } else if (way1.getNode(0)==way2.getLastNode()) { 
96                                                         waylist.splice(del,1);
97                                                         undo.push(new MergeWaysAction(way1,way2,0,way2.length-1));
98                                                         return true;
99                                                 } else if (way1.getLastNode()==way2.getNode(0)) {
100                                                         waylist.splice(del,1);
101                                                         undo.push(new MergeWaysAction(way1,way2,way1.length-1,0));
102                                                         return true;
103                                                 } else if (way1.getLastNode()==way2.getLastNode()) { 
104                                                         waylist.splice(del,1);
105                                                         undo.push(new MergeWaysAction(way1,way2,way1.length-1,way2.length-1));
106                                                         return true;
107                                                 }
108                                         }
109                                 }
110                         }
111                         return false;
112                 }
113
114                 override public function enterState():void {
115                         selection=initSelection.concat();
116                         for each (var entity:Entity in selection) {
117                                 layer.setHighlight(entity, { selected: true, hover: false });
118                         }
119                         controller.updateSelectionUI();
120                         layer.setPurgable(selection,false);
121                 }
122
123                 override public function exitState(newState:ControllerState):void {
124                         layer.setPurgable(selection,true);
125                         for each (var entity:Entity in selection) {
126                                 layer.setHighlight(entity, { selected: false, hover: false });
127                         }
128                         selection = [];
129                         if (!newState.isSelectionState()) { controller.updateSelectionUI(); }
130                 }
131
132                 override public function toString():String {
133                         return "SelectedMultiple";
134                 }
135
136         }
137 }