/*   EXTRAITS DE LA LICENCE
	Copyright CEA, contributeurs : Luc BILLARD et Damien
	CALISTE, laboratoire L_Sim, (2001-2005)
  
	Adresse mèl :
	BILLARD, non joignable par mèl ;
	CALISTE, damien P caliste AT cea P fr.

	Ce logiciel est un programme informatique servant à visualiser des
	structures atomiques dans un rendu pseudo-3D. 

	Ce logiciel est régi par la licence CeCILL soumise au droit français et
	respectant les principes de diffusion des logiciels libres. Vous pouvez
	utiliser, modifier et/ou redistribuer ce programme sous les conditions
	de la licence CeCILL telle que diffusée par le CEA, le CNRS et l'INRIA 
	sur le site "http://www.cecill.info".

	Le fait que vous puissiez accéder à cet en-tête signifie que vous avez 
	pris connaissance de la licence CeCILL, et que vous en avez accepté les
	termes (cf. le fichier Documentation/licence.fr.txt fourni avec ce logiciel).
*/

/*   LICENCE SUM UP
	Copyright CEA, contributors : Luc BILLARD et Damien
	CALISTE, laboratoire L_Sim, (2001-2005)

	E-mail address:
	BILLARD, not reachable any more ;
	CALISTE, damien P caliste AT cea P fr.

	This software is a computer program whose purpose is to visualize atomic
	configurations in 3D.

	This software is governed by the CeCILL  license under French law and
	abiding by the rules of distribution of free software.  You can  use, 
	modify and/ or redistribute the software under the terms of the CeCILL
	license as circulated by CEA, CNRS and INRIA at the following URL
	"http://www.cecill.info". 

	The fact that you are presently reading this means that you have had
	knowledge of the CeCILL license and that you accept its terms. You can
	find a copy of this licence shipped with this software at Documentation/licence.en.txt.
*/
#include <gtk/gtk.h>

#include "gtk_shadeComboBoxWidget.h"
#include <visu_tools.h>
#include <visu_data.h>
#include <visu_configFile.h>


/**
 * SECTION:gtk_shadeComboBoxWidget
 * @short_description: Defines a specialised #GtkComboBox to choose
 * pre-built shades.
 * @see_also: #VisuUiStippleCombobox, #ToolShade
 * @include: coreTools/toolShade.h
 *
 * <para>This widget looks like a #GtkComboBox and it displays a list
 * of preset colour shades. These patterns are defined by colour
 * parameters, see #ToolShade.</para>
 * <para>This widget can emit a #VisuUiShadeCombobox::shade-selected
 * signal that is a wrapper around the #GtkComboBox::changed signal,
 * but it is emitted only when a new shade is selected and this shade
 * is passed to the callback.</para>
 *
 * Since: 3.3
 */

enum {
  SHADE_SELECTED_SIGNAL,
  LAST_SIGNAL
};
enum
  {
    PROP_0,
    SHADE_PROP,
    N_PROP
  };
static GParamSpec *properties[N_PROP];

/* This enum is used to access the column of the GtkListStore
   that contains the informations of stroed shades. */
enum
  {
    /* This has a pointer to a 48x16 image to represent the shade. */
    COLUMN_SHADE_PIXBUF,
    /* This is a pointer to a label that describes the shade. */
    COLUMN_SHADE_LABEL,
    /* This is a label with the shade id '(n)'. */
    COLUMN_SHADE_ID,
    /* This a pointer to the #ToolShade as defined in toolShade.h */
    COLUMN_SHADE_POINTER_TO,

    N_COLUMN_SHADE
  };

/* Store a tree model to remember shades. */
#define SHADE_BOX_WIDTH  48
#define SHADE_BOX_HEIGHT 16
#define SHADE_BOX_BITS   8

/* Entries in the parameter file. */
#define FLAG_PARAMETER_FAVSHADE   "presetShade"
#define DESC_PARAMETER_FAVSHADE   "The id of a shade used as preset one in the shade selectors ; an integer ranging from 0"
#define PARAMETER_FAVSHADE_DEFAULT    0

static void visu_ui_shade_combobox_dispose (GObject *obj);
static void visu_ui_shade_combobox_finalize(GObject *obj);
static void visu_ui_shade_combobox_get_property(GObject* obj, guint property_id,
                                                GValue *value, GParamSpec *pspec);
