bodil / vgtk

A declarative desktop UI framework for Rust built on GTK and Gtk-rs
http://bodil.lol/vgtk/
Other
1.05k stars 37 forks source link

Image created with `Image::from_icon_name` does not update properly #77

Open nt8r opened 3 years ago

nt8r commented 3 years ago

In the following example, clicking the button toggles the boolean in the model, and all widgets except the image created via Image::from_icon_name update as expected.

Changing the default value of the boolean changes which value the image starts with, but that widget never updates for some reason.

This example also demonstrates a workaround: use property_icon_name and property_icon_size instead, and everything works as expected.

Cargo.toml:

[package]
name = "vgtk-image-bug"
version = "0.1.0"
authors = ["anteater"]
edition = "2018"

[dependencies]
vgtk = "*"
pretty_env_logger = "0.4"
futures = "0.3"

main.rs:

#![recursion_limit="256"]

use vgtk::ext::*;
use vgtk::lib::gio::{self, ApplicationFlags};
use vgtk::lib::gtk::{*, Box as GtkBox};
use vgtk::{gtk, Component, UpdateAction, VNode};

use std::default::Default;

#[derive(Clone)]
struct Model {
    value: bool,
}

impl Default for Model {
    fn default() -> Self {
        Model {
            value: false,
        }
    }
}

#[derive(Clone, Debug)]
enum UiMessage {
    Toggle,
}

impl Component for Model {
    type Message = UiMessage;
    type Properties = ();

    fn update(&mut self, _msg: Self::Message) -> UpdateAction<Self> {
        self.value = !self.value;
        UpdateAction::Render
    }

    fn view(&self) -> VNode<Model> {
        let v = self.value;
        gtk! {
            <Application::new_unwrap(Some("org.vgtk.image_bug"), ApplicationFlags::empty())>
                <ApplicationWindow default_width=180 default_height=100 border_width=5>
                    <GtkBox::new(Orientation::Horizontal, 3)>
                        <Image::from_icon_name(Some(if v { "mail-unread" } else { "mail-read" }), if v {IconSize::Menu} else {IconSize::Dialog}) />
                        <Label text=v.to_string() />
                        <Button on clicked=|_| { UiMessage::Toggle } label={if v {"true".to_owned()} else {"false".to_owned()}} />
                        <Image property_icon_name=(if v { "mail-unread".to_owned() } else { "mail-read".to_owned() }) />
                    </GtkBox>
                </ApplicationWindow>
            </Application>
        }
    }
}

fn main() {
    use gio::prelude::ApplicationExtManual;
    let (app, _scope) = vgtk::start::<Model>();
    std::process::exit(app.run(&[]));
}