Add EventIcon/CursorInvoker similar to CanvasIcon/CanvasInvoker

CanvasIcon and CanvasInvoker were removed in a previous GTK3-porting commit
as they were based on hippocanvas.

However, this leaves the toolkit with some missing functionality:
there is no longer a trivial way to show an icon which can receive mouse
events and pop up a palette. Such functionality is used in various
places throughout the shell and activities.

Reimplement this functionality as EventIcon and CursorInvoker.
Instead of reimplementing much of the Icon class (like CanvasIcon did),
EventIcon opts for a more simplistic encapsulation of an Icon object.
This means trivial API changes for CanvasIcon users who must now
use the 'icon' property with the Icon API.

Signed-off-by: Daniel Drake <dsd@laptop.org>
Acked-by: Simon Schampijer <simon@laptop.org>
This commit is contained in:
Daniel Drake 2011-12-14 23:47:11 +00:00 committed by Simon Schampijer
parent 5ad2fc7d6b
commit 827ab7218a
3 changed files with 133 additions and 1 deletions

View File

@ -29,6 +29,7 @@ from gi.repository import GObject
from gi.repository import Gtk from gi.repository import Gtk
import cairo import cairo
from sugar3.graphics import style
from sugar3.graphics.xocolor import XoColor from sugar3.graphics.xocolor import XoColor
from sugar3.util import LRU from sugar3.util import LRU
@ -545,6 +546,75 @@ class Icon(Gtk.Image):
type=float, setter=set_scale) type=float, setter=set_scale)
class EventIcon(Gtk.EventBox):
"""
An Icon class that provides access to mouse events and that can act as a
cursor-positioned palette invoker.
"""
__gtype_name__ = 'EventIcon'
__gsignals__ = {
'activated': (GObject.SIGNAL_RUN_LAST, GObject.TYPE_NONE, []),
}
def __init__(self, **kwargs):
Gtk.EventBox.__init__(self)
self._icon = Icon()
for key, value in kwargs.iteritems():
self._icon.set_property(key, value)
self.add(self._icon)
self._icon.show()
from sugar3.graphics.palette import CursorInvoker
self._palette_invoker = CursorInvoker()
self._palette_invoker.attach(self)
self.modify_bg(Gtk.StateType.NORMAL, style.COLOR_WHITE.get_gdk_color())
self.connect('destroy', self.__destroy_cb)
def __destroy_cb(self, icon):
if self._palette_invoker is not None:
self._palette_invoker.detach()
def do_button_press_event(self, event):
if event.button == 1:
self.emit('activated')
return True
else:
return False
def get_icon(self):
return self._icon
icon = GObject.property(
type=object, getter=get_icon)
def get_palette(self):
return self._palette_invoker.palette
def set_palette(self, palette):
self._palette_invoker.palette = palette
palette = GObject.property(
type=object, setter=set_palette, getter=get_palette)
def get_palette_invoker(self):
return self._palette_invoker
def set_palette_invoker(self, palette_invoker):
self._palette_invoker.detach()
self._palette_invoker = palette_invoker
palette_invoker = GObject.property(
type=object, setter=set_palette_invoker, getter=get_palette_invoker)
def set_tooltip(self, text):
from sugar3.graphics.palette import Palette
self.set_palette(Palette(text))
class CellRendererIcon(Gtk.CellRenderer): class CellRendererIcon(Gtk.CellRenderer):
__gtype_name__ = 'SugarCellRendererIcon' __gtype_name__ = 'SugarCellRendererIcon'

View File

@ -35,7 +35,7 @@ from gi.repository import SugarExt
# DEPRECATED # DEPRECATED
# Import these for backwards compatibility # Import these for backwards compatibility
from sugar3.graphics.palettewindow import MouseSpeedDetector, Invoker, \ from sugar3.graphics.palettewindow import MouseSpeedDetector, Invoker, \
WidgetInvoker, CanvasInvoker, ToolInvoker, CellRendererInvoker WidgetInvoker, CursorInvoker, ToolInvoker, CellRendererInvoker
class Palette(PaletteWindow): class Palette(PaletteWindow):

View File

@ -788,6 +788,68 @@ class WidgetInvoker(Invoker):
widget = GObject.property(type=object, getter=_get_widget, setter=None) widget = GObject.property(type=object, getter=_get_widget, setter=None)
class CursorInvoker(Invoker):
def __init__(self, parent=None):
Invoker.__init__(self)
self._position_hint = self.AT_CURSOR
self._enter_hid = None
self._leave_hid = None
self._release_hid = None
self._item = None
if parent:
self.attach(parent)
def attach(self, parent):
Invoker.attach(self, parent)
self._item = parent
self._enter_hid = self._item.connect('enter-notify-event',
self.__enter_notify_event_cb)
self._leave_hid = self._item.connect('leave-notify-event',
self.__leave_notify_event_cb)
self._release_hid = self._item.connect('button-release-event',
self.__button_release_event_cb)
def detach(self):
Invoker.detach(self)
self._item.disconnect(self._enter_hid)
self._item.disconnect(self._leave_hid)
self._item.disconnect(self._release_hid)
def get_default_position(self):
return self.AT_CURSOR
def get_rect(self):
window = self._item.get_window()
allocation = self._item.get_allocation()
rect = Gdk.Rectangle()
rect.x, rect.y = window.get_root_coords(allocation.x, allocation.y)
rect.width = allocation.width
rect.height = allocation.height
return rect
def __enter_notify_event_cb(self, button, event):
self.notify_mouse_enter()
return False
def __leave_notify_event_cb(self, button, event):
self.notify_mouse_leave()
return False
def __button_release_event_cb(self, button, event):
if event.button == 3:
self.notify_right_click()
return True
else:
return False
def get_toplevel(self):
return self._item.get_toplevel()
class ToolInvoker(WidgetInvoker): class ToolInvoker(WidgetInvoker):
def __init__(self, parent=None): def __init__(self, parent=None):