/*   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 <support.h>
#include "gtk_lineObjectWidget.h"
#include "gtk_stippleComboBoxWidget.h"
#include "gtk_colorComboBoxWidget.h"
#include <visu_tools.h>

/**
 * SECTION:gtk_lineObjectWidget
 * @short_description: Defines a specialised #GtkBox to choose
 * all characteristic of lines.
 * @see_also: #VisuUiColorCombobox and #VisuUiStippleCombobox
 *
 * <para></para>
 *
 * Since: 3.4
 */

enum {
  LINE_USE_CHANGED_SIGNAL,
  LINE_WIDTH_CHANGED_SIGNAL,
  LINE_STIPPLE_CHANGED_SIGNAL,
  LINE_COLOR_CHANGED_SIGNAL,
  LAST_SIGNAL
};

enum
  {
    PROP_0,
    LABEL_PROP,
    COLOR_PROP,
    N_PROP
  };
static GParamSpec *properties[N_PROP];

static void visu_ui_line_dispose (GObject *obj);
static void visu_ui_line_finalize(GObject *obj);
static void visu_ui_line_get_property(GObject* obj, guint property_id,
                                      GValue *value, GParamSpec *pspec);
static void visu_ui_line_set_property(GObject* obj, guint property_id,
                                      const GValue *value, GParamSpec *pspec);

static guint visu_ui_line_signals[LAST_SIGNAL] = { 0 };

/**
 * VisuUiLine:
 *
 * Private structure to store informations of a #VisuUiLine object.
 *
 * Since: 3.4
 */
/**
 * VisuUiLinePrivate:
 *
 * Private data.
 */
struct _VisuUiLinePrivate
{
  GtkWidget *expand;
  GtkWidget *label;
  GtkWidget *used;
  GtkWidget *width;
  GtkWidget *stipple;

  GtkWidget *rgRGB[3];
  GtkWidget *color;
  GtkWidget *btColor;

  gulong rgSignals[3];
  gulong colorSignal;

  /* Binding to a VisuGlExt object. */
  VisuGlExtLined *model;
  GBinding *bind_active, *bind_width, *bind_stipple, *bind_color;

  /* Memory gestion. */
  gboolean dispose_has_run;
};

/* Local callbacks. */
static void onUseChanged(GtkCheckButton *check, VisuUiLine *line);
static void onWidthChanged(GtkSpinButton *spin, VisuUiLine *line);
static void onStippleChanged(VisuUiStippleCombobox *wd, guint stipple, VisuUiLine *line);
static void onRGBValueChanged(GtkRange *rg, VisuUiLine *line);
static void onAddClicked(GtkButton *bt, VisuUiLine *line);
static void onColorChanged(VisuUiColorCombobox *combo, ToolColor *color, VisuUiLine *line);

/* Local methods. */
/**
 * visu_ui_line_get_type
 *
 * #GType are unique numbers to identify objects.
 *
 * Returns: the #GType associated with #VisuUiLine objects.
 *
 * Since: 3.4
 */
G_DEFINE_TYPE_WITH_CODE(VisuUiLine, visu_ui_line, GTK_TYPE_BOX,
                        G_ADD_PRIVATE(VisuUiLine))

