[fractal/wip/christopherdavis/use-hdyavatar] avatar: Use HdyAvatar instead of a custom DrawingArea
- From: Christopher Davis <christopherdavis src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [fractal/wip/christopherdavis/use-hdyavatar] avatar: Use HdyAvatar instead of a custom DrawingArea
- Date: Tue, 29 Sep 2020 18:29:25 +0000 (UTC)
commit 75f6948da514c6fd548ea588d17c424eb874c99d
Author: Christopher Davis <brainblasted disroot org>
Date: Mon Sep 28 23:23:09 2020 -0700
avatar: Use HdyAvatar instead of a custom DrawingArea
HdyAvatar allows for simple HiDPI image loading and
a fallback image.
Related to https://gitlab.gnome.org/GNOME/fractal/issues/496
Cargo.lock | 50 ++--------------
fractal-gtk/Cargo.toml | 3 +-
fractal-gtk/src/cache/mod.rs | 6 +-
fractal-gtk/src/widgets/avatar.rs | 113 +++++++++----------------------------
fractal-gtk/src/widgets/message.rs | 1 +
5 files changed, 37 insertions(+), 136 deletions(-)
---
diff --git a/Cargo.lock b/Cargo.lock
index 0873b493..f8a849da 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -567,7 +567,6 @@ dependencies = [
"html2pango",
"itertools 0.8.2",
"lazy_static",
- "letter-avatar",
"libhandy",
"log",
"loggerv",
@@ -1422,18 +1421,6 @@ version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
-[[package]]
-name = "letter-avatar"
-version = "1.3.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "662660bd131a9c06b36730750de8049efb5d2c8e0c23b3b58e9dd87e61acc245"
-dependencies = [
- "cairo-rs",
- "pango",
- "pangocairo",
- "unicode-segmentation",
-]
-
[[package]]
name = "libc"
version = "0.2.76"
@@ -1442,12 +1429,14 @@ checksum = "755456fae044e6fa1ebbbd1b3e902ae19e73097ed4ed87bb79934a867c007bc3"
[[package]]
name = "libhandy"
-version = "0.7.0"
+version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ce64d9c1f9e9444fb1175cf65cb6db9b55e7ae5f9a44140202da05784a7cdf33"
+checksum = "d776bf5b92993b8006688652cda2683261317dcc82bb4d91d3996bda2f7019e0"
dependencies = [
"bitflags",
"gdk",
+ "gdk-pixbuf",
+ "gdk-pixbuf-sys",
"gdk-sys",
"gio",
"gio-sys",
@@ -1882,37 +1871,6 @@ dependencies = [
"system-deps",
]
-[[package]]
-name = "pangocairo"
-version = "0.10.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "00f5ae67a05a5e023f09f64e9a71c845274d4b82dedee237b70425811885e883"
-dependencies = [
- "bitflags",
- "cairo-rs",
- "cairo-sys-rs",
- "glib",
- "glib-sys",
- "gobject-sys",
- "libc",
- "pango",
- "pango-sys",
- "pangocairo-sys",
-]
-
-[[package]]
-name = "pangocairo-sys"
-version = "0.11.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "94ccc97f698c2f0233b84e5ca676893a1e676785b60eec700b9c0e6dcd0feb98"
-dependencies = [
- "cairo-sys-rs",
- "glib-sys",
- "libc",
- "pango-sys",
- "system-deps",
-]
-
[[package]]
name = "paste"
version = "0.1.18"
diff --git a/fractal-gtk/Cargo.toml b/fractal-gtk/Cargo.toml
index 04b8b794..8ab99f2a 100644
--- a/fractal-gtk/Cargo.toml
+++ b/fractal-gtk/Cargo.toml
@@ -28,7 +28,6 @@ rand = "0.7.3"
regex = "1.3.4"
secret-service = "1.0.0"
serde_json = "1.0.48"
-letter-avatar = "1.3.0"
sourceview4 = "0.2.0"
gspell = "0.5.0"
gtk-sys = "0.10.0"
@@ -54,7 +53,7 @@ path = "../fractal-matrix-api"
package = "fractal-matrix-api"
[dependencies.libhandy]
-version = "0.7.0"
+version = "0.7.1"
[dependencies.gettext-rs]
git = "https://github.com/danigm/gettext-rs"
diff --git a/fractal-gtk/src/cache/mod.rs b/fractal-gtk/src/cache/mod.rs
index 8943eac6..8a8dc78a 100644
--- a/fractal-gtk/src/cache/mod.rs
+++ b/fractal-gtk/src/cache/mod.rs
@@ -178,7 +178,7 @@ pub fn download_to_cache(
Err(TryRecvError::Empty) => Continue(true),
Err(TryRecvError::Disconnected) => Continue(false),
Ok(_resp) => {
- data.borrow_mut().redraw_pixbuf();
+ data.borrow_mut().redraw(None);
Continue(false)
}
});
@@ -204,7 +204,7 @@ pub fn download_to_cache_username(
label.set_text(&username);
if let Some(ref rc_data) = avatar {
let mut data = rc_data.borrow_mut();
- data.redraw_fallback(Some(username));
+ data.redraw(Some(username));
}
Continue(false)
@@ -235,7 +235,7 @@ pub fn download_to_cache_username_emote(
label.set_markup(&format!("<b>{}</b> {}", &username, text));
if let Some(ref rc_data) = avatar {
let mut data = rc_data.borrow_mut();
- data.redraw_fallback(Some(username));
+ data.redraw(Some(username));
}
Continue(false)
diff --git a/fractal-gtk/src/widgets/avatar.rs b/fractal-gtk/src/widgets/avatar.rs
index f2a2a725..1a764613 100644
--- a/fractal-gtk/src/widgets/avatar.rs
+++ b/fractal-gtk/src/widgets/avatar.rs
@@ -1,12 +1,12 @@
+use std::boxed::Box;
use std::cell::RefCell;
use std::path::Path;
use std::rc::Rc;
use crate::util::cache_dir_path;
-use gdk::prelude::GdkContextExt;
use gdk_pixbuf::Pixbuf;
use gtk::prelude::*;
-pub use gtk::DrawingArea;
+use libhandy::AvatarExt as HdyAvatarExt;
pub enum AvatarBadgeColor {
Gold,
@@ -18,25 +18,16 @@ pub type Avatar = gtk::Overlay;
pub struct AvatarData {
id: String,
- username: Option<String>,
size: i32,
cache: Option<Pixbuf>,
- pub widget: gtk::DrawingArea,
- fallback: cairo::ImageSurface,
+ pub widget: libhandy::Avatar,
}
impl AvatarData {
- pub fn redraw_fallback(&mut self, username: Option<String>) {
- self.username = username.clone();
- /* This function should never fail */
- self.fallback = letter_avatar::generate::new(self.id.clone(), username, self.size as f64)
- .expect("this function should never fail");
- self.widget.queue_draw();
- }
-
- pub fn redraw_pixbuf(&mut self) {
+ pub fn redraw(&mut self, username: Option<String>) {
let path = cache_dir_path(None, self.id.as_str()).unwrap_or_default();
self.cache = load_pixbuf(&path, self.size);
+ username.map(|n| self.widget.set_text(Some(&n)));
self.widget.queue_draw();
}
}
@@ -44,7 +35,7 @@ impl AvatarData {
pub trait AvatarExt {
fn avatar_new(size: Option<i32>) -> gtk::Overlay;
fn clean(&self);
- fn create_da(&self, size: Option<i32>) -> DrawingArea;
+ fn create_avatar(&self, size: Option<i32>) -> libhandy::Avatar;
fn circle(
&self,
id: String,
@@ -62,20 +53,19 @@ impl AvatarExt for gtk::Overlay {
}
}
- fn create_da(&self, size: Option<i32>) -> DrawingArea {
- let da = DrawingArea::new();
-
+ fn create_avatar(&self, size: Option<i32>) -> libhandy::Avatar {
let s = size.unwrap_or(40);
- da.set_size_request(s, s);
- self.add(&da);
+ let avatar = libhandy::Avatar::new(s, None, true);
+ avatar.set_show_initials(true);
+ self.add(&avatar);
self.show_all();
- da
+ avatar
}
fn avatar_new(size: Option<i32>) -> gtk::Overlay {
let b = gtk::Overlay::new();
- b.create_da(size);
+ b.create_avatar(size);
b.show_all();
b.get_style_context().add_class("avatar");
@@ -96,21 +86,21 @@ impl AvatarExt for gtk::Overlay {
badge_size: Option<i32>,
) -> Rc<RefCell<AvatarData>> {
self.clean();
- let da = self.create_da(Some(size));
+ let avatar = self.create_avatar(Some(size));
let path = cache_dir_path(None, id.as_str()).unwrap_or_default();
- let user_avatar = load_pixbuf(&path, size);
- let uname = username.clone();
+ let cache = load_pixbuf(&path, size);
/* remove IRC postfix from the username */
let username = if let Some(u) = username {
- Some(u.trim_end_matches(" (IRC)").to_owned())
+ u.trim_end_matches(" (IRC)")
+ .trim_start_matches("#")
+ .to_owned()
} else {
- None
+ id.clone()
};
- /* This function should never fail */
- let fallback = letter_avatar::generate::new(id.clone(), username, size as f64)
- .expect("this function should never fail");
+
+ avatar.set_text(Some(&username));
+
// Power level badge setup
- let has_badge = badge_color.is_some();
let badge_size = badge_size.unwrap_or(size / 3);
if let Some(color) = badge_color {
let badge = gtk::Box::new(gtk::Orientation::Vertical, 0);
@@ -127,64 +117,17 @@ impl AvatarExt for gtk::Overlay {
}
let data = AvatarData {
- id,
- username: uname,
+ id: id.clone(),
size,
- cache: user_avatar,
- fallback,
- widget: da.clone(),
+ cache,
+ widget: avatar.clone(),
};
let avatar_cache: Rc<RefCell<AvatarData>> = Rc::new(RefCell::new(data));
- let user_cache = avatar_cache.clone();
- da.connect_draw(move |da, g| {
- use std::f64::consts::PI;
- let width = size as f64;
- let height = size as f64;
-
- g.set_antialias(cairo::Antialias::Best);
-
- {
- g.set_fill_rule(cairo::FillRule::EvenOdd);
- g.arc(
- width / 2.0,
- height / 2.0,
- width.min(height) / 2.0,
- 0.0,
- 2.0 * PI,
- );
- if has_badge {
- g.clip_preserve();
- g.new_sub_path();
- let badge_radius = badge_size as f64 / 2.0;
- g.arc(
- width - badge_radius,
- badge_radius,
- badge_radius * 1.4,
- 0.0,
- 2.0 * PI,
- );
- }
- g.clip();
-
- let data = user_cache.borrow();
- if let Some(ref pb) = data.cache {
- let context = da.get_style_context();
- gtk::render_background(&context, g, 0.0, 0.0, width, height);
-
- let hpos: f64 = (width - (pb.get_height()) as f64) / 2.0;
- g.set_source_pixbuf(&pb, 0.0, hpos);
- } else {
- /* use fallback */
- g.set_source_surface(&data.fallback, 0f64, 0f64);
- }
- }
-
- g.rectangle(0.0, 0.0, width, height);
- g.fill();
-
- Inhibit(false)
- });
+ avatar.set_image_load_func(Some(Box::new(move |sz| {
+ let path = cache_dir_path(None, id.as_str()).unwrap_or_default();
+ load_pixbuf(&path, sz)
+ })));
avatar_cache
}
diff --git a/fractal-gtk/src/widgets/message.rs b/fractal-gtk/src/widgets/message.rs
index 084e16e9..d68e98ec 100644
--- a/fractal-gtk/src/widgets/message.rs
+++ b/fractal-gtk/src/widgets/message.rs
@@ -268,6 +268,7 @@ impl MessageBox {
let uid = msg.sender.clone();
let alias = msg.sender_name.clone();
let avatar = widgets::Avatar::avatar_new(Some(globals::MSG_ICON_SIZE));
+ avatar.set_valign(gtk::Align::Start);
let data = avatar.circle(
uid.to_string(),
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]