Fix bad initial focus

This commit is contained in:
Alexandre Bury 2020-06-29 18:00:57 -07:00
parent 81e64da72a
commit f2b1fac679
3 changed files with 54 additions and 11 deletions

View File

@ -7,11 +7,28 @@ use crate::{Printer, Vec2, View, With};
/// Arranges its children in a fixed layout. /// Arranges its children in a fixed layout.
/// ///
/// Usually meant to use an external layout engine. /// 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 { pub struct FixedLayout {
children: Vec<Child>, children: Vec<Child>,
focus: usize, focus: usize,
} }
/// Represents a child view inside the FixedLayout.
struct Child { struct Child {
view: Box<dyn View>, view: Box<dyn View>,
position: Rect, 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 source = Direction::Abs(target.opposite());
let (orientation, rel) = target.split(); let (orientation, rel) = target.split();
@ -198,6 +229,7 @@ impl View for FixedLayout {
} }
fn on_event(&mut self, event: Event) -> EventResult { fn on_event(&mut self, event: Event) -> EventResult {
eprintln!("Self focus: {:?}", self.focus);
if self.is_empty() { if self.is_empty() {
return EventResult::Ignored; return EventResult::Ignored;
} }
@ -212,11 +244,12 @@ impl View for FixedLayout {
match result { match result {
EventResult::Ignored => match event { EventResult::Ignored => match event {
Event::Key(Key::Tab) => unimplemented!(), Event::Shift(Key::Tab) => self.move_focus_rel(Relative::Front),
Event::Key(Key::Left) => self.move_focus(Absolute::Left), Event::Key(Key::Tab) => self.move_focus_rel(Relative::Back),
Event::Key(Key::Right) => self.move_focus(Absolute::Right), Event::Key(Key::Left) => self.move_focus_abs(Absolute::Left),
Event::Key(Key::Up) => self.move_focus(Absolute::Up), Event::Key(Key::Right) => self.move_focus_abs(Absolute::Right),
Event::Key(Key::Down) => self.move_focus(Absolute::Down), Event::Key(Key::Up) => self.move_focus_abs(Absolute::Up),
Event::Key(Key::Down) => self.move_focus_abs(Absolute::Down),
_ => EventResult::Ignored, _ => EventResult::Ignored,
}, },
res => res, res => res,
@ -243,6 +276,7 @@ impl View for FixedLayout {
fn take_focus(&mut self, source: Direction) -> bool { fn take_focus(&mut self, source: Direction) -> bool {
// TODO: what if source = None? // TODO: what if source = None?
eprintln!("Self focus: {:?}", self.focus);
match source { match source {
Direction::Abs(Absolute::None) => { Direction::Abs(Absolute::None) => {
// For now, take focus if any view is focusable. // For now, take focus if any view is focusable.

View File

@ -648,7 +648,7 @@ impl View for StackView {
// The text view takes focus because it's scrolling, but it only // The text view takes focus because it's scrolling, but it only
// knows that after a call to `layout()`. // knows that after a call to `layout()`.
if layer.virgin { if layer.virgin {
layer.view.take_focus(Direction::none()); layer.view.take_focus(Direction::front());
layer.virgin = false; layer.virgin = false;
} }
} }

View File

@ -1,12 +1,21 @@
use cursive::{
views::{Button, FixedLayout, TextView},
Rect,
};
fn main() { fn main() {
let mut siv = cursive::default(); let mut siv = cursive::default();
siv.add_layer( siv.add_layer(
cursive::views::Dialog::around( cursive::views::Dialog::around(
cursive::views::FixedLayout::new().child( FixedLayout::new()
cursive::Rect::from_size((0, 0), (10, 1)), .child(Rect::from_size((0, 0), (1, 1)), TextView::new("/"))
cursive::views::TextView::new("abc"), .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()), .button("Quit", |s| s.quit()),
); );