static void visu_ui_shade_combobox_set_property(GObject* obj, guint property_id,
                                                const GValue *value, GParamSpec *pspec);

static guint visu_ui_shade_combobox_signals[LAST_SIGNAL] = { 0 };

/**
 * VisuUiShadeCombobox
 *
 * Private structure to store informations of a #VisuUiShadeCombobox object.
 *
 * Since: 3.3
 */
struct _VisuUiShadeCombobox
{
  GtkComboBox comboToolShade;
  ToolShade* previouslySelectedToolShade;

  gboolean hasAlphaChannel;

  /* Memory gestion. */
  gboolean dispose_has_run;
};
/**
 * VisuUiShadeComboboxClass
 *
 * Private structure to store informations of a #VisuUiShadeComboboxClass object.
 *
 * Since: 3.3
 */
struct _VisuUiShadeComboboxClass
{
  GtkComboBoxClass parent_class;

  void (*shadeComboBox) (VisuUiShadeCombobox *shadeCombo);

  /* This listStore contains all the shades
     known by widgets of this class. It is used
     as TreeModel for the combobox in the widget. */
  GtkListStore *listStoredToolShades;

  guint favToolShade;
};
static VisuUiShadeComboboxClass *my_class = (VisuUiShadeComboboxClass*)0;

/* Local callbacks. */
static void visu_ui_shade_combobox_changed(GtkWidget *widget, VisuUiShadeCombobox *shadeComboBox);

/* Local methods. */
static void addToolShadeToModel(GtkTreeIter *iter, VisuUiShadeComboboxClass* klass,
                                ToolShade* shade);
static void onNewShadeAvailable(ToolPool *obj, ToolShade* newColor, gpointer data);
static void buildWidgets(VisuUiShadeCombobox *shadeComboBox, gboolean showNames);
static void exportParameters(GString *data, VisuData* dataObj);

/**
 * visu_ui_shade_combobox_get_type
 *
 * #GType are unique numbers to identify objects.
 *
 * Returns: the #GType associated with #VisuUiShadeCombobox objects.
 *
 * Since: 3.3
 */
G_DEFINE_TYPE(VisuUiShadeCombobox, visu_ui_shade_combobox, GTK_TYPE_COMBO_BOX)

