aseprite/src/undo_transaction.h
David Capello 29898744fe Fix issue #160, crashes undoing critical actions like "remove layer" or "remove frame".
The OpenGroup & CloseGroup undoers now save the current SpritePosition
when the Undoer instance is created. Before we were using the current
Layer and Frame at the moment of the OpenGroup creation, it was generating
buggy undoers.
2012-08-23 21:44:41 -03:00

153 lines
5.0 KiB
C++

/* ASEPRITE
* Copyright (C) 2001-2012 David Capello
*
* This program 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.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef UNDO_TRANSACTION_H_INCLUDED
#define UNDO_TRANSACTION_H_INCLUDED
#include "gfx/rect.h"
#include "raster/algorithm/flip_type.h"
#include "raster/dithering_method.h"
#include "raster/frame_number.h"
#include "raster/pixel_format.h"
#include "undo/modification.h"
class Cel;
class Document;
class DocumentUndo;
class Image;
class Layer;
class LayerImage;
class Mask;
class Sprite;
namespace undo {
class ObjectsContainer;
class Undoer;
}
// High-level class to group a set of operations to modify the
// document atomically, adding information in the undo history to
// rollback the whole operation if something fails (with an
// exceptions) in the middle of the procedure.
//
// You have to wrap every call to an undo transaction with a
// DocumentWriter. The preferred usage is as the following:
//
// {
// DocumentWriter documentWriter(document);
// UndoTransaction undoTransaction(documentWriter, "My big operation");
// ...
// undoTransaction.commit();
// }
//
class UndoTransaction
{
public:
// Starts a undoable sequence of operations in a transaction that
// can be committed or rollbacked. All the operations will be
// grouped in the sprite's undo as an atomic operation.
UndoTransaction(Document* document, const char* label, undo::Modification mod = undo::ModifyDocument);
virtual ~UndoTransaction();
inline Sprite* getSprite() const { return m_sprite; }
inline bool isEnabled() const { return m_enabledFlag; }
// This must be called to commit all the changes, so the undo will
// be finally added in the sprite.
//
// If you don't use this routine, all the changes will be discarded
// (if the sprite's undo was enabled when the UndoTransaction was
// created).
void commit();
void pushUndoer(undo::Undoer* undoer);
undo::ObjectsContainer* getObjects() const;
// for sprite
void setNumberOfFrames(FrameNumber frames);
void setCurrentFrame(FrameNumber frame);
void setCurrentLayer(Layer* layer);
void setSpriteSize(int w, int h);
void cropSprite(const gfx::Rect& bounds, int bgcolor);
void trimSprite(int bgcolor);
void setPixelFormat(PixelFormat newFormat, DitheringMethod dithering_method);
// for images in stock
int addImageInStock(Image* image);
void removeImageFromStock(int image_index);
void replaceStockImage(int image_index, Image* new_image);
// for layers
LayerImage* newLayer();
void removeLayer(Layer* layer);
void restackLayerAfter(Layer* layer, Layer* afterThis);
void cropLayer(Layer* layer, int x, int y, int w, int h, int bgcolor);
void displaceLayers(Layer* layer, int dx, int dy);
void backgroundFromLayer(LayerImage* layer, int bgcolor);
void layerFromBackground();
void flattenLayers(int bgcolor);
// for frames
void newFrame();
void newFrameForLayer(Layer* layer, FrameNumber frame);
void removeFrame(FrameNumber frame);
void removeFrameOfLayer(Layer* layer, FrameNumber frame);
void copyPreviousFrame(Layer* layer, FrameNumber frame);
void setFrameDuration(FrameNumber frame, int msecs);
void setConstantFrameRate(int msecs);
void moveFrameBefore(FrameNumber frame, FrameNumber beforeFrame);
void moveFrameBeforeLayer(Layer* layer, FrameNumber frame, FrameNumber beforeFrame);
// for cels
void addCel(LayerImage* layer, Cel* cel);
void removeCel(LayerImage* layer, Cel* cel);
void setCelFramePosition(Cel* cel, FrameNumber frame);
void setCelPosition(Cel* cel, int x, int y);
Cel* getCurrentCel();
void cropCel(Cel* cel, int x, int y, int w, int h, int bgcolor);
// for image
Image* getCelImage(Cel* cel);
void clearMask(int bgcolor);
void flipImage(Image* image, const gfx::Rect& bounds, raster::algorithm::FlipType flipType);
void flipImageWithMask(Image* image, const Mask* mask, raster::algorithm::FlipType flipType, int bgcolor);
void pasteImage(const Image* src_image, int x, int y, int opacity);
// for mask
void copyToCurrentMask(Mask* mask);
void setMaskPosition(int x, int y);
void deselectMask();
private:
void configureLayerAsBackground(LayerImage* layer);
void closeUndoGroup();
void rollback();
Document* m_document;
Sprite* m_sprite;
DocumentUndo* m_undo;
bool m_closed;
bool m_committed;
bool m_enabledFlag;
const char* m_label;
undo::Modification m_modification;
};
#endif