Closed MGlolenstine closed 4 years ago
If you want to send a state to another widget, to need to use message passing. Look at this example.
Ok, so I basically have to send something to the fn update
inside the widget? So I could send a callback function using the Msg passing with a function as an argument and then just save it in the widget?
Actually, no. You would need to do something like:
#[derive(Msg)]
pub enum CounterMsg {
Decrement,
Increment,
SendValue(i32),
}
#[widget]
impl Widget for Counter {
fn model(relm: &Relm<Self>, _: ()) -> CounterModel {
CounterModel {
counter: 0,
relm: relm.clone(),
}
}
fn update(&mut self, event: CounterMsg) {
match event {
Decrement => {
self.model.counter -= 1;
self.model.relm.emit(SendValue(self.model.counter));
},
Increment => {
self.model.counter += 1;
self.model.relm.emit(SendValue(self.model.counter));
},
}
}
view! {
gtk::Box {
orientation: Vertical,
gtk::Button {
label: "+",
property_height_request: 100,
clicked => Increment,
},
gtk::Label {
label: "0",
vexpand: true,
text: &self.model.counter.to_string(),
},
gtk::Button {
label: "-",
property_height_request: 100,
clicked => Decrement,
},
}
}
}
and you receive it in the window like this:
#[widget]
impl Widget for Win {
fn model() -> Model {
Model {}
}
fn update(&mut self, event: Msg) {
match event {
Msg::Quit => gtk::main_quit(),
}
}
view! {
gtk::Window {
// …
gtk::Box {
orientation: Vertical,
Counter{
SendValue(value) => println!("value"), // TODO: do something with the value, could send a message to do stuff in the update method.
}
},
delete_event(_, _) => (Msg::Quit, Inhibit(false)),
}
}
}
Oh so a parent propagation with the emit
.
Thanks for your help!
@antoyo I'm having some slight problems with the emit
calls, as it says that Relm<Counter>
, that's the widget one, doesn't implement it.
no method named `emit` found for struct `relm::state::Relm<utils::widgets::counter::Counter>` in the current scope
method not found in `relm::state::Relm<utils::widgets::counter::Counter>`
My CounterModel
looks like this
pub struct CounterModel {
counter: i32,
relm: Relm<Counter>,
}
Sorry, the syntax is:
self.model.relm.stream().emit(Msg);
I forgot the call to stream()
.
It works perfectly now!
Thanks!
Let's say that I have a counter implemented using a "+" and a "-" buttons, with current value written between them. Whenever I press on the "+" button, the value increases and for "-" decreases by 1.
Now, how would I capture that value and send it back to the "main view", if this "counter" is a
Widget
, that's included in the top view?To make it by an example, how would I pass the
cur_number
to theCounter
widget and get it called, every time the number changes?I did try manually implementing the
Counter
struct and giving it an FnMut variable type, but then I also had to initialize a new window, add it as root and then the widget didn't want to work as I wanted it to.Would I be able to add a constructor, that'd take a callback as an argument without having to create a new window and still have it initialized with the
#[widget]
. I think that an example like this is missing and it'd be really nice to have it included in the repository.Widget:
Main view: