Add DocumentUndo to avoid app specific data in the undo library.

The UndoHistory was simplified, m_enabled/label/modification members
were removed because they aren't part of the undo library goal.
Now the "label" field is part of Open/CloseGroup undoers, and all undoers
must be enclosed in a group (this restriction is only for the app, the
undo library doesn't have this restriction). In this way, the
label/modification information is exchanged between an
OpenGroup <-> CloseGroup pair only.
This commit is contained in:
David Capello 2012-07-08 01:25:26 -03:00
parent 160bf5ba0a
commit 594a272c06
37 changed files with 523 additions and 437 deletions

View File

@ -141,6 +141,7 @@ add_library(aseprite-library
context_flags.cpp context_flags.cpp
context_listener_list.cpp context_listener_list.cpp
document.cpp document.cpp
document_undo.cpp
documents.cpp documents.cpp
drop_files.cpp drop_files.cpp
file_system.cpp file_system.cpp

View File

@ -31,7 +31,7 @@
#include "raster/sprite.h" #include "raster/sprite.h"
#include "raster/stock.h" #include "raster/stock.h"
#include "ui/gui.h" #include "ui/gui.h"
#include "undo/undo_history.h" #include "undo_transaction.h"
#include "undoers/set_cel_opacity.h" #include "undoers/set_cel_opacity.h"
#include <allegro/unicode.h> #include <allegro/unicode.h>
@ -129,18 +129,16 @@ void CelPropertiesCommand::onExecute(Context* context)
Sprite* sprite_writer = document_writer->getSprite(); Sprite* sprite_writer = document_writer->getSprite();
Layer* layer_writer = sprite_writer->getCurrentLayer(); Layer* layer_writer = sprite_writer->getCurrentLayer();
Cel* cel_writer = static_cast<LayerImage*>(layer_writer)->getCel(sprite->getCurrentFrame()); Cel* cel_writer = static_cast<LayerImage*>(layer_writer)->getCel(sprite->getCurrentFrame());
undo::UndoHistory* undo = document_writer->getUndoHistory();
int new_opacity = slider_opacity->getValue(); int new_opacity = slider_opacity->getValue();
// The opacity was changed? // The opacity was changed?
if (cel_writer != NULL && if (cel_writer != NULL &&
cel_writer->getOpacity() != new_opacity) { cel_writer->getOpacity() != new_opacity) {
if (undo->isEnabled()) { UndoTransaction undo(document_writer, "Cel Opacity Change", undo::ModifyDocument);
undo->setLabel("Cel Opacity Change"); if (undo.isEnabled()) {
undo->setModification(undo::ModifyDocument); undo.pushUndoer(new undoers::SetCelOpacity(undo.getObjects(), cel_writer));
undo.commit();
undo->pushUndoer(new undoers::SetCelOpacity(undo->getObjects(), cel_writer));
} }
// Change cel opacity. // Change cel opacity.

View File

@ -21,12 +21,12 @@
#include "app.h" #include "app.h"
#include "commands/command.h" #include "commands/command.h"
#include "console.h" #include "console.h"
#include "document_undo.h"
#include "document_wrappers.h" #include "document_wrappers.h"
#include "modules/gui.h" #include "modules/gui.h"
#include "raster/layer.h" #include "raster/layer.h"
#include "raster/sprite.h" #include "raster/sprite.h"
#include "ui/gui.h" #include "ui/gui.h"
#include "undo/undo_history.h"
#include "undo_transaction.h" #include "undo_transaction.h"
#include "undoers/add_layer.h" #include "undoers/add_layer.h"
#include "undoers/move_layer.h" #include "undoers/move_layer.h"
@ -64,8 +64,7 @@ void DuplicateLayerCommand::onExecute(Context* context)
{ {
ActiveDocumentWriter document(context); ActiveDocumentWriter document(context);
Sprite* sprite = document->getSprite(); Sprite* sprite = document->getSprite();
undo::UndoHistory* undo = document->getUndoHistory(); UndoTransaction undo(document, "Layer Duplication");
UndoTransaction undoTransaction(document, "Layer Duplication");
LayerImage* sourceLayer = static_cast<LayerImage*>(sprite->getCurrentLayer()); LayerImage* sourceLayer = static_cast<LayerImage*>(sprite->getCurrentLayer());
// Create a new layer // Create a new layer
@ -73,20 +72,20 @@ void DuplicateLayerCommand::onExecute(Context* context)
// Disable undo because the layer content is added as a whole with // Disable undo because the layer content is added as a whole with
// AddLayer() undoer. // AddLayer() undoer.
document->getUndoHistory()->setEnabled(false); document->getUndo()->setEnabled(false);
// Copy the layer content (cels + images) // Copy the layer content (cels + images)
document->copyLayerContent(sourceLayer, document, newLayerPtr); document->copyLayerContent(sourceLayer, document, newLayerPtr);
// Restore enabled status. // Restore enabled status.
document->getUndoHistory()->setEnabled(undoTransaction.isEnabled()); document->getUndo()->setEnabled(undo.isEnabled());
// Copy the layer name // Copy the layer name
newLayerPtr->setName(newLayerPtr->getName() + " Copy"); newLayerPtr->setName(newLayerPtr->getName() + " Copy");
// Add the new layer in the sprite. // Add the new layer in the sprite.
if (undo->isEnabled()) if (undo.isEnabled())
undo->pushUndoer(new undoers::AddLayer(undo->getObjects(), undo.pushUndoer(new undoers::AddLayer(undo.getObjects(),
sourceLayer->get_parent(), newLayerPtr)); sourceLayer->get_parent(), newLayerPtr));
sourceLayer->get_parent()->add_layer(newLayerPtr); sourceLayer->get_parent()->add_layer(newLayerPtr);
@ -94,12 +93,12 @@ void DuplicateLayerCommand::onExecute(Context* context)
// Release the pointer as it is owned by the sprite now // Release the pointer as it is owned by the sprite now
Layer* newLayer = newLayerPtr.release(); Layer* newLayer = newLayerPtr.release();
if (undo->isEnabled()) { if (undo.isEnabled()) {
undo->pushUndoer(new undoers::MoveLayer(undo->getObjects(), newLayer)); undo.pushUndoer(new undoers::MoveLayer(undo.getObjects(), newLayer));
undo->pushUndoer(new undoers::SetCurrentLayer(undo->getObjects(), sprite)); undo.pushUndoer(new undoers::SetCurrentLayer(undo.getObjects(), sprite));
} }
undoTransaction.commit(); undo.commit();
sourceLayer->get_parent()->move_layer(newLayer, sourceLayer); sourceLayer->get_parent()->move_layer(newLayer, sourceLayer);
sprite->setCurrentLayer(newLayer); sprite->setCurrentLayer(newLayer);

View File

@ -21,6 +21,7 @@
#include "base/bind.h" #include "base/bind.h"
#include "commands/command.h" #include "commands/command.h"
#include "commands/commands.h" #include "commands/commands.h"
#include "document_undo.h"
#include "document_wrappers.h" #include "document_wrappers.h"
#include "ini_file.h" #include "ini_file.h"
#include "modules/gui.h" #include "modules/gui.h"
@ -32,7 +33,6 @@
#include "raster/sprite.h" #include "raster/sprite.h"
#include "raster/stock.h" #include "raster/stock.h"
#include "ui/gui.h" #include "ui/gui.h"
#include "undo/undo_history.h"
#include "undo_transaction.h" #include "undo_transaction.h"
#include <limits> #include <limits>
@ -257,7 +257,9 @@ protected:
// Undo the sprite sheet conversion // Undo the sprite sheet conversion
if (undo) { if (undo) {
m_document->getUndoHistory()->doUndo(); if (m_document->getUndo()->canUndo())
m_document->getUndo()->doUndo();
m_document->generateMaskBoundaries(); m_document->generateMaskBoundaries();
m_document->destroyExtraCel(); // Regenerate extras m_document->destroyExtraCel(); // Regenerate extras

View File

@ -26,7 +26,7 @@
#include "raster/image.h" #include "raster/image.h"
#include "raster/mask.h" #include "raster/mask.h"
#include "raster/sprite.h" #include "raster/sprite.h"
#include "undo/undo_history.h" #include "undo_transaction.h"
#include "undoers/set_mask.h" #include "undoers/set_mask.h"
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
@ -76,14 +76,9 @@ void InvertMaskCommand::onExecute(Context* context)
else { else {
ActiveDocumentWriter document(context); ActiveDocumentWriter document(context);
Sprite* sprite(document->getSprite()); Sprite* sprite(document->getSprite());
undo::UndoHistory* undo = document->getUndoHistory(); UndoTransaction undo(document, "Mask Invert", undo::DoesntModifyDocument);
if (undo.isEnabled())
/* undo */ undo.pushUndoer(new undoers::SetMask(undo.getObjects(), document));
if (undo->isEnabled()) {
undo->setLabel("Mask Invert");
undo->setModification(undo::DoesntModifyDocument);
undo->pushUndoer(new undoers::SetMask(undo->getObjects(), document));
}
/* create a new mask */ /* create a new mask */
UniquePtr<Mask> mask(new Mask()); UniquePtr<Mask> mask(new Mask());
@ -108,11 +103,12 @@ void InvertMaskCommand::onExecute(Context* context)
document->getMask()->getBounds().y); document->getMask()->getBounds().y);
} }
/* we need only need the area inside the sprite */ // We need only need the area inside the sprite
mask->intersect(0, 0, sprite->getWidth(), sprite->getHeight()); mask->intersect(0, 0, sprite->getWidth(), sprite->getHeight());
// Set the new mask // Set the new mask
document->setMask(mask); document->setMask(mask);
undo.commit();
document->generateMaskBoundaries(); document->generateMaskBoundaries();
update_screen_for_document(document); update_screen_for_document(document);

View File

@ -26,7 +26,7 @@
#include "raster/mask.h" #include "raster/mask.h"
#include "raster/sprite.h" #include "raster/sprite.h"
#include "ui/alert.h" #include "ui/alert.h"
#include "undo/undo_history.h" #include "undo_transaction.h"
#include "undoers/set_mask.h" #include "undoers/set_mask.h"
#include "util/msk_file.h" #include "util/msk_file.h"
@ -84,16 +84,15 @@ void LoadMaskCommand::onExecute(Context* context)
{ {
DocumentWriter documentWriter(document); DocumentWriter documentWriter(document);
undo::UndoHistory* undo(documentWriter->getUndoHistory()); UndoTransaction undo(documentWriter, "Mask Load", undo::DoesntModifyDocument);
// Add the mask change into the undo history. // Add the mask change into the undo history.
if (undo->isEnabled()) { if (undo.isEnabled())
undo->setLabel("Mask Load"); undo.pushUndoer(new undoers::SetMask(undo.getObjects(), documentWriter));
undo->setModification(undo::DoesntModifyDocument);
undo->pushUndoer(new undoers::SetMask(undo->getObjects(), documentWriter));
}
documentWriter->setMask(mask); documentWriter->setMask(mask);
undo.commit();
documentWriter->generateMaskBoundaries(); documentWriter->generateMaskBoundaries();
} }

View File

@ -23,7 +23,7 @@
#include "modules/gui.h" #include "modules/gui.h"
#include "raster/mask.h" #include "raster/mask.h"
#include "raster/sprite.h" #include "raster/sprite.h"
#include "undo/undo_history.h" #include "undo_transaction.h"
#include "undoers/set_mask.h" #include "undoers/set_mask.h"
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
@ -57,20 +57,18 @@ void MaskAllCommand::onExecute(Context* context)
{ {
ActiveDocumentWriter document(context); ActiveDocumentWriter document(context);
Sprite* sprite(document->getSprite()); Sprite* sprite(document->getSprite());
undo::UndoHistory* undo(document->getUndoHistory()); UndoTransaction undo(document, "Mask All", undo::DoesntModifyDocument);
// Undo // Undo
if (undo->isEnabled()) { if (undo.isEnabled())
undo->setLabel("Mask All"); undo.pushUndoer(new undoers::SetMask(undo.getObjects(), document));
undo->setModification(undo::DoesntModifyDocument);
undo->pushUndoer(new undoers::SetMask(undo->getObjects(), document));
}
// Change the selection // Change the selection
document->getMask()->replace(0, 0, sprite->getWidth(), sprite->getHeight()); document->getMask()->replace(0, 0, sprite->getWidth(), sprite->getHeight());
document->setMaskVisible(true); document->setMaskVisible(true);
document->resetTransformation(); document->resetTransformation();
undo.commit();
document->generateMaskBoundaries(); document->generateMaskBoundaries();
update_screen_for_document(document); update_screen_for_document(document);
} }

View File

@ -28,11 +28,9 @@
#include "raster/sprite.h" #include "raster/sprite.h"
#include "raster/stock.h" #include "raster/stock.h"
#include "ui/gui.h" #include "ui/gui.h"
#include "undo/undo_history.h" #include "undo_transaction.h"
#include "undoers/add_cel.h" #include "undoers/add_cel.h"
#include "undoers/add_image.h" #include "undoers/add_image.h"
#include "undoers/close_group.h"
#include "undoers/open_group.h"
#include "undoers/remove_layer.h" #include "undoers/remove_layer.h"
#include "undoers/replace_image.h" #include "undoers/replace_image.h"
#include "undoers/set_cel_position.h" #include "undoers/set_cel_position.h"
@ -81,7 +79,7 @@ void MergeDownLayerCommand::onExecute(Context* context)
{ {
ActiveDocumentWriter document(context); ActiveDocumentWriter document(context);
Sprite* sprite(document->getSprite()); Sprite* sprite(document->getSprite());
undo::UndoHistory* undo(document->getUndoHistory()); UndoTransaction undo(document, "Merge Down Layer", undo::ModifyDocument);
Layer *src_layer, *dst_layer; Layer *src_layer, *dst_layer;
Cel *src_cel, *dst_cel; Cel *src_cel, *dst_cel;
Image *src_image, *dst_image; Image *src_image, *dst_image;
@ -90,12 +88,6 @@ void MergeDownLayerCommand::onExecute(Context* context)
src_layer = sprite->getCurrentLayer(); src_layer = sprite->getCurrentLayer();
dst_layer = sprite->getCurrentLayer()->get_prev(); dst_layer = sprite->getCurrentLayer()->get_prev();
if (undo->isEnabled()) {
undo->setLabel("Merge Down Layer");
undo->setModification(undo::ModifyDocument);
undo->pushUndoer(new undoers::OpenGroup());
}
for (frpos=0; frpos<sprite->getTotalFrames(); ++frpos) { for (frpos=0; frpos<sprite->getTotalFrames(); ++frpos) {
// Get frames // Get frames
src_cel = static_cast<LayerImage*>(src_layer)->getCel(frpos); src_cel = static_cast<LayerImage*>(src_layer)->getCel(frpos);
@ -123,17 +115,17 @@ void MergeDownLayerCommand::onExecute(Context* context)
// Adding it in the stock of images // Adding it in the stock of images
index = sprite->getStock()->addImage(dst_image); index = sprite->getStock()->addImage(dst_image);
if (undo->isEnabled()) if (undo.isEnabled())
undo->pushUndoer(new undoers::AddImage( undo.pushUndoer(new undoers::AddImage(
undo->getObjects(), sprite->getStock(), index)); undo.getObjects(), sprite->getStock(), index));
// Creating a copy of the cell // Creating a copy of the cell
dst_cel = new Cel(frpos, index); dst_cel = new Cel(frpos, index);
dst_cel->setPosition(src_cel->getX(), src_cel->getY()); dst_cel->setPosition(src_cel->getX(), src_cel->getY());
dst_cel->setOpacity(src_cel->getOpacity()); dst_cel->setOpacity(src_cel->getOpacity());
if (undo->isEnabled()) if (undo.isEnabled())
undo->pushUndoer(new undoers::AddCel(undo->getObjects(), dst_layer, dst_cel)); undo.pushUndoer(new undoers::AddCel(undo.getObjects(), dst_layer, dst_cel));
static_cast<LayerImage*>(dst_layer)->addCel(dst_cel); static_cast<LayerImage*>(dst_layer)->addCel(dst_cel);
} }
@ -171,13 +163,13 @@ void MergeDownLayerCommand::onExecute(Context* context)
src_cel->getOpacity(), src_cel->getOpacity(),
static_cast<LayerImage*>(src_layer)->getBlendMode()); static_cast<LayerImage*>(src_layer)->getBlendMode());
if (undo->isEnabled()) if (undo.isEnabled())
undo->pushUndoer(new undoers::SetCelPosition(undo->getObjects(), dst_cel)); undo.pushUndoer(new undoers::SetCelPosition(undo.getObjects(), dst_cel));
dst_cel->setPosition(x1, y1); dst_cel->setPosition(x1, y1);
if (undo->isEnabled()) if (undo.isEnabled())
undo->pushUndoer(new undoers::ReplaceImage(undo->getObjects(), undo.pushUndoer(new undoers::ReplaceImage(undo.getObjects(),
sprite->getStock(), dst_cel->getImage())); sprite->getStock(), dst_cel->getImage()));
sprite->getStock()->replaceImage(dst_cel->getImage(), new_image); sprite->getStock()->replaceImage(dst_cel->getImage(), new_image);
@ -187,10 +179,9 @@ void MergeDownLayerCommand::onExecute(Context* context)
} }
} }
if (undo->isEnabled()) { if (undo.isEnabled()) {
undo->pushUndoer(new undoers::SetCurrentLayer(undo->getObjects(), sprite)); undo.pushUndoer(new undoers::SetCurrentLayer(undo.getObjects(), sprite));
undo->pushUndoer(new undoers::RemoveLayer(undo->getObjects(), src_layer)); undo.pushUndoer(new undoers::RemoveLayer(undo.getObjects(), src_layer));
undo->pushUndoer(new undoers::CloseGroup());
} }
sprite->setCurrentLayer(dst_layer); sprite->setCurrentLayer(dst_layer);
@ -198,6 +189,7 @@ void MergeDownLayerCommand::onExecute(Context* context)
delete src_layer; delete src_layer;
undo.commit();
update_screen_for_document(document); update_screen_for_document(document);
} }

