Relm4 icon indicating copy to clipboard operation
Relm4 copied to clipboard

How to avoid Message recursion

Open imsamuka opened this issue 1 year ago • 2 comments

I'm creating a Configuration panel, and I found myself a little stuck when creating a Restore Default button. See the snippet:

gtk::Box {
    set_orientation: gtk::Orientation::Horizontal,

    #[name = "rest_spin_btn"]
    gtk::SpinButton {
        set_tooltip_text: Some("Rest Duration"),
        set_range: (1.0, 180.0),
     /* #[watch] */
        set_value: (model.config.rest_time.as_secs() / 60) as f64,
        set_increments: (1.0, 5.0),

        connect_value_changed[sender] => move |btn| {
            let value = btn.value() as u64;
            sender.input(AppMsg::ChangeConfig(Box::new(move |mut config|
                config.rest_time = Duration::from_secs(value * 60)
            )))
        },
    },

    #[name = "defaults_btn"]
    gtk::Button {
        set_icon_name: ICON_RESTART,
        set_tooltip_text: Some("Restore default configuration"),
        connect_clicked => AppMsg::ChangeConfig(Box::new(|config|
            *config = Config::default()
        )),
    },
}

This will create the rest_spin_btn : SpinButton to edit some configuration and a defaults_btn : Button that restores the configuration default. This will work, but the panel will not reflect the changes after defaults_btn is pressed. The commented out #[watch] is the normally preferred way to reflect changes in the UI, but if it was un-commented, set_value would be called and the connect_value_changed signal would be emitted, causing a loop.

This seems like a fairly common case, what's the best way to circumvent this?

imsamuka avatar Feb 27 '23 01:02 imsamuka