Different Data Types in Different on_click events in druid-rs

34 Views Asked by At

I am trying to build a simple placeholder GUI for an signal processing project in rust, with the Druid library. I've been looking at different examples from the github page to understand how it works and apply it to my code, and even though it is very barebone, it's working for the most part. However I am struggling with an error that I really dont understand how to fix and that I haven't been able to find a solution for online.

I have a view switcher, and in my view 3 I want the Play Audio button to call the play_audio button to play some audio (which should be the audio the user has selected in the filedialogoption as a placeholder behavior).

Here's my code (I know my code is probably not clean at all but this is my first project with rust and I've just begun learning the language) :

use druid::widget::{Button, Flex, ViewSwitcher, Label, CrossAxisAlignment, MainAxisAlignment};
use druid::{
    commands, AppDelegate, AppLauncher, Command, DelegateCtx, Env, FileDialogOptions, FileSpec,
    Handled, LocalizedString, Target, Widget, WindowDesc, Data, Lens, WidgetExt
};

use std::io::BufReader;

struct Delegate;

#[derive(Clone, Data, Lens)]
struct AppState {
    current_view: u32,
    current_text: String,
}


pub fn launch() {
    let main_window = WindowDesc::new(ui_builder())
        .title(LocalizedString::new("gui").with_placeholder("GUI"));
    let mut data = AppState {
        current_view: 0,
        current_text: "".to_string(),
    };
    AppLauncher::with_window(main_window)
        .delegate(Delegate)
        .log_to_console()
        .launch(data)
        .expect("launch failed");
}


fn ui_builder() -> impl Widget<AppState> {
 
    let view_switcher = ViewSwitcher::new(
        |data: &AppState, _env| data.current_view,
        |selector, _data, _env| match selector {
            0 => Box::new(
                Flex::column()
                    .with_flex_child(Label::new("Please select an audio file").center(), 1.0)
                    .with_flex_child(Button::new("Import File").on_click(move |ctx, data: &mut u32, _| {
                let audio = FileSpec::new("Audio files", &["mp3","wav"]);
                let open_dialog_options = FileDialogOptions::new()
                    .allowed_types(vec![audio])
                    .name_label("Source")
                    .title("Choose the source audio file")
                    .button_text("Import")
                    ;
                ctx.submit_command(druid::commands::SHOW_OPEN_PANEL.with(open_dialog_options.clone()));
                //*data=1;
            })
            .center(),
            1.0)
            .lens(AppState::current_view)
            ),
            1=>Box::new(
                Flex::column()
                .with_flex_child(Label::new("What would you like to do").center(), 1.0)
                .with_flex_child(Flex::row()
                                        .with_flex_child(Button::new("Pitch Track").center().on_click(|_ctx, data: &mut u32, _| {*data=2;}), 1.0)
                                        .with_flex_child(Button::new("Pitch Shift").center().on_click(|_ctx, data: &mut u32, _| {*data=3;}), 1.0), 1.0)
                .lens(AppState::current_view)
            ),
            2=>Box::new(
                Flex::column()
                .with_flex_child(Label::new("Pitch Tracking").center(), 1.0)
                .with_flex_child(Button::new("Restart").center().on_click(|_ctx, data: &mut u32, _| {*data=0;}), 1.0)
                .lens(AppState::current_view)
            ),

            3=>Box::new(
                Flex::column()
                .with_flex_child(Label::new("What would you like to do").center(), 1.0)
                                        .with_flex_child(Button::new("Restart").center().on_click(|_ctx, data: &mut u32, _| {
                                            *data=0;}), 1.0)
                                        .with_flex_child(Button::new("Play Audio").center().on_click(|_ctx, data:  &mut AppState, _| {
                                                let current_text = data.current_text.clone();
                                                play_audio((data.current_text).to_string());
                                            }), 1.0)
                .lens(AppState::current_view)
            ),
            _ => Box::new(Label::new("Unknown").center()),
        });


    Flex::row()
        .main_axis_alignment(MainAxisAlignment::Center)
        .cross_axis_alignment(CrossAxisAlignment::Center)
        .with_flex_child(view_switcher, 1.0)
        
}


fn play_audio(output_path : String){
    let (_stream, handle) = rodio::OutputStream::try_default().unwrap();
    let sink = rodio::Sink::try_new(&handle).unwrap();
    let file = std::fs::File::open(output_path).unwrap();
    sink.append(rodio::Decoder::new(BufReader::new(file)).unwrap());
    sink.sleep_until_end();
}




impl AppDelegate<AppState> for Delegate {
    fn command(
        &mut self,
        _ctx: &mut DelegateCtx,
        _target: Target,
        cmd: &Command,
        data: &mut AppState,
        _env: &Env,
    ) -> Handled {
        if let Some(file_info) = cmd.get(commands::OPEN_FILE) {
            data.current_text = file_info.path().to_string_lossy().to_string();
            data.current_view = 1;
            return Handled::Yes;
        }
        Handled::No
    }
}

When I try to compile this I get the following Error :


error[E0277]: the trait bound `Align<AppState>: druid::Widget<u32>` is not satisfied
   --> src\GUI\gui.rs:104:58
    |
104 |                                           .with_flex_child(Button::new("Play Audio").center().on_click(|_ctx, ...
    |  __________________________________________---------------_^
    | |                                          |
    | |                                          required by a bound introduced by this call
105 | |                                                 let current_text = data.current_text.clone();
106 | |                                                 play_audio((data.current_text).to_string());}), 1.0)
    | |______________________________________________________________________________________________^ the trait `druid::Widget<u32>` is not implemented for `Align<AppState>`
    |
    = help: the trait `druid::Widget<AppState>` is implemented for `Align<AppState>`
    = help: for that trait implementation, expected `AppState`, found `u32`
    = note: required for `ControllerHost<Align<AppState>, Click<AppState>>` to implement `druid::Widget<u32>`
