On Fri, Mar 28, 2008 at 8:13 PM, Tomeu Vizoso <[EMAIL PROTECTED]> wrote:
> On Fri, Mar 28, 2008 at 6:46 PM, Marco Pesenti Gritti
>  <[EMAIL PROTECTED]> wrote:
>  > On Fri, Mar 28, 2008 at 6:19 PM, Tomeu Vizoso <[EMAIL PROTECTED]> wrote:
>  >  +    def set_tooltip(self, tooltip):
>  >  +        if self._tooltip != tooltip:
>  >  +            self._tooltip = tooltip
>  >  +            if tooltip and self.palette is None:
>  >  +                self.palette = Palette(tooltip)
>  >  +            elif self.palette:
>  >  +                self.palette.set_primary_text(tooltip)
>  >
>  >  Is the if at the top really necessary? I can't think of use cases
>  >  where we would be hitting it.
>  >  Also I'd replace the palette if you set_tooltip and a Palette already 
> exist.
>
>  How so?

Ok, this is the only standing issue in the attached patch.

Thanks,

Tomeu
From 20867c472a96d70d77f01c1480e186d5f241cfe6 Mon Sep 17 00:00:00 2001
From: Tomeu Vizoso <[EMAIL PROTECTED]>
Date: Fri, 28 Mar 2008 20:36:47 +0100
Subject: [PATCH] Add support for accelerators to buttons.

---
 sugar/activity/activity.py        |   21 ++++------
 sugar/graphics/palette.py         |   31 ++++++++++-----
 sugar/graphics/radiotoolbutton.py |   50 +++++++++++++++++++++----
 sugar/graphics/toolbutton.py      |   74 +++++++++++++++++++++++++++++++-----
 4 files changed, 135 insertions(+), 41 deletions(-)

diff --git a/sugar/activity/activity.py b/sugar/activity/activity.py
index 146d863..2c1eaae 100644
--- a/sugar/activity/activity.py
+++ b/sugar/activity/activity.py
@@ -28,6 +28,7 @@ See the methods of the Activity class below for more information on what you
 will need for a real activity.
 """
 # Copyright (C) 2006-2007 Red Hat, Inc.
+# Copyright (C) 2007-2008 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
@@ -125,14 +126,14 @@ class ActivityToolbar(gtk.Toolbar):
 
         self._update_share()
 
-        self.keep = ToolButton('document-save')
-        self.keep.set_tooltip(_('Keep'))
+        self.keep = ToolButton('document-save', tooltip=_('Keep'))
+        self.keep.props.accelerator = '<Ctrl>S'
         self.keep.connect('clicked', self.__keep_clicked_cb)
         self.insert(self.keep, -1)
         self.keep.show()
 
-        self.stop = ToolButton('activity-stop')
-        self.stop.set_tooltip(_('Stop'))
+        self.stop = ToolButton('activity-stop', tooltip=_('Stop'))
+        self.stop.props.accelerator = '<Ctrl>Q'
         self.stop.connect('clicked', self.__stop_clicked_cb)
         self.insert(self.stop, -1)
         self.stop.show()
@@ -418,7 +419,6 @@ class Activity(Window, gtk.Container):
 
         self.connect('realize', self.__realize_cb)
         self.connect('delete-event', self.__delete_event_cb)
-        self.connect("key_press_event", self.__key_press_event_cb)
 
         self._active = False
         self._activity_id = handle.activity_id
@@ -433,6 +433,10 @@ class Activity(Window, gtk.Container):
         self._max_participants = 0
         self._invites_queue = []
 
+        accel_group = gtk.AccelGroup()
+        self.set_data('sugar-accel-group', accel_group)
+        self.add_accel_group(accel_group)
+
         self._bus = ActivityService(self)
         self._owns_file = False
 
@@ -905,13 +909,6 @@ class Activity(Window, gtk.Container):
 
     metadata = property(get_metadata, None)
 
-    def __key_press_event_cb(self, widget, event):
-        key = gtk.gdk.keyval_name(event.keyval)
-        if key == 's' and (event.state & gtk.gdk.CONTROL_MASK):
-            logging.debug('Keep requested')
-            self.copy()
-            return True
-
 def get_bundle_name():
     """Return the bundle name for the current process' bundle"""
     return os.environ['SUGAR_BUNDLE_NAME']
diff --git a/sugar/graphics/palette.py b/sugar/graphics/palette.py
index e84cc51..4430b96 100644
--- a/sugar/graphics/palette.py
+++ b/sugar/graphics/palette.py
@@ -1,4 +1,5 @@
 # Copyright (C) 2007, Eduardo Silva <[EMAIL PROTECTED]>
+# Copyright (C) 2008, 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
@@ -176,9 +177,9 @@ class Palette(gtk.Window):
 
         vbox = gtk.VBox()
 
-        self._label = gtk.Label()
-        self._label.set_size_request(-1, style.zoom(style.GRID_CELL_SIZE)
-                                          - 2*self.get_border_width())
+        self._label = gtk.AccelLabel('')
+        self._label.set_size_request(-1, style.zoom(style.GRID_CELL_SIZE) -
+                                         2 * self.get_border_width())
         self._label.set_alignment(0, 0.5)
         self._label.set_padding(style.DEFAULT_SPACING, 0)
 
