]> Pileus Git - ~andy/gtk/blobdiff - tests/testmerge.c
Remove GtkObject completely
[~andy/gtk] / tests / testmerge.c
index 193861329eab7508eb773a1d16487c00e732c89d..b1ca1e4072580085890efa735ba00b4a2ea36ecf 100644 (file)
@@ -1,7 +1,35 @@
+/* testmerge.c
+ * Copyright (C) 2003 James Henstridge
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library 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 "config.h"
+
 #include <stdio.h>
 #include <string.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
 #include <gtk/gtk.h>
 
+#ifndef STDOUT_FILENO
+#define STDOUT_FILENO 1 
+#endif
+
 struct { const gchar *filename; guint merge_id; } merge_ids[] = {
   { "merge-1.ui", 0 },
   { "merge-2.ui", 0 },
@@ -15,10 +43,37 @@ dump_tree (GtkWidget    *button,
   gchar *dump;
 
   dump = gtk_ui_manager_get_ui (merge);
-  g_message (dump);
+  g_message ("%s", dump);
   g_free (dump);
 }
 
+static void
+dump_accels (void)
+{
+  gtk_accel_map_save_fd (STDOUT_FILENO);
+}
+
+static void
+print_toplevel (GtkWidget *widget, gpointer user_data)
+{
+  g_print ("%s\n", G_OBJECT_TYPE_NAME (widget));
+}
+
+static void
+dump_toplevels (GtkWidget    *button, 
+               GtkUIManager *merge)
+{
+  GSList *toplevels;
+
+  toplevels = gtk_ui_manager_get_toplevels (merge, 
+                                           GTK_UI_MANAGER_MENUBAR |
+                                           GTK_UI_MANAGER_TOOLBAR |
+                                           GTK_UI_MANAGER_POPUP);
+
+  g_slist_foreach (toplevels, (GFunc) print_toplevel, NULL);
+  g_slist_free (toplevels);
+}
+
 static void
 toggle_tearoffs (GtkWidget    *button, 
                 GtkUIManager *merge)
@@ -30,6 +85,64 @@ toggle_tearoffs (GtkWidget    *button,
   gtk_ui_manager_set_add_tearoffs (merge, !add_tearoffs);
 }
 
+static gint
+delayed_toggle_dynamic (GtkUIManager *merge)
+{
+  GtkAction *dyn;
+  static GtkActionGroup *dynamic = NULL;
+  static guint merge_id = 0;
+
+  if (!dynamic)
+    {
+      dynamic = gtk_action_group_new ("dynamic");
+      gtk_ui_manager_insert_action_group (merge, dynamic, 0);
+      dyn = g_object_new (GTK_TYPE_ACTION,
+                         "name", "dyn1",
+                         "label", "Dynamic action 1",
+                         "stock_id", GTK_STOCK_COPY,
+                         NULL);
+      gtk_action_group_add_action (dynamic, dyn);
+      dyn = g_object_new (GTK_TYPE_ACTION,
+                         "name", "dyn2",
+                         "label", "Dynamic action 2",
+                         "stock_id", GTK_STOCK_EXECUTE,
+                         NULL);
+      gtk_action_group_add_action (dynamic, dyn);
+    }
+  
+  if (merge_id == 0)
+    {
+      merge_id = gtk_ui_manager_new_merge_id (merge);
+      gtk_ui_manager_add_ui (merge, merge_id, "/toolbar1/ToolbarPlaceholder", 
+                            "dyn1", "dyn1", 0, 0);
+      gtk_ui_manager_add_ui (merge, merge_id, "/toolbar1/ToolbarPlaceholder", 
+                            "dynsep", NULL, GTK_UI_MANAGER_SEPARATOR, 0);
+      gtk_ui_manager_add_ui (merge, merge_id, "/toolbar1/ToolbarPlaceholder", 
+                            "dyn2", "dyn2", 0, 0);
+
+      gtk_ui_manager_add_ui (merge, merge_id, "/menubar/EditMenu", 
+                            "dyn1menu", "dyn1", GTK_UI_MANAGER_MENU, 0);
+      gtk_ui_manager_add_ui (merge, merge_id, "/menubar/EditMenu/dyn1menu", 
+                            "dyn1", "dyn1", GTK_UI_MANAGER_MENUITEM, 0);
+      gtk_ui_manager_add_ui (merge, merge_id, "/menubar/EditMenu/dyn1menu/dyn1", 
+                            "dyn2", "dyn2", GTK_UI_MANAGER_AUTO, FALSE);
+    }
+  else 
+    {
+      gtk_ui_manager_remove_ui (merge, merge_id);
+      merge_id = 0;
+    }
+
+  return FALSE;
+}
+
+static void
+toggle_dynamic (GtkWidget    *button, 
+               GtkUIManager *merge)
+{
+  gdk_threads_add_timeout (2000, (GSourceFunc)delayed_toggle_dynamic, merge);
+}
+
 static void
 activate_action (GtkAction *action)
 {
@@ -45,7 +158,7 @@ toggle_action (GtkAction *action)
   const gchar *name = gtk_action_get_name (action);
   const gchar *typename = G_OBJECT_TYPE_NAME (action);
 
-  g_message ("Action %s (type=%s) activated (active=%d)", name, typename,
+  g_message ("ToggleAction %s (type=%s) toggled (active=%d)", name, typename,
             gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)));
 }
 
@@ -53,32 +166,39 @@ toggle_action (GtkAction *action)
 static void
 radio_action_changed (GtkAction *action, GtkRadioAction *current)
 {
-  g_message ("Action %s (type=%s) activated (active=%d) (value %d)", 
+  g_message ("RadioAction %s (type=%s) activated (active=%d) (value %d)", 
             gtk_action_get_name (GTK_ACTION (current)), 
             G_OBJECT_TYPE_NAME (GTK_ACTION (current)),
             gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (current)),
             gtk_radio_action_get_current_value (current));
 }
 
-
 static GtkActionEntry entries[] = {
   { "FileMenuAction", NULL, "_File" },
   { "EditMenuAction", NULL, "_Edit" },
   { "HelpMenuAction", NULL, "_Help" },
   { "JustifyMenuAction", NULL, "_Justify" },
+  { "EmptyMenu1Action", NULL, "Empty 1" },
+  { "EmptyMenu2Action", NULL, "Empty 2" },
   { "Test", NULL, "Test" },
 
-  { "QuitAction",  GTK_STOCK_QUIT,  NULL, "<control>q", NULL, G_CALLBACK (gtk_main_quit) },
-  { "NewAction",   GTK_STOCK_NEW,   NULL, "<control>n", NULL, G_CALLBACK (activate_action) },
-  { "New2Action",  GTK_STOCK_NEW,   NULL, "<control>m", NULL, G_CALLBACK (activate_action) },
-  { "OpenAction",  GTK_STOCK_OPEN,  NULL, "<control>o", NULL, G_CALLBACK (activate_action) },
-  { "CutAction",   GTK_STOCK_CUT,   NULL, "<control>x", NULL, G_CALLBACK (activate_action) },
-  { "CopyAction",  GTK_STOCK_COPY,  NULL, "<control>c", NULL, G_CALLBACK (activate_action) },
-  { "PasteAction", GTK_STOCK_PASTE, NULL, "<control>v", NULL, G_CALLBACK (activate_action) },
-  { "AboutAction", NULL,            "_About", NULL,     NULL, G_CALLBACK (activate_action) },
+  { "QuitAction",  GTK_STOCK_QUIT,  NULL,     "<control>q", "Quit", G_CALLBACK (gtk_main_quit) },
+  { "NewAction",   GTK_STOCK_NEW,   NULL,     "<control>n", "Create something", G_CALLBACK (activate_action) },
+  { "New2Action",  GTK_STOCK_NEW,   NULL,     "<control>m", "Create something else", G_CALLBACK (activate_action) },
+  { "OpenAction",  GTK_STOCK_OPEN,  NULL,     NULL,         "Open it", G_CALLBACK (activate_action) },
+  { "CutAction",   GTK_STOCK_CUT,   NULL,     "<control>x", "Knive", G_CALLBACK (activate_action) },
+  { "CopyAction",  GTK_STOCK_COPY,  NULL,     "<control>c", "Copy", G_CALLBACK (activate_action) },
+  { "PasteAction", GTK_STOCK_PASTE, NULL,     "<control>v", "Paste", G_CALLBACK (activate_action) },
+  { "AboutAction", NULL,            "_About", NULL,         "About", G_CALLBACK (activate_action) },
 };
 static guint n_entries = G_N_ELEMENTS (entries);
 
+static GtkToggleActionEntry toggle_entries[] = {
+  { "BoldAction",  GTK_STOCK_BOLD,  "_Bold",  "<control>b", "Make it bold", G_CALLBACK (toggle_action), 
+    TRUE },
+};
+static guint n_toggle_entries = G_N_ELEMENTS (toggle_entries);
+
 enum {
   JUSTIFY_LEFT,
   JUSTIFY_CENTER,
@@ -144,7 +264,7 @@ toggle_merge (GtkWidget    *button,
                                           "could not merge %s: %s", merge_ids[mergenum].filename,
                                           err->message);
 
-         g_signal_connect (G_OBJECT (dialog), "response", G_CALLBACK (gtk_object_destroy), NULL);
+         g_signal_connect (dialog, "response", G_CALLBACK (gtk_widget_destroy), NULL);
          gtk_widget_show (dialog);
 
          g_clear_error (&err);
@@ -169,8 +289,8 @@ set_name_func (GtkTreeViewColumn *tree_column,
   char *name;
   
   gtk_tree_model_get (tree_model, iter, 0, &action, -1);
-  g_object_get (G_OBJECT (action), "name", &name, NULL);
-  g_object_set (G_OBJECT (cell), "text", name, NULL);
+  g_object_get (action, "name", &name, NULL);
+  g_object_set (cell, "text", name, NULL);
   g_free (name);
   g_object_unref (action);
 }
@@ -186,8 +306,8 @@ set_sensitive_func (GtkTreeViewColumn *tree_column,
   gboolean sensitive;
   
   gtk_tree_model_get (tree_model, iter, 0, &action, -1);
-  g_object_get (G_OBJECT (action), "sensitive", &sensitive, NULL);
-  g_object_set (G_OBJECT (cell), "active", sensitive, NULL);
+  g_object_get (action, "sensitive", &sensitive, NULL);
+  g_object_set (cell, "active", sensitive, NULL);
   g_object_unref (action);
 }
 
@@ -203,8 +323,8 @@ set_visible_func (GtkTreeViewColumn *tree_column,
   gboolean visible;
   
   gtk_tree_model_get (tree_model, iter, 0, &action, -1);
-  g_object_get (G_OBJECT (action), "visible", &visible, NULL);
-  g_object_set (G_OBJECT (cell), "active", visible, NULL);
+  g_object_get (action, "visible", &visible, NULL);
+  g_object_set (cell, "active", visible, NULL);
   g_object_unref (action);
 }
 
@@ -222,8 +342,8 @@ sensitivity_toggled (GtkCellRendererToggle *cell,
   gtk_tree_model_get_iter (model, &iter, path);
 
   gtk_tree_model_get (model, &iter, 0, &action, -1);
-  g_object_get (G_OBJECT (action), "sensitive", &sensitive, NULL);
-  g_object_set (G_OBJECT (action), "sensitive", !sensitive, NULL);
+  g_object_get (action, "sensitive", &sensitive, NULL);
+  g_object_set (action, "sensitive", !sensitive, NULL);
   gtk_tree_model_row_changed (model, path, &iter);
   gtk_tree_path_free (path);
 }
@@ -242,8 +362,8 @@ visibility_toggled (GtkCellRendererToggle *cell,
   gtk_tree_model_get_iter (model, &iter, path);
 
   gtk_tree_model_get (model, &iter, 0, &action, -1);
-  g_object_get (G_OBJECT (action), "visible", &visible, NULL);
-  g_object_set (G_OBJECT (action), "visible", !visible, NULL);
+  g_object_get (action, "visible", &visible, NULL);
+  g_object_set (action, "visible", !visible, NULL);
   gtk_tree_model_row_changed (model, path, &iter);
   gtk_tree_path_free (path);
 }
@@ -308,6 +428,8 @@ create_tree_view (GtkUIManager *merge)
          gtk_list_store_append (store, &iter);
          gtk_list_store_set (store, &iter, 0, l->data, -1);
        }
+
+      g_list_free (actions);
     }
   
   tree_view = gtk_tree_view_new_with_model (GTK_TREE_MODEL (store));
@@ -371,24 +493,123 @@ static void
 activate_path (GtkWidget      *button,
               GtkUIManager   *merge)
 {
-  gtk_ui_manager_activate (merge, "/menubar/HelpMenu/About");
+  GtkAction *action = gtk_ui_manager_get_action (merge, 
+                                                "/menubar/HelpMenu/About");
+  if (action)
+    gtk_action_activate (action);
+  else 
+    g_message ("no action found");
+}
+
+typedef struct _ActionStatus ActionStatus;
+
+struct _ActionStatus {
+  GtkAction *action;
+  GtkWidget *statusbar;
+};
+
+static void
+action_status_destroy (gpointer data)
+{
+  ActionStatus *action_status = data;
+
+  g_object_unref (action_status->action);
+  g_object_unref (action_status->statusbar);
+
+  g_free (action_status);
+}
+
+static void
+set_tip (GtkWidget *widget)
+{
+  ActionStatus *data;
+  gchar *tooltip;
+  
+  data = g_object_get_data (G_OBJECT (widget), "action-status");
+  
+  if (data) 
+    {
+      g_object_get (data->action, "tooltip", &tooltip, NULL);
+      
+      gtk_statusbar_push (GTK_STATUSBAR (data->statusbar), 0, 
+                         tooltip ? tooltip : "");
+      
+      g_free (tooltip);
+    }
+}
+
+static void
+unset_tip (GtkWidget *widget)
+{
+  ActionStatus *data;
+
+  data = g_object_get_data (G_OBJECT (widget), "action-status");
+
+  if (data)
+    gtk_statusbar_pop (GTK_STATUSBAR (data->statusbar), 0);
+}
+                   
+static void
+connect_proxy (GtkUIManager *merge,
+              GtkAction    *action,
+              GtkWidget    *proxy,
+              GtkWidget    *statusbar)
+{
+  if (GTK_IS_MENU_ITEM (proxy)) 
+    {
+      ActionStatus *data;
+
+      data = g_object_get_data (G_OBJECT (proxy), "action-status");
+      if (data)
+       {
+         g_object_unref (data->action);
+         g_object_unref (data->statusbar);
+
+         data->action = g_object_ref (action);
+         data->statusbar = g_object_ref (statusbar);
+       }
+      else
+       {
+         data = g_new0 (ActionStatus, 1);
+
+         data->action = g_object_ref (action);
+         data->statusbar = g_object_ref (statusbar);
+
+         g_object_set_data_full (G_OBJECT (proxy), "action-status", 
+                                 data, action_status_destroy);
+         
+         g_signal_connect (proxy, "select",  G_CALLBACK (set_tip), NULL);
+         g_signal_connect (proxy, "deselect", G_CALLBACK (unset_tip), NULL);
+       }
+    }
 }
 
 int
 main (int argc, char **argv)
 {
   GtkActionGroup *action_group;
+  GtkAction *action;
   GtkUIManager *merge;
   GtkWidget *window, *table, *frame, *menu_box, *vbox, *view;
-  GtkWidget *button, *area;
+  GtkWidget *button, *area, *statusbar;
   gint i;
   
   gtk_init (&argc, &argv);
 
   action_group = gtk_action_group_new ("TestActions");
-  gtk_action_group_add_actions (action_group, entries, n_entries, NULL);
+  gtk_action_group_add_actions (action_group, 
+                               entries, n_entries, 
+                               NULL);
+  action = gtk_action_group_get_action (action_group, "EmptyMenu1Action");
+  g_object_set (action, "hide_if_empty", FALSE, NULL);
+  action = gtk_action_group_get_action (action_group, "EmptyMenu2Action");
+  g_object_set (action, "hide_if_empty", TRUE, NULL);
+  gtk_action_group_add_toggle_actions (action_group, 
+                                      toggle_entries, n_toggle_entries, 
+                                      NULL);
   gtk_action_group_add_radio_actions (action_group, 
                                      radio_entries, n_radio_entries, 
+                                     JUSTIFY_RIGHT,
                                      G_CALLBACK (radio_action_changed), NULL);
 
   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
@@ -408,17 +629,33 @@ main (int argc, char **argv)
   menu_box = gtk_vbox_new (FALSE, 0);
   gtk_container_set_border_width (GTK_CONTAINER (menu_box), 2);
   gtk_container_add (GTK_CONTAINER (frame), menu_box);
-  
+
+  statusbar = gtk_statusbar_new ();
+  gtk_box_pack_end (GTK_BOX (menu_box), statusbar, FALSE, FALSE, 0);
+    
   area = gtk_drawing_area_new ();
   gtk_widget_set_events (area, GDK_BUTTON_PRESS_MASK);
   gtk_widget_set_size_request (area, -1, 40);
   gtk_box_pack_end (GTK_BOX (menu_box), area, FALSE, FALSE, 0);
   gtk_widget_show (area);
 
+  button = gtk_button_new ();
+  gtk_box_pack_end (GTK_BOX (menu_box), button, FALSE, FALSE, 0);
+  gtk_activatable_set_related_action (GTK_ACTIVATABLE (button),
+                           gtk_action_group_get_action (action_group, "AboutAction"));
+
+  gtk_widget_show (button);
+
+  button = gtk_check_button_new ();
+  gtk_box_pack_end (GTK_BOX (menu_box), button, FALSE, FALSE, 0);
+  gtk_activatable_set_related_action (GTK_ACTIVATABLE (button),
+                           gtk_action_group_get_action (action_group, "BoldAction"));
+  gtk_widget_show (button);
+
   merge = gtk_ui_manager_new ();
 
-  g_signal_connect (area, "button_press_event",
-                   G_CALLBACK (area_press), merge);
+  g_signal_connect (merge, "connect-proxy", G_CALLBACK (connect_proxy), statusbar);
+  g_signal_connect (area, "button_press_event", G_CALLBACK (area_press), merge);
 
   gtk_ui_manager_insert_action_group (merge, action_group, 0);
   g_signal_connect (merge, "add_widget", G_CALLBACK (add_widget), menu_box);
@@ -447,6 +684,10 @@ main (int argc, char **argv)
   g_signal_connect (button, "clicked", G_CALLBACK (toggle_tearoffs), merge);
   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
 
+  button = gtk_check_button_new_with_label ("Dynamic");
+  g_signal_connect (button, "clicked", G_CALLBACK (toggle_dynamic), merge);
+  gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
+
   button = gtk_button_new_with_label ("Activate path");
   g_signal_connect (button, "clicked", G_CALLBACK (activate_path), merge);
   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
@@ -455,6 +696,14 @@ main (int argc, char **argv)
   g_signal_connect (button, "clicked", G_CALLBACK (dump_tree), merge);
   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
 
+  button = gtk_button_new_with_label ("Dump Toplevels");
+  g_signal_connect (button, "clicked", G_CALLBACK (dump_toplevels), merge);
+  gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
+
+  button = gtk_button_new_with_label ("Dump Accels");
+  g_signal_connect (button, "clicked", G_CALLBACK (dump_accels), NULL);
+  gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
+
   view = create_tree_view (merge);
   gtk_table_attach (GTK_TABLE (table), view, 1,2, 0,1,
                    GTK_FILL|GTK_EXPAND, GTK_FILL|GTK_EXPAND, 0, 0);
@@ -462,6 +711,41 @@ main (int argc, char **argv)
   gtk_widget_show_all (window);
   gtk_main ();
 
+#ifdef DEBUG_UI_MANAGER
+  {
+    GList *action;
+    
+    g_print ("\n> before unreffing the ui manager <\n");
+    for (action = gtk_action_group_list_actions (action_group);
+        action; 
+        action = action->next)
+      {
+       GtkAction *a = action->data;
+       g_print ("  action %s ref count %d\n", 
+                gtk_action_get_name (a), G_OBJECT (a)->ref_count);
+      }
+  }
+#endif
+
+  g_object_unref (merge);
+
+#ifdef DEBUG_UI_MANAGER
+  {
+    GList *action;
+
+    g_print ("\n> after unreffing the ui manager <\n");
+    for (action = gtk_action_group_list_actions (action_group);
+        action; 
+        action = action->next)
+      {
+       GtkAction *a = action->data;
+       g_print ("  action %s ref count %d\n", 
+                gtk_action_get_name (a), G_OBJECT (a)->ref_count);
+      }
+  }
+#endif
+
+  g_object_unref (action_group);
 
   return 0;
 }