/* The TdeGtk Theming Engine for Gtk+.
 * Copyright (C) 2011 Canonical Ltd
 *
 * This  library is free  software; you can  redistribute it and/or
 * modify it  under  the terms  of the  GNU Lesser  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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License  along  with  this library;  if not,  write to  the Free
 * Software Foundation, Inc., 51  Franklin St, Fifth Floor, Boston,
 * MA 02110-1301, USA.
 *
 * Authored by Andrea Cimitan <andrea.cimitan@canonical.com>
 *
 */

#include <cairo.h>
#include <cairo-gobject.h>
#include <gtk/gtk.h>

#include "tdegtk.h"
#include "tdegtk-cairo-support.h"
#include "tdegtk-draw.h"
#include "tdegtk-engine.h"
#include "tdegtk-support.h"
#include "tdegtk-types.h"

#define TDEGTK_NAMESPACE "tdegtk"

#define TDEGTK_CAIRO_INIT \
        cairo_set_line_width (cr, 1.0); \
        cairo_set_line_cap (cr, CAIRO_LINE_CAP_SQUARE); \
        cairo_set_line_join (cr, CAIRO_LINE_JOIN_MITER);

G_DEFINE_DYNAMIC_TYPE (TdeGtkEngine, tdegtk_engine, GTK_TYPE_THEMING_ENGINE)

static void
tdegtk_engine_render_activity (GtkThemingEngine *engine,
                              cairo_t          *cr,
                              gdouble           x,
                              gdouble           y,
                              gdouble           width,
                              gdouble           height)
{
	TdeGtkStyleFunctions *style_functions;
	const GtkWidgetPath *path;
	
	TDEGTK_CAIRO_INIT
	
	tdegtk_lookup_functions (TDEGTK_ENGINE (engine), &style_functions);
	path = gtk_theming_engine_get_path (engine);
	
	if (gtk_theming_engine_has_class (engine, GTK_STYLE_CLASS_SPINNER)) {
		GTK_THEMING_ENGINE_CLASS (tdegtk_engine_parent_class)->render_activity (engine, cr, x, y, width, height);
	}
	else {
		style_functions->draw_activity (engine, cr, x, y, width, height);
	}
}

static void
tdegtk_engine_render_arrow (GtkThemingEngine *engine,
                           cairo_t          *cr,
                           gdouble           angle,
                           gdouble           x,
                           gdouble           y,
                           gdouble           size)
{
	TdeGtkStyleFunctions *style_functions;
	
	TDEGTK_CAIRO_INIT
	
	tdegtk_lookup_functions (TDEGTK_ENGINE (engine), &style_functions);
	
	style_functions->draw_arrow (engine, cr, angle, x, y, size);
}

static void
tdegtk_engine_render_background (GtkThemingEngine *engine,
                                cairo_t          *cr,
                                gdouble           x,
                                gdouble           y,
                                gdouble           width,
                                gdouble           height)
{
	TdeGtkStyleFunctions *style_functions;
	const GtkWidgetPath *path;
	GtkRegionFlags flags;
	
	TDEGTK_CAIRO_INIT
	
	tdegtk_lookup_functions (TDEGTK_ENGINE (engine), &style_functions);
	path = gtk_theming_engine_get_path (engine);
	
	if (gtk_theming_engine_has_class (engine, GTK_STYLE_CLASS_BUTTON) &&
		gtk_theming_engine_has_class (engine, GTK_STYLE_CLASS_SPINBUTTON)
		) {
		style_functions->draw_spinbutton_background (engine, cr, x, y, width, height);
	}
	else if (!gtk_widget_path_is_type (path, GTK_TYPE_ICON_VIEW) &&
		gtk_theming_engine_has_class (engine, GTK_STYLE_CLASS_VIEW) &&
		gtk_theming_engine_has_region (engine, GTK_STYLE_REGION_COLUMN, &flags)
		) {
		style_functions->draw_cell_background (engine, cr, x, y, width, height, flags);
	}
	else {
		style_functions->draw_common_background (engine, cr, x, y, width, height);
	}
}

