Ticket #4008: 0001-Add-support-for-locking-Palettes-SL-4008.patch

File 0001-Add-support-for-locking-Palettes-SL-4008.patch, 11.5 KB (added by erikos, 11 years ago)

New patch that (finally) handles as well the points raised in the ticket

  • src/sugar3/activity/widgets.py

    From 0d24d0be2f5ed51301dc02fa45c27bd8a3f803f9 Mon Sep 17 00:00:00 2001
    From: Simon Schampijer <simon@laptop.org>
    Date: Thu, 15 Nov 2012 18:09:00 +0100
    Subject: [PATCH toolkit-gtk3] Add support for locking Palettes, SL #4008
    
    This adds a property that indicates that a Palette should
    behave in a locking manner. The behaviour is the same
    as with the secondary Toolbars: when you hover over the invoking
    widget the Palette will popdown and react to mouse movements,
    leaving the invoker area or the Palette itself will popdown
    the Palette again. When you click the invoking widget
    the Palette will be locked. You have to unlock it again
    to pop it down.
    
    This patch makes the DescriptionButton and the Colorbutton
    work.
    
    If the DescriptionButton or the Colorbutton are placed in
    the primary toolbar they will share the locked state with
    the secondary toolbars. Only one can be locked at a time.
    
    When a secondary toolbar is unlocked we do force that the
    open Palettes are closed. Having a locking Palette in
    a subtoolbar will also work (Activity Toolbar case or
    ColorButton case in a few examples). There is no state
    sharing implemented here at the moment, but so far we
    do only have cases with one lockable Palette in a
    subtoolbar.
    
    This will also fix the case where we want to use the
    OSK to edit the description of the activity SL #3887.
    
    Signed-off-by: Simon Schampijer <simon@laptop.org>
    ---
     src/sugar3/activity/widgets.py       | 41 +++++++++++++++++++--------
     src/sugar3/graphics/colorbutton.py   | 34 +++++++++++++++++------
     src/sugar3/graphics/palettewindow.py | 54 ++++++++++++++++++++++++++++++++----
     src/sugar3/graphics/toolbarbox.py    |  1 +
     4 files changed, 105 insertions(+), 25 deletions(-)
    
    diff --git a/src/sugar3/activity/widgets.py b/src/sugar3/activity/widgets.py
    index 03b2415..b60fc66 100644
    a b class TitleEntry(Gtk.ToolItem): 
    219219            shared_activity.props.name = title
    220220
    221221
    222 class DescriptionItem(Gtk.ToolItem):
     222class DescriptionItem(ToolButton):
    223223
    224224    def __init__(self, activity, **kwargs):
    225         Gtk.ToolItem.__init__(self)
    226 
    227         description_button = ToolButton('edit-description')
    228         description_button.show()
    229         description_button.set_tooltip(_('Description'))
    230         description_button.palette_invoker.props.toggle_palette = True
    231         description_button.props.hide_tooltip_on_click = False
    232         self._palette = description_button.get_palette()
     225        ToolButton.__init__(self, 'edit-description', **kwargs)
     226        self.set_tooltip(_('Description'))
     227        self.palette_invoker.props.toggle_palette = True
     228        self.palette_invoker.props.lock_palette = True
     229        self.props.hide_tooltip_on_click = False
     230        self._palette = self.get_palette()
    233231
    234232        description_box = PaletteMenuBox()
    235233        sw = Gtk.ScrolledWindow()
    class DescriptionItem(Gtk.ToolItem): 
    251249        self._palette.set_content(description_box)
    252250        description_box.show_all()
    253251
    254         self.add(description_button)
    255 
    256252        activity.metadata.connect('updated', self.__jobject_updated_cb)
    257253
     254    def set_expanded(self, expanded):
     255        box = self.toolbar_box
     256        if not box:
     257            return
     258
     259        if not expanded:
     260            self.palette_invoker.notify_popdown()
     261            return
     262
     263        if box.expanded_button is not None:
     264            box.expanded_button.queue_draw()
     265            if box.expanded_button != self:
     266                box.expanded_button.set_expanded(False)
     267        box.expanded_button = self
     268
     269    def get_toolbar_box(self):
     270        parent = self.get_parent()
     271        if not hasattr(parent, 'owner'):
     272            return None
     273        return parent.owner
     274
     275    toolbar_box = property(get_toolbar_box)
     276
    258277    def _get_text_from_buffer(self):
    259278        buf = self._text_view.get_buffer()
    260279        start_iter = buf.get_start_iter()
  • src/sugar3/graphics/colorbutton.py

    diff --git a/src/sugar3/graphics/colorbutton.py b/src/sugar3/graphics/colorbutton.py
    index 823fd61..065a55e 100644
    a b class _ColorButton(Gtk.Button): 
    112112        return '#%.2X%.2X%.2X' % (fg_color.red * 255, fg_color.green * 255,
    113113                              fg_color.blue * 255)
    114114
    115     def do_clicked(self):
    116         if self._palette:
    117             if not self._palette.is_up():
    118                 self._palette.popup(immediate=True,
    119                                     state=self._palette.SECONDARY)
    120             else:
    121                 self._palette.popdown(immediate=True)
    122             return True
    123 
    124115    def set_color(self, color):
    125116        assert isinstance(color, Gdk.Color)
    126117
    class ColorToolButton(Gtk.ToolItem): 
    451442        color_button.icon_size = Gtk.IconSize.LARGE_TOOLBAR
    452443
    453444        self._palette_invoker.attach_tool(self)
     445        self._palette_invoker.props.toggle_palette = True
     446        self._palette_invoker.props.lock_palette = True
    454447
    455448        # This widget just proxies the following properties to the colorbutton
    456449        color_button.connect('notify::color', self.__notify_change)
    class ColorToolButton(Gtk.ToolItem): 
    489482    palette_invoker = GObject.property(
    490483        type=object, setter=set_palette_invoker, getter=get_palette_invoker)
    491484
     485    def set_expanded(self, expanded):
     486        box = self.toolbar_box
     487        if not box:
     488            return
     489
     490        if not expanded:
     491            self._palette_invoker.notify_popdown()
     492            return
     493
     494        if box.expanded_button is not None:
     495            box.expanded_button.queue_draw()
     496            if box.expanded_button != self:
     497                box.expanded_button.set_expanded(False)
     498        box.expanded_button = self
     499
     500    def get_toolbar_box(self):
     501        parent = self.get_parent()
     502        if not hasattr(parent, 'owner'):
     503            return None
     504        return parent.owner
     505
     506    toolbar_box = property(get_toolbar_box)
     507
    492508    def set_color(self, color):
    493509        self.get_child().props.color = color
    494510
  • src/sugar3/graphics/palettewindow.py

    diff --git a/src/sugar3/graphics/palettewindow.py b/src/sugar3/graphics/palettewindow.py
    index 0283551..cadb4fe 100644
    a b STABLE. 
    2424"""
    2525
    2626import logging
     27import math
    2728
    2829from gi.repository import Gdk
    2930from gi.repository import Gtk
    class PaletteWindow(GObject.GObject): 
    655656        self.popdown()
    656657
    657658    def _invoker_mouse_enter_cb(self, invoker):
    658         self.on_invoker_enter()
     659        if not self._invoker.locked:
     660            self.on_invoker_enter()
    659661
    660662    def _invoker_mouse_leave_cb(self, invoker):
    661         self.on_invoker_leave()
     663        if not self._invoker.locked:
     664            self.on_invoker_leave()
    662665
    663666    def _invoker_right_click_cb(self, invoker):
    664667        self.popup(immediate=True, state=self.SECONDARY)
    665668
    666669    def _invoker_toggle_state_cb(self, invoker):
    667         if self.is_up():
     670        if self.is_up() and self._palette_state == self.SECONDARY:
    668671            self.popdown(immediate=True)
    669672        else:
    670673            self.popup(immediate=True, state=self.SECONDARY)
    671674
    672675    def __enter_notify_cb(self, widget):
    673         self.on_enter()
     676        if not self._invoker.locked:
     677            self.on_enter()
    674678
    675679    def __leave_notify_cb(self, widget):
    676         self.on_leave()
     680        if not self._invoker.locked:
     681            self.on_leave()
    677682
    678683    def __show_cb(self, widget):
    679684        if self._invoker is not None:
    class Invoker(GObject.GObject): 
    774779        self._palette = None
    775780        self._cache_palette = True
    776781        self._toggle_palette = False
     782        self._lock_palette = False
     783        self.locked = False
    777784
    778785    def attach(self, parent):
    779786        self.parent = parent
    class Invoker(GObject.GObject): 
    10121019    button left click/touch tap. Defaults to False.
    10131020    """
    10141021
     1022    def get_lock_palette(self):
     1023        return self._lock_palette
     1024
     1025    def set_lock_palette(self, lock_palette):
     1026        self._lock_palette = lock_palette
     1027
     1028    lock_palette = GObject.property(type=object, setter=set_lock_palette,
     1029                                      getter=get_lock_palette)
     1030    """Whether the invoker will lock the Palette and
     1031    ignore mouse events. Defaults to False.
     1032    """
     1033
    10151034    def __palette_popdown_cb(self, palette):
    10161035        if not self.props.cache_palette:
    10171036            self.set_palette(None)
    class WidgetInvoker(Invoker): 
    10231042        Invoker.__init__(self)
    10241043
    10251044        self._widget = None
     1045        self._expanded = False
    10261046        self._enter_hid = None
    10271047        self._leave_hid = None
    10281048        self._release_hid = None
    10291049        self._click_hid = None
    10301050        self._touch_hid = None
     1051        self._draw_hid = None
    10311052        self._long_pressed_recognized = False
    10321053        self._long_pressed_hid = None
    10331054        self._long_pressed_controller = SugarGestures.LongPressController()
    class WidgetInvoker(Invoker): 
    10541075            self.__touch_event_cb)
    10551076        self._release_hid = self._widget.connect('button-release-event',
    10561077            self.__button_release_event_cb)
     1078        self._draw_hid = self._widget.connect_after('draw', self.__drawing_cb)
    10571079
    10581080        self._long_pressed_hid = self._long_pressed_controller.connect(
    10591081            'pressed', self.__long_pressed_event_cb, self._widget)
    10601082        self._long_pressed_controller.attach(self._widget,
    10611083            SugarGestures.EventControllerFlags.NONE)
     1084
    10621085        self.attach(parent)
    10631086
    10641087    def detach(self):
    class WidgetInvoker(Invoker): 
    10661089        self._widget.disconnect(self._enter_hid)
    10671090        self._widget.disconnect(self._leave_hid)
    10681091        self._widget.disconnect(self._release_hid)
     1092        self._widget.disconnect(self._draw_hid)
    10691093        if self._click_hid:
    10701094            self._widget.disconnect(self._click_hid)
    10711095        self._widget.disconnect(self._touch_hid)
    class WidgetInvoker(Invoker): 
    11261150        return False
    11271151
    11281152    def __click_event_cb(self, button):
     1153        if self.props.lock_palette:
     1154            if not self.locked:
     1155                self.locked = True
     1156                self.parent.set_expanded(True)
     1157
    11291158        if self.props.toggle_palette:
    11301159            self.notify_toggle_state()
    11311160
    class WidgetInvoker(Invoker): 
    11511180        self._widget.queue_draw()
    11521181
    11531182    def notify_popdown(self):
     1183        self.locked = False
    11541184        Invoker.notify_popdown(self)
    11551185        self._widget.queue_draw()
    11561186
    class WidgetInvoker(Invoker): 
    11581188        return self._widget
    11591189    widget = GObject.property(type=object, getter=_get_widget, setter=None)
    11601190
     1191    def __drawing_cb(self, widget, cr):
     1192        if not self.props.lock_palette:
     1193            return False
     1194        alloc = widget.get_allocation()
     1195        arrow_size = style.TOOLBAR_ARROW_SIZE / 2
     1196        y = alloc.height - arrow_size
     1197        x = (alloc.width - arrow_size) / 2
     1198        context = widget.get_style_context()
     1199        context.add_class('toolitem')
     1200        if self.locked:
     1201            Gtk.render_arrow(context, cr, 0, x, y, arrow_size)
     1202        else:
     1203            Gtk.render_arrow(context, cr, math.pi, x, y, arrow_size)
     1204
    11611205
    11621206class CursorInvoker(Invoker):
    11631207
  • src/sugar3/graphics/toolbarbox.py

    diff --git a/src/sugar3/graphics/toolbarbox.py b/src/sugar3/graphics/toolbarbox.py
    index 1683403..8c4e644 100644
    a b class ToolbarButton(ToolButton): 
    8989
    9090    def set_expanded(self, expanded):
    9191        self.popdown()
     92        palettegroup.popdown_all()
    9293
    9394        if self.page is None or self.is_expanded() == expanded:
    9495            return