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.56k stars 604 forks source link

Preview doesn't work for @image-url in the getting started "memory" game example #4045

Closed vikky999 closed 11 months ago

vikky999 commented 11 months ago

The documentation says: "When using the slint! macro, the path is relative to the folder in which the Cargo.toml is located. When using .slint files, it's relative to the folder of the .slint file containing it. "

This is from this URL https://slint.dev/releases/1.3.1/docs/tutorial/rust/memory_tile

The sample code looks like this

fn main() {
    MainWindow::new().unwrap().run().unwrap();
}

slint::slint! {
component MemoryTile inherits Rectangle {
    width: 64px;
    height: 64px;
    background: #3960D5;

    Image {
        source: @image-url("icons/bus.png");
        width: parent.width;
        height: parent.height;
    }
}

export component MainWindow inherits Window {
    MemoryTile {}
}
}

As per the documentation, since we are using the slint! macro, the icons should be in the folder memory/icons/

And that works as expected

However, if you don't cargo run, but instead try to live preview. It throws this error: Please open an issue on https://github.com/slint-ui/slint/issues Error loading image from /Users/vivek/work/rust/memory/src/icons/bus.png: No such file or directory (os error 2)

Why is it looking in the src directory ?

Shouldn't the live preview use the same relative path as running the code directly with cargo run, this is inconsistent and confusing.

tronical commented 11 months ago

Why is it looking in the src directory ?

I think that's because the preview looks for it relative to the source file (say your main.rs), while when using cargo run we resolve relative to the cargo manifest location (as we don't know in which file the macro is used).

I see two angles:

  1. Perhaps for the live-preview we should go upwards in the directory hierarchy and look for Cargo.toml when we end up using extract_rust_macro. That way the preview would be aligned.
  2. For the behavior of the macro to use the cargo manifest directory, I wonder if it would be possible to make slint::slint! be a wrapper that uses file! and then invokes a slint::real_slint! macro. Or will that always report the location of the slint! macro, instead of the use-site?

cc @ogoffart

ogoffart commented 11 months ago

We already have logic to take care of this in https://github.com/slint-ui/slint/blob/768084b68e18c8d5320eb78b756e33a1f8e136ad/internal/compiler/typeloader.rs#L705 (that's the solution 1) And it works for me. (Linux)

For the behavior of the macro to use the cargo manifest directory, I wonder if it would be possible to make slint::slint! be a wrapper that uses file!

No, the macro would just see the file! token that's not usefull. I'm afraid there is no way to find out what's the file name.

ogoffart commented 11 months ago

Correction: it doesn't work for me, i was testing it wrong.
So I can reproduce the problem.

The base_directory function doesn't work properly. I think it regressed in 0ff8e2cdb6e3054eedb694ce61f4ef12d51a1882 since the code was using parent() before, and now it uses dirname that always ends with a / I think dirname should strip the /. @hunger , what do you think? Or we go back to parent() as before, i thought the code looked simpler

ogoffart commented 11 months ago

Proposed fix in https://github.com/slint-ui/slint/pull/4057