diff options
author | Benjamin Berg <benjamin@sipsolutions.net> | 2011-10-30 15:54:13 (GMT) |
---|---|---|
committer | Benjamin Berg <benjamin@sipsolutions.net> | 2011-10-30 15:54:13 (GMT) |
commit | 047d6edbbb6700cddce9481a87e7caf421cfdb76 (patch) | |
tree | 5d4c039a98220eabe31c569f54ac8e4cdcb690af | |
parent | fdb0daa01d20535a7b87cfd2c9c3be019cb20e9f (diff) |
Basic nonworking menu added.
-rw-r--r-- | src/sugar3/graphics/palette.py | 70 | ||||
-rw-r--r-- | src/sugar3/graphics/palettewindow.py | 98 |
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) |