Add HildonAppMenu::changed signal
[hildon] / hildon / hildon-app-menu.c
index 12a80c4..06e8165 100644 (file)
@@ -128,20 +128,27 @@ filter_visibility_changed                       (GtkWidget     *item,
                                                  GParamSpec    *arg1,
                                                  HildonAppMenu *menu);
 
-static gboolean
-menu_item_button_event                          (GtkButton      *item,
-                                                 GdkEventButton *event,
-                                                 GtkWidget      *menu);
-
 static void
 remove_item_from_list                           (GList    **list,
                                                  gpointer   item);
 
 static void
+emit_menu_changed                               (HildonAppMenu *menu,
+                                                 gpointer item);
+
+static void
 hildon_app_menu_apply_style                     (GtkWidget *widget);
 
 G_DEFINE_TYPE (HildonAppMenu, hildon_app_menu, GTK_TYPE_WINDOW);
 
+enum
+{
+    CHANGED,
+    LAST_SIGNAL
+};
+
+static guint app_menu_signals[LAST_SIGNAL] = { 0 };
+
 /**
  * hildon_app_menu_new:
  *
@@ -199,6 +206,9 @@ hildon_app_menu_insert                          (HildonAppMenu *menu,
 
     /* Remove item from list when it is destroyed */
     g_object_weak_ref (G_OBJECT (item), (GWeakNotify) remove_item_from_list, &(priv->buttons));
+    g_object_weak_ref (G_OBJECT (item), (GWeakNotify) emit_menu_changed, menu);
+
+    g_signal_emit (menu, app_menu_signals[CHANGED], 0);
 }
 
 /**
@@ -306,6 +316,9 @@ hildon_app_menu_add_filter                      (HildonAppMenu *menu,
 
     /* Remove filter from list when it is destroyed */
     g_object_weak_ref (G_OBJECT (filter), (GWeakNotify) remove_item_from_list, &(priv->filters));
+    g_object_weak_ref (G_OBJECT (filter), (GWeakNotify) emit_menu_changed, menu);
+
+    g_signal_emit (menu, app_menu_signals[CHANGED], 0);
 }
 
 static void
@@ -433,6 +446,13 @@ remove_item_from_list                           (GList    **list,
 }
 
 static void
+emit_menu_changed                               (HildonAppMenu *menu,
+                                                 gpointer item)
+{
+    g_signal_emit (menu, app_menu_signals[CHANGED], 0);
+}
+
+static void
 hildon_app_menu_show_all                        (GtkWidget *widget)
 {
     HildonAppMenu *menu = HILDON_APP_MENU (widget);
@@ -528,6 +548,17 @@ hildon_app_menu_map                             (GtkWidget *widget)
         priv->find_intruder_idle_id = gdk_threads_add_idle (hildon_app_menu_find_intruder, widget);
 }
 
+static void
+hildon_app_menu_grab_notify                     (GtkWidget *widget,
+                                                 gboolean   was_grabbed)
+{
+    if (GTK_WIDGET_CLASS (hildon_app_menu_parent_class)->grab_notify)
+        GTK_WIDGET_CLASS (hildon_app_menu_parent_class)->grab_notify (widget, was_grabbed);
+
+    if (!was_grabbed && GTK_WIDGET_VISIBLE (widget))
+        gtk_widget_hide (widget);
+}
+
 static gboolean
 hildon_app_menu_hide_idle                       (gpointer widget)
 {
@@ -792,6 +823,39 @@ hildon_app_menu_repack_items                    (HildonAppMenu *menu,
             }
         }
     }
+
+    gtk_widget_queue_draw (GTK_WIDGET (menu));
+}
+
+/**
+ * hildon_app_menu_has_visible_children:
+ * @menu: a #HildonAppMenu
+ *
+ * Returns whether this menu has any visible items
+ * and/or filters. If this is %FALSE, the menu will
+ * not be popped up.
+ *
+ * Returns: whether there are visible items or filters
+ *
+ * Since: 2.2
+ **/
+gboolean
+hildon_app_menu_has_visible_children (HildonAppMenu *menu)
+{
+   HildonAppMenuPrivate *priv;
+   GList *i;
+   gboolean show_menu = FALSE;
+
+    priv = HILDON_APP_MENU_GET_PRIVATE (menu);
+
+    /* Don't show menu if it doesn't contain visible items */
+    for (i = priv->buttons; i && !show_menu; i = i->next)
+        show_menu = GTK_WIDGET_VISIBLE (i->data);
+
+    for (i = priv->filters; i && !show_menu; i = i->next)
+           show_menu = GTK_WIDGET_VISIBLE (i->data);
+
+    return show_menu;
 }
 
 /**
@@ -808,23 +872,10 @@ void
 hildon_app_menu_popup                           (HildonAppMenu *menu,
                                                  GtkWindow     *parent_window)
 {
-    HildonAppMenuPrivate *priv;
-    gboolean show_menu = FALSE;
-    GList *i;
-
     g_return_if_fail (HILDON_IS_APP_MENU (menu));
     g_return_if_fail (GTK_IS_WINDOW (parent_window));
 
-    priv = HILDON_APP_MENU_GET_PRIVATE (menu);
-
-    /* Don't show menu if it doesn't contain visible items */
-    for (i = priv->buttons; i && !show_menu; i = i->next)
-        show_menu = GTK_WIDGET_VISIBLE (i->data);
-
-    for (i = priv->filters; i && !show_menu; i = i->next)
-        show_menu = GTK_WIDGET_VISIBLE (i->data);
-
-    if (show_menu) {
+    if (hildon_app_menu_has_visible_children (menu)) {
         hildon_app_menu_set_parent_window (menu, parent_window);
         gtk_widget_show (GTK_WIDGET (menu));
     }
@@ -961,6 +1012,7 @@ hildon_app_menu_class_init                      (HildonAppMenuClass *klass)
     widget_class->map = hildon_app_menu_map;
     widget_class->realize = hildon_app_menu_realize;
     widget_class->unrealize = hildon_app_menu_unrealize;
+    widget_class->grab_notify = hildon_app_menu_grab_notify;
     widget_class->key_press_event = hildon_app_menu_key_press;
     widget_class->style_set = hildon_app_menu_style_set;
     widget_class->delete_event = hildon_app_menu_delete_event_handler;
@@ -1023,4 +1075,22 @@ hildon_app_menu_class_init                      (HildonAppMenuClass *klass)
             "the screen edges (in horizontal mode)",
             0, G_MAXUINT, 50,
             G_PARAM_READABLE));
+
+
+    /**
+     * HildonAppMenu::changed:
+     * @widget: the widget that received the signal
+     *
+     * The HildonAppMenu::changed signal is emitted whenever an
+     * item or filter is added or removed from the menu.
+     *
+     * Since: 2.2
+     */
+    app_menu_signals[CHANGED] =
+        g_signal_new ("changed",
+                      G_TYPE_FROM_CLASS (klass),
+                      G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+                      0,
+                      NULL, NULL,
+                      g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0, NULL);
 }