slint-ui / slint

Slint is a declarative GUI toolkit to build native user interfaces for Rust, C++, or JavaScript apps.
https://slint.dev
Other
17.71k stars 614 forks source link

PopupWindow: Misleading error trying to access sub-component from another component #4438

Open DoumanAsh opened 10 months ago

DoumanAsh commented 10 months ago

Given following:

export component Main2 inherits Window {
    about_window := PopupWindow {
        width: min(ui.preferred-width, root.width - 80px);
    }

    config_window := PopupWindow {
        x: 100px;
        y: 100px;
        width: min(ui.preferred-width, root.width - 80px);
        close-on-click: false;

        Rectangle {
            border-color: grey;
            border-width: 1px;
            background: grey;
        }

        ui := VerticalBox {
            height: 100%;
            width: 100%;
        }
    }
}

slint-build produces misleading error:

  --- stderr
  error: Cannot access the inside of a PopupWindow from enclosing component
     --> /Users/artur.m/repos/work/evp-vehicle-authentication-service/identity-demo/ui/main.slint:312:22
      |
  312 |     config_window := PopupWindow {
      |                      ^

This error happens because I tried to access ui component, declared in config_window from within about_window

ogoffart commented 10 months ago

Thanks for filling an issue.

This is indeed a bad limitation of the PopupWindow. See the FIXME comment in https://github.com/slint-ui/slint/blob/d67f0de80815b1bf3808a4f142aea84cd196d813/internal/compiler/passes/lower_popups.rs#L106-L110 The problem is that in that part of the code we no longer know what is the span of the reference. (We probably should store it in Expression::PropertyReference and pass it along, there are other error that would benefit from that)

We could try to make it work to access these properties by moving the properties from the popup ItemTree to the parent SubComponent. But that's difficult for the properties in "native" items.

In general, the PopupWindow has many design issue. See the meta issue https://github.com/slint-ui/slint/issues/1143

DoumanAsh commented 10 months ago

Oh I see. I thought it should not be allowed to access another window's properties from withing different window. But I'm not sure what are scoping rules in slint markup language.

Is it expected for all declarations to be global within root component? I would honestly expect it to be restricted to access one sub-component from another one 🤔

tronical commented 10 months ago

Another idea would perhaps be to detect this situation (that properties from a PopupWindow are referenced from the outside) and then compile it in a way that the PopupWindow component is already instantiated. (That means 'init' will be called only once, instead of on every show() though).