Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[BUG] adding content causes views to be pushed off screen. #613

Open
TwoClocks opened this issue Nov 6, 2021 · 2 comments · May be fixed by #614
Open

[BUG] adding content causes views to be pushed off screen. #613

TwoClocks opened this issue Nov 6, 2021 · 2 comments · May be fixed by #614
Labels

Comments

@TwoClocks
Copy link

The following code walks the bottom panel off the bottom of the screen.

While I suppose its height is still the required height, but it's off the screen, so who knows.

I think this is a bug?

If it's not, how do I keep both panels on the screen?

Great crate BTW. It's been fun to use.

fn main() {
    let mut ui = CursiveRunnable::default();
    let mut ui = ui.runner();

    let mut bottom_content = String::with_capacity(1023);
    for n in (1..11).rev() {
        bottom_content.push_str(&format!("{} Line num\n", n));
    }

    ui.add_layer(
        LinearLayout::vertical()
            .child(ResizedView::with_min_height(
                10,
                Panel::new(TextView::new("top content\n").with_name("top")).title("Top Panel"),
            ))
            .child(ResizedView::with_min_height(
                10,
                Panel::new(TextView::new(bottom_content).with_name("bottom")).title("Bottom Panel"),
            )),
    );

    ui.add_global_callback('q', |s| s.quit());

    ui.refresh();
    ui.step();

    while ui.is_running() {
        std::thread::sleep(std::time::Duration::from_millis(500));

        ui.call_on_name("top", |view: &mut TextView| {
            view.append(format!("now is {:?}\n", std::time::Instant::now()))
        });

        ui.refresh();
        ui.step();
    }
}
@gyscos
Copy link
Owner

gyscos commented Jan 3, 2022

Hi, and thanks for the report!

Yeah LinearLayout doesn't always behave nicely when things really don't want to fit in the constrained space.

If the views really don't want to fit, LinearLayout has to break a few things here. It may not make the optimal choice, but it's possible to guide the layout so that it handles this "degenerate" case better.

For example it may help to "force" one of the views to shrink as needed so the full view never exceeds the window size.
One way to do that is to make a view scrollable: the content can grow arbitrarily, but the view itself will be able to fit within the given space.

The default behaviour would be to start showing a scrollbar whenever the content exceeds the available space, and then to keep showing the top of the content.

You can change these things as needed, for example if you don't want a scrollbar and want to stick to the bottom:

ui.add_layer( 
    LinearLayout::vertical() 
        .child(ResizedView::with_min_height( 
            10, 
            Panel::new( 
                TextView::new("top content\n") 
                    .with_name("top") 
                    .scrollable() 
                    .show_scrollbars(false) 
                    .scroll_strategy(cursive::view::scroll::ScrollStrategy::StickToBottom),
            ) 
            .title("Top Panel"), 
        )) 
        .child(ResizedView::with_min_height( 
            10, 
            Panel::new(TextView::new(bottom_content).with_name("bottom")) 
                .title("Bottom Panel"), 
        )), 
); 

This is one of many ways to handle the layout when the size exceeds the available space. You could also have the entire layer scroll rather than just the top panel, or write a custom view to handle any other behaviour (like changing layout depending on the available size, for example to move to a side panel when the height is too low). But when it's likely to happen, it's best to explicitly handle these cases of constrained space, rather than letting LinearLayout handle it.

@TwoClocks
Copy link
Author

Yep. Adding a scrollbar fixes the issue.

I'm not sure what you want to do w/ my layout logic PR, which also fixes the issue w/o needing to add a scroll bar. I'm obviously biased, but I think it's a better general solution. Also easy to add weights too (I think). Let me know if you have any interest... I'd be happy to work on it w/ you. If not, also happy to delete the PR.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants