summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Kling <kling@serenityos.org>2020-08-27 17:47:19 +0200
committerAndreas Kling <kling@serenityos.org>2020-08-27 17:47:19 +0200
commit0b9d765f6bc080eda22594120ed95815ad839d10 (patch)
tree3958f2775c24685e94c6fbec64947ee24cdd684d
parent1b3169f405ac9250b65ee3608e2962f51d2d8e3c (diff)
downloadserenity-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.cpp35
-rw-r--r--Libraries/LibGUI/AbstractTableView.h1
-rw-r--r--Libraries/LibGUI/AbstractView.h15
-rw-r--r--Libraries/LibGUI/TableView.cpp50
-rw-r--r--Libraries/LibGUI/TableView.h2
-rw-r--r--Libraries/LibGUI/TreeView.cpp104
-rw-r--r--Libraries/LibGUI/TreeView.h2
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;