From c3b24953204ef4fab62202a293768252c49e823e Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Fri, 28 Aug 2020 21:24:59 +0200 Subject: [PATCH] Spreadsheet: Have cursor movement keys commit and stop cell editing Customize the cell editing delegate to stop editing when one of the various cursor movement keys is hit. This allows you to type into a cell and then move to an adjacent cell by simply pressing an arrow. This may not be the best factoring for this feature, but it's pretty dang cool and we'll see how it evolves over time. :^) --- Applications/Spreadsheet/SpreadsheetView.cpp | 9 ++- Applications/Spreadsheet/SpreadsheetView.h | 63 +++++++++++++++++++- 2 files changed, 69 insertions(+), 3 deletions(-) diff --git a/Applications/Spreadsheet/SpreadsheetView.cpp b/Applications/Spreadsheet/SpreadsheetView.cpp index cf9170f5b9..c3196b697c 100644 --- a/Applications/Spreadsheet/SpreadsheetView.cpp +++ b/Applications/Spreadsheet/SpreadsheetView.cpp @@ -78,8 +78,13 @@ SpreadsheetView::SpreadsheetView(Sheet& sheet) m_table_view->set_alternating_row_colors(false); m_table_view->set_highlight_selected_rows(false); m_table_view->set_editable(true); - m_table_view->aid_create_editing_delegate = [&](auto&) { - return make(*m_sheet); + m_table_view->aid_create_editing_delegate = [this](auto&) { + auto delegate = make(*m_sheet); + delegate->on_cursor_key_pressed = [this](auto& event) { + m_table_view->stop_editing(); + m_table_view->event(event); + }; + return delegate; }; m_table_view->on_selection_change = [&] { diff --git a/Applications/Spreadsheet/SpreadsheetView.h b/Applications/Spreadsheet/SpreadsheetView.h index 23d27ebfa8..8d1e341b23 100644 --- a/Applications/Spreadsheet/SpreadsheetView.h +++ b/Applications/Spreadsheet/SpreadsheetView.h @@ -34,6 +34,49 @@ namespace Spreadsheet { +class CellEditor final : public GUI::TextEditor { + C_OBJECT(CellEditor); + +public: + virtual ~CellEditor() { } + + Function on_cursor_key_pressed; + +private: + CellEditor() + : TextEditor(TextEditor::Type::SingleLine) + { + } + + static bool is_navigation(const GUI::KeyEvent& event) + { + if (event.modifiers() == KeyModifier::Mod_Shift && event.key() == KeyCode::Key_Tab) + return true; + + if (event.modifiers()) + return false; + + switch (event.key()) { + case KeyCode::Key_Tab: + case KeyCode::Key_Left: + case KeyCode::Key_Right: + case KeyCode::Key_Up: + case KeyCode::Key_Down: + return true; + default: + return false; + } + } + + virtual void keydown_event(GUI::KeyEvent& event) override + { + if (is_navigation(event)) + on_cursor_key_pressed(event); + else + TextEditor::keydown_event(event); + } +}; + class SpreadsheetView final : public GUI::Widget { C_OBJECT(SpreadsheetView); @@ -52,7 +95,7 @@ private: SpreadsheetView(Sheet&); - class EditingDelegate : public GUI::StringModelEditingDelegate { + class EditingDelegate final : public GUI::StringModelEditingDelegate { public: EditingDelegate(const Sheet& sheet) : m_sheet(sheet) @@ -60,6 +103,24 @@ private: } virtual void set_value(const GUI::Variant& value) override; + virtual RefPtr create_widget() override + { + auto textbox = CellEditor::construct(); + textbox->on_return_pressed = [this] { + commit(); + }; + textbox->on_escape_pressed = [this] { + rollback(); + }; + textbox->on_cursor_key_pressed = [this](auto& event) { + commit(); + on_cursor_key_pressed(event); + }; + return textbox; + } + + Function on_cursor_key_pressed; + private: bool m_has_set_initial_value { false }; const Sheet& m_sheet;