note: required by a bound in `Flex::<T>::with_flex_child`
   --> C:\Users\ymri.000\.cargo\git\checkouts\druid-f71533f3d81c0bc8\e53a5ab\druid\src\widget\flex.rs:468:21
    |
466 |     pub fn with_flex_child(
    |            --------------- required by a bound in this associated function
467 |         mut self,
468 |         child: impl Widget<T> + 'static,
    |                     ^^^^^^^^^ required by this bound in `Flex::<T>::with_flex_child`

error[E0277]: the trait bound `Click<AppState>: Controller<u32, Align<AppState>>` is not satisfied
   --> src\GUI\gui.rs:104:58
    |
104 |                                           .with_flex_child(Button::new("Play Audio").center().on_click(|_ctx, ...
    |  __________________________________________---------------_^
    | |                                          |
    | |                                          required by a bound introduced by this call
105 | |                                                 let current_text = data.current_text.clone();
106 | |                                                 play_audio((data.current_text).to_string());}), 1.0)
    | |______________________________________________________________________________________________^ the trait `Controller<u32, Align<AppState>>` is not implemented for `Click<AppState>`
    |
    = help: the trait `Controller<AppState, Align<AppState>>` is implemented for `Click<AppState>`
    = help: for that trait implementation, expected `AppState`, found `u32`
    = note: required for `ControllerHost<Align<AppState>, Click<AppState>>` to implement `druid::Widget<u32>`
note: required by a bound in `Flex::<T>::with_flex_child`
   --> C:\Users\ymri.000\.cargo\git\checkouts\druid-f71533f3d81c0bc8\e53a5ab\druid\src\widget\flex.rs:468:21
    |
466 |     pub fn with_flex_child(
    |            --------------- required by a bound in this associated function
467 |         mut self,
468 |         child: impl Widget<T> + 'static,
    |                     ^^^^^^^^^ required by this bound in `Flex::<T>::with_flex_child`

For more information about this error, try `rustc --explain E0277`.
error: could not compile `gui` (bin "gui") due to 2 previous errorserror[E0277]: the trait bound `Align<AppState>: druid::Widget<u32>` is not satisfied
   --> src\GUI\gui.rs:104:58
    |
104 |                                           .with_flex_child(Button::new("Play Audio").center().on_click(|_ctx, ...
    |  __________________________________________---------------_^
    | |                                          |
    | |                                          required by a bound introduced by this call
105 | |                                                 let current_text = data.current_text.clone();
106 | |                                                 play_audio((data.current_text).to_string());}), 1.0)
    | |______________________________________________________________________________________________^ the trait `druid::Widget<u32>` is not implemented for `Align<AppState>`
    |
    = help: the trait `druid::Widget<AppState>` is implemented for `Align<AppState>`
    = help: for that trait implementation, expected `AppState`, found `u32`
    = note: required for `ControllerHost<Align<AppState>, Click<AppState>>` to implement `druid::Widget<u32>`
note: required by a bound in `Flex::<T>::with_flex_child`
   --> C:\Users\ymri.000\.cargo\git\checkouts\druid-f71533f3d81c0bc8\e53a5ab\druid\src\widget\flex.rs:468:21
    |
466 |     pub fn with_flex_child(
    |            --------------- required by a bound in this associated function
467 |         mut self,
468 |         child: impl Widget<T> + 'static,
    |                     ^^^^^^^^^ required by this bound in `Flex::<T>::with_flex_child`

error[E0277]: the trait bound `Click<AppState>: Controller<u32, Align<AppState>>` is not satisfied
   --> src\GUI\gui.rs:104:58
    |
104 |                                           .with_flex_child(Button::new("Play Audio").center().on_click(|_ctx, ...
    |  __________________________________________---------------_^
    | |                                          |
    | |                                          required by a bound introduced by this call
105 | |                                                 let current_text = data.current_text.clone();
106 | |                                                 play_audio((data.current_text).to_string());}), 1.0)
    | |______________________________________________________________________________________________^ the trait `Controller<u32, Align<AppState>>` is not implemented for `Click<AppState>`
    |
    = help: the trait `Controller<AppState, Align<AppState>>` is implemented for `Click<AppState>`
    = help: for that trait implementation, expected `AppState`, found `u32`
    = note: required for `ControllerHost<Align<AppState>, Click<AppState>>` to implement `druid::Widget<u32>`
note: required by a bound in `Flex::<T>::with_flex_child`
   --> C:\Users\ymri.000\.cargo\git\checkouts\druid-f71533f3d81c0bc8\e53a5ab\druid\src\widget\flex.rs:468:21
    |
466 |     pub fn with_flex_child(
    |            --------------- required by a bound in this associated function
467 |         mut self,
468 |         child: impl Widget<T> + 'static,
    |                     ^^^^^^^^^ required by this bound in `Flex::<T>::with_flex_child`

For more information about this error, try `rustc --explain E0277`.
error: could not compile `gui` (bin "gui") due to 2 previous errors

I've tried a ton of different workarounds but nothing has worked for me yet, and I can't seem to find any solution or anyone having this problem online.

If anyone had an idea to help me, it would be greatly appreciated ! Thank you for reading.

I tried changing the data type in my on_click event for all the buttons in the selector, however this raised an error with my lens() statements, which also raised errors when removed, I tried different types for the Play Audio button on_click data Type which none of them works (it seems like I have to have them all as &mut u32 ?). I have tried passing the text directly to the play_audio() function without cloning first but it didnt change anything, and some other stuff I don't remember.

0

There are 0 best solutions below