static void visu_ui_shade_combobox_class_init(VisuUiShadeComboboxClass *klass)
{
  GtkTreeIter iter;
  GList *shadeLst;
  VisuConfigFileEntry *resourceEntry;
  int rgShade[2] = {0, 128};
  
  DBG_fprintf(stderr, "Gtk VisuUiShadeCombobox: creating the class of the widget.\n");
  DBG_fprintf(stderr, "                     - adding new signals ;\n");
  /**
   * VisuUiShadeCombobox::shade-selected:
   * @combo: the #VisuUiShadeCombobox that emits the signal ;
   * @shade: the newly selected #ToolShade.
   *
   * This signal is emitted when a new valid colour shade is selected.
   *
   * Since: 3.3
   */
  visu_ui_shade_combobox_signals[SHADE_SELECTED_SIGNAL] =
    g_signal_new ("shade-selected",
		  G_TYPE_FROM_CLASS (klass),
		  G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION,
		  G_STRUCT_OFFSET (VisuUiShadeComboboxClass, shadeComboBox),
		  NULL, 
		  NULL,                
		  g_cclosure_marshal_VOID__POINTER,
		  G_TYPE_NONE, 1, G_TYPE_POINTER);

  g_signal_connect(tool_shade_getStorage(), "new-element",
                   G_CALLBACK(onNewShadeAvailable), (gpointer)klass);

  DBG_fprintf(stderr, "                     - initializing the listStore of shades.\n");
  /* Init the listStore of shades. */
  klass->listStoredToolShades = gtk_list_store_new(N_COLUMN_SHADE,
					       GDK_TYPE_PIXBUF,
					       G_TYPE_STRING,
					       G_TYPE_STRING,
					       G_TYPE_POINTER);
  for (shadeLst = tool_pool_asList(tool_shade_getStorage());
       shadeLst; shadeLst = g_list_next(shadeLst))
    addToolShadeToModel(&iter, klass, (ToolShade*)shadeLst->data);
  klass->favToolShade = 0;

  /* Dealing with parameters. */
  resourceEntry = visu_config_file_addIntegerArrayEntry(VISU_CONFIG_FILE_PARAMETER,
                                                        FLAG_PARAMETER_FAVSHADE,
                                                        DESC_PARAMETER_FAVSHADE,
                                                        1, (int*)&klass->favToolShade, rgShade, FALSE);
  visu_config_file_entry_setVersion(resourceEntry, 3.5f);
  visu_config_file_addExportFunction(VISU_CONFIG_FILE_PARAMETER,
				   exportParameters);

  /* Connect freeing methods. */
  G_OBJECT_CLASS(klass)->dispose  = visu_ui_shade_combobox_dispose;
  G_OBJECT_CLASS(klass)->finalize = visu_ui_shade_combobox_finalize;
  G_OBJECT_CLASS(klass)->set_property = visu_ui_shade_combobox_set_property;
  G_OBJECT_CLASS(klass)->get_property = visu_ui_shade_combobox_get_property;

  /**
   * VisuUiShadeCombobox::shade:
   *
   * Store the shade of the current selection.
   *
   * Since: 3.8
   */
  properties[SHADE_PROP] = g_param_spec_boxed("shade", "Shade",
                                              "shade of the current selection",
                                              TOOL_TYPE_SHADE,
                                              G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
  g_object_class_install_property(G_OBJECT_CLASS(klass), SHADE_PROP,
				  properties[SHADE_PROP]);

  my_class = klass;
}

static void visu_ui_shade_combobox_dispose(GObject *obj)
{
  DBG_fprintf(stderr, "Gtk VisuUiShadeCombobox: dispose object %p.\n", (gpointer)obj);

  if (VISU_UI_SHADE_COMBOBOX(obj)->dispose_has_run)
    return;

  VISU_UI_SHADE_COMBOBOX(obj)->dispose_has_run = TRUE;
  /* Chain up to the parent class */
  G_OBJECT_CLASS(visu_ui_shade_combobox_parent_class)->dispose(obj);
}
static void visu_ui_shade_combobox_finalize(GObject *obj)
{
  g_return_if_fail(obj);

  DBG_fprintf(stderr, "Gtk VisuUiShadeCombobox: finalize object %p.\n", (gpointer)obj);

  /* Chain up to the parent class */
  G_OBJECT_CLASS(visu_ui_shade_combobox_parent_class)->finalize(obj);

  DBG_fprintf(stderr, " | freeing ... OK.\n");
}
static void visu_ui_shade_combobox_get_property(GObject* obj, guint property_id,
                                                GValue *value, GParamSpec *pspec)
{
  VisuUiShadeCombobox *self = VISU_UI_SHADE_COMBOBOX(obj);

  DBG_fprintf(stderr, "Gtk VisuUiShadeCombobox: get property '%s'.\n",
	      g_param_spec_get_name(pspec));
  switch (property_id)
    {
    case SHADE_PROP:
      g_value_set_static_boxed(value, visu_ui_shade_combobox_getSelection(self));
      break;
    default:
      /* We don't have any other property... */
      G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, property_id, pspec);
      break;
    }
}
static void visu_ui_shade_combobox_set_property(GObject* obj, guint property_id,
                                                const GValue *value, GParamSpec *pspec)
{
  VisuUiShadeCombobox *self = VISU_UI_SHADE_COMBOBOX(obj);

  DBG_fprintf(stderr, "Gtk VisuUiShadeCombobox: set property '%s'.\n",
	      g_param_spec_get_name(pspec));
  switch (property_id)
    {
    case SHADE_PROP:
      if (!visu_ui_shade_combobox_setSelectionByShade(self,
                                                      (ToolShade*)g_value_get_boxed(value)))
        gtk_combo_box_set_active(GTK_COMBO_BOX(obj), -1);
      break;
    default:
      /* We don't have any other property... */
      G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, property_id, pspec);
      break;
    }
}


static void visu_ui_shade_combobox_init(VisuUiShadeCombobox *shadeComboBox)
{
  DBG_fprintf(stderr, "Gtk VisuUiShadeCombobox: initializing new object (%p).\n",
	      (gpointer)shadeComboBox);

  shadeComboBox->hasAlphaChannel = TRUE;
  shadeComboBox->dispose_has_run = FALSE;
  shadeComboBox->previouslySelectedToolShade = (ToolShade*)0;
}