static void visu_ui_line_class_init(VisuUiLineClass *klass)
{
  DBG_fprintf(stderr, "Gtk VisuUiLine: creating the class of the widget.\n");
  DBG_fprintf(stderr, "                     - adding new signals ;\n");
  /**
   * VisuUiLine::use-changed:
   * @line: the #VisuUiLine that emits the signal ;
   * @used: TRUE if the line is used.
   *
   * This signal is emitted when the usage check box is changed.
   *
   * Since: 3.4
   */
  visu_ui_line_signals[LINE_USE_CHANGED_SIGNAL] =
    g_signal_new ("use-changed",
		  G_TYPE_FROM_CLASS (klass),
		  G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION,
		  G_STRUCT_OFFSET (VisuUiLineClass, lineObject),
		  NULL, 
		  NULL,                
		  g_cclosure_marshal_VOID__BOOLEAN,
		  G_TYPE_NONE, 1, G_TYPE_BOOLEAN);
  /**
   * VisuUiLine::width-changed:
   * @line: the #VisuUiLine that emits the signal ;
   * @width: the new width.
   *
   * This signal is emitted when the width of the line is changed.
   *
   * Since: 3.4
   */
  visu_ui_line_signals[LINE_WIDTH_CHANGED_SIGNAL] =
    g_signal_new ("width-changed",
		  G_TYPE_FROM_CLASS (klass),
		  G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION,
		  G_STRUCT_OFFSET (VisuUiLineClass, lineObject),
		  NULL, 
		  NULL,                
		  g_cclosure_marshal_VOID__INT,
		  G_TYPE_NONE, 1, G_TYPE_INT);
  /**
   * VisuUiLine::stipple-changed:
   * @line: the #VisuUiLine that emits the signal ;
   * @stipple: the new stipple pattern.
   *
   * This signal is emitted when the stipple pattern of the line is changed.
   *
   * Since: 3.4
   */
  visu_ui_line_signals[LINE_STIPPLE_CHANGED_SIGNAL] =
    g_signal_new ("stipple-changed",
		  G_TYPE_FROM_CLASS (klass),
		  G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION,
		  G_STRUCT_OFFSET (VisuUiLineClass, lineObject),
		  NULL, 
		  NULL,                
		  g_cclosure_marshal_VOID__UINT,
		  G_TYPE_NONE, 1, G_TYPE_UINT);
  /**
   * VisuUiLine::color-changed:
   * @line: the #VisuUiLine that emits the signal ;
   * @color: the new color values (three RGB values).
   *
   * This signal is emitted when the colour of the line is changed.
   *
   * Since: 3.4
   */
  visu_ui_line_signals[LINE_COLOR_CHANGED_SIGNAL] =
    g_signal_new ("color-changed",
		  G_TYPE_FROM_CLASS (klass),
		  G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION,
		  G_STRUCT_OFFSET (VisuUiLineClass, lineObject),
		  NULL, 
		  NULL,                
		  g_cclosure_marshal_VOID__POINTER,
		  G_TYPE_NONE, 1, G_TYPE_POINTER);
  
  /* Connect freeing methods. */
  G_OBJECT_CLASS(klass)->dispose = visu_ui_line_dispose;
  G_OBJECT_CLASS(klass)->finalize = visu_ui_line_finalize;
  G_OBJECT_CLASS(klass)->set_property = visu_ui_line_set_property;
  G_OBJECT_CLASS(klass)->get_property = visu_ui_line_get_property;

  /**
   * VisuUiLine::label:
   *
   * Store the label.
   *
   * Since: 3.8
   */
  properties[LABEL_PROP] = g_param_spec_string("label", "line label",
                                               "displayed label on the expander",
                                               "parameters",
                                               G_PARAM_WRITABLE | G_PARAM_CONSTRUCT);
  g_object_class_install_property(G_OBJECT_CLASS(klass), LABEL_PROP,
				  properties[LABEL_PROP]);
  /**
   * VisuUiLine::color:
   *
   * Store the current color.
   *
   * Since: 3.8
   */
  properties[COLOR_PROP] = g_param_spec_boxed("color", "line color",
                                              "selected color",
                                              TOOL_TYPE_COLOR,
                                              G_PARAM_READWRITE);
  g_object_class_install_property(G_OBJECT_CLASS(klass), COLOR_PROP,
				  properties[COLOR_PROP]);
}

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

  if (VISU_UI_LINE(obj)->priv->dispose_has_run)
    return;

  visu_ui_line_bind(VISU_UI_LINE(obj), (VisuGlExtLined*)0);

  VISU_UI_LINE(obj)->priv->dispose_has_run = TRUE;
  /* Chain up to the parent class */
  G_OBJECT_CLASS(visu_ui_line_parent_class)->dispose(obj);
}
static void visu_ui_line_finalize(GObject *obj)
{
  g_return_if_fail(obj);

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

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

  DBG_fprintf(stderr, " | freeing ... OK.\n");
}
static void visu_ui_line_get_property(GObject* obj, guint property_id,
                                      GValue *value, GParamSpec *pspec)
{
  float rgba[4];
  VisuUiLine *self = VISU_UI_LINE(obj);

  DBG_fprintf(stderr, "Gtk VisuUiLine: get property '%s' -> ",
	      g_param_spec_get_name(pspec));
  switch (property_id)
    {
    case COLOR_PROP:
      rgba[0] = gtk_range_get_value(GTK_RANGE(self->priv->rgRGB[0]));
      rgba[1] = gtk_range_get_value(GTK_RANGE(self->priv->rgRGB[1]));
      rgba[2] = gtk_range_get_value(GTK_RANGE(self->priv->rgRGB[2]));
      rgba[3] = 1.f;
      g_value_take_boxed(value, tool_color_new(rgba));
      DBG_fprintf(stderr, "%gx%gx%g.\n", rgba[0], rgba[1], rgba[2]);
      break;
    default:
      /* We don't have any other property... */
      G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, property_id, pspec);
      break;
    }
}
static void visu_ui_line_set_property(GObject* obj, guint property_id,
                                      const GValue *value, GParamSpec *pspec)
{
  ToolColor *color;
  gchar *markup;
  VisuUiLine *self = VISU_UI_LINE(obj);

  DBG_fprintf(stderr, "Gtk VisuUiLine: set property '%s' -> ",
	      g_param_spec_get_name(pspec));
  switch (property_id)
    {
    case LABEL_PROP:
      markup = g_markup_printf_escaped("<b>%s</b>", g_value_get_string(value));
      gtk_label_set_markup(GTK_LABEL(self->priv->label), markup);
      DBG_fprintf(stderr, "%s.\n", markup);
      g_free(markup);
      break;
    case COLOR_PROP:
      color = (ToolColor*)g_value_get_boxed(value);
      visu_ui_line_setColor(self, color->rgba);
      DBG_fprintf(stderr, "%gx%gx%g.\n", color->rgba[0], color->rgba[1], color->rgba[2]);
      break;
    default:
      /* We don't have any other property... */
      G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, property_id, pspec);
      break;
    }
}


