Merge lp:~philip.scott/granite/Avatar into lp:~elementary-pantheon/granite/granite

Proposed by Felipe Escoto
Status: Merged
Approved by: Danielle Foré
Approved revision: 863
Merged at revision: 882
Proposed branch: lp:~philip.scott/granite/Avatar
Merge into: lp:~elementary-pantheon/granite/granite
Diff against target: 198 lines (+163/-0)
3 files modified
demo/GraniteDemo.vala (+22/-0)
lib/CMakeLists.txt (+1/-0)
lib/Widgets/Avatar.vala (+140/-0)
To merge this branch: bzr merge lp:~philip.scott/granite/Avatar
Reviewer Review Type Date Requested Status
kay van der Zander (community) extra set eyes. Approve
Adam Bieńkowski (community) code Approve
Victor Martinez (community) Needs Fixing
xapantu (community) Approve
Rico Tzschichholz Needs Fixing
Review via email: mp+266120@code.launchpad.net

Commit message

New widget: Avatar

Description of the change

Moved the Avatar class i used to draw the user's image from the new Wingpanel indicator into it's own class. It's also the same that is used in Greeter and could also be used in switchboard's user plug.

To post a comment you must log in.
Revision history for this message
kay van der Zander (kay20) wrote :

Just a tip, i notice you use tabs instead of spaces

Code style quote "Vala code is indented using 4 spaces for consistency and readability"

The outlining is consistent that is what matters.

Line 49 see dif, outline could be better.
Line 115 remove white line.

Draw_connect could be made better readable.
like i learned you.
i also find it wierd that this.draw.connect always returned false. I doubt this is right.

review: Needs Fixing (extra set eyes.)
Revision history for this message
Felipe Escoto (philip.scott) wrote :

Corrected the code style.

