Splitting ways in an ordered relation - handles insertion order. Still not reversible
[potlatch2.git] / net / systemeD / halcyon / connection / actions / SplitWayAction.as
1 package net.systemeD.halcyon.connection.actions {
2
3     import net.systemeD.halcyon.connection.*;
4         import net.systemeD.halcyon.Globals;
5     
6     public class SplitWayAction extends CompositeUndoableAction {
7     
8         private var selectedWay:Way;
9         private var selectedNode:Node;
10         private var newWay:Way;
11     
12         public function SplitWayAction(selectedWay:Way, selectedNode:Node) {
13             super("Split way "+selectedWay.id);
14             this.selectedWay = selectedWay;
15             this.selectedNode = selectedNode;
16         }
17     
18         public override function doAction():uint {
19             if (newWay==null) {
20                                 newWay = Connection.getConnection().createWay(
21                                         selectedWay.getTagsCopy(), 
22                                         selectedWay.sliceNodes(selectedWay.indexOfNode(selectedNode),selectedWay.length),
23                                         push);
24
25                                 // copy relations
26                                 // FIXME make this reversible
27
28                 // we reverse the list, which is already sorted by position. This way positions aren't affected
29                 // for previous inserts when all the inserts are eventually executed
30                 for each (var o:Object in selectedWay.memberships.reverse()) {
31                   // newWay should be added immediately after the selectedWay, unless the setup
32                   // is arse-backwards. By that I mean either:
33                   // a) The first node (0) of selectedWay is in the subsequentWay, or
34                   // b) The last node (N) of selectedWay is in the preceedingWay
35                   // Note that the code above means newWay is the tail of selectedWay S-->.-->N
36                   // i.e. preceedingWay x--x--x--x                             P-1   ↓
37                   //      selectedWay            N<--.<--S<--.<--0             P     ↓ relation members list
38                   //      subsequentWay                           x--x--x--x   P+1   ↓
39                   // There are some edge cases:
40                   // 1) If the immediately adjacent member isn't a way - handled fine
41                   // 2) If the selectedWay shares first/last node with non-adjacent ways - phooey
42                   
43                   var backwards:Boolean = false;
44                   // note that backwards is actually a ternary of 'true', 'false', and 'itdoesntmatter' (== 'false')
45                   
46                   var offset:int = 1; //work from o.position outwards along the length of the relationmembers
47                   while ((o.position - offset) >= 0 || (o.position + offset < o.relation.length)) {
48                     if ((o.position - offset >= 0) && o.relation.getMember(o.position - offset).entity is Way)  {
49                       var preceedingWay:Way = o.relation.getMember(o.position - offset).entity as Way;
50                       if(preceedingWay.indexOfNode(selectedWay.getLastNode()) >= 0) {
51                         backwards = true;
52                       }
53                     }
54                     if ((o.position + offset < o.relation.length) && o.relation.getMember(o.position + offset).entity is Way) {
55                       var subsequentWay:Way = o.relation.getMember(o.position + offset).entity as Way;
56                       if(subsequentWay.indexOfNode(selectedWay.getNode(0)) >= 0) {
57                         backwards = true;
58                       }
59                     }
60                     offset++;
61                   }
62                   if (backwards) {
63                     o.relation.insertMember(o.position, new RelationMember(newWay, o.role)); //insert newWay before selectedWay
64                   } else {
65                     o.relation.insertMember(o.position + 1, new RelationMember(newWay, o.role)); // insert after
66                   }
67                 }
68                 
69                 // now that we're done with the selectedWay, remove the nodes
70                 selectedWay.deleteNodesFrom(selectedWay.indexOfNode(selectedNode)+1, push);
71             }
72             newWay.suspend();
73             selectedWay.suspend();
74             super.doAction();
75             newWay.resume();
76             selectedWay.resume();
77             return SUCCESS;
78         }
79         
80         public override function undoAction():uint {
81             selectedWay.suspend();
82             newWay.suspend();
83             
84             super.undoAction();
85             
86             newWay.resume();
87             selectedWay.resume();
88             return SUCCESS;
89         }
90     }
91
92 }