static void visu_ui_line_init(VisuUiLine *line)
{
  GtkWidget *vbox, *hbox, *label, *table;
  char *rgb[3];
  char *rgbName[3] = {"scroll_r", "scroll_g", "scroll_b"};
  int i;

  DBG_fprintf(stderr, "Gtk VisuUiLine: initializing new object (%p).\n",
	      (gpointer)line);

  line->priv = visu_ui_line_get_instance_private(line);

  line->priv->model = (VisuGlExtLined*)0;

  gtk_orientable_set_orientation(GTK_ORIENTABLE(line), GTK_ORIENTATION_VERTICAL);
  gtk_box_set_spacing(GTK_BOX(line), 5);

  /********************/
  /* The header line. */
  /********************/
  hbox = gtk_hbox_new(FALSE, 0);
  gtk_box_pack_start(GTK_BOX(line), hbox, FALSE, FALSE, 0);

  /* The drawn checkbox. */
  line->priv->used = gtk_check_button_new();
  gtk_widget_set_valign(line->priv->used, GTK_ALIGN_START);
  gtk_box_pack_start(GTK_BOX(hbox), line->priv->used, FALSE, FALSE, 0);
  g_signal_connect(G_OBJECT(line->priv->used), "toggled",
                   G_CALLBACK(onUseChanged), (gpointer)line);

  /* The expander. */
  line->priv->expand = gtk_expander_new("");\
  gtk_widget_set_margin_start(line->priv->expand, 5);
  gtk_box_pack_start(GTK_BOX(hbox), line->priv->expand, TRUE, TRUE, 0);

  /* The label. */
  hbox = gtk_hbox_new(FALSE, 30);
  line->priv->label = gtk_label_new("");
  gtk_widget_set_name(line->priv->label, "label_head");
  gtk_box_pack_start(GTK_BOX(hbox), line->priv->label, TRUE, FALSE, 0);
  label = gtk_label_new(_("<span size=\"small\"><i>"
			  "expand for options</i></span>"));
  gtk_label_set_use_markup(GTK_LABEL(label), TRUE);
  gtk_box_pack_end(GTK_BOX(hbox), label, FALSE, FALSE, 0);
  gtk_expander_set_label_widget(GTK_EXPANDER(line->priv->expand), hbox);

  /* The insider. */
  vbox = gtk_vbox_new(FALSE, 2);
  gtk_container_add(GTK_CONTAINER(line->priv->expand), vbox);

  /*******************/
  /* The scale line. */
  /*******************/
  hbox = gtk_hbox_new(FALSE, 0);
  gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);

  /* The label. */
  label = gtk_label_new(_("Line style:"));
  gtk_label_set_xalign(GTK_LABEL(label), 0.);
  gtk_box_pack_start(GTK_BOX(hbox), label, TRUE, TRUE, 0);

  /* The scale width spin button. */
  label = gtk_label_new(_("width:"));
  gtk_widget_set_margin_start(label, 5);
  gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
  line->priv->width = gtk_spin_button_new_with_range(1., 10., 1.);
  gtk_entry_set_width_chars(GTK_ENTRY(line->priv->width), 2);
  gtk_box_pack_start(GTK_BOX(hbox), line->priv->width, FALSE, FALSE, 0);
  g_signal_connect(G_OBJECT(line->priv->width), "value-changed",
                   G_CALLBACK(onWidthChanged), (gpointer)line);
  /* px for pixel. */
  label = gtk_label_new(_("px"));
  gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 2);
  /* The stipple pattern. */
  line->priv->stipple = visu_ui_stipple_combobox_new();
  gtk_widget_set_margin_start(line->priv->stipple, 5);
  gtk_widget_set_hexpand(line->priv->stipple, FALSE);
  gtk_widget_set_halign(line->priv->stipple, GTK_ALIGN_END);
  gtk_box_pack_start(GTK_BOX(hbox), line->priv->stipple, TRUE, TRUE, 0);
  g_signal_connect(G_OBJECT(line->priv->stipple), "stipple-selected",
		   G_CALLBACK(onStippleChanged), (gpointer)line);

  /********************/
  /* The colour line. */
  /********************/
  hbox = gtk_hbox_new(FALSE, 10);
  
  gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
  /* The table for the box colour. */
  table = gtk_grid_new();
  tool_grid_resize(table, 3, 2);
  gtk_box_pack_end(GTK_BOX(hbox), table, TRUE, TRUE, 0);
  rgb[0] = _("R:");
  rgb[1] = _("G:");
  rgb[2] = _("B:");
  for (i = 0; i < 3; i++)
    {
      label = gtk_label_new(rgb[i]);
      gtk_grid_attach(GTK_GRID(table), label, 0, i, 1, 1);
      line->priv->rgRGB[i] = gtk_hscale_new_with_range(0., 1., 0.001);
      gtk_widget_set_hexpand(line->priv->rgRGB[i], TRUE);
      gtk_scale_set_value_pos(GTK_SCALE(line->priv->rgRGB[i]),
			      GTK_POS_RIGHT);
      gtk_range_set_value(GTK_RANGE(line->priv->rgRGB[i]), 0.741456963);
      gtk_widget_set_name(line->priv->rgRGB[i], rgbName[i]);
      gtk_grid_attach(GTK_GRID(table), line->priv->rgRGB[i], 1, i, 1, 1);
      line->priv->rgSignals[i] = g_signal_connect(G_OBJECT(line->priv->rgRGB[i]),
					    "value-changed",
					    G_CALLBACK(onRGBValueChanged),
					    (gpointer)line);
    }
  vbox = gtk_vbox_new(FALSE, 0);
  gtk_box_pack_start(GTK_BOX(hbox), vbox, FALSE, FALSE, 0);
  label = gtk_label_new(_("color:"));
  line->priv->color = visu_ui_color_combobox_new(FALSE);
  line->priv->colorSignal = g_signal_connect(G_OBJECT(line->priv->color), "color-selected",
				       G_CALLBACK(onColorChanged), (gpointer)line);
  gtk_label_set_xalign(GTK_LABEL(label), 0.);
  gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 0);
  hbox = gtk_hbox_new(FALSE, 0);
  gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
  visu_ui_color_combobox_setPrintValues(VISU_UI_COLOR_COMBOBOX(line->priv->color), FALSE);
  gtk_box_pack_start(GTK_BOX(hbox), line->priv->color, FALSE, FALSE, 0);
  line->priv->btColor = gtk_button_new();
  gtk_box_pack_end(GTK_BOX(hbox), line->priv->btColor, FALSE, FALSE, 0);
  gtk_container_add(GTK_CONTAINER(line->priv->btColor),
		    gtk_image_new_from_icon_name("go-previous", GTK_ICON_SIZE_MENU));
  label = gtk_label_new(_("<span size=\"small\"><i>(preset)</i></span>"));
  gtk_label_set_use_markup(GTK_LABEL(label), TRUE);
  gtk_label_set_xalign(GTK_LABEL(label), 1.);
  gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 0);
  g_signal_connect(G_OBJECT(line->priv->btColor), "clicked",
		   G_CALLBACK(onAddClicked), (gpointer)line);

  gtk_widget_show_all(GTK_WIDGET(line));
}

