+2008-07-28 Alberto Garcia <agarcia@igalia.com>
+
+ * src/hildon-app-menu-private.h
+ * src/hildon-app-menu.c (hildon_app_menu_button_press)
+ (hildon_app_menu_button_release, hildon_app_menu_init)
+ (hildon_app_menu_class_init): Don't hide the menu on button
+ release if the user didn't press outside first.
+
+ * src/hildon-window.h
+ * src/hildon-window.c (hildon_window_toggle_menu)
+ (hildon_window_toggle_menu_real, hildon_window_class_init): Make
+ hildon_window_toggle_menu a virtual function for the stackable
+ window to override it.
+
+ * src/hildon-stackable-window.h
+ * src/hildon-stackable-window-private.h
+ * src/hildon-stackable-window.c
+ (hildon_stackable_window_realize)
+ (hildon_stackable_window_finalize)
+ (hildon_stackable_window_class_init)
+ (hildon_stackable_window_init)
+ (hildon_stackable_window_set_main_menu): New function to set the
+ app menu of a HildonStackableWindow.
+
+ * examples/hildon-app-menu-example.c: Remove the button to show
+ the app menu, now it'll be shown when clicking on the title bar
+ instead.
+
2008-07-22 Claudio Saavedra <csaavedra@igalia.com>
* src/hildon-button.c: (hildon_button_set_arrangement): Do not
*/
#include <gtk/gtk.h>
+#include <hildon-stackable-window.h>
#include <hildon-app-menu.h>
static void
GtkLabel *label)
{
const char *buttontext = gtk_button_get_label (button);
- char *text = g_strdup_printf("Last button clicked:\n%s", buttontext);
+ char *text = g_strdup_printf("Last option selected:\n%s", buttontext);
gtk_label_set_text (label, text);
g_free (text);
}
}
static void
-button_clicked (GtkButton *button,
- HildonAppMenu *menu)
-{
- gtk_widget_show (GTK_WIDGET (menu));
-}
-
-static void
close_app (GtkWidget *widget,
GdkEvent *event,
GtkWidget *menu)
char **argv)
{
GtkWidget *win;
- GtkWidget *button;
GtkWidget *label;
GtkWidget *label2;
GtkBox *vbox;
"}\n"
"class \"HildonAppMenu\" style \"default\"\n");
- button = gtk_button_new_with_label ("Press me");
- label = gtk_label_new ("This is an example of the\nHildonAppMenu widget");
- label2 = gtk_label_new ("No button has been clicked");
+ label = gtk_label_new ("This is an example of the\nHildonAppMenu widget.\n\n"
+ "Click on the titlebar\nto pop up the menu.");
+ label2 = gtk_label_new ("No menu option has been selected yet.");
+
+ gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_CENTER);
+ gtk_label_set_justify (GTK_LABEL (label2), GTK_JUSTIFY_CENTER);
+
vbox = GTK_BOX (gtk_vbox_new (FALSE, 10));
- win = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+ win = hildon_stackable_window_new ();
menu = create_menu (label2);
+ hildon_stackable_window_set_main_menu (HILDON_STACKABLE_WINDOW (win), menu);
+
gtk_box_pack_start (vbox, label, TRUE, TRUE, 0);
- gtk_box_pack_start (vbox, button, TRUE, TRUE, 0);
gtk_box_pack_start (vbox, label2, TRUE, TRUE, 0);
gtk_container_set_border_width (GTK_CONTAINER (win), 20);
gtk_container_add (GTK_CONTAINER (win), GTK_WIDGET (vbox));
- g_signal_connect (button, "clicked", G_CALLBACK(button_clicked), menu);
g_signal_connect (win, "delete_event", G_CALLBACK(close_app), menu);
gtk_widget_show_all (win);
GtkSizeGroup *sizegroup;
GdkWindow *transfer_window;
int nitems;
+ gboolean pressed_outside;
};
}
static gboolean
-hildon_app_menu_button_release (GtkWidget *widget,
+hildon_app_menu_button_press (GtkWidget *widget,
GdkEventButton *event)
{
int x, y;
- gboolean released_outside;
+ HildonAppMenuPrivate *priv = HILDON_APP_MENU_GET_PRIVATE(widget);
gdk_window_get_position (widget->window, &x, &y);
- /* Whether the button has been released outside the widget */
- released_outside = (event->x_root < x || event->x_root > x + widget->allocation.width ||
- event->y_root < y || event->y_root > y + widget->allocation.height);
+ /* Whether the button has been pressed outside the widget */
+ priv->pressed_outside = (event->x_root < x || event->x_root > x + widget->allocation.width ||
+ event->y_root < y || event->y_root > y + widget->allocation.height);
+
+ if (GTK_WIDGET_CLASS (hildon_app_menu_parent_class)->button_press_event) {
+ return GTK_WIDGET_CLASS (hildon_app_menu_parent_class)->button_press_event (widget, event);
+ } else {
+ return FALSE;
+ }
+}
+
+static gboolean
+hildon_app_menu_button_release (GtkWidget *widget,
+ GdkEventButton *event)
+{
+ HildonAppMenuPrivate *priv = HILDON_APP_MENU_GET_PRIVATE(widget);
+
+ if (priv->pressed_outside) {
+ int x, y;
+ gboolean released_outside;
+
+ gdk_window_get_position (widget->window, &x, &y);
+
+ /* Whether the button has been released outside the widget */
+ released_outside = (event->x_root < x || event->x_root > x + widget->allocation.width ||
+ event->y_root < y || event->y_root > y + widget->allocation.height);
+
+ if (released_outside) {
+ gtk_widget_hide (widget);
+ }
- if (released_outside) {
- gtk_widget_hide (widget);
+ priv->pressed_outside = FALSE; /* Always reset pressed_outside to FALSE */
}
if (GTK_WIDGET_CLASS (hildon_app_menu_parent_class)->button_release_event) {
priv->sizegroup = GTK_SIZE_GROUP (gtk_size_group_new (GTK_SIZE_GROUP_BOTH));
priv->nitems = 0;
priv->transfer_window = NULL;
+ priv->pressed_outside = FALSE;
/* Set spacing between table elements */
gtk_table_set_row_spacings (priv->table, vertical_spacing);
widget_class->map = hildon_app_menu_map;
widget_class->unmap = hildon_app_menu_unmap;
widget_class->realize = hildon_app_menu_realize;
+ widget_class->button_press_event = hildon_app_menu_button_press;
widget_class->button_release_event = hildon_app_menu_button_release;
g_type_class_add_private (klass, sizeof (HildonAppMenuPrivate));
struct _HildonStackableWindowPrivate
{
gboolean going_home;
+ HildonAppMenu *app_menu;
};
#define HILDON_STACKABLE_WINDOW_GET_PRIVATE(obj) \
}
}
+void
+hildon_stackable_window_set_main_menu (HildonStackableWindow *self,
+ HildonAppMenu *menu)
+{
+ HildonStackableWindowPrivate *priv;
+
+ g_return_if_fail (HILDON_IS_STACKABLE_WINDOW (self));
+ g_return_if_fail (!menu || HILDON_IS_APP_MENU (menu));
+ priv = HILDON_STACKABLE_WINDOW_GET_PRIVATE (self);
+
+ /* Remove reference to old menu */
+ if (priv->app_menu)
+ g_object_unref (priv->app_menu);
+
+ /* Add new menu */
+ priv->app_menu = menu;
+ if (priv->app_menu)
+ g_object_ref (priv->app_menu);
+}
+
+static gboolean
+hildon_stackable_window_toggle_menu (HildonWindow *self,
+ guint button,
+ guint32 time)
+{
+ HildonStackableWindowPrivate *priv;
+
+ g_return_val_if_fail (HILDON_IS_STACKABLE_WINDOW (self), FALSE);
+ priv = HILDON_STACKABLE_WINDOW_GET_PRIVATE (self);
+ g_assert (priv != NULL);
+
+ if (priv->app_menu)
+ {
+ if (GTK_WIDGET_MAPPED (GTK_WIDGET (priv->app_menu)))
+ gtk_widget_hide (GTK_WIDGET (priv->app_menu));
+ else
+ gtk_widget_show (GTK_WIDGET (priv->app_menu));
+
+ return TRUE;
+ }
+ else if (HILDON_WINDOW_CLASS (hildon_stackable_window_parent_class)->toggle_menu)
+ {
+ return HILDON_WINDOW_CLASS (hildon_stackable_window_parent_class)->toggle_menu (self, button, time);
+ }
+ else
+ {
+ return FALSE;
+ }
+}
+
static void
hildon_stackable_window_realize (GtkWidget *widget)
{
}
static void
+hildon_stackable_window_finalize (GObject *object)
+{
+ HildonStackableWindowPrivate *priv = HILDON_STACKABLE_WINDOW_GET_PRIVATE (object);
+
+ if (priv->app_menu) {
+ gtk_widget_destroy (GTK_WIDGET (priv->app_menu));
+ }
+}
+
+static void
hildon_stackable_window_class_init (HildonStackableWindowClass *klass)
{
+ GObjectClass *obj_class = G_OBJECT_CLASS (klass);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
HildonWindowClass *window_class = HILDON_WINDOW_CLASS (klass);
+ obj_class->finalize = hildon_stackable_window_finalize;
+
widget_class->map = hildon_stackable_window_map;
widget_class->unmap = hildon_stackable_window_unmap;
widget_class->realize = hildon_stackable_window_realize;
widget_class->delete_event = hildon_stackable_window_delete_event;
window_class->unset_program = hildon_stackable_window_unset_program;
+ window_class->toggle_menu = hildon_stackable_window_toggle_menu;
g_type_class_add_private (klass, sizeof (HildonStackableWindowPrivate));
}
static void
hildon_stackable_window_init (HildonStackableWindow *self)
{
- hildon_stackable_window_set_going_home (self, FALSE);
+ HildonStackableWindowPrivate *priv = HILDON_STACKABLE_WINDOW_GET_PRIVATE (self);
+
+ priv->going_home = FALSE;
+ priv->app_menu = NULL;
}
/**
#define __HILDON_STACKABLE_WINDOW_H__
#include "hildon-window.h"
+#include "hildon-app-menu.h"
G_BEGIN_DECLS
GtkWidget*
hildon_stackable_window_new (void);
+void
+hildon_stackable_window_set_main_menu (HildonStackableWindow *self,
+ HildonAppMenu *menu);
+
G_END_DECLS
#endif /* __HILDON_STACKABLE_WINDOW_H__ */
guint32 time);
static gboolean
+hildon_window_toggle_menu_real (HildonWindow * self,
+ guint button,
+ guint32 time);
+
+static gboolean
hildon_window_escape_timeout (gpointer data);
static GdkFilterReturn
/* To this class */
window_class->unset_program = hildon_window_unset_program_real;
+ window_class->toggle_menu = hildon_window_toggle_menu_real;
/* gtkobject stuff*/
GTK_OBJECT_CLASS (window_class)->destroy = hildon_window_destroy;
/* FIXME Why is this even needed here? */
}
+static gboolean
+hildon_window_toggle_menu (HildonWindow *self,
+ guint button,
+ guint32 time)
+{
+ g_return_val_if_fail (HILDON_IS_WINDOW (self), FALSE);
+
+ if (HILDON_WINDOW_GET_CLASS (self)->toggle_menu != NULL)
+ {
+ return HILDON_WINDOW_GET_CLASS (self)->toggle_menu (self, button, time);
+ }
+ else
+ {
+ return FALSE;
+ }
+}
+
+
/*
* Toggles the display of the HildonWindow menu.
* Returns whether or not something was done (whether or not we had a menu
* to toggle)
*/
static gboolean
-hildon_window_toggle_menu (HildonWindow * self,
+hildon_window_toggle_menu_real (HildonWindow * self,
guint button,
guint32 time)
{
/* opera hacks for clip board operation */
void (*clipboard_operation)(HildonWindow *hwindow, int operation);
void (*unset_program)(HildonWindow *hwindow);
+ gboolean (*toggle_menu)(HildonWindow * self, guint button, guint32 time);
/* Padding for future extension */
void (*_hildon_reserved1)(void);
- void (*_hildon_reserved2)(void);
};
GType G_GNUC_CONST