Skip to main content

fractal/components/rows/
check_loading_row.rs

1use adw::subclass::prelude::*;
2use gtk::{glib, glib::clone, prelude::*};
3
4use crate::{components::LoadingBin, utils::bool_to_accessible_tristate};
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/rows/check_loading_row.ui")]
15    #[properties(wrapper_type = super::CheckLoadingRow)]
16    pub struct CheckLoadingRow {
17        #[template_child]
18        bin: TemplateChild<LoadingBin>,
19        #[template_child]
20        check: TemplateChild<gtk::CheckButton>,
21        /// The action activated by the button.
22        #[property(get = Self::action_name, set = Self::set_action_name, override_interface = gtk::Actionable)]
23        action_name: PhantomData<Option<glib::GString>>,
24        /// The target value of the action of the button.
25        #[property(get = Self::action_target_value, set = Self::set_action_target, override_interface = gtk::Actionable)]
26        action_target: PhantomData<Option<glib::Variant>>,
27        /// Whether the row is loading.
28        #[property(get = Self::is_loading, set = Self::set_is_loading)]
29        is_loading: PhantomData<bool>,
30    }
31
32    #[glib::object_subclass]
33    impl ObjectSubclass for CheckLoadingRow {
34        const NAME: &'static str = "CheckLoadingRow";
35        type Type = super::CheckLoadingRow;
36        type ParentType = adw::ActionRow;
37        type Interfaces = (gtk::Actionable,);
38
39        fn class_init(klass: &mut Self::Class) {
40            Self::bind_template(klass);
41        }
42
43        fn instance_init(obj: &InitializingObject<Self>) {
44            obj.init_template();
45        }
46    }
47
48    #[glib::derived_properties]
49    impl ObjectImpl for CheckLoadingRow {
50        fn constructed(&self) {
51            self.parent_constructed();
52            let obj = self.obj();
53
54            self.check.connect_active_notify(clone!(
55                #[weak]
56                obj,
57                move |check| {
58                    obj.update_state(&[gtk::accessible::State::Checked(
59                        bool_to_accessible_tristate(check.is_active()),
60                    )]);
61                }
62            ));
63            obj.update_state(&[gtk::accessible::State::Checked(
64                bool_to_accessible_tristate(self.check.is_active()),
65            )]);
66        }
67    }
68
69    impl WidgetImpl for CheckLoadingRow {}
70    impl ListBoxRowImpl for CheckLoadingRow {}
71    impl PreferencesRowImpl for CheckLoadingRow {}
72    impl ActionRowImpl for CheckLoadingRow {}
73
74    impl ActionableImpl for CheckLoadingRow {
75        fn action_name(&self) -> Option<glib::GString> {
76            self.check.action_name()
77        }
78
79        fn action_target_value(&self) -> Option<glib::Variant> {
80            self.check.action_target_value()
81        }
82
83        fn set_action_name(&self, name: Option<&str>) {
84            self.check.set_action_name(name);
85        }
86
87        fn set_action_target_value(&self, value: Option<&glib::Variant>) {
88            self.check.set_action_target(value);
89        }
90    }
91
92    impl CheckLoadingRow {
93        /// Set the target value of the action of the button.
94        #[allow(clippy::needless_pass_by_value)] // glib::Properties macro does not work with ref.
95        fn set_action_target(&self, value: Option<glib::Variant>) {
96            self.set_action_target_value(value.as_ref());
97        }
98
99        /// Whether the row is loading.
100        fn is_loading(&self) -> bool {
101            self.bin.is_loading()
102        }
103
104        /// Set whether the row is loading.
105        fn set_is_loading(&self, loading: bool) {
106            if self.is_loading() == loading {
107                return;
108            }
109
110            self.bin.set_is_loading(loading);
111            self.obj().notify_is_loading();
112        }
113    }
114}
115
116glib::wrapper! {
117    /// An `AdwActionRow` with a check button and a loading state.
118    pub struct CheckLoadingRow(ObjectSubclass<imp::CheckLoadingRow>)
119        @extends gtk::Widget, gtk::ListBoxRow, adw::PreferencesRow, adw::ActionRow,
120        @implements gtk::Accessible, gtk::Buildable, gtk::ConstraintTarget, gtk::Actionable;
121}
122
123impl CheckLoadingRow {
124    pub fn new() -> Self {
125        glib::Object::new()
126    }
127}