diff options
Diffstat (limited to 'sugar/graphics')
-rw-r--r-- | sugar/graphics/Makefile.am | 2 | ||||
-rw-r--r-- | sugar/graphics/canvasbutton.py | 2 | ||||
-rw-r--r-- | sugar/graphics/canvasicon.py | 18 | ||||
-rw-r--r-- | sugar/graphics/icon.py | 27 | ||||
-rw-r--r-- | sugar/graphics/iconentry.py | 45 | ||||
-rw-r--r-- | sugar/graphics/menuitem.py | 2 | ||||
-rw-r--r-- | sugar/graphics/objectchooser.py | 2 | ||||
-rw-r--r-- | sugar/graphics/palette.py | 94 | ||||
-rw-r--r-- | sugar/graphics/palettegroup.py | 17 | ||||
-rw-r--r-- | sugar/graphics/radiotoolbutton.py | 18 | ||||
-rw-r--r-- | sugar/graphics/style.py | 2 | ||||
-rw-r--r-- | sugar/graphics/toggletoolbutton.py | 18 | ||||
-rw-r--r-- | sugar/graphics/toolbutton.py | 18 |
13 files changed, 171 insertions, 94 deletions
diff --git a/sugar/graphics/Makefile.am b/sugar/graphics/Makefile.am index af66cfb..2d0dc17 100644 --- a/sugar/graphics/Makefile.am +++ b/sugar/graphics/Makefile.am @@ -9,7 +9,7 @@ sugar_PYTHON = \ combobox.py \ icon.py \ iconbutton.py \ - menuitem.py \ + iconentry.py \ notebook.py \ objectchooser.py \ radiotoolbutton.py \ diff --git a/sugar/graphics/canvasbutton.py b/sugar/graphics/canvasbutton.py index 31bc833..fc869f9 100644 --- a/sugar/graphics/canvasbutton.py +++ b/sugar/graphics/canvasbutton.py @@ -25,7 +25,7 @@ class CanvasButton(hippo.CanvasButton): hippo.CanvasButton.__init__(self, text=label) if icon_name: - icon = Icon(icon_name, gtk.ICON_SIZE_BUTTON) + icon = Icon(icon_name,icon_size=gtk.ICON_SIZE_BUTTON) self.props.widget.set_image(icon) icon.show() diff --git a/sugar/graphics/canvasicon.py b/sugar/graphics/canvasicon.py index 39f1358..a77eecd 100644 --- a/sugar/graphics/canvasicon.py +++ b/sugar/graphics/canvasicon.py @@ -142,6 +142,8 @@ class CanvasIcon(hippo.CanvasBox, hippo.CanvasItem): gobject.PARAM_READWRITE), 'size' : (int, None, None, 0, 1024, 0, gobject.PARAM_READWRITE), + 'scale' : (int, None, None, 0, 1024, 0, + gobject.PARAM_READWRITE), 'cache' : (bool, None, None, False, gobject.PARAM_READWRITE), 'active' : (bool, None, None, True, @@ -156,6 +158,7 @@ class CanvasIcon(hippo.CanvasBox, hippo.CanvasItem): self._buffers = {} self._cur_buffer = None self._size = 0 + self._scale = 0 self._fill_color = None self._stroke_color = None self._icon_name = None @@ -210,6 +213,11 @@ class CanvasIcon(hippo.CanvasBox, hippo.CanvasItem): self._clear_buffers() self._size = value self.emit_request_changed() + elif pspec.name == 'scale': + if self._scale != value and not self._cache: + self._clear_buffers() + self._scale = value + self.emit_request_changed() elif pspec.name == 'cache': self._cache = value elif pspec.name == 'active': @@ -277,6 +285,8 @@ class CanvasIcon(hippo.CanvasBox, hippo.CanvasItem): return self._active elif pspec.name == 'badge-name': return self._badge_name + elif pspec.name == 'scale': + return self._scale def _get_icon_size(self, handle): if handle: @@ -286,9 +296,11 @@ class CanvasIcon(hippo.CanvasBox, hippo.CanvasItem): return [0, 0] def _get_size(self, handle): - if self._size == 0: - width, height = self._get_icon_size(handle) - else: + width, height = self._get_icon_size(handle) + 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] diff --git a/sugar/graphics/icon.py b/sugar/graphics/icon.py index 731412f..e324d45 100644 --- a/sugar/graphics/icon.py +++ b/sugar/graphics/icon.py @@ -34,17 +34,18 @@ class Icon(gtk.Image): gobject.PARAM_READWRITE) } - def __init__(self, name, size=gtk.ICON_SIZE_LARGE_TOOLBAR, **kwargs): + def __init__(self, name, **kwargs): + self._constructed = False self._fill_color = None self._stroke_color = None self._icon_name = name - self._size = size self._theme = gtk.icon_theme_get_default() + self._data = None + gobject.GObject.__init__(self, **kwargs) - # If we have a non-styled-icon - if not self._fill_color and not self._stroke_color: - self._update_normal_icon() + self._constructed = True + self._update_icon() def _get_pixbuf(self, data, width, height): loader = gtk.gdk.PixbufLoader('svg') @@ -77,9 +78,12 @@ class Icon(gtk.Image): source.set_state(gtk.STATE_INSENSITIVE) icon_set.add_source(source) - self.set_from_icon_set(icon_set, self._size) + self.props.icon_set = icon_set def _update_icon(self): + if not self._constructed: + return + if not self._fill_color and not self._stroke_color: self._update_normal_icon() return @@ -100,12 +104,12 @@ class Icon(gtk.Image): self._data = data # Redraw pixbuf - [w, h] = gtk.icon_size_lookup(self._size) + [w, h] = gtk.icon_size_lookup(self.props.icon_size) pixbuf = self._get_pixbuf(self._data, w, h) self.set_from_pixbuf(pixbuf) def _get_real_name(self, name): - info = self._theme.lookup_icon(name, self._size, 0) + info = self._theme.lookup_icon(name, self.props.icon_size, 0) if not info: raise ValueError("Icon '" + name + "' not found.") fname = info.get_filename() @@ -122,9 +126,16 @@ class Icon(gtk.Image): elif pspec.name == 'stroke-color': self._stroke_color = value self._update_icon() + else: + gtk.Image.do_set_property(self, pspec, value) + + if pspec.name == 'icon-size': + self._update_icon() def do_get_property(self, pspec): if pspec.name == 'fill-color': return self._fill_color elif pspec.name == 'stroke-color': return self._stroke_color + else: + return gtk.Image.do_get_property(self, pspec) diff --git a/sugar/graphics/iconentry.py b/sugar/graphics/iconentry.py new file mode 100644 index 0000000..2f7584f --- /dev/null +++ b/sugar/graphics/iconentry.py @@ -0,0 +1,45 @@ +# Copyright (C) 2007, One Laptop Per Child +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the +# Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. + +import gtk + +from sugar import _sugaruiext + +ICON_ENTRY_PRIMARY = _sugaruiext.ICON_ENTRY_PRIMARY +ICON_ENTRY_SECONDARY = _sugaruiext.ICON_ENTRY_SECONDARY + +class IconEntry(_sugaruiext.IconEntry): + def set_icon_from_name(self, position, name): + icon_theme = gtk.icon_theme_get_default() + icon_info = icon_theme.lookup_icon(name, + gtk.ICON_SIZE_SMALL_TOOLBAR, + 0) + + pixbuf = gtk.gdk.pixbuf_new_from_file(icon_info.get_filename()) + + image = gtk.Image() + image.set_from_pixbuf(pixbuf) + image.show() + + self.set_icon(position, image) + + def set_icon(self, position, image): + if image.get_storage_type() not in [gtk.IMAGE_PIXBUF, gtk.IMAGE_STOCK]: + raise ValueError('Image must have a storage type of pixbuf or ' + + 'stock, not %r.' % image.get_storage_type()) + _sugaruiext.IconEntry.set_icon(self, position, image) + diff --git a/sugar/graphics/menuitem.py b/sugar/graphics/menuitem.py index 492f5f1..db4a293 100644 --- a/sugar/graphics/menuitem.py +++ b/sugar/graphics/menuitem.py @@ -22,7 +22,7 @@ class MenuItem(gtk.ImageMenuItem): def __init__(self, text_label, icon_name=None): gtk.ImageMenuItem.__init__(self, text_label) if icon_name: - icon = Icon(icon_name, gtk.ICON_SIZE_MENU) + icon = Icon(icon_name, icon_size=gtk.ICON_SIZE_MENU) self.set_image(icon) icon.show() diff --git a/sugar/graphics/objectchooser.py b/sugar/graphics/objectchooser.py index 5b09e13..46739f6 100644 --- a/sugar/graphics/objectchooser.py +++ b/sugar/graphics/objectchooser.py @@ -150,7 +150,7 @@ class CollapsedEntry(CanvasRoundBox): self._icon_name = type.icon if not self._icon_name: - self._icon_name = 'theme:stock-missing' + self._icon_name = 'theme:image-missing' return self._icon_name diff --git a/sugar/graphics/palette.py b/sugar/graphics/palette.py index 368a0f6..6b1209a 100644 --- a/sugar/graphics/palette.py +++ b/sugar/graphics/palette.py @@ -87,9 +87,7 @@ class Palette(gtk.Window): 'invoker' : (object, None, None, gobject.PARAM_READWRITE), 'position' : (gobject.TYPE_INT, None, None, 0, 6, - 0, gobject.PARAM_READWRITE), - 'draw-gap' : (bool, None, None, False, - gobject.PARAM_READWRITE) + 0, gobject.PARAM_READWRITE) } __gsignals__ = { @@ -114,7 +112,6 @@ class Palette(gtk.Window): self._group_id = None self._up = False self._position = self.DEFAULT - self._draw_gap = False self._palette_popup_sid = None self._popup_anim = animator.Animator(0.3, 10) @@ -162,6 +159,7 @@ class Palette(gtk.Window): self._leave_notify_event_cb) self.set_primary_text(label, accel_path) + self.set_group_id('default') def is_up(self): return self._up @@ -178,8 +176,9 @@ class Palette(gtk.Window): return gtk.gdk.Rectangle(x, y, width, height) def set_primary_text(self, label, accel_path=None): - self._label.set_text(label) - self._label.show() + if label is not None: + self._label.set_text(label) + self._label.show() def set_content(self, widget): if len(self._content.get_children()) > 0: @@ -196,6 +195,7 @@ class Palette(gtk.Window): group = palettegroup.get_group(self._group_id) group.remove(self) if group_id: + self._group_id = group_id group = palettegroup.get_group(group_id) group.add(self) @@ -206,9 +206,6 @@ class Palette(gtk.Window): self._invoker.connect('mouse-leave', self._invoker_mouse_leave_cb) elif pspec.name == 'position': self._position = value - elif pspec.name == 'draw-gap': - self._draw_gap = value - self.queue_draw() else: raise AssertionError @@ -217,8 +214,6 @@ class Palette(gtk.Window): return self._invoker elif pspec.name == 'position': return self._position - elif pspec.name == 'draw-gap': - return self._draw_gap else: raise AssertionError @@ -228,7 +223,7 @@ class Palette(gtk.Window): def do_expose_event(self, event): # We want to draw a border with a beautiful gap - if self._draw_gap: + if self._invoker.has_rectangle_gap(): invoker = self._invoker.get_rect() palette = self.get_rect() @@ -398,6 +393,9 @@ class Palette(gtk.Window): self.menu.set_active(True) self.show() + if self._invoker: + self._invoker.notify_popup() + self._up = True _palette_observer.emit('popup', self) self.emit('popup') @@ -406,22 +404,31 @@ class Palette(gtk.Window): if not self._palette_popup_sid is None: _palette_observer.disconnect(self._palette_popup_sid) self._palette_popup_sid = None + self.menu.set_active(False) self.hide() + if self._invoker: + self._invoker.notify_popdown() + self._up = False self.emit('popdown') - def popup(self): + def popup(self, immediate=False): self._popdown_anim.stop() - self._popup_anim.start() + + if not immediate: + self._popup_anim.start() + else: + self._show() + self._secondary_anim.start() - def popdown(self, inmediate=False): + def popdown(self, immediate=False): self._secondary_anim.stop() self._popup_anim.stop() - if not inmediate: + if not immediate: self._popdown_anim.start() else: self._hide() @@ -440,7 +447,15 @@ class Palette(gtk.Window): self._state = state def _invoker_mouse_enter_cb(self, invoker): - self.popup() + immediate = False + if self._group_id: + group = palettegroup.get_group(self._group_id) + if group and group.is_up(): + immediate = True + group.popdown() + + print immediate + self.popup(immediate=immediate) def _invoker_mouse_leave_cb(self, invoker): self.popdown() @@ -535,6 +550,12 @@ class Invoker(gobject.GObject): def __init__(self): gobject.GObject.__init__(self) + def has_rectangle_gap(self): + return False + + def draw_rectangle(self, event, palette): + pass + def get_default_position(self): return Palette.AROUND @@ -543,6 +564,12 @@ class Invoker(gobject.GObject): height = gtk.gdk.screen_height() return gtk.gdk.Rectangle(0, 0, width, height) + def notify_popup(self): + pass + + def notify_popdown(self): + pass + class WidgetInvoker(Invoker): def __init__(self, widget): Invoker.__init__(self) @@ -562,31 +589,24 @@ class WidgetInvoker(Invoker): return gtk.gdk.Rectangle(x, y, width, height) - def draw_invoker_rect(self, event, palette): + def has_rectangle_gap(self): + return True + + def draw_rectangle(self, event, palette): style = self._widget.style - if palette.is_up(): - gap = _calculate_gap(self.get_rect(), palette.get_rect()) - - if gap: - style.paint_box_gap(event.window, gtk.STATE_PRELIGHT, - gtk.SHADOW_IN, event.area, self._widget, - "palette-invoker", - self._widget.allocation.x, - self._widget.allocation.y, - self._widget.allocation.width, - self._widget.allocation.height, - gap[0], gap[1], gap[2]) - else: - style.paint_box(event.window, gtk.STATE_PRELIGHT, + gap = _calculate_gap(self.get_rect(), palette.get_rect()) + if gap: + style.paint_box_gap(event.window, gtk.STATE_PRELIGHT, gtk.SHADOW_IN, event.area, self._widget, "palette-invoker", self._widget.allocation.x, self._widget.allocation.y, self._widget.allocation.width, - self._widget.allocation.height) + self._widget.allocation.height, + gap[0], gap[1], gap[2]) else: style.paint_box(event.window, gtk.STATE_PRELIGHT, - gtk.SHADOW_NONE, event.area, self._widget, + gtk.SHADOW_IN, event.area, self._widget, "palette-invoker", self._widget.allocation.x, self._widget.allocation.y, @@ -602,6 +622,12 @@ class WidgetInvoker(Invoker): def get_toplevel(self): return self._widget.get_toplevel() + def notify_popup(self): + self._widget.queue_draw() + + def notify_popdown(self): + self._widget.queue_draw() + class CanvasInvoker(Invoker): def __init__(self, item): Invoker.__init__(self) diff --git a/sugar/graphics/palettegroup.py b/sugar/graphics/palettegroup.py index d5e1125..d6ae122 100644 --- a/sugar/graphics/palettegroup.py +++ b/sugar/graphics/palettegroup.py @@ -39,6 +39,7 @@ class Group(gobject.GObject): gobject.GObject.__init__(self) self._up = False self._palettes = [] + self._sig_ids = {} def is_up(self): return self._up @@ -46,18 +47,26 @@ class Group(gobject.GObject): def add(self, palette): self._palettes.append(palette) + self._sig_ids[palette] = [] + sid = palette.connect('popup', self._palette_popup_cb) - palette.popup_sid = sid + self._sig_ids[palette].append(sid) sid = palette.connect('popdown', self._palette_popdown_cb) - palette.podown_sid = sid + self._sig_ids[palette].append(sid) def remove(self, palette): - self.disconnect(palette.popup_sid) - self.disconnect(palette.popdown_sid) + sig_ids = self._sig_ids[palette] + for sid in sig_ids: + palette.disconnect(sid) self._palettes.remove(palette) + def popdown(self): + for palette in self._palettes: + if palette.is_up(): + palette.popdown(immediate=True) + def _palette_popup_cb(self, palette): if not self._up: self.emit('popup') diff --git a/sugar/graphics/radiotoolbutton.py b/sugar/graphics/radiotoolbutton.py index fb584ee..4ffc7d1 100644 --- a/sugar/graphics/radiotoolbutton.py +++ b/sugar/graphics/radiotoolbutton.py @@ -40,25 +40,15 @@ class RadioToolButton(gtk.RadioToolButton): def set_palette(self, palette): self._palette = palette self._palette.props.invoker = WidgetInvoker(self.child) - self._palette.props.draw_gap = True - - self._palette.connect("popup", self._palette_changed) - self._palette.connect("popdown", self._palette_changed) def set_tooltip(self, text): - self._palette = Palette(text) - self._palette.props.invoker = WidgetInvoker(self.child) + self._set_palette(Palette(text)) def do_expose_event(self, event): - if self._palette and self._palette.props.draw_gap: - if self._palette.is_up() or self.child.state == gtk.STATE_PRELIGHT: - invoker = self._palette.props.invoker - invoker.draw_invoker_rect(event, self._palette) + if self._palette and self._palette.is_up(): + invoker = self._palette.props.invoker + invoker.draw_rectangle(event, self._palette) gtk.RadioToolButton.do_expose_event(self, event) - def _palette_changed(self, palette): - # Force a redraw to update the invoker rectangle - self.queue_draw() - palette = property(get_palette, set_palette) diff --git a/sugar/graphics/style.py b/sugar/graphics/style.py index c0094b6..9d561eb 100644 --- a/sugar/graphics/style.py +++ b/sugar/graphics/style.py @@ -128,6 +128,8 @@ COLOR_WHITE = Color('#FFFFFF') COLOR_TRANSPARENT = Color('#FFFFFF', alpha=0.0) COLOR_PANEL_GREY = Color('#C0C0C0') COLOR_SELECTION_GREY = Color('#A6A6A6') +COLOR_TOOLBAR_GREY = Color('#404040') +COLOR_BUTTON_GREY = Color('#808080') COLOR_INACTIVE_FILL = Color('#9D9FA1') COLOR_INACTIVE_STROKE = Color('#757575') diff --git a/sugar/graphics/toggletoolbutton.py b/sugar/graphics/toggletoolbutton.py index 41050e2..74e78a6 100644 --- a/sugar/graphics/toggletoolbutton.py +++ b/sugar/graphics/toggletoolbutton.py @@ -39,25 +39,15 @@ class ToggleToolButton(gtk.ToggleToolButton): def set_palette(self, palette): self._palette = palette self._palette.props.invoker = WidgetInvoker(self.child) - self._palette.props.draw_gap = True - - self._palette.connect("popup", self._palette_changed) - self._palette.connect("popdown", self._palette_changed) def set_tooltip(self, text): - self._palette = Palette(text) - self._palette.props.invoker = WidgetInvoker(self.child) + self._set_palette(Palette(text)) def do_expose_event(self, event): - if self._palette and self._palette.props.draw_gap: - if self._palette.is_up() or self.child.state == gtk.STATE_PRELIGHT: - invoker = self._palette.props.invoker - invoker.draw_invoker_rect(event, self._palette) + if self._palette and self._palette.is_up(): + invoker = self._palette.props.invoker + invoker.draw_rectangle(event, self._palette) gtk.ToggleToolButton.do_expose_event(self, event) - def _palette_changed(self, palette): - # Force a redraw to update the invoker rectangle - self.queue_draw() - palette = property(get_palette, set_palette) diff --git a/sugar/graphics/toolbutton.py b/sugar/graphics/toolbutton.py index 52a5d62..b42f63e 100644 --- a/sugar/graphics/toolbutton.py +++ b/sugar/graphics/toolbutton.py @@ -28,7 +28,8 @@ class ToolButton(gtk.ToolButton): def __init__(self, icon_name=None): gtk.ToolButton.__init__(self) self._palette = None - self.set_icon(icon_name) + if icon_name: + self.set_icon(icon_name) self.connect('clicked', self._button_clicked_cb) def set_icon(self, icon_name): @@ -42,19 +43,14 @@ class ToolButton(gtk.ToolButton): def set_palette(self, palette): self._palette = palette self._palette.props.invoker = WidgetInvoker(self.child) - self._palette.props.draw_gap = True - - self._palette.connect("popup", self._palette_changed) - self._palette.connect("popdown", self._palette_changed) def set_tooltip(self, text): self.set_palette(Palette(text)) def do_expose_event(self, event): - if self._palette and self._palette.props.draw_gap: - if self._palette.is_up() or self.child.state == gtk.STATE_PRELIGHT: - invoker = self._palette.props.invoker - invoker.draw_invoker_rect(event, self._palette) + if self._palette and self._palette.is_up(): + invoker = self._palette.props.invoker + invoker.draw_rectangle(event, self._palette) gtk.ToolButton.do_expose_event(self, event) @@ -62,8 +58,4 @@ class ToolButton(gtk.ToolButton): if self._palette: self._palette.popdown(True) - def _palette_changed(self, palette): - # Force a redraw to update the invoker rectangle - self.queue_draw() - palette = property(get_palette, set_palette) |