diff --git a/cursive-core/src/views/fixed_layout.rs b/cursive-core/src/views/fixed_layout.rs index 10a7334..def2c9a 100644 --- a/cursive-core/src/views/fixed_layout.rs +++ b/cursive-core/src/views/fixed_layout.rs @@ -7,11 +7,28 @@ use crate::{Printer, Vec2, View, With}; /// Arranges its children in a fixed layout. /// /// Usually meant to use an external layout engine. +/// +/// # Examples +/// +/// ```rust +/// use cursive_core::{ +/// views::{FixedLayout, TextView, Button}, +/// Rect, +/// }; +/// +/// let layout = FixedLayout::new() +/// .child(Rect::from_size((0,0), (1,1)), TextView::new("/")) +/// .child(Rect::from_size((14,0), (1,1)), TextView::new(r"\")) +/// .child(Rect::from_size((0,2), (1,1)), TextView::new(r"\")) +/// .child(Rect::from_size((14,2), (1,1)), TextView::new("/")) +/// .child(Rect::from_size((3,1), (11,1)), Button::new("Clickme", |s| s.quit())); +/// ```` pub struct FixedLayout { children: Vec, focus: usize, } +/// Represents a child view inside the FixedLayout. struct Child { view: Box, position: Rect, @@ -123,7 +140,21 @@ impl FixedLayout { } } - fn move_focus(&mut self, target: Absolute) -> EventResult { + fn move_focus_rel(&mut self, target: Relative) -> EventResult { + let source = Direction::Rel(target.swap()); + for (i, c) in + Self::iter_mut(source, &mut self.children).skip(self.focus + 1) + { + if c.view.take_focus(source) { + self.focus = i; + return EventResult::Consumed(None); + } + } + + EventResult::Ignored + } + + fn move_focus_abs(&mut self, target: Absolute) -> EventResult { let source = Direction::Abs(target.opposite()); let (orientation, rel) = target.split(); @@ -198,6 +229,7 @@ impl View for FixedLayout { } fn on_event(&mut self, event: Event) -> EventResult { + eprintln!("Self focus: {:?}", self.focus); if self.is_empty() { return EventResult::Ignored; } @@ -212,11 +244,12 @@ impl View for FixedLayout { match result { EventResult::Ignored => match event { - Event::Key(Key::Tab) => unimplemented!(), - Event::Key(Key::Left) => self.move_focus(Absolute::Left), - Event::Key(Key::Right) => self.move_focus(Absolute::Right), - Event::Key(Key::Up) => self.move_focus(Absolute::Up), - Event::Key(Key::Down) => self.move_focus(Absolute::Down), + Event::Shift(Key::Tab) => self.move_focus_rel(Relative::Front), + Event::Key(Key::Tab) => self.move_focus_rel(Relative::Back), + Event::Key(Key::Left) => self.move_focus_abs(Absolute::Left), + Event::Key(Key::Right) => self.move_focus_abs(Absolute::Right), + Event::Key(Key::Up) => self.move_focus_abs(Absolute::Up), + Event::Key(Key::Down) => self.move_focus_abs(Absolute::Down), _ => EventResult::Ignored, }, res => res, @@ -243,6 +276,7 @@ impl View for FixedLayout { fn take_focus(&mut self, source: Direction) -> bool { // TODO: what if source = None? + eprintln!("Self focus: {:?}", self.focus); match source { Direction::Abs(Absolute::None) => { // For now, take focus if any view is focusable. diff --git a/cursive-core/src/views/stack_view.rs b/cursive-core/src/views/stack_view.rs index cb99c29..5235c55 100644 --- a/cursive-core/src/views/stack_view.rs +++ b/cursive-core/src/views/stack_view.rs @@ -648,7 +648,7 @@ impl View for StackView { // The text view takes focus because it's scrolling, but it only // knows that after a call to `layout()`. if layer.virgin { - layer.view.take_focus(Direction::none()); + layer.view.take_focus(Direction::front()); layer.virgin = false; } } diff --git a/examples/src/bin/fixed_layout.rs b/examples/src/bin/fixed_layout.rs index 900d785..def7985 100644 --- a/examples/src/bin/fixed_layout.rs +++ b/examples/src/bin/fixed_layout.rs @@ -1,12 +1,21 @@ +use cursive::{ + views::{Button, FixedLayout, TextView}, + Rect, +}; fn main() { let mut siv = cursive::default(); siv.add_layer( cursive::views::Dialog::around( - cursive::views::FixedLayout::new().child( - cursive::Rect::from_size((0, 0), (10, 1)), - cursive::views::TextView::new("abc"), - ), + FixedLayout::new() + .child(Rect::from_size((0, 0), (1, 1)), TextView::new("/")) + .child(Rect::from_size((14, 0), (1, 1)), TextView::new(r"\")) + .child(Rect::from_size((0, 2), (1, 1)), TextView::new(r"\")) + .child(Rect::from_size((14, 2), (1, 1)), TextView::new("/")) + .child( + Rect::from_size((2, 1), (11, 1)), + Button::new("Click me!", |s| s.quit()), + ), ) .button("Quit", |s| s.quit()), );