Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarco Pesenti Gritti <marco@localhost.localdomain>2007-06-26 12:55:16 (GMT)
committer Marco Pesenti Gritti <marco@localhost.localdomain>2007-06-26 12:55:16 (GMT)
commit3eaeebc60e9045a99aeac9616ccf25be6ec28370 (patch)
treea9013402157a2f62e3e60b4173521dff6c05ee09
parent5c3c7be96667b3a833633d131c47a9457f70409b (diff)
Lots of palette refactoring.
-rw-r--r--lib/Makefile.am2
-rw-r--r--lib/sugar-menu.c71
-rw-r--r--lib/sugar-menu.h53
-rw-r--r--shell/view/home/HomeBox.py3
-rw-r--r--sugar/_sugarext.defs25
-rw-r--r--sugar/_sugarext.override2
-rw-r--r--sugar/graphics/menu.py2
-rw-r--r--sugar/graphics/palette.py206
-rw-r--r--sugar/graphics/toolbutton.py3
9 files changed, 261 insertions, 106 deletions
diff --git a/lib/Makefile.am b/lib/Makefile.am
index 2ade166..445307e 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -17,6 +17,8 @@ libsugar_la_SOURCES = \
sugar-address-entry.h \
sugar-key-grabber.c \
sugar-key-grabber.h \
+ sugar-menu.h \
+ sugar-menu.c \
sugar-x11-util.c \
sugar-x11-util.h
diff --git a/lib/sugar-menu.c b/lib/sugar-menu.c
new file mode 100644
index 0000000..822b4a7
--- /dev/null
+++ b/lib/sugar-menu.c
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2006-2007, Red Hat, Inc.
+ *
+ * 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.
+ */
+
+#include <gtk/gtkwindow.h>
+
+#include "sugar-menu.h"
+
+static void sugar_menu_class_init (SugarMenuClass *menu_class);
+static void sugar_menu_init (SugarMenu *menu);
+
+
+G_DEFINE_TYPE(SugarMenu, sugar_menu, GTK_TYPE_MENU)
+
+static void
+sugar_menu_class_init(SugarMenuClass *menu_class)
+{
+}
+
+static void
+sugar_menu_init(SugarMenu *menu)
+{
+}
+
+void
+sugar_menu_popup(SugarMenu *menu,
+ int x,
+ int y)
+{
+ GtkWidget *window;
+
+ window = GTK_WIDGET(menu)->parent;
+ g_return_if_fail(window != NULL);
+
+ GTK_MENU_SHELL(menu)->active = TRUE;
+
+ gtk_widget_show(GTK_WIDGET(menu));
+
+ gtk_window_move(GTK_WINDOW(window), x, y);
+ gtk_widget_show(window);
+}
+
+void
+sugar_menu_popdown(SugarMenu *menu)
+{
+ GtkWidget *window;
+
+ window = GTK_WIDGET(menu)->parent;
+ g_return_if_fail(window != NULL);
+
+ GTK_MENU_SHELL(menu)->active = FALSE;
+
+ gtk_widget_hide(GTK_WIDGET(menu));
+ gtk_widget_hide(window);
+}
+
diff --git a/lib/sugar-menu.h b/lib/sugar-menu.h
new file mode 100644
index 0000000..a9c3f67
--- /dev/null
+++ b/lib/sugar-menu.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2006-2007, Red Hat, Inc.
+ *
+ * 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.
+ */
+
+#ifndef __SUGAR_MENU_H__
+#define __SUGAR_MENU_H__
+
+#include <gtk/gtkmenu.h>
+
+G_BEGIN_DECLS
+
+typedef struct _SugarMenu SugarMenu;
+typedef struct _SugarMenuClass SugarMenuClass;
+
+#define SUGAR_TYPE_MENU (sugar_menu_get_type())
+#define SUGAR_MENU(object) (G_TYPE_CHECK_INSTANCE_CAST((object), SUGAR_TYPE_MENU, SugarMenu))
+#define SUGAR_MENU_CLASS(klass) (G_TYPE_CHACK_CLASS_CAST((klass), SUGAR_TYPE_MENU, SugarMenuClass))
+#define SUGAR_IS_MENU(object) (G_TYPE_CHECK_INSTANCE_TYPE((object), SUGAR_TYPE_MENU))
+#define SUGAR_IS_MENU_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), SUGAR_TYPE_MENU))
+#define SUGAR_MENU_GET_CLASS(object) (G_TYPE_INSTANCE_GET_CLASS((object), SUGAR_TYPE_MENU, SugarMenuClass))
+
+struct _SugarMenu {
+ GtkMenu base_instance;
+};
+
+struct _SugarMenuClass {
+ GtkMenuClass base_class;
+};
+
+GType sugar_menu_get_type (void);
+void sugar_menu_popup (SugarMenu *menu,
+ int x,
+ int y);
+void sugar_menu_popdown (SugarMenu *menu);
+
+G_END_DECLS
+
+#endif /* __SUGAR_MENU_H__ */
diff --git a/shell/view/home/HomeBox.py b/shell/view/home/HomeBox.py
index 88fbc65..a42ef74 100644
--- a/shell/view/home/HomeBox.py
+++ b/shell/view/home/HomeBox.py
@@ -132,8 +132,7 @@ class HomeMyIcon(MyIcon):
MyIcon.__init__(self, scale)
self._shell = shell
- self._palette = Palette()
- self._palette.set_primary_state(profile.get_nick_name())
+ self._palette = Palette(profile.get_nick_name())
self._palette.props.invoker = CanvasInvoker(self)
shutdown_menu_item = gtk.MenuItem(_('Shutdown'))
diff --git a/sugar/_sugarext.defs b/sugar/_sugarext.defs
index 33f49f8..2e07b61 100644
--- a/sugar/_sugarext.defs
+++ b/sugar/_sugarext.defs
@@ -15,8 +15,33 @@
(gtype-id "SUGAR_TYPE_KEY_GRABBER")
)
+(define-object Menu
+ (in-module "Sugar")
+ (parent "GtkMenu")
+ (c-name "SugarMenu")
+ (gtype-id "SUGAR_TYPE_MENU")
+)
+
;; Enumerations and flags ...
+;; From sugar-menu.h
+
+(define-method popup
+ (of-object "SugarMenu")
+ (c-name "sugar_menu_popup")
+ (return-type "none")
+ (parameters
+ '("gint" "x")
+ '("gint" "y")
+ )
+)
+
+(define-method popdown
+ (of-object "SugarMenu")
+ (c-name "sugar_menu_popdown")
+ (return-type "none")
+)
+
;; From sugar-key-grabber.h
(define-function sugar_key_grabber_get_type
diff --git a/sugar/_sugarext.override b/sugar/_sugarext.override
index 0c1c5ea..7f798c2 100644
--- a/sugar/_sugarext.override
+++ b/sugar/_sugarext.override
@@ -6,6 +6,7 @@ headers
#include "pygobject.h"
#include "sugar-address-entry.h"
#include "sugar-key-grabber.h"
+#include "sugar-menu.h"
#include "sugar-x11-util.h"
#include "xdgmime.h"
@@ -17,6 +18,7 @@ modulename _sugarext
%%
import gobject.GObject as PyGObject_Type
import gtk.Entry as PyGtkEntry_Type
+import gtk.Menu as PyGtkMenu_Type
import gtk.gdk.Window as PyGdkWindow_Type
%%
ignore-glob
diff --git a/sugar/graphics/menu.py b/sugar/graphics/menu.py
index 14f471e..8aa0a64 100644
--- a/sugar/graphics/menu.py
+++ b/sugar/graphics/menu.py
@@ -88,7 +88,7 @@ class MenuItem(hippo.CanvasBox):
return hippo.CanvasBox.do_get_property(self, pspec)
class Menu(Popup):
- __gtype_name__ = 'SugarMenu'
+ __gtype_name__ = 'SugarCanvasMenu'
__gsignals__ = {
'action': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, ([object]))
diff --git a/sugar/graphics/palette.py b/sugar/graphics/palette.py
index 21c7995..919b3e7 100644
--- a/sugar/graphics/palette.py
+++ b/sugar/graphics/palette.py
@@ -21,6 +21,7 @@ import time
import hippo
from sugar.graphics import animator
+from sugar import _sugarext
ALIGNMENT_AUTOMATIC = 0
ALIGNMENT_BOTTOM_LEFT = 1
@@ -32,7 +33,7 @@ ALIGNMENT_RIGHT_TOP = 6
ALIGNMENT_TOP_LEFT = 7
ALIGNMENT_TOP_RIGHT = 8
-class Palette(gtk.Window):
+class Palette(gobject.GObject):
__gtype_name__ = 'SugarPalette'
__gproperties__ = {
@@ -43,12 +44,8 @@ class Palette(gtk.Window):
gobject.PARAM_READWRITE)
}
- _PADDING = 1
- _WIN_BORDER = 5
-
- def __init__(self, **kwargs):
- gobject.GObject.__init__(self, type=gtk.WINDOW_POPUP, **kwargs)
- gtk.Window.__init__(self)
+ def __init__(self, label, accel_path=None):
+ gobject.GObject.__init__(self)
self._alignment = ALIGNMENT_AUTOMATIC
@@ -60,35 +57,39 @@ class Palette(gtk.Window):
self._popdown_anim.add(_PopdownAnimation(self))
self._popdown_anim.start()
- self._palette_label = gtk.Label()
- self._palette_label.show()
+ self._menu = _sugarext.Menu()
- vbox = gtk.VBox(False, 0)
- vbox.pack_start(self._palette_label, True, True, self._PADDING)
+ primary = _PrimaryMenuItem(label, accel_path)
+ self._menu.append(primary)
+ primary.show()
- self._separator = gtk.HSeparator()
+ self._separator = gtk.SeparatorMenuItem()
+ self._menu.append(self._separator)
- self._menu_bar = gtk.MenuBar()
- self._menu_bar.set_pack_direction(gtk.PACK_DIRECTION_TTB)
+ self._content = _ContentMenuItem()
+ self._menu.append(self._content)
- self._content = gtk.HBox()
- self._button_bar = gtk.HButtonBox()
-
- # Set main container
- vbox.pack_start(self._separator, True, True, self._PADDING)
- vbox.pack_start(self._menu_bar, True, True, self._PADDING)
- vbox.pack_start(self._content, True, True, self._PADDING)
- vbox.pack_start(self._button_bar, True, True, self._PADDING)
+ self._button_bar = _ButtonBarMenuItem()
+ self._menu.append(self._button_bar)
- vbox.show()
- self.add(vbox)
+ self._menu.connect('enter-notify-event',
+ self._enter_notify_event_cb)
+ self._menu.connect('leave-notify-event',
+ self._leave_notify_event_cb)
+ self._menu.connect('button-press-event',
+ self._button_press_event_cb)
- # Widget events
- self.connect('enter-notify-event', self._enter_notify_event_cb)
- self.connect('leave-notify-event', self._leave_notify_event_cb)
- self.connect('button-press-event', self._button_press_event_cb)
+ def append_menu_item(self, item):
+ self._separator.show()
+ self._menu.insert(item, len(self._menu.get_children()) - 2)
+
+ def set_content(self, widget):
+ self._content.set_widget(widget)
+ self._content.show()
- self.set_border_width(self._WIN_BORDER)
+ def append_button(self, button):
+ self._button_bar.append_button(button)
+ self._button_bar.show()
def do_set_property(self, pspec, value):
if pspec.name == 'invoker':
@@ -99,109 +100,78 @@ class Palette(gtk.Window):
else:
raise AssertionError
- def place(self):
- # Automatic Alignment
+ def _get_position(self):
if self._alignment == ALIGNMENT_AUTOMATIC:
- # Trying Different types of ALIGNMENTS,
- # and return the choosen one
- if self._try_position(ALIGNMENT_BOTTOM_LEFT):
- return ALIGNMENT_BOTTOM_LEFT
- elif self._try_position(ALIGNMENT_BOTTOM_RIGHT):
- return ALIGNMENT_BOTTOM_RIGHT
- elif self._try_position(ALIGNMENT_LEFT_BOTTOM):
- return ALIGNMENT_LEFT_BOTTOM
- elif self._try_position(ALIGNMENT_LEFT_TOP):
- return ALIGNMENT_LEFT_TOP
- elif self._try_position(ALIGNMENT_RIGHT_BOTTOM):
- return ALIGNMENT_RIGHT_BOTTOM
- elif self._try_position(ALIGNMENT_RIGHT_TOP):
- return ALIGNMENT_RIGHT_TOP
- elif self._try_position(ALIGNMENT_TOP_LEFT):
- return ALIGNMENT_TOP_LEFT
- elif self._try_position(ALIGNMENT_TOP_RIGHT):
- return ALIGNMENT_TOP_RIGHT
+ x, y = self._try_position(ALIGNMENT_BOTTOM_LEFT)
+ if x == -1:
+ x, y = self._try_position(ALIGNMENT_BOTTOM_LEFT)
+ if x == -1:
+ x, y = self._try_position(ALIGNMENT_BOTTOM_RIGHT)
+ if x == -1:
+ x, y = self._try_position(ALIGNMENT_LEFT_BOTTOM)
+ if x == -1:
+ x, y = self._try_position(ALIGNMENT_LEFT_TOP)
+ if x == -1:
+ x, y = self._try_position(ALIGNMENT_RIGHT_BOTTOM)
+ if x == -1:
+ x, y = self._try_position(ALIGNMENT_RIGHT_TOP)
+ if x == -1:
+ x, y = self._try_position(ALIGNMENT_LEFT_BOTTOM)
+ if x == -1:
+ x, y = self._try_position(ALIGNMENT_LEFT_BOTTOM)
else:
- # Manual Alignment
- move_x, move_y = self._calc_position(self._alignment)
- self.move(move_x, move_y)
+ x, y = self._position_for_alignment(self._alignment)
+
+ return (x, y)
def _try_position(self, alignment):
- screen_width = gtk.gdk.screen_width()
- screen_height = gtk.gdk.screen_height()
- x, y = self._calc_position(alignment)
- self._width, self._height = self.size_request()
-
- if (x + self._width > screen_width) or \
- (y + self._height > screen_height):
- return False
+ x, y = self._position_for_alignment(alignment)
+ allocation = self._menu.get_allocation()
+
+ if (x + allocation.width > gtk.gdk.screen_width()) or \
+ (y + allocation.height > gtk.gdk.screen_height()):
+ return (-1, -1)
else:
- self.move(x, y)
- self.show()
- return True
+ return (x, y)
- def _calc_position(self, alignment):
+ def _position_for_alignment(self, alignment):
# Invoker: x, y, width and height
inv_rect = self._invoker.get_rect()
- palette_rectangle = self.get_allocation()
+ palette_rect = self._menu.get_allocation()
if alignment == ALIGNMENT_BOTTOM_LEFT:
move_x = inv_rect.x
move_y = inv_rect.y + inv_rect.height
-
elif alignment == ALIGNMENT_BOTTOM_RIGHT:
move_x = (inv_rect.x + inv_rect.width) - self._width
move_y = inv_rect.y + inv_rect.height
-
elif alignment == ALIGNMENT_LEFT_BOTTOM:
move_x = inv_rect.x - self._width
move_y = inv_rect.y
-
elif alignment == ALIGNMENT_LEFT_TOP:
move_x = inv_rect.x - self._width
- move_y = (inv_rect.y + inv_rect.height) - palette_rectangle.height
-
+ move_y = (inv_rect.y + inv_rect.height) - palette_rect.height
elif alignment == ALIGNMENT_RIGHT_BOTTOM:
move_x = inv_rect.x + inv_rect.width
move_y = inv_rect.y
-
elif alignment == ALIGNMENT_RIGHT_TOP:
move_x = inv_rect.x + inv_rect.width
- move_y = (inv_rect.y + inv_rect.height) - palette_rectangle.height
-
+ move_y = (inv_rect.y + inv_rect.height) - palette_rect.height
elif alignment == ALIGNMENT_TOP_LEFT:
move_x = inv_rect.x
- move_y = inv_rect.y - palette_rectangle.height
-
+ move_y = inv_rect.y - palette_rect.height
elif alignment == ALIGNMENT_TOP_RIGHT:
move_x = (inv_rect.x + inv_rect.width) - self._width
- move_y = inv_rect.y - palette_rectangle.height
+ move_y = inv_rect.y - palette_rect.height
return move_x, move_y
- def set_primary_state(self, label, accel_path=None):
- if accel_path != None:
- item = gtk.MenuItem(label)
- item.set_accel_path(accel_path)
- self.append_menu_item(item)
- self._separator.hide()
- else:
- self._palette_label.set_text(label)
+ def _show(self):
+ x, y = self._get_position()
+ self._menu.popup(x, y)
- def append_menu_item(self, item):
- self._separator.show()
- self._menu_bar.show()
- self._menu_bar.append(item)
- item.show()
-
- def set_content(self, widget):
- self._separator.show()
- self._content.pack_start(widget, True, True, self._PADDING)
- widget.show()
-
- def append_button(self, button):
- button.connect('released', self._close_palette_cb)
- self._button_bar.pack_start(button, True, True, self._PADDING)
- button.show()
+ def _hide(self):
+ self._menu.popdown()
def popup(self):
self._popdown_anim.stop()
@@ -228,6 +198,40 @@ class Palette(gtk.Window):
def _button_press_event_cb(self, widget, event):
pass
+class _PrimaryMenuItem(gtk.MenuItem):
+ def __init__(self, label, accel_path):
+ gtk.MenuItem.__init__(self)
+
+ label = gtk.AccelLabel(label)
+ label.set_accel_widget(self)
+
+ if accel_path:
+ self.set_accel_path(accel_path)
+ label.set_alignment(0.0, 0.5)
+
+ self.add(label)
+ label.show()
+
+class _ContentMenuItem(gtk.MenuItem):
+ def __init__(self):
+ gtk.MenuItem.__init__(self)
+
+ def set_widget(self, widget):
+ if self.child:
+ self.remove(self.child)
+ self.add(widget)
+
+class _ButtonBarMenuItem(gtk.MenuItem):
+ def __init__(self):
+ gtk.MenuItem.__init__(self)
+
+ self._hbar = gtk.HButtonBox()
+ self.add(self._hbar)
+ self._hbar.show()
+
+ def append_button(self, button):
+ self._hbar.pack_start(button)
+
class _PopupAnimation(animator.Animation):
def __init__(self, palette):
animator.Animation.__init__(self, 0.0, 1.0)
@@ -235,7 +239,7 @@ class _PopupAnimation(animator.Animation):
def next_frame(self, current):
if current == 1.0:
- self._palette.place()
+ self._palette._show()
class _PopdownAnimation(animator.Animation):
def __init__(self, palette):
@@ -244,7 +248,7 @@ class _PopdownAnimation(animator.Animation):
def next_frame(self, current):
if current == 1.0:
- self._palette.hide()
+ self._palette._hide()
class Invoker(object):
def __init__(self):
diff --git a/sugar/graphics/toolbutton.py b/sugar/graphics/toolbutton.py
index fe87717..2c85432 100644
--- a/sugar/graphics/toolbutton.py
+++ b/sugar/graphics/toolbutton.py
@@ -40,6 +40,5 @@ class ToolButton(gtk.ToolButton):
self._palette.props.invoker = WidgetInvoker(self.child)
def set_tooltip(self, text):
- self._palette = Palette()
- self._palette.set_primary_state(text)
+ self._palette = Palette(text)
self._palette.props.invoker = WidgetInvoker(self.child)