@@ -14,86 +14,101 @@ const Params = imports.misc.params;
1414var AVATAR_ICON_SIZE = 64 ;
1515
1616var Avatar = GObject . registerClass (
17- class Avatar extends St . Bin {
17+ class Avatar extends Clutter . Actor {
1818 _init ( user , params ) {
1919 let themeContext = St . ThemeContext . get_for_stage ( global . stage ) ;
2020 params = Params . parse ( params , {
2121 styleClass : 'user-icon' ,
2222 reactive : true ,
23- track_hover : true ,
2423 iconSize : AVATAR_ICON_SIZE ,
2524 } ) ;
2625
2726 super . _init ( {
28- style_class : params . styleClass ,
27+ layout_manager : new Clutter . BinLayout ( ) ,
2928 reactive : params . reactive ,
3029 width : params . iconSize * themeContext . scaleFactor ,
3130 height : params . iconSize * themeContext . scaleFactor ,
3231 } ) ;
3332
34- this . connect ( 'notify::hover' , this . _onHoverChanged . bind ( this ) ) ;
35-
36- this . set_important ( true ) ;
33+ this . _styleClass = params . styleClass ;
3734 this . _iconSize = params . iconSize ;
3835 this . _user = user ;
36+ this . _iconFile = null ;
37+ this . _child = null ;
3938
40- this . bind_property ( 'reactive' , this , 'track-hover' ,
41- GObject . BindingFlags . SYNC_CREATE ) ;
4239 this . bind_property ( 'reactive' , this , 'can-focus' ,
4340 GObject . BindingFlags . SYNC_CREATE ) ;
4441
4542 // Monitor the scaling factor to make sure we recreate the avatar when needed.
4643 this . _scaleFactorChangeId =
4744 themeContext . connect ( 'notify::scale-factor' , this . update . bind ( this ) ) ;
4845
46+ // Monitor for changes to the icon file on disk
47+ this . _textureCache = St . TextureCache . get_default ( ) ;
48+ this . _textureFileChangedId =
49+ this . _textureCache . connect ( 'texture-file-changed' , this . _onTextureFileChanged . bind ( this ) ) ;
50+
4951 this . connect ( 'destroy' , this . _onDestroy . bind ( this ) ) ;
5052 }
5153
5254 _onHoverChanged ( ) {
53- if ( this . hover ) {
54- if ( this . child ) {
55- this . child . add_style_class_name ( 'highlighted' ) ;
56- }
57- else {
55+ if ( ! this . _child )
56+ return ;
57+
58+ if ( this . _child . hover ) {
59+ if ( this . _iconFile ) {
5860 let effect = new Clutter . BrightnessContrastEffect ( ) ;
5961 effect . set_brightness ( 0.2 ) ;
6062 effect . set_contrast ( 0.3 ) ;
61- this . add_effect ( effect ) ;
63+ this . _child . add_effect ( effect ) ;
64+ } else {
65+ this . _child . add_style_class_name ( 'highlighted' ) ;
6266 }
63- this . add_accessible_state ( Atk . StateType . FOCUSED ) ;
67+ this . _child . add_accessible_state ( Atk . StateType . FOCUSED ) ;
6468 } else {
65- if ( this . child ) {
66- this . child . remove_style_class_name ( 'highlighted' ) ;
69+ if ( this . _iconFile ) {
70+ this . _child . clear_effects ( ) ;
71+ } else {
72+ this . _child . remove_style_class_name ( 'highlighted' ) ;
6773 }
68- else {
69- this . clear_effects ( ) ;
70- }
71- this . remove_accessible_state ( Atk . StateType . FOCUSED ) ;
74+ this . _child . remove_accessible_state ( Atk . StateType . FOCUSED ) ;
7275 }
7376 }
7477
75- vfunc_style_changed ( ) {
76- super . vfunc_style_changed ( ) ;
77-
78- let node = this . get_theme_node ( ) ;
78+ _onStyleChanged ( ) {
79+ let node = this . _child . get_theme_node ( ) ;
7980 let [ found , iconSize ] = node . lookup_length ( 'icon-size' , false ) ;
8081
8182 if ( ! found )
8283 return ;
8384
8485 let themeContext = St . ThemeContext . get_for_stage ( global . stage ) ;
8586
86- // node.lookup_length() returns a scaled value, but we
87- // need unscaled
88- this . _iconSize = iconSize / themeContext . scaleFactor ;
89- this . update ( ) ;
87+ // node.lookup_length() returns a scaled value, but we need unscaled
88+ let newIconSize = iconSize / themeContext . scaleFactor ;
89+
90+ if ( newIconSize !== this . _iconSize ) {
91+ this . _iconSize = newIconSize ;
92+ this . update ( ) ;
93+ }
9094 }
9195
9296 _onDestroy ( ) {
9397 if ( this . _scaleFactorChangeId ) {
9498 let themeContext = St . ThemeContext . get_for_stage ( global . stage ) ;
9599 themeContext . disconnect ( this . _scaleFactorChangeId ) ;
96- delete this . _scaleFactorChangeId ;
100+ this . _scaleFactorChangeId = 0 ;
101+ }
102+
103+ if ( this . _textureFileChangedId ) {
104+ this . _textureCache . disconnect ( this . _textureFileChangedId ) ;
105+ this . _textureFileChangedId = 0 ;
106+ }
107+ }
108+
109+ _onTextureFileChanged ( cache , file ) {
110+ if ( this . _iconFile && file . get_path ( ) === this . _iconFile ) {
111+ this . update ( ) ;
97112 }
98113 }
99114
@@ -114,24 +129,49 @@ class Avatar extends St.Bin {
114129 iconFile = null ;
115130 }
116131
132+ this . _iconFile = iconFile ;
133+
117134 let { scaleFactor } = St . ThemeContext . get_for_stage ( global . stage ) ;
118135 this . set_size (
119136 this . _iconSize * scaleFactor ,
120137 this . _iconSize * scaleFactor ) ;
121138
139+ // Remove old child
140+ if ( this . _child ) {
141+ this . _child . destroy ( ) ;
142+ this . _child = null ;
143+ }
144+
145+ let size = this . _iconSize * scaleFactor ;
146+
122147 if ( iconFile ) {
123- this . child = null ;
124- this . add_style_class_name ( 'user-avatar' ) ;
125- this . style = `
126- background-image: url("${ iconFile } ");
127- background-size: cover;` ;
148+ this . _child = new St . Bin ( {
149+ style_class : `${ this . _styleClass } user-avatar` ,
150+ reactive : this . reactive ,
151+ track_hover : this . reactive ,
152+ width : size ,
153+ height : size ,
154+ style : `background-image: url("${ iconFile } "); background-size: cover;` ,
155+ } ) ;
128156 } else {
129- this . style = null ;
130- this . child = new St . Icon ( {
131- icon_name : 'xsi-avatar-default-symbolic' ,
132- icon_size : this . _iconSize ,
157+ this . _child = new St . Bin ( {
158+ style_class : this . _styleClass ,
159+ reactive : this . reactive ,
160+ track_hover : this . reactive ,
161+ width : size ,
162+ height : size ,
163+ child : new St . Icon ( {
164+ icon_name : 'xsi-avatar-default-symbolic' ,
165+ icon_size : this . _iconSize ,
166+ } ) ,
133167 } ) ;
134168 }
169+
170+ this . _child . set_important ( true ) ;
171+ this . _child . connect ( 'notify::hover' , this . _onHoverChanged . bind ( this ) ) ;
172+ this . _child . connect ( 'style-changed' , this . _onStyleChanged . bind ( this ) ) ;
173+
174+ this . add_child ( this . _child ) ;
135175 }
136176} ) ;
137177
@@ -155,7 +195,7 @@ class UserWidget extends St.BoxLayout {
155195
156196 this . _avatar = new Avatar ( user ) ;
157197 this . _avatar . x_align = Clutter . ActorAlign . CENTER ;
158- this . add ( this . _avatar , { x_fill : false } ) ;
198+ this . add_child ( this . _avatar ) ;
159199
160200 this . _label = new St . Label ( { style_class : 'user-widget-label' } ) ;
161201 this . _label . y_align = Clutter . ActorAlign . CENTER ;
0 commit comments