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_listener_list.cpp
document.cpp
document_undo.cpp
documents.cpp
drop_files.cpp
file_system.cpp

View File

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

View File

@ -21,12 +21,12 @@
#include "app.h"
#include "commands/command.h"
#include "console.h"
#include "document_undo.h"
#include "document_wrappers.h"
#include "modules/gui.h"
#include "raster/layer.h"
#include "raster/sprite.h"
#include "ui/gui.h"
#include "undo/undo_history.h"
#include "undo_transaction.h"
#include "undoers/add_layer.h"
#include "undoers/move_layer.h"
@ -64,8 +64,7 @@ void DuplicateLayerCommand::onExecute(Context* context)
{
ActiveDocumentWriter document(context);
Sprite* sprite = document->getSprite();
undo::UndoHistory* undo = document->getUndoHistory();
UndoTransaction undoTransaction(document, "Layer Duplication");
UndoTransaction undo(document, "Layer Duplication");
LayerImage* sourceLayer = static_cast<LayerImage*>(sprite->getCurrentLayer());
// 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
// AddLayer() undoer.
document->getUndoHistory()->setEnabled(false);
document->getUndo()->setEnabled(false);
// Copy the layer content (cels + images)
document->copyLayerContent(sourceLayer, document, newLayerPtr);
// Restore enabled status.
document->getUndoHistory()->setEnabled(undoTransaction.isEnabled());
document->getUndo()->setEnabled(undo.isEnabled());
// Copy the layer name
newLayerPtr->setName(newLayerPtr->getName() + " Copy");
// Add the new layer in the sprite.
if (undo->isEnabled())
undo->pushUndoer(new undoers::AddLayer(undo->getObjects(),
if (undo.isEnabled())
undo.pushUndoer(new undoers::AddLayer(undo.getObjects(),
sourceLayer->get_parent(), 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
Layer* newLayer = newLayerPtr.release();
if (undo->isEnabled()) {
undo->pushUndoer(new undoers::MoveLayer(undo->getObjects(), newLayer));
undo->pushUndoer(new undoers::SetCurrentLayer(undo->getObjects(), sprite));
if (undo.isEnabled()) {
undo.pushUndoer(new undoers::MoveLayer(undo.getObjects(), newLayer));
undo.pushUndoer(new undoers::SetCurrentLayer(undo.getObjects(), sprite));
}
undoTransaction.commit();
undo.commit();
sourceLayer->get_parent()->move_layer(newLayer, sourceLayer);
sprite->setCurrentLayer(newLayer);

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -24,29 +24,23 @@
#include "base/mutex.h"
#include "base/scoped_lock.h"
#include "base/unique_ptr.h"
#include "document_undo.h"
#include "file/format_options.h"
#include "flatten.h"
#include "objects_container_impl.h"
#include "raster/cel.h"
#include "raster/layer.h"
#include "raster/mask.h"
#include "raster/palette.h"
#include "raster/sprite.h"
#include "raster/stock.h"
#include "undo/undo_history.h"
#include "undoers/add_image.h"
#include "undoers/add_layer.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)
: m_id(WithoutDocumentId)
, m_sprite(sprite)
, m_objects(new ObjectsContainerImpl)
, m_undoHistory(new UndoHistory(m_objects, this))
, m_undo(new DocumentUndo)
, m_filename("Sprite")
, m_associated_to_file(false)
, m_mutex(new Mutex)
@ -147,7 +141,7 @@ void Document::setFilename(const char* filename)
bool Document::isModified() const
{
return !m_undoHistory->isSavedState();
return !m_undo->isSavedState();
}
bool Document::isAssociatedToFile() const
@ -157,7 +151,7 @@ bool Document::isAssociatedToFile() const
void Document::markAsSaved()
{
m_undoHistory->markSavedState();
m_undo->markSavedState();
m_associated_to_file = true;
}
@ -324,7 +318,7 @@ void Document::resetTransformation()
void Document::copyLayerContent(const Layer* sourceLayer0, Document* destDoc, Layer* destLayer0) const
{
UndoHistory* undo = destDoc->getUndoHistory();
DocumentUndo* undo = destDoc->getUndo();
// Copy the layer name
destLayer0->setName(sourceLayer0->getName());
@ -429,7 +423,7 @@ Document* Document::duplicate(DuplicateType type) const
case DuplicateExactCopy:
// Disable the undo
documentCopy->getUndoHistory()->setEnabled(false);
documentCopy->getUndo()->setEnabled(false);
// Copy the layer folder
copyLayerContent(getSprite()->getFolder(), documentCopy, spriteCopy->getFolder());
@ -441,7 +435,7 @@ Document* Document::duplicate(DuplicateType type) const
}
// Re-enable the undo
documentCopy->getUndoHistory()->setEnabled(true);
documentCopy->getUndo()->setEnabled(true);
break;
case DuplicateWithFlattenLayers:
@ -547,8 +541,3 @@ void Document::unlock()
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
#define DOCUMENT_H_INCLUDED
#include "base/compiler_specific.h"
#include "base/disable_copying.h"
#include "base/shared_ptr.h"
#include "base/unique_ptr.h"
#include "document_id.h"
#include "gfx/transformation.h"
#include "raster/pixel_format.h"
#include "undo/undo_config_provider.h"
#include <string>
class Cel;
class DocumentUndo;
class FormatOptions;
class Image;
class Layer;
@ -39,11 +38,6 @@ class Mutex;
class Sprite;
struct _BoundSeg;
namespace undo {
class ObjectsContainer;
class UndoHistory;
}
struct PreferredEditorSettings
{
int scroll_x;
@ -60,7 +54,7 @@ enum DuplicateType
// An application document. It is the class used to contain one file
// opened and being edited by the user (a sprite).
class Document : public undo::UndoConfigProvider
class Document
{
public:
@ -83,10 +77,10 @@ public:
void setId(DocumentId id) { m_id = id; }
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; }
undo::UndoHistory* getUndoHistory() { return m_undoHistory; }
DocumentUndo* getUndo() { return m_undo; }
void addSprite(Sprite* sprite);
@ -180,23 +174,14 @@ public:
void unlock();
private:
size_t getUndoSizeLimit() OVERRIDE;
// Unique identifier for this document (it is assigned by Documents class).
DocumentId m_id;
// The main sprite.
UniquePtr<Sprite> m_sprite;
// 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;
// Undo and redo information about the document.
UniquePtr<DocumentUndo> m_undo;
// Document's file name (from where it was loaded, where it is saved).
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 "context.h"
#include "document.h"
#include "document_undo.h"
#include "raster/mask.h"
#include "undo/undo_history.h"
#include "undoers/set_mask.h"
@ -261,7 +261,7 @@ public:
m_modify_selection = state;
if (state) {
undo::UndoHistory* undo = loop->getDocument()->getUndoHistory();
DocumentUndo* undo = loop->getDocument()->getUndo();
if (undo->isEnabled())
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_diffCount = 0;
m_diffSaved = 0;
m_enabled = true;
m_label = NULL;
m_modification = ModifyDocument;
m_undoers = new UndoersStack(this);
try {
@ -44,16 +41,6 @@ UndoHistory::~UndoHistory()
delete m_redoers;
}
bool UndoHistory::isEnabled() const
{
return m_enabled ? true: false;
}
void UndoHistory::setEnabled(bool state)
{
m_enabled = state;
}
bool UndoHistory::canUndo() const
{
return !m_undoers->empty();
@ -87,40 +74,20 @@ void UndoHistory::clearRedo()
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;
}
Modification UndoHistory::getModification()
{
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();
if (!m_redoers->empty())
return *m_redoers->begin();
else
return NULL;
}
bool UndoHistory::isSavedState() const
@ -141,20 +108,13 @@ void UndoHistory::runUndo(Direction direction)
do {
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);
if (!undoer)
break;
setLabel(itemLabel);
setModification(itemModification);
Modification itemModification = DoesntModifyDocument;
itemModification = undoer->getModification();
undoer->revert(getObjects(), redoers);
@ -202,7 +162,7 @@ void UndoHistory::pushUndoer(Undoer* undoer)
postUndoerAddedEvent(undoer);
}
bool UndoHistory::graftUndoerInLastGroup(Undoer* undoer)
bool UndoHistory::implantUndoerInLastGroup(Undoer* undoer)
{
Undoer* lastUndoer = m_undoers->popUndoer(UndoersStack::PopFromHead);
bool result;
@ -241,7 +201,7 @@ void UndoHistory::postUndoerAddedEvent(Undoer* undoer)
// it has passed the undo-limit.
if (m_groupLevel == 0) {
// More differences.
if (m_modification == ModifyDocument)
if (undoer->getModification() == ModifyDocument)
m_diffCount++;
checkSizeLimit();

View File

@ -24,9 +24,6 @@ public:
UndoHistory(ObjectsContainer* objects, UndoConfigProvider* configProvider);
virtual ~UndoHistory();
bool isEnabled() const;
void setEnabled(bool state);
bool canUndo() const;
bool canRedo() const;
@ -35,18 +32,8 @@ public:
void clearRedo();
// Current label for next added Undoers.
const char* getLabel();
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;
Undoer* getNextUndoer();
Undoer* getNextRedoer();
bool isSavedState() const;
void markSavedState();
@ -58,7 +45,7 @@ public:
// Special method to add new undoers inside the last added group.
// Returns true if the undoer was added in a group.
bool graftUndoerInLastGroup(Undoer* undoer);
bool implantUndoerInLastGroup(Undoer* undoer);
private:
enum Direction { UndoDirection, RedoDirection };
@ -76,9 +63,6 @@ private:
int m_groupLevel;
int m_diffCount;
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;
};

View File

@ -7,6 +7,8 @@
#ifndef UNDO_UNDOER_H_INCLUDED
#define UNDO_UNDOER_H_INCLUDED
#include "undo/modification.h"
namespace undo {
class ObjectsContainer;
@ -30,6 +32,10 @@ public:
// using to revert the action.
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.
virtual bool isOpenGroup() const = 0;

View File

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

View File

@ -7,7 +7,6 @@
#ifndef UNDO_UNDOERS_STACK_H_INCLUDED
#define UNDO_UNDOERS_STACK_H_INCLUDED
#include "undo/modification.h"
#include "undo/undoers_collector.h"
#include <vector>
@ -29,26 +28,7 @@ public:
PopFromTail
};
// One item in the stack (label + Undoer)
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 std::vector<Undoer*> Items;
typedef Items::iterator iterator;
typedef Items::const_iterator const_iterator;

View File

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

View File

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

View File

@ -26,6 +26,12 @@
using namespace undo;
using namespace undoers;
CloseGroup::CloseGroup(const char* label, undo::Modification modification)
: m_label(label)
, m_modification(modification)
{
}
void CloseGroup::dispose()
{
delete this;
@ -33,5 +39,5 @@ void CloseGroup::dispose()
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
{
public:
CloseGroup(const char* label, undo::Modification modification);
void dispose() OVERRIDE;
size_t getMemSize() const OVERRIDE { return sizeof(*this); }
undo::Modification getModification() const { return m_modification; }
bool isOpenGroup() const OVERRIDE { return false; }
bool isCloseGroup() const OVERRIDE { return true; }
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

View File

@ -26,6 +26,12 @@
using namespace undo;
using namespace undoers;
OpenGroup::OpenGroup(const char* label, undo::Modification modification)
: m_label(label)
, m_modification(modification)
{
}
void OpenGroup::dispose()
{
delete this;
@ -33,5 +39,5 @@ void OpenGroup::dispose()
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
{
public:
OpenGroup(const char* label, undo::Modification modification);
void dispose() OVERRIDE;
size_t getMemSize() const OVERRIDE { return sizeof(*this); }
undo::Modification getModification() const { return m_modification; }
bool isOpenGroup() const OVERRIDE { return true; }
bool isCloseGroup() const OVERRIDE { return false; }
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

View File

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

View File

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

View File

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

View File

@ -26,6 +26,7 @@ class Document;
class Image;
class Layer;
class Sprite;
class UndoTransaction;
// 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,
@ -36,7 +37,7 @@ class Sprite;
class ExpandCelCanvas
{
public:
ExpandCelCanvas(Document* document, Sprite* sprite, Layer* layer, TiledMode tiledMode);
ExpandCelCanvas(Document* document, Sprite* sprite, Layer* layer, TiledMode tiledMode, UndoTransaction& undo);
~ExpandCelCanvas();
// Commit changes made in getDestCanvas() in the cel's image. Adds
@ -75,6 +76,7 @@ private:
Image* m_dstImage;
bool m_closed;
bool m_committed;
UndoTransaction& m_undo;
};
#endif

View File

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

View File

@ -35,7 +35,7 @@
#include "tools/tool.h"
#include "tools/tool_loop.h"
#include "ui/gui.h"
#include "undo/undo_history.h"
#include "undo_transaction.h"
#include "util/expand_cel_canvas.h"
#include "widgets/color_bar.h"
#include "widgets/editor/editor.h"
@ -71,6 +71,7 @@ class ToolLoopImpl : public tools::ToolLoop
tools::ToolLoop::Button m_button;
int m_primary_color;
int m_secondary_color;
UndoTransaction m_undoTransaction;
ExpandCelCanvas m_expandCelCanvas;
public:
@ -94,7 +95,13 @@ public:
, m_button(button)
, m_primary_color(color_utils::color_for_layer(primary_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
ISettings* settings = m_context->getSettings();
@ -146,19 +153,6 @@ public:
m_offset.x = -x1;
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()
@ -172,6 +166,8 @@ public:
else if (getInk()->isSelection()) {
m_document->generateMaskBoundaries();
}
m_undoTransaction.commit();
}
// If the trace was not canceled or it is not a 'paint' ink...