Iced: Layers

Created on 23 Oct 2019  路  5Comments  路  Source: hecrj/iced

Currently, Iced assumes widgets cannot be laid out on top of each other. We should implement support for multiple layers of widgets.

This is a necessary feature to implement many kind of interactables, like dropdown menus, select fields, etc.

iced_native will need to group widgets to perform layouting and process some events first for widgets positioned on top.

iced_wgpu will also need to process the scene graph and sort draw calls based on the different layers.

feature help wanted

Most helpful comment

I would like to add my 2 cents. In other GUI libraries like GTK under X11, such overlays are actually separate windows, and can therefore extend outside the actual application window.

In my opinion, this is very useful for dropdowns and menus. I collected a couple of screenshots to illustrate my point.

Selectbox
image

Menu
image

In such cases or in cases of very small windows, it looks like it would be desirable to have a similar effect in Iced, too. I'm absolutely not sure how difficult something like that is to achieve...

All 5 comments

How would the depth of the widgets be determined? Maybe with something like this?

enum Depth {
    Above,
    Below,
    Topmost,
}

fn view(&mut self) -> Element<Message> {
    // ...
    Layer(SomeWidget::new(), Depth::Above)
    // ...
}

Then the current depth would have to be kept in the layouting state. Given a combobox for example, would it be best for the choice list to be part of the drawing code and the widget set to be on top (and ComboBox::new actually returns Layer(ComboBox {...}, Depth::Above) or the choice list be a separate widget, attached to the ComboBox's layout? Or maybe there's a better approach?

I do not have a particular approach in mind yet. There is definitely an interesting amount of exploration ahead of us here.

I do know using something like absolute indices (like z-index in CSS) can be quite painful and does not compose _at all_.

A relative Layer widget sounds like a good idea to me, as I think it should compose no matter where you decide to nest it. elm-ui follows a similar approach and the author gave a great talk in elm-conf with many interesting ideas. I recommend watching it for inspiration!

Given a combobox for example, would it be best for the choice list to be part of the drawing code and the widget set to be on top (and ComboBox::new actually returns Layer(ComboBox {...}, Depth::Above) or the choice list be a separate widget, attached to the ComboBox's layout? Or maybe there's a better approach?

I think layers (or at least _event_ layers) will need to exist as a first-class concept in iced_native. As of now, they cannot simply be another widget because the runtime needs to be aware of them. In other words, update needs to be aware that layers on top, although potentially nested deeply in the widget tree, should capture mouse events.

I am not yet sure about how we will end up implementing this. I do have the feeling that the different methods in the Widget trait are inherently coupled (node defines layout, which in turn affects on_event, draw, and hash_layout). Layers will make this coupling even more apparent.

I think the problem is telling us something here: we should define layout, update, and draw in a unified, declarative way. The runtime will then figure out how to process events and draw widgets. How could this API look like? I am not sure yet! :sweat_smile: This is where we should explore! I think the way iced_web works makes everything very composable and easy to extend.

I would like to add my 2 cents. In other GUI libraries like GTK under X11, such overlays are actually separate windows, and can therefore extend outside the actual application window.

In my opinion, this is very useful for dropdowns and menus. I collected a couple of screenshots to illustrate my point.

Selectbox
image

Menu
image

In such cases or in cases of very small windows, it looks like it would be desirable to have a similar effect in Iced, too. I'm absolutely not sure how difficult something like that is to achieve...

Isn't it better to achieve single instance window widget support @hecrj ?
After we can improve it to have such functionality like gimp has.
If such, in our app windows are crucial and we really want to use iced, so we can definetely contribute, but can you guide and write your general ideas about layers first naive implementaion, so I can submit draft for pull request?

Separate windows would be the ideal way to go, but aren't really supported by winit yet (https://github.com/rust-windowing/winit/issues/403), and even if it were I don't know if it would be portable to all platforms (e.g. Android).

FYI, for KAS I solved the event handling via specific support for "pop-ups" (still a bit hacky, but required to support closing menus when clicking under them and things like accelerator key bindings on the menus). For drawing it uses the depth buffer with some specific offsets (not the only option, but otherwise you'd need indirect drawing for each layer I believe).

Was this page helpful?
0 / 5 - 0 ratings

Related issues

cetra3 picture cetra3  路  3Comments

olanod picture olanod  路  4Comments

aentity picture aentity  路  3Comments

porglezomp picture porglezomp  路  3Comments

sumibi-yakitori picture sumibi-yakitori  路  3Comments