[fractal/fractal-next] components: Add widget for user pills



commit c2f73e551f2278f47206d3e6b983904db6f1ec1d
Author: Julian Sparber <julian sparber net>
Date:   Thu May 20 09:22:47 2021 +0200

    components: Add widget for user pills

 data/resources/resources.gresource.xml |   1 +
 data/resources/style.css               |   6 ++
 data/resources/ui/user-pill.ui         |  32 ++++++++++
 po/POTFILES.in                         |   2 +
 src/components/mod.rs                  |   2 +
 src/components/user_pill.rs            | 111 +++++++++++++++++++++++++++++++++
 src/meson.build                        |   1 +
 src/session/mod.rs                     |   2 +-
 8 files changed, 156 insertions(+), 1 deletion(-)
---
diff --git a/data/resources/resources.gresource.xml b/data/resources/resources.gresource.xml
index 5acbb7e1..f83e2946 100644
--- a/data/resources/resources.gresource.xml
+++ b/data/resources/resources.gresource.xml
@@ -17,6 +17,7 @@
     <file compressed="true" preprocess="xml-stripblanks" 
alias="sidebar-room-row.ui">ui/sidebar-room-row.ui</file>
     <file compressed="true" preprocess="xml-stripblanks" alias="window.ui">ui/window.ui</file>
     <file compressed="true" preprocess="xml-stripblanks" 
alias="context-menu-bin.ui">ui/context-menu-bin.ui</file>
+    <file compressed="true" preprocess="xml-stripblanks" alias="user-pill.ui">ui/user-pill.ui</file>
     <file compressed="true">style.css</file>
     <file preprocess="xml-stripblanks">icons/scalable/actions/send-symbolic.svg</file>
     <file preprocess="xml-stripblanks">icons/scalable/status/welcome.svg</file>
diff --git a/data/resources/style.css b/data/resources/style.css
index 584ff678..5d46ab2c 100644
--- a/data/resources/style.css
+++ b/data/resources/style.css
@@ -3,6 +3,12 @@
   font-weight: bold;
 }
 
