1
# -*- coding: utf-8 -*-
3
# This file is part of emesene.
5
# Emesene is free software; you can redistribute it and/or modify
6
# it under the terms of the GNU General Public License as published by
7
# the Free Software Foundation; either version 2 of the License, or
8
# (at your option) any later version.
10
# emesene is distributed in the hope that it will be useful,
11
# but WITHOUT ANY WARRANTY; without even the implied warranty of
12
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
# GNU General Public License for more details.
15
# You should have received a copy of the GNU General Public License
16
# along with emesene; if not, write to the Free Software
17
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
24
class FancyAvatarRenderer ( gtk.GenericCellRenderer ):
25
"""Renderer for avatar """
28
'pixbuf': (gtk.gdk.Pixbuf, 'Pixbuf','Pixbuf',gobject.PARAM_READWRITE),
29
'blocked': (bool , 'User Blocked status', '',False, gobject.PARAM_READWRITE),
30
'dimention' : (gobject.TYPE_INT, 'cell dimentions', 'height width of cell', 0, 96, 32, gobject.PARAM_READWRITE),
31
'status': (str, 'Contact status', '','FLN', gobject.PARAM_READWRITE),
32
'radius_factor' : (gobject.TYPE_FLOAT,'radius of pixbuf',
33
'0.0 to 0.5 with 0.1 = 10% of dimention',0.0, 0.5,0.11, gobject.PARAM_READWRITE),
36
def __init__(self, controller, cellDimention = 32, cellRadius = 0.11):
37
#gobject.GObject.__init__(self)
38
self.__gobject_init__()
42
self._dimention = cellDimention
43
self._radius_factor = cellRadius
45
self.set_property('xpad', 1)
46
self.set_property('ypad', 1)
48
self._theme = controller.theme
49
self._config = controller.config
51
#set up information of statusTransformation
52
self.__set_transformation(self._config.user['statusTransformation'])
54
self.transId = self._config.connect('change::statusTransformation', \
55
self.__transformation_callback)
58
self._config.disconnect(self.transId)
59
gtk.GenericCellRenderer.destroy(self)
61
def __set_transformation(self, setting):
62
transformation = setting.split('|')
63
if 'pixelate' in transformation: self._pixalated = True
64
else: self._pixalated = False
65
if 'corner' in transformation: self._corner = True
66
else: self._corner = False
67
if 'alpha' in transformation: self._alpha_status = True
68
else: self._alpha_status = False
69
if 'mini' in transformation: self._mini = True
70
else: self._mini = False
72
def __transformation_callback(self, config, newvalue, oldvalue):
73
self.__set_transformation(newvalue)
75
def do_get_property(self, property):
76
if property.name == 'pixbuf':
78
elif property.name == 'dimention':
79
return self._dimention
80
elif property.name == 'radius-factor':
81
return self._radius_factor
82
elif property.name == 'blocked':
84
elif property.name == 'status':
87
raise AttributeError, 'unknown property %s' % property.name
89
def do_set_property(self, property, value):
90
if property.name == 'pixbuf':
92
elif property.name == 'dimention':
93
self._dimention = value
94
elif property.name == 'radius-factor':
95
self._radius_factor = value
96
elif property.name == 'blocked':
98
elif property.name == 'status':
101
raise AttributeError, 'unknown property %s' % property.name
103
def on_get_size( self, widget, cell_area=None ):
104
xpad,ypad = self.get_property('xpad'), self.get_property('ypad')
105
if self._dimention >= 32: width = self._dimention
106
elif self._mini: width = self._dimention
107
elif self._corner: width = self._dimention * 2
108
else: width = self._dimention
109
height = self._dimention + (ypad *2)
110
return ( 0, 0, width, height)
112
def on_render( self, window, widget, background_area, cell_area, expose_area, flags ):
113
avatar = self._pixbuf
117
if self._pixalated: avatar = __getPixalate(self._pixbuf)
118
if self._corner: overlay = self.__getOverlay()
119
if self._alpha_status: alpha = self.__getAlpha()
121
xpad,ypad = self.get_property('xpad'), self.get_property('ypad')
122
cell_x, cell_y, cell_width, cell_height = cell_area
123
ctx = window.cairo_create()
124
ctx.translate(cell_x,cell_y)
126
if not avatar == None:
127
self.__drawScalePixbuf( ctx,avatar,cell_width - self._dimention,ypad ,self._dimention,
128
gtk.ANCHOR_CENTER, self._radius_factor, alpha)
130
if not overlay == None:
131
if self._dimention >= 32 :
132
self.__drawScalePixbuf( ctx,overlay,cell_width - 16, ypad + self._dimention - 16,16, position = gtk.ANCHOR_SW)
134
self.__drawScalePixbuf( ctx,overlay,cell_width - 8, ypad + self._dimention - 8,8, position = gtk.ANCHOR_SW)
136
self.__drawScalePixbuf( ctx,overlay,0,ypad ,16)
138
def __getAlpha(self):
139
if self._status in ['IDL', 'FLN']: return 0.75
142
def __getOverlay(self):
144
return self._theme.getImage('status-blocked')
145
elif self._status in ['AWY','BRB','LUN','IDL' ] :
146
return self._theme.getImage('status-away')
147
elif self._status in ['BSY','PHN' ] :
148
return self._theme.getImage('status-busy')
152
def __getPixalate( self, pixbuf ):
153
pixbuf_to_modify = pixbuf.copy()
154
if not self._status == 'NLN':
155
if contact.status == 'BSY':
156
pixbuf_to_modify.saturate_and_pixelate(pixbuf,1.0, True)
158
pixbuf_to_modify.saturate_and_pixelate(pixbuf,0.1, False)
159
return pixbuf_to_modify
162
def __drawScalePixbuf(self, ctx, pixbuf, x,y , dimention, position = gtk.ANCHOR_CENTER, radius = 0, alpha = 1 ):
165
ctx.set_antialias(cairo.ANTIALIAS_SUBPIXEL)
168
pix_width = pixbuf.get_width()
169
pix_height = pixbuf.get_height()
170
if (pix_width > dimention) or (pix_height > dimention):
171
scale_factor = float(dimention) / max (pix_width,pix_height)
174
scale_width = pix_width* scale_factor
175
scale_height = pix_height* scale_factor
178
if position in [gtk.ANCHOR_NW,gtk.ANCHOR_W,gtk.ANCHOR_SW] : x = 0
179
elif position in [gtk.ANCHOR_N,gtk.ANCHOR_CENTER,gtk.ANCHOR_S] : x = (dimention/2) - (scale_width/2)
180
else: x = dimention - scale_width
181
if position in [gtk.ANCHOR_NW,gtk.ANCHOR_N,gtk.ANCHOR_NE] : y = 0
182
elif position in [gtk.ANCHOR_E,gtk.ANCHOR_CENTER,gtk.ANCHOR_W] : y = (dimention/2) - (scale_height/2)
183
else: y = dimention - scale_height
187
self.__roundedrecMoonlight(ctx,0,0,scale_width,scale_height, self._dimention * radius)
189
ctx.scale(scale_factor,scale_factor)
190
ctx.set_source_pixbuf(pixbuf,0,0)
191
ctx.paint_with_alpha(alpha)
194
def __roundedrecMoonlight(self, cr,x,y,w,h,radius=5):
195
# http://cairographics.org/cookbook/roundedrectangles/
196
# modified from mono moonlight aka mono silverlight
197
# test limits (without using multiplications)
198
# http://graphics.stanford.edu/courses/cs248-98-fall/Final/q1.html
200
ARC_TO_BEZIER = 0.55228475
201
if radius > (min(w,h)/2):
202
radius = (min(w,h)/2)
203
#approximate (quite close) the arc using a bezier curve
204
c = ARC_TO_BEZIER * radius
207
cr.move_to ( x + radius, y)
208
cr.rel_line_to ( w - 2 * radius, 0.0)
209
cr.rel_curve_to ( c, 0.0, radius, c, radius, radius)
210
cr.rel_line_to ( 0, h - 2 * radius)
211
cr.rel_curve_to ( 0.0, c, c - radius, radius, -radius, radius)
212
cr.rel_line_to ( -w + 2 * radius, 0)
213
cr.rel_curve_to ( -c, 0, -radius, -c, -radius, -radius)
214
cr.rel_line_to (0, -h + 2 * radius)
215
cr.rel_curve_to (0.0, -c, radius - c, -radius, radius, -radius)
218
gobject.type_register( FancyAvatarRenderer )