Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/sugar/graphics
diff options
context:
space:
mode:
Diffstat (limited to 'sugar/graphics')
-rw-r--r--sugar/graphics/Makefile.am2
-rw-r--r--sugar/graphics/canvasbutton.py2
-rw-r--r--sugar/graphics/canvasicon.py18
-rw-r--r--sugar/graphics/icon.py27
-rw-r--r--sugar/graphics/iconentry.py45
-rw-r--r--sugar/graphics/menuitem.py2
-rw-r--r--sugar/graphics/objectchooser.py2
-rw-r--r--sugar/graphics/palette.py94
-rw-r--r--sugar/graphics/palettegroup.py17
-rw-r--r--sugar/graphics/radiotoolbutton.py18
-rw-r--r--sugar/graphics/style.py2
-rw-r--r--sugar/graphics/toggletoolbutton.py18
-rw-r--r--sugar/graphics/toolbutton.py18
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)