Skip to main content

fractal/components/
role_badge.rs

1use adw::{prelude::*, subclass::prelude::*};
2use gtk::glib;
3
4use crate::session::MemberRole;
5
6mod imp {
7    use std::cell::Cell;
8
9    use super::*;
10
11    #[derive(Debug, Default, glib::Properties)]
12    #[properties(wrapper_type = super::RoleBadge)]
13    pub struct RoleBadge {
14        label: gtk::Label,
15        /// The role displayed by this badge.
16        #[property(get, set = Self::set_role, explicit_notify, builder(MemberRole::default()))]
17        role: Cell<MemberRole>,
18        /// Whether the role displayed by this badge is the default role.
19        #[property(get)]
20        is_default_role: Cell<bool>,
21    }
22
23    #[glib::object_subclass]
24    impl ObjectSubclass for RoleBadge {
25        const NAME: &'static str = "RoleBadge";
26        type Type = super::RoleBadge;
27        type ParentType = adw::Bin;
28
29        fn class_init(klass: &mut Self::Class) {
30            klass.set_css_name("role-badge");
31        }
32    }
33
34    #[glib::derived_properties]
35    impl ObjectImpl for RoleBadge {
36        fn constructed(&self) {
37            self.parent_constructed();
38
39            self.obj().set_child(Some(&self.label));
40            self.update_badge();
41            self.update_is_default_role();
42        }
43    }
44
45    impl WidgetImpl for RoleBadge {}
46    impl BinImpl for RoleBadge {}
47
48    impl RoleBadge {
49        /// Set the role displayed by this badge.
50        fn set_role(&self, role: MemberRole) {
51            if self.role.get() == role {
52                return;
53            }
54
55            self.role.set(role);
56            self.update_badge();
57            self.update_is_default_role();
58            self.obj().notify_role();
59        }
60
61        /// Update whether the role displayed by this badge is the default role.
62        fn update_is_default_role(&self) {
63            let is_default = self.role.get() == MemberRole::Default;
64
65            if self.is_default_role.get() == is_default {
66                return;
67            }
68
69            self.is_default_role.set(is_default);
70            self.obj().notify_is_default_role();
71        }
72
73        /// Update the badge for the current state.
74        fn update_badge(&self) {
75            let obj = self.obj();
76            let role = self.role.get();
77
78            self.label.set_text(&role.to_string());
79
80            if role == MemberRole::Creator {
81                obj.add_css_class("creator");
82            } else {
83                obj.remove_css_class("creator");
84            }
85
86            if role == MemberRole::Administrator {
87                obj.add_css_class("admin");
88            } else {
89                obj.remove_css_class("admin");
90            }
91
92            if role == MemberRole::Moderator {
93                obj.add_css_class("mod");
94            } else {
95                obj.remove_css_class("mod");
96            }
97
98            if role == MemberRole::Muted {
99                obj.add_css_class("muted");
100            } else {
101                obj.remove_css_class("muted");
102            }
103        }
104    }
105}
106
107glib::wrapper! {
108    /// Inline widget displaying a badge with the role of a room member.
109    pub struct RoleBadge(ObjectSubclass<imp::RoleBadge>)
110        @extends gtk::Widget, adw::Bin,
111        @implements gtk::Accessible, gtk::Buildable, gtk::ConstraintTarget;
112}
113
114impl RoleBadge {
115    pub fn new() -> Self {
116        glib::Object::new()
117    }
118}