Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniel Drake <dsd@laptop.org>2011-10-30 15:54:05 (GMT)
committer Daniel Drake <dsd@laptop.org>2011-10-30 15:54:05 (GMT)
commit21a820497b3e55cb8a007e5f10e36a721734db8d (patch)
tree252c486c158d8f1707b9b86869da6e721b49910e
parent13dc438894b74606c358c369472a7988fe500b82 (diff)
parent047d6edbbb6700cddce9481a87e7caf421cfdb76 (diff)
Merge branch 'master' of git.sugarlabs.org:~erikos/sugar-toolkit/sugar-toolkit-gtk3
-rw-r--r--src/sugar3/graphics/palette.py70
-rw-r--r--src/sugar3/graphics/palettewindow.py98
2 files changed, 124 insertions, 44 deletions
diff --git a/src/sugar3/graphics/palette.py b/src/sugar3/graphics/palette.py
index 7a2dcc7..7d5833e 100644
--- a/src/sugar3/graphics/palette.py
+++ b/src/sugar3/graphics/palette.py
@@ -29,7 +29,7 @@ from sugar3.graphics import palettegroup
from sugar3.graphics import animator
from sugar3.graphics import style
from sugar3.graphics.icon import Icon
-from sugar3.graphics import palettewindow
+from sugar3.graphics.palettewindow import PaletteWindow, _PaletteWindowWidget, _PaletteMenuWidget
# DEPRECATED
# Import these for backwards compatibility
@@ -37,7 +37,7 @@ from sugar3.graphics.palettewindow import MouseSpeedDetector, Invoker, \
WidgetInvoker, CanvasInvoker, ToolInvoker, CellRendererInvoker
-class Palette(palettewindow.PaletteWindow):
+class Palette(PaletteWindow):
PRIMARY = 0
SECONDARY = 1
@@ -52,19 +52,16 @@ class Palette(palettewindow.PaletteWindow):
# DEPRECATED: label is passed with the primary-text property,
# accel_path is set via the invoker property
- self.widget = palettewindow._PaletteWindowWidget()
-
-
self._primary_text = None
self._secondary_text = None
self._icon = None
self._icon_visible = True
self._palette_state = self.PRIMARY
- palette_box = Gtk.VBox()
+ self._palette_box = Gtk.VBox()
primary_box = Gtk.HBox()
- palette_box.pack_start(primary_box, False, True, 0)
+ self._palette_box.pack_start(primary_box, False, True, 0)
primary_box.show()
self._icon_box = Gtk.HBox()
@@ -98,7 +95,7 @@ class Palette(palettewindow.PaletteWindow):
labels_box.pack_start(self._secondary_label, True, True, 0)
self._secondary_box = Gtk.VBox()
- palette_box.pack_start(self._secondary_box, True, True, 0)
+ self._palette_box.pack_start(self._secondary_box, True, True, 0)
self._separator = Gtk.HSeparator()
self._secondary_box.pack_start(self._separator, True, True, 0)
@@ -107,7 +104,7 @@ class Palette(palettewindow.PaletteWindow):
self._secondary_anim.add(_SecondaryAnimation(self))
# we init after initializing all of our containers
- palettewindow.PaletteWindow.__init__(self, **kwargs)
+ PaletteWindow.__init__(self, **kwargs)
self._full_request = [0, 0]
self._content = None
@@ -122,13 +119,19 @@ class Palette(palettewindow.PaletteWindow):
self._secondary_box.pack_start(self.action_bar, True, True, 0)
self.action_bar.show()
- self.widget.add(palette_box)
- palette_box.show()
+ self._palette_box.show()
self.connect('notify::invoker', self.__notify_invoker_cb)
- self.widget.connect('realize', self.__realize_cb)
- self.widget.connect('hide', self.__hide_cb)
- self.widget.connect('destroy', self.__destroy_cb)
+ self.connect('popdown', self.__popdown_cb)
+
+ self._widget = None
+
+
+ def _setup_widget(self):
+ PaletteWindow._setup_widget(self)
+
+ # Why?
+ self._widget.connect('destroy', self.__destroy_cb)
def _invoker_right_click_cb(self, invoker):
self.popup(immediate=True, state=self.SECONDARY)
@@ -137,7 +140,7 @@ class Palette(palettewindow.PaletteWindow):
self._secondary_anim.stop()
self.popdown(immediate=True)
- def __hide_cb(self, widget):
+ def __popdown_cb(self, widget):
self._secondary_anim.stop()
def __notify_invoker_cb(self, palette, pspec):
@@ -157,7 +160,7 @@ class Palette(palettewindow.PaletteWindow):
if self._invoker is not None:
self._update_full_request()
- palettewindow.PaletteWindow.popup(self, immediate)
+ PaletteWindow.popup(self, immediate)
if state is None:
state = self.PRIMARY
@@ -173,10 +176,10 @@ class Palette(palettewindow.PaletteWindow):
self._secondary_anim.stop()
# to suppress glitches while later re-opening
self.set_palette_state(self.PRIMARY)
- palettewindow.PaletteWindow.popdown(self, immediate)
+ PaletteWindow.popdown(self, immediate)
def on_enter(self, event):
- palettewindow.PaletteWindow.on_enter(self, event)
+ PaletteWindow.on_enter(self, event)
self._secondary_anim.start()
def _add_content(self):
@@ -272,8 +275,16 @@ class Palette(palettewindow.PaletteWindow):
default=True,
getter=get_icon_visible,
setter=set_icon_visible)
-
+
def set_content(self, widget):
+ assert self._widget is None or isinstance(self._widget, _PaletteWindowWidget)
+
+ if self._widget is None:
+ self._widget = _PaletteWindowWidget()
+ self._setup_widget()
+
+ self._widget.add(self._palette_box)
+
if self._content.get_children():
self._content.remove(self._content.get_children()[0])
@@ -288,7 +299,7 @@ class Palette(palettewindow.PaletteWindow):
# We need to figure out how to do the size request with GTK+ 3.
# def do_size_request(self, requisition):
-# palettewindow.PaletteWindow.do_size_request(self, requisition)
+# PaletteWindow.do_size_request(self, requisition)
# # Gtk.AccelLabel request doesn't include the accelerator.
# label_width = self._label_alignment.size_request()[0] + \
@@ -305,16 +316,13 @@ class Palette(palettewindow.PaletteWindow):
def _update_accept_focus(self):
accept_focus = len(self._content.get_children())
- self.widget.set_accept_focus(accept_focus)
-
- def __realize_cb(self, widget):
- self._update_accept_focus()
+ self._widget.set_accept_focus(accept_focus)
def _update_full_request(self):
if self._palette_state == self.PRIMARY:
self._secondary_box.show()
- self._full_request = self.widget.size_request()
+ self._full_request = self._widget.size_request()
if self._palette_state == self.PRIMARY:
self._secondary_box.hide()
@@ -331,6 +339,18 @@ class Palette(palettewindow.PaletteWindow):
self._palette_state = state
+ def get_menu(self):
+ assert self._widget is None or isinstance(self._widget, _PaletteMenuWidget)
+
+ if self._widget is None:
+ self._widget = _PaletteMenuWidget()
+
+ self._setup_widget()
+
+ return self._widget
+
+ menu = GObject.property(type=object, getter=get_menu)
+
class PaletteActionBar(Gtk.HButtonBox):
diff --git a/src/sugar3/graphics/palettewindow.py b/src/sugar3/graphics/palettewindow.py
index 3406a10..6feb8c7 100644
--- a/src/sugar3/graphics/palettewindow.py
+++ b/src/sugar3/graphics/palettewindow.py
@@ -65,6 +65,52 @@ def _calculate_gap(a, b):
return False
+class _PaletteMenuWidget(Gtk.Menu):
+ def __init__(self):
+ Gtk.Menu.__init__(self)
+
+ accel_group = Gtk.AccelGroup()
+ self.set_data('sugar-accel-group', accel_group)
+ self.get_toplevel().add_accel_group(accel_group)
+
+ self._popup_position = (0, 0)
+
+ def set_accept_focus(self, focus):
+ pass
+
+ def get_origin(self):
+ res, x, y = self.get_toplevel().get_window().get_origin()
+ return x, y
+
+ def do_size_request(self, requisition):
+ Gtk.Window.do_size_request(self, requisition)
+ requisition.width = max(requisition.width, style.GRID_CELL_SIZE * 2)
+
+ def move(self, x, y):
+ self._popup_position = (x, y)
+
+ def do_draw(self, cr):
+
+ # TODO: Draw the border with gap here.
+ cr.set_source_rgb(0.5, 0.5, 0.5)
+ cr.paint()
+
+ # Fall trough to the container expose handler.
+ # (Leaving out the window expose handler which redraws everything)
+ Gtk.Bin.do_draw(self, cr)
+
+ def set_transient_for(self, window):
+ pass
+
+ def _position(self, widget, data):
+ return self._popup_position[0], self._popup_position[1], False
+
+ def popup(self):
+ Gtk.Menu.popup(self, None, None, self._position, None, 0, 0)
+
+ def popdown(self):
+ Gtk.Menu.popdown(self)
+
class _PaletteWindowWidget(Gtk.Window):
def __init__(self):
@@ -135,6 +181,11 @@ class _PaletteWindowWidget(Gtk.Window):
# (Leaving out the window expose handler which redraws everything)
Gtk.Bin.do_draw(self, cr)
+ def popup(self):
+ self.show()
+
+ def popdown(self):
+ self.hide()
class MouseSpeedDetector(GObject.GObject):
@@ -146,15 +197,15 @@ class MouseSpeedDetector(GObject.GObject):
_MOTION_SLOW = 1
_MOTION_FAST = 2
- def __init__(self, parent, delay, thresh):
+ def __init__(self, delay, thresh):
"""Create MouseSpeedDetector object,
delay in msec
threshold in pixels (per tick of 'delay' msec)"""
GObject.GObject.__init__(self)
+ self.parent = None
self._threshold = thresh
- self._parent = parent
self._delay = delay
self._state = None
self._timeout_hid = None
@@ -172,7 +223,7 @@ class MouseSpeedDetector(GObject.GObject):
self._state = None
def _get_mouse_position(self):
- display = self._parent.get_display()
+ display = self.parent.get_display()
manager = display.get_device_manager()
pointer_device = manager.get_client_pointer()
screen, x, y = pointer_device.get_position()
@@ -229,15 +280,22 @@ class PaletteWindow(GObject.GObject):
self.set_group_id('default')
- self.widget.connect('show', self.__show_cb)
- self.widget.connect('hide', self.__hide_cb)
- self.widget.connect('destroy', self.__destroy_cb)
- self.widget.connect('enter-notify-event', self.__enter_notify_event_cb)
- self.widget.connect('leave-notify-event', self.__leave_notify_event_cb)
-
- self._mouse_detector = MouseSpeedDetector(self.widget, 200, 5)
+ self._mouse_detector = MouseSpeedDetector(200, 5)
self._mouse_detector.connect('motion-slow', self._mouse_slow_cb)
+ def destroy(self):
+ if self._widget:
+ self._widget.destroy()
+
+ def _setup_widget(self):
+ self._widget.connect('show', self.__show_cb)
+ self._widget.connect('hide', self.__hide_cb)
+ self._widget.connect('destroy', self.__destroy_cb)
+ self._widget.connect('enter-notify-event', self.__enter_notify_event_cb)
+ self._widget.connect('leave-notify-event', self.__leave_notify_event_cb)
+
+ self._mouse_detector.parent = self._widget
+
def __destroy_cb(self, palette):
self.set_group_id(None)
self._mouse_detector.disconnect_by_func(self._mouse_slow_cb)
@@ -307,23 +365,24 @@ class PaletteWindow(GObject.GObject):
logging.error('Cannot update the palette position.')
return
- rect = self.widget.size_request()
+ rect = self._widget.size_request()
position = invoker.get_position_for_alignment(self._alignment, rect)
if position is None:
position = invoker.get_position(rect)
- self.widget.move(position.x, position.y)
+ self._widget.move(position.x, position.y)
def get_full_size_request(self):
- return self.widget.size_request()
+ return self._widget.size_request()
def popup(self, immediate=False):
+ logging.error("hello from popup")
if self._invoker is not None:
full_size_request = self.get_full_size_request()
self._alignment = self._invoker.get_alignment(full_size_request)
self.update_position()
- self.widget.set_transient_for(self._invoker.get_toplevel())
+ self._widget.set_transient_for(self._invoker.get_toplevel())
self._popdown_anim.stop()
@@ -331,7 +390,7 @@ class PaletteWindow(GObject.GObject):
self._popup_anim.start()
else:
self._popup_anim.stop()
- self.widget.show()
+ self._widget.popup()
# we have to invoke update_position() twice
# since WM could ignore first move() request
self.update_position()
@@ -345,8 +404,9 @@ class PaletteWindow(GObject.GObject):
else:
self._popdown_anim.stop()
# XXX: Please, someone remove or explain this :-)
- self.widget.size_request()
- self.widget.hide()
+ if self._widget is not None:
+ self._widget.size_request()
+ self._widget.popdown()
def on_invoker_enter(self):
self._popdown_anim.stop()
@@ -392,12 +452,12 @@ class PaletteWindow(GObject.GObject):
self.emit('popdown')
def get_rect(self):
- win_x, win_y = self.widget.get_origin()
+ win_x, win_y = self._widget.get_origin()
rectangle = self.get_allocation()
x = win_x + rectangle.x
y = win_y + rectangle.y
- requisition = self.widget.size_request()
+ requisition = self._widget.size_request()
rect = Gdk.Rectangle()
rect.x, rect.y, rect.width, rect.height = (x, y, requisition.width, requisition.height)