From d8bac4dbdae44a5fadc53aa70fa6dc7c4bdb2a6d Mon Sep 17 00:00:00 2001 From: Samuel Bowman Date: Thu, 30 Sep 2021 21:31:35 -0400 Subject: [PATCH] Spreadsheet: Move menu and action code to initialize_menubar() Previously, all the code to add menus and actions was in main(). This was messy and didn't allow us to reference the actions from SpreadsheetWidget, which is needed in order to add a toolbar. This commit moves the menu and action adding code to method on SpreadsheetWidget called initialize_menubar() which is based upon applications such as TextEditor which have identically named methods doing the same thing. In additon, clipboard_action(), previouly a lambda in main(), has also been made into a method on SpreadsheetWidget since it would otherwise be destroyed when it goes out of scope. (This was previously avoided by declaring the lambda in main() so it's always in scope.) --- .../Spreadsheet/SpreadsheetWidget.cpp | 161 +++++++++++++++++- .../Spreadsheet/SpreadsheetWidget.h | 4 + Userland/Applications/Spreadsheet/main.cpp | 153 +---------------- 3 files changed, 165 insertions(+), 153 deletions(-) diff --git a/Userland/Applications/Spreadsheet/SpreadsheetWidget.cpp b/Userland/Applications/Spreadsheet/SpreadsheetWidget.cpp index fcad4a05e3..a3a487e4ba 100644 --- a/Userland/Applications/Spreadsheet/SpreadsheetWidget.cpp +++ b/Userland/Applications/Spreadsheet/SpreadsheetWidget.cpp @@ -7,10 +7,11 @@ #include "SpreadsheetWidget.h" #include "CellSyntaxHighlighter.h" #include "HelpWindow.h" -#include "LibGUI/InputBox.h" +#include #include #include #include +#include #include #include #include @@ -340,6 +341,164 @@ void SpreadsheetWidget::set_filename(const String& filename) } } +void SpreadsheetWidget::clipboard_action(bool is_cut) +{ + /// text/x-spreadsheet-data: + /// - action: copy/cut + /// - currently selected cell + /// - selected cell+ + auto* worksheet_ptr = current_worksheet_if_available(); + if (!worksheet_ptr) { + GUI::MessageBox::show_error(window(), "There are no active worksheets"); + return; + } + auto& worksheet = *worksheet_ptr; + auto& cells = worksheet.selected_cells(); + VERIFY(!cells.is_empty()); + StringBuilder text_builder, url_builder; + url_builder.append(is_cut ? "cut\n" : "copy\n"); + bool first = true; + auto cursor = current_selection_cursor(); + if (cursor) { + Spreadsheet::Position position { (size_t)cursor->column(), (size_t)cursor->row() }; + url_builder.append(position.to_url(worksheet).to_string()); + url_builder.append('\n'); + } + + for (auto& cell : cells) { + if (first && !cursor) { + url_builder.append(cell.to_url(worksheet).to_string()); + url_builder.append('\n'); + } + + url_builder.append(cell.to_url(worksheet).to_string()); + url_builder.append('\n'); + + auto cell_data = worksheet.at(cell); + if (!first) + text_builder.append('\t'); + if (cell_data) + text_builder.append(cell_data->data()); + first = false; + } + HashMap metadata; + metadata.set("text/x-spreadsheet-data", url_builder.to_string()); + dbgln(url_builder.to_string()); + + GUI::Clipboard::the().set_data(text_builder.string_view().bytes(), "text/plain", move(metadata)); +} + +void SpreadsheetWidget::initialize_menubar(GUI::Window& window) +{ + auto& file_menu = window.add_menu("&File"); + + file_menu.add_action(GUI::Action::create("Add New Sheet", Gfx::Bitmap::try_load_from_file("/res/icons/16x16/new-tab.png"), [&](auto&) { + add_sheet(); + })); + + file_menu.add_action(GUI::CommonActions::make_open_action([&](auto&) { + Optional load_path = GUI::FilePicker::get_open_filepath(&window); + if (!load_path.has_value()) + return; + + load(load_path.value()); + })); + + file_menu.add_action(GUI::CommonActions::make_save_action([&](auto&) { + if (current_filename().is_empty()) { + String name = "workbook"; + Optional save_path = GUI::FilePicker::get_save_filepath(&window, name, "sheets"); + if (!save_path.has_value()) + return; + + save(save_path.value()); + } else { + save(current_filename()); + } + })); + + file_menu.add_action(GUI::CommonActions::make_save_as_action([&](auto&) { + String name = "workbook"; + Optional save_path = GUI::FilePicker::get_save_filepath(&window, name, "sheets"); + if (!save_path.has_value()) + return; + + save(save_path.value()); + + if (!current_filename().is_empty()) + set_filename(current_filename()); + })); + + file_menu.add_separator(); + + file_menu.add_action(GUI::CommonActions::make_quit_action([&](auto&) { + if (!request_close()) + return; + GUI::Application::the()->quit(0); + })); + + auto& edit_menu = window.add_menu("&Edit"); + + edit_menu.add_action(GUI::CommonActions::make_cut_action([&](auto&) { clipboard_action(true); }, &window)); + edit_menu.add_action(GUI::CommonActions::make_copy_action([&](auto&) { clipboard_action(false); }, &window)); + edit_menu.add_action(GUI::CommonActions::make_paste_action([&](auto&) { + ScopeGuard update_after_paste { [&] { update(); } }; + + auto* worksheet_ptr = current_worksheet_if_available(); + if (!worksheet_ptr) { + GUI::MessageBox::show_error(&window, "There are no active worksheets"); + return; + } + auto& sheet = *worksheet_ptr; + auto& cells = sheet.selected_cells(); + VERIFY(!cells.is_empty()); + const auto& data = GUI::Clipboard::the().data_and_type(); + if (auto spreadsheet_data = data.metadata.get("text/x-spreadsheet-data"); spreadsheet_data.has_value()) { + Vector source_positions, target_positions; + auto lines = spreadsheet_data.value().split_view('\n'); + auto action = lines.take_first(); + + for (auto& line : lines) { + dbgln("Paste line '{}'", line); + auto position = sheet.position_from_url(line); + if (position.has_value()) + source_positions.append(position.release_value()); + } + + for (auto& position : sheet.selected_cells()) + target_positions.append(position); + + if (source_positions.is_empty()) + return; + + auto first_position = source_positions.take_first(); + sheet.copy_cells(move(source_positions), move(target_positions), first_position, action == "cut" ? Spreadsheet::Sheet::CopyOperation::Cut : Spreadsheet::Sheet::CopyOperation::Copy); + } else { + for (auto& cell : sheet.selected_cells()) + sheet.ensure(cell).set_data(StringView { data.data.data(), data.data.size() }); + update(); + } + }, + &window)); + + auto& help_menu = window.add_menu("&Help"); + + help_menu.add_action(GUI::Action::create( + "&Functions Help", [&](auto&) { + if (auto* worksheet_ptr = current_worksheet_if_available()) { + auto docs = worksheet_ptr->gather_documentation(); + auto help_window = Spreadsheet::HelpWindow::the(&window); + help_window->set_docs(move(docs)); + help_window->show(); + } else { + GUI::MessageBox::show_error(&window, "Cannot prepare documentation/help without an active worksheet"); + } + }, + &window)); + + help_menu.add_action(GUI::CommonActions::make_about_action("Spreadsheet", GUI::Icon::default_icon("app-spreadsheet"), &window)); +} + SpreadsheetWidget::~SpreadsheetWidget() { } diff --git a/Userland/Applications/Spreadsheet/SpreadsheetWidget.h b/Userland/Applications/Spreadsheet/SpreadsheetWidget.h index 790e198768..dcdb51e4be 100644 --- a/Userland/Applications/Spreadsheet/SpreadsheetWidget.h +++ b/Userland/Applications/Spreadsheet/SpreadsheetWidget.h @@ -40,6 +40,8 @@ public: return m_selected_view->cursor(); } + void initialize_menubar(GUI::Window&); + private: virtual void resize_event(GUI::ResizeEvent&) override; @@ -60,6 +62,8 @@ private: bool m_should_change_selected_cells { false }; OwnPtr m_workbook; + + void clipboard_action(bool is_cut); }; } diff --git a/Userland/Applications/Spreadsheet/main.cpp b/Userland/Applications/Spreadsheet/main.cpp index edce7bbdfb..0ed5a66f22 100644 --- a/Userland/Applications/Spreadsheet/main.cpp +++ b/Userland/Applications/Spreadsheet/main.cpp @@ -85,51 +85,7 @@ int main(int argc, char* argv[]) if (filename) spreadsheet_widget.load(filename); - auto& file_menu = window->add_menu("&File"); - - file_menu.add_action(GUI::Action::create("Add New Sheet", Gfx::Bitmap::try_load_from_file("/res/icons/16x16/new-tab.png"), [&](auto&) { - spreadsheet_widget.add_sheet(); - })); - file_menu.add_action(GUI::CommonActions::make_open_action([&](auto&) { - Optional load_path = GUI::FilePicker::get_open_filepath(window); - if (!load_path.has_value()) - return; - - spreadsheet_widget.load(load_path.value()); - })); - - file_menu.add_action(GUI::CommonActions::make_save_action([&](auto&) { - if (spreadsheet_widget.current_filename().is_empty()) { - String name = "workbook"; - Optional save_path = GUI::FilePicker::get_save_filepath(window, name, "sheets"); - if (!save_path.has_value()) - return; - - spreadsheet_widget.save(save_path.value()); - } else { - spreadsheet_widget.save(spreadsheet_widget.current_filename()); - } - })); - - file_menu.add_action(GUI::CommonActions::make_save_as_action([&](auto&) { - auto current_filename = spreadsheet_widget.current_filename(); - String name = "workbook"; - Optional save_path = GUI::FilePicker::get_save_filepath(window, name, "sheets"); - if (!save_path.has_value()) - return; - - spreadsheet_widget.save(save_path.value()); - - if (!current_filename.is_empty()) - spreadsheet_widget.set_filename(current_filename); - })); - file_menu.add_separator(); - - file_menu.add_action(GUI::CommonActions::make_quit_action([&](auto&) { - if (!spreadsheet_widget.request_close()) - return; - app->quit(0); - })); + spreadsheet_widget.initialize_menubar(*window); window->on_close_request = [&]() -> GUI::Window::CloseRequestDecision { if (spreadsheet_widget.request_close()) @@ -137,113 +93,6 @@ int main(int argc, char* argv[]) return GUI::Window::CloseRequestDecision::StayOpen; }; - auto& edit_menu = window->add_menu("&Edit"); - - auto clipboard_action = [&](bool is_cut) { - /// text/x-spreadsheet-data: - /// - action: copy/cut - /// - currently selected cell - /// - selected cell+ - auto* worksheet_ptr = spreadsheet_widget.current_worksheet_if_available(); - if (!worksheet_ptr) { - GUI::MessageBox::show_error(window, "There are no active worksheets"); - return; - } - auto& worksheet = *worksheet_ptr; - auto& cells = worksheet.selected_cells(); - VERIFY(!cells.is_empty()); - StringBuilder text_builder, url_builder; - url_builder.append(is_cut ? "cut\n" : "copy\n"); - bool first = true; - auto cursor = spreadsheet_widget.current_selection_cursor(); - if (cursor) { - Spreadsheet::Position position { (size_t)cursor->column(), (size_t)cursor->row() }; - url_builder.append(position.to_url(worksheet).to_string()); - url_builder.append('\n'); - } - - for (auto& cell : cells) { - if (first && !cursor) { - url_builder.append(cell.to_url(worksheet).to_string()); - url_builder.append('\n'); - } - - url_builder.append(cell.to_url(worksheet).to_string()); - url_builder.append('\n'); - - auto cell_data = worksheet.at(cell); - if (!first) - text_builder.append('\t'); - if (cell_data) - text_builder.append(cell_data->data()); - first = false; - } - HashMap metadata; - metadata.set("text/x-spreadsheet-data", url_builder.to_string()); - dbgln(url_builder.to_string()); - - GUI::Clipboard::the().set_data(text_builder.string_view().bytes(), "text/plain", move(metadata)); - }; - - edit_menu.add_action(GUI::CommonActions::make_cut_action([&](auto&) { clipboard_action(true); }, window)); - edit_menu.add_action(GUI::CommonActions::make_copy_action([&](auto&) { clipboard_action(false); }, window)); - edit_menu.add_action(GUI::CommonActions::make_paste_action([&](auto&) { - ScopeGuard update_after_paste { [&] { spreadsheet_widget.update(); } }; - - auto* worksheet_ptr = spreadsheet_widget.current_worksheet_if_available(); - if (!worksheet_ptr) { - GUI::MessageBox::show_error(window, "There are no active worksheets"); - return; - } - auto& sheet = *worksheet_ptr; - auto& cells = sheet.selected_cells(); - VERIFY(!cells.is_empty()); - const auto& data = GUI::Clipboard::the().data_and_type(); - if (auto spreadsheet_data = data.metadata.get("text/x-spreadsheet-data"); spreadsheet_data.has_value()) { - Vector source_positions, target_positions; - auto lines = spreadsheet_data.value().split_view('\n'); - auto action = lines.take_first(); - - for (auto& line : lines) { - dbgln("Paste line '{}'", line); - auto position = sheet.position_from_url(line); - if (position.has_value()) - source_positions.append(position.release_value()); - } - - for (auto& position : sheet.selected_cells()) - target_positions.append(position); - - if (source_positions.is_empty()) - return; - - auto first_position = source_positions.take_first(); - sheet.copy_cells(move(source_positions), move(target_positions), first_position, action == "cut" ? Spreadsheet::Sheet::CopyOperation::Cut : Spreadsheet::Sheet::CopyOperation::Copy); - } else { - for (auto& cell : sheet.selected_cells()) - sheet.ensure(cell).set_data(StringView { data.data.data(), data.data.size() }); - spreadsheet_widget.update(); - } - }, - window)); - - auto& help_menu = window->add_menu("&Help"); - - help_menu.add_action(GUI::Action::create( - "&Functions Help", [&](auto&) { - if (auto* worksheet_ptr = spreadsheet_widget.current_worksheet_if_available()) { - auto docs = worksheet_ptr->gather_documentation(); - auto help_window = Spreadsheet::HelpWindow::the(window); - help_window->set_docs(move(docs)); - help_window->show(); - } else { - GUI::MessageBox::show_error(window, "Cannot prepare documentation/help without an active worksheet"); - } - }, - window)); - - help_menu.add_action(GUI::CommonActions::make_about_action("Spreadsheet", app_icon, window)); - window->show(); return app->exec();