/*
 * This program 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) version 3.
 *
 * This program 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 the program; if not, see <http://www.gnu.org/licenses/>  
 *
 *
 * Authors:
 *		Srinivasa Ragavan <sragavan@novell.com>
 *
 * Copyright (C) 2009 Novell, Inc. (www.novell.com)
 *
 */

#include "custom-cell-renderer-vbox.h"

/* This is based mainly on GtkCellRendererProgress
 *  in GAIM, written and (c) 2002 by Sean Egan
 *  (Licensed under the GPL), which in turn is
 *  based on Gtk's GtkCellRenderer[Text|Toggle|Pixbuf]
 *  implementation by Jonathan Blandford */

/* Some boring function declarations: GObject type system stuff */

static void     custom_cell_renderer_vbox_init       (CustomCellRendererVBox      *cellprogress);

static void     custom_cell_renderer_vbox_class_init (CustomCellRendererVBoxClass *klass);

static void     custom_cell_renderer_vbox_get_property  (GObject                    *object,
                                                             guint                       param_id,
                                                             GValue                     *value,
                                                             GParamSpec                 *pspec);

static void     custom_cell_renderer_vbox_set_property  (GObject                    *object,
                                                             guint                       param_id,
                                                             const GValue               *value,
                                                             GParamSpec                 *pspec);

static void     custom_cell_renderer_vbox_finalize (GObject *gobject);


/* These functions are the heart of our custom cell renderer: */

static void     custom_cell_renderer_vbox_get_size   (GtkCellRenderer            *cell,
                                                          GtkWidget                  *widget,
                                                          GdkRectangle               *cell_area,
                                                          gint                       *x_offset,
                                                          gint                       *y_offset,
                                                          gint                       *width,
                                                          gint                       *height);

static void     custom_cell_renderer_vbox_render     (GtkCellRenderer            *cell,
                                                          GdkWindow                  *window,
                                                          GtkWidget                  *widget,
                                                          GdkRectangle               *background_area,
                                                          GdkRectangle               *cell_area,
                                                          GdkRectangle               *expose_area,
                                                          guint                       flags);


enum
{
  PROP_PERCENTAGE = 1,
};

static   gpointer parent_class;

static gboolean
cc_vbox_activate (GtkCellRenderer      *cell, 
				  GdkEvent	       *event,
				  GtkWidget            *widget,
				  const gchar          *path,
				  GdkRectangle         *background_area,
				  GdkRectangle         *cell_area,
				  GtkCellRendererState  flags);

/***************************************************************************
 *
 *  custom_cell_renderer_vbox_get_type: here we register our type with
 *                                          the GObject type system if we
 *                                          haven't done so yet. Everything
 *                                          else is done in the callbacks.
 *
 ***************************************************************************/

GType
custom_cell_renderer_vbox_get_type (void)
{
  static GType cell_progress_type = 0;

  if (cell_progress_type == 0)
  {
    static const GTypeInfo cell_progress_info =
    {
      sizeof (CustomCellRendererVBoxClass),
      NULL,                                                     /* base_init */
      NULL,                                                     /* base_finalize */
      (GClassInitFunc) custom_cell_renderer_vbox_class_init,
      NULL,                                                     /* class_finalize */
      NULL,                                                     /* class_data */
      sizeof (CustomCellRendererVBox),
      0,                                                        /* n_preallocs */
      (GInstanceInitFunc) custom_cell_renderer_vbox_init,
    };

    /* Derive from GtkCellRenderer */
    cell_progress_type = g_type_register_static (GTK_TYPE_CELL_RENDERER,
                                                 "CustomCellRendererVBox",
                                                  &cell_progress_info,
                                                  0);
  }

  return cell_progress_type;
}


/***************************************************************************
 *
 *  custom_cell_renderer_vbox_init: set some default properties of the
 *                                      parent (GtkCellRenderer).
 *
 ***************************************************************************/

static void
custom_cell_renderer_vbox_init (CustomCellRendererVBox *cellrendererprogress)
{
  cellrendererprogress->children = NULL;
  GTK_CELL_RENDERER(cellrendererprogress)->mode = GTK_CELL_RENDERER_MODE_INERT;
  GTK_CELL_RENDERER(cellrendererprogress)->xpad = 2;
  GTK_CELL_RENDERER(cellrendererprogress)->ypad = 2;
}

