xilem icon indicating copy to clipboard operation
xilem copied to clipboard

Experimental composable widgets for styling

Open DJMcNab opened this issue 3 years ago • 2 comments

Inspired by https://tonsky.me/blog/clojure-ui/#tweak-and-reuse and Tailwind CSS, this demonstrates how our current widget model lends itself to view level styling.

For reference, the user-facing part of this is:

fn app_logic(data: &mut f64) -> impl View<f64> {
    background(
        Color::RED,
        padding(
            *data,
            button(format!("Padding {data}px"), |data| *data += 1.),
        ),
    )
}

Which creates the following application.

Initial state: image

After 37 clicks: image

Beautiful, I know.

DJMcNab avatar Nov 29 '22 12:11 DJMcNab

If I am not mistaken, using piets clipping abilities, it would be possible to adopt a "BorderView" as well, rounding the borders of an element, right?

I'm just curious what this system is capable of doing :)

nilsmartel avatar Dec 03 '22 11:12 nilsmartel

Borders is an open question for me

From a conceptual viewpoint it's easy; just draw a line along the parent clipping path, or a rectangle if the parent isn't a clip.

In terms of actual implementation, I'm less sure how that fits into our painting model at the moment.

DJMcNab avatar Dec 03 '22 11:12 DJMcNab

Hi, I'm currently looking at Xilem because I am fascinated by the project. I found this pull request and decided to experiment with it, so I made the padding view have individual sizes for all 4 sides: image image

(not sure if you want me to add that in, just thought it would be cool to show ^^) Since we're talking about how we could implement a BorderView, @DJMcNab what makes you unsure about how it fits into the painting model? I know the project relies on piet-gpu for drawing but I'm not too familiar with its current state, or even with its API at the moment...

Speykious avatar Dec 11 '22 11:12 Speykious

I played around with this a little, and ended up implementing a border widget too. I also found that for simple wrapper widgets like these there isn't really a need for a Pod - especially for the background widget, all its implementation needs to do is paint a rectangle before forwarding all of the calls to the inner widget. I'm interested whether people think this Pod-free way of creating wrapper widgets is a good idea, since it probably eliminates a little runtime checking and allocating?

My code is here.

rosefromthedead avatar Jan 30 '23 20:01 rosefromthedead

I wanted to avoid the Pod, but I found issues with widgets inspecting PaintCx::size, for example. It seemed to me that the traits are designed such that Widgets were intended to only exist with Pods.

PaintCx is not externally constructible, so "spoofing" that isn't intended. And button reads cx.size() to get the area to draw.

That is to say, I would like to avoid the Pod. But working within the constraint of changing nothing else, it doesn't work.

DJMcNab avatar Jan 30 '23 21:01 DJMcNab

Oh yeah, size is the one thing I hadn't figured out yet, and I assumed it would be fairly straightforward like the mouse events were... oops. For background at least, it feels like that can still be kept podless.

About the border thing, I think I accidentally avoided the problem you mentioned (how to know the parent clipping path) by just making the clip and the border be part of the same widget.. maybe that's the easy way out. I can't think of a reason why a user might need them to be different widgets, and worst case the path could just be specified twice.

rosefromthedead avatar Jan 30 '23 21:01 rosefromthedead

Yeah, joining clip and border seems reasonable. One could imagine wanting to have different kinds of border (e.g. an image based border), but that could probably be its own copy-pasted widget.

DJMcNab avatar Jan 30 '23 21:01 DJMcNab

So, the Xilem Vector Graphics talk has clarified this for me slightly.

Broadly, I still think the styled views are compelling, but the implementation methods using a unique widget for each is not needed

DJMcNab avatar Jun 13 '23 15:06 DJMcNab