From 3c23922708740158abd1975ecd8213a65beacad3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Garc=C3=ADa=20Moreno?= Date: Fri, 22 Dec 2017 21:10:38 +0100 Subject: [PATCH] Member avatar with the avatar widget --- fractal-gtk/src/globals.rs | 2 ++ fractal-gtk/src/widgets/avatar.rs | 36 ++++++++++++++++++++---------- fractal-gtk/src/widgets/member.rs | 27 +++++++++++++--------- fractal-gtk/src/widgets/message.rs | 14 +++++++----- 4 files changed, 50 insertions(+), 29 deletions(-) diff --git a/fractal-gtk/src/globals.rs b/fractal-gtk/src/globals.rs index ecae021e..9703cbb3 100644 --- a/fractal-gtk/src/globals.rs +++ b/fractal-gtk/src/globals.rs @@ -1 +1,3 @@ pub static CACHE_SIZE: usize = 40; +pub static MSG_ICON_SIZE: i32 = 40; +pub static USERLIST_ICON_SIZE: i32 = 30; diff --git a/fractal-gtk/src/widgets/avatar.rs b/fractal-gtk/src/widgets/avatar.rs index cdf36dc9..4ff0751a 100644 --- a/fractal-gtk/src/widgets/avatar.rs +++ b/fractal-gtk/src/widgets/avatar.rs @@ -64,12 +64,13 @@ impl AvatarExt for gtk::Box { fn default(&self, icon: String, size: Option) { self.clean(); let da = self.create_da(size); + let s = size.unwrap_or(40); da.connect_draw(move |da, g| { use std::f64::consts::PI; - let width = da.get_allocated_width() as f64; - let height = da.get_allocated_height() as f64; + let width = s as f64; + let height = s as f64; let context = da.get_style_context().unwrap(); @@ -77,7 +78,15 @@ impl AvatarExt for gtk::Box { g.set_antialias(cairo::Antialias::Best); let img = gtk::Image::new_from_icon_name(&icon[..], 5); - let pb = img.get_pixbuf().unwrap(); + let icon = gtk::IconTheme::get_default().unwrap() + .load_icon(&icon[..], s, gtk::IconLookupFlags::empty()) + .unwrap(); + if let None = icon { + eprintln!("BAD IMAGE"); + return Inhibit(false); + } + + let pb = icon.unwrap(); let hpos: f64 = (width - (pb.get_height()) as f64) / 2.0; g.set_source_pixbuf(&pb, 0.0, hpos); @@ -94,28 +103,31 @@ impl AvatarExt for gtk::Box { fn circle(&self, path: String, size: Option) { self.clean(); let da = self.create_da(size); + let s = size.unwrap_or(40); let p = path.clone(); da.connect_draw(move |da, g| { use std::f64::consts::PI; - let width = da.get_allocated_width() as f64; - let height = da.get_allocated_height() as f64; + let width = s as f64; + let height = s as f64; let context = da.get_style_context().unwrap(); gtk::render_background(&context, g, 0.0, 0.0, width, height); g.set_antialias(cairo::Antialias::Best); - let pb = Pixbuf::new_from_file_at_scale(&p, width as i32, -1, true).unwrap(); - let hpos: f64 = (width - (pb.get_height()) as f64) / 2.0; + if let Ok(pb) = Pixbuf::new_from_file_at_scale(&p, width as i32, -1, true) { + let hpos: f64 = (width - (pb.get_height()) as f64) / 2.0; - g.arc(width / 2.0, height / 2.0, width.min(height) / 2.0, 0.0, 2.0 * PI); - g.clip(); + g.arc(width / 2.0, height / 2.0, width.min(height) / 2.0, 0.0, 2.0 * PI); + g.clip(); - g.set_source_pixbuf(&pb, 0.0, hpos); - g.rectangle(0.0, 0.0, width, height); - g.fill(); + g.set_source_pixbuf(&pb, 0.0, hpos); + g.rectangle(0.0, 0.0, width, height); + g.fill(); + da.queue_draw(); + } Inhibit(false) }); diff --git a/fractal-gtk/src/widgets/member.rs b/fractal-gtk/src/widgets/member.rs index a559e0bd..c7526a4a 100644 --- a/fractal-gtk/src/widgets/member.rs +++ b/fractal-gtk/src/widgets/member.rs @@ -14,6 +14,10 @@ use std::sync::mpsc::{Sender, Receiver}; use app::AppOp; +use globals; +use widgets; +use widgets::AvatarExt; + // Room Search item pub struct MemberBox<'a> { member: &'a Member, @@ -39,9 +43,10 @@ impl<'a> MemberBox<'a> { username.set_margin_end(5); username.set_ellipsize(pango::EllipsizeMode::End); - let avatar = gtk::Image::new_from_icon_name("avatar-default-symbolic", 3); - get_member_avatar(backend.clone(), avatar.clone(), Some(self.member.clone()), 30, 10); - avatar.set_alignment(0.5, 0.5); + let avatar = widgets::Avatar::avatar_new(Some(globals::USERLIST_ICON_SIZE)); + avatar.default(String::from("avatar-default-symbolic"), + Some(globals::USERLIST_ICON_SIZE)); + get_member_avatar(backend.clone(), avatar.clone(), Some(self.member.clone()), globals::USERLIST_ICON_SIZE, 10); avatar.set_margin_start(5); w.add(&avatar); @@ -53,7 +58,7 @@ impl<'a> MemberBox<'a> { } } -pub fn get_member_avatar(backend: Sender, img: gtk::Image, m: Option, size: i32, tries: i32) { +pub fn get_member_avatar(backend: Sender, img: widgets::Avatar, m: Option, size: i32, tries: i32) { if tries <= 0 { return; } @@ -63,11 +68,11 @@ pub fn get_member_avatar(backend: Sender, img: gtk::Image, m: Option< gtk::timeout_add(50, move || match rx.try_recv() { Err(_) => gtk::Continue(true), Ok(avatar) => { - if let Ok(pixbuf) = Pixbuf::new_from_file_at_scale(&avatar, size, size, false) { - img.set_from_pixbuf(&pixbuf); + if let Ok(_) = Pixbuf::new_from_file_at_scale(&avatar, size, size, false) { + img.circle(avatar, Some(size)); } else { // trying again if fail - img.set_from_icon_name("avatar-default-symbolic", 5); + img.default(String::from("avatar-default-symbolic"), Some(size)); get_member_avatar(backend.clone(), img.clone(), m.clone(), size, tries - 1); } @@ -78,17 +83,17 @@ pub fn get_member_avatar(backend: Sender, img: gtk::Image, m: Option< -pub fn get_member_info(backend: Sender, img: gtk::Image, username: gtk::Label, sender: String, size: i32, tries: i32) { +pub fn get_member_info(backend: Sender, img: widgets::Avatar, username: gtk::Label, sender: String, size: i32, tries: i32) { let (tx, rx): (Sender<(String, String)>, Receiver<(String, String)>) = channel(); backend.send(BKCommand::GetUserInfoAsync(sender.clone(), tx)).unwrap(); gtk::timeout_add(50, move || match rx.try_recv() { Err(_) => gtk::Continue(true), Ok((name, avatar)) => { - if let Ok(pixbuf) = Pixbuf::new_from_file_at_scale(&avatar, size, size, false) { - img.set_from_pixbuf(&pixbuf); + if let Ok(_) = Pixbuf::new_from_file_at_scale(&avatar, size, size, false) { + img.circle(avatar, Some(size)); } else { // trying again if fail - img.set_from_icon_name("avatar-default-symbolic", 5); + img.default(String::from("avatar-default-symbolic"), Some(size)); get_member_info(backend.clone(), img.clone(), username.clone(), sender.clone(), size, tries - 1); return gtk::Continue(false); } diff --git a/fractal-gtk/src/widgets/message.rs b/fractal-gtk/src/widgets/message.rs index f1f37521..671e4823 100644 --- a/fractal-gtk/src/widgets/message.rs +++ b/fractal-gtk/src/widgets/message.rs @@ -20,6 +20,9 @@ use util; use std::path::Path; use app::AppOp; +use globals; +use widgets; +use widgets::AvatarExt; use widgets::member::get_member_avatar; use widgets::member::get_member_info; @@ -113,19 +116,20 @@ impl<'a> MessageBox<'a> { content } - fn build_room_msg_avatar(&self) -> gtk::Image { + fn build_room_msg_avatar(&self) -> widgets::Avatar { let sender = self.msg.sender.clone(); let backend = self.op.backend.clone(); - let avatar; + let avatar = widgets::Avatar::avatar_new(Some(globals::MSG_ICON_SIZE)); let fname = api::util::cache_path(&sender).unwrap_or(strn!("")); let pathname = fname.clone(); let p = Path::new(&pathname); if p.is_file() { - avatar = gtk::Image::new_from_file(&fname); + avatar.circle(fname, Some(globals::MSG_ICON_SIZE)); } else { - avatar = gtk::Image::new_from_icon_name("avatar-default-symbolic", 5); + avatar.default(String::from("avatar-default-symbolic"), + Some(globals::MSG_ICON_SIZE)); } let m = self.room.members.get(&sender); @@ -141,8 +145,6 @@ impl<'a> MessageBox<'a> { } }; - avatar.set_alignment(0.5, 0.0); - avatar }