/*  xfce4
 *  Copyright (C) 2002 Olivier Fourdan (fourdan@xfce.org)
 *
 * 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.
 */

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include <gdk/gdk.h>
#include <gtk/gtkmisc.h>

#include "xfce_decorbutton.h"

#define DECORBUTTON_WIDTH  10
#define DECORBUTTON_HEIGHT 10

static const unsigned char close_dark_bits[] = {
    0x00, 0x00, 0xc6, 0x00, 0x62, 0x00, 0x20, 0x00, 0x00, 0x00, 0x0c, 0x00,
    0x06, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
};
static const unsigned char close_mid_bits[] = {
    0x00, 0x00, 0x00, 0x00, 0x8c, 0x00, 0x5c, 0x00, 0x38, 0x00, 0x70, 0x00,
    0xe8, 0x00, 0xc4, 0x00, 0x00, 0x00, 0x00, 0x00,
};
static const unsigned char close_light_bits[] = {
    0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x80, 0x01, 0xc0, 0x00, 0x00, 0x00,
    0x10, 0x00, 0x18, 0x01, 0x8c, 0x01, 0x00, 0x00,
};
static const unsigned char hide_light_bits[] = {
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0xc0, 0x00, 0x60, 0x00,
    0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};
static const unsigned char hide_mid_bits[] = {
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x38, 0x00, 0x10, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};
static const unsigned char hide_dark_bits[] = {
    0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};

/* Forward declarations */

static void xfce_decorbutton_class_init (XfceDecorbuttonClass * class);
static void xfce_decorbutton_init (XfceDecorbutton * decorbutton);
static void xfce_decorbutton_destroy (GtkObject * object);
static void xfce_decorbutton_finalize (GObject * object);
static void xfce_decorbutton_size_request (GtkWidget * widget,
					   GtkRequisition * requisition);
static gint xfce_decorbutton_expose (GtkWidget * widget,
				     GdkEventExpose * event);
static void xfce_decorbutton_draw (GtkWidget * widget, GdkRectangle * area);

/* Local data */

static GtkWidgetClass *parent_class = NULL;

GtkType
xfce_decorbutton_get_type (void)
{
    static GtkType decorbutton_type = 0;

    if (!decorbutton_type)
    {
	static const GTypeInfo decorbutton_info = {
	    sizeof (XfceDecorbuttonClass),
	    NULL,		/* base_init */
	    NULL,		/* base_finalize */
	    (GClassInitFunc) xfce_decorbutton_class_init,
	    NULL,		/* class_finalize */
	    NULL,		/* class_data */
	    sizeof (XfceDecorbutton),
	    0,			/* n_preallocs */
	    (GInstanceInitFunc) xfce_decorbutton_init,
	    NULL		/* value_table */
	};

	decorbutton_type =
	    g_type_register_static (GTK_TYPE_MISC, "XfceDecorbutton",
				    &decorbutton_info, 0);
    }

    return decorbutton_type;
}

static void
xfce_decorbutton_class_init (XfceDecorbuttonClass * class)
{
    GObjectClass *gobject_class = G_OBJECT_CLASS (class);
    GtkObjectClass *object_class;
    GtkWidgetClass *widget_class;

    object_class = (GtkObjectClass *) class;
    widget_class = (GtkWidgetClass *) class;
    gobject_class = G_OBJECT_CLASS (class);

    parent_class = gtk_type_class (gtk_misc_get_type ());

    widget_class->size_request = xfce_decorbutton_size_request;
    object_class->destroy = xfce_decorbutton_destroy;
    gobject_class->finalize = xfce_decorbutton_finalize;

    widget_class->expose_event = xfce_decorbutton_expose;
}

static void
xfce_decorbutton_init (XfceDecorbutton * decorbutton)
{
    GTK_WIDGET_SET_FLAGS (decorbutton, GTK_NO_WINDOW);
    decorbutton->close_dark_bmap = NULL;
    decorbutton->close_mid_bmap = NULL;
    decorbutton->close_light_bmap = NULL;
    decorbutton->hide_dark_bmap = NULL;
    decorbutton->hide_mid_bmap = NULL;
    decorbutton->hide_light_bmap = NULL;
}

GtkWidget *
xfce_decorbutton_new (XfceDecorbuttonType type)
{
    XfceDecorbutton *decorbutton;

    decorbutton = g_object_new (xfce_decorbutton_get_type (), NULL);
    decorbutton->type = type;

    return GTK_WIDGET (decorbutton);
}

static void
xfce_decorbutton_destroy (GtkObject * object)
{
    g_return_if_fail (object != NULL);
    g_return_if_fail (XFCE_IS_DECORBUTTON (object));

    if (GTK_OBJECT_CLASS (parent_class)->destroy)
	(*GTK_OBJECT_CLASS (parent_class)->destroy) (object);
}

static void
xfce_decorbutton_finalize (GObject * object)
{
    XfceDecorbutton *decorbutton;

    g_return_if_fail (object != NULL);
    g_return_if_fail (XFCE_IS_DECORBUTTON (object));

    decorbutton = XFCE_DECORBUTTON (object);

    if (decorbutton->close_dark_bmap)
    {
	g_object_unref (G_OBJECT (decorbutton->close_dark_bmap));
	decorbutton->close_dark_bmap = NULL;
    }
    if (decorbutton->close_mid_bmap)
    {
	g_object_unref (G_OBJECT (decorbutton->close_mid_bmap));
	decorbutton->close_mid_bmap = NULL;
    }
    if (decorbutton->close_light_bmap)
    {
	g_object_unref (G_OBJECT (decorbutton->close_light_bmap));
	decorbutton->close_light_bmap = NULL;
    }
    if (decorbutton->hide_dark_bmap)
    {
	g_object_unref (G_OBJECT (decorbutton->hide_dark_bmap));
	decorbutton->hide_dark_bmap = NULL;
    }
    if (decorbutton->hide_mid_bmap)
    {
	g_object_unref (G_OBJECT (decorbutton->hide_mid_bmap));
	decorbutton->hide_mid_bmap = NULL;
    }
    if (decorbutton->hide_light_bmap)
    {
	g_object_unref (G_OBJECT (decorbutton->hide_light_bmap));
	decorbutton->hide_light_bmap = NULL;
    }
    G_OBJECT_CLASS (parent_class)->finalize (object);
}

