cursive icon indicating copy to clipboard operation
cursive copied to clipboard

Is it possible to set a default option for SelectView in ListView?

Open eatradish opened this issue 2 years ago • 1 comments

Describe the bug I tried to write an interface with a SelectView in a ListView with the following code:

use std::{rc::Rc, cell::RefCell};

use cursive::{
    traits::Resizable,
    view::SizeConstraint,
    views::{Dialog, LinearLayout, ListView, ResizedView, ScrollView, SelectView, TextView},
    Cursive, View,
};

fn main() {
    let mut c = cursive::default();
    let msg = Rc::new(RefCell::new(String::new()));
    let msg_clone = msg.clone();
    let s = wrap_in_dialog(
        LinearLayout::vertical()
            .child(
                ListView::new().child(
                    "QAQ",
                    SelectView::new()
                        .popup()
                        .autojump()
                        .with_all_str(vec!["a", "b"])
                        .selected(0)
                        .on_submit(move |_, c| match c {
                            "a" => {
                                msg_clone.replace(c.to_string());
                            },
                            "b" => {
                                msg_clone.replace(c.to_string());
                            },
                            _ => {
                                msg_clone.replace("nothing".to_string());
                            },
                        }),
                ),
            )
            .min_width(20),
        "qaq",
        None,
    ).button("Next", move |c| {
        let msg = msg.as_ref().to_owned().into_inner();
        show_msg(c, &msg);
    });
    c.add_layer(s);
    c.run();
}

fn show_msg(siv: &mut Cursive, msg: &str) {
    siv.add_layer(
        Dialog::around(TextView::new(msg))
            .title("QAQ")
            .button("OK", |s| {
                s.pop_layer();
            })
            .padding_lrtb(2, 2, 1, 1),
    );
}

fn wrap_in_dialog<V: View, S: Into<String>>(inner: V, title: S, width: Option<usize>) -> Dialog {
    Dialog::around(ResizedView::new(
        SizeConstraint::AtMost(width.unwrap_or(64)),
        SizeConstraint::Free,
        ScrollView::new(inner),
    ))
    .padding_lrtb(2, 2, 1, 1)
    .title(title)
}

I found that in the interface it selects a by default, but this is just an illusion, in fact here cursive doesn't select anything.

Screenshots The screen at the beginning (it looks like a is selected, but it is not):

image

After pressing the Next button directly:

image

select a and click "Next":

image

Environment

  • AOSC OS (Linux distro)
  • Backend used: ncurses
saki@CIP [ atest@ ] ! locale
LANG=en_US.UTF-8
LC_CTYPE="en_US.UTF-8"
LC_NUMERIC="en_US.UTF-8"
LC_TIME="en_US.UTF-8"
LC_COLLATE="en_US.UTF-8"
LC_MONETARY="en_US.UTF-8"
LC_MESSAGES="en_US.UTF-8"
LC_PAPER="en_US.UTF-8"
LC_NAME="en_US.UTF-8"
LC_ADDRESS="en_US.UTF-8"
LC_TELEPHONE="en_US.UTF-8"
LC_MEASUREMENT="en_US.UTF-8"
LC_IDENTIFICATION="en_US.UTF-8"
LC_ALL=
  • cursive 0.18

eatradish avatar May 15 '22 13:05 eatradish

Hi, and thanks for the report!

I think the issue here is that on_submit is only called when actually "submitting" something (for popup SelectView, this is indeed when selecting an entry. But setting the selection at first does not "submit" anything.

It seems you want to know the current selection, rather than doing something on submit. To do that, you could query the state of the view in the show_msg callback. To query the current state of the view, you could give it a name, then find a view by name. You can check the third tutorial for how to do that.

gyscos avatar Jun 19 '22 20:06 gyscos