Make CanvasIcon use IconBuffer. Change the API to use

a separate property for icon_name and file_name.
This commit is contained in:
Marco Pesenti Gritti 2007-08-26 14:16:09 +02:00
parent f44c340b3a
commit 98157bbccb
13 changed files with 102 additions and 366 deletions

View File

@ -26,7 +26,7 @@ class ColorPicker(hippo.CanvasBox, hippo.CanvasItem):
self.props.orientation = hippo.ORIENTATION_HORIZONTAL self.props.orientation = hippo.ORIENTATION_HORIZONTAL
self._xo = CanvasIcon(size=style.XLARGE_ICON_SIZE, self._xo = CanvasIcon(size=style.XLARGE_ICON_SIZE,
icon_name='theme:computer-xo') icon_name='computer-xo')
self._set_random_colors() self._set_random_colors()
self._xo.connect('activated', self._xo_activated_cb) self._xo.connect('activated', self._xo_activated_cb)
self.append(self._xo) self.append(self._xo)

View File

@ -20,7 +20,7 @@ from view.BuddyMenu import BuddyMenu
class BuddyIcon(CanvasIcon): class BuddyIcon(CanvasIcon):
def __init__(self, shell, buddy): def __init__(self, shell, buddy):
CanvasIcon.__init__(self, icon_name='theme:computer-xo', CanvasIcon.__init__(self, icon_name='computer-xo',
xo_color=buddy.get_color()) xo_color=buddy.get_color())
self._shell = shell self._shell = shell

View File

@ -47,7 +47,7 @@ class DeviceView(CanvasIcon):
# Update palette # Update palette
if self._model.props.charging: if self._model.props.charging:
status = _STATUS_CHARGING status = _STATUS_CHARGING
self.props.badge_name = 'theme:badge-charging' self.props.badge_name = 'badge-charging'
elif self._model.props.discharging: elif self._model.props.discharging:
status = _STATUS_DISCHARGING status = _STATUS_DISCHARGING
self.props.badge_name = None self.props.badge_name = None

View File

@ -22,7 +22,7 @@ from model.devices import device
class DeviceView(canvasicon.CanvasIcon): class DeviceView(canvasicon.CanvasIcon):
def __init__(self, model): def __init__(self, model):
canvasicon.CanvasIcon.__init__(self, size=style.MEDIUM_ICON_SIZE, canvasicon.CanvasIcon.__init__(self, size=style.MEDIUM_ICON_SIZE,
icon_name='theme:network-mesh') icon_name='network-mesh')
self._model = model self._model = model
model.connect('notify::state', self._state_changed_cb) model.connect('notify::state', self._state_changed_cb)
@ -35,11 +35,11 @@ class DeviceView(canvasicon.CanvasIcon):
# FIXME Change icon colors once we have real icons # FIXME Change icon colors once we have real icons
state = self._model.props.state state = self._model.props.state
if state == device.STATE_ACTIVATING: if state == device.STATE_ACTIVATING:
self.props.fill_color = style.COLOR_INACTIVE_FILL self.props.fill_color = style.COLOR_INACTIVE_FILL.get_svg()
self.props.stroke_color = style.COLOR_INACTIVE_STROKE self.props.stroke_color = style.COLOR_INACTIVE_STROKE.get_svg()
elif state == device.STATE_ACTIVATED: elif state == device.STATE_ACTIVATED:
self.props.fill_color = None self.props.fill_color = None
self.props.stroke_color = None self.props.stroke_color = None
elif state == device.STATE_INACTIVE: elif state == device.STATE_INACTIVE:
self.props.fill_color = style.COLOR_INACTIVE_FILL self.props.fill_color = style.COLOR_INACTIVE_FILL.get_svg()
self.props.stroke_color = style.COLOR_INACTIVE_STROKE self.props.stroke_color = style.COLOR_INACTIVE_STROKE.get_svg()

View File

@ -19,4 +19,4 @@ from view.devices import deviceview
class DeviceView(deviceview.DeviceView): class DeviceView(deviceview.DeviceView):
def __init__(self, model): def __init__(self, model):
deviceview.DeviceView.__init__(self, model) deviceview.DeviceView.__init__(self, model)
self.props.icon_name = 'theme:network-wired' self.props.icon_name = 'network-wired'

