diff --git a/src/app/commands/cmd_undo_history.cpp b/src/app/commands/cmd_undo_history.cpp index ded7f7c87..4eef43b8c 100644 --- a/src/app/commands/cmd_undo_history.cpp +++ b/src/app/commands/cmd_undo_history.cpp @@ -1,5 +1,5 @@ // Aseprite -// Copyright (C) 2015-2016 David Capello +// Copyright (C) 2015-2017 David Capello // // This program is distributed under the terms of // the End-User License Agreement for Aseprite. @@ -52,8 +52,9 @@ public: }; UndoHistoryWindow(Context* ctx) - : m_ctx(ctx), - m_document(nullptr) { + : m_ctx(ctx) + , m_document(nullptr) { + m_title = text(); actions()->Change.connect(&UndoHistoryWindow::onChangeAction, this); } @@ -168,6 +169,10 @@ private: refillList(history); } + void onTotalUndoSizeChange(DocumentUndo* history) override { + updateTitle(); + } + void attachDocument(app::Document* document) { detachDocument(); @@ -179,6 +184,7 @@ private: history->add_observer(this); refillList(history); + updateTitle(); } void detachDocument() { @@ -188,6 +194,7 @@ private: clearList(); m_document->undoHistory()->remove_observer(this); m_document = nullptr; + updateTitle(); } void clearList() { @@ -232,9 +239,19 @@ private: } } + void updateTitle() { + if (!m_document) + setText(m_title); + else + setTextf("%s (%s)", + m_title.c_str(), + base::get_pretty_memory_size(m_document->undoHistory()->totalUndoSize()).c_str()); + } + Context* m_ctx; app::Document* m_document; doc::frame_t m_frame; + std::string m_title; }; class UndoHistoryCommand : public Command { diff --git a/src/app/document_undo.cpp b/src/app/document_undo.cpp index cdd205711..973361ec3 100644 --- a/src/app/document_undo.cpp +++ b/src/app/document_undo.cpp @@ -24,6 +24,7 @@ #include #define UNDO_TRACE(...) +#define STATE_CMD(state) (static_cast(state->cmd())) namespace app { @@ -59,6 +60,7 @@ void DocumentUndo::add(CmdTransaction* cmd) m_totalUndoSize += cmd->memSize(); notify_observers(&DocumentUndoObserver::onAddUndoState, this); + notify_observers(&DocumentUndoObserver::onTotalUndoSizeChange, this); if (App::instance()) { const size_t undoLimitSize = @@ -97,14 +99,34 @@ bool DocumentUndo::canRedo() const void DocumentUndo::undo() { - m_undoHistory.undo(); - notify_observers(&DocumentUndoObserver::onAfterUndo, this); + const undo::UndoState* state = nextUndo(); + ASSERT(state); + const Cmd* cmd = STATE_CMD(state); + size_t oldSize = m_totalUndoSize; + m_totalUndoSize -= cmd->memSize(); + { + m_undoHistory.undo(); + notify_observers(&DocumentUndoObserver::onAfterUndo, this); + } + m_totalUndoSize += cmd->memSize(); + if (m_totalUndoSize != oldSize) + notify_observers(&DocumentUndoObserver::onTotalUndoSizeChange, this); } void DocumentUndo::redo() { - m_undoHistory.redo(); - notify_observers(&DocumentUndoObserver::onAfterRedo, this); + const undo::UndoState* state = nextRedo(); + ASSERT(state); + const Cmd* cmd = STATE_CMD(state); + size_t oldSize = m_totalUndoSize; + m_totalUndoSize -= cmd->memSize(); + { + m_undoHistory.redo(); + notify_observers(&DocumentUndoObserver::onAfterRedo, this); + } + m_totalUndoSize += cmd->memSize(); + if (m_totalUndoSize != oldSize) + notify_observers(&DocumentUndoObserver::onTotalUndoSizeChange, this); } void DocumentUndo::clearRedo() @@ -133,7 +155,7 @@ std::string DocumentUndo::nextUndoLabel() const { const undo::UndoState* state = nextUndo(); if (state) - return static_cast(state->cmd())->label(); + return STATE_CMD(state)->label(); else return ""; } @@ -142,7 +164,7 @@ std::string DocumentUndo::nextRedoLabel() const { const undo::UndoState* state = nextRedo(); if (state) - return static_cast(state->cmd())->label(); + return STATE_CMD(state)->label(); else return ""; } @@ -151,8 +173,7 @@ SpritePosition DocumentUndo::nextUndoSpritePosition() const { const undo::UndoState* state = nextUndo(); if (state) - return static_cast(state->cmd()) - ->spritePositionBeforeExecute(); + return STATE_CMD(state)->spritePositionBeforeExecute(); else return SpritePosition(); } @@ -161,8 +182,7 @@ SpritePosition DocumentUndo::nextRedoSpritePosition() const { const undo::UndoState* state = nextRedo(); if (state) - return static_cast(state->cmd()) - ->spritePositionAfterExecute(); + return STATE_CMD(state)->spritePositionAfterExecute(); else return SpritePosition(); } @@ -171,7 +191,7 @@ Cmd* DocumentUndo::lastExecutedCmd() const { const undo::UndoState* state = m_undoHistory.currentState(); if (state) - return static_cast(state->cmd()); + return STATE_CMD(state); else return NULL; } @@ -179,6 +199,17 @@ Cmd* DocumentUndo::lastExecutedCmd() const void DocumentUndo::moveToState(const undo::UndoState* state) { m_undoHistory.moveTo(state); + + // Recalculate the total undo size + size_t oldSize = m_totalUndoSize; + m_totalUndoSize = 0; + const undo::UndoState* s = m_undoHistory.firstState(); + while (s) { + m_totalUndoSize += STATE_CMD(s)->memSize(); + s = s->next(); + } + if (m_totalUndoSize != oldSize) + notify_observers(&DocumentUndoObserver::onTotalUndoSizeChange, this); } const undo::UndoState* DocumentUndo::nextUndo() const @@ -197,7 +228,7 @@ const undo::UndoState* DocumentUndo::nextRedo() const void DocumentUndo::onDeleteUndoState(undo::UndoState* state) { - Cmd* cmd = static_cast(state->cmd()); + Cmd* cmd = STATE_CMD(state); UNDO_TRACE("UNDO: Deleting undo state <%s> of %s from %s\n", cmd->label().c_str(), diff --git a/src/app/document_undo.h b/src/app/document_undo.h index 34c982a32..7acb62902 100644 --- a/src/app/document_undo.h +++ b/src/app/document_undo.h @@ -32,6 +32,8 @@ namespace app { public: DocumentUndo(); + size_t totalUndoSize() const { return m_totalUndoSize; } + void setContext(doc::Context* ctx); void add(CmdTransaction* cmd); diff --git a/src/app/document_undo_observer.h b/src/app/document_undo_observer.h index 000746991..7bfcbd057 100644 --- a/src/app/document_undo_observer.h +++ b/src/app/document_undo_observer.h @@ -25,6 +25,7 @@ class DocumentUndo; virtual void onAfterUndo(DocumentUndo* history) = 0; virtual void onAfterRedo(DocumentUndo* history) = 0; virtual void onClearRedo(DocumentUndo* history) = 0; + virtual void onTotalUndoSizeChange(DocumentUndo* history) = 0; }; } // namespace app