#include <gtk/gtk.h>

const char* ui = 
  "<interface>"
  "  <menu id='menu-somemenu'>"
  "    <submenu>"
  "      <attribute name='label' translatable='yes'>_View</attribute>"
  "      <section>"
  "        <item>"
  "          <attribute name='label' translatable='yes'>Zoom 200%</attribute>"
  "          <attribute name='action'>somemenu.zoom</attribute>"
  "          <attribute name='target'>200</attribute>"
  "        </item>"
  "        <item>"
  "          <attribute name='label' translatable='yes'>Zoom 100%</attribute>"
  "          <attribute name='action'>somemenu.zoom</attribute>"
  "          <attribute name='target'>100</attribute>"
  "        </item>"
  "        <item>"
  "          <attribute name='label' translatable='yes'>Zoom 50%</attribute>"
  "          <attribute name='action'>somemenu.zoom</attribute>"
  "          <attribute name='target'>50</attribute>"
  "        </item>"
  "        <item>"
  "          <attribute name='label' translatable='yes'>Zoom 25%</attribute>"
  "          <attribute name='action'>somemenu.zoom</attribute>"
  "          <attribute name='target'>25</attribute>"
  "        </item>"
  "      </section>"
  "    </submenu>"
  "  </menu>"
  "</interface>";

static GtkWidget *menu = NULL;

typedef void (* ActivateCallback) (GSimpleAction *action,
  GVariant  *parameter,
  gpointer  user_data);

static void
add_action_radio_int (GSimpleActionGroup *action_group, const char* name, gint32 initial_state, ActivateCallback callback)
{
  GSimpleAction* action = g_simple_action_new_stateful (name, G_VARIANT_TYPE_INT32, g_variant_new_int32(initial_state));

  if (callback) {
    g_signal_connect (action, "activate",
      G_CALLBACK (callback), NULL);
  }

  g_action_map_add_action (G_ACTION_MAP (action_group), G_ACTION (action));
  g_object_unref (action);
}


static void
on_menu_radio_item (GSimpleAction *action, GVariant* parameter, gpointer user_data)
{
  g_warning ("%s called.\n", G_STRFUNC);

  g_assert (parameter);
  g_assert (g_variant_is_of_type (parameter,  G_VARIANT_TYPE_INT32));

  gint32 state = g_variant_get_int32 (parameter);

/*
  GVariant *variant_state = g_action_get_state (G_ACTION (action));

  g_assert (variant_state);
  g_assert (g_variant_is_of_type (variant_state,  G_VARIANT_TYPE_INT32));
  gint32 state = g_variant_get_int32 (variant_state);
*/

  g_action_change_state (G_ACTION (action), parameter);
}



static gboolean
on_window_delete_event (GtkWidget *widget,
  GdkEvent  *event,
  gpointer   data)
{
  return FALSE;
}

static void
on_window_destroy (GtkWidget *widget,
  gpointer data )
{
  gtk_main_quit ();
}

int
main (int argc, char *argv[])
{
  gtk_init (&argc, &argv);

  GtkWidget *window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
  gtk_widget_show (window);

  g_signal_connect (window, "delete-event",
    G_CALLBACK (on_window_delete_event), NULL);
  g_signal_connect (window, "destroy",
    G_CALLBACK (on_window_destroy), NULL);


  GtkBuilder *builder = gtk_builder_new();

  GError* error = NULL;
  gtk_builder_add_from_string (builder, ui, -1, &error);
  g_assert_no_error (error);

  GMenu* gmenu = G_MENU (gtk_builder_get_object (builder, "menu-somemenu"));
  g_assert (gmenu);

  menu = gtk_menu_bar_new_from_model (G_MENU_MODEL (gmenu));
  g_assert (menu);

  /* This doesn't work, so we must use the SimpleActionGroup to specify a callback instead: */
  /*
  GMenuItem* menu_item = G_MENU_ITEM (gtk_builder_get_object (builder,
"something"));
  g_assert (menu_item);
  */

  GSimpleActionGroup *action_group = g_simple_action_group_new ();

  add_action_radio_int (action_group, "zoom", 100, on_menu_radio_item);

  gtk_widget_insert_action_group(GTK_WIDGET (window), "somemenu", G_ACTION_GROUP (action_group));

  GtkWidget* box = gtk_box_new(GTK_ORIENTATION_VERTICAL, 6);
  gtk_widget_show (box);
  gtk_container_add (GTK_CONTAINER (window), box);
 
  gtk_box_pack_start (GTK_BOX (box), menu, FALSE, TRUE, 6);
  gtk_widget_show (menu);


  gtk_main ();

  g_object_unref (G_OBJECT (builder));
  g_object_unref (G_OBJECT (action_group));
   
  return 0;
}