static void buildWidgets(VisuUiShadeCombobox *shadeComboBox, gboolean showNames)
{
  GObjectClass *klass;
  GtkCellRenderer *renderer;

  klass = G_OBJECT_GET_CLASS(shadeComboBox);
  gtk_combo_box_set_model(GTK_COMBO_BOX(shadeComboBox),
			  GTK_TREE_MODEL(VISU_UI_SHADE_COMBOBOX_CLASS(klass)->listStoredToolShades));

  renderer = gtk_cell_renderer_pixbuf_new();
  gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(shadeComboBox), renderer, FALSE);
  gtk_cell_layout_add_attribute(GTK_CELL_LAYOUT(shadeComboBox), renderer,
				"pixbuf", COLUMN_SHADE_PIXBUF);
  if (showNames)
    {
      renderer = gtk_cell_renderer_text_new();
      g_object_set(G_OBJECT(renderer), "foreground", "#505050", "xpad", 0,
                   "align-set", TRUE, "xalign", 1.0, NULL);
      gtk_cell_layout_pack_end(GTK_CELL_LAYOUT(shadeComboBox), renderer, FALSE);
      gtk_cell_layout_add_attribute(GTK_CELL_LAYOUT(shadeComboBox), renderer,
				    "markup", COLUMN_SHADE_ID);
      renderer = gtk_cell_renderer_text_new();
      /* g_object_set(G_OBJECT(renderer), "scale", 0.85, NULL); */
      gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(shadeComboBox), renderer, TRUE);
      gtk_cell_layout_add_attribute(GTK_CELL_LAYOUT(shadeComboBox), renderer,
				    "text", COLUMN_SHADE_LABEL);
    }

  if ((gint)VISU_UI_SHADE_COMBOBOX_CLASS(klass)->favToolShade < gtk_tree_model_iter_n_children
      (GTK_TREE_MODEL(VISU_UI_SHADE_COMBOBOX_CLASS(klass)->listStoredToolShades), (GtkTreeIter*)0))
    gtk_combo_box_set_active(GTK_COMBO_BOX(shadeComboBox),
			     VISU_UI_SHADE_COMBOBOX_CLASS(klass)->favToolShade);
  else
    gtk_combo_box_set_active(GTK_COMBO_BOX(shadeComboBox), -1);
  g_signal_connect(G_OBJECT(shadeComboBox), "changed",
		   G_CALLBACK(visu_ui_shade_combobox_changed), (gpointer)shadeComboBox);
}
/**
 * visu_ui_shade_combobox_new :
 * @hasAlphaChannel : a boolean.
 * @showNames: if TRUE, the names of the shades are displayed.
 *
 * A #VisuUiShadeCombobox widget is like a #GtkComboBox widget, but it is already filled
 * with the known shades. Using this widget
 * is a convienient way to share shades between all part of V_Sim and to give a consistent
 * look of all shade selection. If the argument @hasAlphaChannel is FALSE, the widget
 * display all shades but without their alpha channel, assuming it to be fully opaque.
 *
 * Returns: (transfer full): a newly created #VisuUiShadeCombobox widget.
 *
 * Since: 3.3
 */
GtkWidget* visu_ui_shade_combobox_new(gboolean hasAlphaChannel, gboolean showNames)
{
  VisuUiShadeCombobox *shadeComboBox;

  DBG_fprintf(stderr, "Gtk VisuUiShadeCombobox: creating new object with alpha: %d.\n",
	      hasAlphaChannel);

  shadeComboBox = VISU_UI_SHADE_COMBOBOX(g_object_new(visu_ui_shade_combobox_get_type (), NULL));
  shadeComboBox->hasAlphaChannel = hasAlphaChannel;

  DBG_fprintf(stderr, "Gtk VisuUiShadeCombobox: build widgets.\n");

  buildWidgets(shadeComboBox, showNames);

  return GTK_WIDGET(shadeComboBox);
}