View File

@ -27,6 +27,7 @@
#include "commands/command.h" #include "commands/command.h"
#include "commands/params.h" #include "commands/params.h"
#include "console.h" #include "console.h"
#include "document_undo.h"
#include "document_wrappers.h" #include "document_wrappers.h"
#include "gfx/hsv.h" #include "gfx/hsv.h"
#include "gfx/rgb.h" #include "gfx/rgb.h"
@ -44,9 +45,7 @@
#include "ui/graphics.h" #include "ui/graphics.h"
#include "ui/gui.h" #include "ui/gui.h"
#include "ui_context.h" #include "ui_context.h"
#include "undo/undo_history.h" #include "undo_transaction.h"
#include "undoers/close_group.h"
#include "undoers/open_group.h"
#include "undoers/set_palette_colors.h" #include "undoers/set_palette_colors.h"
#include "widgets/color_bar.h" #include "widgets/color_bar.h"
#include "widgets/color_sliders.h" #include "widgets/color_sliders.h"
@ -123,10 +122,10 @@ private:
ui::Timer m_redrawTimer; ui::Timer m_redrawTimer;
bool m_redrawAll; bool m_redrawAll;
// True if the palette change must be graft in the UndoHistory // True if the palette change must be implant in the UndoHistory
// (e.g. when two or more changes in the palette are made in short // (e.g. when two or more changes in the palette are made in short
// time). // time).
bool m_graftChange; bool m_implantChange;
// True if the PaletteChange signal is generated by the same // True if the PaletteChange signal is generated by the same
// PaletteEntryEditor instance. // PaletteEntryEditor instance.
@ -261,7 +260,7 @@ PaletteEntryEditor::PaletteEntryEditor()
, m_quantizeButton("Quantize") , m_quantizeButton("Quantize")
, m_disableHexUpdate(false) , m_disableHexUpdate(false)
, m_redrawAll(false) , m_redrawAll(false)
, m_graftChange(false) , m_implantChange(false)
, m_selfPalChange(false) , m_selfPalChange(false)
, m_redrawTimer(250, this) , m_redrawTimer(250, this)
{ {
@ -403,7 +402,7 @@ bool PaletteEntryEditor::onProcessMessage(Message* msg)
// Redraw all editors // Redraw all editors
if (m_redrawAll) { if (m_redrawAll) {
m_redrawAll = false; m_redrawAll = false;
m_graftChange = false; m_implantChange = false;
m_redrawTimer.stop(); m_redrawTimer.stop();
// Call all listener of PaletteChange event. // Call all listener of PaletteChange event.
@ -803,7 +802,6 @@ void PaletteEntryEditor::updateCurrentSpritePalette(const char* operationName)
try { try {
ActiveDocumentWriter document(UIContext::instance()); ActiveDocumentWriter document(UIContext::instance());
Sprite* sprite(document->getSprite()); Sprite* sprite(document->getSprite());
undo::UndoHistory* undo = document->getUndoHistory();
Palette* newPalette = get_current_palette(); // System current pal Palette* newPalette = get_current_palette(); // System current pal
Palette* currentSpritePalette = sprite->getPalette(sprite->getCurrentFrame()); // Sprite current pal Palette* currentSpritePalette = sprite->getPalette(sprite->getCurrentFrame()); // Sprite current pal
int from, to; int from, to;
@ -813,23 +811,21 @@ void PaletteEntryEditor::updateCurrentSpritePalette(const char* operationName)
currentSpritePalette->countDiff(newPalette, &from, &to); currentSpritePalette->countDiff(newPalette, &from, &to);
if (from >= 0 && to >= from) { if (from >= 0 && to >= from) {
DocumentUndo* undo = document->getUndo();
// Add undo information to save the range of pal entries that will be modified. // Add undo information to save the range of pal entries that will be modified.
if (undo->isEnabled()) { if (undo->isEnabled()) {
if (m_graftChange && strcmp(undo->getLabel(), operationName) == 0) { if (m_implantChange && strcmp(undo->getNextUndoLabel(), operationName) == 0) {
undo->setLabel(operationName); undo->implantUndoerInLastGroup
undo->setModification(undo::ModifyDocument); (new undoers::SetPaletteColors(undo->getObjects(),
sprite, currentSpritePalette, from, to));
undo->graftUndoerInLastGroup(new undoers::SetPaletteColors(undo->getObjects(),
sprite, currentSpritePalette, from, to));
} }
else { else {
undo->setLabel(operationName); UndoTransaction undoTransaction(document, operationName, undo::ModifyDocument);
undo->setModification(undo::ModifyDocument); undoTransaction.pushUndoer
(new undoers::SetPaletteColors(undoTransaction.getObjects(),
undo->pushUndoer(new undoers::OpenGroup()); sprite, currentSpritePalette, from, to));
undo->pushUndoer(new undoers::SetPaletteColors(undo->getObjects(), undoTransaction.commit();
sprite, currentSpritePalette, from, to));
undo->pushUndoer(new undoers::CloseGroup());
} }
} }
@ -849,7 +845,7 @@ void PaletteEntryEditor::updateCurrentSpritePalette(const char* operationName)
m_redrawTimer.start(); m_redrawTimer.start();
m_redrawAll = false; m_redrawAll = false;
m_graftChange = true; m_implantChange = true;
} }
void PaletteEntryEditor::updateColorBar() void PaletteEntryEditor::updateColorBar()

View File

@ -20,10 +20,10 @@
#include "app.h" #include "app.h"
#include "commands/command.h" #include "commands/command.h"
#include "document_undo.h"
#include "document_wrappers.h" #include "document_wrappers.h"
#include "modules/gui.h" #include "modules/gui.h"
#include "raster/sprite.h" #include "raster/sprite.h"
#include "undo/undo_history.h"
#include "widgets/status_bar.h" #include "widgets/status_bar.h"
class RedoCommand : public Command class RedoCommand : public Command
@ -49,7 +49,7 @@ bool RedoCommand::onEnabled(Context* context)
ActiveDocumentWriter document(context); ActiveDocumentWriter document(context);
return return
document != NULL && document != NULL &&
document->getUndoHistory()->canRedo(); document->getUndo()->canRedo();
} }
void RedoCommand::onExecute(Context* context) void RedoCommand::onExecute(Context* context)
@ -58,9 +58,9 @@ void RedoCommand::onExecute(Context* context)
app_get_statusbar() app_get_statusbar()
->showTip(1000, "Redid %s", ->showTip(1000, "Redid %s",
document->getUndoHistory()->getNextRedoLabel()); document->getUndo()->getNextRedoLabel());
document->getUndoHistory()->doRedo(); document->getUndo()->doRedo();
document->generateMaskBoundaries(); document->generateMaskBoundaries();
document->destroyExtraCel(); // Regenerate extras document->destroyExtraCel(); // Regenerate extras

View File

@ -23,7 +23,7 @@
#include "modules/gui.h" #include "modules/gui.h"
#include "raster/mask.h" #include "raster/mask.h"
#include "raster/sprite.h" #include "raster/sprite.h"
#include "undo/undo_history.h" #include "undo_transaction.h"
#include "undoers/set_mask.h" #include "undoers/set_mask.h"
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
@ -60,19 +60,18 @@ bool ReselectMaskCommand::onEnabled(Context* context)
void ReselectMaskCommand::onExecute(Context* context) void ReselectMaskCommand::onExecute(Context* context)
{ {
ActiveDocumentWriter document(context); ActiveDocumentWriter document(context);
undo::UndoHistory* undo = document->getUndoHistory(); {
UndoTransaction undo(document, "Mask Reselection", undo::DoesntModifyDocument);
if (undo.isEnabled())
undo.pushUndoer(new undoers::SetMask(undo.getObjects(), document));
// Undo // Make the mask visible again.
if (undo->isEnabled()) { document->setMaskVisible(true);
undo->setLabel("Mask Reselection");
undo->setModification(undo::DoesntModifyDocument); undo.commit();
undo->pushUndoer(new undoers::SetMask(undo->getObjects(), document));
} }
// Make the mask visible again.
document->setMaskVisible(true);
document->generateMaskBoundaries(); document->generateMaskBoundaries();
update_screen_for_document(document); update_screen_for_document(document);
} }

View File

@ -20,10 +20,10 @@
#include "app.h" #include "app.h"
#include "commands/command.h" #include "commands/command.h"
#include "document_undo.h"
#include "document_wrappers.h" #include "document_wrappers.h"
#include "modules/gui.h" #include "modules/gui.h"
#include "raster/sprite.h" #include "raster/sprite.h"
#include "undo/undo_history.h"
#include "widgets/status_bar.h" #include "widgets/status_bar.h"
class UndoCommand : public Command class UndoCommand : public Command
@ -49,7 +49,7 @@ bool UndoCommand::onEnabled(Context* context)
ActiveDocumentWriter document(context); ActiveDocumentWriter document(context);
return return
document != NULL && document != NULL &&
document->getUndoHistory()->canUndo(); document->getUndo()->canUndo();
} }
void UndoCommand::onExecute(Context* context) void UndoCommand::onExecute(Context* context)
@ -58,9 +58,9 @@ void UndoCommand::onExecute(Context* context)
app_get_statusbar() app_get_statusbar()
->showTip(1000, "Undid %s", ->showTip(1000, "Undid %s",
document->getUndoHistory()->getNextUndoLabel()); document->getUndo()->getNextUndoLabel());
document->getUndoHistory()->doUndo(); document->getUndo()->doUndo();
document->generateMaskBoundaries(); document->generateMaskBoundaries();
document->destroyExtraCel(); // Regenerate extras document->destroyExtraCel(); // Regenerate extras

View File

@ -35,10 +35,8 @@
#include "ui/region.h" #include "ui/region.h"
#include "ui/view.h" #include "ui/view.h"
#include "ui/widget.h" #include "ui/widget.h"
#include "undo/undo_history.h" #include "undo_transaction.h"
#include "undoers/close_group.h"
#include "undoers/image_area.h" #include "undoers/image_area.h"
#include "undoers/open_group.h"
#include "widgets/editor/editor.h" #include "widgets/editor/editor.h"
#include <cstdlib> #include <cstdlib>
@ -206,17 +204,16 @@ void FilterManagerImpl::apply()
} }
if (!cancelled) { if (!cancelled) {
undo::UndoHistory* undo = m_document->getUndoHistory(); UndoTransaction undo(m_document, m_filter->getName(), undo::ModifyDocument);
// Undo stuff // Undo stuff
if (undo->isEnabled()) { if (undo.isEnabled())
undo->setLabel(m_filter->getName()); undo.pushUndoer(new undoers::ImageArea(undo.getObjects(), m_src, m_x, m_y, m_w, m_h));
undo->setModification(undo::ModifyDocument);
undo->pushUndoer(new undoers::ImageArea(undo->getObjects(), m_src, m_x, m_y, m_w, m_h));
}
// Copy "dst" to "src" // Copy "dst" to "src"
image_copy(m_src, m_dst, 0, 0); image_copy(m_src, m_dst, 0, 0);
undo.commit();
} }
} }
@ -234,13 +231,7 @@ void FilterManagerImpl::applyToTarget()
// Initialize writting operation // Initialize writting operation
DocumentReader doc_reader(m_document); DocumentReader doc_reader(m_document);
DocumentWriter doc_writer(doc_reader); DocumentWriter doc_writer(doc_reader);
undo::UndoHistory* undo = m_document->getUndoHistory(); UndoTransaction undo(m_document, m_filter->getName(), undo::ModifyDocument);
// Open group of undo operations
if (images.size() > 1) {
if (undo->isEnabled())
undo->pushUndoer(new undoers::OpenGroup());
}
m_progressBase = 0.0f; m_progressBase = 0.0f;
m_progressWidth = 1.0f / images.size(); m_progressWidth = 1.0f / images.size();
@ -259,11 +250,7 @@ void FilterManagerImpl::applyToTarget()
m_progressBase += m_progressWidth; m_progressBase += m_progressWidth;
} }
// Close group of undo operations undo.commit();
if (images.size() > 1) {
if (undo->isEnabled())
undo->pushUndoer(new undoers::CloseGroup());
}
} }
void FilterManagerImpl::flush() void FilterManagerImpl::flush()