/**
 * visu_ui_line_new :
 * @label: the name of the group, output in bold.
 *
 * A #VisuUiLine widget is a widget allowing to choose the
 * properties of a line. These properties are the line stipple
 * pattern, its colour and its width. The colour is available through
 * #GtkRange and with a #VisuUiColorCombobox widget. There is also a
 * checkbox allowing to turn the line on or off.
 *
 * Returns: (transfer full): a newly created #VisuUiLine widget.
 *
 * Since: 3.4
 */
GtkWidget* visu_ui_line_new(const gchar* label)
{
  DBG_fprintf(stderr, "Gtk VisuUiLine: creating new object.\n");

  return GTK_WIDGET(g_object_new(visu_ui_line_get_type(), "label", label, NULL));
}
/**
 * visu_ui_line_bind:
 * @line: a #VisuUiLine object.
 * @model: (transfer none): a #VisuGlExtLined object.
 *
 * Bind the properties of @model to be displayed by @line.
 *
 * Since: 3.8
 **/
void visu_ui_line_bind(VisuUiLine *line, VisuGlExtLined *model)
{
  g_return_if_fail(VISU_IS_UI_LINE(line));

  if (line->priv->model)
    {
      g_object_unref(G_OBJECT(line->priv->bind_active));
      g_object_unref(G_OBJECT(line->priv->bind_width));
      g_object_unref(G_OBJECT(line->priv->bind_stipple));
      g_object_unref(G_OBJECT(line->priv->bind_color));
      g_object_unref(G_OBJECT(line->priv->model));
    }
  line->priv->model = model;
  if (model)
    {
      g_object_ref(G_OBJECT(model));
      line->priv->bind_active = g_object_bind_property(model, "active",
                                                 line->priv->used, "active",
                                                 G_BINDING_BIDIRECTIONAL |
                                                 G_BINDING_SYNC_CREATE);
      line->priv->bind_width = g_object_bind_property(model, "width",
                                                line->priv->width, "value",
                                                G_BINDING_BIDIRECTIONAL |
                                                G_BINDING_SYNC_CREATE);
      line->priv->bind_stipple = g_object_bind_property(model, "stipple",
                                                  line->priv->stipple, "value",
                                                  G_BINDING_BIDIRECTIONAL |
                                                  G_BINDING_SYNC_CREATE);
      line->priv->bind_color = g_object_bind_property(model, "color",
                                                line, "color",
                                                G_BINDING_BIDIRECTIONAL |
                                                G_BINDING_SYNC_CREATE);
    }
}

