/* Test case - GtkNotebook does not fully remove disposed children
 */

#include <gtk/gtk.h>

#define GTK4 ((100*GTK_MAJOR_VERSION + GTK_MINOR_VERSION) > 390)

static GtkWidget* notebook;
static GtkWidget* label1;
static GtkWidget* label2;
static GtkWidget* label3;

static GQuark gtkmm_quark;

static void
destroy_notify_callback (gpointer data)
{
  /* Clear the widget pointer, marking that the widget has been deleted. */
  *((GtkWidget**)data) = NULL;
}

static void
initialize_widget(GtkWidget** widget)
{
  if (g_object_is_floating (*widget))
    g_object_ref_sink (*widget);
  g_object_set_qdata_full (G_OBJECT (*widget), gtkmm_quark, widget, &destroy_notify_callback);
}

static void
delete_widget (GtkWidget** widget)
{
  if (*widget)
    g_object_unref (*widget);

  /* If the last reference has been removed, destroy_notify_callback() has been
   * called, and it has cleared *widget.
   * If not, which happens if *widget is inside a container that keeps its own
   * reference, then get it out of the container with a call to g_object_run_dispose().
   */
  if (*widget)
    g_object_run_dispose (G_OBJECT (*widget));
}


static void
button_dispose_cb (GtkButton *button,
                   gpointer user_data)
{
  delete_widget (&label3);
}

static void
button_quit_cb (GtkButton *button,
                gpointer user_data)
{
  /* Delete notebook and labels in the inverse order from how they were
   * created (last created, first destroyed).
   */

  /* gtk+-4: If the notebook's pages are deleted before the notebook,
   * they are not removed from the notebook. They are removed from their
   * parent, which is a GtkStack.
   * gtk+-3: The notebook is the parent of its pages. Then it doesn't matter
   * in which order the notebook and its pages are deleted.
   */
#if 1
  /* Doesn't work in gtk+-4. */
  delete_widget (&label3);
  delete_widget (&label2);
  delete_widget (&label1);
  delete_widget (&notebook);
#else
  /* Works in gtk+-4, provided the dispose button has not been pressed. */
  delete_widget (&notebook);
  delete_widget (&label3);
  delete_widget (&label2);
  delete_widget (&label1);
#endif

  gtk_main_quit ();
}

gint
main (gint argc, gchar *argv[])
{
  GtkWidget *window, *box, *buttonbox, *button_dispose, *button_quit;

#if GTK4
  gtk_init ();
#else
  gtk_init (&argc, &argv);
#endif

  gtkmm_quark = g_quark_from_static_string ("gtkmm_quark");

  window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
  box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
  buttonbox = gtk_button_box_new (GTK_ORIENTATION_HORIZONTAL);
  button_dispose = gtk_button_new_with_label ("Dispose of tab 3");
  button_quit = gtk_button_new_with_label ("Quit");

  /* Create notebook and labels as they would be created in gtkmm,
   * if they are members of a class.
   */
  notebook = gtk_notebook_new ();
  initialize_widget (&notebook);

  label1 = gtk_label_new ("Contents of tab 1");
  initialize_widget (&label1);

  label2 = gtk_label_new ("Contents of tab 2");
  initialize_widget (&label2);

  label3 = gtk_label_new ("Contents of tab 3");
  initialize_widget (&label3);

  gtk_window_set_title (GTK_WINDOW (window), "GtkNotebook example");
  gtk_window_set_default_size (GTK_WINDOW (window), 400, 200);

  gtk_container_add (GTK_CONTAINER (window), box);

#if GTK4
  gtk_box_pack_start (GTK_BOX (box), notebook);
  gtk_widget_set_hexpand (notebook, TRUE);
  gtk_widget_set_vexpand (notebook, TRUE);
  gtk_widget_set_halign (notebook, GTK_ALIGN_FILL);
  gtk_widget_set_valign (notebook, GTK_ALIGN_FILL);
  gtk_box_pack_start (GTK_BOX (box), buttonbox);
  gtk_box_pack_start (GTK_BOX (buttonbox), button_dispose);
  gtk_box_pack_start (GTK_BOX (buttonbox), button_quit);
#else
  gtk_box_pack_start (GTK_BOX (box), notebook, TRUE, TRUE, 0);
  gtk_box_pack_start (GTK_BOX (box), buttonbox, FALSE, FALSE, 0);
  gtk_box_pack_start (GTK_BOX (buttonbox), button_dispose, FALSE, FALSE, 0);
  gtk_box_pack_start (GTK_BOX (buttonbox), button_quit, FALSE, FALSE, 0);
#endif

  g_signal_connect (button_dispose, "clicked", G_CALLBACK (button_dispose_cb), NULL);
  g_signal_connect (button_quit, "clicked", G_CALLBACK (button_quit_cb), NULL);
  g_signal_connect (window, "delete-event", G_CALLBACK (gtk_main_quit), NULL);

  /* Add the Notebook pages. */
  gtk_notebook_append_page (GTK_NOTEBOOK (notebook), label1, gtk_label_new ("First"));
  gtk_notebook_append_page (GTK_NOTEBOOK (notebook), label2, gtk_label_new ("Second"));
  gtk_notebook_append_page (GTK_NOTEBOOK (notebook), label3, gtk_label_new ("Third"));

#if GTK4
  gtk_widget_show (window);
#else
  gtk_widget_show_all (window);
#endif

  gtk_main ();

  return 0;
}
