diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 1c645075e..62e408125 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -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 diff --git a/src/commands/cmd_cel_properties.cpp b/src/commands/cmd_cel_properties.cpp index 246303672..bd6da95c0 100644 --- a/src/commands/cmd_cel_properties.cpp +++ b/src/commands/cmd_cel_properties.cpp @@ -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 @@ -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(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. diff --git a/src/commands/cmd_duplicate_layer.cpp b/src/commands/cmd_duplicate_layer.cpp index 4e5235d5c..2df62bfe5 100644 --- a/src/commands/cmd_duplicate_layer.cpp +++ b/src/commands/cmd_duplicate_layer.cpp @@ -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(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); diff --git a/src/commands/cmd_export_sprite_sheet.cpp b/src/commands/cmd_export_sprite_sheet.cpp index 1897c554f..15214cf06 100644 --- a/src/commands/cmd_export_sprite_sheet.cpp +++ b/src/commands/cmd_export_sprite_sheet.cpp @@ -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 @@ -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 diff --git a/src/commands/cmd_invert_mask.cpp b/src/commands/cmd_invert_mask.cpp index 2d1de10c3..46c37d896 100644 --- a/src/commands/cmd_invert_mask.cpp +++ b/src/commands/cmd_invert_mask.cpp @@ -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(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); diff --git a/src/commands/cmd_load_mask.cpp b/src/commands/cmd_load_mask.cpp index ec2d8b2b7..6ed644c81 100644 --- a/src/commands/cmd_load_mask.cpp +++ b/src/commands/cmd_load_mask.cpp @@ -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(); } diff --git a/src/commands/cmd_mask_all.cpp b/src/commands/cmd_mask_all.cpp index eaab0d13f..9d32fcf81 100644 --- a/src/commands/cmd_mask_all.cpp +++ b/src/commands/cmd_mask_all.cpp @@ -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); } diff --git a/src/commands/cmd_merge_down_layer.cpp b/src/commands/cmd_merge_down_layer.cpp index aa8a2ac4a..f0548ba03 100644 --- a/src/commands/cmd_merge_down_layer.cpp +++ b/src/commands/cmd_merge_down_layer.cpp @@ -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; frposgetTotalFrames(); ++frpos) { // Get frames src_cel = static_cast(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(dst_layer)->addCel(dst_cel); } @@ -171,13 +163,13 @@ void MergeDownLayerCommand::onExecute(Context* context) src_cel->getOpacity(), static_cast(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); } diff --git a/src/commands/cmd_palette_editor.cpp b/src/commands/cmd_palette_editor.cpp index 9624a9369..f83b20b2b 100644 --- a/src/commands/cmd_palette_editor.cpp +++ b/src/commands/cmd_palette_editor.cpp @@ -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() diff --git a/src/commands/cmd_redo.cpp b/src/commands/cmd_redo.cpp index a992440a9..44affd6c6 100644 --- a/src/commands/cmd_redo.cpp +++ b/src/commands/cmd_redo.cpp @@ -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 diff --git a/src/commands/cmd_reselect_mask.cpp b/src/commands/cmd_reselect_mask.cpp index 1583f897d..d259ddd33 100644 --- a/src/commands/cmd_reselect_mask.cpp +++ b/src/commands/cmd_reselect_mask.cpp @@ -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); } diff --git a/src/commands/cmd_undo.cpp b/src/commands/cmd_undo.cpp index ddb96d1ac..0159cc15e 100644 --- a/src/commands/cmd_undo.cpp +++ b/src/commands/cmd_undo.cpp @@ -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 diff --git a/src/commands/filters/filter_manager_impl.cpp b/src/commands/filters/filter_manager_impl.cpp index 594f44380..941941250 100644 --- a/src/commands/filters/filter_manager_impl.cpp +++ b/src/commands/filters/filter_manager_impl.cpp @@ -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 @@ -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() diff --git a/src/dialogs/aniedit.cpp b/src/dialogs/aniedit.cpp index f1a111252..447d17413 100644 --- a/src/dialogs/aniedit.cpp +++ b/src/dialogs/aniedit.cpp @@ -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(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(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(); diff --git a/src/dialogs/maskcol.cpp b/src/dialogs/maskcol.cpp index 83e9f4c1f..a62c5a229 100644 --- a/src/dialogs/maskcol.cpp +++ b/src/dialogs/maskcol.cpp @@ -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()); diff --git a/src/document.cpp b/src/document.cpp index f8e05e3cf..82a714628 100644 --- a/src/document.cpp +++ b/src/document.cpp @@ -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 // 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; -} diff --git a/src/document.h b/src/document.h index 961242609..efc32c4f3 100644 --- a/src/document.h +++ b/src/document.h @@ -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 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 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 m_objects; - - // Stack of undoers to undo operations. - UniquePtr m_undoHistory; + // Undo and redo information about the document. + UniquePtr m_undo; // Document's file name (from where it was loaded, where it is saved). std::string m_filename; diff --git a/src/document_undo.cpp b/src/document_undo.cpp new file mode 100644 index 000000000..f2b708b99 --- /dev/null +++ b/src/document_undo.cpp @@ -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 // TODO remove this when get_config_int() is removed from here +#include + +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(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(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 ""; + } +} diff --git a/src/document_undo.h b/src/document_undo.h new file mode 100644 index 000000000..3ad027fa5 --- /dev/null +++ b/src/document_undo.h @@ -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 m_objects; + + // Stack of undoers to undo operations. + UniquePtr m_undoHistory; + + bool m_enabled; + + DISABLE_COPYING(DocumentUndo); +}; + +#endif diff --git a/src/tools/inks.h b/src/tools/inks.h index b114f18f1..5442d2e8a 100644 --- a/src/tools/inks.h +++ b/src/tools/inks.h @@ -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())); diff --git a/src/undo/undo_history.cpp b/src/undo/undo_history.cpp index 5f5d8c83f..7922a4ec9 100644 --- a/src/undo/undo_history.cpp +++ b/src/undo/undo_history.cpp @@ -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(); diff --git a/src/undo/undo_history.h b/src/undo/undo_history.h index 506e7296a..1820e4bfd 100644 --- a/src/undo/undo_history.h +++ b/src/undo/undo_history.h @@ -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; }; diff --git a/src/undo/undoer.h b/src/undo/undoer.h index e6db08992..649b31257 100644 --- a/src/undo/undoer.h +++ b/src/undo/undoer.h @@ -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; diff --git a/src/undo/undoers_stack.cpp b/src/undo/undoers_stack.cpp index afd429927..10975efbe 100644 --- a/src/undo/undoers_stack.cpp +++ b/src/undo/undoers_stack.cpp @@ -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()) diff --git a/src/undo/undoers_stack.h b/src/undo/undoers_stack.h index 490de20de..822b3b703 100644 --- a/src/undo/undoers_stack.h +++ b/src/undo/undoers_stack.h @@ -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 @@ -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 Items; + typedef std::vector Items; typedef Items::iterator iterator; typedef Items::const_iterator const_iterator; diff --git a/src/undo_transaction.cpp b/src/undo_transaction.cpp index 30583b376..99cdef5a4 100644 --- a/src/undo_transaction.cpp +++ b/src/undo_transaction.cpp @@ -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; frgetTotalFrames(); ++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((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); diff --git a/src/undo_transaction.h b/src/undo_transaction.h index 52176c26d..a1314f98c 100644 --- a/src/undo_transaction.h +++ b/src/undo_transaction.h @@ -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 diff --git a/src/undoers/close_group.cpp b/src/undoers/close_group.cpp index 0868c9948..e944d6f79 100644 --- a/src/undoers/close_group.cpp +++ b/src/undoers/close_group.cpp @@ -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)); } diff --git a/src/undoers/close_group.h b/src/undoers/close_group.h index 2ae07366c..3d8847763 100644 --- a/src/undoers/close_group.h +++ b/src/undoers/close_group.h @@ -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 diff --git a/src/undoers/open_group.cpp b/src/undoers/open_group.cpp index 2a46b129d..b5d1e27b6 100644 --- a/src/undoers/open_group.cpp +++ b/src/undoers/open_group.cpp @@ -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)); } diff --git a/src/undoers/open_group.h b/src/undoers/open_group.h index 222697a33..185ef33d2 100644 --- a/src/undoers/open_group.h +++ b/src/undoers/open_group.h @@ -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 diff --git a/src/undoers/undoer_base.h b/src/undoers/undoer_base.h index e15418da6..05cdd8eda 100644 --- a/src/undoers/undoer_base.h +++ b/src/undoers/undoer_base.h @@ -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; } }; diff --git a/src/util/celmove.cpp b/src/util/celmove.cpp index d3d959abd..d603b920f 100644 --- a/src/util/celmove.cpp +++ b/src/util/celmove.cpp @@ -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(src_layer)->getCel(src_frame); dst_cel = static_cast(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(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(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(src_layer)->getCel(src_frame); dst_cel = static_cast(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(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 diff --git a/src/util/expand_cel_canvas.cpp b/src/util/expand_cel_canvas.cpp index c1c732f87..b3493bb51 100644 --- a/src/util/expand_cel_canvas.cpp +++ b/src/util/expand_cel_canvas.cpp @@ -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(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(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(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(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. diff --git a/src/util/expand_cel_canvas.h b/src/util/expand_cel_canvas.h index 6c5757fba..513de4ce8 100644 --- a/src/util/expand_cel_canvas.h +++ b/src/util/expand_cel_canvas.h @@ -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 diff --git a/src/widgets/editor/pixels_movement.cpp b/src/widgets/editor/pixels_movement.cpp index d22e326be..5a15e1c6a 100644 --- a/src/widgets/editor/pixels_movement.cpp +++ b/src/widgets/editor/pixels_movement.cpp @@ -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(), diff --git a/src/widgets/editor/tool_loop_impl.cpp b/src/widgets/editor/tool_loop_impl.cpp index d0fb0f818..efb3bd67e 100644 --- a/src/widgets/editor/tool_loop_impl.cpp +++ b/src/widgets/editor/tool_loop_impl.cpp @@ -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...