static void onUseChanged(GtkCheckButton *check, VisuUiLine *line)
{
  g_signal_emit(G_OBJECT(line), visu_ui_line_signals[LINE_USE_CHANGED_SIGNAL],
		0, gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(check)), NULL);
}
static void onWidthChanged(GtkSpinButton *spin, VisuUiLine *line)
{
  g_signal_emit(G_OBJECT(line), visu_ui_line_signals[LINE_WIDTH_CHANGED_SIGNAL],
		0, (gint)gtk_spin_button_get_value(GTK_SPIN_BUTTON(spin)), NULL);
}
static void onStippleChanged(VisuUiStippleCombobox *wd _U_, guint stipple, VisuUiLine *line)
{
  g_signal_emit(G_OBJECT(line), visu_ui_line_signals[LINE_STIPPLE_CHANGED_SIGNAL],
		0, stipple, NULL);
}
static void onRGBValueChanged(GtkRange *rg _U_, VisuUiLine *line)
{
  float rgba[4];
  int i;

  g_return_if_fail(VISU_IS_UI_LINE(line));

  rgba[0] = gtk_range_get_value(GTK_RANGE(line->priv->rgRGB[0]));
  rgba[1] = gtk_range_get_value(GTK_RANGE(line->priv->rgRGB[1]));
  rgba[2] = gtk_range_get_value(GTK_RANGE(line->priv->rgRGB[2]));
  rgba[3] = 1.f;
  tool_color_getByValues(&i, rgba[0], rgba[1], rgba[2], rgba[3]);

  g_signal_handler_block(G_OBJECT(line->priv->color), line->priv->colorSignal);
  if (i < 0)
    gtk_combo_box_set_active(GTK_COMBO_BOX(line->priv->color), -1);
  else
    gtk_combo_box_set_active(GTK_COMBO_BOX(line->priv->color), i + 1);
  g_signal_handler_unblock(G_OBJECT(line->priv->color), line->priv->colorSignal);

  gtk_widget_set_sensitive(line->priv->btColor, (i < 0));

  g_object_notify_by_pspec(G_OBJECT(line), properties[COLOR_PROP]);
  g_signal_emit(G_OBJECT(line), visu_ui_line_signals[LINE_COLOR_CHANGED_SIGNAL],
		0, (gpointer)rgba, NULL);
}
static void onAddClicked(GtkButton *bt _U_, VisuUiLine *line)
{
  float rgba[4];
  int selected;

  g_return_if_fail(VISU_IS_UI_LINE(line));

  DBG_fprintf(stderr, "Gtk VisuUiLine: adding a new color from ranges.\n");

  rgba[0] = gtk_range_get_value(GTK_RANGE(line->priv->rgRGB[0]));
  rgba[1] = gtk_range_get_value(GTK_RANGE(line->priv->rgRGB[1]));
  rgba[2] = gtk_range_get_value(GTK_RANGE(line->priv->rgRGB[2]));
  rgba[3] = 1.f;
  tool_color_addFloatRGBA(rgba, &selected);
  g_signal_handler_block(G_OBJECT(line->priv->color), line->priv->colorSignal);
  gtk_combo_box_set_active(GTK_COMBO_BOX(line->priv->color), selected);
  g_signal_handler_unblock(G_OBJECT(line->priv->color), line->priv->colorSignal);
  gtk_widget_set_sensitive(line->priv->btColor, FALSE);
}
static void onColorChanged(VisuUiColorCombobox *combo _U_, ToolColor *color, VisuUiLine *line)
{
  visu_ui_line_setColor(line, color->rgba);
}