/***************************************************************************
 *
 *  custom_cell_renderer_vbox_class_init:
 *
 *  set up our own get_property and set_property functions, and
 *  override the parent's functions that we need to implement.
 *  And make our new "percentage" property known to the type system.
 *  If you want cells that can be activated on their own (ie. not
 *  just the whole row selected) or cells that are editable, you
 *  will need to override 'activate' and 'start_editing' as well.
 *
 ***************************************************************************/

static void
custom_cell_renderer_vbox_class_init (CustomCellRendererVBoxClass *klass)
{
  GtkCellRendererClass *cell_class   = GTK_CELL_RENDERER_CLASS(klass);
  GObjectClass         *object_class = G_OBJECT_CLASS(klass);

  parent_class           = g_type_class_peek_parent (klass);
  object_class->finalize = custom_cell_renderer_vbox_finalize;

  /* Hook up functions to set and get our
   *   custom cell renderer properties */
  object_class->get_property = custom_cell_renderer_vbox_get_property;
  object_class->set_property = custom_cell_renderer_vbox_set_property;
  cell_class->activate  = cc_vbox_activate;

  /* Override the two crucial functions that are the heart
   *   of a cell renderer in the parent class */
  cell_class->get_size = custom_cell_renderer_vbox_get_size;
  cell_class->render   = custom_cell_renderer_vbox_render;

 }


/***************************************************************************
 *
 *  custom_cell_renderer_vbox_finalize: free any resources here
 *
 ***************************************************************************/

static void
custom_cell_renderer_vbox_finalize (GObject *object)
{
/*
  CustomCellRendererVBox *cellrendererprogress = CUSTOM_CELL_RENDERER_VBOX(object);
*/

  /* Free any dynamically allocated resources here */

  (* G_OBJECT_CLASS (parent_class)->finalize) (object);
}


/***************************************************************************
 *
 *  custom_cell_renderer_vbox_get_property: as it says
 *
 ***************************************************************************/

static void
custom_cell_renderer_vbox_get_property (GObject    *object,
                                            guint       param_id,
                                            GValue     *value,
                                            GParamSpec *psec)
{
  /*CustomCellRendererVBox  *cellprogress = CUSTOM_CELL_RENDERER_VBOX(object);*/

  switch (param_id)
  {
    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, psec);
      break;
  }
}


/***************************************************************************
 *
 *  custom_cell_renderer_vbox_set_property: as it says
 *
 ***************************************************************************/

static void
custom_cell_renderer_vbox_set_property (GObject      *object,
                                            guint         param_id,
                                            const GValue *value,
                                            GParamSpec   *pspec)
{
  /*CustomCellRendererVBox *cellprogress = CUSTOM_CELL_RENDERER_VBOX (object);*/

  switch (param_id)
  {
      default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID(object, param_id, pspec);
      break;
  }
}

/***************************************************************************
 *
 *  custom_cell_renderer_vbox_new: return a new cell renderer instance
 *
 ***************************************************************************/

GtkCellRenderer *
custom_cell_renderer_vbox_new (void)
{
  return g_object_new(CUSTOM_TYPE_CELL_RENDERER_VBOX, NULL);
}


/***************************************************************************
 *
 *  custom_cell_renderer_vbox_get_size: crucial - calculate the size
 *                                          of our cell, taking into account
 *                                          padding and alignment properties
 *                                          of parent.
 *
 ***************************************************************************/


void
custom_cell_renderer_vbox_append (GtkCellRenderer *cell, GtkCellRenderer *child)
{
	
  CustomCellRendererVBox *cellprogress = CUSTOM_CELL_RENDERER_VBOX (cell);
  cellprogress->children = g_list_append (cellprogress->children, child);
}

static void
custom_cell_renderer_vbox_get_size (GtkCellRenderer *cell,
                                        GtkWidget       *widget,
                                        GdkRectangle    *cell_area,
                                        gint            *x_offset,
                                        gint            *y_offset,
                                        gint            *width,
                                        gint            *height)
{
  CustomCellRendererVBox *cellprogress = CUSTOM_CELL_RENDERER_VBOX (cell);
  gint calc_width = 0;
  gint calc_height = 0;
  gint xo = 0, yo = 0;
  GList *tmp;
  gint cx=0, cy=0, cw=0, ch=0;

  tmp = cellprogress->children;
  while (tmp) {
	  GtkCellRenderer *child = (GtkCellRenderer *) tmp->data;
	  gtk_cell_renderer_get_size (child, widget, cell_area, &cx, &cy, &cw, &ch);
	  if (cw > calc_width)
		  calc_width = cw;
	  calc_height += ch;
	  if (cx > xo)
		  xo = cx;
	  if (cy > yo)
		  yo = cy;
	  tmp = tmp->next;
  }
  if (width)
    *width = calc_width;

  if (height)

    *height = calc_height;

  if (cell_area)
  {
    if (x_offset)
    {
      *x_offset = MAX (xo, 0);
    }

    if (y_offset)
    {
      *y_offset = MAX (yo, 0);
    }
  }
}


