diff options
author | Zack Penn <zack@sysdevs.org> | 2022-02-19 14:03:50 -0600 |
---|---|---|
committer | Ali Mohammad Pur <Ali.mpfard@gmail.com> | 2022-02-21 16:04:48 +0330 |
commit | e41dfa6599c9768e81147c04cd4f5d1c697a4d54 (patch) | |
tree | 741782ba2124c02bad43d5b90aad6661096d6a9a /Userland | |
parent | d00781de36f8f9c22d77ad2e1f2d6d3279a9b8f5 (diff) | |
download | serenity-e41dfa6599c9768e81147c04cd4f5d1c697a4d54.zip |
Spreadsheet: Add undo/redo implementation
The Spreadsheet application currently does not support undo/redo,
and with this update, we are starting the process of adding this feature
:-)
Additionally, the save dialog has been updated to use
GUI::MessageBox::ask_about_unsaved_changes() for system cohesity.
Spreadsheet: Add basic undo functinoality
The spreadsheet application now has basic support for undo. Testing of
this feature is limited, and may not work as intended yet.
Spreadsheet: Add callback when a cell's value is changed
In addition to the callback being added, this commit also exposes the
SheetModel class via a getter in SpreadSheetView.
Spreadsheet: Remove debug statements and use cell change callback
This commit uses the on_cell_data_change callback from within the
SheetModel class. This allows for us to push/pop changes to the undo
stack.
With this, we have basic Undo/Redo functionality :-)
Spreadsheet: Actually add window::set_modified
Spreadsheet: Const-correctness :-)
Spreadsheet: Reorder the edit menu actions
Diffstat (limited to 'Userland')
-rw-r--r-- | Userland/Applications/Spreadsheet/Cell.cpp | 17 | ||||
-rw-r--r-- | Userland/Applications/Spreadsheet/Cell.h | 14 | ||||
-rw-r--r-- | Userland/Applications/Spreadsheet/SpreadsheetModel.cpp | 3 | ||||
-rw-r--r-- | Userland/Applications/Spreadsheet/SpreadsheetModel.h | 2 | ||||
-rw-r--r-- | Userland/Applications/Spreadsheet/SpreadsheetView.h | 2 | ||||
-rw-r--r-- | Userland/Applications/Spreadsheet/SpreadsheetWidget.cpp | 43 | ||||
-rw-r--r-- | Userland/Applications/Spreadsheet/SpreadsheetWidget.h | 10 |
7 files changed, 89 insertions, 2 deletions
diff --git a/Userland/Applications/Spreadsheet/Cell.cpp b/Userland/Applications/Spreadsheet/Cell.cpp index 32e98270e2..dd111615c1 100644 --- a/Userland/Applications/Spreadsheet/Cell.cpp +++ b/Userland/Applications/Spreadsheet/Cell.cpp @@ -191,4 +191,21 @@ void Cell::copy_from(const Cell& other) m_thrown_value = other.m_thrown_value; } +CellUndoCommand::CellUndoCommand(Cell& cell, String const& previous_data) + : m_cell(cell) + , m_current_data(cell.data()) + , m_previous_data(previous_data) +{ +} + +void CellUndoCommand::undo() +{ + m_cell.set_data(m_previous_data); +} + +void CellUndoCommand::redo() +{ + m_cell.set_data(m_current_data); +} + } diff --git a/Userland/Applications/Spreadsheet/Cell.h b/Userland/Applications/Spreadsheet/Cell.h index 231bb92738..f38b0a7092 100644 --- a/Userland/Applications/Spreadsheet/Cell.h +++ b/Userland/Applications/Spreadsheet/Cell.h @@ -14,6 +14,7 @@ #include <AK/String.h> #include <AK/Types.h> #include <AK/WeakPtr.h> +#include <LibGUI/Command.h> namespace Spreadsheet { @@ -120,4 +121,17 @@ private: Format m_evaluated_formats; }; +class CellUndoCommand : public GUI::Command { +public: + CellUndoCommand(Cell&, String const&); + + virtual void undo() override; + virtual void redo() override; + +private: + Cell& m_cell; + String m_current_data; + String m_previous_data; +}; + } diff --git a/Userland/Applications/Spreadsheet/SpreadsheetModel.cpp b/Userland/Applications/Spreadsheet/SpreadsheetModel.cpp index 51b1c5cca4..e7980430f0 100644 --- a/Userland/Applications/Spreadsheet/SpreadsheetModel.cpp +++ b/Userland/Applications/Spreadsheet/SpreadsheetModel.cpp @@ -153,7 +153,10 @@ void SheetModel::set_data(const GUI::ModelIndex& index, const GUI::Variant& valu return; auto& cell = m_sheet->ensure({ (size_t)index.column(), (size_t)index.row() }); + auto previous_data = cell.data(); cell.set_data(value.to_string()); + if (on_cell_data_change) + on_cell_data_change(cell, previous_data); did_update(UpdateFlag::DontInvalidateIndices); } diff --git a/Userland/Applications/Spreadsheet/SpreadsheetModel.h b/Userland/Applications/Spreadsheet/SpreadsheetModel.h index f28411db23..5c6dcb36a5 100644 --- a/Userland/Applications/Spreadsheet/SpreadsheetModel.h +++ b/Userland/Applications/Spreadsheet/SpreadsheetModel.h @@ -29,6 +29,8 @@ public: void update(); + Function<void(Cell&, String&)> on_cell_data_change; + private: explicit SheetModel(Sheet& sheet) : m_sheet(sheet) diff --git a/Userland/Applications/Spreadsheet/SpreadsheetView.h b/Userland/Applications/Spreadsheet/SpreadsheetView.h index e372d68385..67f2dc4f3c 100644 --- a/Userland/Applications/Spreadsheet/SpreadsheetView.h +++ b/Userland/Applications/Spreadsheet/SpreadsheetView.h @@ -103,6 +103,8 @@ public: void move_cursor(GUI::AbstractView::CursorMovement); + NonnullRefPtr<SheetModel> model() { return m_sheet_model; }; + private: virtual void hide_event(GUI::HideEvent&) override; virtual void show_event(GUI::ShowEvent&) override; diff --git a/Userland/Applications/Spreadsheet/SpreadsheetWidget.cpp b/Userland/Applications/Spreadsheet/SpreadsheetWidget.cpp index cc320b7974..3396b695aa 100644 --- a/Userland/Applications/Spreadsheet/SpreadsheetWidget.cpp +++ b/Userland/Applications/Spreadsheet/SpreadsheetWidget.cpp @@ -205,6 +205,14 @@ SpreadsheetWidget::SpreadsheetWidget(GUI::Window& parent_window, NonnullRefPtrVe }, window()); + m_undo_action = GUI::CommonActions::make_undo_action([&](auto&) { + undo(); + }); + + m_redo_action = GUI::CommonActions::make_redo_action([&](auto&) { + redo(); + }); + m_functions_help_action = GUI::Action::create( "&Functions Help", Gfx::Bitmap::try_load_from_file("/res/icons/16x16/app-help.png").release_value_but_fixme_should_propagate_errors(), [&](auto&) { if (auto* worksheet_ptr = current_worksheet_if_available()) { @@ -227,6 +235,8 @@ SpreadsheetWidget::SpreadsheetWidget(GUI::Window& parent_window, NonnullRefPtrVe toolbar.add_action(*m_cut_action); toolbar.add_action(*m_copy_action); toolbar.add_action(*m_paste_action); + toolbar.add_action(*m_undo_action); + toolbar.add_action(*m_redo_action); } void SpreadsheetWidget::resize_event(GUI::ResizeEvent& event) @@ -251,6 +261,10 @@ void SpreadsheetWidget::setup_tabs(NonnullRefPtrVector<Sheet> new_sheets) m_selected_view->on_selection_dropped = nullptr; } m_selected_view = &static_cast<SpreadsheetView&>(selected_widget); + m_selected_view->model()->on_cell_data_change = [&](auto& cell, auto& previous_data) { + undo_stack().push(make<CellUndoCommand>(cell, previous_data)); + window()->set_modified(true); + }; m_selected_view->on_selection_changed = [&](Vector<Position>&& selection) { auto* sheet_ptr = m_selected_view->sheet_if_available(); // How did this even happen? @@ -390,11 +404,33 @@ void SpreadsheetWidget::try_generate_tip_for_input_expression(StringView source, } } +void SpreadsheetWidget::undo() +{ + if (!m_undo_stack.can_undo()) + return; + + m_undo_stack.undo(); + update(); +} + +void SpreadsheetWidget::redo() +{ + if (!m_undo_stack.can_redo()) + return; + + m_undo_stack.redo(); + update(); +} + void SpreadsheetWidget::save(StringView filename) { auto result = m_workbook->save(filename); - if (result.is_error()) + if (result.is_error()) { GUI::MessageBox::show_error(window(), result.error()); + return; + } + undo_stack().set_current_unmodified(); + window()->set_modified(false); } void SpreadsheetWidget::load_file(Core::File& file) @@ -418,7 +454,7 @@ void SpreadsheetWidget::load_file(Core::File& file) bool SpreadsheetWidget::request_close() { - if (!m_workbook->dirty()) + if (!undo_stack().is_current_modified()) return true; auto result = GUI::MessageBox::ask_about_unsaved_changes(window(), current_filename()); @@ -533,6 +569,9 @@ void SpreadsheetWidget::initialize_menubar(GUI::Window& window) file_menu.add_action(*m_quit_action); auto& edit_menu = window.add_menu("&Edit"); + edit_menu.add_action(*m_undo_action); + edit_menu.add_action(*m_redo_action); + edit_menu.add_separator(); edit_menu.add_action(*m_cut_action); edit_menu.add_action(*m_copy_action); edit_menu.add_action(*m_paste_action); diff --git a/Userland/Applications/Spreadsheet/SpreadsheetWidget.h b/Userland/Applications/Spreadsheet/SpreadsheetWidget.h index aa7fb14b4d..4a2ead0fe2 100644 --- a/Userland/Applications/Spreadsheet/SpreadsheetWidget.h +++ b/Userland/Applications/Spreadsheet/SpreadsheetWidget.h @@ -42,6 +42,10 @@ public: void initialize_menubar(GUI::Window&); + void undo(); + void redo(); + auto& undo_stack() { return m_undo_stack; } + private: virtual void resize_event(GUI::ResizeEvent&) override; @@ -60,6 +64,7 @@ private: RefPtr<GUI::Menu> m_tab_context_menu; RefPtr<SpreadsheetView> m_tab_context_menu_sheet_view; bool m_should_change_selected_cells { false }; + GUI::UndoStack m_undo_stack; OwnPtr<Workbook> m_workbook; @@ -69,11 +74,16 @@ private: RefPtr<GUI::Action> m_save_action; RefPtr<GUI::Action> m_save_as_action; RefPtr<GUI::Action> m_quit_action; + RefPtr<GUI::Action> m_cut_action; RefPtr<GUI::Action> m_copy_action; RefPtr<GUI::Action> m_paste_action; + RefPtr<GUI::Action> m_undo_action; + RefPtr<GUI::Action> m_redo_action; + RefPtr<GUI::Action> m_functions_help_action; RefPtr<GUI::Action> m_about_action; + RefPtr<GUI::Action> m_rename_action; }; |