fractal/components/loading/
bin.rs1use adw::prelude::*;
2use gtk::{glib, subclass::prelude::*};
3
4use crate::utils::ChildPropertyExt;
5
6mod imp {
7 use std::marker::PhantomData;
8
9 use glib::subclass::InitializingObject;
10
11 use super::*;
12
13 #[derive(Debug, Default, gtk::CompositeTemplate, glib::Properties)]
14 #[template(resource = "/org/gnome/Fractal/ui/components/loading/bin.ui")]
15 #[properties(wrapper_type = super::LoadingBin)]
16 pub struct LoadingBin {
17 #[template_child]
18 stack: TemplateChild<gtk::Stack>,
19 #[template_child]
20 child_bin: TemplateChild<adw::Bin>,
21 #[property(get = Self::child, set = Self::set_child, explicit_notify, nullable)]
23 child: PhantomData<Option<gtk::Widget>>,
24 #[property(get = Self::is_loading, set = Self::set_is_loading, explicit_notify)]
26 is_loading: PhantomData<bool>,
27 #[property(get = Self::vhomogeneous, set = Self::set_vhomogeneous)]
30 vhomogeneous: PhantomData<bool>,
31 }
32
33 #[glib::object_subclass]
34 impl ObjectSubclass for LoadingBin {
35 const NAME: &'static str = "LoadingBin";
36 type Type = super::LoadingBin;
37 type ParentType = gtk::Widget;
38
39 fn class_init(klass: &mut Self::Class) {
40 Self::bind_template(klass);
41
42 klass.set_layout_manager_type::<gtk::BinLayout>();
43 klass.set_css_name("loading-bin");
44 }
45
46 fn instance_init(obj: &InitializingObject<Self>) {
47 obj.init_template();
48 }
49 }
50
51 #[glib::derived_properties]
52 impl ObjectImpl for LoadingBin {
53 fn dispose(&self) {
54 self.stack.unparent();
55 }
56 }
57
58 impl WidgetImpl for LoadingBin {}
59
60 impl LoadingBin {
61 fn is_loading(&self) -> bool {
63 self.stack.visible_child_name().as_deref() == Some("loading")
64 }
65
66 fn set_is_loading(&self, loading: bool) {
68 if self.is_loading() == loading {
69 return;
70 }
71
72 let child_name = if loading { "loading" } else { "child" };
73 self.stack.set_visible_child_name(child_name);
74 self.obj().notify_is_loading();
75 }
76
77 fn vhomogeneous(&self) -> bool {
80 self.stack.is_vhomogeneous()
81 }
82
83 fn set_vhomogeneous(&self, homogeneous: bool) {
86 self.stack.set_vhomogeneous(homogeneous);
87 }
88
89 fn child(&self) -> Option<gtk::Widget> {
91 self.child_bin.child()
92 }
93
94 fn set_child(&self, child: Option<>k::Widget>) {
96 if self.child().as_ref() == child {
97 return;
98 }
99
100 self.child_bin.set_child(child);
101 self.obj().notify_child();
102 }
103 }
104}
105
106glib::wrapper! {
107 pub struct LoadingBin(ObjectSubclass<imp::LoadingBin>)
109 @extends gtk::Widget,
110 @implements gtk::Accessible, gtk::Buildable, gtk::ConstraintTarget;
111}
112
113impl LoadingBin {
114 pub fn new() -> Self {
115 glib::Object::new()
116 }
117}
118
119impl Default for LoadingBin {
120 fn default() -> Self {
121 Self::new()
122 }
123}
124
125impl ChildPropertyExt for LoadingBin {
126 fn child_property(&self) -> Option<gtk::Widget> {
127 self.child()
128 }
129
130 fn set_child_property(&self, child: Option<&impl IsA<gtk::Widget>>) {
131 self.set_child(child.map(Cast::upcast_ref));
132 }
133}