1 module auxil.location; 2 3 import auxil.model : Orientation; // FIXME avoid import from this module 4 import auxil.treepath; 5 6 alias SizeType = int; 7 8 enum Order { Sinking, Bubbling, } 9 10 struct Axis 11 { 12 SizeType position, destination, change, size; 13 } 14 15 @safe 16 struct Location 17 { 18 @nogc: 19 enum State { seeking, first, rest, finishing, } 20 State _state; 21 TreePath current_path, path; 22 Axis x, y; 23 24 @property 25 { 26 State state() @safe @nogc nothrow { return _state; } 27 } 28 29 package void resetState() @safe @nogc nothrow 30 { 31 _state = (path.value.length) ? State.seeking : State.rest; 32 y.change = 0; 33 x.change = 0; 34 } 35 36 /// returns true if the processing should be interrupted 37 package bool checkState() @safe @nogc 38 { 39 final switch(_state) 40 { 41 case State.seeking: 42 if (current_path.value == path.value) 43 _state = State.first; 44 break; 45 case State.first: 46 _state = State.rest; 47 break; 48 case State.rest: 49 // do nothing 50 break; 51 case State.finishing: 52 { 53 return true; 54 } 55 } 56 return false; 57 } 58 59 void indent() 60 { 61 current_path.put(0); 62 } 63 64 void unindent() 65 { 66 current_path.popBack; 67 } 68 69 auto startValue(Order order)(size_t len) 70 { 71 import std.algorithm : among; 72 73 size_t start_value; 74 static if (order == Order.Bubbling) 75 { 76 start_value = len; 77 start_value--; 78 } 79 if (_state.among(State.seeking, State.first)) 80 { 81 auto idx = current_path.value.length; 82 if (idx && path.value.length >= idx) 83 { 84 start_value = path.value[idx-1]; 85 // position should change only if we've got the initial path 86 // and don't get the end 87 if (_state == State.seeking) y.change = 0; 88 } 89 } 90 return start_value; 91 } 92 93 void setPath(int v) 94 { 95 current_path.back = v; 96 } 97 98 bool stateFirstOrRest() @safe @nogc pure nothrow 99 { 100 import std.algorithm : among; 101 return !!_state.among(State.first, State.rest); 102 } 103 }