static void visu_ui_shade_combobox_changed(GtkWidget *widget _U_, VisuUiShadeCombobox *shadeComboBox)
{
  int selected;
  GtkTreeIter iter;
  GObjectClass *klass;
  ToolShade *shade;

  selected = gtk_combo_box_get_active(GTK_COMBO_BOX(shadeComboBox));
  DBG_fprintf(stderr, "Gtk VisuUiShadeCombobox: internal combobox changed signal -> %d.\n", selected);
  if (selected < 0)
    {
      shadeComboBox->previouslySelectedToolShade = (ToolShade*)0;
/*       DBG_fprintf(stderr, "Gtk VisuUiShadeCombobox: emitting 'shade-selected' signal.\n"); */
/*       g_signal_emit(G_OBJECT(shadeComboBox), */
/* 		    visu_ui_shade_combobox_signals[SHADE_SELECTED_SIGNAL], 0, (gpointer)0, NULL); */
      return;
    }

  gtk_combo_box_get_active_iter(GTK_COMBO_BOX(shadeComboBox), &iter);
  klass = G_OBJECT_GET_CLASS(shadeComboBox);
  gtk_tree_model_get(GTK_TREE_MODEL(VISU_UI_SHADE_COMBOBOX_CLASS(klass)->listStoredToolShades), &iter,
		     COLUMN_SHADE_POINTER_TO, &shade,
		     -1);
  if (shade != shadeComboBox->previouslySelectedToolShade)
    {
      shadeComboBox->previouslySelectedToolShade = shade;
      DBG_fprintf(stderr, "Gtk VisuUiShadeCombobox: emitting 'shade-selected' signal for shade (%p).\n", (gpointer)shade);
      g_object_notify_by_pspec(G_OBJECT(shadeComboBox), properties[SHADE_PROP]);
      g_signal_emit(G_OBJECT(shadeComboBox),
		    visu_ui_shade_combobox_signals[SHADE_SELECTED_SIGNAL], 0, (gpointer)shade, NULL);
    }
  else
    DBG_fprintf(stderr, "Gtk VisuUiShadeCombobox: aborting 'shade-selected' signal.\n");
}
/**
 * visu_ui_shade_combobox_buildStamp:
 * @shade: a #ToolShade object ;
 * @pixbuf: (inout) (allow-none): an existing pixbuf (can be NULL).
 *
 * This method is used to create pixbuf representing shades. If @pixbuf is given,
 * it must be a valid pixbuf, and the shade is created in it. Otherwise, a new
 * pixbuf is created.
 *
 * Returns: (transfer full): a pixbuf pointer.
 *
 * Since: 3.3
 */
GdkPixbuf* visu_ui_shade_combobox_buildStamp(ToolShade *shade, GdkPixbuf *pixbuf)
{
  GdkPixbuf *pixbufToolShadeBox;
  int rowstride, x, y;
  guchar *pixels, *p;
  float grey;
  float **rgbVals;

  if (!pixbuf)
    pixbufToolShadeBox = gdk_pixbuf_new(GDK_COLORSPACE_RGB, FALSE,
				    SHADE_BOX_BITS,
				    SHADE_BOX_WIDTH,
				    SHADE_BOX_HEIGHT);
  else
    pixbufToolShadeBox = pixbuf;
  rowstride = gdk_pixbuf_get_rowstride(pixbufToolShadeBox);
  pixels = gdk_pixbuf_get_pixels(pixbufToolShadeBox);
  rgbVals  = g_malloc(sizeof(float*) * SHADE_BOX_WIDTH);
  rgbVals[0] = g_malloc(sizeof(float) * SHADE_BOX_WIDTH * 5);
  for (x = 0; x < SHADE_BOX_WIDTH; x++)
    {
      rgbVals[x] = rgbVals[0] + x * 5;
      rgbVals[x][0] = (float)x / (float)(SHADE_BOX_WIDTH - 1);
      tool_shade_valueToRGB(shade, &rgbVals[x][1], rgbVals[x][0]);
    }
  for (y = 0; y < SHADE_BOX_HEIGHT; y++)
    for (x = 0; x < SHADE_BOX_WIDTH; x++)
      {
	p = pixels + y * rowstride + x * 3;
	if (x < SHADE_BOX_WIDTH / 2)
	  {
	    if (y < SHADE_BOX_HEIGHT / 2)
	      grey = 0.75;
	    else
	      grey = 0.5;
	  }
	else
	  {
	    if (y < SHADE_BOX_HEIGHT / 2)
	      grey = 0.5;
	    else
	      grey = 0.75;
	  }
	p[0] = (guchar)((rgbVals[x][1] * rgbVals[x][4] +
			 (1. - rgbVals[x][4]) * grey) * 255.);
	p[1] = (guchar)((rgbVals[x][2] * rgbVals[x][4] +
			 (1. - rgbVals[x][4]) * grey) * 255.);
	p[2] = (guchar)((rgbVals[x][3] * rgbVals[x][4] +
			 (1. - rgbVals[x][4]) * grey) * 255.);
      }
  g_free(rgbVals[0]);
  g_free(rgbVals);
  return pixbufToolShadeBox;
}