@@ -186,7 +187,7 @@ class Palette(gtk.Window):
             self._label.set_max_width_chars(text_maxlen)
             self._label.set_ellipsize(pango.ELLIPSIZE_MIDDLE)
 
-        vbox.pack_start(self._label, False)
+        vbox.pack_start(self._label)
 
         self._secondary_box = gtk.VBox()
         vbox.pack_start(self._secondary_box)
@@ -220,7 +221,7 @@ class Palette(gtk.Window):
         self.connect('leave-notify-event',
                      self._leave_notify_event_cb)
 
-        self.set_primary_text(label, accel_path)
+        self.set_primary_text(label)
         self.set_group_id('default')
 
         self._mouse_detector = MouseSpeedDetector(self, 200, 5)
@@ -263,9 +264,9 @@ class Palette(gtk.Window):
         
         return gtk.gdk.Rectangle(x, y, width, height)
 
-    def set_primary_text(self, label, accel_path=None):
+    def set_primary_text(self, label):
         if label is not None:
-            self._label.set_markup("<b>"+label+"</b>")
+            self._label.set_markup('<b>%s</b>' % label)
             self._label.show()
 
     def set_content(self, widget):
@@ -302,6 +303,8 @@ class Palette(gtk.Window):
                     'mouse-enter', self._invoker_mouse_enter_cb)
                 self._leave_invoker_hid = self._invoker.connect(
                     'mouse-leave', self._invoker_mouse_leave_cb)
+                if hasattr(value.props, 'widget'):
+                    self._label.props.accel_widget = value.props.widget
         else:
             raise AssertionError
 
@@ -314,11 +317,15 @@ class Palette(gtk.Window):
     def do_size_request(self, requisition):
         gtk.Window.do_size_request(self, requisition)
 
-        requisition.width = max(requisition.width, self._full_request[0])
+        # gtk.AccelLabel request doesn't include the accelerator.
+        label_width = self._label.size_request()[0] + \
+                      self._label.get_accel_width() + \
+                      2 * self.get_border_width()
 
-        # Minimum width
         requisition.width = max(requisition.width,
-                                style.zoom(style.GRID_CELL_SIZE*2))
+                                style.zoom(style.GRID_CELL_SIZE * 2),
+                                label_width,
+                                self._full_request[0])
 
     def do_size_allocate(self, allocation):
         gtk.Window.do_size_allocate(self, allocation)
@@ -819,6 +826,10 @@ class WidgetInvoker(Invoker):
         Invoker.notify_popdown(self)
         self._widget.queue_draw()
 
+    def _get_widget(self):
+        return self._widget
+    widget = gobject.property(type=object, getter=_get_widget, setter=None)
+
 class CanvasInvoker(Invoker):
     def __init__(self, item):
         Invoker.__init__(self)
diff --git a/sugar/graphics/radiotoolbutton.py b/sugar/graphics/radiotoolbutton.py
index cb4ae25..f3fc858 100644
--- a/sugar/graphics/radiotoolbutton.py
+++ b/sugar/graphics/radiotoolbutton.py
@@ -1,5 +1,5 @@
 # Copyright (C) 2007, Red Hat, Inc.
-# Copyright (C) 2007, One Laptop Per Child
+# Copyright (C) 2007-2008, 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
@@ -16,19 +16,55 @@
 # Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 # Boston, MA 02111-1307, USA.
 
+import logging
+
 import gtk
+import gobject
 
 from sugar.graphics.icon import Icon
 from sugar.graphics.palette import Palette, ToolInvoker
+from sugar.graphics import toolbutton
 
 class RadioToolButton(gtk.RadioToolButton):
     __gtype_name__ = "SugarRadioToolButton"
 
-    def __init__(self, named_icon=None, group=None, xo_color=None):
-        gtk.RadioToolButton.__init__(self, group=group)
+    def __init__(self, named_icon=None, group=None, xo_color=None, **kwargs):
+        self._accelerator = None
+        self._tooltip = None
         self._palette = None
         self._xo_color = xo_color
-        self.set_named_icon(named_icon)
+
+        gobject.GObject.__init__(self, **kwargs)
+
+        if named_icon:
+            self.set_named_icon(named_icon)
+        if group:
+            self.props.group = group
+
+    def set_tooltip(self, tooltip):
+        self._tooltip = tooltip
+        if tooltip and self.palette is None:
+            self.palette = Palette(tooltip)
+        elif self.palette:
+            self.palette.set_primary_text(tooltip)
+            
+        # Set label, shows up when toolbar overflows
+        gtk.RadioToolButton.set_label(self, tooltip)
+
+    def get_tooltip(self):
+        return self._tooltip
+
+    tooltip = gobject.property(type=str, setter=set_tooltip, getter=get_tooltip)
+
+    def set_accelerator(self, accelerator):
+        self._accelerator = accelerator
+        toolbutton.setup_accelerator(self)
+
+    def get_accelerator(self):
+        return self._accelerator
+
+    accelerator = gobject.property(type=str, setter=set_accelerator,
+            getter=get_accelerator)
 
     def set_named_icon(self, named_icon):
         icon = Icon(icon_name=named_icon,
@@ -46,8 +82,7 @@ class RadioToolButton(gtk.RadioToolButton):
         self._palette = palette
         self._palette.props.invoker = ToolInvoker(self)
 
-    def set_tooltip(self, text):
-        self.set_palette(Palette(text))
+    palette = gobject.property(type=object, setter=set_palette, getter=get_palette)
 
     def do_expose_event(self, event):
         if self._palette and self._palette.is_up():
@@ -63,5 +98,4 @@ class RadioToolButton(gtk.RadioToolButton):
                                        self.allocation.height)
 
         gtk.RadioToolButton.do_expose_event(self, event)