View File

@ -18,7 +18,6 @@
from sugar.graphics.icon import get_icon_state from sugar.graphics.icon import get_icon_state
from sugar.graphics.icon import CanvasIcon from sugar.graphics.icon import CanvasIcon
from sugar.graphics import style from sugar.graphics import style
from sugar.graphics import style
from model.devices.network import wireless from model.devices.network import wireless
from model.devices import device from model.devices import device
@ -56,11 +55,11 @@ class DeviceView(CanvasIcon):
# FIXME Change icon colors once we have real icons # FIXME Change icon colors once we have real icons
state = self._model.props.state state = self._model.props.state
if state == device.STATE_ACTIVATING: if state == device.STATE_ACTIVATING:
self.props.fill_color = style.COLOR_INACTIVE_FILL self.props.fill_color = style.COLOR_INACTIVE_FILL.get_svg()
self.props.stroke_color = style.COLOR_INACTIVE_STROKE self.props.stroke_color = style.COLOR_INACTIVE_STROKE.get_svg()
elif state == device.STATE_ACTIVATED: elif state == device.STATE_ACTIVATED:
self.props.fill_color = None self.props.fill_color = None
self.props.stroke_color = None self.props.stroke_color = None
elif state == device.STATE_INACTIVE: elif state == device.STATE_INACTIVE:
self.props.fill_color = style.COLOR_INACTIVE_FILL self.props.fill_color = style.COLOR_INACTIVE_FILL.get_svg()
self.props.stroke_color = style.COLOR_INACTIVE_STROKE self.props.stroke_color = style.COLOR_INACTIVE_STROKE.get_svg()

View File

@ -28,9 +28,9 @@ from frameinvoker import FrameCanvasInvoker
class ActivityButton(IconButton): class ActivityButton(IconButton):
def __init__(self, activity_info): def __init__(self, activity_info):
IconButton.__init__(self, icon_name=activity_info.icon, IconButton.__init__(self, file_name=activity_info.icon,
stroke_color=style.COLOR_WHITE, stroke_color=style.COLOR_WHITE.get_svg(),
fill_color=style.COLOR_TRANSPARENT) fill_color=style.COLOR_TRANSPARENT.get_svg())
palette = Palette(activity_info.name) palette = Palette(activity_info.name)
palette.props.invoker = FrameCanvasInvoker(self) palette.props.invoker = FrameCanvasInvoker(self)

View File

@ -30,7 +30,7 @@ class ZoomBox(hippo.CanvasBox):
self._shell = shell self._shell = shell
icon = IconButton(icon_name='theme:zoom-mesh') icon = IconButton(icon_name='zoom-mesh')
icon.connect('activated', icon.connect('activated',
self._level_clicked_cb, self._level_clicked_cb,
ShellModel.ZOOM_MESH) ShellModel.ZOOM_MESH)
@ -41,7 +41,7 @@ class ZoomBox(hippo.CanvasBox):
palette.set_group_id('frame') palette.set_group_id('frame')
icon.set_palette(palette) icon.set_palette(palette)
icon = IconButton(icon_name='theme:zoom-friends') icon = IconButton(icon_name='zoom-friends')
icon.connect('activated', icon.connect('activated',
self._level_clicked_cb, self._level_clicked_cb,
ShellModel.ZOOM_FRIENDS) ShellModel.ZOOM_FRIENDS)
@ -52,7 +52,7 @@ class ZoomBox(hippo.CanvasBox):
palette.set_group_id('frame') palette.set_group_id('frame')
icon.set_palette(palette) icon.set_palette(palette)
icon = IconButton(icon_name='theme:zoom-home') icon = IconButton(icon_name='zoom-home')
icon.connect('activated', icon.connect('activated',
self._level_clicked_cb, self._level_clicked_cb,
ShellModel.ZOOM_HOME) ShellModel.ZOOM_HOME)
@ -63,7 +63,7 @@ class ZoomBox(hippo.CanvasBox):
palette.set_group_id('frame') palette.set_group_id('frame')
icon.set_palette(palette) icon.set_palette(palette)
icon = IconButton(icon_name='theme:zoom-activity') icon = IconButton(icon_name='zoom-activity')
icon.connect('activated', icon.connect('activated',
self._level_clicked_cb, self._level_clicked_cb,
ShellModel.ZOOM_ACTIVITY) ShellModel.ZOOM_ACTIVITY)

