summaryrefslogtreecommitdiff
path: root/Userland/Applications/HexEditor/HexEditor.cpp
diff options
context:
space:
mode:
authorkamp <nbvdkamp@gmail.com>2022-09-07 23:41:37 +0200
committerLinus Groh <mail@linusgroh.de>2022-11-01 12:07:28 +0000
commit8b0a464f5c281456a2f382e7296b1c92cedc2c8a (patch)
treed114d02562751a0f174c1c4e45190fa2e5d3c35d /Userland/Applications/HexEditor/HexEditor.cpp
parent24f729d0ef60cabf9529da6a227773e63d79b219 (diff)
downloadserenity-8b0a464f5c281456a2f382e7296b1c92cedc2c8a.zip
HexEditor: Implement undo and redo actions
Diffstat (limited to 'Userland/Applications/HexEditor/HexEditor.cpp')
-rw-r--r--Userland/Applications/HexEditor/HexEditor.cpp88
1 files changed, 82 insertions, 6 deletions
diff --git a/Userland/Applications/HexEditor/HexEditor.cpp b/Userland/Applications/HexEditor/HexEditor.cpp
index 701a461666..5aff8d3f5d 100644
--- a/Userland/Applications/HexEditor/HexEditor.cpp
+++ b/Userland/Applications/HexEditor/HexEditor.cpp
@@ -82,8 +82,22 @@ void HexEditor::fill_selection(u8 fill_byte)
if (!has_selection())
return;
- for (size_t i = m_selection_start; i < m_selection_end; i++)
- m_document->set(i, fill_byte);
+ ByteBuffer old_values;
+ ByteBuffer new_values;
+
+ size_t length = m_selection_end - m_selection_start;
+
+ new_values.resize(length);
+ old_values.resize(length);
+
+ for (size_t i = 0; i < length; i++) {
+ size_t position = m_selection_start + i;
+ old_values[i] = m_document->get(position).value;
+ new_values[i] = fill_byte;
+ m_document->set(position, fill_byte);
+ }
+
+ did_complete_action(m_selection_start, move(old_values), move(new_values));
update();
did_change();
@@ -465,6 +479,8 @@ void HexEditor::hex_mode_keydown_event(GUI::KeyEvent& event)
VERIFY(m_position <= m_document->size());
+ auto old_value = m_document->get(m_position).value;
+
// yes, this is terrible... but it works.
auto value = (event.key() >= KeyCode::Key_0 && event.key() <= KeyCode::Key_9)
? event.key() - KeyCode::Key_0
@@ -472,11 +488,14 @@ void HexEditor::hex_mode_keydown_event(GUI::KeyEvent& event)
if (!m_cursor_at_low_nibble) {
u8 existing_change = m_document->get(m_position).value;
- existing_change = value << 4 | (existing_change & 0xF); // shift new value left 4 bits, OR with existing last 4 bits
- m_document->set(m_position, existing_change);
+ u8 new_value = value << 4 | (existing_change & 0xF); // shift new value left 4 bits, OR with existing last 4 bits
+ m_document->set(m_position, new_value);
+ did_complete_action(m_position, old_value, new_value);
m_cursor_at_low_nibble = true;
} else {
- m_document->set(m_position, (m_document->get(m_position).value & 0xF0) | value); // save the first 4 bits, OR the new value in the last 4
+ u8 new_value = (m_document->get(m_position).value & 0xF0) | value; // save the first 4 bits, OR the new value in the last 4
+ m_document->set(m_position, new_value);
+ did_complete_action(m_position, old_value, new_value);
if (m_position + 1 < m_document->size())
m_position++;
m_cursor_at_low_nibble = false;
@@ -498,7 +517,11 @@ void HexEditor::text_mode_keydown_event(GUI::KeyEvent& event)
if (event.code_point() == 0) // This is a control key
return;
- m_document->set(m_position, event.code_point());
+ auto old_value = m_document->get(m_position).value;
+ auto new_value = event.code_point();
+ m_document->set(m_position, new_value);
+ did_complete_action(m_position, old_value, new_value);
+
if (m_position + 1 < m_document->size())
m_position++;
m_cursor_at_low_nibble = false;
@@ -797,3 +820,56 @@ void HexEditor::reset_cursor_blink_state()
m_cursor_blink_active = true;
m_blink_timer->restart();
}
+
+void HexEditor::did_complete_action(size_t position, u8 old_value, u8 new_value)
+{
+ if (old_value == new_value)
+ return;
+
+ auto command = make<HexDocumentUndoCommand>(m_document->make_weak_ptr(), position);
+
+ // We know this won't allocate because the buffers start empty
+ MUST(command->try_add_changed_byte(old_value, new_value));
+ // FIXME: Handle errors
+ MUST(m_undo_stack.try_push(move(command)));
+}
+
+void HexEditor::did_complete_action(size_t position, ByteBuffer&& old_values, ByteBuffer&& new_values)
+{
+ auto command = make<HexDocumentUndoCommand>(m_document->make_weak_ptr(), position);
+
+ // FIXME: Handle errors
+ MUST(command->try_add_changed_bytes(move(old_values), move(new_values)));
+ MUST(m_undo_stack.try_push(move(command)));
+}
+
+bool HexEditor::undo()
+{
+ if (!m_undo_stack.can_undo())
+ return false;
+
+ m_undo_stack.undo();
+ reset_cursor_blink_state();
+ update();
+ update_status();
+ did_change();
+ return true;
+}
+
+bool HexEditor::redo()
+{
+ if (!m_undo_stack.can_redo())
+ return false;
+
+ m_undo_stack.redo();
+ reset_cursor_blink_state();
+ update();
+ update_status();
+ did_change();
+ return true;
+}
+
+GUI::UndoStack& HexEditor::undo_stack()
+{
+ return m_undo_stack;
+}