linebender / druid

A data-first Rust-native UI design toolkit.
https://linebender.org/druid/
Apache License 2.0
9.56k stars 569 forks source link

Labels drawn inside a Split widget overflow their containers #442

Open s3thi opened 4 years ago

s3thi commented 4 years ago

I have some code that creates a split layout:

fn ui_builder() -> impl Widget<i32> {
    Split::horizontal(
        Flex::column().with_child(Label::new("Sidebar goes here").center(), 1.),
        Flex::column().with_child(Label::new("Task goes here").center(), 1.),
    )
    .draggable(true)
}

If I drag the split handle so that the left side of the Split is smaller than the width of the Label it contains, the label text overflows its container and into the right side of the split. This is what it looks like:

Screen Shot 2020-01-02 at 5 53 57 PM

I can reproduce the same issue by manually setting the size of the Split:

fn ui_builder() -> impl Widget<i32> {
    Split::horizontal(
        Flex::column().with_child(Label::new("Sidebar goes here").center(), 1.),
        Flex::column().with_child(Label::new("Task goes here").center(), 1.),
    )
    .draggable(true)
    .split_point(0.2)
}

If I use a Button instead of a Label as a child, the button resizes itself to fit inside the Split as expect. But the text inside the button overflows the Split container as well as the button. Here's the code to reproduce the issue:

fn ui_builder() -> impl Widget<i32> {
    Split::horizontal(
        Flex::column().with_child(Button::new("Button goes here", Button::noop).center(), 1.),
        Flex::column().with_child(Label::new("Task goes here").center(), 1.),
    )
    .draggable(true)
    .split_point(0.2)
}

Here's is what it produces:

Screen Shot 2020-01-02 at 6 00 57 PM

The issue occurs on the current master branch. I haven't had a chance to test it on 0.4.

Zarenor commented 4 years ago

Thanks for writing this up!

Currently, this is a known issue. No container clips it's children, and the label widget does not have any mechanism by which to respect bounds.

Some of this may be fixed in (#428) depending on how multiline labels are implemented.

We've proposed a couple of solutions. I had suggested a Clip widget, similar to flutter, which fills an container and clips the contents. Raph has proposed a different solution, involving setting a property on the LayoutCtx in #401.

One more thing to consider: Currently, I don't think we allow for bounding window sizes, and I know we don't have a way of specifying bounds (minimum or maximum split points) for the split widget. If you have the time to implement any of those, we would welcome the contribution.

I think for the split widget bounds, at least, I can offer some guidance (in a separate issue or PR review). Window bounding is likely to require some work in druid-shell and need separate implementations per-OS. It's going to be a much more complicated topic to approach, I think.

EDIT: Corrected some errors, better reflected state of paint-in-bounds/clipping

s3thi commented 4 years ago

Thanks for the detailed explanation! Like a lot of the stuff I've previously reported, looks like this is on the radar and on its way to being fixed in v0.5. That's good to know.

When you talk about setting bounds on Split, do you mean setting maximum/minimum sizes for the two panes it creates? I might spend some time with Split next week, so I'll attempt to add this feature. I'll start a new issue when I do that.

Zarenor commented 4 years ago

That's exactly what I mean. There's some interesting questions to resolve there, mostly to do with failure cases when it's not possible to maintain the required minimum widths because the Split is given too little space. This only manifests if you implement min and max in a pixel-width based way, rather than a in-range-[0,1] way. Both are options we'd like to have, but you can implement either or both.