/**
 * visu_ui_line_setUsed:
 * @line: the object to modify ;
 * @status: a boolean.
 *
 * The line can be turn on or off, call this routine to change the
 * interface status.
 *
 * Since: 3.4
 */
void visu_ui_line_setUsed(VisuUiLine *line, gboolean status)
{
  g_return_if_fail(VISU_IS_UI_LINE(line));

  gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(line->priv->used), status);
}
/**
 * visu_ui_line_setWidth:
 * @line: the object to modify ;
 * @width: a value.
 *
 * The line can be drawn with a given width, call this routine to change the
 * interface value.
 *
 * Since: 3.4
 */
void visu_ui_line_setWidth(VisuUiLine *line, gint width)
{
  g_return_if_fail(VISU_IS_UI_LINE(line) && width > 0 && width < 11);

  gtk_spin_button_set_value(GTK_SPIN_BUTTON(line->priv->width), (gdouble)width);
}
/**
 * visu_ui_line_setColor:
 * @line: the object to modify ;
 * @rgb: a RGB array.
 *
 * The line can is drawn in a given colour. Change the interface
 * values using this routine. The colour ranges are updated and if it
 * correspond to a registered colour, it is selected in the combobox.
 *
 * Since: 3.4
 */
void visu_ui_line_setColor(VisuUiLine *line, float rgb[3])
{
  gboolean change;

  g_return_if_fail(VISU_IS_UI_LINE(line));

  g_signal_handler_block(G_OBJECT(line->priv->rgRGB[0]), line->priv->rgSignals[0]);
  g_signal_handler_block(G_OBJECT(line->priv->rgRGB[1]), line->priv->rgSignals[1]);
  g_signal_handler_block(G_OBJECT(line->priv->rgRGB[2]), line->priv->rgSignals[2]);

  change = FALSE;
  if ((float)gtk_range_get_value(GTK_RANGE(line->priv->rgRGB[0])) != rgb[0])
    {
      change = TRUE;
      gtk_range_set_value(GTK_RANGE(line->priv->rgRGB[0]), rgb[0]);
    }
  if ((float)gtk_range_get_value(GTK_RANGE(line->priv->rgRGB[1])) != rgb[1])
    {
      change = TRUE;
      gtk_range_set_value(GTK_RANGE(line->priv->rgRGB[1]), rgb[1]);
    }
  if ((float)gtk_range_get_value(GTK_RANGE(line->priv->rgRGB[2])) != rgb[2])
    {
      change = TRUE;
      gtk_range_set_value(GTK_RANGE(line->priv->rgRGB[2]), rgb[2]);
    }

  g_signal_handler_unblock(G_OBJECT(line->priv->rgRGB[0]), line->priv->rgSignals[0]);
  g_signal_handler_unblock(G_OBJECT(line->priv->rgRGB[1]), line->priv->rgSignals[1]);
  g_signal_handler_unblock(G_OBJECT(line->priv->rgRGB[2]), line->priv->rgSignals[2]);

  if (change)
    onRGBValueChanged((GtkRange*)0, line);
}
/**
 * visu_ui_line_setStipple:
 * @line: the object to modify ;
 * @stipple: a value.
 *
 * The line can be drawn with a given stipple pattern, call this
 * routine to change the interface value.
 *
 * Since: 3.4
 */
void visu_ui_line_setStipple(VisuUiLine *line, guint16 stipple)
{
  g_return_if_fail(VISU_IS_UI_LINE(line));

  visu_ui_stipple_combobox_set(VISU_UI_STIPPLE_COMBOBOX(line->priv->stipple), stipple);
}
/**
 * visu_ui_line_getOptionBox:
 * @line:  the object to get the GtkVBox.
 *
 * Give access to the #GtkVBox of the expander.
 *
 * Since: 3.6
 *
 * Returns: (transfer none): a #GtkWidget.
 */
GtkWidget* visu_ui_line_getOptionBox(VisuUiLine *line)
{
  g_return_val_if_fail(VISU_IS_UI_LINE(line), (GtkWidget*)0);

  return gtk_bin_get_child(GTK_BIN(line->priv->expand));
}