View File

@ -94,28 +94,28 @@ class AccessPointView(PulsingIcon):
if self._model.props.state == accesspointmodel.STATE_CONNECTING: if self._model.props.state == accesspointmodel.STATE_CONNECTING:
self.props.pulse_time = 1.0 self.props.pulse_time = 1.0
self.props.colors = [ self.props.colors = [
[ style.Color(self._device_stroke), [ style.Color(self._device_stroke).get_svg(),
style.Color(self._device_fill) ], style.Color(self._device_fill).get_svg() ],
[ style.Color(self._device_stroke), [ style.Color(self._device_stroke).get_svg(),
style.Color('#e2e2e2') ] '#e2e2e2' ]
] ]
elif self._model.props.state == accesspointmodel.STATE_CONNECTED: elif self._model.props.state == accesspointmodel.STATE_CONNECTED:
self.props.pulse_time = 2.0 self.props.pulse_time = 2.0
self.props.colors = [ self.props.colors = [
[ style.Color(self._device_stroke), [ style.Color(self._device_stroke).get_svg(),
style.Color(self._device_fill) ], style.Color(self._device_fill).get_svg() ],
[ style.Color('#ffffff'), [ '#ffffff',
style.Color(self._device_fill) ] style.Color(self._device_fill).get_svg() ]
] ]
elif self._model.props.state == accesspointmodel.STATE_NOTCONNECTED: elif self._model.props.state == accesspointmodel.STATE_NOTCONNECTED:
self.props.pulse_time = 0.0 self.props.pulse_time = 0.0
self.props.colors = [ self.props.colors = [
[ style.Color(self._device_stroke), [ style.Color(self._device_stroke).get_svg(),
style.Color(self._device_fill) ] style.Color(self._device_fill).get_svg() ]
] ]
_MESH_ICON_NAME = 'theme:network-mesh' _MESH_ICON_NAME = 'network-mesh'
class MeshDeviceView(PulsingIcon): class MeshDeviceView(PulsingIcon):
def __init__(self, nm_device): def __init__(self, nm_device):

View File

@ -20,5 +20,5 @@ from sugar import profile
class MyIcon(CanvasIcon): class MyIcon(CanvasIcon):
def __init__(self, size): def __init__(self, size):
CanvasIcon.__init__(self, size=size, CanvasIcon.__init__(self, size=size,
icon_name='theme:computer-xo', icon_name='computer-xo',
xo_color=profile.get_color()) xo_color=profile.get_color())

View File

@ -73,8 +73,8 @@ class ActivityIcon(CanvasIcon):
self._level = self._level_max self._level = self._level_max
color = self._icon_colors[self._level] color = self._icon_colors[self._level]
CanvasIcon.__init__(self, icon_name=icon_name, xo_color=color, CanvasIcon.__init__(self, file_name=icon_name, xo_color=color,
size=style.MEDIUM_ICON_SIZE, cache=True) size=style.MEDIUM_ICON_SIZE)
self._activity = activity self._activity = activity
self._pulse_id = 0 self._pulse_id = 0
@ -119,8 +119,6 @@ class ActivityIcon(CanvasIcon):
if self._pulse_id: if self._pulse_id:
gobject.source_remove(self._pulse_id) gobject.source_remove(self._pulse_id)
self._pulse_id = 0 self._pulse_id = 0
# dispose of all rendered icons from launch feedback
self._clear_buffers()
def _compute_icon_colors(self): def _compute_icon_colors(self):
_LEVEL_MAX = 1.6 _LEVEL_MAX = 1.6

View File