static void onNewShadeAvailable(ToolPool *obj _U_, ToolShade* newShade, gpointer data)
{
  VisuUiShadeComboboxClass *klass;
  GtkTreeIter iter;

  g_return_if_fail(data);

  DBG_fprintf(stderr, "Gtk VisuUiShadeComboboxClass: catch the 'shadeNewAvailable' signal.\n");
  klass = VISU_UI_SHADE_COMBOBOX_CLASS(data);
  addToolShadeToModel(&iter, klass, newShade);
}
static void addToolShadeToModel(GtkTreeIter *iter, VisuUiShadeComboboxClass* klass,
                                ToolShade* shade)
{
  GtkTreePath *path;
  gint *ids;
  gchar *idLbl;
  GdkPixbuf *pix;

  g_return_if_fail(iter && klass && shade);

  DBG_fprintf(stderr, "Gtk VisuUiShadeCombobox: appending a new shade '%s'.\n",
	      tool_shade_getLabel(shade));
  gtk_list_store_append(klass->listStoredToolShades, iter);
  path = gtk_tree_model_get_path(GTK_TREE_MODEL(klass->listStoredToolShades), iter);
  ids = gtk_tree_path_get_indices(path);
  idLbl = g_strdup_printf("<span size=\"small\">(%d)</span>", ids[0]);
  gtk_tree_path_free(path);
  pix = visu_ui_shade_combobox_buildStamp(shade, (GdkPixbuf*)0);
  gtk_list_store_set(klass->listStoredToolShades, iter,
		     COLUMN_SHADE_PIXBUF      , pix,
		     COLUMN_SHADE_LABEL       , tool_shade_getLabel(shade),
		     COLUMN_SHADE_ID          , idLbl,
		     COLUMN_SHADE_POINTER_TO  , (gpointer)shade,
		     -1);
  g_object_unref(G_OBJECT(pix));
  g_free(idLbl);
  DBG_fprintf(stderr, "Gtk VisuUiShadeCombobox: appending a new shade '%s'.\n",
	      tool_shade_getLabel(shade));
}
/**
 * visu_ui_shade_combobox_setSelectionByShade:
 * @shadeComboBox: a #VisuUiShadeCombobox widget ;
 * @shade: a #ToolShade object.
 *
 * Use this method to set the ComboBox on the given shade. This emits a 'shade-channel'
 * signal if the shade is changed, which means, a previous shade has been modified,
 * or a new shade is selected.
 *
 * Returns: TRUE if the @shade already exists in the model.
 *
 * Since: 3.3
 */
gboolean visu_ui_shade_combobox_setSelectionByShade(VisuUiShadeCombobox* shadeComboBox,
                                                    ToolShade *shade)
{
  GtkTreeIter iter;
  gboolean validIter;
  GObjectClass *klass;
  GtkListStore *model;
  ToolShade *tmpToolShade;

  g_return_val_if_fail(VISU_IS_UI_SHADE_COMBOBOX(shadeComboBox), FALSE);

  DBG_fprintf(stderr, "Gtk VisuUiShadeCombobox: select a new shade %p.\n", (gpointer)shade);
  if (!shade)
    {
      gtk_combo_box_set_active(GTK_COMBO_BOX(shadeComboBox), -1);
      return TRUE;
    }

  klass = G_OBJECT_GET_CLASS(shadeComboBox);
  model = GTK_LIST_STORE(VISU_UI_SHADE_COMBOBOX_CLASS(klass)->listStoredToolShades);
  for (validIter = gtk_tree_model_get_iter_first(GTK_TREE_MODEL(model), &iter);
       validIter; validIter = gtk_tree_model_iter_next(GTK_TREE_MODEL(model), &iter))
    {
      gtk_tree_model_get(GTK_TREE_MODEL(model), &iter,
			 COLUMN_SHADE_POINTER_TO, &tmpToolShade,
			 -1);
      if (tmpToolShade == shade || tool_shade_compare(tmpToolShade, shade))
	{
	  gtk_combo_box_set_active_iter(GTK_COMBO_BOX(shadeComboBox), &iter);
	  return TRUE;
	}
    }
  return FALSE;
}
GdkPixbuf* shadeComboBoxGet_selectedPixbuf(VisuUiShadeCombobox *shadeComboBox)
{
  gboolean validIter;
  GtkTreeIter iter;
  GdkPixbuf *pixbuf;
  GObjectClass *klass;

  g_return_val_if_fail(VISU_IS_UI_SHADE_COMBOBOX(shadeComboBox), (GdkPixbuf*)0);

  validIter = gtk_combo_box_get_active_iter(GTK_COMBO_BOX(shadeComboBox), &iter);
  if (!validIter)
    return (GdkPixbuf*)0;

  pixbuf = (GdkPixbuf*)0;
  klass = G_OBJECT_GET_CLASS(shadeComboBox);
  gtk_tree_model_get(GTK_TREE_MODEL(VISU_UI_SHADE_COMBOBOX_CLASS(klass)->listStoredToolShades), &iter,
		     COLUMN_SHADE_PIXBUF, &pixbuf,
		     -1);
  return pixbuf;
}
/**
 * visu_ui_shade_combobox_getSelection:
 * @shadeComboBox: a #VisuUiShadeCombobox widget.
 *
 * The user can access to the selected #ToolShade object using this method.
 *
 * Returns: (transfer none): a pointer to the selected #ToolShade
 * object (or NULL). This object is read-only.
 *
 * Since: 3.3
 */