/***************************************************************************
 *
 *  custom_cell_renderer_vbox_render: crucial - do the rendering.
 *
 ***************************************************************************/

static void
custom_cell_renderer_vbox_render (GtkCellRenderer *cell,
                                      GdkWindow       *window,
                                      GtkWidget       *widget,
                                      GdkRectangle    *background_area,
                                      GdkRectangle    *cell_area,
                                      GdkRectangle    *expose_area,
                                      guint            flags)
{
  CustomCellRendererVBox *cellprogress = CUSTOM_CELL_RENDERER_VBOX (cell);
  gint                        width, height;
  gint                        x_offset, y_offset;
  gint store_x;
  GList *tmp = cellprogress->children;
  int i=0;

  custom_cell_renderer_vbox_get_size (cell, widget, cell_area,
                                          &x_offset, &y_offset,
                                          &width, &height);
  cell_area->y =  cell_area->y - (height / 2) + (4 * cell->ypad);
  store_x = cell_area->x;
  while(tmp) {
	  GtkCellRenderer *child = (GtkCellRenderer *)tmp->data;
	  gint cx, cy, cw, ch;

	  cell_area->x  = store_x;
	  gtk_cell_renderer_get_size (child, widget, cell_area, &cx, &cy, &cw, &ch);
	  if (GTK_IS_CELL_RENDERER_PIXBUF(child) && (!(flags & GTK_CELL_RENDERER_SELECTED)))
		   gtk_cell_renderer_render (child, window, widget, background_area, cell_area, expose_area, GTK_CELL_RENDERER_INSENSITIVE);
	  else
		   gtk_cell_renderer_render (child, window, widget, background_area, cell_area, expose_area, flags);
	  /* FIXME: Just trial & error hacks. Need to find why chiid's ypad is 0 */
	  cell_area->y += ch - (2*2)+ i; /* 2-cellpad*/
	  i+=4;
	  cell_area->y += 3*2; /* 2 - cell-pad */
	  tmp = tmp->next;
  }
}


static gboolean
cc_vbox_activate (GtkCellRenderer      *cell, 
				  GdkEvent	       *eb,
				  GtkWidget            *widget,
				  const gchar          *path,
				  GdkRectangle         *background_area,
				  GdkRectangle         *cell_area,
				  GtkCellRendererState  flags)
{
  CustomCellRendererVBox *cellprogress = CUSTOM_CELL_RENDERER_VBOX (cell);
  gint                        width, height;
  gint                        x_offset, y_offset;
  gint store_x, i=0;
  GList *tmp = cellprogress->children;
  GdkEventButton *event = (GdkEventButton *)eb;

  if (!event)
	   return TRUE;
  custom_cell_renderer_vbox_get_size (cell, widget, cell_area,
									  &x_offset, &y_offset,
									  &width, &height);
  cell_area->y =  cell_area->y -  (9 * cell->ypad);
  store_x = cell_area->x;
  while(tmp) {
	  GtkCellRenderer *child = (GtkCellRenderer *)tmp->data;
	  gint cx, cy, cw, ch;

	  cell_area->x  = store_x;
	  gtk_cell_renderer_get_size (child, widget, cell_area, &cx, &cy, &cw, &ch);
	  if ((event->x >= cell_area->x && event->x <= cell_area->x+cw) &&
		  (event->y >= cell_area->y +ch&& event->y <= cell_area->y+(2*ch))) {
		   CellRenderActivateFunc func = g_object_get_data ((GObject *)child, "activate_func");
		   if (func) {
				(*func)(child, (GdkEvent *)event, widget, path, background_area, cell_area, flags);
				return TRUE;
		   }	
	  }
	  
	  cell_area->y += ch - (1*2)+ i; /* 2-cellpad*/
	  i+=4;
	  cell_area->y += 1*2; /* 2 - cell-pad */
	  tmp = tmp->next;
  } 
	 return FALSE;
}