+.user-pill {
+  border-radius: 9999px;
+  background-color: alpha(@theme_text_color, 0.1);
+  padding-right: 6px;
+}
+
 /* Login */
 .login {
   min-width: 250px;
diff --git a/data/resources/ui/user-pill.ui b/data/resources/ui/user-pill.ui
new file mode 100644
index 00000000..aff200ae
--- /dev/null
+++ b/data/resources/ui/user-pill.ui
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+  <template class="UserPill" parent="AdwBin">
+    <property name="focusable">True</property>
+    <style>
+      <class name="user-pill"/>
+    </style>
+    <child>
+      <object class="GtkBox">
+        <property name="spacing">6</property>
+        <child>
+          <object class="AdwAvatar" id="avatar">
+            <property name="show-initials">True</property>
+            <property name="size">24</property>
+            <property name="text" bind-source="display_name" bind-property="label" bind-flags="sync-create" 
/>
+          </object>
+        </child>
+        <child>
+          <object class="GtkLabel" id="display_name">
+            <property name="ellipsize">middle</property>
+            <property name="max-width-chars">30</property>
+            <binding name="label">
+              <lookup name="display-name">
+                <lookup name="user">UserPill</lookup>
+              </lookup>
+            </binding>
+          </object>
+        </child>
+      </object>
+    </child>
+  </template>
+</interface>
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 1ef516a9..28385a3c 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -21,12 +21,14 @@ data/resources/ui/sidebar-category-row.ui
 data/resources/ui/sidebar-item.ui
 data/resources/ui/sidebar-room-row.ui
 data/resources/ui/sidebar.ui
+data/resources/ui/user-pill.ui
 data/resources/ui/window.ui
 
 # Rust files
 src/application.rs
 src/components/context_menu_bin.rs
 src/components/mod.rs
+src/components/user_pill.rs
 src/login.rs
 src/main.rs
 src/secret.rs
diff --git a/src/components/mod.rs b/src/components/mod.rs
index 8ea2852e..05615c7f 100644
--- a/src/components/mod.rs
+++ b/src/components/mod.rs
@@ -1,3 +1,5 @@
 mod context_menu_bin;
+mod user_pill;
 
 pub use self::context_menu_bin::{ContextMenuBin, ContextMenuBinImpl};
+pub use self::user_pill::UserPill;
diff --git a/src/components/user_pill.rs b/src/components/user_pill.rs
new file mode 100644
index 00000000..cfe92d4e
--- /dev/null
+++ b/src/components/user_pill.rs
@@ -0,0 +1,111 @@
+use adw::subclass::prelude::*;
+use gtk::prelude::*;
+use gtk::subclass::prelude::*;
+use gtk::{glib, CompositeTemplate};
+
+use crate::session::User;
+
+mod imp {
+    use super::*;
+    use glib::subclass::InitializingObject;
+    use std::cell::RefCell;
+
+    #[derive(Debug, Default, CompositeTemplate)]
+    #[template(resource = "/org/gnome/FractalNext/user-pill.ui")]
+    pub struct UserPill {
+        /// The user displayed by this widget
+        pub user: RefCell<Option<User>>,
+        #[template_child]
+        pub display_name: TemplateChild<gtk::Label>,
+        #[template_child]
+        pub avatar: TemplateChild<adw::Avatar>,
+    }
+
+    #[glib::object_subclass]
+    impl ObjectSubclass for UserPill {
+        const NAME: &'static str = "UserPill";
+        type Type = super::UserPill;
+        type ParentType = adw::Bin;
+
+        fn class_init(klass: &mut Self::Class) {
+            Self::bind_template(klass);
+        }
+
+        fn instance_init(obj: &InitializingObject<Self>) {
+            obj.init_template();
+        }
+    }
+
+    impl ObjectImpl for UserPill {
+        fn properties() -> &'static [glib::ParamSpec] {
+            use once_cell::sync::Lazy;
+            static PROPERTIES: Lazy<Vec<glib::ParamSpec>> = Lazy::new(|| {
+                vec![glib::ParamSpec::new_object(
+                    "user",
+                    "User",
+                    "The user displayed by this widget",
+                    User::static_type(),
+                    glib::ParamFlags::READWRITE | glib::ParamFlags::EXPLICIT_NOTIFY,
+                )]
+            });
+
+            PROPERTIES.as_ref()
+        }
+
+        fn set_property(
+            &self,
+            obj: &Self::Type,
+            _id: usize,
+            value: &glib::Value,
+            pspec: &glib::ParamSpec,
+        ) {
+            match pspec.name() {
+                "user" => {
+                    let user = value.get().unwrap();
+                    obj.set_user(user);
+                }
+                _ => unimplemented!(),
+            }
+        }
+
+        fn property(&self, obj: &Self::Type, _id: usize, pspec: &glib::ParamSpec) -> glib::Value {
+            match pspec.name() {
+                "user" => obj.user().to_value(),
+                _ => unimplemented!(),
+            }
+        }
+    }
+
+    impl WidgetImpl for UserPill {}
+
+    impl BinImpl for UserPill {}
+}
+
+glib::wrapper! {
+    pub struct UserPill(ObjectSubclass<imp::UserPill>)
+        @extends gtk::Widget, adw::Bin, @implements gtk::Accessible;
+}
+
+/// A widget displaying a `User`
+impl UserPill {
+    pub fn new() -> Self {
+        glib::Object::new(&[]).expect("Failed to create UserPill")
+    }
+
+    pub fn set_user(&self, user: Option<User>) {
+        let priv_ = imp::UserPill::from_instance(self);
+
+        if *priv_.user.borrow() == user {
+            return;
+        }
+
+        priv_.user.replace(user);
+
+        self.notify("user");
+    }
+
+    pub fn user(&self) -> Option<User> {
+        let priv_ = imp::UserPill::from_instance(self);
+        priv_.user.borrow().clone()
+    }
+}
diff --git a/src/meson.build b/src/meson.build
index fa656726..d91b6343 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -22,6 +22,7 @@ sources = files(
   'application.rs',
   'components/context_menu_bin.rs',
   'components/mod.rs',
+  'components/user_pill.rs',
   'config.rs',
   'main.rs',
   'window.rs',
diff --git a/src/session/mod.rs b/src/session/mod.rs
index c6b6147c..fd4038e9 100644
--- a/src/session/mod.rs
+++ b/src/session/mod.rs
@@ -8,7 +8,7 @@ use self::categories::Categories;
 use self::content::Content;
 use self::room::Room;
 use self::sidebar::Sidebar;
-use self::user::User;
+pub use self::user::User;
 
 use crate::event_from_sync_event;
 use crate::secret;


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]