/*
* Project: MoleCuilder
* Description: creates and alters molecular systems
* Copyright (C) 2010-2012 University of Bonn. All rights reserved.
*
*
* This file is part of MoleCuilder.
*
* MoleCuilder is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* MoleCuilder is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with MoleCuilder. If not, see .
*/
/*
* ActionSequenze.cpp
*
* Created on: Dec 17, 2009
* Author: crueger
*/
// include config.h
#ifdef HAVE_CONFIG_H
#include
#endif
#include "CodePatterns/MemDebug.hpp"
#include "Actions/ActionSequence.hpp"
#include "Actions/Action.hpp"
#include "Actions/ActionExceptions.hpp"
#include "UIElements/Dialog.hpp"
#include "CodePatterns/Assert.hpp"
#include
using namespace MoleCuilder;
ActionSequence::ActionSequence() :
loop(1)
{}
ActionSequence::ActionSequence(const ActionSequence &_other) :
loop(1)
{
// we need to override copy cstor as we have pointer referenced objects
for(actionSet::const_iterator it=_other.actions.begin(); it!=_other.actions.end(); it++){
actions.push_back((*it)->clone());
}
}
ActionSequence::~ActionSequence()
{}
void ActionSequence::addAction(Action* _action){
actions.push_back(_action);
}
bool ActionSequence::removeAction(const std::string &name){
actionSet::iterator it=actions.begin();
for(; it!=actions.end(); it++){
if ((*it)->getName() == name) {
actions.erase(it);
break;
}
}
return it!=actions.end();
}
Action* ActionSequence::removeLastAction(){
if(actions.empty()) {
return 0;
}
else {
Action* theAction;
theAction = actions.back();
actions.pop_back();
return theAction;
}
}
// this method is used outside the ActionModule
// Each action registers itself with the history
Dialog* ActionSequence::fillAllDialogs(Dialog *dialog){
for(actionSet::iterator it=actions.begin(); it!=actions.end(); it++){
dialog = (*it)->fillDialog(dialog);
}
return dialog;
}
// this method is used outside the ActionModule
// Each action registers itself with the history
void ActionSequence::callAll(){
for (size_t i=0;icall();
}
}
// This method is used internally when MakroActions are constructed.
// In this case only the makro Action should be registered and
// handle the states
ActionSequence::stateSet ActionSequence::callAll(bool){
stateSet states;
for (size_t i=0;iperformCall();
if (state == Action::failure)
throw ActionFailureException() << ActionNameString((*it)->getName());
states.push_back(state);
}
return states;
}
ActionSequence::stateSet ActionSequence::undoAll(stateSet states){
ASSERT(canUndo(),"Trying to undo a sequence that contains methods that can't be undone");
stateSet res;
actionSet::reverse_iterator actionRit = actions.rbegin();
stateSet::reverse_iterator stateRit = states.rbegin();
for(;actionRit!=actions.rend();++actionRit,++stateRit){
ASSERT(stateRit!=states.rend(),"End of states prematurely reached.");
if((*actionRit)->shouldUndo()){
ActionState::ptr newState = (*actionRit)->performUndo(*stateRit);
// The order of the states has to correspond to the order of the actions
// this is why we have to add at the beginning
res.push_front(newState);
}
else{
res.push_front(Action::success);
}
}
return res;
}
ActionSequence::stateSet ActionSequence::redoAll(stateSet states){
stateSet res;
actionSet::iterator actionIt = actions.begin();
stateSet::iterator stateIt = states.begin();
for(;actionIt!=actions.end();++actionIt,++stateIt){
ASSERT(stateIt!=states.end(),"End of states prematurely reached.");
if((*actionIt)->shouldUndo()){
ActionState::ptr newState =(*actionIt)->performRedo(*stateIt);
res.push_back(newState);
}
else{
res.push_back(Action::success);
}
}
return res;
}
bool ActionSequence::canUndo(){
bool canUndo=true;
for(std::deque::iterator it=actions.begin(); it!=actions.end(); ++it){
if((*it)->shouldUndo()){
canUndo &= (*it)->canUndo();
}
}
return canUndo;
}
bool ActionSequence::shouldUndo(){
bool shouldUndo = false;
for(std::deque::iterator it=actions.begin();it!=actions.end();++it){
shouldUndo |= (*it)->shouldUndo();
}
return shouldUndo;
}
void ActionSequence::outputAsCLI(std::ostream &ost) const
{
for(std::deque::const_iterator it=actions.begin();it!=actions.end();++it){
(*it)->outputAsCLI(ost);
ost << " ";
}
}
void ActionSequence::outputAsPython(std::ostream &ost, const std::string &prefix) const
{
for(std::deque::const_iterator it=actions.begin();it!=actions.end();++it)
(*it)->outputAsPython(ost, prefix);
}
void ActionSequence::setOptionValue(const std::string &_token, const std::string &_value)
{
for(std::deque::const_iterator it=actions.begin();it!=actions.end();++it)
(*it)->setOptionValue(_token, _value);
}