* src/hildon-app-menu-private.h * src/hildon-app-menu.c (hildon_app_menu_button_press...
authorAlberto Garcia <agarcia@igalia.com>
Mon, 28 Jul 2008 18:43:44 +0000 (18:43 +0000)
committerAlberto Garcia <agarcia@igalia.com>
Mon, 28 Jul 2008 18:43:44 +0000 (18:43 +0000)
* 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.

ChangeLog
examples/hildon-app-menu-example.c
src/hildon-app-menu-private.h
src/hildon-app-menu.c
src/hildon-stackable-window-private.h
src/hildon-stackable-window.c
src/hildon-stackable-window.h
src/hildon-window.c
src/hildon-window.h

index cad8bf9..32a5de3 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,31 @@
+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
index cf64e2a..32cb9f1 100644 (file)
@@ -23,6 +23,7 @@
  */
 
 #include                                        <gtk/gtk.h>
+#include                                        <hildon-stackable-window.h>
 #include                                        <hildon-app-menu.h>
 
 static void
@@ -30,7 +31,7 @@ menu_button_clicked                             (GtkButton *button,
                                                  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);
 }
@@ -77,13 +78,6 @@ create_menu                                     (GtkWidget *label)
 }
 
 static void
-button_clicked                                  (GtkButton *button,
-                                                 HildonAppMenu *menu)
-{
-    gtk_widget_show (GTK_WIDGET (menu));
-}
-
-static void
 close_app                                       (GtkWidget *widget,
                                                  GdkEvent  *event,
                                                  GtkWidget *menu)
@@ -97,7 +91,6 @@ main                                            (int argc,
                                                  char **argv)
 {
     GtkWidget *win;
-    GtkWidget *button;
     GtkWidget *label;
     GtkWidget *label2;
     GtkBox *vbox;
@@ -110,22 +103,26 @@ main                                            (int argc,
                          "}\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);
index 069766b..b1ecc5c 100644 (file)
@@ -35,6 +35,7 @@ struct                                          _HildonAppMenuPrivate
     GtkSizeGroup *sizegroup;
     GdkWindow *transfer_window;
     int nitems;
+    gboolean pressed_outside;
 };
 
 
index e9ee900..714292f 100644 (file)
@@ -210,20 +210,46 @@ hildon_app_menu_unmap                           (GtkWidget *widget)
 }
 
 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) {
@@ -303,6 +329,7 @@ hildon_app_menu_init                            (HildonAppMenu *menu)
     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);
@@ -353,6 +380,7 @@ hildon_app_menu_class_init                      (HildonAppMenuClass *klass)
     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));
index f7058f5..906a90b 100644 (file)
@@ -32,6 +32,7 @@ typedef struct                                  _HildonStackableWindowPrivate Hi
 struct                                          _HildonStackableWindowPrivate
 {
     gboolean going_home;
+    HildonAppMenu *app_menu;
 };
 
 #define                                         HILDON_STACKABLE_WINDOW_GET_PRIVATE(obj) \
index 5fe4642..f457887 100644 (file)
@@ -188,6 +188,56 @@ hildon_stackable_window_unset_program           (HildonWindow *hwin)
     }
 }
 
+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)
 {
@@ -223,17 +273,31 @@ hildon_stackable_window_delete_event            (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));
 }
@@ -241,7 +305,10 @@ hildon_stackable_window_class_init              (HildonStackableWindowClass *kla
 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;
 }
 
 /**
index ee180f8..06a7bae 100644 (file)
@@ -26,6 +26,7 @@
 #define                                         __HILDON_STACKABLE_WINDOW_H__
 
 #include                                        "hildon-window.h"
+#include                                        "hildon-app-menu.h"
 
 G_BEGIN_DECLS
 
@@ -80,6 +81,10 @@ hildon_stackable_window_get_type                (void) G_GNUC_CONST;
 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__ */
index 28a25cd..bb0b79e 100644 (file)
@@ -206,6 +206,11 @@ hildon_window_toggle_menu                       (HildonWindow * self,
                                                 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
@@ -280,6 +285,7 @@ hildon_window_class_init                        (HildonWindowClass * window_clas
 
     /* 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; 
@@ -1555,13 +1561,31 @@ detach_menu_func                                (GtkWidget *attach_widget,
     /* 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)
 {
index 40a758d..728e8ac 100644 (file)
@@ -80,9 +80,9 @@ struct                                          _HildonWindowClass
     /* 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