-    
-    palette = property(get_palette, set_palette)
+
diff --git a/sugar/graphics/toolbutton.py b/sugar/graphics/toolbutton.py
index 26acc83..686bfe8 100644
--- a/sugar/graphics/toolbutton.py
+++ b/sugar/graphics/toolbutton.py
@@ -1,4 +1,5 @@
 # Copyright (C) 2007, Red Hat, Inc.
+# Copyright (C) 2008, 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
@@ -15,22 +16,78 @@
 # Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 # Boston, MA 02111-1307, USA.
 
+import logging
+
 import gtk
 import gobject
-import time
 
 from sugar.graphics.icon import Icon
 from sugar.graphics.palette import Palette, ToolInvoker
 
+def _add_accelerator(tool_button):
+    if not tool_button.props.accelerator or not tool_button.get_toplevel() or \
+            not tool_button.child:
+        return
+
+    # TODO: should we remove the accelerator from the prev top level?
+
+    accel_group = tool_button.get_toplevel().get_data('sugar-accel-group')
+    if not accel_group:
+        logging.warning('No gtk.AccelGroup in the top level window.')
+        return
+
+    keyval, mask = gtk.accelerator_parse(tool_button.props.accelerator)
+    # the accelerator needs to be set at the child, so the gtk.AccelLabel
+    # in the palette can pick it up.
+    tool_button.child.add_accelerator('clicked', accel_group, keyval, mask,
+                                      gtk.ACCEL_LOCKED | gtk.ACCEL_VISIBLE)
+
+def _hierarchy_changed_cb(tool_button, previous_toplevel):
+    _add_accelerator(tool_button)
+
+def setup_accelerator(tool_button):
+    _add_accelerator(tool_button)
+    tool_button.connect('hierarchy-changed', _hierarchy_changed_cb)
+
 class ToolButton(gtk.ToolButton):
     __gtype_name__ = "SugarToolButton"
 
-    def __init__(self, icon_name=None):
-        gtk.ToolButton.__init__(self)
+    def __init__(self, icon_name=None, **kwargs):
+        self._accelerator = None
+        self._tooltip = None
         self._palette = None
+
+        gobject.GObject.__init__(self, **kwargs)
+
         if icon_name:
             self.set_icon(icon_name)
-        self.connect('clicked', self._button_clicked_cb)
+
+        self.connect('clicked', self.__button_clicked_cb)
+
+    def set_tooltip(self, tooltip):
+        self._tooltip = tooltip
+        if tooltip and self.palette is None:
+            self.palette = Palette(tooltip)
+        elif self.palette:
+            self.palette.set_primary_text(tooltip)
+            
+        # Set label, shows up when toolbar overflows
+        gtk.ToolButton.set_label(self, tooltip)
+
+    def get_tooltip(self):
+        return self._tooltip
+
+    tooltip = gobject.property(type=str, setter=set_tooltip, getter=get_tooltip)
+
+    def set_accelerator(self, accelerator):
+        self._accelerator = accelerator
+        setup_accelerator(self)
+
+    def get_accelerator(self):
+        return self._accelerator
+
+    accelerator = gobject.property(type=str, setter=set_accelerator,
+            getter=get_accelerator)
 
     def set_icon(self, icon_name):
         icon = Icon(icon_name=icon_name)
@@ -46,11 +103,7 @@ class ToolButton(gtk.ToolButton):
         self._palette = palette
         self._palette.props.invoker = ToolInvoker(self)
 
-    def set_tooltip(self, text):
-        self.set_palette(Palette(text))
-
-        # Set label, shows up when toolbar overflows
-        self.set_label(text)
+    palette = gobject.property(type=object, setter=set_palette, getter=get_palette)
         
     def do_expose_event(self, event):
         if self._palette and self._palette.is_up():
@@ -67,8 +120,7 @@ class ToolButton(gtk.ToolButton):
 
         gtk.ToolButton.do_expose_event(self, event)
     
-    def _button_clicked_cb(self, widget):
+    def __button_clicked_cb(self, widget):
         if self._palette:
             self._palette.popdown(True)
 
-    palette = property(get_palette, set_palette)
-- 
1.5.2.5

_______________________________________________
Sugar mailing list
[email protected]
http://lists.laptop.org/listinfo/sugar

Reply via email to