source: src/Actions/ActionSequence.cpp

Candidate_v1.6.1
Last change on this file was e3ce0e, checked in by Frederik Heber <frederik.heber@…>, 7 years ago

MakroAction allows getting the internal ActionSequence's current step.

  • Property mode set to 100644
File size: 6.1 KB
Line 
1/*
2 * Project: MoleCuilder
3 * Description: creates and alters molecular systems
4 * Copyright (C) 2010-2012 University of Bonn. All rights reserved.
5 *
6 *
7 * This file is part of MoleCuilder.
8 *
9 * MoleCuilder is free software: you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation, either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * MoleCuilder is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with MoleCuilder. If not, see <http://www.gnu.org/licenses/>.
21 */
22
23/*
24 * ActionSequence.cpp
25 *
26 * Created on: Dec 17, 2009
27 * Author: crueger
28 */
29
30// include config.h
31#ifdef HAVE_CONFIG_H
32#include <config.h>
33#endif
34
35//#include "CodePatterns/MemDebug.hpp"
36
37#include "Actions/ActionSequence.hpp"
38#include "Actions/Action.hpp"
39#include "Actions/ActionExceptions.hpp"
40#include "UIElements/Dialog.hpp"
41
42#include "CodePatterns/Assert.hpp"
43
44#include <iostream>
45
46using namespace MoleCuilder;
47
48ActionSequence::ActionSequence() :
49 loop(1),
50 step(0)
51{}
52
53ActionSequence::ActionSequence(const ActionSequence &_other) :
54 loop(1),
55 step(0)
56{
57 // we need to override copy cstor as we have pointer referenced objects
58 for(actionSet::const_iterator it=_other.actions.begin(); it!=_other.actions.end(); it++){
59 actions.push_back((*it)->clone());
60 }
61}
62
63ActionSequence::~ActionSequence()
64{
65 for (actionSet::iterator iter = actions.begin(); !actions.empty(); iter = actions.begin()) {
66 delete *iter;
67 actions.erase(iter);
68 }
69}
70
71
72void ActionSequence::addAction(Action* _action)
73{
74 // actions are already clone on push as ActionRegistry hands out const refs only
75 actions.push_back(_action);
76}
77
78bool ActionSequence::removeAction(const std::string &name)
79{
80 actionSet::iterator it=actions.begin();
81 for(; it!=actions.end(); it++){
82 if ((*it)->getName() == name) {
83 delete *it;
84 actions.erase(it);
85 break;
86 }
87 }
88 return it!=actions.end();
89}
90
91Action* ActionSequence::removeLastAction()
92{
93 if(actions.empty()) {
94 return 0;
95 }
96 else {
97 Action* theAction;
98 theAction = actions.back();
99 actions.pop_back();
100 return theAction;
101 }
102}
103
104// this method is used outside the ActionModule
105// Each action registers itself with the history
106Dialog* ActionSequence::fillAllDialogs(Dialog *dialog)
107{
108 for(actionSet::iterator it=actions.begin(); it!=actions.end(); it++){
109 dialog = (*it)->fillDialog(dialog);
110 }
111 return dialog;
112}
113
114// this method is used outside the ActionModule
115// Each action registers itself with the history
116void ActionSequence::callAll()
117{
118 for (step=0;step<loop;++step)
119 for(actionSet::iterator it=actions.begin(); it!=actions.end(); it++){
120 // we want to have a global bookkeeping for all actions in the sequence, so
121 // we bypass the normal call
122 (*it)->call();
123 }
124}
125
126// This method is used internally when MakroActions are constructed.
127// In this case only the makro Action should be registered and
128// handle the states
129ActionSequence::stateSet ActionSequence::callAll(bool)
130{
131 stateSet states;
132 for (step=0;step<loop;++step)
133 for(actionSet::iterator it=actions.begin(); it!=actions.end(); it++){
134 // we want to have a global bookkeeping for all actions in the sequence, so
135 // we bypass the normal call
136 ActionState::ptr state = (*it)->performCall();
137 if (state == Action::failure)
138 throw ActionFailureException() << ActionNameString((*it)->getName());
139 states.push_back(state);
140 }
141 return states;
142}
143
144ActionSequence::stateSet ActionSequence::undoAll(stateSet states)
145{
146 ASSERT(canUndo(),"Trying to undo a sequence that contains methods that can't be undone");
147 stateSet res;
148 actionSet::reverse_iterator actionRit = actions.rbegin();
149 stateSet::reverse_iterator stateRit = states.rbegin();
150 for(;actionRit!=actions.rend();++actionRit,++stateRit){
151 ASSERT(stateRit!=states.rend(),"End of states prematurely reached.");
152 if((*actionRit)->shouldUndo()){
153 ActionState::ptr newState = (*actionRit)->performUndo(*stateRit);
154 // The order of the states has to correspond to the order of the actions
155 // this is why we have to add at the beginning
156 res.push_front(newState);
157 }
158 else{
159 res.push_front(Action::success);
160 }
161 }
162 return res;
163}
164
165ActionSequence::stateSet ActionSequence::redoAll(stateSet states)
166{
167 stateSet res;
168 actionSet::iterator actionIt = actions.begin();
169 stateSet::iterator stateIt = states.begin();
170 for(;actionIt!=actions.end();++actionIt,++stateIt){
171 ASSERT(stateIt!=states.end(),"End of states prematurely reached.");
172 if((*actionIt)->shouldUndo()){
173 ActionState::ptr newState =(*actionIt)->performRedo(*stateIt);
174 res.push_back(newState);
175 }
176 else{
177 res.push_back(Action::success);
178 }
179 }
180 return res;
181}
182
183bool ActionSequence::canUndo()
184{
185 bool canUndo=true;
186 for(std::deque<Action*>::iterator it=actions.begin(); it!=actions.end(); ++it){
187 if((*it)->shouldUndo()){
188 canUndo &= (*it)->canUndo();
189 }
190 }
191 return canUndo;
192}
193
194bool ActionSequence::shouldUndo()
195{
196 bool shouldUndo = false;
197 for(std::deque<Action*>::iterator it=actions.begin();it!=actions.end();++it){
198 shouldUndo |= (*it)->shouldUndo();
199 }
200 return shouldUndo;
201}
202
203void ActionSequence::outputAsCLI(std::ostream &ost) const
204{
205 for(std::deque<Action*>::const_iterator it=actions.begin();it!=actions.end();++it){
206 (*it)->outputAsCLI(ost);
207 ost << " ";
208 }
209}
210
211void ActionSequence::outputAsPython(std::ostream &ost, const std::string &prefix) const
212{
213 for(std::deque<Action*>::const_iterator it=actions.begin();it!=actions.end();++it)
214 (*it)->outputAsPython(ost, prefix);
215}
216
217void ActionSequence::setOptionValue(const std::string &_token, const std::string &_value)
218{
219 for(std::deque<Action*>::const_iterator it=actions.begin();it!=actions.end();++it)
220 (*it)->setOptionValue(_token, _value);
221}
Note: See TracBrowser for help on using the repository browser.