diff options
author | Andreas Kling <kling@serenityos.org> | 2020-08-27 17:47:19 +0200 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2020-08-27 17:47:19 +0200 |
commit | 0b9d765f6bc080eda22594120ed95815ad839d10 (patch) | |
tree | 3958f2775c24685e94c6fbec64947ee24cdd684d | |
parent | 1b3169f405ac9250b65ee3608e2962f51d2d8e3c (diff) | |
download | serenity-0b9d765f6bc080eda22594120ed95815ad839d10.zip |
LibGUI: Add AbstractView::move_cursor() and share some movement logic
A view can now be told to move its cursor in one of multiple directions
as specified by the CursorMovement enum.
View subclasses can override move_cursor(CursorMovement) to implement
their own cursor behavior. By default, AbstractView::move_cursor() is
a no-op.
This patch improves code sharing between TableView and TreeView. :^)
-rw-r--r-- | Libraries/LibGUI/AbstractTableView.cpp | 35 | ||||
-rw-r--r-- | Libraries/LibGUI/AbstractTableView.h | 1 | ||||
-rw-r--r-- | Libraries/LibGUI/AbstractView.h | 15 | ||||
-rw-r--r-- | Libraries/LibGUI/TableView.cpp | 50 | ||||
-rw-r--r-- | Libraries/LibGUI/TableView.h | 2 | ||||
-rw-r--r-- | Libraries/LibGUI/TreeView.cpp | 104 | ||||
-rw-r--r-- | Libraries/LibGUI/TreeView.h | 2 |
7 files changed, 154 insertions, 55 deletions
diff --git a/Libraries/LibGUI/AbstractTableView.cpp b/Libraries/LibGUI/AbstractTableView.cpp index f5e6559bd2..aaf596eb9c 100644 --- a/Libraries/LibGUI/AbstractTableView.cpp +++ b/Libraries/LibGUI/AbstractTableView.cpp @@ -383,4 +383,39 @@ void AbstractTableView::set_row_height(int height) update_row_sizes(); } +void AbstractTableView::keydown_event(KeyEvent& event) +{ + if (event.key() == KeyCode::Key_Left) { + move_cursor(CursorMovement::Left); + event.accept(); + return; + } + if (event.key() == KeyCode::Key_Right) { + move_cursor(CursorMovement::Right); + event.accept(); + return; + } + if (event.key() == KeyCode::Key_Up) { + move_cursor(CursorMovement::Up); + event.accept(); + return; + } + if (event.key() == KeyCode::Key_Down) { + move_cursor(CursorMovement::Down); + event.accept(); + return; + } + if (event.key() == KeyCode::Key_Home) { + move_cursor(CursorMovement::Home); + event.accept(); + return; + } + if (event.key() == KeyCode::Key_End) { + move_cursor(CursorMovement::End); + event.accept(); + return; + } + return AbstractView::keydown_event(event); +} + } diff --git a/Libraries/LibGUI/AbstractTableView.h b/Libraries/LibGUI/AbstractTableView.h index 4341a5d139..c753dba91c 100644 --- a/Libraries/LibGUI/AbstractTableView.h +++ b/Libraries/LibGUI/AbstractTableView.h @@ -96,6 +96,7 @@ protected: virtual void mousedown_event(MouseEvent&) override; virtual void doubleclick_event(MouseEvent&) override; virtual void context_menu_event(ContextMenuEvent&) override; + virtual void keydown_event(KeyEvent&) override; virtual void resize_event(ResizeEvent&) override; virtual void did_update_model(unsigned flags) override; diff --git a/Libraries/LibGUI/AbstractView.h b/Libraries/LibGUI/AbstractView.h index 273f7f50f2..31d31aa8a4 100644 --- a/Libraries/LibGUI/AbstractView.h +++ b/Libraries/LibGUI/AbstractView.h @@ -33,9 +33,22 @@ namespace GUI { class AbstractView : public ScrollableWidget { - C_OBJECT_ABSTRACT(AbstractView) + C_OBJECT_ABSTRACT(AbstractView); public: + enum class CursorMovement { + Up, + Down, + Left, + Right, + Home, + End, + PageUp, + PageDown, + }; + + virtual void move_cursor(CursorMovement) { } + void set_model(RefPtr<Model>); Model* model() { return m_model.ptr(); } const Model* model() const { return m_model.ptr(); } diff --git a/Libraries/LibGUI/TableView.cpp b/Libraries/LibGUI/TableView.cpp index dc773f1349..b5feb595c0 100644 --- a/Libraries/LibGUI/TableView.cpp +++ b/Libraries/LibGUI/TableView.cpp @@ -154,28 +154,44 @@ void TableView::keydown_event(KeyEvent& event) { if (!model()) return; - auto& model = *this->model(); if (event.key() == KeyCode::Key_Return) { activate_or_edit_selected(); return; } - if (event.key() == KeyCode::Key_Left) { - move_selection(0, -1); + return AbstractTableView::keydown_event(event); +} + +void TableView::move_cursor(CursorMovement movement) +{ + if (!model()) return; - } - if (event.key() == KeyCode::Key_Right) { + auto& model = *this->model(); + switch (movement) { + case CursorMovement::Left: + move_selection(0, -1); + break; + case CursorMovement::Right: move_selection(0, 1); - return; - } - if (event.key() == KeyCode::Key_Up) { + break; + case CursorMovement::Up: move_selection(-1, 0); - return; - } - if (event.key() == KeyCode::Key_Down) { + break; + case CursorMovement::Down: move_selection(1, 0); - return; + break; + case CursorMovement::Home: { + auto index = model.index(0, 0); + set_selection(index); + scroll_into_view(index, Gfx::Orientation::Vertical); + break; } - if (event.key() == KeyCode::Key_PageUp) { + case CursorMovement::End: { + auto index = model.index(model.row_count() - 1, 0); + set_selection(index); + scroll_into_view(index, Gfx::Orientation::Vertical); + break; + } + case CursorMovement::PageUp: { int items_per_page = visible_content_rect().height() / row_height(); auto old_index = selection().first(); auto new_index = model.index(max(0, old_index.row() - items_per_page), old_index.column()); @@ -184,9 +200,9 @@ void TableView::keydown_event(KeyEvent& event) scroll_into_view(new_index, Orientation::Vertical); update(); } - return; + break; } - if (event.key() == KeyCode::Key_PageDown) { + case CursorMovement::PageDown: { int items_per_page = visible_content_rect().height() / row_height(); auto old_index = selection().first(); auto new_index = model.index(min(model.row_count() - 1, old_index.row() + items_per_page), old_index.column()); @@ -195,9 +211,9 @@ void TableView::keydown_event(KeyEvent& event) scroll_into_view(new_index, Orientation::Vertical); update(); } - return; + break; + } } - return Widget::keydown_event(event); } } diff --git a/Libraries/LibGUI/TableView.h b/Libraries/LibGUI/TableView.h index fc228aaebb..792b8290ae 100644 --- a/Libraries/LibGUI/TableView.h +++ b/Libraries/LibGUI/TableView.h @@ -38,6 +38,8 @@ public: protected: TableView(); + virtual void move_cursor(CursorMovement) override; + virtual void keydown_event(KeyEvent&) override; virtual void paint_event(PaintEvent&) override; }; diff --git a/Libraries/LibGUI/TreeView.cpp b/Libraries/LibGUI/TreeView.cpp index 0984bd0628..b19f89f51b 100644 --- a/Libraries/LibGUI/TreeView.cpp +++ b/Libraries/LibGUI/TreeView.cpp @@ -418,43 +418,6 @@ void TreeView::keydown_event(KeyEvent& event) return; } - if (event.key() == KeyCode::Key_Up) { - ModelIndex previous_index; - ModelIndex found_index; - traverse_in_paint_order([&](const ModelIndex& index, const Gfx::IntRect&, const Gfx::IntRect&, int) { - if (index == cursor_index) { - found_index = previous_index; - return IterationDecision::Break; - } - previous_index = index; - return IterationDecision::Continue; - }); - if (found_index.is_valid()) { - selection().set(found_index); - scroll_into_view(selection().first(), Orientation::Vertical); - update(); - } - return; - } - if (event.key() == KeyCode::Key_Down) { - ModelIndex previous_index; - ModelIndex found_index; - traverse_in_paint_order([&](const ModelIndex& index, const Gfx::IntRect&, const Gfx::IntRect&, int) { - if (previous_index == cursor_index) { - found_index = index; - return IterationDecision::Break; - } - previous_index = index; - return IterationDecision::Continue; - }); - if (found_index.is_valid()) { - selection().set(found_index); - scroll_into_view(selection().first(), Orientation::Vertical); - update(); - } - return; - } - auto open_tree_node = [&](bool open, MetadataForIndex& metadata) { if (on_toggle) on_toggle(cursor_index, open); @@ -509,6 +472,73 @@ void TreeView::keydown_event(KeyEvent& event) return; } } + + AbstractTableView::keydown_event(event); +} + +void TreeView::move_cursor(CursorMovement movement) +{ + auto cursor_index = selection().first(); + + switch (movement) { + case CursorMovement::Up: { + ModelIndex previous_index; + ModelIndex found_index; + traverse_in_paint_order([&](const ModelIndex& index, const Gfx::IntRect&, const Gfx::IntRect&, int) { + if (index == cursor_index) { + found_index = previous_index; + return IterationDecision::Break; + } + previous_index = index; + return IterationDecision::Continue; + }); + if (found_index.is_valid()) { + selection().set(found_index); + scroll_into_view(selection().first(), Orientation::Vertical); + update(); + } + break; + } + case CursorMovement::Down: { + ModelIndex previous_index; + ModelIndex found_index; + traverse_in_paint_order([&](const ModelIndex& index, const Gfx::IntRect&, const Gfx::IntRect&, int) { + if (previous_index == cursor_index) { + found_index = index; + return IterationDecision::Break; + } + previous_index = index; + return IterationDecision::Continue; + }); + if (found_index.is_valid()) { + selection().set(found_index); + scroll_into_view(selection().first(), Orientation::Vertical); + update(); + } + return; + } + + case CursorMovement::Home: + // FIXME: Implement. + break; + + case CursorMovement::End: + // FIXME: Implement. + break; + + case CursorMovement::PageUp: + // FIXME: Implement. + break; + + case CursorMovement::PageDown: + // FIXME: Implement. + break; + + case CursorMovement::Left: + case CursorMovement::Right: + // There is no left/right in a treeview, those keys expand/collapse items instead. + break; + } } int TreeView::item_count() const diff --git a/Libraries/LibGUI/TreeView.h b/Libraries/LibGUI/TreeView.h index 4ce99842a8..18ad2c8413 100644 --- a/Libraries/LibGUI/TreeView.h +++ b/Libraries/LibGUI/TreeView.h @@ -52,8 +52,10 @@ protected: virtual void paint_event(PaintEvent&) override; virtual void doubleclick_event(MouseEvent&) override; virtual void keydown_event(KeyEvent&) override; + virtual void did_update_selection() override; virtual void did_update_model(unsigned flags) override; + virtual void move_cursor(CursorMovement) override; private: virtual ModelIndex index_at_event_position(const Gfx::IntPoint&, bool& is_toggle) const override; |