[fractal/fractal-next] components: Add widget for user pills
- From: Julian Sparber <jsparber src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [fractal/fractal-next] components: Add widget for user pills
- Date: Mon, 24 May 2021 14:16:36 +0000 (UTC)
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]