View File

@ -25,6 +25,7 @@
#include "commands/params.h" #include "commands/params.h"
#include "console.h" #include "console.h"
#include "document.h" #include "document.h"
#include "document_undo.h"
#include "document_wrappers.h" #include "document_wrappers.h"
#include "gfx/point.h" #include "gfx/point.h"
#include "gfx/rect.h" #include "gfx/rect.h"
@ -35,7 +36,6 @@
#include "skin/skin_theme.h" #include "skin/skin_theme.h"
#include "ui/gui.h" #include "ui/gui.h"
#include "ui_context.h" #include "ui_context.h"
#include "undo/undo_history.h"
#include "undo_transaction.h" #include "undo_transaction.h"
#include "util/celmove.h" #include "util/celmove.h"
#include "util/thmbnail.h" #include "util/thmbnail.h"
@ -713,11 +713,11 @@ bool AnimationEditor::onProcessMessage(Message* msg)
// Undo. // Undo.
if (command && strcmp(command->short_name(), CommandId::Undo) == 0) { if (command && strcmp(command->short_name(), CommandId::Undo) == 0) {
const DocumentReader document(const_cast<Document*>(m_document)); const DocumentReader document(const_cast<Document*>(m_document));
const undo::UndoHistory* undo = document->getUndoHistory(); const DocumentUndo* undo = document->getUndo();
if (undo->canUndo()) { if (undo->canUndo()) {
DocumentWriter document_writer(document); DocumentWriter document_writer(document);
undo::UndoHistory* undo_writer = document_writer->getUndoHistory(); DocumentUndo* undo_writer = document_writer->getUndo();
undo_writer->doUndo(); undo_writer->doUndo();
@ -732,11 +732,11 @@ bool AnimationEditor::onProcessMessage(Message* msg)
// Redo. // Redo.
if (command && strcmp(command->short_name(), CommandId::Redo) == 0) { if (command && strcmp(command->short_name(), CommandId::Redo) == 0) {
const DocumentReader document(const_cast<Document*>(m_document)); const DocumentReader document(const_cast<Document*>(m_document));
const undo::UndoHistory* undo = document->getUndoHistory(); const DocumentUndo* undo = document->getUndo();
if (undo->canRedo()) { if (undo->canRedo()) {
DocumentWriter document_writer(document); DocumentWriter document_writer(document);
undo::UndoHistory* undo_writer = document_writer->getUndoHistory(); DocumentUndo* undo_writer = document_writer->getUndo();
undo_writer->doRedo(); undo_writer->doRedo();

View File

@ -37,7 +37,7 @@
#include "ui/label.h" #include "ui/label.h"
#include "ui/slider.h" #include "ui/slider.h"
#include "ui/widget.h" #include "ui/widget.h"
#include "undo/undo_history.h" #include "undo_transaction.h"
#include "undoers/set_mask.h" #include "undoers/set_mask.h"
#include "util/misc.h" #include "util/misc.h"
#include "widgets/color_bar.h" #include "widgets/color_bar.h"
@ -139,13 +139,10 @@ void dialogs_mask_color(Document* document)
if (window->get_killer() == button_ok) { if (window->get_killer() == button_ok) {
DocumentWriter documentWriter(documentReader); DocumentWriter documentWriter(documentReader);
undo::UndoHistory* undo = document->getUndoHistory(); UndoTransaction undo(document, "Mask by Color", undo::DoesntModifyDocument);
if (undo->isEnabled()) { if (undo.isEnabled())
undo->setLabel("Mask by Color"); undo.pushUndoer(new undoers::SetMask(undo.getObjects(), document));
undo->setModification(undo::DoesntModifyDocument);
undo->pushUndoer(new undoers::SetMask(undo->getObjects(), document));
}
// Change the mask // Change the mask
{ {
@ -153,6 +150,8 @@ void dialogs_mask_color(Document* document)
document->setMask(mask); document->setMask(mask);
} }
undo.commit();
set_config_color("MaskColor", "Color", button_color->getColor()); set_config_color("MaskColor", "Color", button_color->getColor());
set_config_int("MaskColor", "Tolerance", slider_tolerance->getValue()); set_config_int("MaskColor", "Tolerance", slider_tolerance->getValue());
set_config_bool("MaskColor", "Preview", check_preview->isSelected()); set_config_bool("MaskColor", "Preview", check_preview->isSelected());

View File

@ -24,29 +24,23 @@
#include "base/mutex.h" #include "base/mutex.h"
#include "base/scoped_lock.h" #include "base/scoped_lock.h"
#include "base/unique_ptr.h" #include "base/unique_ptr.h"
#include "document_undo.h"
#include "file/format_options.h" #include "file/format_options.h"
#include "flatten.h" #include "flatten.h"
#include "objects_container_impl.h"
#include "raster/cel.h" #include "raster/cel.h"
#include "raster/layer.h" #include "raster/layer.h"
#include "raster/mask.h" #include "raster/mask.h"
#include "raster/palette.h" #include "raster/palette.h"
#include "raster/sprite.h" #include "raster/sprite.h"
#include "raster/stock.h" #include "raster/stock.h"
#include "undo/undo_history.h"
#include "undoers/add_image.h" #include "undoers/add_image.h"
#include "undoers/add_layer.h" #include "undoers/add_layer.h"
#include "util/boundary.h" #include "util/boundary.h"
#include <allegro/config.h> // TODO remove this when get_config_int() is removed from here
using namespace undo;
Document::Document(Sprite* sprite) Document::Document(Sprite* sprite)
: m_id(WithoutDocumentId) : m_id(WithoutDocumentId)
, m_sprite(sprite) , m_sprite(sprite)
, m_objects(new ObjectsContainerImpl) , m_undo(new DocumentUndo)
, m_undoHistory(new UndoHistory(m_objects, this))
, m_filename("Sprite") , m_filename("Sprite")
, m_associated_to_file(false) , m_associated_to_file(false)
, m_mutex(new Mutex) , m_mutex(new Mutex)
@ -147,7 +141,7 @@ void Document::setFilename(const char* filename)
bool Document::isModified() const bool Document::isModified() const
{ {
return !m_undoHistory->isSavedState(); return !m_undo->isSavedState();
} }
bool Document::isAssociatedToFile() const bool Document::isAssociatedToFile() const
@ -157,7 +151,7 @@ bool Document::isAssociatedToFile() const
void Document::markAsSaved() void Document::markAsSaved()
{ {
m_undoHistory->markSavedState(); m_undo->markSavedState();
m_associated_to_file = true; m_associated_to_file = true;
} }
@ -324,7 +318,7 @@ void Document::resetTransformation()
void Document::copyLayerContent(const Layer* sourceLayer0, Document* destDoc, Layer* destLayer0) const void Document::copyLayerContent(const Layer* sourceLayer0, Document* destDoc, Layer* destLayer0) const
{ {
UndoHistory* undo = destDoc->getUndoHistory(); DocumentUndo* undo = destDoc->getUndo();
// Copy the layer name // Copy the layer name
destLayer0->setName(sourceLayer0->getName()); destLayer0->setName(sourceLayer0->getName());
@ -429,7 +423,7 @@ Document* Document::duplicate(DuplicateType type) const
case DuplicateExactCopy: case DuplicateExactCopy:
// Disable the undo // Disable the undo
documentCopy->getUndoHistory()->setEnabled(false); documentCopy->getUndo()->setEnabled(false);
// Copy the layer folder // Copy the layer folder
copyLayerContent(getSprite()->getFolder(), documentCopy, spriteCopy->getFolder()); copyLayerContent(getSprite()->getFolder(), documentCopy, spriteCopy->getFolder());
@ -441,7 +435,7 @@ Document* Document::duplicate(DuplicateType type) const
} }
// Re-enable the undo // Re-enable the undo
documentCopy->getUndoHistory()->setEnabled(true); documentCopy->getUndo()->setEnabled(true);
break; break;
case DuplicateWithFlattenLayers: case DuplicateWithFlattenLayers:
@ -547,8 +541,3 @@ void Document::unlock()
ASSERT(false); ASSERT(false);
} }
} }
size_t Document::getUndoSizeLimit()
{
return ((size_t)get_config_int("Options", "UndoSizeLimit", 8))*1024*1024;
}

View File

@ -19,18 +19,17 @@
#ifndef DOCUMENT_H_INCLUDED #ifndef DOCUMENT_H_INCLUDED
#define DOCUMENT_H_INCLUDED #define DOCUMENT_H_INCLUDED
#include "base/compiler_specific.h"
#include "base/disable_copying.h" #include "base/disable_copying.h"
#include "base/shared_ptr.h" #include "base/shared_ptr.h"
#include "base/unique_ptr.h" #include "base/unique_ptr.h"
#include "document_id.h" #include "document_id.h"
#include "gfx/transformation.h" #include "gfx/transformation.h"
#include "raster/pixel_format.h" #include "raster/pixel_format.h"
#include "undo/undo_config_provider.h"
#include <string> #include <string>
class Cel; class Cel;
class DocumentUndo;
class FormatOptions; class FormatOptions;
class Image; class Image;
class Layer; class Layer;
@ -39,11 +38,6 @@ class Mutex;
class Sprite; class Sprite;
struct _BoundSeg; struct _BoundSeg;
namespace undo {
class ObjectsContainer;
class UndoHistory;
}
struct PreferredEditorSettings struct PreferredEditorSettings
{ {
int scroll_x; int scroll_x;
@ -60,7 +54,7 @@ enum DuplicateType
// An application document. It is the class used to contain one file // An application document. It is the class used to contain one file
// opened and being edited by the user (a sprite). // opened and being edited by the user (a sprite).
class Document : public undo::UndoConfigProvider class Document
{ {
public: public:
@ -83,10 +77,10 @@ public:
void setId(DocumentId id) { m_id = id; } void setId(DocumentId id) { m_id = id; }
const Sprite* getSprite() const { return m_sprite; } const Sprite* getSprite() const { return m_sprite; }
const undo::UndoHistory* getUndoHistory() const { return m_undoHistory; } const DocumentUndo* getUndo() const { return m_undo; }
Sprite* getSprite() { return m_sprite; } Sprite* getSprite() { return m_sprite; }
undo::UndoHistory* getUndoHistory() { return m_undoHistory; } DocumentUndo* getUndo() { return m_undo; }
void addSprite(Sprite* sprite); void addSprite(Sprite* sprite);
@ -180,23 +174,14 @@ public:
void unlock(); void unlock();
private: private:
size_t getUndoSizeLimit() OVERRIDE;
// Unique identifier for this document (it is assigned by Documents class). // Unique identifier for this document (it is assigned by Documents class).
DocumentId m_id; DocumentId m_id;
// The main sprite. // The main sprite.
UniquePtr<Sprite> m_sprite; UniquePtr<Sprite> m_sprite;
// Collection of objects used by UndoHistory to reference deleted // Undo and redo information about the document.
// objects that are re-created by an Undoer. The container keeps an UniquePtr<DocumentUndo> m_undo;
// ID that is saved in the serialization process, and loaded in the
// deserialization process. The ID can be used by different undoers
// to keep references to deleted objects.
UniquePtr<undo::ObjectsContainer> m_objects;
// Stack of undoers to undo operations.
UniquePtr<undo::UndoHistory> m_undoHistory;
// Document's file name (from where it was loaded, where it is saved). // Document's file name (from where it was loaded, where it is saved).
std::string m_filename; std::string m_filename;

127
src/document_undo.cpp Normal file
View File

@ -0,0 +1,127 @@
/* 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
*/
#include "config.h"
#include "document_undo.h"
#include "objects_container_impl.h"
#include "undo/undo_history.h"
#include "undoers/close_group.h"
#include <allegro/config.h> // TODO remove this when get_config_int() is removed from here
#include <cassert>
DocumentUndo::DocumentUndo()
: m_objects(new ObjectsContainerImpl)
, m_undoHistory(new undo::UndoHistory(m_objects, this))
, m_enabled(true)
{
}
bool DocumentUndo::canUndo() const
{
return m_undoHistory->canUndo();
}
bool DocumentUndo::canRedo() const
{
return m_undoHistory->canRedo();
}
void DocumentUndo::doUndo()
{
return m_undoHistory->doUndo();
}
void DocumentUndo::doRedo()
{
return m_undoHistory->doRedo();
}
void DocumentUndo::clearRedo()
{
return m_undoHistory->clearRedo();
}
bool DocumentUndo::isSavedState() const
{
return m_undoHistory->isSavedState();
}
void DocumentUndo::markSavedState()
{
return m_undoHistory->markSavedState();
}
undo::ObjectsContainer* DocumentUndo::getObjects() const
{
return m_undoHistory->getObjects();
}
void DocumentUndo::pushUndoer(undo::Undoer* undoer)
{
return m_undoHistory->pushUndoer(undoer);
}
bool DocumentUndo::implantUndoerInLastGroup(undo::Undoer* undoer)
{
return m_undoHistory->implantUndoerInLastGroup(undoer);
}
size_t DocumentUndo::getUndoSizeLimit()
{
return ((size_t)get_config_int("Options", "UndoSizeLimit", 8))*1024*1024;
}
const char* DocumentUndo::getNextUndoLabel() const
{
undo::Undoer* undoer = m_undoHistory->getNextUndoer();
if (undoer) {
if (undoers::CloseGroup* closeGroup = dynamic_cast<undoers::CloseGroup*>(undoer)) {
return closeGroup->getLabel();
}
else {
assert(false && "There are some action without a CloseGroup");
return "";
}
}
else {
assert(false && "There are some action without label");
return "";
}
}
const char* DocumentUndo::getNextRedoLabel() const
{
undo::Undoer* undoer = m_undoHistory->getNextRedoer();
if (undoer) {
if (undoers::CloseGroup* closeGroup = dynamic_cast<undoers::CloseGroup*>(undoer)) {
return closeGroup->getLabel();
}
else {
assert(false && "There are some action without a CloseGroup");
return "";
}
}
else {
assert(false && "There are some action without label");
return "";
}
}

79
src/document_undo.h Normal file
View File

@ -0,0 +1,79 @@
/* 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 DOCUMENT_UNDO_H_INCLUDED
#define DOCUMENT_UNDO_H_INCLUDED
#include "base/compiler_specific.h"
#include "base/disable_copying.h"
#include "base/unique_ptr.h"
#include "undo/undo_config_provider.h"
namespace undo {
class ObjectsContainer;
class UndoHistory;
class Undoer;
}
class DocumentUndo : public undo::UndoConfigProvider
{
public:
DocumentUndo();
bool isEnabled() const { return m_enabled; }
void setEnabled(bool state) { m_enabled = state; }
bool canUndo() const;
bool canRedo() const;
void doUndo();
void doRedo();
void clearRedo();
bool isSavedState() const;
void markSavedState();
undo::ObjectsContainer* getObjects() const;
void pushUndoer(undo::Undoer* undoer);
bool implantUndoerInLastGroup(undo::Undoer* undoer);
const char* getNextUndoLabel() const;
const char* getNextRedoLabel() const;
private:
size_t getUndoSizeLimit() OVERRIDE;
// Collection of objects used by UndoHistory to reference deleted
// objects that are re-created by an Undoer. The container keeps an
// ID that is saved in the serialization process, and loaded in the
// deserialization process. The ID can be used by different undoers
// to keep references to deleted objects.
UniquePtr<undo::ObjectsContainer> m_objects;
// Stack of undoers to undo operations.
UniquePtr<undo::UndoHistory> m_undoHistory;
bool m_enabled;
DISABLE_COPYING(DocumentUndo);
};
#endif

View File

@ -22,8 +22,8 @@
#include "app/color_utils.h" #include "app/color_utils.h"
#include "context.h" #include "context.h"
#include "document.h" #include "document.h"
#include "document_undo.h"
#include "raster/mask.h" #include "raster/mask.h"
#include "undo/undo_history.h"
#include "undoers/set_mask.h" #include "undoers/set_mask.h"
@ -261,7 +261,7 @@ public:
m_modify_selection = state; m_modify_selection = state;
if (state) { if (state) {
undo::UndoHistory* undo = loop->getDocument()->getUndoHistory(); DocumentUndo* undo = loop->getDocument()->getUndo();
if (undo->isEnabled()) if (undo->isEnabled())
undo->pushUndoer(new undoers::SetMask(undo->getObjects(), loop->getDocument())); undo->pushUndoer(new undoers::SetMask(undo->getObjects(), loop->getDocument()));

View File

@ -24,9 +24,6 @@ UndoHistory::UndoHistory(ObjectsContainer* objects, UndoConfigProvider* configPr
m_groupLevel = 0; m_groupLevel = 0;
m_diffCount = 0; m_diffCount = 0;
m_diffSaved = 0; m_diffSaved = 0;
m_enabled = true;
m_label = NULL;
m_modification = ModifyDocument;
m_undoers = new UndoersStack(this); m_undoers = new UndoersStack(this);
try { try {
@ -44,16 +41,6 @@ UndoHistory::~UndoHistory()
delete m_redoers; delete m_redoers;
} }
bool UndoHistory::isEnabled() const
{
return m_enabled ? true: false;
}
void UndoHistory::setEnabled(bool state)
{
m_enabled = state;
}
bool UndoHistory::canUndo() const bool UndoHistory::canUndo() const
{ {
return !m_undoers->empty(); return !m_undoers->empty();
@ -87,40 +74,20 @@ void UndoHistory::clearRedo()
m_diffSaved = -1; m_diffSaved = -1;
} }
const char* UndoHistory::getLabel() Undoer* UndoHistory::getNextUndoer()
{ {
return m_label; if (!m_undoers->empty())
return *m_undoers->begin();
else
return NULL;
} }
void UndoHistory::setLabel(const char* label) Undoer* UndoHistory::getNextRedoer()
{ {
m_label = label; if (!m_redoers->empty())
} return *m_redoers->begin();
else
Modification UndoHistory::getModification() return NULL;
{
return m_modification;
}
void UndoHistory::setModification(Modification mod)
{
m_modification = mod;
}
const char* UndoHistory::getNextUndoLabel() const
{
ASSERT(canUndo());
UndoersStack::Item* item = *m_undoers->begin();
return item->getLabel();
}
const char* UndoHistory::getNextRedoLabel() const
{
ASSERT(canRedo());
UndoersStack::Item* item = *m_redoers->begin();
return item->getLabel();
} }
bool UndoHistory::isSavedState() const bool UndoHistory::isSavedState() const
@ -141,20 +108,13 @@ void UndoHistory::runUndo(Direction direction)
do { do {
const char* itemLabel = NULL; const char* itemLabel = NULL;
Modification itemModification = DoesntModifyDocument;
if (!undoers->empty()) {
UndoersStack::Item* item = *undoers->begin();
itemLabel = item->getLabel();
itemModification = item->getModification();
}
Undoer* undoer = undoers->popUndoer(UndoersStack::PopFromHead); Undoer* undoer = undoers->popUndoer(UndoersStack::PopFromHead);
if (!undoer) if (!undoer)
break; break;
setLabel(itemLabel); Modification itemModification = DoesntModifyDocument;
setModification(itemModification); itemModification = undoer->getModification();
undoer->revert(getObjects(), redoers); undoer->revert(getObjects(), redoers);
@ -202,7 +162,7 @@ void UndoHistory::pushUndoer(Undoer* undoer)
postUndoerAddedEvent(undoer); postUndoerAddedEvent(undoer);
} }
bool UndoHistory::graftUndoerInLastGroup(Undoer* undoer) bool UndoHistory::implantUndoerInLastGroup(Undoer* undoer)
{ {
Undoer* lastUndoer = m_undoers->popUndoer(UndoersStack::PopFromHead); Undoer* lastUndoer = m_undoers->popUndoer(UndoersStack::PopFromHead);
bool result; bool result;
@ -241,7 +201,7 @@ void UndoHistory::postUndoerAddedEvent(Undoer* undoer)
// it has passed the undo-limit. // it has passed the undo-limit.
if (m_groupLevel == 0) { if (m_groupLevel == 0) {
// More differences. // More differences.
if (m_modification == ModifyDocument) if (undoer->getModification() == ModifyDocument)
m_diffCount++; m_diffCount++;
checkSizeLimit(); checkSizeLimit();

View File

@ -24,9 +24,6 @@ public:
UndoHistory(ObjectsContainer* objects, UndoConfigProvider* configProvider); UndoHistory(ObjectsContainer* objects, UndoConfigProvider* configProvider);
virtual ~UndoHistory(); virtual ~UndoHistory();
bool isEnabled() const;
void setEnabled(bool state);
bool canUndo() const; bool canUndo() const;
bool canRedo() const; bool canRedo() const;
@ -35,18 +32,8 @@ public:
void clearRedo(); void clearRedo();
// Current label for next added Undoers. Undoer* getNextUndoer();
const char* getLabel(); Undoer* getNextRedoer();
void setLabel(const char* label);
// Change the "modify saved status" flag to be assigned for next
// added items. When it is activated means that each added Undoer
// modifies the "saved status" of the document.
Modification getModification();
void setModification(Modification mod);
const char* getNextUndoLabel() const;
const char* getNextRedoLabel() const;
bool isSavedState() const; bool isSavedState() const;
void markSavedState(); void markSavedState();
@ -58,7 +45,7 @@ public:
// Special method to add new undoers inside the last added group. // Special method to add new undoers inside the last added group.
// Returns true if the undoer was added in a group. // Returns true if the undoer was added in a group.
bool graftUndoerInLastGroup(Undoer* undoer); bool implantUndoerInLastGroup(Undoer* undoer);
private: private:
enum Direction { UndoDirection, RedoDirection }; enum Direction { UndoDirection, RedoDirection };
@ -76,9 +63,6 @@ private:
int m_groupLevel; int m_groupLevel;
int m_diffCount; int m_diffCount;
int m_diffSaved; int m_diffSaved;
bool m_enabled; // Is undo enabled?
const char* m_label; // Current label to be applied to all next undo operations.
Modification m_modification; // Current label to be applied to all next undo operations.
UndoConfigProvider* m_configProvider; UndoConfigProvider* m_configProvider;
}; };

View File

@ -7,6 +7,8 @@
#ifndef UNDO_UNDOER_H_INCLUDED #ifndef UNDO_UNDOER_H_INCLUDED
#define UNDO_UNDOER_H_INCLUDED #define UNDO_UNDOER_H_INCLUDED
#include "undo/modification.h"
namespace undo { namespace undo {
class ObjectsContainer; class ObjectsContainer;
@ -30,6 +32,10 @@ public:
// using to revert the action. // using to revert the action.
virtual size_t getMemSize() const = 0; virtual size_t getMemSize() const = 0;
// Returns the kind of modification that this item does with the
// document.
virtual Modification getModification() const = 0;
// Returns true if this undoer is the first action of a group. // Returns true if this undoer is the first action of a group.
virtual bool isOpenGroup() const = 0; virtual bool isOpenGroup() const = 0;

View File

@ -26,10 +26,8 @@ UndoersStack::~UndoersStack()
void UndoersStack::clear() void UndoersStack::clear()
{ {
for (iterator it = begin(), end = this->end(); it != end; ++it) { for (iterator it = begin(), end = this->end(); it != end; ++it)
(*it)->getUndoer()->dispose(); // Delete the Undoer. (*it)->dispose(); // Delete the Undoer.
delete *it; // Delete the UndoersStack::Item.
}
m_size = 0; m_size = 0;
m_items.clear(); // Clear the list of items. m_items.clear(); // Clear the list of items.
@ -50,15 +48,7 @@ void UndoersStack::pushUndoer(Undoer* undoer)
ASSERT(undoer != NULL); ASSERT(undoer != NULL);
try { try {
Item* item = new Item(m_undoHistory->getLabel(), m_items.insert(begin(), undoer);
m_undoHistory->getModification(), undoer);
try {
m_items.insert(begin(), item);
}
catch (...) {
delete item;
throw;
}
} }
catch (...) { catch (...) {
undoer->dispose(); undoer->dispose();
@ -79,8 +69,7 @@ Undoer* UndoersStack::popUndoer(PopFrom popFrom)
else else
it = --end(); it = --end();
undoer = (*it)->getUndoer(); // Set the undoer to return. undoer = (*it); // Set the undoer to return.
delete *it; // Delete the UndoersStack::Item.
m_items.erase(it); // Erase the item from the stack. m_items.erase(it); // Erase the item from the stack.
m_size -= undoer->getMemSize(); // Reduce the stack size. m_size -= undoer->getMemSize(); // Reduce the stack size.
} }
@ -100,7 +89,7 @@ size_t UndoersStack::countUndoGroups() const
level = 0; level = 0;
do { do {
const Undoer* undoer = (*it)->getUndoer(); const Undoer* undoer = (*it);
++it; ++it;
if (undoer->isOpenGroup()) if (undoer->isOpenGroup())

View File

@ -7,7 +7,6 @@
#ifndef UNDO_UNDOERS_STACK_H_INCLUDED #ifndef UNDO_UNDOERS_STACK_H_INCLUDED
#define UNDO_UNDOERS_STACK_H_INCLUDED #define UNDO_UNDOERS_STACK_H_INCLUDED
#include "undo/modification.h"
#include "undo/undoers_collector.h" #include "undo/undoers_collector.h"
#include <vector> #include <vector>
@ -29,26 +28,7 @@ public:
PopFromTail PopFromTail
}; };
// One item in the stack (label + Undoer) typedef std::vector<Undoer*> Items;
class Item
{
public:
Item(const char* label, Modification mod, Undoer* undoer)
: m_label(label)
, m_mod(mod)
, m_undoer(undoer) { }
const char* getLabel() const { return m_label; }
Modification getModification() const { return m_mod; }
Undoer* getUndoer() const { return m_undoer; }
private:
const char* m_label;
Modification m_mod;
Undoer* m_undoer;
};
typedef std::vector<Item*> Items;
typedef Items::iterator iterator; typedef Items::iterator iterator;
typedef Items::const_iterator const_iterator; typedef Items::const_iterator const_iterator;

View File

@ -22,6 +22,7 @@
#include "base/unique_ptr.h" #include "base/unique_ptr.h"
#include "document.h" #include "document.h"
#include "document_undo.h"
#include "raster/algorithm/flip_image.h" #include "raster/algorithm/flip_image.h"
#include "raster/blend.h" #include "raster/blend.h"
#include "raster/cel.h" #include "raster/cel.h"
@ -64,21 +65,20 @@
#include "undoers/set_total_frames.h" #include "undoers/set_total_frames.h"
UndoTransaction::UndoTransaction(Document* document, const char* label, undo::Modification modification) UndoTransaction::UndoTransaction(Document* document, const char* label, undo::Modification modification)
: m_label(label)
, m_modification(modification)
{ {
ASSERT(label != NULL); ASSERT(label != NULL);
m_document = document; m_document = document;
m_sprite = document->getSprite(); m_sprite = document->getSprite();
m_undoHistory = document->getUndoHistory(); m_undo = document->getUndo();
m_closed = false; m_closed = false;
m_committed = false; m_committed = false;
m_enabledFlag = m_undoHistory->isEnabled(); m_enabledFlag = m_undo->isEnabled();
if (isEnabled()) { if (isEnabled())
m_undoHistory->setLabel(label); m_undo->pushUndoer(new undoers::OpenGroup(m_label, m_modification));
m_undoHistory->setModification(modification);
m_undoHistory->pushUndoer(new undoers::OpenGroup());
}
} }
UndoTransaction::~UndoTransaction() UndoTransaction::~UndoTransaction()
@ -106,7 +106,7 @@ void UndoTransaction::closeUndoGroup()
if (isEnabled()) { if (isEnabled()) {
// Close the undo information. // Close the undo information.
m_undoHistory->pushUndoer(new undoers::CloseGroup()); m_undo->pushUndoer(new undoers::CloseGroup(m_label, m_modification));
m_closed = true; m_closed = true;
} }
} }
@ -132,21 +132,31 @@ void UndoTransaction::rollback()
closeUndoGroup(); closeUndoGroup();
// Undo the group of operations. // Undo the group of operations.
m_undoHistory->doUndo(); m_undo->doUndo();
// Clear the redo (sorry to the user, here we lost the old redo // Clear the redo (sorry to the user, here we lost the old redo
// information). // information).
m_undoHistory->clearRedo(); m_undo->clearRedo();
} }
} }
void UndoTransaction::pushUndoer(undo::Undoer* undoer)
{
m_undo->pushUndoer(undoer);
}
undo::ObjectsContainer* UndoTransaction::getObjects() const
{
return m_undo->getObjects();
}
void UndoTransaction::setNumberOfFrames(int frames) void UndoTransaction::setNumberOfFrames(int frames)
{ {
ASSERT(frames >= 1); ASSERT(frames >= 1);
// Save in undo the current totalFrames property // Save in undo the current totalFrames property
if (isEnabled()) if (isEnabled())
m_undoHistory->pushUndoer(new undoers::SetTotalFrames(m_undoHistory->getObjects(), m_sprite)); m_undo->pushUndoer(new undoers::SetTotalFrames(m_undo->getObjects(), m_sprite));
// Change the property // Change the property
m_sprite->setTotalFrames(frames); m_sprite->setTotalFrames(frames);
@ -157,7 +167,7 @@ void UndoTransaction::setCurrentFrame(int frame)
ASSERT(frame >= 0); ASSERT(frame >= 0);
if (isEnabled()) if (isEnabled())
m_undoHistory->pushUndoer(new undoers::SetCurrentFrame(m_undoHistory->getObjects(), m_sprite)); m_undo->pushUndoer(new undoers::SetCurrentFrame(m_undo->getObjects(), m_sprite));
m_sprite->setCurrentFrame(frame); m_sprite->setCurrentFrame(frame);
} }
@ -171,8 +181,8 @@ void UndoTransaction::setCurrentFrame(int frame)
void UndoTransaction::setCurrentLayer(Layer* layer) void UndoTransaction::setCurrentLayer(Layer* layer)
{ {
if (isEnabled()) if (isEnabled())
m_undoHistory->pushUndoer(new undoers::SetCurrentLayer( m_undo->pushUndoer(new undoers::SetCurrentLayer(
m_undoHistory->getObjects(), m_sprite)); m_undo->getObjects(), m_sprite));
m_sprite->setCurrentLayer(layer); m_sprite->setCurrentLayer(layer);
} }
@ -183,7 +193,7 @@ void UndoTransaction::setSpriteSize(int w, int h)
ASSERT(h > 0); ASSERT(h > 0);
if (isEnabled()) if (isEnabled())
m_undoHistory->pushUndoer(new undoers::SetSpriteSize(m_undoHistory->getObjects(), m_sprite)); m_undo->pushUndoer(new undoers::SetSpriteSize(m_undo->getObjects(), m_sprite));
m_sprite->setSize(w, h); m_sprite->setSize(w, h);
} }
@ -242,7 +252,7 @@ void UndoTransaction::setPixelFormat(PixelFormat newFormat, DitheringMethod dith
// Change pixel format of the stock of images. // Change pixel format of the stock of images.
if (isEnabled()) if (isEnabled())
m_undoHistory->pushUndoer(new undoers::SetStockPixelFormat(m_undoHistory->getObjects(), m_sprite->getStock())); m_undo->pushUndoer(new undoers::SetStockPixelFormat(m_undo->getObjects(), m_sprite->getStock()));
m_sprite->getStock()->setPixelFormat(newFormat); m_sprite->getStock()->setPixelFormat(newFormat);
@ -264,7 +274,7 @@ void UndoTransaction::setPixelFormat(PixelFormat newFormat, DitheringMethod dith
// Change sprite's pixel format. // Change sprite's pixel format.
if (isEnabled()) if (isEnabled())
m_undoHistory->pushUndoer(new undoers::SetSpritePixelFormat(m_undoHistory->getObjects(), m_sprite)); m_undo->pushUndoer(new undoers::SetSpritePixelFormat(m_undo->getObjects(), m_sprite));
m_sprite->setPixelFormat(newFormat); m_sprite->setPixelFormat(newFormat);
@ -280,12 +290,12 @@ void UndoTransaction::setPixelFormat(PixelFormat newFormat, DitheringMethod dith
PalettesList palettes = m_sprite->getPalettes(); PalettesList palettes = m_sprite->getPalettes();
for (PalettesList::iterator it = palettes.begin(); it != palettes.end(); ++it) { for (PalettesList::iterator it = palettes.begin(); it != palettes.end(); ++it) {
Palette* palette = *it; Palette* palette = *it;
m_undoHistory->pushUndoer(new undoers::RemovePalette( m_undo->pushUndoer(new undoers::RemovePalette(
m_undoHistory->getObjects(), m_sprite, palette->getFrame())); m_undo->getObjects(), m_sprite, palette->getFrame()));
} }
m_undoHistory->pushUndoer(new undoers::AddPalette( m_undo->pushUndoer(new undoers::AddPalette(
m_undoHistory->getObjects(), m_sprite, 0)); m_undo->getObjects(), m_sprite, 0));
} }
// It's a UniquePtr because setPalette'll create a copy of "graypal". // It's a UniquePtr because setPalette'll create a copy of "graypal".
@ -310,7 +320,7 @@ int UndoTransaction::addImageInStock(Image* image)
int image_index = m_sprite->getStock()->addImage(image); int image_index = m_sprite->getStock()->addImage(image);
if (isEnabled()) if (isEnabled())
m_undoHistory->pushUndoer(new undoers::AddImage(m_undoHistory->getObjects(), m_undo->pushUndoer(new undoers::AddImage(m_undo->getObjects(),
m_sprite->getStock(), image_index)); m_sprite->getStock(), image_index));
return image_index; return image_index;
@ -327,7 +337,7 @@ void UndoTransaction::removeImageFromStock(int image_index)
ASSERT(image); ASSERT(image);
if (isEnabled()) if (isEnabled())
m_undoHistory->pushUndoer(new undoers::RemoveImage(m_undoHistory->getObjects(), m_undo->pushUndoer(new undoers::RemoveImage(m_undo->getObjects(),
m_sprite->getStock(), image_index)); m_sprite->getStock(), image_index));
m_sprite->getStock()->removeImage(image); m_sprite->getStock()->removeImage(image);
@ -342,7 +352,7 @@ void UndoTransaction::replaceStockImage(int image_index, Image* new_image)
// replace the image in the stock // replace the image in the stock
if (isEnabled()) if (isEnabled())
m_undoHistory->pushUndoer(new undoers::ReplaceImage(m_undoHistory->getObjects(), m_undo->pushUndoer(new undoers::ReplaceImage(m_undo->getObjects(),
m_sprite->getStock(), image_index)); m_sprite->getStock(), image_index));
m_sprite->getStock()->replaceImage(image_index, new_image); m_sprite->getStock()->replaceImage(image_index, new_image);
@ -361,7 +371,7 @@ LayerImage* UndoTransaction::newLayer()
// add the layer in the sprite set // add the layer in the sprite set
if (isEnabled()) if (isEnabled())
m_undoHistory->pushUndoer(new undoers::AddLayer(m_undoHistory->getObjects(), m_undo->pushUndoer(new undoers::AddLayer(m_undo->getObjects(),
m_sprite->getFolder(), layer)); m_sprite->getFolder(), layer));
m_sprite->getFolder()->add_layer(layer); m_sprite->getFolder()->add_layer(layer);
@ -400,7 +410,7 @@ void UndoTransaction::removeLayer(Layer* layer)
// remove the layer // remove the layer
if (isEnabled()) if (isEnabled())
m_undoHistory->pushUndoer(new undoers::RemoveLayer(m_undoHistory->getObjects(), m_undo->pushUndoer(new undoers::RemoveLayer(m_undo->getObjects(),
layer)); layer));
parent->remove_layer(layer); parent->remove_layer(layer);
@ -412,7 +422,7 @@ void UndoTransaction::removeLayer(Layer* layer)
void UndoTransaction::moveLayerAfter(Layer* layer, Layer* after_this) void UndoTransaction::moveLayerAfter(Layer* layer, Layer* after_this)
{ {
if (isEnabled()) if (isEnabled())
m_undoHistory->pushUndoer(new undoers::MoveLayer(m_undoHistory->getObjects(), layer)); m_undo->pushUndoer(new undoers::MoveLayer(m_undo->getObjects(), layer));
layer->get_parent()->move_layer(layer, after_this); layer->get_parent()->move_layer(layer, after_this);
} }
@ -501,7 +511,7 @@ void UndoTransaction::backgroundFromLayer(LayerImage* layer, int bgcolor)
if (bg_image->w == cel_image->w && if (bg_image->w == cel_image->w &&
bg_image->h == cel_image->h) { bg_image->h == cel_image->h) {
if (isEnabled()) if (isEnabled())
m_undoHistory->pushUndoer(new undoers::ImageArea(m_undoHistory->getObjects(), m_undo->pushUndoer(new undoers::ImageArea(m_undo->getObjects(),
cel_image, 0, 0, cel_image->w, cel_image->h)); cel_image, 0, 0, cel_image->w, cel_image->h));
image_copy(cel_image, bg_image, 0, 0); image_copy(cel_image, bg_image, 0, 0);
@ -540,8 +550,8 @@ void UndoTransaction::layerFromBackground()
ASSERT(m_sprite->getCurrentLayer()->is_background()); ASSERT(m_sprite->getCurrentLayer()->is_background());
if (isEnabled()) { if (isEnabled()) {
m_undoHistory->pushUndoer(new undoers::SetLayerFlags(m_undoHistory->getObjects(), m_sprite->getCurrentLayer())); m_undo->pushUndoer(new undoers::SetLayerFlags(m_undo->getObjects(), m_sprite->getCurrentLayer()));
m_undoHistory->pushUndoer(new undoers::SetLayerName(m_undoHistory->getObjects(), m_sprite->getCurrentLayer())); m_undo->pushUndoer(new undoers::SetLayerName(m_undo->getObjects(), m_sprite->getCurrentLayer()));
} }
m_sprite->getCurrentLayer()->set_background(false); m_sprite->getCurrentLayer()->set_background(false);
@ -568,13 +578,13 @@ void UndoTransaction::flattenLayers(int bgcolor)
background = new LayerImage(m_sprite); background = new LayerImage(m_sprite);
if (isEnabled()) if (isEnabled())
m_undoHistory->pushUndoer(new undoers::AddLayer(m_undoHistory->getObjects(), m_undo->pushUndoer(new undoers::AddLayer(m_undo->getObjects(),
m_sprite->getFolder(), background)); m_sprite->getFolder(), background));
m_sprite->getFolder()->add_layer(background); m_sprite->getFolder()->add_layer(background);
if (isEnabled()) if (isEnabled())
m_undoHistory->pushUndoer(new undoers::MoveLayer(m_undoHistory->getObjects(), m_undo->pushUndoer(new undoers::MoveLayer(m_undo->getObjects(),
background)); background));
background->configureAsBackground(); background->configureAsBackground();
@ -595,8 +605,8 @@ void UndoTransaction::flattenLayers(int bgcolor)
if (isEnabled()) { if (isEnabled()) {
Dirty* dirty = new Dirty(cel_image, image); Dirty* dirty = new Dirty(cel_image, image);
dirty->saveImagePixels(cel_image); dirty->saveImagePixels(cel_image);
m_undoHistory->pushUndoer(new undoers::DirtyArea( m_undo->pushUndoer(new undoers::DirtyArea(
m_undoHistory->getObjects(), cel_image, dirty)); m_undo->getObjects(), cel_image, dirty));
delete dirty; delete dirty;
} }
} }
@ -620,8 +630,8 @@ void UndoTransaction::flattenLayers(int bgcolor)
/* select the background */ /* select the background */
if (m_sprite->getCurrentLayer() != background) { if (m_sprite->getCurrentLayer() != background) {
if (isEnabled()) if (isEnabled())
m_undoHistory->pushUndoer(new undoers::SetCurrentLayer( m_undo->pushUndoer(new undoers::SetCurrentLayer(
m_undoHistory->getObjects(), m_sprite)); m_undo->getObjects(), m_sprite));
m_sprite->setCurrentLayer(background); m_sprite->setCurrentLayer(background);
} }
@ -637,7 +647,7 @@ void UndoTransaction::flattenLayers(int bgcolor)
// Remove the layer // Remove the layer
if (isEnabled()) if (isEnabled())
m_undoHistory->pushUndoer(new undoers::RemoveLayer(m_undoHistory->getObjects(), m_undo->pushUndoer(new undoers::RemoveLayer(m_undo->getObjects(),
old_layer)); old_layer));
m_sprite->getFolder()->remove_layer(old_layer); m_sprite->getFolder()->remove_layer(old_layer);
@ -651,9 +661,9 @@ void UndoTransaction::flattenLayers(int bgcolor)
void UndoTransaction::configureLayerAsBackground(LayerImage* layer) void UndoTransaction::configureLayerAsBackground(LayerImage* layer)
{ {
if (isEnabled()) { if (isEnabled()) {
m_undoHistory->pushUndoer(new undoers::SetLayerFlags(m_undoHistory->getObjects(), layer)); m_undo->pushUndoer(new undoers::SetLayerFlags(m_undo->getObjects(), layer));
m_undoHistory->pushUndoer(new undoers::SetLayerName(m_undoHistory->getObjects(), layer)); m_undo->pushUndoer(new undoers::SetLayerName(m_undo->getObjects(), layer));
m_undoHistory->pushUndoer(new undoers::MoveLayer(m_undoHistory->getObjects(), layer)); m_undo->pushUndoer(new undoers::MoveLayer(m_undo->getObjects(), layer));
} }
layer->configureAsBackground(); layer->configureAsBackground();
@ -787,7 +797,7 @@ void UndoTransaction::addCel(LayerImage* layer, Cel* cel)
ASSERT(cel); ASSERT(cel);
if (isEnabled()) if (isEnabled())
m_undoHistory->pushUndoer(new undoers::AddCel(m_undoHistory->getObjects(), m_undo->pushUndoer(new undoers::AddCel(m_undo->getObjects(),
layer, cel)); layer, cel));
layer->addCel(cel); layer->addCel(cel);
@ -815,7 +825,7 @@ void UndoTransaction::removeCel(LayerImage* layer, Cel* cel)
removeImageFromStock(cel->getImage()); removeImageFromStock(cel->getImage());
if (isEnabled()) if (isEnabled())
m_undoHistory->pushUndoer(new undoers::RemoveCel(m_undoHistory->getObjects(), m_undo->pushUndoer(new undoers::RemoveCel(m_undo->getObjects(),
layer, cel)); layer, cel));
// remove the cel from the layer // remove the cel from the layer
@ -831,7 +841,7 @@ void UndoTransaction::setCelFramePosition(Cel* cel, int frame)
ASSERT(frame >= 0); ASSERT(frame >= 0);
if (isEnabled()) if (isEnabled())
m_undoHistory->pushUndoer(new undoers::SetCelFrame(m_undoHistory->getObjects(), cel)); m_undo->pushUndoer(new undoers::SetCelFrame(m_undo->getObjects(), cel));
cel->setFrame(frame); cel->setFrame(frame);
} }
@ -841,7 +851,7 @@ void UndoTransaction::setCelPosition(Cel* cel, int x, int y)
ASSERT(cel); ASSERT(cel);
if (isEnabled()) if (isEnabled())
m_undoHistory->pushUndoer(new undoers::SetCelPosition(m_undoHistory->getObjects(), cel)); m_undo->pushUndoer(new undoers::SetCelPosition(m_undo->getObjects(), cel));
cel->setPosition(x, y); cel->setPosition(x, y);
} }
@ -849,8 +859,8 @@ void UndoTransaction::setCelPosition(Cel* cel, int x, int y)
void UndoTransaction::setFrameDuration(int frame, int msecs) void UndoTransaction::setFrameDuration(int frame, int msecs)
{ {
if (isEnabled()) if (isEnabled())
m_undoHistory->pushUndoer(new undoers::SetFrameDuration( m_undo->pushUndoer(new undoers::SetFrameDuration(
m_undoHistory->getObjects(), m_sprite, frame)); m_undo->getObjects(), m_sprite, frame));
m_sprite->setFrameDuration(frame, msecs); m_sprite->setFrameDuration(frame, msecs);
} }
@ -859,8 +869,8 @@ void UndoTransaction::setConstantFrameRate(int msecs)
{ {
if (isEnabled()) { if (isEnabled()) {
for (int fr=0; fr<m_sprite->getTotalFrames(); ++fr) for (int fr=0; fr<m_sprite->getTotalFrames(); ++fr)
m_undoHistory->pushUndoer(new undoers::SetFrameDuration( m_undo->pushUndoer(new undoers::SetFrameDuration(
m_undoHistory->getObjects(), m_sprite, fr)); m_undo->getObjects(), m_sprite, fr));
} }
m_sprite->setDurationForAllFrames(msecs); m_sprite->setDurationForAllFrames(msecs);
@ -1000,7 +1010,7 @@ void UndoTransaction::clearMask(int bgcolor)
// If the layer is the background then we clear the image. // If the layer is the background then we clear the image.
if (m_sprite->getCurrentLayer()->is_background()) { if (m_sprite->getCurrentLayer()->is_background()) {
if (isEnabled()) if (isEnabled())
m_undoHistory->pushUndoer(new undoers::ImageArea(m_undoHistory->getObjects(), m_undo->pushUndoer(new undoers::ImageArea(m_undo->getObjects(),
image, 0, 0, image->w, image->h)); image, 0, 0, image->w, image->h));
// clear all // clear all
@ -1026,7 +1036,7 @@ void UndoTransaction::clearMask(int bgcolor)
return; return;
if (isEnabled()) if (isEnabled())
m_undoHistory->pushUndoer(new undoers::ImageArea(m_undoHistory->getObjects(), m_undo->pushUndoer(new undoers::ImageArea(m_undo->getObjects(),
image, x1, y1, x2-x1+1, y2-y1+1)); image, x1, y1, x2-x1+1, y2-y1+1));
// clear the masked zones // clear the masked zones
@ -1053,9 +1063,9 @@ void UndoTransaction::flipImage(Image* image,
{ {
// Insert the undo operation. // Insert the undo operation.
if (isEnabled()) { if (isEnabled()) {
m_undoHistory->pushUndoer m_undo->pushUndoer
(new undoers::FlipImage (new undoers::FlipImage
(m_undoHistory->getObjects(), image, bounds, flipType)); (m_undo->getObjects(), image, bounds, flipType));
} }
// Flip the portion of the bitmap. // Flip the portion of the bitmap.
@ -1074,7 +1084,7 @@ void UndoTransaction::flipImageWithMask(Image* image, const Mask* mask, raster::
UniquePtr<Dirty> dirty((new Dirty(image, flippedImage))); UniquePtr<Dirty> dirty((new Dirty(image, flippedImage)));
dirty->saveImagePixels(image); dirty->saveImagePixels(image);
m_undoHistory->pushUndoer(new undoers::DirtyArea(m_undoHistory->getObjects(), image, dirty)); m_undo->pushUndoer(new undoers::DirtyArea(m_undo->getObjects(), image, dirty));
} }
// Copy the flipped image into the image specified as argument. // Copy the flipped image into the image specified as argument.
@ -1106,7 +1116,7 @@ void UndoTransaction::copyToCurrentMask(Mask* mask)
ASSERT(mask); ASSERT(mask);
if (isEnabled()) if (isEnabled())
m_undoHistory->pushUndoer(new undoers::SetMask(m_undoHistory->getObjects(), m_undo->pushUndoer(new undoers::SetMask(m_undo->getObjects(),
m_document)); m_document));
m_document->getMask()->copyFrom(mask); m_document->getMask()->copyFrom(mask);
@ -1117,7 +1127,7 @@ void UndoTransaction::setMaskPosition(int x, int y)
ASSERT(m_document->getMask()); ASSERT(m_document->getMask());
if (isEnabled()) if (isEnabled())
m_undoHistory->pushUndoer(new undoers::SetMaskPosition(m_undoHistory->getObjects(), m_document)); m_undo->pushUndoer(new undoers::SetMaskPosition(m_undo->getObjects(), m_document));
m_document->getMask()->setOrigin(x, y); m_document->getMask()->setOrigin(x, y);
m_document->resetTransformation(); m_document->resetTransformation();
@ -1126,7 +1136,7 @@ void UndoTransaction::setMaskPosition(int x, int y)
void UndoTransaction::deselectMask() void UndoTransaction::deselectMask()
{ {
if (isEnabled()) if (isEnabled())
m_undoHistory->pushUndoer(new undoers::SetMask(m_undoHistory->getObjects(), m_undo->pushUndoer(new undoers::SetMask(m_undo->getObjects(),
m_document)); m_document));
m_document->setMaskVisible(false); m_document->setMaskVisible(false);

View File

@ -27,6 +27,7 @@
class Cel; class Cel;
class Document; class Document;
class DocumentUndo;
class Image; class Image;
class Layer; class Layer;
class LayerImage; class LayerImage;
@ -34,7 +35,8 @@ class Mask;
class Sprite; class Sprite;
namespace undo { namespace undo {
class UndoHistory; class ObjectsContainer;
class Undoer;
} }
// High-level class to group a set of operations to modify the // High-level class to group a set of operations to modify the
@ -73,6 +75,9 @@ public:
// created). // created).
void commit(); void commit();
void pushUndoer(undo::Undoer* undoer);
undo::ObjectsContainer* getObjects() const;
// for sprite // for sprite
void setNumberOfFrames(int frames); void setNumberOfFrames(int frames);
void setCurrentFrame(int frame); void setCurrentFrame(int frame);
@ -135,10 +140,12 @@ private:
Document* m_document; Document* m_document;
Sprite* m_sprite; Sprite* m_sprite;
undo::UndoHistory* m_undoHistory; DocumentUndo* m_undo;
bool m_closed; bool m_closed;
bool m_committed; bool m_committed;
bool m_enabledFlag; bool m_enabledFlag;
const char* m_label;
undo::Modification m_modification;
}; };
#endif #endif

View File

@ -26,6 +26,12 @@
using namespace undo; using namespace undo;
using namespace undoers; using namespace undoers;
CloseGroup::CloseGroup(const char* label, undo::Modification modification)
: m_label(label)
, m_modification(modification)
{
}
void CloseGroup::dispose() void CloseGroup::dispose()
{ {
delete this; delete this;
@ -33,5 +39,5 @@ void CloseGroup::dispose()
void CloseGroup::revert(ObjectsContainer* objects, UndoersCollector* redoers) void CloseGroup::revert(ObjectsContainer* objects, UndoersCollector* redoers)
{ {
redoers->pushUndoer(new OpenGroup()); redoers->pushUndoer(new OpenGroup(m_label, m_modification));
} }

View File

@ -27,11 +27,19 @@ namespace undoers {
class CloseGroup : public undo::Undoer class CloseGroup : public undo::Undoer
{ {
public: public:
CloseGroup(const char* label, undo::Modification modification);
void dispose() OVERRIDE; void dispose() OVERRIDE;
size_t getMemSize() const OVERRIDE { return sizeof(*this); } size_t getMemSize() const OVERRIDE { return sizeof(*this); }
undo::Modification getModification() const { return m_modification; }
bool isOpenGroup() const OVERRIDE { return false; } bool isOpenGroup() const OVERRIDE { return false; }
bool isCloseGroup() const OVERRIDE { return true; } bool isCloseGroup() const OVERRIDE { return true; }
void revert(undo::ObjectsContainer* objects, undo::UndoersCollector* redoers) OVERRIDE; void revert(undo::ObjectsContainer* objects, undo::UndoersCollector* redoers) OVERRIDE;
const char* getLabel() { return m_label; }
private:
const char* m_label;
undo::Modification m_modification;
}; };
} // namespace undoers } // namespace undoers

View File

@ -26,6 +26,12 @@
using namespace undo; using namespace undo;
using namespace undoers; using namespace undoers;
OpenGroup::OpenGroup(const char* label, undo::Modification modification)
: m_label(label)
, m_modification(modification)
{
}
void OpenGroup::dispose() void OpenGroup::dispose()
{ {
delete this; delete this;
@ -33,5 +39,5 @@ void OpenGroup::dispose()
void OpenGroup::revert(ObjectsContainer* objects, UndoersCollector* redoers) void OpenGroup::revert(ObjectsContainer* objects, UndoersCollector* redoers)
{ {
redoers->pushUndoer(new CloseGroup()); redoers->pushUndoer(new CloseGroup(m_label, m_modification));
} }

View File

@ -27,11 +27,19 @@ namespace undoers {
class OpenGroup : public undo::Undoer class OpenGroup : public undo::Undoer
{ {
public: public:
OpenGroup(const char* label, undo::Modification modification);
void dispose() OVERRIDE; void dispose() OVERRIDE;
size_t getMemSize() const OVERRIDE { return sizeof(*this); } size_t getMemSize() const OVERRIDE { return sizeof(*this); }
undo::Modification getModification() const { return m_modification; }
bool isOpenGroup() const OVERRIDE { return true; } bool isOpenGroup() const OVERRIDE { return true; }
bool isCloseGroup() const OVERRIDE { return false; } bool isCloseGroup() const OVERRIDE { return false; }
void revert(undo::ObjectsContainer* objects, undo::UndoersCollector* redoers) OVERRIDE; void revert(undo::ObjectsContainer* objects, undo::UndoersCollector* redoers) OVERRIDE;
const char* getLabel() { return m_label; }
private:
const char* m_label;
undo::Modification m_modification;
}; };
} // namespace undoers } // namespace undoers

View File

@ -17,6 +17,7 @@ namespace undoers {
class UndoerBase : public undo::Undoer class UndoerBase : public undo::Undoer
{ {
public: public:
undo::Modification getModification() const OVERRIDE { return undo::DoesntModifyDocument; }
bool isOpenGroup() const OVERRIDE { return false; } bool isOpenGroup() const OVERRIDE { return false; }
bool isCloseGroup() const OVERRIDE { return false; } bool isCloseGroup() const OVERRIDE { return false; }
}; };

View File

@ -31,11 +31,9 @@
#include "raster/layer.h" #include "raster/layer.h"
#include "raster/sprite.h" #include "raster/sprite.h"
#include "raster/stock.h" #include "raster/stock.h"
#include "undo/undo_history.h" #include "undo_transaction.h"
#include "undoers/add_cel.h" #include "undoers/add_cel.h"
#include "undoers/add_image.h" #include "undoers/add_image.h"
#include "undoers/close_group.h"
#include "undoers/open_group.h"
#include "undoers/remove_cel.h" #include "undoers/remove_cel.h"
#include "undoers/remove_image.h" #include "undoers/remove_image.h"
#include "undoers/replace_image.h" #include "undoers/replace_image.h"
@ -52,7 +50,7 @@ static Layer* dst_layer = NULL;
static int src_frame = 0; static int src_frame = 0;
static int dst_frame = 0; static int dst_frame = 0;
static void remove_cel(Sprite* sprite, undo::UndoHistory* undo, LayerImage *layer, Cel *cel); static void remove_cel(Sprite* sprite, UndoTransaction& undo, LayerImage *layer, Cel *cel);
void set_frame_to_handle(Layer *_src_layer, int _src_frame, void set_frame_to_handle(Layer *_src_layer, int _src_frame,
Layer *_dst_layer, int _dst_frame) Layer *_dst_layer, int _dst_frame)
@ -66,7 +64,6 @@ void set_frame_to_handle(Layer *_src_layer, int _src_frame,
void move_cel(DocumentWriter& document) void move_cel(DocumentWriter& document)
{ {
Sprite* sprite = document->getSprite(); Sprite* sprite = document->getSprite();
undo::UndoHistory* undo = document->getUndoHistory();
Cel *src_cel, *dst_cel; Cel *src_cel, *dst_cel;
ASSERT(src_layer != NULL); ASSERT(src_layer != NULL);
@ -82,13 +79,10 @@ void move_cel(DocumentWriter& document)
src_cel = static_cast<LayerImage*>(src_layer)->getCel(src_frame); src_cel = static_cast<LayerImage*>(src_layer)->getCel(src_frame);
dst_cel = static_cast<LayerImage*>(dst_layer)->getCel(dst_frame); dst_cel = static_cast<LayerImage*>(dst_layer)->getCel(dst_frame);
if (undo->isEnabled()) { UndoTransaction undo(document, "Move Cel", undo::ModifyDocument);
undo->setLabel("Move Cel"); if (undo.isEnabled()) {
undo->setModification(undo::ModifyDocument); undo.pushUndoer(new undoers::SetCurrentLayer(undo.getObjects(), sprite));
undo->pushUndoer(new undoers::OpenGroup()); undo.pushUndoer(new undoers::SetCurrentFrame(undo.getObjects(), sprite));
undo->pushUndoer(new undoers::SetCurrentLayer(undo->getObjects(), sprite));
undo->pushUndoer(new undoers::SetCurrentFrame(undo->getObjects(), sprite));
} }
sprite->setCurrentLayer(dst_layer); sprite->setCurrentLayer(dst_layer);
@ -102,15 +96,15 @@ void move_cel(DocumentWriter& document)
/* move the cel in the same layer */ /* move the cel in the same layer */
if (src_cel != NULL) { if (src_cel != NULL) {
if (src_layer == dst_layer) { if (src_layer == dst_layer) {
if (undo->isEnabled()) if (undo.isEnabled())
undo->pushUndoer(new undoers::SetCelFrame(undo->getObjects(), src_cel)); undo.pushUndoer(new undoers::SetCelFrame(undo.getObjects(), src_cel));
src_cel->setFrame(dst_frame); src_cel->setFrame(dst_frame);
} }
/* move the cel in different layers */ /* move the cel in different layers */
else { else {
if (undo->isEnabled()) if (undo.isEnabled())
undo->pushUndoer(new undoers::RemoveCel(undo->getObjects(), src_layer, src_cel)); undo.pushUndoer(new undoers::RemoveCel(undo.getObjects(), src_layer, src_cel));
static_cast<LayerImage*>(src_layer)->removeCel(src_cel); static_cast<LayerImage*>(src_layer)->removeCel(src_cel);
src_cel->setFrame(dst_frame); src_cel->setFrame(dst_frame);
@ -127,11 +121,11 @@ void move_cel(DocumentWriter& document)
sprite->getWidth(), sprite->getWidth(),
sprite->getHeight(), 0); sprite->getHeight(), 0);
if (undo->isEnabled()) { if (undo.isEnabled()) {
undo->pushUndoer(new undoers::ReplaceImage(undo->getObjects(), undo.pushUndoer(new undoers::ReplaceImage(undo.getObjects(),
sprite->getStock(), src_cel->getImage())); sprite->getStock(), src_cel->getImage()));
undo->pushUndoer(new undoers::SetCelPosition(undo->getObjects(), src_cel)); undo.pushUndoer(new undoers::SetCelPosition(undo.getObjects(), src_cel));
undo->pushUndoer(new undoers::SetCelOpacity(undo->getObjects(), src_cel)); undo.pushUndoer(new undoers::SetCelOpacity(undo.getObjects(), src_cel));
} }
image_clear(dst_image, app_get_color_to_clear_layer(dst_layer)); image_clear(dst_image, app_get_color_to_clear_layer(dst_layer));
@ -144,15 +138,14 @@ void move_cel(DocumentWriter& document)
image_free(src_image); image_free(src_image);
} }
if (undo->isEnabled()) if (undo.isEnabled())
undo->pushUndoer(new undoers::AddCel(undo->getObjects(), dst_layer, src_cel)); undo.pushUndoer(new undoers::AddCel(undo.getObjects(), dst_layer, src_cel));
static_cast<LayerImage*>(dst_layer)->addCel(src_cel); static_cast<LayerImage*>(dst_layer)->addCel(src_cel);
} }
} }
if (undo->isEnabled()) undo.commit();
undo->pushUndoer(new undoers::CloseGroup());
set_frame_to_handle(NULL, 0, NULL, 0); set_frame_to_handle(NULL, 0, NULL, 0);
} }
@ -160,7 +153,7 @@ void move_cel(DocumentWriter& document)
void copy_cel(DocumentWriter& document) void copy_cel(DocumentWriter& document)
{ {
Sprite* sprite = document->getSprite(); Sprite* sprite = document->getSprite();
undo::UndoHistory* undo = document->getUndoHistory(); UndoTransaction undo(document, "Move Cel", undo::ModifyDocument);
Cel *src_cel, *dst_cel; Cel *src_cel, *dst_cel;
ASSERT(src_layer != NULL); ASSERT(src_layer != NULL);
@ -171,13 +164,9 @@ void copy_cel(DocumentWriter& document)
src_cel = static_cast<LayerImage*>(src_layer)->getCel(src_frame); src_cel = static_cast<LayerImage*>(src_layer)->getCel(src_frame);
dst_cel = static_cast<LayerImage*>(dst_layer)->getCel(dst_frame); dst_cel = static_cast<LayerImage*>(dst_layer)->getCel(dst_frame);
if (undo->isEnabled()) { if (undo.isEnabled()) {
undo->setLabel("Move Cel"); undo.pushUndoer(new undoers::SetCurrentLayer(undo.getObjects(), sprite));
undo->setModification(undo::ModifyDocument); undo.pushUndoer(new undoers::SetCurrentFrame(undo.getObjects(), sprite));
undo->pushUndoer(new undoers::OpenGroup());
undo->pushUndoer(new undoers::SetCurrentLayer(undo->getObjects(), sprite));
undo->pushUndoer(new undoers::SetCurrentFrame(undo->getObjects(), sprite));
} }
sprite->setCurrentLayer(dst_layer); sprite->setCurrentLayer(dst_layer);
@ -224,8 +213,8 @@ void copy_cel(DocumentWriter& document)
/* add the image in the stock */ /* add the image in the stock */
image_index = sprite->getStock()->addImage(dst_image); image_index = sprite->getStock()->addImage(dst_image);
if (undo->isEnabled()) if (undo.isEnabled())
undo->pushUndoer(new undoers::AddImage(undo->getObjects(), undo.pushUndoer(new undoers::AddImage(undo.getObjects(),
sprite->getStock(), image_index)); sprite->getStock(), image_index));
/* create the new cel */ /* create the new cel */
@ -233,19 +222,18 @@ void copy_cel(DocumentWriter& document)
dst_cel->setPosition(dst_cel_x, dst_cel_y); dst_cel->setPosition(dst_cel_x, dst_cel_y);
dst_cel->setOpacity(dst_cel_opacity); dst_cel->setOpacity(dst_cel_opacity);
if (undo->isEnabled()) if (undo.isEnabled())
undo->pushUndoer(new undoers::AddCel(undo->getObjects(), dst_layer, dst_cel)); undo.pushUndoer(new undoers::AddCel(undo.getObjects(), dst_layer, dst_cel));
static_cast<LayerImage*>(dst_layer)->addCel(dst_cel); static_cast<LayerImage*>(dst_layer)->addCel(dst_cel);
} }
if (undo->isEnabled()) undo.commit();
undo->pushUndoer(new undoers::CloseGroup());
set_frame_to_handle(NULL, 0, NULL, 0); set_frame_to_handle(NULL, 0, NULL, 0);
} }
static void remove_cel(Sprite* sprite, undo::UndoHistory* undo, LayerImage *layer, Cel *cel) static void remove_cel(Sprite* sprite, UndoTransaction& undo, LayerImage *layer, Cel *cel)
{ {
Image *image; Image *image;
Cel *it; Cel *it;
@ -264,25 +252,21 @@ static void remove_cel(Sprite* sprite, undo::UndoHistory* undo, LayerImage *laye
} }
} }
if (undo->isEnabled())
undo->pushUndoer(new undoers::OpenGroup());
if (!used) { if (!used) {
// If the image is only used by this cel, we can remove the // If the image is only used by this cel, we can remove the
// image from the stock. // image from the stock.
image = sprite->getStock()->getImage(cel->getImage()); image = sprite->getStock()->getImage(cel->getImage());
if (undo->isEnabled()) if (undo.isEnabled())
undo->pushUndoer(new undoers::RemoveImage(undo->getObjects(), undo.pushUndoer(new undoers::RemoveImage(undo.getObjects(),
sprite->getStock(), cel->getImage())); sprite->getStock(), cel->getImage()));
sprite->getStock()->removeImage(image); sprite->getStock()->removeImage(image);
image_free(image); image_free(image);
} }
if (undo->isEnabled()) { if (undo.isEnabled()) {
undo->pushUndoer(new undoers::RemoveCel(undo->getObjects(), layer, cel)); undo.pushUndoer(new undoers::RemoveCel(undo.getObjects(), layer, cel));
undo->pushUndoer(new undoers::CloseGroup());
} }
// Remove the cel // Remove the cel

View File

@ -27,16 +27,14 @@
#include "raster/layer.h" #include "raster/layer.h"
#include "raster/sprite.h" #include "raster/sprite.h"
#include "raster/stock.h" #include "raster/stock.h"
#include "undo/undo_history.h" #include "undo_transaction.h"
#include "undoers/add_cel.h" #include "undoers/add_cel.h"
#include "undoers/add_image.h" #include "undoers/add_image.h"
#include "undoers/close_group.h"
#include "undoers/dirty_area.h" #include "undoers/dirty_area.h"
#include "undoers/open_group.h"
#include "undoers/replace_image.h" #include "undoers/replace_image.h"
#include "undoers/set_cel_position.h" #include "undoers/set_cel_position.h"
ExpandCelCanvas::ExpandCelCanvas(Document* document, Sprite* sprite, Layer* layer, TiledMode tiledMode) ExpandCelCanvas::ExpandCelCanvas(Document* document, Sprite* sprite, Layer* layer, TiledMode tiledMode, UndoTransaction& undo)
: m_document(document) : m_document(document)
, m_sprite(sprite) , m_sprite(sprite)
, m_layer(layer) , m_layer(layer)
@ -45,6 +43,7 @@ ExpandCelCanvas::ExpandCelCanvas(Document* document, Sprite* sprite, Layer* laye
, m_celCreated(false) , m_celCreated(false)
, m_closed(false) , m_closed(false)
, m_committed(false) , m_committed(false)
, m_undo(undo)
{ {
if (m_layer->is_image()) { if (m_layer->is_image()) {
m_cel = static_cast<LayerImage*>(layer)->getCel(m_sprite->getCurrentFrame()); m_cel = static_cast<LayerImage*>(layer)->getCel(m_sprite->getCurrentFrame());
@ -116,8 +115,6 @@ void ExpandCelCanvas::commit()
ASSERT(!m_closed); ASSERT(!m_closed);
ASSERT(!m_committed); ASSERT(!m_committed);
undo::UndoHistory* undo = m_document->getUndoHistory();
// If the size of each image is the same, we can create an undo // If the size of each image is the same, we can create an undo
// with only the differences between both images. // with only the differences between both images.
if (m_cel->getX() == m_originalCelX && if (m_cel->getX() == m_originalCelX &&
@ -135,18 +132,16 @@ void ExpandCelCanvas::commit()
m_cel->setImage(m_sprite->getStock()->addImage(m_celImage)); m_cel->setImage(m_sprite->getStock()->addImage(m_celImage));
// Is the undo enabled?. // Is the undo enabled?.
if (undo->isEnabled()) { if (m_undo.isEnabled()) {
// We can temporary remove the cel. // We can temporary remove the cel.
static_cast<LayerImage*>(m_sprite->getCurrentLayer())->removeCel(m_cel); static_cast<LayerImage*>(m_sprite->getCurrentLayer())->removeCel(m_cel);
// We create the undo information (for the new m_celImage // We create the undo information (for the new m_celImage
// in the stock and the new cel in the layer)... // in the stock and the new cel in the layer)...
undo->pushUndoer(new undoers::OpenGroup()); m_undo.pushUndoer(new undoers::AddImage(m_undo.getObjects(),
undo->pushUndoer(new undoers::AddImage(undo->getObjects(), m_sprite->getStock(), m_cel->getImage()));
m_sprite->getStock(), m_cel->getImage())); m_undo.pushUndoer(new undoers::AddCel(m_undo.getObjects(),
undo->pushUndoer(new undoers::AddCel(undo->getObjects(), m_sprite->getCurrentLayer(), m_cel));
m_sprite->getCurrentLayer(), m_cel));
undo->pushUndoer(new undoers::CloseGroup());
// And finally we add the cel again in the layer. // And finally we add the cel again in the layer.
static_cast<LayerImage*>(m_sprite->getCurrentLayer())->addCel(m_cel); static_cast<LayerImage*>(m_sprite->getCurrentLayer())->addCel(m_cel);
@ -155,12 +150,12 @@ void ExpandCelCanvas::commit()
// If the m_celImage was already created before the whole process... // If the m_celImage was already created before the whole process...
else { else {
// Add to the undo history the differences between m_celImage and m_dstImage // Add to the undo history the differences between m_celImage and m_dstImage
if (undo->isEnabled()) { if (m_undo.isEnabled()) {
UniquePtr<Dirty> dirty(new Dirty(m_celImage, m_dstImage)); UniquePtr<Dirty> dirty(new Dirty(m_celImage, m_dstImage));
dirty->saveImagePixels(m_celImage); dirty->saveImagePixels(m_celImage);
if (dirty != NULL) if (dirty != NULL)
undo->pushUndoer(new undoers::DirtyArea(undo->getObjects(), m_celImage, dirty)); m_undo.pushUndoer(new undoers::DirtyArea(m_undo.getObjects(), m_celImage, dirty));
} }
// Copy the destination to the cel image. // Copy the destination to the cel image.
@ -170,23 +165,20 @@ void ExpandCelCanvas::commit()
// If the size of both images are different, we have to // If the size of both images are different, we have to
// replace the entire image. // replace the entire image.
else { else {
if (undo->isEnabled()) { if (m_undo.isEnabled()) {
undo->pushUndoer(new undoers::OpenGroup());
if (m_cel->getX() != m_originalCelX || if (m_cel->getX() != m_originalCelX ||
m_cel->getY() != m_originalCelY) { m_cel->getY() != m_originalCelY) {
int x = m_cel->getX(); int x = m_cel->getX();
int y = m_cel->getY(); int y = m_cel->getY();
m_cel->setPosition(m_originalCelX, m_originalCelY); m_cel->setPosition(m_originalCelX, m_originalCelY);
undo->pushUndoer(new undoers::SetCelPosition(undo->getObjects(), m_cel)); m_undo.pushUndoer(new undoers::SetCelPosition(m_undo.getObjects(), m_cel));
m_cel->setPosition(x, y); m_cel->setPosition(x, y);
} }
undo->pushUndoer(new undoers::ReplaceImage(undo->getObjects(), m_undo.pushUndoer(new undoers::ReplaceImage(m_undo.getObjects(),
m_sprite->getStock(), m_cel->getImage())); m_sprite->getStock(), m_cel->getImage()));
undo->pushUndoer(new undoers::CloseGroup());
} }
// Replace the image in the stock. // Replace the image in the stock.

View File

@ -26,6 +26,7 @@ class Document;
class Image; class Image;
class Layer; class Layer;
class Sprite; class Sprite;
class UndoTransaction;
// This class can be used to expand the canvas of the current cel to // This class can be used to expand the canvas of the current cel to
// the visible portion of sprite. If the user cancels the operation, // the visible portion of sprite. If the user cancels the operation,
@ -36,7 +37,7 @@ class Sprite;
class ExpandCelCanvas class ExpandCelCanvas
{ {
public: public:
ExpandCelCanvas(Document* document, Sprite* sprite, Layer* layer, TiledMode tiledMode); ExpandCelCanvas(Document* document, Sprite* sprite, Layer* layer, TiledMode tiledMode, UndoTransaction& undo);
~ExpandCelCanvas(); ~ExpandCelCanvas();
// Commit changes made in getDestCanvas() in the cel's image. Adds // Commit changes made in getDestCanvas() in the cel's image. Adds
@ -75,6 +76,7 @@ private:
Image* m_dstImage; Image* m_dstImage;
bool m_closed; bool m_closed;
bool m_committed; bool m_committed;
UndoTransaction& m_undo;
}; };
#endif #endif

View File

@ -448,7 +448,8 @@ void PixelsMovement::stampImage()
// Expand the canvas to paste the image in the fully visible // Expand the canvas to paste the image in the fully visible
// portion of sprite. // portion of sprite.
ExpandCelCanvas expandCelCanvas(documentWriter, m_sprite, ExpandCelCanvas expandCelCanvas(documentWriter, m_sprite,
m_sprite->getCurrentLayer(), TILED_NONE); m_sprite->getCurrentLayer(), TILED_NONE,
m_undoTransaction);
image_merge(expandCelCanvas.getDestCanvas(), image, image_merge(expandCelCanvas.getDestCanvas(), image,
-expandCelCanvas.getCel()->getX(), -expandCelCanvas.getCel()->getX(),

View File

@ -35,7 +35,7 @@
#include "tools/tool.h" #include "tools/tool.h"
#include "tools/tool_loop.h" #include "tools/tool_loop.h"
#include "ui/gui.h" #include "ui/gui.h"
#include "undo/undo_history.h" #include "undo_transaction.h"
#include "util/expand_cel_canvas.h" #include "util/expand_cel_canvas.h"
#include "widgets/color_bar.h" #include "widgets/color_bar.h"
#include "widgets/editor/editor.h" #include "widgets/editor/editor.h"
@ -71,6 +71,7 @@ class ToolLoopImpl : public tools::ToolLoop
tools::ToolLoop::Button m_button; tools::ToolLoop::Button m_button;
int m_primary_color; int m_primary_color;
int m_secondary_color; int m_secondary_color;
UndoTransaction m_undoTransaction;
ExpandCelCanvas m_expandCelCanvas; ExpandCelCanvas m_expandCelCanvas;
public: public:
@ -94,7 +95,13 @@ public:
, m_button(button) , m_button(button)
, m_primary_color(color_utils::color_for_layer(primary_color, layer)) , m_primary_color(color_utils::color_for_layer(primary_color, layer))
, m_secondary_color(color_utils::color_for_layer(secondary_color, layer)) , m_secondary_color(color_utils::color_for_layer(secondary_color, layer))
, m_expandCelCanvas(document, sprite, layer, m_tiled_mode) , m_undoTransaction(m_document,
m_tool->getText().c_str(),
((getInk()->isSelection() ||
getInk()->isEyedropper() ||
getInk()->isScrollMovement()) ? undo::DoesntModifyDocument:
undo::ModifyDocument))
, m_expandCelCanvas(document, sprite, layer, m_tiled_mode, m_undoTransaction)
{ {
// Settings // Settings
ISettings* settings = m_context->getSettings(); ISettings* settings = m_context->getSettings();
@ -146,19 +153,6 @@ public:
m_offset.x = -x1; m_offset.x = -x1;
m_offset.y = -y1; m_offset.y = -y1;
// Set undo label for any kind of undo used in the whole loop
if (m_document->getUndoHistory()->isEnabled()) {
m_document->getUndoHistory()->setLabel(m_tool->getText().c_str());
if (getInk()->isSelection() ||
getInk()->isEyedropper() ||
getInk()->isScrollMovement()) {
m_document->getUndoHistory()->setModification(undo::DoesntModifyDocument);
}
else
m_document->getUndoHistory()->setModification(undo::ModifyDocument);
}
} }
~ToolLoopImpl() ~ToolLoopImpl()
@ -172,6 +166,8 @@ public:
else if (getInk()->isSelection()) { else if (getInk()->isSelection()) {
m_document->generateMaskBoundaries(); m_document->generateMaskBoundaries();
} }
m_undoTransaction.commit();
} }
// If the trace was not canceled or it is not a 'paint' ink... // If the trace was not canceled or it is not a 'paint' ink...