ladybird/Userland/Libraries/LibGUI/UndoStack.cpp
luiz 964249a5b0 LibGUI: Fixes modified indicator behavior after saving
Pior to this change when the user added text after having saved the file
the Text Editor wouldn't enable the modified flag, unless this new text
was a new line.

This happened because the UndoStack was merging the Command added by
the new text with the old text one, and when is_current_modified()
was called, the m_stack_index would not have been incremented, and
it would return false.

In this change was added a condition to verify if the modified tag is
active, and the merge is only done if the document is already modified.
2021-09-04 21:04:33 +02:00

127 lines
2.4 KiB
C++

/*
* Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <LibGUI/Command.h>
#include <LibGUI/UndoStack.h>
namespace GUI {
UndoStack::UndoStack()
{
}
UndoStack::~UndoStack()
{
}
bool UndoStack::can_undo() const
{
return m_stack_index > 0;
}
bool UndoStack::can_redo() const
{
if (m_stack.is_empty())
return false;
return m_stack_index != m_stack.size();
}
void UndoStack::undo()
{
if (!can_undo())
return;
auto& command = m_stack[--m_stack_index];
command.undo();
if (on_state_change)
on_state_change();
}
void UndoStack::redo()
{
if (!can_redo())
return;
auto& command = m_stack[m_stack_index++];
command.redo();
if (on_state_change)
on_state_change();
}
void UndoStack::push(NonnullOwnPtr<Command> command)
{
// If the stack cursor is behind the top of the stack, nuke everything from here to the top.
while (m_stack.size() != m_stack_index)
m_stack.take_last();
if (m_clean_index.has_value() && m_clean_index.value() > m_stack.size())
m_clean_index = {};
if (!m_stack.is_empty() && is_current_modified()) {
if (m_stack.last().merge_with(*command))
return;
}
m_stack.append(move(command));
m_stack_index = m_stack.size();
if (on_state_change)
on_state_change();
}
void UndoStack::set_current_unmodified()
{
if (m_clean_index.has_value() && m_clean_index.value() == m_stack_index)
return;
m_clean_index = m_stack_index;
if (on_state_change)
on_state_change();
}
bool UndoStack::is_current_modified() const
{
if (m_stack.is_empty())
return false;
if (!m_clean_index.has_value())
return true;
if (m_stack_index != m_clean_index.value())
return true;
return false;
}
void UndoStack::clear()
{
if (m_stack.is_empty() && m_stack_index == 0 && !m_clean_index.has_value())
return;
m_stack.clear();
m_stack_index = 0;
m_clean_index.clear();
if (on_state_change)
on_state_change();
}
Optional<String> UndoStack::undo_action_text() const
{
if (!can_undo())
return {};
return m_stack[m_stack_index - 1].action_text();
}
Optional<String> UndoStack::redo_action_text() const
{
if (!can_redo())
return {};
return m_stack[m_stack_index].action_text();
}
}