static void
tdegtk_engine_render_check (GtkThemingEngine *engine,
                           cairo_t          *cr,
                           gdouble           x,
                           gdouble           y,
                           gdouble           width,
                           gdouble           height)
{
	TdeGtkStyleFunctions *style_functions;
	
	TDEGTK_CAIRO_INIT
	
	tdegtk_lookup_functions (TDEGTK_ENGINE (engine), &style_functions);
	
	style_functions->draw_check (engine, cr, x, y, width, height);
}

static void
tdegtk_engine_render_expander (GtkThemingEngine *engine,
                              cairo_t          *cr,
                              gdouble           x,
                              gdouble           y,
                              gdouble           width,
                              gdouble           height)
{
	TdeGtkStyleFunctions *style_functions;
	
	TDEGTK_CAIRO_INIT
	
	tdegtk_lookup_functions (TDEGTK_ENGINE (engine), &style_functions);
	
	style_functions->draw_expander (engine, cr, x, y, width, height);
}

static void
tdegtk_engine_render_extension (GtkThemingEngine *engine,
                               cairo_t          *cr,
                               gdouble           x,
                               gdouble           y,
                               gdouble           width,
                               gdouble           height,
                               GtkPositionType   gap_side)
{
	TdeGtkStyleFunctions *style_functions;
	
	TDEGTK_CAIRO_INIT
	
	tdegtk_lookup_functions (TDEGTK_ENGINE (engine), &style_functions);
	
	style_functions->draw_extension (engine, cr, x, y, width, height, gap_side);
}

static void
tdegtk_engine_render_focus (GtkThemingEngine *engine,
                           cairo_t          *cr,
                           gdouble           x,
                           gdouble           y,
                           gdouble           width,
                           gdouble           height)
{
	TdeGtkStyleFunctions *style_functions;
	
	TDEGTK_CAIRO_INIT
	
	tdegtk_lookup_functions (TDEGTK_ENGINE (engine), &style_functions);
	
	style_functions->draw_focus (engine, cr, x, y, width, height);
}

static void
tdegtk_engine_render_frame (GtkThemingEngine *engine,
                           cairo_t          *cr,
                           gdouble           x,
                           gdouble           y,
                           gdouble           width,
                           gdouble           height)
{
	TdeGtkStyleFunctions *style_functions;
	const GtkWidgetPath *path;
	GtkRegionFlags flags;
	
	TDEGTK_CAIRO_INIT
	
	tdegtk_lookup_functions (TDEGTK_ENGINE (engine), &style_functions);
	path = gtk_theming_engine_get_path (engine);
	
	if (gtk_theming_engine_has_class (engine, GTK_STYLE_CLASS_SEPARATOR)) {
		style_functions->draw_separator (engine, cr, x, y, width, height);
	}
	else if (gtk_theming_engine_has_class (engine, GTK_STYLE_CLASS_BUTTON) &&
		gtk_theming_engine_has_class (engine, GTK_STYLE_CLASS_SPINBUTTON)
		) {
		style_functions->draw_spinbutton_frame (engine, cr, x, y, width, height);
	}
	else if (!gtk_widget_path_is_type (path, GTK_TYPE_ICON_VIEW) &&
		gtk_theming_engine_has_class (engine, GTK_STYLE_CLASS_VIEW) &&
		gtk_theming_engine_has_region (engine, GTK_STYLE_REGION_COLUMN, &flags)
		) {
		style_functions->draw_cell_frame (engine, cr, x, y, width, height, flags);
	}
	else {
		style_functions->draw_common_frame (engine, cr, x, y, width, height);
	}
}

static void
tdegtk_engine_render_frame_gap (GtkThemingEngine *engine,
                               cairo_t          *cr,
                               gdouble           x,
                               gdouble           y,
                               gdouble           width,
                               gdouble           height,
                               GtkPositionType   gap_side,
                               gdouble           xy0_gap,
                               gdouble           xy1_gap)
{
	TdeGtkStyleFunctions *style_functions;
	
	TDEGTK_CAIRO_INIT
	
	tdegtk_lookup_functions (TDEGTK_ENGINE (engine), &style_functions);
	
	if (gtk_theming_engine_has_class (engine, GTK_STYLE_CLASS_NOTEBOOK)) {
		style_functions->draw_notebook (engine, cr, x, y, width, height, gap_side, xy0_gap, xy1_gap);
	}
	else {
		style_functions->draw_frame_gap (engine, cr, x, y, width, height, gap_side, xy0_gap, xy1_gap);
	}
}