draw.connect IS actually supposed to always return false to propagate the event further (see http://valadoc.org/#!api=gtk+-3.0/Gtk.Widget.draw)

And for the outlines.... if you or anyone else has any suggestions, i'll gladly change them :)

Revision history for this message
Rico Tzschichholz (ricotz) wrote :

No offence, but this looks awful.

* gobject-style construction with construct properties
* gtk.builder compatibility
* use "public override bool draw (Cairo.Context cr) { ... }"

Revision history for this message
Adam Bieńkowski (donadigo) wrote :

As others said you should use overriding for draw method. I wanted to point other issues like:
* Do not use new int margin, margin is a property reserved by Gtk and shouldn't be used in calculations, rather use standalone variable name like: avatar_margin.

* There is currently no way of getting the pixbuf directly from the avatar. There should be a method called get_pixbuf that returns it.

review: Needs Fixing
Revision history for this message
Rico Tzschichholz (ricotz) :
review: Needs Fixing
Revision history for this message
Rico Tzschichholz (ricotz) wrote :
Revision history for this message
Danielle Foré (danrabbit) wrote :

Please don't forget to add it to Granite Demo. Probably could add it to the Headerbar with the current user's avatar.

Revision history for this message
Felipe Escoto (philip.scott) wrote :

Alright, it's been added to Granite Demo. Do we want to show a tooltip text on it?

Revision history for this message
Rico Tzschichholz (ricotz) wrote :

The demo-code should give you the hint that this class has a weird way to be used. So I hope you remember what we talked about.

E.g. add a constructor which takes a icon-name or file-path

review: Needs Fixing
Revision history for this message
Rico Tzschichholz (ricotz) wrote :

Get rid of this additional margin let the css-class take care of it.
Only use "this.*"-syntax if it is actually needed.

review: Needs Fixing
Revision history for this message
Danielle Foré (danrabbit) wrote :

Yes having a tooltip would be good practice.

Revision history for this message
xapantu (xapantu) wrote :

Looks fine to me. I am not super-convinced by your "/var/lib/AccountsService/icons/" thing in the demo, but as it is only in the demo, let's do that for now.

review: Approve
Revision history for this message
Victor Martinez (victored) wrote :

Hey it looks good. Please consider my suggestions below.

review: Needs Fixing
Revision history for this message
Victor Martinez (victored) wrote :

There are other places where variable declarations should use 'var' too. Mixed style doesn't look consistent.

Revision history for this message
Rico Tzschichholz (ricotz) wrote :

> There are other places where variable declarations should use 'var' too. Mixed
> style doesn't look consistent.

Better realize what "unowned Gtk.StyleContext style_context = get_style_context ();" does. Don't use "var style_context = ..." since it is NOT the same.

Revision history for this message
Rico Tzschichholz (ricotz) :
Revision history for this message
Victor Martinez (victored) wrote :

Hey Rico I checked the generated C code and you're totally right about 'var'. There's no type inference for unowned. Please disregard that suggestion Phillip.

Revision history for this message
Felipe Escoto (philip.scott) :
Revision history for this message
Adam Bieńkowski (donadigo) wrote :

Looks OK from the code perspectiive.

review: Approve (code)
Revision history for this message
Victor Martinez (victored) wrote :

Hey thanks for making the changes!

Code builds fine against current trunk and it does what it says on the tin. Changing 'draw_theme_background' to 'false' after an avatar image has already been drawn doesn't seem to queue a redraw. This property could be made private for now, or you could connect to the notify signal like you do for pixbuf. I guess we need this because the default avatar icon has its own shadow included?

lp:~philip.scott/granite/Avatar updated
863. By Felipe Escoto

New widget: Avatar

Revision history for this message
Felipe Escoto (philip.scott) wrote :

I decided to go with just setting draw_theme_background as private since it's only used when setting the default icon from within the widget, and to avoid extra triggers of the draw method.

Revision history for this message
kay van der Zander (kay20) :
review: Approve (extra set eyes.)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'demo/GraniteDemo.vala'
2--- demo/GraniteDemo.vala 2015-08-30 10:10:29 +0000
3+++ demo/GraniteDemo.vala 2015-09-01 21:14:05 +0000
4@@ -104,8 +104,11 @@
5 home_button.hide ();
6 });
7
8+ var avatar = create_avatar ();
9+
10 headerbar.pack_start (home_button);
11 headerbar.pack_end (about_button);
12+ headerbar.pack_end (avatar);
13 window.set_titlebar (headerbar);
14 }
15
16@@ -274,6 +277,25 @@
17 });
18 }
19
20+ private Granite.Widgets.Avatar create_avatar () {
21+ var username = GLib.Environment.get_user_name ();
22+ var avatar = new Granite.Widgets.Avatar ();
23+ var iconfile = @"/var/lib/AccountsService/icons/$username";
24+
25+ avatar.valign = Gtk.Align.CENTER;
26+
27+ try {
28+ var pixbuf = new Gdk.Pixbuf.from_file (iconfile);
29+ avatar.pixbuf = pixbuf.scale_simple (24, 24, Gdk.InterpType.BILINEAR);
30+ avatar.set_tooltip_text ("Avatar widget: User image found");
31+ } catch (Error e) {
32+ avatar.show_default (24);
33+ avatar.set_tooltip_text ("Avatar widget: User image not found, using fallback");
34+ }
35+
36+ return avatar;
37+ }
38+
39 public static int main (string[] args) {
40 var application = new Granite.Demo ();
41 return application.run (args);
42
43=== modified file 'lib/CMakeLists.txt'
44--- lib/CMakeLists.txt 2015-08-27 10:10:08 +0000
45+++ lib/CMakeLists.txt 2015-09-01 21:14:05 +0000
46@@ -20,6 +20,7 @@
47 Services/IconFactory.vala
48 Services/SimpleCommand.vala
49 Widgets/AlertView.vala
50+ Widgets/Avatar.vala
51 Widgets/Utils.vala
52 Widgets/WrapLabel.vala
53 Widgets/AboutDialog.vala
54
55=== added file 'lib/Widgets/Avatar.vala'
56--- lib/Widgets/Avatar.vala 1970-01-01 00:00:00 +0000
57+++ lib/Widgets/Avatar.vala 2015-09-01 21:14:05 +0000
58@@ -0,0 +1,140 @@
59+/*
60+ * Copyright (C) 2015 Granite Developers (https://launchpad.net/granite)
61+ *
62+ * This program or library is free software; you can redistribute it
63+ * and/or modify it under the terms of the GNU Lesser General Public
64+ * License as published by the Free Software Foundation; either
65+ * version 3 of the License, or (at your option) any later version.
66+ *
67+ * This library is distributed in the hope that it will be useful,
68+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
69+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
70+ * Lesser General Public License for more details.
71+ *
72+ * You should have received a copy of the GNU Lesser General
73+ * Public License along with this library; if not, write to the
74+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
75+ * Boston, MA 02110-1301 USA.
76+ *
77+ * Authored by: Felipe Escoto <felescoto95@hotmail.com>, Rico Tzschichholz <ricotz@ubuntu.com>
78+ */
79+
80+/**
81+ * The Avatar widget allowes to theme & crop images with css BORDER_RADIUS property in the .avatar class.
82+ *
83+ */
84+public class Granite.Widgets.Avatar : Gtk.EventBox {
85+ private const string DEFAULT_ICON = "avatar-default";
86+ private const string DEFAULT_STYLE = "avatar";
87+ private const int EXTRA_MARGIN = 4;
88+ private bool draw_theme_background = true;
89+
90+ public Gdk.Pixbuf? pixbuf { get; set; }
91+
92+ /**
93+ * Makes new Avatar widget
94+ *
95+ */
96+ public Avatar () {
97+ }
98+
99+ /**
100+ * Creates a new Avatar from the speficied pixbuf
101+ *
102+ * @param pixbuf image to be used
103+ */
104+ public Avatar.from_pixbuf (Gdk.Pixbuf pixbuf) {
105+ Object (pixbuf: pixbuf);
106+ }
107+
108+ /**
109+ * Creates a new Avatar from the speficied filepath and icon size
110+ *
111+ * @param filepath image to be used
112+ * @param size to scale the image
113+ */
114+ public Avatar.from_file (string filepath, int icon_size) {
115+ try {
116+ pixbuf = new Gdk.Pixbuf.from_file_at_scale (filepath, icon_size, icon_size, true);
117+ } catch (Error e) {
118+ show_default (icon_size);
119+ }
120+ }
121+
122+ /**
123+ * Creates a new Avatar with the default icon from theme without applying the css style
124+ *
125+ * @param icon_size size of the icon to be loaded
126+ */
127+ public Avatar.with_default_icon (int icon_size) {
128+ show_default (icon_size);
129+ }
130+
131+ construct {
132+ valign = Gtk.Align.CENTER;
133+ halign = Gtk.Align.CENTER;
134+ visible_window = false;
135+ get_style_context ().add_class (DEFAULT_STYLE);
136+
137+ notify["pixbuf"].connect (refresh_size_request);
138+ }
139+
140+ ~Avatar () {
141+ notify["pixbuf"].disconnect (refresh_size_request);
142+ }
143+
144+ private void refresh_size_request () {
145+ if (pixbuf != null) {
146+ set_size_request (pixbuf.width + EXTRA_MARGIN * 2, pixbuf.height + EXTRA_MARGIN * 2);
147+ draw_theme_background = true;
148+ } else {
149+ set_size_request (0, 0);
150+ }
151+
152+ queue_draw ();
153+ }
154+
155+ /**
156+ * Load the default avatar icon from theme into the widget without applying the css style
157+ *
158+ * @param icon_size size of the icon to be loaded
159+ */
160+ public void show_default (int icon_size) {
161+ Gtk.IconTheme icon_theme = Gtk.IconTheme.get_default ();
162+ try {
163+ pixbuf = icon_theme.load_icon (DEFAULT_ICON, icon_size, 0);
164+ } catch (Error e) {
165+ stderr.printf ("Error setting default avatar icon: %s ", e.message);
166+ }
167+
168+ draw_theme_background = false;
169+ }
170+
171+ public override bool draw (Cairo.Context cr) {
172+ if (pixbuf == null) {
173+ return base.draw (cr);
174+ }
175+
176+ unowned Gtk.StyleContext style_context = get_style_context ();
177+ var width = get_allocated_width () - EXTRA_MARGIN * 2;
178+ var height = get_allocated_height () - EXTRA_MARGIN * 2;
179+
180+ if (draw_theme_background) {
181+ var border_radius = style_context.get_property (Gtk.STYLE_PROPERTY_BORDER_RADIUS, Gtk.StateFlags.NORMAL).get_int ();
182+ var crop_radius = int.min (width / 2, border_radius * width / 100);
183+
184+ Granite.Drawing.Utilities.cairo_rounded_rectangle (cr, EXTRA_MARGIN, EXTRA_MARGIN, width, height, crop_radius);
185+ Gdk.cairo_set_source_pixbuf (cr, pixbuf, EXTRA_MARGIN, EXTRA_MARGIN);
186+ cr.fill_preserve ();
187+ style_context.render_background (cr, EXTRA_MARGIN, EXTRA_MARGIN, width, height);
188+ style_context.render_frame (cr, EXTRA_MARGIN, EXTRA_MARGIN, width, height);
189+
190+ } else {
191+ Granite.Drawing.Utilities.cairo_rounded_rectangle (cr, EXTRA_MARGIN, EXTRA_MARGIN, width, height, 0);
192+ Gdk.cairo_set_source_pixbuf (cr, pixbuf, EXTRA_MARGIN, EXTRA_MARGIN);
193+ cr.fill_preserve ();
194+ }
195+
196+ return Gdk.EVENT_STOP;
197+ }
198+}

Subscribers

People subscribed via source and target branches