@ -231,11 +231,8 @@ class _IconBuffer(object):
def get_surface(self): def get_surface(self):
cache_key = self._get_cache_key() cache_key = self._get_cache_key()
if self._surface_cache.has_key(cache_key): if self._surface_cache.has_key(cache_key):
print cache_key
return self._surface_cache[cache_key] return self._surface_cache[cache_key]
print 'gah'
icon_info = self._get_icon_info() icon_info = self._get_icon_info()
if icon_info.file_name is None: if icon_info.file_name is None:
return None return None
@ -290,7 +287,6 @@ class _IconBuffer(object):
def set_cache_size(self, cache_size): def set_cache_size(self, cache_size):
while len(self._surface_cache) > cache_size: while len(self._surface_cache) > cache_size:
print len(self._surface_cache)
self._surface_cache.popitem() self._surface_cache.popitem()
self._cache_size self._cache_size
@ -389,116 +385,12 @@ class Icon(gtk.Image):
else: else:
return gtk.Image.do_get_property(self, pspec) return gtk.Image.do_get_property(self, pspec)
_ICON_REQUEST_SIZE = 50
class _IconCacheIcon:
def __init__(self, name, fill_color, stroke_color, now):
self.last_used = now
self.usage_count = 1
self.badge_x = 1.0 - _BADGE_SIZE / 2
self.badge_y = 1.0 - _BADGE_SIZE / 2
if name[0:6] == "theme:":
info = gtk.icon_theme_get_default().lookup_icon(
name[6:], _ICON_REQUEST_SIZE, 0)
if not info:
raise ValueError("Icon '" + name + "' not found.")
fname = info.get_filename()
attach_points = info.get_attach_points()
if attach_points is not None:
self.badge_x = float(attach_points[0][0]) / _ICON_REQUEST_SIZE
self.badge_y = float(attach_points[0][1]) / _ICON_REQUEST_SIZE
del info
else:
fname = name
self.handle = self._read_icon_data(fname, fill_color, stroke_color)
def _read_icon_data(self, filename, fill_color, stroke_color):
icon_file = open(filename, 'r')
data = icon_file.read()
icon_file.close()
if fill_color:
entity = '<!ENTITY fill_color "%s">' % fill_color
data = re.sub('<!ENTITY fill_color .*>', entity, data)
if stroke_color:
entity = '<!ENTITY stroke_color "%s">' % stroke_color
data = re.sub('<!ENTITY stroke_color .*>', entity, data)
self.data_size = len(data)
return rsvg.Handle(data=data)
class _IconCache:
_CACHE_MAX = 50000 # in bytes
def __init__(self):
self._icons = {}
self._cache_size = 0
def _cache_cleanup(self, key, now):
while self._cache_size > self._CACHE_MAX:
evict_key = None
oldest_key = None
oldest_time = now
for icon_key, icon in self._icons.items():
# Don't evict the icon we are about to use if it's in the cache
if icon_key == key:
continue
# evict large icons first
if icon.data_size > self._CACHE_MAX:
evict_key = icon_key
break
# evict older icons next; those used over 2 minutes ago
if icon.last_used < now - 120:
evict_key = icon_key
break
# otherwise, evict the oldest
if oldest_time > icon.last_used:
oldest_time = icon.last_used
oldest_key = icon_key
# If there's nothing specific to evict, try evicting
# the oldest thing
if not evict_key:
if not oldest_key:
break
evict_key = oldest_key
self._cache_size -= self._icons[evict_key].data_size
del self._icons[evict_key]
def get_icon(self, name, fill_color, stroke_color):
if not name:
return None
if fill_color or stroke_color:
key = (name, fill_color, stroke_color)
else:
key = name
# If we're over the cache limit, evict something from the cache
now = time.time()
self._cache_cleanup(key, now)
if self._icons.has_key(key):
icon = self._icons[key]
icon.usage_count += 1
icon.last_used = now
else:
icon = _IconCacheIcon(name, fill_color, stroke_color, now)
self._icons[key] = icon
self._cache_size += icon.data_size
return icon
class CanvasIcon(hippo.CanvasBox, hippo.CanvasItem): class CanvasIcon(hippo.CanvasBox, hippo.CanvasItem):
__gtype_name__ = 'CanvasIcon' __gtype_name__ = 'CanvasIcon'
__gproperties__ = { __gproperties__ = {
'file-name' : (str, None, None, None,
gobject.PARAM_READWRITE),
'icon-name' : (str, None, None, None, 'icon-name' : (str, None, None, None,
gobject.PARAM_READWRITE), gobject.PARAM_READWRITE),
'xo-color' : (object, None, None, 'xo-color' : (object, None, None,
@ -509,263 +401,110 @@ class CanvasIcon(hippo.CanvasBox, hippo.CanvasItem):
gobject.PARAM_READWRITE), gobject.PARAM_READWRITE),
'size' : (int, None, None, 0, 1024, 0, 'size' : (int, None, None, 0, 1024, 0,
gobject.PARAM_READWRITE), gobject.PARAM_READWRITE),
'scale' : (int, None, None, 0, 1024, 0, 'scale' : (float, None, None, -1024.0, 1024.0, 1.0,
gobject.PARAM_READWRITE), gobject.PARAM_READWRITE),
'cache' : (bool, None, None, False, 'cache_size' : (int, None, None, 0, 1024, 0,
gobject.PARAM_READWRITE),
'active' : (bool, None, None, True,
gobject.PARAM_READWRITE), gobject.PARAM_READWRITE),
'badge-name' : (str, None, None, None, 'badge-name' : (str, None, None, None,
gobject.PARAM_READWRITE) gobject.PARAM_READWRITE)
} }
_cache = _IconCache()
def __init__(self, **kwargs): def __init__(self, **kwargs):
self._buffers = {} self._buffer = _IconBuffer()
self._cur_buffer = None
self._size = 0
self._scale = 0
self._fill_color = None
self._stroke_color = None
self._icon_name = None
self._cache = False
self._icon = None
self._active = True
self._palette = None
self._badge_name = None
self._badge_icon = None
hippo.CanvasBox.__init__(self, **kwargs) hippo.CanvasBox.__init__(self, **kwargs)
self.connect_after('motion-notify-event', self._motion_notify_event_cb) self._palette = None
def _clear_buffers(self):
icon_key = self._get_current_buffer_key(self._icon_name)
badge_key = None
if self._badge_name:
badge_key = self._get_current_buffer_key(self._badge_name)
for key in self._buffers.keys():
if key != icon_key:
if not badge_key or (key != badge_key):
del self._buffers[key]
self._buffers = {}
def do_set_property(self, pspec, value): def do_set_property(self, pspec, value):
if pspec.name == 'icon-name': if pspec.name == 'file-name':
if self._icon_name != value and not self._cache: self._buffer.file_name = value
self._clear_buffers() self._buffer.invalidate()
self._icon_name = value self.emit_paint_needed(0, 0, -1, -1)
self._icon = None elif pspec.name == 'icon-name':
self._buffer.icon_name = value
self._buffer.invalidate()
self.emit_paint_needed(0, 0, -1, -1) self.emit_paint_needed(0, 0, -1, -1)
elif pspec.name == 'xo-color': elif pspec.name == 'xo-color':
self.props.fill_color = style.Color(value.get_fill_color()) self.props.fill_color = value.get_fill_color()
self.props.stroke_color = style.Color(value.get_stroke_color()) self.props.stroke_color = value.get_stroke_color()
elif pspec.name == 'fill-color': elif pspec.name == 'fill-color':
if self._fill_color != value: self._buffer.fill_color = value
if not self._cache: self._buffer.invalidate()
self._clear_buffers()
self._fill_color = value
self._icon = None
self._badge_icon = None
self.emit_paint_needed(0, 0, -1, -1) self.emit_paint_needed(0, 0, -1, -1)
elif pspec.name == 'stroke-color': elif pspec.name == 'stroke-color':
if self._stroke_color != value: self._buffer.stroke_color = value
if not self._cache: self._buffer.invalidate()
self._clear_buffers()
self._stroke_color = value
self._icon = None
self._badge_icon = None
self.emit_paint_needed(0, 0, -1, -1) self.emit_paint_needed(0, 0, -1, -1)
elif pspec.name == 'size': elif pspec.name == 'size':
if self._size != value and not self._cache: self._buffer.width = value
self._clear_buffers() self._buffer.height = value
self._size = value self._buffer.invalidate()
self.emit_request_changed() self.emit_request_changed()
elif pspec.name == 'scale': elif pspec.name == 'scale':
if self._scale != value and not self._cache: self._buffer.scale = value
self._clear_buffers() self._buffer.invalidate()
self._scale = value
self.emit_request_changed() self.emit_request_changed()
elif pspec.name == 'cache': elif pspec.name == 'cache-size':
self._cache = value self._buffer.cache_size = value
elif pspec.name == 'active':
if self._active != value:
if not self._cache:
self._clear_buffers()
self._active = value
self._icon = None
self.emit_paint_needed(0, 0, -1, -1)
elif pspec.name == 'badge-name': elif pspec.name == 'badge-name':
if self._badge_name != value and not self._cache:
self._clear_buffers()
self._badge_name = value
self._badge_icon = None
self.emit_paint_needed(0, 0, -1, -1) self.emit_paint_needed(0, 0, -1, -1)
def _choose_colors(self):
fill_color = None
stroke_color = None
if self._active:
if self._fill_color:
fill_color = self._fill_color.get_svg()
if self._stroke_color:
stroke_color = self._stroke_color.get_svg()
else:
stroke_color = color.ICON_STROKE_INACTIVE.get_svg()
if self._fill_color:
fill_color = self._fill_color.get_svg()
return [fill_color, stroke_color]
def _get_icon_from_cache(self, name, icon):
if not icon:
cache = CanvasIcon._cache
[fill_color, stroke_color] = self._choose_colors()
icon = cache.get_icon(name, fill_color, stroke_color)
return icon
def _get_icon(self):
self._icon = self._get_icon_from_cache(self._icon_name, self._icon)
return self._icon
def _get_badge_icon(self):
self._badge_icon = self._get_icon_from_cache(self._badge_name,
self._badge_icon)
return self._badge_icon
def _get_current_buffer_key(self, name):
[fill_color, stroke_color] = self._choose_colors()
return (name, fill_color, stroke_color, self._size)
def do_get_property(self, pspec): def do_get_property(self, pspec):
if pspec.name == 'size': if pspec.name == 'size':
return self._size return self._buffer.width
elif pspec.name == 'file-name':
return self._buffer.file_name
elif pspec.name == 'icon-name': elif pspec.name == 'icon-name':
return self._icon_name return self._buffer.icon_name
elif pspec.name == 'fill-color': elif pspec.name == 'fill-color':
return self._fill_color return self._buffer.fill_color
elif pspec.name == 'stroke-color': elif pspec.name == 'stroke-color':
return self._stroke_color return self._buffer.stroke_color
elif pspec.name == 'cache': elif pspec.name == 'cache-size':
return self._cache return self._buffer.cache_size
elif pspec.name == 'active':
return self._active
elif pspec.name == 'badge-name': elif pspec.name == 'badge-name':
return self._badge_name return self._buffer.badge_name
elif pspec.name == 'scale': elif pspec.name == 'scale':
return self._scale return self._buffer.scale
def _get_icon_size(self, icon):
if icon:
dimensions = icon.handle.get_dimension_data()
return int(dimensions[0]), int(dimensions[1])
else:
return [0, 0]
def _get_size(self, icon):
width, height = self._get_icon_size(icon)
if self._scale != 0:
width = int(width * self._scale)
height = int(height * self._scale)
elif self._size != 0:
width = height = self._size
return [width, height]
def _get_buffer(self, cr, name, icon, scale_factor=None):
"""Return a cached cairo surface for the SVG icon, or if none exists,
create a new cairo surface with the right size."""
buf = None
key = self._get_current_buffer_key(name)
if self._buffers.has_key(key):
buf = self._buffers[key]
else:
[icon_w, icon_h] = self._get_icon_size(icon)
[target_w, target_h] = self._get_size(icon)
if scale_factor:
target_w = int(target_w * scale_factor)
target_h = int(target_h * scale_factor)
target = cr.get_target()
buf = target.create_similar(cairo.CONTENT_COLOR_ALPHA,
target_w, target_h)
ctx = cairo.Context(buf)
ctx.scale(float(target_w) / float(icon_w),
float(target_h) / float(icon_h))
icon.handle.render_cairo(ctx)
del ctx
self._buffers[key] = buf
return buf
def do_paint_below_children(self, cr, damaged_box): def do_paint_below_children(self, cr, damaged_box):
icon = self._get_icon() surface = self._buffer.get_surface()
if icon is None: if surface:
return width, height = self.get_allocation()
icon_buf = self._get_buffer(cr, self._icon_name, icon) x = (width - surface.get_width()) / 2
[width, height] = self.get_allocation() y = (height - surface.get_height()) / 2
icon_x = (width - icon_buf.get_width()) / 2
icon_y = (height - icon_buf.get_height()) / 2
cr.set_source_surface(icon_buf, icon_x, icon_y) cr.set_source_surface(surface, x, y)
cr.paint()
if self._badge_name:
badge_icon = self._get_badge_icon()
if badge_icon:
badge_buf = self._get_buffer(cr, self._badge_name, badge_icon, _BADGE_SIZE)
badge_x = (icon_x + icon.badge_x * icon_buf.get_width() -
badge_buf.get_width() / 2)
badge_y = (icon_y + icon.badge_y * icon_buf.get_height() -
badge_buf.get_height() / 2)
cr.set_source_surface(badge_buf, badge_x, badge_y)
cr.paint() cr.paint()
def do_get_content_width_request(self): def do_get_content_width_request(self):
icon = self._get_icon() surface = self._buffer.get_surface()
[width, height] = self._get_size(icon) if surface:
if self._badge_name is not None: size = surface.get_width()
# If the badge goes outside the bounding box, add space elif self._buffer.width:
# on *both* sides (to keep the main icon centered) size = self._buffer.width
if icon.badge_x < 0.0: else:
width = int(width * 2 * (1.0 - icon.badge_x)) size = 0
elif icon.badge_x + _BADGE_SIZE > 1.0:
width = int(width * 2 * (icon.badge_x + _BADGE_SIZE - 1.0)) return size, size
return (width, width)
def do_get_content_height_request(self, for_width): def do_get_content_height_request(self, for_width):
icon = self._get_icon() surface = self._buffer.get_surface()
[width, height] = self._get_size(icon) if surface:
if self._badge_name is not None: size = surface.get_height()
if icon.badge_y < 0.0: elif self._buffer.height:
height = int(height * 2 * (1.0 - icon.badge_y)) size = self._buffer.height
elif icon.badge_y + _BADGE_SIZE > 1.0: else:
height = int(height * 2 * (icon.badge_y + _BADGE_SIZE - 1.0)) size = 0
return (height, height)
return size, size
def do_button_press_event(self, event): def do_button_press_event(self, event):
self.emit_activated() self.emit_activated()
return True return True
def _motion_notify_event_cb(self, button, event):
if event.detail == hippo.MOTION_DETAIL_ENTER:
self.prelight(True)
elif event.detail == hippo.MOTION_DETAIL_LEAVE:
self.prelight(False)
return False
def prelight(self, enter):
"""
Override this method for adding prelighting behavior.
"""
pass
def get_palette(self): def get_palette(self):
return self._palette return self._palette
@ -787,6 +526,6 @@ def get_icon_state(base_name, perc):
while strength <= 100: while strength <= 100:
icon_name = '%s-%03d' % (base_name, strength) icon_name = '%s-%03d' % (base_name, strength)
if icon_theme.has_icon(icon_name): if icon_theme.has_icon(icon_name):
return 'theme:' + icon_name return icon_name
strength = strength + step strength = strength + step

View File

@ -31,11 +31,11 @@ class IconButton(CanvasIcon, hippo.CanvasItem):
__gtype_name__ = 'SugarIconButton' __gtype_name__ = 'SugarIconButton'
def __init__(self, **kwargs): def __init__(self, **kwargs):
CanvasIcon.__init__(self, cache=True, **kwargs) CanvasIcon.__init__(self, **kwargs)
if not self.props.fill_color and not self.props.stroke_color: if not self.props.fill_color and not self.props.stroke_color:
self.props.fill_color = style.Color("#404040") self.props.fill_color = style.Color("#404040").get_svg()
self.props.stroke_color = style.Color("#FFFFFF") self.props.stroke_color = style.Color("#FFFFFF").get_svg()
self.connect('activated', self._icon_clicked_cb) self.connect('activated', self._icon_clicked_cb)