/* gcc `pkg-config --cflags --libs glib-2.0 gio-2.0 gtk+-3.0` test.c -g -o test && ./test */

#include <glib.h>
#include <gtk/gtk.h>
#include <stdio.h>
#include <string.h>

static void
add_spinner_cb (GtkButton *button,
		GtkContainer *container)
{
	GtkWidget *spinner, *label;
	gchar buff[256];
	static gint counter = 0;

	spinner = gtk_spinner_new ();
	gtk_spinner_start (GTK_SPINNER (spinner));
	gtk_widget_show (spinner);
	gtk_container_add (container, spinner);

	counter++;
	sprintf (buff, "Spinner %d", counter);
	label = gtk_label_new (buff);
	gtk_label_set_ellipsize (GTK_LABEL (label), PANGO_ELLIPSIZE_END);
	gtk_widget_show (label);
	gtk_container_add (container, label);

	sprintf (buff, "_Add spinner %d", counter);
	gtk_button_set_label (button, buff);
}

static void
start_stop_spinners (GtkContainer *grid,
		     gboolean start)
{
	GList *children = gtk_container_get_children (grid), *ch;

	for (ch = children; ch; ch = ch->next) {
		if (GTK_IS_SPINNER (ch->data)) {
			if (start) {
				gtk_spinner_start (ch->data);
			} else {
				gtk_spinner_stop (ch->data);
			}
		}
	}

	g_list_free (children);
}

static void
start_spinners_cb (GtkButton *button,
		   GtkContainer *grid)
{
	start_stop_spinners (grid, TRUE);
}

static void
stop_spinners_cb (GtkButton *button,
		  GtkContainer *grid)
{
	start_stop_spinners (grid, FALSE);
}

static gboolean
idle_received_cb (gpointer user_data)
{
	GtkLabel *label = user_data;
	gtk_label_set_text (label, "IDLE received");
	return FALSE;
}

static void
schedule_idle_cb (GtkButton *button,
		  GtkLabel *label)
{
	gtk_label_set_text (label, "Scheduled IDLE, waiting for it...");
	g_idle_add (idle_received_cb, label);
}

static gboolean
timeout_received_cb (gpointer label)
{
	schedule_idle_cb (NULL, label);
	return FALSE;
}

static void
schedule_idle_timeout_cb (GtkButton *button,
			  GtkLabel *label)
{
	gtk_label_set_text (label, "Scheduled IDLE, waiting for timeout...");
	g_timeout_add_seconds (1, timeout_received_cb, label);
}

static void
async_thread (GSimpleAsyncResult *res,
	      GObject *object,
	      GCancellable *cancellable)
{
	g_usleep (G_USEC_PER_SEC * 2);
}

static void
async_received_cb (GObject *source_object,
		   GAsyncResult *result,
		   gpointer user_data)
{
	gtk_label_set_text (GTK_LABEL (source_object), "Async schedule received");
}

static void
schedule_async_cb (GtkButton *button,
		   GtkLabel *label)
{
	GSimpleAsyncResult *simple;

	gtk_label_set_text (label, "Scheduled async, waiting for it...");

	simple = g_simple_async_result_new (
		G_OBJECT (label), async_received_cb, NULL,
		schedule_async_cb);
	g_simple_async_result_run_in_thread (simple, async_thread, G_PRIORITY_DEFAULT_IDLE, NULL);
	g_object_unref (simple);
}

typedef struct _EShellTaskbar EShellTaskbar;
typedef struct _EShellTaskbarClass EShellTaskbarClass;

struct _EShellTaskbar {
	GtkBox parent;
};

struct _EShellTaskbarClass {
	GtkBoxClass parent_class;
};

GType		e_shell_taskbar_get_type	(void);

G_DEFINE_TYPE (EShellTaskbar, e_shell_taskbar, GTK_TYPE_HBOX);
static void
shell_taskbar_get_preferred_width (GtkWidget *widget,
                                   gint *minimum_width,
                                   gint *natural_width)
{
	/* to never get larger than allocated size (which changes window width) */

	if (minimum_width != NULL)
		*minimum_width = 1;

	if (natural_width != NULL)
		*natural_width = 1;
}

static void
e_shell_taskbar_class_init (EShellTaskbarClass *class)
{
	GtkWidgetClass *widget_class;

	widget_class = GTK_WIDGET_CLASS (class);
	widget_class->get_preferred_width = shell_taskbar_get_preferred_width;
}

static void
e_shell_taskbar_init (EShellTaskbar *shell_taskbar)
{
}

int
main (int argc, char **argv)
{
	GtkWidget *grid, *dialog, *w1, *w2, *taskbar;

	g_type_init ();
	gtk_init (&argc, &argv);

	
	grid = g_object_new (e_shell_taskbar_get_type (),
		"orientation", GTK_ORIENTATION_VERTICAL,
		NULL);
	taskbar = g_object_new (e_shell_taskbar_get_type (), NULL);

	dialog = gtk_dialog_new_with_buttons ("test spinners", NULL, GTK_DIALOG_MODAL,
		GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
		NULL);
	gtk_container_add (GTK_CONTAINER (gtk_dialog_get_content_area (GTK_DIALOG (dialog))), grid);

	w1 = g_object_new (GTK_TYPE_GRID,
		"orientation", GTK_ORIENTATION_HORIZONTAL,
		NULL);
	gtk_container_add (GTK_CONTAINER (grid), w1);

	w2 = gtk_button_new_with_mnemonic ("_Add spinner");
	g_signal_connect (w2, "clicked", G_CALLBACK (add_spinner_cb), taskbar);
	gtk_container_add (GTK_CONTAINER (w1), w2);

	w2 = gtk_button_new_with_mnemonic ("_Start spinners");
	g_signal_connect (w2, "clicked", G_CALLBACK (start_spinners_cb), taskbar);
	gtk_container_add (GTK_CONTAINER (w1), w2);

	w2 = gtk_button_new_with_mnemonic ("S_top spinners");
	g_signal_connect (w2, "clicked", G_CALLBACK (stop_spinners_cb), taskbar);
	gtk_container_add (GTK_CONTAINER (w1), w2);

	w1 = g_object_new (GTK_TYPE_GRID,
		"orientation", GTK_ORIENTATION_HORIZONTAL,
		NULL);
	gtk_container_add (GTK_CONTAINER (grid), w1);
	gtk_container_add (GTK_CONTAINER (grid), taskbar);
	grid = w1;

	w1 = gtk_label_new ("");
	gtk_container_add (GTK_CONTAINER (grid), w1);

	w2 = gtk_button_new_with_mnemonic ("S_chedule idle");
	g_signal_connect (w2, "clicked", G_CALLBACK (schedule_idle_cb), w1);
	gtk_container_add (GTK_CONTAINER (grid), w2);

	w2 = gtk_button_new_with_mnemonic ("Sche_dule idle timeout");
	g_signal_connect (w2, "clicked", G_CALLBACK (schedule_idle_timeout_cb), w1);
	gtk_container_add (GTK_CONTAINER (grid), w2);

	w2 = gtk_button_new_with_mnemonic ("Sche_dule async");
	g_signal_connect (w2, "clicked", G_CALLBACK (schedule_async_cb), w1);
	gtk_container_add (GTK_CONTAINER (grid), w2);

	gtk_widget_show_all (gtk_dialog_get_content_area (GTK_DIALOG (dialog)));
	gtk_dialog_run (GTK_DIALOG (dialog));
	gtk_widget_destroy (dialog);

	return 0;
}
