1 /* 2 This file is part of the Grantlee template system. 3 4 Copyright (c) 2011 Stephen Kelly <steveire@gmail.com> 5 6 This library is free software; you can redistribute it and/or 7 modify it under the terms of the GNU Lesser General Public 8 License as published by the Free Software Foundation; either version 9 2.1 of the Licence, or (at your option) any later version. 10 11 This library is distributed in the hope that it will be useful, 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 Lesser General Public License for more details. 15 16 You should have received a copy of the GNU Lesser General Public 17 License along with this library. If not, see <http://www.gnu.org/licenses/>. 18 19 */ 20 21 #ifndef GRANTLEE_STATEMACHINE_P_H 22 #define GRANTLEE_STATEMACHINE_P_H 23 24 #include <QtCore/QString> 25 #include <QtCore/QVector> 26 27 namespace Grantlee 28 { 29 30 template <typename TransitionInterface> class State 31 { 32 public: 33 typedef TransitionInterface Type; 34 class Transition : public TransitionInterface 35 { 36 public: 37 typedef TransitionInterface Type; 38 explicit Transition(State<TransitionInterface> *parent = {}) 39 { 40 if (parent) 41 parent->addTransition(this); 42 } setTargetState(State<TransitionInterface> * state)43 void setTargetState(State<TransitionInterface> *state) 44 { 45 m_targetState = state; 46 } targetState()47 State<TransitionInterface> *targetState() const { return m_targetState; } 48 49 private: 50 State<TransitionInterface> *m_targetState; 51 }; 52 53 explicit State(State<TransitionInterface> *parent = {}) 54 : m_initialState(0), m_parent(parent), m_endTransition(0), 55 m_unconditionalTransition(0) 56 { 57 if (parent) 58 parent->addChild(this); 59 } 60 ~State()61 virtual ~State() 62 { 63 qDeleteAll(m_transitions); 64 qDeleteAll(m_children); 65 } 66 addChild(State<TransitionInterface> * state)67 void addChild(State<TransitionInterface> *state) { m_children.append(state); } children()68 QVector<State<TransitionInterface> *> children() const { return m_children; } parent()69 State<TransitionInterface> *parent() const { return m_parent; } 70 setInitialState(State<TransitionInterface> * state)71 void setInitialState(State<TransitionInterface> *state) 72 { 73 m_initialState = state; 74 } initialState()75 State<TransitionInterface> *initialState() { return m_initialState; } 76 addTransition(Transition * transition)77 void addTransition(Transition *transition) 78 { 79 m_transitions.append(transition); 80 } transitions()81 QVector<Transition *> transitions() { return m_transitions; } 82 setEndTransition(Transition * transition)83 void setEndTransition(Transition *transition) 84 { 85 delete m_endTransition; 86 m_endTransition = transition; 87 } endTransition()88 Transition *endTransition() const { return m_endTransition; } 89 setUnconditionalTransition(State<TransitionInterface> * transition)90 void setUnconditionalTransition(State<TransitionInterface> *transition) 91 { 92 delete m_unconditionalTransition; 93 m_unconditionalTransition = transition; 94 } unconditionalTransition()95 State<TransitionInterface> *unconditionalTransition() const 96 { 97 return m_unconditionalTransition; 98 } 99 enter()100 void enter() { onEntry(); } exit()101 void exit() { onExit(); } 102 103 protected: onEntry()104 virtual void onEntry() {} onExit()105 virtual void onExit() {} 106 107 private: 108 State<TransitionInterface> *m_initialState; 109 QVector<Transition *> m_transitions; 110 QVector<State<TransitionInterface> *> m_children; 111 State<TransitionInterface> *const m_parent; 112 Transition *m_endTransition; 113 State<TransitionInterface> *m_unconditionalTransition; 114 QString m_stateName; 115 }; 116 117 template <typename TransitionInterface> 118 class StateMachine : public State<TransitionInterface> 119 { 120 public: 121 typedef typename State<TransitionInterface>::Transition Transition; 122 123 explicit StateMachine(State<TransitionInterface> *parent = {}) 124 : State<TransitionInterface>(parent), m_currentState(0) 125 { 126 } 127 finished()128 void finished() 129 { 130 State<TransitionInterface> *s = m_currentState; 131 Q_FOREVER 132 { 133 Q_ASSERT(s); 134 if (!handleFinished(s)) 135 s = s->parent(); 136 else 137 break; 138 } 139 } 140 start()141 void start() 142 { 143 m_currentState = this->initialState(); 144 Q_ASSERT(m_currentState); 145 performEnter(m_currentState); 146 } 147 stop()148 void stop() 149 { 150 performExit(this); 151 m_currentState = 0; 152 } 153 154 protected: currentState()155 State<TransitionInterface> *currentState() const { return m_currentState; } 156 executeTransition(State<TransitionInterface> * sourceState,Transition * transition)157 void executeTransition(State<TransitionInterface> *sourceState, 158 Transition *transition) 159 { 160 performExit(sourceState); 161 transition->onTransition(); 162 m_currentState = transition->targetState(); 163 State<TransitionInterface> *enteredState = m_currentState; 164 Q_ASSERT(enteredState); 165 performEnter(enteredState); 166 triggerUnconditionalTransition(enteredState); 167 } 168 169 private: performEnter(State<TransitionInterface> * toState)170 void performEnter(State<TransitionInterface> *toState) 171 { 172 toState->enter(); 173 Q_FOREVER if (toState->initialState()) 174 { 175 toState = toState->initialState(); 176 Q_ASSERT(toState); 177 toState->enter(); 178 m_currentState = toState; 179 } 180 else 181 { 182 Q_ASSERT(toState->children().isEmpty()); 183 break; 184 } 185 } 186 performExit(State<TransitionInterface> * fromState)187 void performExit(State<TransitionInterface> *fromState) 188 { 189 State<TransitionInterface> *exitedState = m_currentState; 190 do { 191 exitedState->exit(); 192 exitedState = exitedState->parent(); 193 } while (exitedState && exitedState != fromState); 194 } 195 triggerUnconditionalTransition(State<TransitionInterface> * enteredState)196 void triggerUnconditionalTransition(State<TransitionInterface> *enteredState) 197 { 198 State<TransitionInterface> *childState = m_currentState; 199 do { 200 Q_ASSERT(childState); 201 202 if (childState->unconditionalTransition()) { 203 Transition *t = new Transition; 204 t->setTargetState(childState->unconditionalTransition()); 205 executeTransition(childState, t); 206 delete t; 207 return; 208 } 209 childState = childState->parent(); 210 Q_ASSERT(childState != enteredState); 211 Q_UNUSED(enteredState); 212 } while (childState); 213 } 214 handleFinished(State<TransitionInterface> * state)215 bool handleFinished(State<TransitionInterface> *state) 216 { 217 Transition *handler = state->endTransition(); 218 if (!handler) 219 return false; 220 221 executeTransition(state, handler); 222 return true; 223 } 224 225 private: 226 State<TransitionInterface> *m_currentState; 227 }; 228 } 229 230 #endif 231