1use gpui::{Focusable, actions};
2
3actions!(
4 keyboard_navigation,
5 [NextRow, PreviousRow, NextColumn, PreviousColumn]
6);
7
8/// Implement this trait to enable grid-like keyboard navigation for a layout.
9///
10/// This trait allows you to navigate through a layout of rows with mixed column
11/// lengths. In example, a layout might have rows with 5, 1 and 3 columns.
12///
13/// Moving up or down between rows will focus the first element in the next or previous row.
14/// Moving left or right between columns will focus the next or previous element in the same row.
15///
16/// Wrapping can be enabled via `vertical_wrapping` and `horizontal_wrapping` respectively.
17pub trait KeyboardNavigation: Focusable {
18 fn has_focus(&self) -> bool;
19 /// The focused row. Always has a value to allow for "focused inactive" states.
20 fn focused_row(&self) -> usize;
21 /// The focused column. Always has a value to allow for "focused inactive" states.
22 fn focused_column(&self) -> usize;
23 /// Focus the first focusable element in the layout.
24 fn focus_first(&self);
25 /// Focus the next row, wrapping back to the first row if necessary.
26 ///
27 /// Is a no-op if wrapping is not enabled.
28 fn focus_next_row(&self);
29 /// Focus the previous row, wrapping back to the last row if necessary.
30 ///
31 /// Is a no-op if wrapping is not enabled.
32 fn focus_previous_row(&self);
33 /// Focus the next column, wrapping back to the first column if necessary.
34 ///
35 /// Is a no-op if wrapping is not enabled.
36 fn focus_next_column(&self);
37 /// Focus the previous column, wrapping back to the last column if necessary.
38 ///
39 /// Is a no-op if wrapping is not enabled.
40 fn focus_previous_column(&self);
41 /// Focus the row at the given index.
42 fn focus_row_index(&self, index: usize);
43 /// Focus the column at the given index.
44 fn focus_column_index(&self, ix: usize);
45 /// When reaching the last row, should moving down wrap
46 /// back to the first row, and vice versa?
47 fn vertical_wrap(&self) -> bool {
48 false
49 }
50 /// When reaching the last column, should moving right wrap
51 /// back to the first column, and vice versa?
52 fn horizontal_wrap(&self) -> bool {
53 false
54 }
55}
56
57pub struct NavigationRow {}
58
59pub struct NavigationColumn {}