static void
xfce_decorbutton_size_request (GtkWidget * widget,
			       GtkRequisition * requisition)
{
    requisition->width = DECORBUTTON_WIDTH + 4;
    requisition->height = DECORBUTTON_HEIGHT + 4;
}

static gint
xfce_decorbutton_expose (GtkWidget * widget, GdkEventExpose * event)
{
    g_return_val_if_fail (XFCE_IS_DECORBUTTON (widget), FALSE);
    g_return_val_if_fail (event != NULL, FALSE);

    xfce_decorbutton_draw (widget, &event->area);

    return FALSE;
}

static void
draw_part (GdkDrawable * drawable, GdkGC * gc, GdkRectangle * area, gint x,
	   gint y, GdkBitmap * bmap)
{
    if (area)
    {
	gdk_gc_set_clip_rectangle (gc, area);
    }

    gdk_gc_set_ts_origin (gc, x, y);
    gdk_gc_set_stipple (gc, bmap);
    gdk_gc_set_fill (gc, GDK_STIPPLED);

    gdk_draw_rectangle (drawable, gc, TRUE, x, y, DECORBUTTON_WIDTH,
			DECORBUTTON_HEIGHT);

    gdk_gc_set_fill (gc, GDK_SOLID);

    if (area)
    {
	gdk_gc_set_clip_rectangle (gc, NULL);
    }
}

static void
xfce_decorbutton_draw (GtkWidget * widget, GdkRectangle * area)
{
    XfceDecorbutton *decorbutton;
    GtkMisc *misc;

    g_return_if_fail (widget != NULL);
    g_return_if_fail (XFCE_IS_DECORBUTTON (widget));

    decorbutton = XFCE_DECORBUTTON (widget);
    misc = GTK_MISC (widget);

    if (GTK_WIDGET_DRAWABLE (widget))
    {
	guint w = widget->allocation.width;
	guint h = widget->allocation.height;
	gint x = widget->allocation.x + (w - DECORBUTTON_WIDTH) / 2;
	gint y = widget->allocation.y + (h - DECORBUTTON_HEIGHT) / 2;

	if (!(decorbutton->close_dark_bmap))
	{
	    decorbutton->close_dark_bmap =
		gdk_bitmap_create_from_data (widget->window, (gchar*) close_dark_bits,
					     DECORBUTTON_WIDTH,
					     DECORBUTTON_HEIGHT);
	}
	if (!(decorbutton->close_mid_bmap))
	{
	    decorbutton->close_mid_bmap =
		gdk_bitmap_create_from_data (widget->window, (gchar*) close_mid_bits,
					     DECORBUTTON_WIDTH,
					     DECORBUTTON_HEIGHT);
	}
	if (!(decorbutton->close_light_bmap))
	{
	    decorbutton->close_light_bmap =
		gdk_bitmap_create_from_data (widget->window, (gchar*) close_light_bits,
					     DECORBUTTON_WIDTH,
					     DECORBUTTON_HEIGHT);
	}
	if (!(decorbutton->hide_dark_bmap))
	{
	    decorbutton->hide_dark_bmap =
		gdk_bitmap_create_from_data (widget->window, (gchar*) hide_dark_bits,
					     DECORBUTTON_WIDTH,
					     DECORBUTTON_HEIGHT);
	}
	if (!(decorbutton->hide_mid_bmap))
	{
	    decorbutton->hide_mid_bmap =
		gdk_bitmap_create_from_data (widget->window, (gchar*) hide_mid_bits,
					     DECORBUTTON_WIDTH,
					     DECORBUTTON_HEIGHT);
	}
	if (!(decorbutton->hide_light_bmap))
	{
	    decorbutton->hide_light_bmap =
		gdk_bitmap_create_from_data (widget->window, (gchar*) hide_light_bits,
					     DECORBUTTON_WIDTH,
					     DECORBUTTON_HEIGHT);
	}

	switch (decorbutton->type)
	{
	    case XFCE_DECORBUTTON_CLOSE:
		draw_part (widget->window,
			   widget->style->light_gc[widget->state], area, x, y,
			   decorbutton->close_light_bmap);
		draw_part (widget->window,
			   widget->style->mid_gc[widget->state], area, x, y,
			   decorbutton->close_mid_bmap);
		draw_part (widget->window,
			   widget->style->dark_gc[widget->state], area, x, y,
			   decorbutton->close_dark_bmap);
		break;
	    case XFCE_DECORBUTTON_HIDE:
	    default:
		draw_part (widget->window,
			   widget->style->light_gc[widget->state], area, x, y,
			   decorbutton->hide_light_bmap);
		draw_part (widget->window,
			   widget->style->mid_gc[widget->state], area, x, y,
			   decorbutton->hide_mid_bmap);
		draw_part (widget->window,
			   widget->style->dark_gc[widget->state], area, x, y,
			   decorbutton->hide_dark_bmap);
		break;
	}
    }
}
