summaryrefslogtreecommitdiffstats
path: root/src/app/layout_manager.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/app/layout_manager.rs')
-rw-r--r--src/app/layout_manager.rs133
1 files changed, 90 insertions, 43 deletions
diff --git a/src/app/layout_manager.rs b/src/app/layout_manager.rs
index 9b88fb8a..61d17924 100644
--- a/src/app/layout_manager.rs
+++ b/src/app/layout_manager.rs
@@ -997,9 +997,9 @@ Supported widget names:
// --- New stuff ---
/// Represents a row in the layout tree.
-#[derive(PartialEq, Eq, Clone)]
+#[derive(Debug, PartialEq, Eq, Clone)]
pub struct RowLayout {
- last_selected_index: usize,
+ last_selected: Option<NodeId>,
pub parent_rule: LayoutRule,
pub bound: Rect,
}
@@ -1007,7 +1007,7 @@ pub struct RowLayout {
impl RowLayout {
fn new(parent_rule: LayoutRule) -> Self {
Self {
- last_selected_index: 0,
+ last_selected: None,
parent_rule,
bound: Rect::default(),
}
@@ -1015,9 +1015,9 @@ impl RowLayout {
}
/// Represents a column in the layout tree.
-#[derive(PartialEq, Eq, Clone)]
+#[derive(Debug, PartialEq, Eq, Clone)]
pub struct ColLayout {
- last_selected_index: usize,
+ last_selected: Option<NodeId>,
pub parent_rule: LayoutRule,
pub bound: Rect,
}
@@ -1025,7 +1025,7 @@ pub struct ColLayout {
impl ColLayout {
fn new(parent_rule: LayoutRule) -> Self {
Self {
- last_selected_index: 0,
+ last_selected: None,
parent_rule,
bound: Rect::default(),
}
@@ -1033,7 +1033,7 @@ impl ColLayout {
}
/// Represents a widget in the layout tree.
-#[derive(PartialEq, Eq, Clone, Default)]
+#[derive(Debug, PartialEq, Eq, Clone, Default)]
pub struct WidgetLayout {
pub bound: Rect,
}
@@ -1042,7 +1042,7 @@ pub struct WidgetLayout {
/// - [`LayoutNode::Row`] (a non-leaf that distributes its children horizontally)
/// - [`LayoutNode::Col`] (a non-leaf node that distributes its children vertically)
/// - [`LayoutNode::Widget`] (a leaf node that contains the ID of the widget it is associated with)
-#[derive(PartialEq, Eq, Clone)]
+#[derive(Debug, PartialEq, Eq, Clone)]
pub enum LayoutNode {
/// A non-leaf that distributes its children horizontally
Row(RowLayout),
@@ -1382,6 +1382,8 @@ pub fn create_layout_tree(
));
}
+ correct_layout_last_selections(&mut arena, selected);
+
Ok(LayoutCreationOutput {
layout_tree: arena,
root: root_id,
@@ -1391,6 +1393,35 @@ pub fn create_layout_tree(
})
}
+/// We may have situations where we also have to make sure the correct layout indices are selected.
+/// For example, when we select a widget by clicking, we want to update the layout so that it's as if a user
+/// manually moved to it via keybinds.
+///
+/// We can do this by just going through the ancestors, starting from the widget itself.
+pub fn correct_layout_last_selections(arena: &mut Arena<LayoutNode>, selected: NodeId) {
+ let mut selected_ancestors = selected.ancestors(&arena).collect::<Vec<_>>();
+ let prev_node = selected_ancestors.pop();
+ if let Some(mut prev_node) = prev_node {
+ for node in selected_ancestors {
+ if let Some(layout_node) = arena.get_mut(node).map(|n| n.get_mut()) {
+ match layout_node {
+ LayoutNode::Row(RowLayout { last_selected, .. })
+ | LayoutNode::Col(ColLayout { last_selected, .. }) => {
+ *last_selected = Some(prev_node);
+ }
+ LayoutNode::Widget(_) => {}
+ }
+ }
+ prev_node = node;
+ }
+ }
+}
+
+pub enum MoveWidgetResult {
+ ForceRedraw(NodeId),
+ NodeId(NodeId),
+}
+
/// Attempts to find and return the selected [`BottomWidgetId`] after moving in a direction.
///
/// Note this function assumes a properly built tree - if not, bad things may happen! We generally assume that:
@@ -1399,7 +1430,7 @@ pub fn create_layout_tree(
pub fn move_widget_selection(
layout_tree: &mut Arena<LayoutNode>, current_widget: &mut TmpBottomWidget,
current_widget_id: NodeId, direction: MovementDirection,
-) -> NodeId {
+) -> MoveWidgetResult {
// We first give our currently-selected widget a chance to react to the movement - it may handle it internally!
let handled = match direction {
MovementDirection::Left => current_widget.handle_widget_selection_left(),
@@ -1408,16 +1439,18 @@ pub fn move_widget_selection(
MovementDirection::Down => current_widget.handle_widget_selection_down(),
};
+ // TODO: Do testing.
+
match handled {
SelectionAction::Handled => {
// If it was handled by the widget, then we don't have to do anything - return the current one.
- current_widget_id
+ MoveWidgetResult::ForceRedraw(current_widget_id)
}
SelectionAction::NotHandled => {
/// Keeps traversing up the `layout_tree` until it hits a parent where `current_id` is a child and parent
/// is a [`LayoutNode::Row`], returning its parent's [`NodeId`] and the child's [`NodeId`] (in that order).
/// If this crawl fails (i.e. hits a root, it is an invalid tree for some reason), it returns [`None`].
- fn find_first_row(
+ fn find_parent_row(
layout_tree: &Arena<LayoutNode>, current_id: NodeId,
) -> Option<(NodeId, NodeId)> {
layout_tree
@@ -1430,7 +1463,7 @@ pub fn move_widget_selection(
})
.and_then(|(parent_id, parent_node)| match parent_node.get() {
LayoutNode::Row(_) => Some((parent_id, current_id)),
- LayoutNode::Col(_) => find_first_row(layout_tree, parent_id),
+ LayoutNode::Col(_) => find_parent_row(layout_tree, parent_id),
LayoutNode::Widget(_) => None,
})
}
@@ -1438,7 +1471,7 @@ pub fn move_widget_selection(
/// Keeps traversing up the `layout_tree` until it hits a parent where `current_id` is a child and parent
/// is a [`LayoutNode::Col`], returning its parent's [`NodeId`] and the child's [`NodeId`] (in that order).
/// If this crawl fails (i.e. hits a root, it is an invalid tree for some reason), it returns [`None`].
- fn find_first_col(
+ fn find_parent_col(
layout_tree: &Arena<LayoutNode>, current_id: NodeId,
) -> Option<(NodeId, NodeId)> {
layout_tree
@@ -1450,7 +1483,7 @@ pub fn move_widget_selection(
.map(|parent_node| (parent_id, parent_node))
})
.and_then(|(parent_id, parent_node)| match parent_node.get() {
- LayoutNode::Row(_) => find_first_col(layout_tree, parent_id),
+ LayoutNode::Row(_) => find_parent_col(layout_tree, parent_id),
LayoutNode::Col(_) => Some((parent_id, current_id)),
LayoutNode::Widget(_) => None,
})
@@ -1461,21 +1494,19 @@ pub fn move_widget_selection(
if let Some(current_node) = layout_tree.get(current_id) {
match current_node.get() {
LayoutNode::Row(RowLayout {
- last_selected_index,
+ last_selected,
parent_rule: _,
bound: _,
})
| LayoutNode::Col(ColLayout {
- last_selected_index,
+ last_selected,
parent_rule: _,
bound: _,
}) => {
- if let Some(next_child) =
- current_id.children(layout_tree).nth(*last_selected_index)
- {
+ if let Some(next_child) = *last_selected {
descend_to_leaf(layout_tree, next_child)
} else {
- current_id
+ current_node.first_child().unwrap_or(current_id)
}
}
LayoutNode::Widget(_) => {
@@ -1493,7 +1524,7 @@ pub fn move_widget_selection(
// on the tree layout to help us decide where to go.
// Movement logic is inspired by i3. When we enter a new column/row, we go to the *last* selected
// element; if we can't, go to the nearest one.
- match direction {
+ let proposed_id = match direction {
MovementDirection::Left => {
// When we move "left":
// 1. Look for the parent of the current widget.
@@ -1513,7 +1544,8 @@ pub fn move_widget_selection(
fn find_left(
layout_tree: &mut Arena<LayoutNode>, current_id: NodeId,
) -> NodeId {
- if let Some((parent_id, child_id)) = find_first_row(layout_tree, current_id)
+ if let Some((parent_id, child_id)) =
+ find_parent_row(layout_tree, current_id)
{
if let Some(prev_sibling) =
child_id.preceding_siblings(layout_tree).nth(1)
@@ -1521,16 +1553,17 @@ pub fn move_widget_selection(
// Subtract one from the currently selected index...
if let Some(parent) = layout_tree.get_mut(parent_id) {
if let LayoutNode::Row(row) = parent.get_mut() {
- row.last_selected_index =
- row.last_selected_index.saturating_sub(1);
+ row.last_selected = Some(prev_sibling);
}
}
// Now descend downwards!
descend_to_leaf(layout_tree, prev_sibling)
- } else {
+ } else if parent_id != current_id {
// Darn, we can't go further back! Recurse on this ID.
- find_left(layout_tree, child_id)
+ find_left(layout_tree, parent_id)
+ } else {
+ current_id
}
} else {
// Failed, just return the current ID.
@@ -1546,23 +1579,26 @@ pub fn move_widget_selection(
fn find_right(
layout_tree: &mut Arena<LayoutNode>, current_id: NodeId,
) -> NodeId {
- if let Some((parent_id, child_id)) = find_first_row(layout_tree, current_id)
+ if let Some((parent_id, child_id)) =
+ find_parent_row(layout_tree, current_id)
{
- if let Some(prev_sibling) =
+ if let Some(following_sibling) =
child_id.following_siblings(layout_tree).nth(1)
{
// Add one to the currently selected index...
if let Some(parent) = layout_tree.get_mut(parent_id) {
if let LayoutNode::Row(row) = parent.get_mut() {
- row.last_selected_index += 1;
+ row.last_selected = Some(following_sibling);
}
}
// Now descend downwards!
- descend_to_leaf(layout_tree, prev_sibling)
- } else {
+ descend_to_leaf(layout_tree, following_sibling)
+ } else if parent_id != current_id {
// Darn, we can't go further back! Recurse on this ID.
- find_right(layout_tree, child_id)
+ find_right(layout_tree, parent_id)
+ } else {
+ current_id
}
} else {
// Failed, just return the current ID.
@@ -1578,7 +1614,8 @@ pub fn move_widget_selection(
fn find_above(
layout_tree: &mut Arena<LayoutNode>, current_id: NodeId,
) -> NodeId {
- if let Some((parent_id, child_id)) = find_first_col(layout_tree, current_id)
+ if let Some((parent_id, child_id)) =
+ find_parent_col(layout_tree, current_id)
{
if let Some(prev_sibling) =
child_id.preceding_siblings(layout_tree).nth(1)
@@ -1586,16 +1623,17 @@ pub fn move_widget_selection(
// Subtract one from the currently selected index...
if let Some(parent) = layout_tree.get_mut(parent_id) {
if let LayoutNode::Col(row) = parent.get_mut() {
- row.last_selected_index =
- row.last_selected_index.saturating_sub(1);
+ row.last_selected = Some(prev_sibling);
}
}
// Now descend downwards!
descend_to_leaf(layout_tree, prev_sibling)
- } else {
+ } else if parent_id != current_id {
// Darn, we can't go further back! Recurse on this ID.
- find_above(layout_tree, child_id)
+ find_above(layout_tree, parent_id)
+ } else {
+ current_id
}
} else {
// Failed, just return the current ID.
@@ -1611,23 +1649,26 @@ pub fn move_widget_selection(
fn find_below(
layout_tree: &mut Arena<LayoutNode>, current_id: NodeId,
) -> NodeId {
- if let Some((parent_id, child_id)) = find_first_col(layout_tree, current_id)
+ if let Some((parent_id, child_id)) =
+ find_parent_col(layout_tree, current_id)
{
- if let Some(prev_sibling) =
+ if let Some(following_sibling) =
child_id.following_siblings(layout_tree).nth(1)
{
// Add one to the currently selected index...
if let Some(parent) = layout_tree.get_mut(parent_id) {
if let LayoutNode::Col(row) = parent.get_mut() {
- row.last_selected_index += 1;
+ row.last_selected = Some(following_sibling);
}
}
// Now descend downwards!
- descend_to_leaf(layout_tree, prev_sibling)
- } else {
+ descend_to_leaf(layout_tree, following_sibling)
+ } else if parent_id != current_id {
// Darn, we can't go further back! Recurse on this ID.
- find_below(layout_tree, child_id)
+ find_below(layout_tree, parent_id)
+ } else {
+ current_id
}
} else {
// Failed, just return the current ID.
@@ -1636,6 +1677,12 @@ pub fn move_widget_selection(
}
find_below(layout_tree, current_widget_id)
}
+ };
+
+ if let Some(LayoutNode::Widget(_)) = layout_tree.get(proposed_id).map(|n| n.get()) {
+ MoveWidgetResult::NodeId(proposed_id)
+ } else {
+ MoveWidgetResult::NodeId(current_widget_id)
}
}
}