/* gcc `pkg-config --cflags --libs gtk+-3.0` css.c -g -O0 -o css && ./css */

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

typedef struct _LikeTreeview {
	GtkBox parent;
} LikeTreeview;

typedef struct _LikeTreeviewClass {
	GtkBoxClass parent;
} LikeTreeviewClass;

G_DEFINE_TYPE (LikeTreeview, like_treeview, GTK_TYPE_BOX)

static void
like_treeview_class_init (LikeTreeviewClass *ltv_class)
{
	gtk_widget_class_set_css_name (GTK_WIDGET_CLASS (ltv_class), "treeview");
}

static void
like_treeview_init (LikeTreeview *ltv)
{
}

/* *************************************************************************** */

typedef struct _LikeHeader {
	GtkBox parent;
} LikeHeader;

typedef struct _LikeHeaderClass {
	GtkBoxClass parent;
} LikeHeaderClass;

G_DEFINE_TYPE (LikeHeader, like_header, GTK_TYPE_BOX)

static void
like_header_class_init (LikeHeaderClass *lh_class)
{
	gtk_widget_class_set_css_name (GTK_WIDGET_CLASS (lh_class), "header");
}

static void
like_header_init (LikeHeader *lh)
{
}

/* *************************************************************************** */

typedef struct _LikeButton {
	GtkBox parent;
} LikeButton;

typedef struct _LikeButtonClass {
	GtkBoxClass parent;
} LikeButtonClass;

G_DEFINE_TYPE (LikeButton, like_button, GTK_TYPE_BOX)

static void
like_button_class_init (LikeButtonClass *lb_class)
{
	gtk_widget_class_set_css_name (GTK_WIDGET_CLASS (lb_class), "button");
}

static void
like_button_init (LikeButton *lb)
{
}

/* *************************************************************************** */

typedef struct _CustomDraw {
	GtkLabel parent;
} CustomDraw;

typedef struct _CustomDrawClass {
	GtkLabelClass parent;
} CustomDrawClass;

G_DEFINE_TYPE (CustomDraw, custom_draw, GTK_TYPE_LABEL)

static gboolean
cd_draw (GtkWidget *widget,
	 cairo_t *cr)
{
	GtkStyleContext *context;
	GtkAllocation allocation;
	PangoContext *pango_context;
	PangoLayout *layout;

	if (!GTK_WIDGET_CLASS (custom_draw_parent_class)->draw (widget, cr))
		return FALSE;

	context = gtk_widget_get_style_context (widget);
	gtk_widget_get_allocation (widget, &allocation);

	gtk_render_background (
		context, cr, allocation.x, allocation.y,
		allocation.width, allocation.height);
	gtk_render_frame (
		context, cr, allocation.x, allocation.y,
		allocation.width, allocation.height);

	pango_context = gtk_widget_create_pango_context (widget);
	layout = pango_layout_new (pango_context);
	g_object_unref (pango_context);

	pango_layout_set_text (layout, gtk_label_get_label (GTK_LABEL (widget)), -1);
	pango_layout_set_ellipsize (layout, PANGO_ELLIPSIZE_END);
	pango_layout_set_width (layout, MAX (80, allocation.width) * PANGO_SCALE);

	gtk_render_layout (context, cr, allocation.x + 6, allocation.y + 6, layout);

	g_object_unref (layout);

	return TRUE;
}

static void
custom_draw_class_init (CustomDrawClass *cd_class)
{
	GTK_WIDGET_CLASS (cd_class)->draw = cd_draw;
}

static void
custom_draw_init (CustomDraw *cd)
{
}

static GtkWidget *
custom_draw_new (const gchar *label)
{
	return g_object_new (custom_draw_get_type (), "label", label, NULL);
}

/* *************************************************************************** */

int main (int argc, char *argv[])
{
	GtkWidget *dialog, *container, *widget, *treeview_box, *header_box, *button_box;
	GtkListStore *model;
	GtkTreeIter iter;
	GTimer *timer;

	gtk_init (&argc, &argv);

	dialog = gtk_dialog_new_with_buttons ("css", NULL, 0, "_Cancel", GTK_RESPONSE_CANCEL, NULL);
	g_object_set (G_OBJECT (dialog),
		"default-width", 640,
		"default-height", 480,
		NULL);

	container = gtk_dialog_get_content_area (GTK_DIALOG (dialog));
	gtk_box_set_spacing (GTK_BOX (container), 10);

	/* Native GtkTreeView */

	model = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_STRING);
	gtk_list_store_append (model, &iter);
	gtk_list_store_set (model, &iter, 0, "row text", -1);
	widget = gtk_tree_view_new_with_model (GTK_TREE_MODEL (model));
	g_object_unref (model);
	gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (widget), -1, "Native GtkTreeView column",
		gtk_cell_renderer_text_new (), "text", 0, NULL);
	gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (widget), -1, "Second Native column",
		gtk_cell_renderer_text_new (), "text", 1, NULL);
	gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (widget), TRUE);

	gtk_container_add (GTK_CONTAINER (container), widget);

	/* native GtkButton */
	gtk_container_add (GTK_CONTAINER (container), gtk_button_new_with_label ("Native GtkButton"));
	gtk_container_add (GTK_CONTAINER (container), custom_draw_new ("CustomDraw"));

	/* 'treeview' box */
	treeview_box = g_object_new (like_treeview_get_type (), "orientation", GTK_ORIENTATION_VERTICAL, "spacing", 5, "margin-start", 20, NULL);
	gtk_container_add (GTK_CONTAINER (container), treeview_box);
	gtk_container_add (GTK_CONTAINER (treeview_box), gtk_button_new_with_label ("Native GtkButton inside 'treeview'"));
	gtk_container_add (GTK_CONTAINER (treeview_box), custom_draw_new ("CustomDraw inside 'treeview'"));

	/* 'button_box' box */
	button_box = g_object_new (like_button_get_type (), "orientation", GTK_ORIENTATION_VERTICAL, "spacing", 5, "margin-start", 20, NULL);
	gtk_container_add (GTK_CONTAINER (treeview_box), button_box);
	gtk_container_add (GTK_CONTAINER (button_box), gtk_button_new_with_label ("Native GtkButton inside 'treeview & button'"));
	gtk_container_add (GTK_CONTAINER (button_box), custom_draw_new ("CustomDraw inside 'treeview & button'"));

	/* 'header_box' box */
	header_box = g_object_new (like_header_get_type (), "orientation", GTK_ORIENTATION_VERTICAL, "spacing", 5, "margin-start", 20, NULL);
	gtk_container_add (GTK_CONTAINER (treeview_box), header_box);
	gtk_container_add (GTK_CONTAINER (header_box), gtk_button_new_with_label ("Native GtkButton inside 'treeview & header'"));
	gtk_container_add (GTK_CONTAINER (header_box), custom_draw_new ("CustomDraw inside 'treeview & header'"));

	/* 'button_box' box */
	button_box = g_object_new (like_button_get_type (), "orientation", GTK_ORIENTATION_VERTICAL, "spacing", 5, "margin-start", 20, NULL);
	gtk_container_add (GTK_CONTAINER (header_box), button_box);
	gtk_container_add (GTK_CONTAINER (button_box), gtk_button_new_with_label ("Native GtkButton inside 'treeview & header & button'"));
	gtk_container_add (GTK_CONTAINER (button_box), custom_draw_new ("CustomDraw inside 'treeview & header & button'"));

	gtk_widget_show_all (container);

	gtk_dialog_run (GTK_DIALOG (dialog));

	gtk_widget_destroy (dialog);

	return 0;
}
