gyscos / cursive

A Text User Interface library for the Rust programming language
MIT License
4.24k stars 240 forks source link

Moving between buttons from one linear layout to another #315

Open cotigao opened 5 years ago

cotigao commented 5 years ago

This is a minimal version, of what I'm trying to achieve,

fn main() {
    let mut siv = Cursive::default();
    let mut l = LinearLayout::new(Orientation::Vertical);

    for _ in 1..5 {
       let mut h = LinearLayout::new(Orientation::Horizontal);

       let b1 = Button::new("A", |_| {});
       let b2 = Button::new("B", |_| {});
       let b3 = Button::new("C", |_| {});

       h.add_child(b1);
       h.add_child(b2);
       h.add_child(b3);

       l.add_child(h);
    }

    siv.add_layer(ScrollView::new(l));
    siv.set_fps(30);
    siv.run();
}

However, when I try to move between the buttons from one horizontal layout to another (by pressing up/down keys) , the movement is not always natural. Sometimes it moves diagonally up (or down), which is not desired. I'm on v0.10.0. (rustc v1.31)

Is this expected?, as in do I need to write my own wrapper view to handle this?

gyscos commented 5 years ago

Hi, and thanks for the report!

This is currently a limitation of the focus system: when the focus leaves one linear layout and enters the next one, it knows the "direction" of the focus change (for example from the bottom), but not the exact location, so it doesn't know which button to select.

I'm afraid there is no short-term solution for this.

Adding more information to a change of focus, like the exact position of the previous focus, is one solution, but it involves a large refactor of the focus system. A better solution for this use-case would be a single grid-like view, but it's not quite there yet. A grid view would solve many problems, but it requires a non-trivial layout algorithm to support arbitrary configurations. I'll see if a reduced-scope version could be implemented earlier.

cotigao commented 5 years ago

Hi, Thanks for the update!