Back to index

scribus-ng  1.3.4.dfsg+svn20071115
undostack.cpp
Go to the documentation of this file.
00001 /*
00002 For general Scribus (>=1.3.2) copyright and licensing information please refer
00003 to the COPYING file provided with the program. Following this notice may exist
00004 a copyright and/or license notice that predates the release of Scribus 1.3.2
00005 for which a new license (GPL+exception) is in place.
00006 */
00007 /***************************************************************************
00008  *   Copyright (C) 2005 by Riku Leino                                      *
00009  *   riku@scribus.info                                                     *
00010  *                                                                         *
00011  *   This program is free software; you can redistribute it and/or modify  *
00012  *   it under the terms of the GNU General Public License as published by  *
00013  *   the Free Software Foundation; either version 2 of the License, or     *
00014  *   (at your option) any later version.                                   *
00015  *                                                                         *
00016  *   This program is distributed in the hope that it will be useful,       *
00017  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00018  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
00019  *   GNU General Public License for more details.                          *
00020  *                                                                         *
00021  *   You should have received a copy of the GNU General Public License     *
00022  *   along with this program; if not, write to the                         *
00023  *   Free Software Foundation, Inc.,                                       *
00024  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
00025  ***************************************************************************/
00026 
00027 #include "undomanager.h"
00028 #include "undoobject.h"
00029 #include "undostack.h"
00030 
00031 UndoStack::UndoStack(int maxSize) : maxSize_(maxSize)
00032 {
00033 
00034 }
00035 
00036 bool UndoStack::action(UndoState *state)
00037 {
00038     redoActions_.clear();
00039     undoActions_.insert(undoActions_.begin(), state);
00040     bool needsPopping = checkSize(); // only store maxSize_ amount of actions
00041 
00042     return needsPopping;
00043 }
00044 
00045 bool UndoStack::undo(uint steps, int objectId)
00046 {
00047        for (uint i = 0; i < steps && !undoActions_.empty(); ++i) {
00048               UndoState *tmpUndoState = 0;
00049               if (objectId == Um::GLOBAL_UNDO_MODE)
00050               {
00051                      tmpUndoState = undoActions_[0];
00052                      undoActions_.erase(undoActions_.begin());
00053               }
00054               else
00055               { // object specific mode (search the correct state)
00056                      StateList::iterator it;
00057                      for (it = undoActions_.begin(); it != undoActions_.end(); ++it)
00058                      {
00059                             UndoObject *tmp = (*it)->undoObject();
00060                             if (tmp && tmp->getUId() == static_cast<ulong>(objectId))
00061                             {
00062                                    tmpUndoState = *it;
00063                                    undoActions_.erase(it);
00064                                    break;
00065                             }
00066                      }
00067               }
00068 
00069               redoActions_.insert(redoActions_.begin(), tmpUndoState); // push to the redo actions
00070               tmpUndoState->undo();
00071        }
00072 
00073        return true;
00074 }
00075 
00076 bool UndoStack::redo(uint steps, int objectId)
00077 {
00078        for (uint i = 0; i < steps && !redoActions_.empty(); ++i) {
00079               UndoState *tmpRedoState = 0;
00080               if (objectId == Um::GLOBAL_UNDO_MODE)
00081               {
00082                      tmpRedoState = redoActions_[0];
00083                      redoActions_.erase(redoActions_.begin());
00084               }
00085               else
00086               { // object specific mode (search the correct state)
00087                      StateList::iterator it;
00088                      for (it = redoActions_.begin(); it != redoActions_.end(); ++it)
00089                      {
00090                             UndoObject *tmp = (*it)->undoObject();
00091                             if (tmp && tmp->getUId() == static_cast<ulong>(objectId))
00092                             {
00093                                    tmpRedoState = *it;
00094                                    redoActions_.erase(it);
00095                                    break;
00096                             }
00097                      }
00098               }
00099               
00100               undoActions_.insert(undoActions_.begin(), tmpRedoState); // push to the undo actions
00101               tmpRedoState->redo();
00102        }
00103        
00104        return true;
00105 }
00106 
00107 uint UndoStack::size() const
00108 {
00109     return undoActions_.size() + redoActions_.size();
00110 }
00111 
00112 uint UndoStack::undoItems() const
00113 {
00114     return undoActions_.size();
00115 }
00116 
00117 uint UndoStack::redoItems() const
00118 {
00119     return redoActions_.size();
00120 }
00121 
00122 uint  UndoStack::maxSize() const
00123 {
00124     return maxSize_;
00125 }
00126 
00127 void UndoStack::setMaxSize(uint maxSize)
00128 {
00129     maxSize_ = maxSize;
00130     checkSize(); // we may need to remove actions
00131 }
00132 
00133 bool UndoStack::checkSize() {
00134     if (maxSize_ == 0) // 0 marks for infinite stack size
00135         return false;
00136 
00137     bool needsPopping = size () > maxSize_;
00138 
00139     while (size() > maxSize_) {
00140         if (redoActions_.size() > 0) // clear redo actions first
00141             redoActions_.pop_back();
00142         else
00143             undoActions_.pop_back();
00144     }
00145 
00146     return needsPopping;
00147 }
00148 
00149 void UndoStack::clear()
00150 {
00151        for (uint i = 0; i < undoActions_.size(); ++i)
00152               delete undoActions_[i];
00153        for (uint i = 0; i < redoActions_.size(); ++i)
00154               delete redoActions_[i];
00155        undoActions_.clear();
00156        redoActions_.clear();
00157 }
00158 
00159 UndoState* UndoStack::getNextUndo(int objectId)
00160 {
00161        UndoState *state = 0;
00162        if (!undoActions_.empty())
00163        {
00164               if (objectId == Um::GLOBAL_UNDO_MODE)
00165                      state = undoActions_[0];
00166               else
00167               {
00168                      StateList::iterator it;
00169                      for (it = undoActions_.begin(); it != undoActions_.end(); ++it)
00170                      {
00171                             UndoState*  tmp  = *it;
00172                             TransactionState *ts = dynamic_cast<TransactionState*>(tmp);
00173                             if (ts && ts->contains(objectId))
00174                                    break;
00175                             else if (!ts && tmp->undoObject() && 
00176                                      tmp->undoObject()->getUId() == static_cast<ulong>(objectId))
00177                             {
00178                                    state = tmp;
00179                                    break;
00180                             }
00181                      }
00182               }
00183        }
00184        return state;
00185 }
00186 
00187 UndoState* UndoStack::getNextRedo(int objectId)
00188 {
00189        UndoState *state = 0;
00190        if (!redoActions_.empty())
00191        {
00192               if (objectId == Um::GLOBAL_UNDO_MODE)
00193                      state = redoActions_[0];
00194               else
00195               {
00196                      StateList::iterator it;
00197                      for (it = redoActions_.begin(); it != redoActions_.end(); ++it)
00198                      {
00199                             UndoState*  tmp  = *it;
00200                             TransactionState *ts = dynamic_cast<TransactionState*>(tmp);
00201                             if (ts && ts->contains(objectId))
00202                                    break;
00203                             else if (!ts && tmp->undoObject() && 
00204                                      tmp->undoObject()->getUId() == static_cast<ulong>(objectId))
00205                             {
00206                                    state = tmp;
00207                                    break;
00208                             }
00209                      }
00210               }
00211        }
00212        return state;
00213 }
00214 
00215 UndoStack::~UndoStack()
00216 {
00217     // no dynamically allocated memory
00218 }
00219