ToolShade* visu_ui_shade_combobox_getSelection(VisuUiShadeCombobox *shadeComboBox)
{
  gboolean validIter;
  GtkTreeIter iter;
  ToolShade *shade;
  GObjectClass *klass;

  g_return_val_if_fail(VISU_IS_UI_SHADE_COMBOBOX(shadeComboBox), (ToolShade*)0);

  validIter = gtk_combo_box_get_active_iter(GTK_COMBO_BOX(shadeComboBox), &iter);
  if (!validIter)
    return (ToolShade*)0;

  shade = (ToolShade*)0;
  klass = G_OBJECT_GET_CLASS(shadeComboBox);
  gtk_tree_model_get(GTK_TREE_MODEL(VISU_UI_SHADE_COMBOBOX_CLASS(klass)->listStoredToolShades), &iter,
		     COLUMN_SHADE_POINTER_TO, &shade,
		     -1);
  return shade;
}
/**
 * visu_ui_shade_combobox_getStamp:
 * @shadeComboBox: a #VisuUiShadeCombobox widget ;
 * @shade: a #ToolShade object.
 *
 * The @shadeComboBox has little pixbufs to represent the shade. User methods can
 * use these pixbufs but should considered them read-only.
 *
 * Returns: (transfer none): a pixbuf pointer corresponding to the
 * little image shown on the @shadeComboBox.
 *
 * Since: 3.3
 */
GdkPixbuf* visu_ui_shade_combobox_getStamp(VisuUiShadeCombobox *shadeComboBox,
                                           ToolShade *shade)
{
  GtkTreeIter iter;
  gboolean validIter;
  GdkPixbuf *pixbuf;
  ToolShade *cl;
  GtkListStore *model;

  g_return_val_if_fail(VISU_IS_UI_SHADE_COMBOBOX(shadeComboBox) && shade, (GdkPixbuf*)0);

  model = VISU_UI_SHADE_COMBOBOX_CLASS(G_OBJECT_GET_CLASS(shadeComboBox))->listStoredToolShades;
  validIter = gtk_tree_model_get_iter_first(GTK_TREE_MODEL(model), &iter);
  while (validIter)
    {
      pixbuf = (GdkPixbuf*)0;
      cl = (ToolShade*)0;
      gtk_tree_model_get(GTK_TREE_MODEL(model), &iter,
			 COLUMN_SHADE_PIXBUF, &pixbuf,
			 COLUMN_SHADE_POINTER_TO, &cl,
			 -1);
      if (shade == cl)
	return pixbuf;
      validIter = gtk_tree_model_iter_next(GTK_TREE_MODEL(model), &iter);
    }
  return (GdkPixbuf*)0;
}


static void exportParameters(GString *data, VisuData* dataObj _U_)
{
  g_return_if_fail(my_class);

  g_string_append_printf(data, "# %s\n", DESC_PARAMETER_FAVSHADE);
  g_string_append_printf(data, "%s[gtk]: %d\n\n", FLAG_PARAMETER_FAVSHADE,
			 my_class->favToolShade);
}
