3

I'm struggling with a SpinButton in Rust using Relm. (Disclaimer, I'm a noob with Rust and GTK)

#![feature(proc_macro)]
extern crate gtk;

use chrono::{NaiveTime, Duration};

use gtk::prelude::*;
use gtk::{
    WidgetExt,
    ContainerExt,
    EntryExt,
    Adjustment
};

use relm::Widget;
use relm_attributes::widget;

#[derive(Msg, Debug)]
pub enum Msg {
    Changed,
    Display,
}

#[widget]
impl Widget for DurationSpin {
    fn model(m: Duration) -> Duration {
        m
    }

    fn update(&mut self, event: Msg) {
        match event {
            Msg::Display => self.format_display(),
            Msg::Changed => {
                println!("update, self.spin_btn.get_value_as_int() = {:?}", self.spin_btn.get_value_as_int());
                self.model = Duration::minutes(self.spin_btn.get_value_as_int() as i64)

            },
        };
    }

    fn format_display(&mut self) {
        println!("format_display, self.spin_btn.get_value_as_int() = {:?}", self.spin_btn.get_value_as_int());
        let minus = self.model.num_hours() * 60;
        self.spin_btn.set_text(&format!("{:02}:{:02}",
                                        self.model.num_hours(), self.model.num_minutes() - minus));
    }

    view! {
        #[name="spin_btn"]
        gtk::SpinButton {
            max_width_chars: 5,
            width_chars: 5,
            max_length: 5,
            numeric: false,
            output => (Msg::Display, Inhibit(false)),
            value_changed => Msg::Changed,
            adjustment: &Adjustment::new(self.model.num_minutes() as f64, 0.0, 720.0, 1.0, 60.0, 0.0),
        }
    }
}

(whole project here: https://github.com/Geobert/rusty_flexi)

My issue is that clicking on "+" makes get_value_as_int always returns '1'.

It seems that my output signal is causing this as deactivating the connection solves the bug but I can't see what's wrong with it.

2
  • Try getting the value from the adjustment instead of from the spinbox. I think get_value_as_int() tries to reparse the text in the spinbox, though I'm not sure why that would always give you 1... Commented Jun 7, 2017 at 21:36
  • I tried self.spin_btn.get_adjustment().get_value() with no luck, still returning 1 Commented Jun 8, 2017 at 19:24

1 Answer 1

0

It seems the output signal handler must not be asynchronous. That means you should not use relm message passing in this case.

You should do something like:

fn init_view(&mut self) {
    let hours = self.model.num_hours();
    let minutes = self.model.num_minutes();
    self.spin_btn.connect_output(move |spin_btn| {
        let minus = hours * 60;
        spin_btn.set_text(&format!("{:02}:{:02}",
                                    hours, minutes - minus));
        Inhibit(false)
    });
}

and remove output => (Msg::Display, Inhibit(false)),

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.