diff options
-rw-r--r-- | src/sugar/graphics/icon.py | 137 | ||||
-rw-r--r-- | src/sugar/graphics/palette.py | 121 |
2 files changed, 258 insertions, 0 deletions
diff --git a/src/sugar/graphics/icon.py b/src/sugar/graphics/icon.py index 6e88f88..fe6cc5e 100644 --- a/src/sugar/graphics/icon.py +++ b/src/sugar/graphics/icon.py @@ -919,6 +919,143 @@ class CanvasIcon(hippo.CanvasBox, hippo.CanvasItem): palette = property(get_palette, set_palette) +class CellRendererIcon(gtk.CellRendererPixbuf): + __gtype_name__ = 'SugarCellRendererIcon' + + __gsignals__ = { + 'activate': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, [object]) + } + + def __init__(self, tree_view): + from sugar.graphics.palette import CellRendererInvoker + + self._buffer = _IconBuffer() + self._fill_color = None + self._stroke_color = None + self._prelit_fill_color = None + self._prelit_stroke_color = None + self._palette_invoker = CellRendererInvoker() + + gobject.GObject.__init__(self) + + self._palette_invoker.attach_cell_renderer(tree_view, self) + + self.connect('destroy', self.__destroy_cb) + + def __destroy_cb(self, icon): + self._palette_invoker.detach() + + def create_palette(self): + return None + + def get_palette_invoker(self): + return self._palette_invoker + + palette_invoker = gobject.property(type=object, getter=get_palette_invoker) + + def set_file_name(self, value): + if self._buffer.file_name != value: + self._buffer.file_name = value + + file_name = gobject.property(type=str, setter=set_file_name) + + def set_icon_name(self, value): + if self._buffer.icon_name != value: + self._buffer.icon_name = value + + icon_name = gobject.property(type=object, setter=set_icon_name) + + def set_xo_color(self, value): + self._stroke_color = value.get_stroke_color() + self._fill_color = value.get_fill_color() + + xo_color = gobject.property(type=object, setter=set_xo_color) + + def set_fill_color(self, value): + if self._fill_color != value: + self._fill_color = value + + fill_color = gobject.property(type=object, setter=set_fill_color) + + def set_stroke_color(self, value): + if self._stroke_color != value: + self._stroke_color = value + + stroke_color = gobject.property(type=object, setter=set_stroke_color) + + def set_prelit_fill_color(self, value): + if self._prelit_fill_color != value: + self._prelit_fill_color = value + + prelit_fill_color = gobject.property(type=object, + setter=set_prelit_fill_color) + + def set_prelit_stroke_color(self, value): + if self._prelit_stroke_color != value: + self._prelit_stroke_color = value + + prelit_stroke_color = gobject.property(type=object, + setter=set_prelit_stroke_color) + + def set_background_color(self, value): + if self._buffer.background_color != value: + self._buffer.background_color = value + + background_color = gobject.property(type=object, setter=set_background_color) + + def set_size(self, value): + if self._buffer.width != value: + self._buffer.width = value + self._buffer.height = value + + size = gobject.property(type=object, setter=set_size) + + def _is_prelit(self, tree_view): + x, y = tree_view.get_pointer() + x, y = tree_view.convert_widget_to_bin_window_coords(x, y) + pos = tree_view.get_path_at_pos(x, y) + if pos is None: + return False + + path, column, x, y = pos + + for cell_renderer in column.get_cell_renderers(): + if cell_renderer == self: + cell_x, cell_width = column.cell_get_position(cell_renderer) + if x > cell_x and x < (cell_x + cell_width): + return True + return False + + return False + + def do_render(self, window, widget, background_area, cell_area, expose_area, flags): + has_prelit_colors = None not in [self._prelit_fill_color, + self._prelit_stroke_color] + if flags & gtk.CELL_RENDERER_PRELIT and has_prelit_colors and \ + self._is_prelit(widget): + + self._buffer.fill_color = self._prelit_fill_color + self._buffer.stroke_color = self._prelit_stroke_color + else: + self._buffer.fill_color = self._fill_color + self._buffer.stroke_color = self._stroke_color + + surface = self._buffer.get_surface() + if surface is None: + self.props.pixbuf = None + else: + #FIXME: Do we really want to transform to PNG, then create a pixbuf from it? + # Maybe we should just draw with cairo. + loader = gtk.gdk.pixbuf_loader_new_with_mime_type('image/png') + surface.write_to_png(loader) + loader.close() + self.props.pixbuf = loader.get_pixbuf() + + gtk.CellRendererPixbuf.do_render(self, window, widget, background_area, cell_area, expose_area, flags) + + def do_activate(self, event, widget, path, background_area, cell_area, flags): + self.emit('activate', path) + def get_icon_state(base_name, perc, step=5): strength = round(perc / step) * step icon_theme = gtk.icon_theme_get_default() diff --git a/src/sugar/graphics/palette.py b/src/sugar/graphics/palette.py index 1c668b6..3419e52 100644 --- a/src/sugar/graphics/palette.py +++ b/src/sugar/graphics/palette.py @@ -1145,3 +1145,124 @@ class ToolInvoker(WidgetInvoker): return self.BOTTOM + self.TOP else: return self.LEFT + self.RIGHT + +class CellRendererInvoker(Invoker): + def __init__(self): + Invoker.__init__(self) + + self._position_hint = self.AT_CURSOR + self._tree_view = None + self._cell_renderer = None + self._motion_hid = None + self._leave_hid = None + self._release_hid = None + self.path = None + + def attach_cell_renderer(self, tree_view, cell_renderer): + self._tree_view = tree_view + self._cell_renderer = cell_renderer + + self._motion_hid = tree_view.connect('motion-notify-event', + self.__motion_notify_event_cb) + self._leave_hid = tree_view.connect('leave-notify-event', + self.__leave_notify_event_cb) + self._release_hid = tree_view.connect('button-release-event', + self.__button_release_event_cb) + + self.attach(cell_renderer) + + def detach(self): + Invoker.detach(self) + self._tree_view.disconnect(self._motion_hid) + self._tree_view.disconnect(self._leave_hid) + self._tree_view.disconnect(self._release_hid) + + def get_rect(self): + allocation = self._tree_view.get_allocation() + if self._tree_view.window is not None: + x, y = self._tree_view.window.get_origin() + else: + logging.warning( + "Trying to position palette with invoker that's not realized.") + x = 0 + y = 0 + + if self._tree_view.flags() & gtk.NO_WINDOW: + x += allocation.x + y += allocation.y + + width = allocation.width + height = allocation.height + + return gtk.gdk.Rectangle(x, y, width, height) + + def __motion_notify_event_cb(self, widget, event): + if self._point_in_cell_renderer(event.x, event.y): + + tree_view = self._tree_view + path, column_, x_, y_ = tree_view.get_path_at_pos(int(event.x), + int(event.y)) + if path != self.path: + if self.path is not None: + self._redraw_path(self.path) + if path is not None: + self._redraw_path(path) + if self.palette is not None: + self.palette.popdown(immediate=True) + self.palette = None + self.path = path + + self.notify_mouse_enter() + else: + if self.path is not None: + self._redraw_path(self.path) + self.path = None + self.notify_mouse_leave() + + def _redraw_path(self, path): + for column in self._tree_view.get_columns(): + if self._cell_renderer in column.get_cell_renderers(): + break + area = self._tree_view.get_background_area(path, column) + x, y = self._tree_view.convert_tree_to_widget_coords(area.x, area.y) + self._tree_view.queue_draw_area(x, y, area.width, area.height) + + def __leave_notify_event_cb(self, widget, event): + self.notify_mouse_leave() + + def __button_release_event_cb(self, widget, event): + if event.button == 3 and self._point_in_cell_renderer(event.x, event.y): + self.notify_right_click() + return True + else: + return False + + def _point_in_cell_renderer(self, event_x, event_y): + pos = self._tree_view.get_path_at_pos(int(event_x), int(event_y)) + if pos is None: + return False + + path, column, x, y = pos + + for cell_renderer in column.get_cell_renderers(): + if cell_renderer == self._cell_renderer: + cell_x, cell_width = column.cell_get_position(cell_renderer) + if x > cell_x and x < (cell_x + cell_width): + return True + return False + + return False + + def get_toplevel(self): + return self._tree_view.get_toplevel() + + def notify_popup(self): + Invoker.notify_popup(self) + + def notify_popdown(self): + Invoker.notify_popdown(self) + self.palette = None + + def get_default_position(self): + return self.AT_CURSOR + |