/* * 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); }