fractal/components/rows/
switch_loading_row.rs1use adw::{prelude::*, subclass::prelude::*};
2use gtk::{glib, glib::clone, CompositeTemplate};
3
4use crate::utils::bool_to_accessible_tristate;
5
6mod imp {
7 use std::{cell::Cell, marker::PhantomData};
8
9 use glib::subclass::InitializingObject;
10
11 use super::*;
12
13 #[derive(Debug, Default, CompositeTemplate, glib::Properties)]
14 #[template(resource = "/org/gnome/Fractal/ui/components/rows/switch_loading_row.ui")]
15 #[properties(wrapper_type = super::SwitchLoadingRow)]
16 pub struct SwitchLoadingRow {
17 #[template_child]
18 spinner: TemplateChild<adw::Spinner>,
19 #[template_child]
20 switch: TemplateChild<gtk::Switch>,
21 #[property(get = Self::is_active, set = Self::set_is_active)]
23 is_active: PhantomData<bool>,
24 #[property(get = Self::is_loading, set = Self::set_is_loading)]
26 is_loading: PhantomData<bool>,
27 #[property(get, set = Self::set_read_only, explicit_notify)]
29 read_only: Cell<bool>,
30 }
31
32 #[glib::object_subclass]
33 impl ObjectSubclass for SwitchLoadingRow {
34 const NAME: &'static str = "SwitchLoadingRow";
35 type Type = super::SwitchLoadingRow;
36 type ParentType = adw::ActionRow;
37
38 fn class_init(klass: &mut Self::Class) {
39 Self::bind_template(klass);
40
41 klass.set_accessible_role(gtk::AccessibleRole::Switch);
42 }
43
44 fn instance_init(obj: &InitializingObject<Self>) {
45 obj.init_template();
46 }
47 }
48
49 #[glib::derived_properties]
50 impl ObjectImpl for SwitchLoadingRow {
51 fn constructed(&self) {
52 self.parent_constructed();
53 let obj = self.obj();
54
55 self.switch.connect_active_notify(clone!(
56 #[weak]
57 obj,
58 move |switch| {
59 obj.update_state(&[gtk::accessible::State::Checked(
60 bool_to_accessible_tristate(switch.is_active()),
61 )]);
62 obj.notify_is_active();
63 }
64 ));
65 obj.update_state(&[gtk::accessible::State::Checked(
66 bool_to_accessible_tristate(self.switch.is_active()),
67 )]);
68 }
69 }
70
71 impl WidgetImpl for SwitchLoadingRow {}
72 impl ListBoxRowImpl for SwitchLoadingRow {}
73 impl PreferencesRowImpl for SwitchLoadingRow {}
74 impl ActionRowImpl for SwitchLoadingRow {}
75
76 impl SwitchLoadingRow {
77 fn is_active(&self) -> bool {
79 self.switch.is_active()
80 }
81
82 fn set_is_active(&self, active: bool) {
84 if self.is_active() == active {
85 return;
86 }
87
88 self.switch.set_active(active);
89 self.obj().notify_is_active();
90 }
91
92 fn is_loading(&self) -> bool {
94 self.spinner.is_visible()
95 }
96
97 fn set_is_loading(&self, loading: bool) {
99 if self.is_loading() == loading {
100 return;
101 }
102
103 self.spinner.set_visible(loading);
104 self.obj().notify_is_loading();
105 }
106
107 fn set_read_only(&self, read_only: bool) {
109 if self.read_only.get() == read_only {
110 return;
111 }
112 let obj = self.obj();
113
114 self.read_only.set(read_only);
115
116 obj.update_property(&[gtk::accessible::Property::ReadOnly(read_only)]);
117 obj.notify_read_only();
118 }
119 }
120}
121
122glib::wrapper! {
123 pub struct SwitchLoadingRow(ObjectSubclass<imp::SwitchLoadingRow>)
125 @extends gtk::Widget, gtk::ListBoxRow, adw::PreferencesRow, adw::ActionRow,
126 @implements gtk::Actionable, gtk::Accessible;
127}
128
129impl SwitchLoadingRow {
130 pub fn new() -> Self {
131 glib::Object::new()
132 }
133}