aseprite/src/app/transaction.cpp
David Capello 944634542e Refresh screen/current palette automatically on Transaction::commit() (#378)
Removed app_update_current_palette() with this patch.
2019-10-01 09:24:03 -03:00

176 lines
3.7 KiB
C++

// Aseprite
// Copyright (C) 2018-2019 Igara Studio S.A.
// Copyright (C) 2001-2018 David Capello
//
// This program is distributed under the terms of
// the End-User License Agreement for Aseprite.
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "app/transaction.h"
#include "app/cmd_transaction.h"
#include "app/context_access.h"
#include "app/doc.h"
#include "app/doc_undo.h"
#include "app/modules/palettes.h"
#include "doc/sprite.h"
#include "ui/manager.h"
#include "ui/system.h"
#define TX_TRACE(...)
namespace app {
using namespace doc;
Transaction::Transaction(
Context* ctx,
Doc* doc,
const std::string& label,
Modification modification)
: m_ctx(ctx)
, m_doc(doc)
, m_undo(nullptr)
, m_cmds(nullptr)
, m_changes(Changes::kNone)
{
TX_TRACE("TX: Start <%s> (%s)\n",
label.c_str(),
modification == ModifyDocument ? "modifies document":
"doesn't modify document");
m_doc->add_observer(this);
m_undo = m_doc->undoHistory();
m_cmds = new CmdTransaction(label,
modification == Modification::ModifyDocument,
m_undo->savedCounter());
// Here we are executing an empty CmdTransaction, just to save the
// SpritePosition. Sub-cmds are executed then one by one, in
// Transaction::execute()
m_cmds->execute(m_ctx);
}
Transaction::~Transaction()
{
try {
// If it isn't committed, we have to rollback all changes.
if (m_cmds)
rollback(nullptr);
}
catch (...) {
// Just avoid throwing an exception in the dtor (just in case
// rollback() failed).
// TODO logging error
}
m_doc->remove_observer(this);
}
// Used to set the document range after all the transaction is
// executed and before the commit. This range is stored in
// CmdTransaction to recover it on Edit > Redo.
void Transaction::setNewDocRange(const DocRange& range)
{
ASSERT(m_cmds);
m_cmds->setNewDocRange(range);
}
void Transaction::commit()
{
// This assert can fail when we run scripts in batch mode
//ui::assert_ui_thread();
ASSERT(m_cmds);
TX_TRACE("TX: Commit <%s>\n", m_cmds->label().c_str());
m_cmds->updateSpritePositionAfter();
const SpritePosition sprPos = m_cmds->spritePositionAfterExecute();
m_undo->add(m_cmds);
m_cmds = nullptr;
// Process changes
if (int(m_changes) & int(Changes::kSelection)) {
m_doc->resetTransformation();
m_doc->generateMaskBoundaries();
}
#ifdef ENABLE_UI
if (int(m_changes) & int(Changes::kColorChange)) {
ASSERT(m_doc);
ASSERT(m_doc->sprite());
Palette* pal = m_doc->sprite()->palette(sprPos.frame());
ASSERT(pal);
if (pal)
set_current_palette(pal, false);
else
set_current_palette(nullptr, false);
if (m_ctx->isUIAvailable())
ui::Manager::getDefault()->invalidate();
}
#endif
}
void Transaction::rollbackAndStartAgain()
{
auto newCmds = m_cmds->moveToEmptyCopy();
rollback(newCmds);
newCmds->execute(m_ctx);
}
void Transaction::rollback(CmdTransaction* newCmds)
{
ASSERT(m_cmds);
TX_TRACE("TX: Rollback <%s>\n", m_cmds->label().c_str());
m_cmds->undo();
delete m_cmds;
m_cmds = newCmds;
}
void Transaction::execute(Cmd* cmd)
{
try {
cmd->execute(m_ctx);
}
catch (...) {
delete cmd;
throw;
}
try {
m_cmds->add(cmd);
}
catch (...) {
cmd->undo();
delete cmd;
throw;
}
}
void Transaction::onSelectionChanged(DocEvent& ev)
{
m_changes = Changes(int(m_changes) | int(Changes::kSelection));
}
void Transaction::onColorSpaceChanged(DocEvent& ev)
{
m_changes = Changes(int(m_changes) | int(Changes::kColorChange));
}
void Transaction::onPaletteChanged(DocEvent& ev)
{
m_changes = Changes(int(m_changes) | int(Changes::kColorChange));
}
} // namespace app