Repository navigation
|
The below code creates a dialog with a group of radio buttons followed by a set of checkboxes. I want the application to handle the
I'm at a loss as to how to fix the aberrant behaviors; it seems there's something about how focus-changing is implemented in cursive that I don't understand. Note that, in my actual code, the form is dynamic, so the top group (the one whose first element should receive focus from Code: use cursive::{
Cursive, View,
direction::Direction,
event::{EventResult, Key},
view::{Finder, Nameable},
views::{
Checkbox, Dialog, DialogFocus, DummyView, LinearLayout, OnEventView, PaddedView,
RadioGroup, TextView,
},
};
fn main() {
let mut siv = cursive::default();
siv.add_global_callback('q', Cursive::quit);
siv.add_global_callback('Q', Cursive::quit);
siv.add_global_callback(Key::Esc, Cursive::quit);
let mut layout = LinearLayout::vertical();
layout.add_child(TextView::new("Flavors:"));
let mut group = RadioGroup::<usize>::new();
let mut sublayout = LinearLayout::vertical();
for (i, opt) in [
"Vanilla",
"Chocolate",
"Strawberry",
"Cinnamon",
"Butterscotch",
"Peanut Butter Fudge",
"Chili",
]
.into_iter()
.enumerate()
{
let mut button = group.button(i, opt);
if i == 0 {
let _ = button.select();
}
sublayout.add_child(button);
}
layout.add_child(PaddedView::lrtb(4, 0, 0, 0, sublayout).with_name("top_pad"));
layout.add_child(DummyView);
layout.add_child(TextView::new("Toppings:"));
let mut sublayout = LinearLayout::vertical();
for opt in ["Whipped Cream", "Hot Fudge", "Nuts", "Cherry", "Banana"] {
let chkbox = Checkbox::new();
let lbl = TextView::new(opt);
sublayout.add_child(
LinearLayout::horizontal()
.child(chkbox)
.child(DummyView)
.child(lbl),
);
}
layout.add_child(PaddedView::lrtb(4, 0, 0, 0, sublayout));
siv.add_layer(
OnEventView::new(Dialog::around(layout).button("OK", Cursive::quit))
.on_pre_event_inner(Key::Home, |dialog, _| {
dialog.set_focus(DialogFocus::Content);
dialog.call_on_name("top_pad", |b: &mut PaddedView<LinearLayout>| {
b.take_focus(Direction::up())
});
Some(EventResult::Consumed(None))
})
.on_pre_event_inner(Key::End, |dialog, _| {
dialog.set_focus(DialogFocus::Button(0));
Some(EventResult::Consumed(None))
}),
);
siv.run();
}Dependencies: cursive = "0.21.1" |
Replies: 1 comment 1 reply
|
Hi, and thanks for the report! Currently focus in cursive is not global, but decided per parent view. Each parent in your chain (dialog, layout, sublayout, sublayout's horizontal layout children) keeps its own focus state. So the manual way to ensure some view ends up "focused" is to make each parent in the chain focus the correct child down the chain.
Here's what happens in your "Home" event handler:
Note that All that gets more complex with more nested views, and even more if you want to focus a specific view in the middle, not just the top one. That's why there's also ... Well that's the theory. In practice I just saw that dialog was not properly focusing the content if you use it, so it would have left the focus on the button for example. I just pushed a commit to fix that, tell me if it works for you! |
Hi, and thanks for the report!
Currently focus in cursive is not global, but decided per parent view. Each parent in your chain (dialog, layout, sublayout, sublayout's horizontal layout children) keeps its own focus state. So the manual way to ensure some view ends up "focused" is to make each parent in the chain focus the correct child down the chain.
take_focusis to tell a view that it just received focus, and that it should possibly update its own internal focus (in case it's a parent).Here's what happens in your "Home" event handler:
dialog.set_focus(DialogFocus::Content): update the dialog's own focus to the content.b.take_focus(Direction::up()): update the top sublayout's to beh…