static void
tdegtk_engine_render_handle (GtkThemingEngine *engine,
                            cairo_t          *cr,
                            gdouble           x,
                            gdouble           y,
                            gdouble           width,
                            gdouble           height)
{
	TdeGtkStyleFunctions *style_functions;
	
	TDEGTK_CAIRO_INIT
	
	tdegtk_lookup_functions (TDEGTK_ENGINE (engine), &style_functions);
	
	if (gtk_theming_engine_has_class (engine, GTK_STYLE_CLASS_GRIP)) {
		style_functions->draw_grip (engine, cr, x, y, width, height);
	}
	else {
		style_functions->draw_handle (engine, cr, x, y, width, height);
	}
}

static void
tdegtk_engine_render_line (GtkThemingEngine *engine,
                          cairo_t          *cr,
                          gdouble           x0,
                          gdouble           y0,
                          gdouble           x1,
                          gdouble           y1)
{
	TdeGtkStyleFunctions *style_functions;
	
	TDEGTK_CAIRO_INIT
	
	tdegtk_lookup_functions (TDEGTK_ENGINE (engine), &style_functions);
	
	style_functions->draw_line (engine, cr, x0, y0, x1, y1);
}

static void
tdegtk_engine_render_option (GtkThemingEngine *engine,
                            cairo_t          *cr,
                            gdouble           x,
                            gdouble           y,
                            gdouble           width,
                            gdouble           height)
{
	TdeGtkStyleFunctions *style_functions;
	
	TDEGTK_CAIRO_INIT
	
	tdegtk_lookup_functions (TDEGTK_ENGINE (engine), &style_functions);
	
	style_functions->draw_radio (engine, cr, x, y, width, height);
}

static void
tdegtk_engine_render_slider (GtkThemingEngine *engine,
                            cairo_t          *cr,
                            gdouble           x,
                            gdouble           y,
                            gdouble           width,
                            gdouble           height,
                            GtkOrientation    orientation)
{
	TdeGtkStyleFunctions *style_functions;
	
	TDEGTK_CAIRO_INIT
	
	tdegtk_lookup_functions (TDEGTK_ENGINE (engine), &style_functions);
	
	style_functions->draw_slider (engine, cr, x, y, width, height, orientation);
}

void
tdegtk_engine_register_types (GTypeModule *module)
{
	tdegtk_engine_register_type (module);
}

static void
tdegtk_engine_init (TdeGtkEngine *engine)
{
	tdegtk_register_style_default (&engine->style_functions[TDEGTK_STYLE_DEFAULT]);
}

static void
tdegtk_engine_class_init (TdeGtkEngineClass *klass)
{
	GtkThemingEngineClass *engine_class = GTK_THEMING_ENGINE_CLASS (klass);
	
	engine_class->render_activity    = tdegtk_engine_render_activity;
	engine_class->render_arrow       = tdegtk_engine_render_arrow;
	engine_class->render_background  = tdegtk_engine_render_background;
	engine_class->render_check       = tdegtk_engine_render_check;
	engine_class->render_expander    = tdegtk_engine_render_expander;
	engine_class->render_extension   = tdegtk_engine_render_extension;
	engine_class->render_focus       = tdegtk_engine_render_focus;
	engine_class->render_frame       = tdegtk_engine_render_frame;
	engine_class->render_frame_gap   = tdegtk_engine_render_frame_gap;
	engine_class->render_handle      = tdegtk_engine_render_handle;
	engine_class->render_line        = tdegtk_engine_render_line;
	engine_class->render_option      = tdegtk_engine_render_option;
	engine_class->render_slider      = tdegtk_engine_render_slider;
}

static void
tdegtk_engine_class_finalize (TdeGtkEngineClass *klass)
{
}
