1 /*   EXTRAITS DE LA LICENCE
2 	Copyright CEA, contributeurs : Luc BILLARD et Damien
3 	CALISTE, laboratoire L_Sim, (2001-2005)
4 
5 	Adresse mèl :
6 	BILLARD, non joignable par mèl ;
7 	CALISTE, damien P caliste AT cea P fr.
8 
9 	Ce logiciel est un programme informatique servant à visualiser des
10 	structures atomiques dans un rendu pseudo-3D.
11 
12 	Ce logiciel est régi par la licence CeCILL soumise au droit français et
13 	respectant les principes de diffusion des logiciels libres. Vous pouvez
14 	utiliser, modifier et/ou redistribuer ce programme sous les conditions
15 	de la licence CeCILL telle que diffusée par le CEA, le CNRS et l'INRIA
16 	sur le site "http://www.cecill.info".
17 
18 	Le fait que vous puissiez accéder à cet en-tête signifie que vous avez
19 	pris connaissance de la licence CeCILL, et que vous en avez accepté les
20 	termes (cf. le fichier Documentation/licence.fr.txt fourni avec ce logiciel).
21 */
22 
23 /*   LICENCE SUM UP
24 	Copyright CEA, contributors : Luc BILLARD et Damien
25 	CALISTE, laboratoire L_Sim, (2001-2005)
26 
27 	E-mail address:
28 	BILLARD, not reachable any more ;
29 	CALISTE, damien P caliste AT cea P fr.
30 
31 	This software is a computer program whose purpose is to visualize atomic
32 	configurations in 3D.
33 
34 	This software is governed by the CeCILL  license under French law and
35 	abiding by the rules of distribution of free software.  You can  use,
36 	modify and/ or redistribute the software under the terms of the CeCILL
37 	license as circulated by CEA, CNRS and INRIA at the following URL
38 	"http://www.cecill.info".
39 
40 	The fact that you are presently reading this means that you have had
41 	knowledge of the CeCILL license and that you accept its terms. You can
42 	find a copy of this licence shipped with this software at Documentation/licence.en.txt.
43 */
44 #include <gtk/gtk.h>
45 
46 #include "gtk_colorComboBoxWidget.h"
47 #include <support.h>
48 #include <visu_tools.h>
49 
50 /**
51  * SECTION:gtk_colorComboBoxWidget
52  * @short_description: Defines a specialised #GtkComboBox to choose
53  * stored colours.
54  * @see_also: #ToolColor, #VisuUiStippleCombobox, #VisuUiShadeCombobox
55  * @include: coreTools/toolColor.h
56  *
57  * <para>This widget looks like a #GtkComboBox and it displays a list
58  * of stored colours. These colours may come from the configuration
59  * files or can be selected and stored by the user actions. To do it,
60  * the first entry of the combo box is 'new / modify', that opens a GTK
61  * colour picker. The new values are used to craete a new colour entry
62  * in the combo box. In a complete version, the combo box can have a
63  * #GtkVBox associated to modify colours without creating new entries, see
64  * visu_ui_color_combobox_newWithRanges() method. Otherwise, only already
65  * selected colours are available. The stored colours are shared by
66  * all widgets of this class. It is thus a convenient way to have
67  * coherent colour picker through V_Sim.</para>
68  *
69  * <para>When the widget is created with ranges, the additional part
70  * can be retrieve with visu_ui_color_combobox_getRangeWidgets() and attached
71  * whereever is convenient. When the ranges are modified, the new
72  * colour is not added to the combo box. It can be read using
73  * visu_ui_color_combobox_getRangeColor() or visu_ui_color_combobox_getRangeMaterial(). The combo
74  * box is set thus to an unselected state and
75  * visu_ui_color_combobox_getSelection() will return a NULL
76  * pointer. Besides the colour ranges, there is an add button to
77  * insert the newly defined colour into the combo box.</para>
78  *
79  * <para>This widget can emit a #VisuUiColorCombobox::color-selected
80  * signal that is a wrapper around the #GtkComboBox::changed signal,
81  * but it is emitted only when a new colour is selected (either an
82  * existing one or a newly created from the picker). This colour
83  * is passed to the callback. The two other signals,
84  * #VisuUiColorCombobox::color-value-changed and
85  * #VisuUiColorCombobox::material-value-changed, are generated when the
86  * widget have been created with ranges and that one of these ranges
87  * is modified.</para>
88  *
89  * Since: 3.1
90  */
91 
92 enum {
93   COLOR_SELECTED_SIGNAL,
94   COLOR_VALUE_CHANGED_SIGNAL,
95   MATERIAL_VALUE_CHANGED_SIGNAL,
96   LAST_SIGNAL
97 };
98 static guint signals[LAST_SIGNAL] = { 0 };
99 enum
100   {
101     PROP_0,
102     COLOR_PROP,
103     MATERIAL_PROP,
104     N_PROP
105   };
106 static GParamSpec *properties[N_PROP];
107 
108 /* This enum is used to access the column of the GtkListStore
109    that contains the informations of stroed colors. */
110 enum
111   {
112     /* This has a pointer to a 16x16 image to represent the color,
113        including the alpha channel. */
114     COLUMN_COLOR_PIXBUF_ALPHA,
115     /* This has a pointer to a 16x16 image to represent the color,
116        without the alpha channel. */
117     COLUMN_COLOR_PIXBUF,
118     /* This is a pointer to a label that describes the color :
119        "(n_red;n_green;n_blue;n_alpha)" with n_xxx from 0 to 255. */
120     COLUMN_COLOR_LABEL_ALPHA,
121     /* This is the same label than above but without the alpha value. */
122     COLUMN_COLOR_LABEL,
123     /* This a pointer to the #ToolColor as defined in visuTools.h */
124     COLUMN_COLOR_POINTER_TO,
125     N_COLUMN_COLOR
126   };
127 
128 /* Labels for the ranges part. */
129 #define RED_ELE_LABEL   _("R:")
130 #define GREEN_ELE_LABEL _("G:")
131 #define BLUE_ELE_LABEL  _("B:")
132 #define ALPHA_ELE_LABEL _("Alph:")
133 #define AMB_ELE_LABEL   _("amb:")
134 #define DIF_ELE_LABEL   _("dif:")
135 #define SHI_ELE_LABEL   _("shi:")
136 #define SPE_ELE_LABEL   _("spe:")
137 #define EMI_ELE_LABEL   _("emi:")
138 
139 static void visu_ui_color_combobox_changed (GtkWidget *widget, VisuUiColorCombobox *colorComboBox);
140 static void visu_ui_color_combobox_dispose (GObject *obj);
141 static void visu_ui_color_combobox_finalize(GObject *obj);
142 static void visu_ui_color_combobox_get_property(GObject* obj, guint property_id,
143                                                 GValue *value, GParamSpec *pspec);
144 static void visu_ui_color_combobox_set_property(GObject* obj, guint property_id,
145                                                 const GValue *value, GParamSpec *pspec);
146 
147 /**
148  * VisuUiColorCombobox
149  *
150  * Private structure to store informations of a #VisuUiColorCombobox object.
151  *
152  * Since: 3.1
153  */
154 struct _VisuUiColorCombobox
155 {
156   GtkComboBox comboColor;
157   ToolColor* previouslySelectedColor;
158 
159   gboolean withRanges;
160   GtkWidget *expandRanges;
161   GtkWidget *rgbRanges[4];
162   GtkWidget *materialRanges[TOOL_MATERIAL_N_VALUES];
163   gulong rgbSignals[4];
164   gulong materialSignals[TOOL_MATERIAL_N_VALUES];
165   gulong comboSignal;
166   GtkWidget *addButton;
167 
168   gboolean hasAlphaChannel;
169 
170   GtkCellRenderer *rendererRGB;
171 
172   /* Memory gestion. */
173   gboolean dispose_has_run;
174 };
175 /**
176  * VisuUiColorComboboxClass
177  *
178  * Private structure to store informations of a #VisuUiColorComboboxClass object.
179  *
180  * Since: 3.1
181  */
182 struct _VisuUiColorComboboxClass
183 {
184   GtkComboBoxClass parent_class;
185 
186   void (*colorComboBox) (VisuUiColorCombobox *colorCombo);
187 
188   /* This listStore contains all the colors
189      known by widgets of this class. It is used
190      as TreeModel for the combobox in the widget. */
191   GtkListStore *listStoredColors;
192 
193   gulong colorAddedSignalId;
194 };
195 
196 /* Local callbacks. */
197 static void visu_ui_color_combobox_materialChanged(GtkRange *rg, gpointer data);
198 static void visu_ui_color_combobox_rgbChanged(GtkRange *rg, gpointer data);
199 static void visu_ui_color_combobox_addButtonClicked(GtkButton *button, gpointer data);
200 
201 /* Local methods. */
202 static void addColorToModel(GtkTreeIter *iter, VisuUiColorComboboxClass* klass,
203 			    ToolColor* color);
204 static void onNewColorAvailable(ToolPool *pool, ToolColor* newColor, gpointer data);
205 
206 /**
207  * visu_ui_color_combobox_get_type
208  *
209  * #GType are unique numbers to identify objects.
210  *
211  * Returns: the #GType associated with #VisuUiColorCombobox objects.
212  *
213  * Since: 3.1
214  */
G_DEFINE_TYPE(VisuUiColorCombobox,visu_ui_color_combobox,GTK_TYPE_COMBO_BOX)215 G_DEFINE_TYPE(VisuUiColorCombobox, visu_ui_color_combobox, GTK_TYPE_COMBO_BOX)
216 
217 static void visu_ui_color_combobox_class_init(VisuUiColorComboboxClass *klass)
218 {
219   GtkTreeIter iter;
220   GList *colorLst;
221 
222   DBG_fprintf(stderr, "Gtk VisuUiColorCombobox: creating the class of the widget.\n");
223   DBG_fprintf(stderr, "                     - adding new signals ;\n");
224   /**
225    * VisuUiColorCombobox::color-selected:
226    * @combo: the #VisuUiColorCombobox that emits the signal ;
227    * @color: the newly selected #ToolColor.
228    *
229    * This signal is emitted when a new valid colour is selected,
230    * either an existing one or newly created one.
231    *
232    * Since: 3.1
233    */
234   signals[COLOR_SELECTED_SIGNAL] =
235     g_signal_new ("color-selected",
236 		  G_TYPE_FROM_CLASS (klass),
237 		  G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION,
238 		  G_STRUCT_OFFSET (VisuUiColorComboboxClass, colorComboBox),
239 		  NULL,
240 		  NULL,
241 		  g_cclosure_marshal_VOID__POINTER,
242 		  G_TYPE_NONE, 1, G_TYPE_POINTER);
243   /**
244    * VisuUiColorCombobox::color-value-changed:
245    * @combo: the #VisuUiColorCombobox that emits the signal ;
246    * @RGBA: the modified channel.
247    *
248    * This signal is emitted when the range of a colour is modified.
249    *
250    * Since: 3.3
251    */
252   signals[COLOR_VALUE_CHANGED_SIGNAL] =
253     g_signal_new ("color-value-changed",
254 		  G_TYPE_FROM_CLASS (klass),
255 		  G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION,
256 		  G_STRUCT_OFFSET (VisuUiColorComboboxClass, colorComboBox),
257 		  NULL,
258 		  NULL,
259 		  g_cclosure_marshal_VOID__UINT,
260 		  G_TYPE_NONE, 1, G_TYPE_UINT);
261   /**
262    * VisuUiColorCombobox::material-value-changed:
263    * @combo: the #VisuUiColorCombobox that emits the signal ;
264    * @mat: the modified material channel (see #ToolMaterialIds).
265    *
266    * This signal is emitted when the range of a material is modified.
267    *
268    * Since: 3.3
269    */
270   signals[MATERIAL_VALUE_CHANGED_SIGNAL] =
271     g_signal_new ("material-value-changed",
272 		  G_TYPE_FROM_CLASS (klass),
273 		  G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION,
274 		  G_STRUCT_OFFSET (VisuUiColorComboboxClass, colorComboBox),
275 		  NULL,
276 		  NULL,
277 		  g_cclosure_marshal_VOID__UINT,
278 		  G_TYPE_NONE, 1, G_TYPE_UINT);
279 
280   DBG_fprintf(stderr, "                     - initializing the listStore of colors.\n");
281   /* Init the listStore of colors. */
282   klass->listStoredColors = gtk_list_store_new (N_COLUMN_COLOR,
283 						GDK_TYPE_PIXBUF,
284 						GDK_TYPE_PIXBUF,
285 						G_TYPE_STRING,
286 						G_TYPE_STRING,
287 						G_TYPE_POINTER);
288   gtk_list_store_append(klass->listStoredColors, &iter);
289   gtk_list_store_set(klass->listStoredColors, &iter,
290 		     COLUMN_COLOR_PIXBUF_ALPHA, NULL,
291 		     COLUMN_COLOR_PIXBUF      , NULL,
292 		     COLUMN_COLOR_LABEL_ALPHA , _("New / modify"),
293 		     COLUMN_COLOR_LABEL       , _("New / modify"),
294 		     COLUMN_COLOR_POINTER_TO  , NULL,
295 		     -1);
296   klass->colorAddedSignalId = g_signal_connect(tool_color_getStorage(), "new-element",
297 					       G_CALLBACK(onNewColorAvailable),
298 					       (gpointer)klass);
299   DBG_fprintf(stderr, "                     - add stored colours.\n");
300   colorLst = tool_pool_asList(tool_color_getStorage());
301   while (colorLst)
302     {
303       addColorToModel(&iter, klass, (ToolColor*)colorLst->data);
304       colorLst = g_list_next(colorLst);
305     }
306 
307   /* Connect freeing methods. */
308   G_OBJECT_CLASS(klass)->dispose = visu_ui_color_combobox_dispose;
309   G_OBJECT_CLASS(klass)->finalize = visu_ui_color_combobox_finalize;
310   G_OBJECT_CLASS(klass)->set_property = visu_ui_color_combobox_set_property;
311   G_OBJECT_CLASS(klass)->get_property = visu_ui_color_combobox_get_property;
312 
313   /**
314    * VisuUiColorCombobox::color:
315    *
316    * Store the color of the current selection.
317    *
318    * Since: 3.8
319    */
320   properties[COLOR_PROP] = g_param_spec_boxed("color", "Color",
321                                               "color of the current selection",
322                                               TOOL_TYPE_COLOR, G_PARAM_READWRITE);
323   /**
324    * VisuUiColorCombobox::material:
325    *
326    * Store the material of the current selection.
327    *
328    * Since: 3.8
329    */
330   properties[MATERIAL_PROP] = g_param_spec_boxed("material", "Material",
331                                                  "material of the current selection",
332                                                  TOOL_TYPE_MATERIAL, G_PARAM_READWRITE);
333 
334   g_object_class_install_properties(G_OBJECT_CLASS(klass), N_PROP, properties);
335 }
336 
visu_ui_color_combobox_dispose(GObject * obj)337 static void visu_ui_color_combobox_dispose(GObject *obj)
338 {
339   DBG_fprintf(stderr, "Gtk VisuUiColorCombobox: dispose object %p.\n", (gpointer)obj);
340 
341   if (VISU_UI_COLOR_COMBOBOX(obj)->dispose_has_run)
342     return;
343 
344   VISU_UI_COLOR_COMBOBOX(obj)->dispose_has_run = TRUE;
345   /* Chain up to the parent class */
346   G_OBJECT_CLASS(visu_ui_color_combobox_parent_class)->dispose(obj);
347 }
visu_ui_color_combobox_finalize(GObject * obj)348 static void visu_ui_color_combobox_finalize(GObject *obj)
349 {
350   /* VisuUiColorCombobox *colorComboBox; */
351 
352   g_return_if_fail(obj);
353 
354   DBG_fprintf(stderr, "Gtk VisuUiColorCombobox: finalize object %p.\n", (gpointer)obj);
355 
356   /* colorComboBox = VISU_UI_COLOR_COMBOBOX(obj); */
357 /*   if (colorComboBox->expandRanges) */
358 /*     gtk_widget_destroy(colorComboBox->expandRanges); */
359 
360   /* Chain up to the parent class */
361   G_OBJECT_CLASS(visu_ui_color_combobox_parent_class)->finalize(obj);
362 
363   DBG_fprintf(stderr, "Gtk VisuUiColorCombobox: freeing ... OK.\n");
364 }
visu_ui_color_combobox_get_property(GObject * obj,guint property_id,GValue * value,GParamSpec * pspec)365 static void visu_ui_color_combobox_get_property(GObject* obj, guint property_id,
366                                                 GValue *value, GParamSpec *pspec)
367 {
368   VisuUiColorCombobox *self = VISU_UI_COLOR_COMBOBOX(obj);
369   const ToolColor *color;
370   ToolColor _color;
371 
372   DBG_fprintf(stderr, "Gtk VisuUiColorCombobox: get property '%s'.\n",
373 	      g_param_spec_get_name(pspec));
374   switch (property_id)
375     {
376     case COLOR_PROP:
377       color = visu_ui_color_combobox_getSelection(self);
378       if (color)
379         g_value_set_static_boxed(value, color);
380       else
381         {
382           _color.rgba[0] = gtk_range_get_value(GTK_RANGE(self->rgbRanges[0]));
383           _color.rgba[1] = gtk_range_get_value(GTK_RANGE(self->rgbRanges[1]));
384           _color.rgba[2] = gtk_range_get_value(GTK_RANGE(self->rgbRanges[2]));
385           _color.rgba[3] = gtk_range_get_value(GTK_RANGE(self->rgbRanges[3]));
386           g_value_set_boxed(value, &_color);
387         }
388       DBG_fprintf(stderr, " | color pointer is %p.\n",
389                   (gpointer)g_value_get_boxed(value));
390       break;
391     case MATERIAL_PROP:
392       g_value_take_boxed(value, visu_ui_color_combobox_getRangeMaterial(self));
393       DBG_fprintf(stderr, " | material pointer is %p.\n",
394                   (gpointer)g_value_get_boxed(value));
395       break;
396     default:
397       /* We don't have any other property... */
398       G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, property_id, pspec);
399       break;
400     }
401 }
visu_ui_color_combobox_set_property(GObject * obj,guint property_id,const GValue * value,GParamSpec * pspec)402 static void visu_ui_color_combobox_set_property(GObject* obj, guint property_id,
403                                                 const GValue *value, GParamSpec *pspec)
404 {
405   GtkTreeIter iter;
406   VisuUiColorCombobox *self = VISU_UI_COLOR_COMBOBOX(obj);
407 
408   DBG_fprintf(stderr, "Gtk VisuUiColorCombobox: set property '%s'.\n",
409 	      g_param_spec_get_name(pspec));
410   switch (property_id)
411     {
412     case COLOR_PROP:
413       if (!visu_ui_color_combobox_setSelection(self, (ToolColor*)g_value_get_boxed(value)))
414         {
415           addColorToModel(&iter, VISU_UI_COLOR_COMBOBOX_GET_CLASS(obj),
416                           (ToolColor*)g_value_get_boxed(value));
417           gtk_combo_box_set_active_iter(GTK_COMBO_BOX(obj), &iter);
418         }
419       break;
420     case MATERIAL_PROP:
421       visu_ui_color_combobox_setRangeMaterial(self, (float*)g_value_get_boxed(value), FALSE);
422       break;
423     default:
424       /* We don't have any other property... */
425       G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, property_id, pspec);
426       break;
427     }
428 }
429 
430 
visu_ui_color_combobox_init(VisuUiColorCombobox * colorComboBox)431 static void visu_ui_color_combobox_init(VisuUiColorCombobox *colorComboBox)
432 {
433   DBG_fprintf(stderr, "Gtk VisuUiColorCombobox: initializing new object (%p).\n",
434 	      (gpointer)colorComboBox);
435 
436   colorComboBox->hasAlphaChannel = TRUE;
437   colorComboBox->dispose_has_run = FALSE;
438   colorComboBox->previouslySelectedColor = tool_pool_getById(tool_color_getStorage(), 0);
439 }
440 
_drawPix(GtkCellLayout * layout _U_,GtkCellRenderer * cell,GtkTreeModel * model,GtkTreeIter * iter,gpointer data)441 static void _drawPix(GtkCellLayout *layout _U_, GtkCellRenderer *cell,
442                      GtkTreeModel *model, GtkTreeIter *iter, gpointer data)
443 {
444   GdkPixbuf *pix;
445 
446   if (GPOINTER_TO_INT(data))
447     gtk_tree_model_get(model, iter, COLUMN_COLOR_PIXBUF_ALPHA, &pix, -1);
448   else
449     gtk_tree_model_get(model, iter, COLUMN_COLOR_PIXBUF, &pix, -1);
450 
451   if (pix)
452     {
453       g_object_set(G_OBJECT(cell), "pixbuf", pix, NULL);
454       g_object_unref(pix);
455     }
456   else
457     g_object_set(G_OBJECT(cell), "icon-name", "list-add", NULL);
458 }
buildWidgets(VisuUiColorCombobox * colorComboBox)459 static void buildWidgets(VisuUiColorCombobox *colorComboBox)
460 {
461   GObjectClass *klass;
462   GtkCellRenderer *renderer;
463   GtkWidget *vboxExpand, *table, *label, *hbox, *image;
464   char *rgb[4];
465   char *rgbName[4] = {"scroll_r", "scroll_g", "scroll_b", "scroll_a"};
466   char *material[5];
467   int i, j;
468 
469   klass = G_OBJECT_GET_CLASS(colorComboBox);
470   gtk_combo_box_set_model(GTK_COMBO_BOX(colorComboBox),
471 			  GTK_TREE_MODEL(VISU_UI_COLOR_COMBOBOX_CLASS(klass)->listStoredColors));
472   DBG_fprintf(stderr, "Gtk VisuUiColorCombobox: build widgets.\n");
473   renderer = gtk_cell_renderer_pixbuf_new();
474   gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(colorComboBox), renderer, FALSE);
475   gtk_cell_layout_set_cell_data_func(GTK_CELL_LAYOUT(colorComboBox), renderer, _drawPix,
476                                      GINT_TO_POINTER(colorComboBox->hasAlphaChannel),
477                                      (GDestroyNotify)0);
478   /* if (colorComboBox->hasAlphaChannel) */
479   /*   gtk_cell_layout_add_attribute(GTK_CELL_LAYOUT(colorComboBox), renderer, */
480   /*       			  "pixbuf", COLUMN_COLOR_PIXBUF_ALPHA); */
481   /* else */
482   /*   gtk_cell_layout_add_attribute(GTK_CELL_LAYOUT(colorComboBox), renderer, */
483   /*       			  "pixbuf", COLUMN_COLOR_PIXBUF); */
484   renderer = gtk_cell_renderer_text_new();
485   g_object_set(G_OBJECT(renderer), "scale", 0.85, NULL);
486   gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(colorComboBox), renderer, FALSE);
487   if (colorComboBox->hasAlphaChannel)
488     gtk_cell_layout_add_attribute(GTK_CELL_LAYOUT(colorComboBox), renderer,
489 				  "text", COLUMN_COLOR_LABEL_ALPHA);
490   else
491     gtk_cell_layout_add_attribute(GTK_CELL_LAYOUT(colorComboBox), renderer,
492 				  "text", COLUMN_COLOR_LABEL);
493   colorComboBox->rendererRGB = renderer;
494   DBG_fprintf(stderr, " | renderers OK\n");
495 
496   gtk_combo_box_set_active(GTK_COMBO_BOX(colorComboBox), 1);
497   DBG_fprintf(stderr, " | selection OK\n");
498 
499   colorComboBox->expandRanges = (GtkWidget*)0;
500   if (colorComboBox->withRanges)
501     {
502       DBG_fprintf(stderr, "Gtk VisuUiColorCombobox: add range widgets.\n");
503       rgb[0] = RED_ELE_LABEL;
504       rgb[1] = GREEN_ELE_LABEL;
505       rgb[2] = BLUE_ELE_LABEL;
506       rgb[3] = ALPHA_ELE_LABEL;
507       material[0] = AMB_ELE_LABEL;
508       material[1] = DIF_ELE_LABEL;
509       material[2] = SHI_ELE_LABEL;
510       material[3] = SPE_ELE_LABEL;
511       material[4] = EMI_ELE_LABEL;
512 
513       colorComboBox->expandRanges = gtk_expander_new(_("More options"));
514       gtk_expander_set_expanded(GTK_EXPANDER(colorComboBox->expandRanges), FALSE);
515 
516       vboxExpand = gtk_vbox_new(FALSE, 0);
517       gtk_container_add(GTK_CONTAINER(colorComboBox->expandRanges), vboxExpand);
518 
519       hbox = gtk_hbox_new(FALSE, 0);
520       gtk_box_pack_start(GTK_BOX(vboxExpand), hbox, FALSE, FALSE, 5);
521 
522       table = gtk_grid_new();
523       tool_grid_resize(table, 3, 2);
524       gtk_box_pack_start(GTK_BOX(hbox), table, TRUE, TRUE, 0);
525       gtk_widget_show(table);
526       for (i = 0; i < 3; i++)
527 	{
528 	  label = gtk_label_new(rgb[i]);
529 	  gtk_grid_attach(GTK_GRID(table), label, 0, i, 1, 1);
530 	  colorComboBox->rgbRanges[i] = gtk_hscale_new_with_range(0., 1., 0.001);
531           gtk_widget_set_hexpand(colorComboBox->rgbRanges[i], TRUE);
532 	  gtk_scale_set_value_pos(GTK_SCALE(colorComboBox->rgbRanges[i]),
533 				  GTK_POS_RIGHT);
534 	  gtk_widget_set_name(colorComboBox->rgbRanges[i], rgbName[i]);
535 	  gtk_grid_attach(GTK_GRID(table), colorComboBox->rgbRanges[i],
536                           1, i, 1, 1);
537 	}
538       colorComboBox->addButton = gtk_button_new();
539       gtk_box_pack_start(GTK_BOX(hbox), colorComboBox->addButton, FALSE, FALSE, 2);
540       image = gtk_image_new_from_icon_name("list-add", GTK_ICON_SIZE_BUTTON);
541       gtk_container_add(GTK_CONTAINER(colorComboBox->addButton), image);
542       DBG_fprintf(stderr, " | color OK\n");
543 
544       table = gtk_grid_new();
545       tool_grid_resize(table, 3, 4);
546       gtk_box_pack_start(GTK_BOX(vboxExpand), table, FALSE, FALSE, 5);
547       for (i = 0; i < 2; i++)
548 	{
549 	  for (j = 0; j < 2; j++)
550 	    {
551 	      label = gtk_label_new(material[i * 2 + j]);
552 	      gtk_label_set_xalign(GTK_LABEL(label), 1.);
553 	      gtk_grid_attach(GTK_GRID(table), label, j * 2, i, 1, 1);
554 	      colorComboBox->materialRanges[i * 2 + j] =
555 		gtk_hscale_new_with_range(0., 1., 0.01);
556               gtk_widget_set_hexpand(colorComboBox->materialRanges[i * 2 + j], TRUE);
557 	      gtk_scale_set_value_pos(GTK_SCALE(colorComboBox->materialRanges[i * 2 + j]),
558 				      GTK_POS_RIGHT);
559 	      gtk_widget_set_name(colorComboBox->materialRanges[i * 2 +j], "scroll_mat");
560 	      gtk_grid_attach(GTK_GRID(table), colorComboBox->materialRanges[i * 2 + j],
561                               2 * j + 1, i, 1, 1);
562 	    }
563 	}
564       label = gtk_label_new(material[4]);
565       gtk_label_set_xalign(GTK_LABEL(label), 1);
566       gtk_grid_attach(GTK_GRID(table), label, 0, i, 1, 1);
567       colorComboBox->materialRanges[4] =
568 	gtk_hscale_new_with_range(0., 1., 0.01);
569       gtk_scale_set_value_pos(GTK_SCALE(colorComboBox->materialRanges[4]),
570 			      GTK_POS_RIGHT);
571       gtk_widget_set_name(colorComboBox->materialRanges[4], "scroll_mat");
572       gtk_grid_attach(GTK_GRID(table), colorComboBox->materialRanges[4],
573                       1, i, 1, 1);
574       label = gtk_label_new(rgb[3]);
575       gtk_label_set_xalign(GTK_LABEL(label), 1.);
576       gtk_grid_attach(GTK_GRID(table), label, 2, i, 1, 1);
577       colorComboBox->rgbRanges[3] = gtk_hscale_new_with_range(0., 1., 0.01);
578       gtk_scale_set_value_pos(GTK_SCALE(colorComboBox->rgbRanges[3]),
579 			      GTK_POS_RIGHT);
580       gtk_widget_set_name(colorComboBox->rgbRanges[3], rgbName[3]);
581       gtk_grid_attach(GTK_GRID(table), colorComboBox->rgbRanges[3], 3, i, 1, 1);
582       DBG_fprintf(stderr, " | material OK\n");
583       /* Attach the callbacks. */
584       for (i = 0; i < 4; i++)
585 	colorComboBox->rgbSignals[i] =
586 	  g_signal_connect(G_OBJECT(colorComboBox->rgbRanges[i]), "value-changed",
587 			   G_CALLBACK(visu_ui_color_combobox_rgbChanged), (gpointer)colorComboBox);
588       for (i = 0; i < TOOL_MATERIAL_N_VALUES; i++)
589 	colorComboBox->materialSignals[i] =
590 	  g_signal_connect(G_OBJECT(colorComboBox->materialRanges[i]), "value-changed",
591 			   G_CALLBACK(visu_ui_color_combobox_materialChanged), (gpointer)colorComboBox);
592       g_signal_connect(G_OBJECT(colorComboBox->addButton), "clicked",
593 		       G_CALLBACK(visu_ui_color_combobox_addButtonClicked), (gpointer)colorComboBox);
594       DBG_fprintf(stderr, " | signals OK\n");
595     }
596   colorComboBox->comboSignal = g_signal_connect(G_OBJECT(colorComboBox), "changed",
597 						G_CALLBACK(visu_ui_color_combobox_changed),
598 						(gpointer)colorComboBox);
599 }
600 
601 /**
602  * visu_ui_color_combobox_newWithRanges:
603  * @hasAlphaChannel: a boolean.
604  *
605  * Create a color combo and several ranges.
606  *
607  * Returns: (transfer full): a newly created #VisuUiColorCombobox widget.
608  *
609  * Since: 3.3
610  */
visu_ui_color_combobox_newWithRanges(gboolean hasAlphaChannel)611 GtkWidget* visu_ui_color_combobox_newWithRanges(gboolean hasAlphaChannel)
612 {
613   VisuUiColorCombobox *colorComboBox;
614 
615   DBG_fprintf(stderr, "Gtk VisuUiColorCombobox: creating new object with alpha & ranges: %d.\n",
616 	      hasAlphaChannel);
617 
618   colorComboBox = VISU_UI_COLOR_COMBOBOX(g_object_new(visu_ui_color_combobox_get_type (), NULL));
619   colorComboBox->hasAlphaChannel = hasAlphaChannel;
620   colorComboBox->withRanges = TRUE;
621 
622   buildWidgets(colorComboBox);
623 
624   DBG_fprintf(stderr, "Gtk VisuUiColorCombobox: object ready.\n");
625   return GTK_WIDGET(colorComboBox);
626 }
627 /**
628  * visu_ui_color_combobox_new:
629  * @hasAlphaChannel: a boolean.
630  *
631  * A #VisuUiColorCombobox widget is like a #GtkComboBox widget, but it is already filled
632  * with the colors stores in the structures adhoc in visu_tools.h. Using this widget
633  * is a convienient way to share colors between all part of V_Sim and to give a consistent
634  * look of all color selection. If the argument @hasAlphaChannel is FALSE, the widget
635  * display all colors but without their alpha channel, assuming it to be fully opaque.
636  *
637  * Returns: (transfer full): a newly created #VisuUiColorCombobox widget.
638  *
639  * Since: 3.1
640  */
visu_ui_color_combobox_new(gboolean hasAlphaChannel)641 GtkWidget* visu_ui_color_combobox_new(gboolean hasAlphaChannel)
642 {
643   VisuUiColorCombobox *colorComboBox;
644 
645   DBG_fprintf(stderr, "Gtk VisuUiColorCombobox: creating new object with alpha: %d.\n",
646 	      hasAlphaChannel);
647 
648   colorComboBox = VISU_UI_COLOR_COMBOBOX(g_object_new(visu_ui_color_combobox_get_type (), NULL));
649   colorComboBox->hasAlphaChannel = hasAlphaChannel;
650   colorComboBox->withRanges = FALSE;
651 
652   buildWidgets(colorComboBox);
653 
654   DBG_fprintf(stderr, "Gtk VisuUiColorCombobox: object ready.\n");
655   return GTK_WIDGET(colorComboBox);
656 }
657 /**
658  * visu_ui_color_combobox_setExpanded:
659  * @colorComboBox: a #ToolColor object ;
660  * @value: a boolean value.
661  *
662  * Set the expanded state of the ranges. This is usable only if the colorComboBox
663  * has been created with ranges.
664  *
665  * Since: 3.3
666  */
visu_ui_color_combobox_setExpanded(VisuUiColorCombobox * colorComboBox,gboolean value)667 void visu_ui_color_combobox_setExpanded(VisuUiColorCombobox *colorComboBox, gboolean value)
668 {
669   g_return_if_fail(VISU_IS_UI_COLOR_COMBOBOX(colorComboBox));
670   g_return_if_fail(colorComboBox->withRanges);
671 
672   gtk_expander_set_expanded(GTK_EXPANDER(colorComboBox->expandRanges), value);
673 }
674 /**
675  * visu_ui_color_combobox_setPrintValues:
676  * @colorComboBox: a #ToolColor object ;
677  * @value: a boolean.
678  *
679  * Print or not the RGB values.
680  *
681  * Since: 3.4
682  */
visu_ui_color_combobox_setPrintValues(VisuUiColorCombobox * colorComboBox,gboolean value)683 void visu_ui_color_combobox_setPrintValues(VisuUiColorCombobox *colorComboBox, gboolean value)
684 {
685   g_object_set(G_OBJECT(colorComboBox->rendererRGB),
686 	       "visible", value, NULL);
687 }
688 /**
689  * visu_ui_color_combobox_getRangeWidgets:
690  * @colorComboBox: a #ToolColor object.
691  *
692  * Retrieve the wiodget using to represent the ranges, or NULL if the object
693  * has no ranges.
694  *
695  * Returns: (transfer none): a widget owned by @color.
696  *
697  * Since: 3.3
698  */
visu_ui_color_combobox_getRangeWidgets(VisuUiColorCombobox * colorComboBox)699 GtkWidget* visu_ui_color_combobox_getRangeWidgets(VisuUiColorCombobox *colorComboBox)
700 {
701   g_return_val_if_fail(VISU_IS_UI_COLOR_COMBOBOX(colorComboBox), (GtkWidget*)0);
702 
703   return colorComboBox->expandRanges;
704 }
705 
visu_ui_color_combobox_changed(GtkWidget * widget _U_,VisuUiColorCombobox * colorComboBox)706 static void visu_ui_color_combobox_changed(GtkWidget *widget _U_, VisuUiColorCombobox *colorComboBox)
707 {
708   int selected, i;
709   GdkRGBA gdkcolor;
710   GtkWidget *selection;
711   gint code;
712   float rgba[4];
713   GtkTreeIter iter;
714   GObjectClass *klass;
715   ToolColor *color;
716 
717   selected = gtk_combo_box_get_active(GTK_COMBO_BOX(colorComboBox));
718   DBG_fprintf(stderr, "Gtk VisuUiColorCombobox: internal combobox changed signal -> %d.\n", selected);
719   if (selected < 0)
720     {
721       if (colorComboBox->withRanges)
722 	gtk_widget_set_sensitive(colorComboBox->addButton, TRUE);
723       colorComboBox->previouslySelectedColor = (ToolColor*)0;
724       return;
725     }
726 
727   if (colorComboBox->withRanges)
728     gtk_widget_set_sensitive(colorComboBox->addButton, FALSE);
729 
730   if (selected != 0)
731     {
732       gtk_combo_box_get_active_iter(GTK_COMBO_BOX(colorComboBox), &iter);
733       klass = G_OBJECT_GET_CLASS(colorComboBox);
734       gtk_tree_model_get(GTK_TREE_MODEL(VISU_UI_COLOR_COMBOBOX_CLASS(klass)->listStoredColors), &iter,
735 			   COLUMN_COLOR_POINTER_TO, &color,
736 			   -1);
737       if (color != colorComboBox->previouslySelectedColor)
738 	{
739 	  colorComboBox->previouslySelectedColor = color;
740 	  /* Set the ranges. */
741 	  if (colorComboBox->withRanges)
742 	    for (i = 0; i <4; i++)
743 	      {
744 		g_signal_handler_block(G_OBJECT(colorComboBox->rgbRanges[i]),
745 				       colorComboBox->rgbSignals[i]);
746 		gtk_range_set_value(GTK_RANGE(colorComboBox->rgbRanges[i]),
747 				    (gdouble)color->rgba[i]);
748 		g_signal_handler_unblock(G_OBJECT(colorComboBox->rgbRanges[i]),
749 					 colorComboBox->rgbSignals[i]);
750 	      }
751 	  DBG_fprintf(stderr, "Gtk VisuUiColorCombobox: emitting 'color-selected' signal.\n");
752           g_object_notify_by_pspec(G_OBJECT(colorComboBox), properties[COLOR_PROP]);
753 	  g_signal_emit(G_OBJECT(colorComboBox),
754 			signals[COLOR_SELECTED_SIGNAL], 0, (gpointer)color, NULL);
755 	}
756       else
757 	DBG_fprintf(stderr, "Gtk VisuUiColorCombobox: aborting 'color-selected' signal.\n");
758       return;
759     }
760   if (colorComboBox->previouslySelectedColor)
761     {
762       gdkcolor.red = colorComboBox->previouslySelectedColor->rgba[0];
763       gdkcolor.green = colorComboBox->previouslySelectedColor->rgba[1];
764       gdkcolor.blue = colorComboBox->previouslySelectedColor->rgba[2];
765       gdkcolor.alpha = colorComboBox->previouslySelectedColor->rgba[3];
766     }
767   else
768     {
769       gdkcolor.red = 0.;
770       gdkcolor.green = 0.;
771       gdkcolor.blue = 0.;
772       gdkcolor.alpha = 1.;
773     }
774 
775   /* Create the selection. */
776   selection = gtk_color_chooser_dialog_new(_("Select a color"), NULL);
777   gtk_color_chooser_set_use_alpha(GTK_COLOR_CHOOSER(selection),
778                                   colorComboBox->hasAlphaChannel);
779 /*   createColorSelectionCustomList(GTK_COLOR_SELECTION_DIALOG(selection)); */
780 
781   /* Initialise its values. */
782   gtk_color_chooser_set_rgba(GTK_COLOR_CHOOSER(selection), &gdkcolor);
783 
784   /* Run the dialog window. */
785   code = gtk_dialog_run(GTK_DIALOG(selection));
786   if (code == GTK_RESPONSE_OK || code == GTK_RESPONSE_ACCEPT)
787     {
788       gtk_color_chooser_get_rgba(GTK_COLOR_CHOOSER(selection), &gdkcolor);
789       rgba[0] = (float)gdkcolor.red;
790       rgba[1] = (float)gdkcolor.green;
791       rgba[2] = (float)gdkcolor.blue;
792       rgba[3] = (float)gdkcolor.alpha;
793 
794       klass = G_OBJECT_GET_CLASS(colorComboBox);
795       g_signal_handler_block(tool_color_getStorage(), VISU_UI_COLOR_COMBOBOX_CLASS(klass)->colorAddedSignalId);
796       color = tool_color_addFloatRGBA(rgba, &selected);
797       g_signal_handler_unblock(tool_color_getStorage(), VISU_UI_COLOR_COMBOBOX_CLASS(klass)->colorAddedSignalId);
798       addColorToModel(&iter, VISU_UI_COLOR_COMBOBOX_CLASS(klass), color);
799       gtk_combo_box_set_active_iter(GTK_COMBO_BOX(colorComboBox), &iter);
800     }
801   else
802     {
803       /* Return the combobox to the previously selected color. */
804       if (colorComboBox->previouslySelectedColor)
805 	visu_ui_color_combobox_setSelection(colorComboBox,
806                                             colorComboBox->previouslySelectedColor);
807       else
808 	gtk_combo_box_set_active(GTK_COMBO_BOX(colorComboBox), -1);
809     }
810   gtk_widget_destroy(selection);
811 }
812 
visu_ui_color_combobox_materialChanged(GtkRange * rg,gpointer data)813 static void visu_ui_color_combobox_materialChanged(GtkRange *rg, gpointer data)
814 {
815   int i;
816   VisuUiColorCombobox *colorComboBox;
817 
818   g_return_if_fail(VISU_IS_UI_COLOR_COMBOBOX(data));
819 
820   g_object_notify_by_pspec(G_OBJECT(data), properties[MATERIAL_PROP]);
821 
822   colorComboBox = VISU_UI_COLOR_COMBOBOX(data);
823   DBG_fprintf(stderr, "Gtk VisuUiColorCombobox: internal material range changed signal.\n");
824 
825   DBG_fprintf(stderr, "Gtk VisuUiColorCombobox: emitting 'material-value-changed' signal.\n");
826   for (i = 0; i < TOOL_MATERIAL_N_VALUES; i++)
827     if (GTK_WIDGET(rg) == colorComboBox->materialRanges[i])
828       {
829 	g_signal_emit(G_OBJECT(colorComboBox),
830 		      signals[MATERIAL_VALUE_CHANGED_SIGNAL], 0,
831 		      (ToolMaterialIds)i, NULL);
832 	return;
833       }
834   g_warning("Internal error, unrecognized range.");
835 }
visu_ui_color_combobox_rgbChanged(GtkRange * rg,gpointer data)836 static void visu_ui_color_combobox_rgbChanged(GtkRange *rg, gpointer data)
837 {
838   int i;
839   VisuUiColorCombobox *colorComboBox;
840   float *rgba;
841 
842   g_return_if_fail(VISU_IS_UI_COLOR_COMBOBOX(data));
843 
844   colorComboBox = VISU_UI_COLOR_COMBOBOX(data);
845   DBG_fprintf(stderr, "Gtk VisuUiColorCombobox: internal color range changed signal.\n");
846   rgba = visu_ui_color_combobox_getRangeColor(colorComboBox);
847   tool_color_getByValues(&i, rgba[0], rgba[1], rgba[2], rgba[3]);
848   if (i < 0)
849     {
850       gtk_combo_box_set_active(GTK_COMBO_BOX(colorComboBox), -1);
851       g_object_notify_by_pspec(G_OBJECT(data), properties[COLOR_PROP]);
852     }
853   else
854     gtk_combo_box_set_active(GTK_COMBO_BOX(colorComboBox), i + 1);
855   g_free(rgba);
856 
857   DBG_fprintf(stderr, "Gtk VisuUiColorCombobox: emitting 'color-value-changed' signal.\n");
858   for (i = 0; i < 4; i++)
859     if (GTK_WIDGET(rg) == colorComboBox->rgbRanges[i])
860       {
861 	g_signal_emit(G_OBJECT(colorComboBox),
862 		      signals[COLOR_VALUE_CHANGED_SIGNAL], 0,
863 		      (ToolMaterialIds)i, NULL);
864 	return;
865       }
866   g_warning("Internal error, unrecognized range.");
867 }
visu_ui_color_combobox_addButtonClicked(GtkButton * button _U_,gpointer data)868 static void visu_ui_color_combobox_addButtonClicked(GtkButton *button _U_, gpointer data)
869 {
870   GtkTreeIter iter;
871   GObjectClass *klass;
872   ToolColor *color;
873   VisuUiColorCombobox *colorComboBox;
874   float *rgba;
875   int selected;
876 
877   g_return_if_fail(VISU_IS_UI_COLOR_COMBOBOX(data));
878   colorComboBox = VISU_UI_COLOR_COMBOBOX(data);
879 
880   DBG_fprintf(stderr, "Gtk VisuUiColorCombobox: adding a new color from ranges.\n");
881 
882   rgba = visu_ui_color_combobox_getRangeColor(colorComboBox);
883   klass = G_OBJECT_GET_CLASS(colorComboBox);
884   g_signal_handler_block(tool_color_getStorage(), VISU_UI_COLOR_COMBOBOX_CLASS(klass)->colorAddedSignalId);
885   color = tool_color_addFloatRGBA(rgba, &selected);
886   g_signal_handler_unblock(tool_color_getStorage(), VISU_UI_COLOR_COMBOBOX_CLASS(klass)->colorAddedSignalId);
887   addColorToModel(&iter, VISU_UI_COLOR_COMBOBOX_CLASS(klass), color);
888   gtk_combo_box_set_active_iter(GTK_COMBO_BOX(colorComboBox), &iter);
889   g_free(rgba);
890 }
891 
addColorToModel(GtkTreeIter * iter,VisuUiColorComboboxClass * klass,ToolColor * color)892 static void addColorToModel(GtkTreeIter *iter, VisuUiColorComboboxClass* klass,
893 			    ToolColor* color)
894 {
895   char str[20], strAlpha[20];
896   GdkPixbuf *pixbufColorBox;
897   GdkPixbuf *pixbufColorAlphaBox;
898 
899   if (!color || !klass)
900     return;
901   sprintf(strAlpha, "(#%02x%02x%02x%02x)", (int)(color->rgba[0] * 255.),
902 	  (int)(color->rgba[1] * 255.),
903 	  (int)(color->rgba[2] * 255.),
904 	  (int)(color->rgba[3] * 255.));
905   sprintf(str, "(#%02x%02x%02x)", (int)(color->rgba[0] * 255.),
906 	  (int)(color->rgba[1] * 255.),
907 	  (int)(color->rgba[2] * 255.));
908   pixbufColorAlphaBox = tool_color_get_stamp(color, TRUE);
909   pixbufColorBox = tool_color_get_stamp(color, FALSE);
910   gtk_list_store_append(klass->listStoredColors, iter);
911   gtk_list_store_set(klass->listStoredColors, iter,
912 		     COLUMN_COLOR_PIXBUF_ALPHA, pixbufColorAlphaBox,
913 		     COLUMN_COLOR_PIXBUF      , pixbufColorBox,
914 		     COLUMN_COLOR_LABEL_ALPHA , strAlpha,
915 		     COLUMN_COLOR_LABEL       , str,
916 		     COLUMN_COLOR_POINTER_TO  , (gpointer)color,
917 		     -1);
918   DBG_fprintf(stderr, "Gtk VisuUiColorCombobox: appending a new color '%s'.\n",
919               strAlpha);
920   g_object_unref(pixbufColorAlphaBox);
921   g_object_unref(pixbufColorBox);
922 }
923 /**
924  * visu_ui_color_combobox_setSelection:
925  * @colorComboBox: a #VisuUiColorCombobox widget ;
926  * @color: a #ToolColor object.
927  *
928  * Use this method to set the ComboBox on the given color. This emits a 'color-channel'
929  * signal if the color is changed, which means, a previous color has been modified,
930  * or a new color is selected.
931  *
932  * Returns: TRUE if the @color already exists in the model.
933  *
934  * Since: 3.1
935  */
visu_ui_color_combobox_setSelection(VisuUiColorCombobox * colorComboBox,ToolColor * color)936 gboolean visu_ui_color_combobox_setSelection(VisuUiColorCombobox* colorComboBox, ToolColor *color)
937 {
938   GtkTreeIter iter;
939   gboolean validIter;
940   GObjectClass *klass;
941   GtkListStore *model;
942   ToolColor *tmpColor;
943 
944   g_return_val_if_fail(color && VISU_IS_UI_COLOR_COMBOBOX(colorComboBox), FALSE);
945 
946   DBG_fprintf(stderr, "Gtk VisuUiColorCombobox: select a new color %p.\n", (gpointer)color);
947   klass = G_OBJECT_GET_CLASS(colorComboBox);
948   model = GTK_LIST_STORE(VISU_UI_COLOR_COMBOBOX_CLASS(klass)->listStoredColors);
949   validIter = gtk_tree_model_get_iter_first(GTK_TREE_MODEL(model), &iter);
950   while (validIter)
951     {
952       gtk_tree_model_get(GTK_TREE_MODEL(model), &iter,
953 			 COLUMN_COLOR_POINTER_TO, &tmpColor,
954 			 -1);
955       if (tmpColor && tool_color_equal(tmpColor, color))
956 	{
957 	  gtk_combo_box_set_active_iter(GTK_COMBO_BOX(colorComboBox), &iter);
958 	  return TRUE;
959 	}
960       validIter = gtk_tree_model_iter_next(GTK_TREE_MODEL(model), &iter);
961     }
962   return FALSE;
963 }
964 /**
965  * visu_ui_color_combobox_setRangeColor:
966  * @colorComboBox: a #VisuUiColorCombobox widget ;
967  * @rgba: 4 floating point values ;
968  * @raiseSignal: if TRUE a material-value-changed can be raised.
969  *
970  * Change the values for the ranges that control the color. If the color exists
971  * in the list, it is also selected.
972  * This is possible only if the @colorComboBox has been created with
973  * visu_ui_color_combobox_newWithRanges().
974  *
975  * Since: 3.3
976  */
visu_ui_color_combobox_setRangeColor(VisuUiColorCombobox * colorComboBox,const float rgba[4],gboolean raiseSignal)977 void visu_ui_color_combobox_setRangeColor(VisuUiColorCombobox *colorComboBox,
978                                           const float rgba[4],
979                                           gboolean raiseSignal)
980 {
981   int pos, i;
982   ToolColor *color;
983 
984   color = tool_color_getByValues(&pos, rgba[0], rgba[1], rgba[2], rgba[3]);
985   if (!color)
986     {
987       gtk_combo_box_set_active(GTK_COMBO_BOX(colorComboBox), -1);
988       if (raiseSignal)
989 	for (i = 0; i < 4; i++)
990 	  gtk_range_set_value(GTK_RANGE(colorComboBox->rgbRanges[i]),
991 			      (gdouble)rgba[i]);
992       else
993 	for (i = 0; i < 4; i++)
994 	  {
995 	    g_signal_handler_block(G_OBJECT(colorComboBox->rgbRanges[i]),
996 				   colorComboBox->rgbSignals[i]);
997 	    gtk_range_set_value(GTK_RANGE(colorComboBox->rgbRanges[i]),
998 				(gdouble)rgba[i]);
999 	    g_signal_handler_unblock(G_OBJECT(colorComboBox->rgbRanges[i]),
1000 				     colorComboBox->rgbSignals[i]);
1001 	  }
1002     }
1003   else
1004     {
1005       if (raiseSignal)
1006 	gtk_combo_box_set_active(GTK_COMBO_BOX(colorComboBox), pos + 1);
1007       else
1008 	{
1009 	  colorComboBox->previouslySelectedColor = color;
1010 	  g_signal_handler_block(G_OBJECT(colorComboBox),
1011 				 colorComboBox->comboSignal);
1012 	  gtk_combo_box_set_active(GTK_COMBO_BOX(colorComboBox), pos + 1);
1013 	  g_signal_handler_unblock(G_OBJECT(colorComboBox),
1014 				   colorComboBox->comboSignal);
1015 	  for (i = 0; i < 4; i++)
1016 	    {
1017 	      g_signal_handler_block(G_OBJECT(colorComboBox->rgbRanges[i]),
1018 				     colorComboBox->rgbSignals[i]);
1019 	      gtk_range_set_value(GTK_RANGE(colorComboBox->rgbRanges[i]),
1020 				  (gdouble)rgba[i]);
1021 	      g_signal_handler_unblock(G_OBJECT(colorComboBox->rgbRanges[i]),
1022 				       colorComboBox->rgbSignals[i]);
1023 	    }
1024 	}
1025     }
1026 }
1027 
1028 
onNewColorAvailable(ToolPool * pool _U_,ToolColor * newColor,gpointer data)1029 static void onNewColorAvailable(ToolPool *pool _U_, ToolColor* newColor, gpointer data)
1030 {
1031   VisuUiColorComboboxClass *klass;
1032   GtkTreeIter iter;
1033 
1034   g_return_if_fail(data);
1035 
1036   DBG_fprintf(stderr, "Gtk VisuUiColorComboboxClass: catch the 'new-element' signal.\n");
1037   klass = VISU_UI_COLOR_COMBOBOX_CLASS(data);
1038   addColorToModel(&iter, klass, newColor);
1039 }
1040 /**
1041  * visu_ui_color_combobox_getSelection:
1042  * @colorComboBox: a #VisuUiColorCombobox widget.
1043  *
1044  * The user can access to the selected #ToolColor object using this method.
1045  *
1046  * Returns: (transfer none): a pointer to the selected #ToolColor
1047  * object (or NULL). This object is read-only.
1048  *
1049  * Since: 3.1
1050  */
visu_ui_color_combobox_getSelection(VisuUiColorCombobox * colorComboBox)1051 const ToolColor* visu_ui_color_combobox_getSelection(VisuUiColorCombobox *colorComboBox)
1052 {
1053   gboolean validIter;
1054   GtkTreeIter iter;
1055   ToolColor *color;
1056   GObjectClass *klass;
1057 
1058   g_return_val_if_fail(VISU_IS_UI_COLOR_COMBOBOX(colorComboBox), (ToolColor*)0);
1059 
1060   validIter = gtk_combo_box_get_active_iter(GTK_COMBO_BOX(colorComboBox), &iter);
1061   if (!validIter)
1062     return (const ToolColor*)0;
1063 
1064   color = (ToolColor*)0;
1065   klass = G_OBJECT_GET_CLASS(colorComboBox);
1066   gtk_tree_model_get(GTK_TREE_MODEL(VISU_UI_COLOR_COMBOBOX_CLASS(klass)->listStoredColors), &iter,
1067 		     COLUMN_COLOR_POINTER_TO, &color,
1068 		     -1);
1069   return color;
1070 }
1071 /**
1072  * visu_ui_color_combobox_getPixbufFromColor:
1073  * @colorComboBox: a #VisuUiColorCombobox widget ;
1074  * @color: a #ToolColor object.
1075  *
1076  * The @colorComboBox has little pixbufs to represent the color. User methods can
1077  * use these pixbufs but should considered them read-only.
1078  *
1079  * Returns: (transfer full): a pixbuf pointer corresponding to the
1080  * little image shown on the @colorComboBox.
1081  *
1082  * Since: 3.1
1083  */
visu_ui_color_combobox_getPixbufFromColor(VisuUiColorCombobox * colorComboBox,ToolColor * color)1084 GdkPixbuf* visu_ui_color_combobox_getPixbufFromColor(VisuUiColorCombobox *colorComboBox, ToolColor *color)
1085 {
1086   GtkTreeIter iter;
1087   gboolean validIter;
1088   GdkPixbuf *pixbuf;
1089   ToolColor *cl;
1090   GtkListStore *model;
1091 
1092   g_return_val_if_fail(colorComboBox && color, (GdkPixbuf*)0);
1093 
1094   model = VISU_UI_COLOR_COMBOBOX_CLASS(G_OBJECT_GET_CLASS(colorComboBox))->listStoredColors;
1095   validIter = gtk_tree_model_get_iter_first(GTK_TREE_MODEL(model), &iter);
1096   while (validIter)
1097     {
1098       pixbuf = (GdkPixbuf*)0;
1099       cl = (ToolColor*)0;
1100       if (colorComboBox->hasAlphaChannel)
1101 	gtk_tree_model_get(GTK_TREE_MODEL(model), &iter,
1102 			   COLUMN_COLOR_PIXBUF_ALPHA, &pixbuf,
1103 			   COLUMN_COLOR_POINTER_TO, &cl,
1104 			   -1);
1105       else
1106 	gtk_tree_model_get(GTK_TREE_MODEL(model), &iter,
1107 			   COLUMN_COLOR_PIXBUF, &pixbuf,
1108 			   COLUMN_COLOR_POINTER_TO, &cl,
1109 			   -1);
1110       if (cl && tool_color_equal(color, cl))
1111 	return pixbuf;
1112       if (pixbuf)
1113         g_object_unref(pixbuf);
1114       validIter = gtk_tree_model_iter_next(GTK_TREE_MODEL(model), &iter);
1115     }
1116   return (GdkPixbuf*)0;
1117 }
1118 /**
1119  * visu_ui_color_combobox_setRangeMaterial:
1120  * @colorComboBox: a #VisuUiColorCombobox widget ;
1121  * @material: TOOL_MATERIAL_N_VALUES (see #ToolMaterialIds) floating point values ;
1122  * @raiseSignal: if TRUE a material-value-changed can be raised.
1123  *
1124  * Change the values for the ranges that control the light (emission, diffuse...).
1125  * This is possible only if the @colorComboBox has been created with
1126  * visu_ui_color_combobox_newWithRanges().
1127  *
1128  * Since: 3.3
1129  */
visu_ui_color_combobox_setRangeMaterial(VisuUiColorCombobox * colorComboBox,const float material[TOOL_MATERIAL_N_VALUES],gboolean raiseSignal)1130 void visu_ui_color_combobox_setRangeMaterial(VisuUiColorCombobox *colorComboBox,
1131                                              const float material[TOOL_MATERIAL_N_VALUES],
1132                                              gboolean raiseSignal)
1133 {
1134   int i;
1135 
1136   g_return_if_fail(VISU_IS_UI_COLOR_COMBOBOX(colorComboBox));
1137   g_return_if_fail(colorComboBox->withRanges);
1138 
1139   if (raiseSignal)
1140     for (i = 0; i < TOOL_MATERIAL_N_VALUES; i++)
1141       gtk_range_set_value(GTK_RANGE(colorComboBox->materialRanges[i]),
1142 			  (gdouble)material[i]);
1143   else
1144     for (i = 0; i < TOOL_MATERIAL_N_VALUES; i++)
1145       {
1146 	g_signal_handler_block(G_OBJECT(colorComboBox->materialRanges[i]),
1147 			       colorComboBox->materialSignals[i]);
1148 	gtk_range_set_value(GTK_RANGE(colorComboBox->materialRanges[i]),
1149 			    (gdouble)material[i]);
1150 	g_signal_handler_unblock(G_OBJECT(colorComboBox->materialRanges[i]),
1151 				 colorComboBox->materialSignals[i]);
1152       }
1153 }
1154 /**
1155  * visu_ui_color_combobox_getRangeMaterial:
1156  * @colorComboBox: a #VisuUiColorCombobox widget.
1157  *
1158  * If the @colorComboBox uses ranges (see visu_ui_color_combobox_newWithRanges()), this method
1159  * is used to get the values from the material ranges.
1160  *
1161  * Returns: (array fixed-size=5) (transfer full): a newly created array of size
1162  * TOOL_MATERIAL_N_VALUES (see #ToolMaterialIds). Use g_free() to delete it.
1163  *
1164  * Since: 3.3
1165  */
visu_ui_color_combobox_getRangeMaterial(VisuUiColorCombobox * colorComboBox)1166 float* visu_ui_color_combobox_getRangeMaterial(VisuUiColorCombobox *colorComboBox)
1167 {
1168   int i;
1169   float *values;
1170 
1171   g_return_val_if_fail(VISU_IS_UI_COLOR_COMBOBOX(colorComboBox), (float*)0);
1172   g_return_val_if_fail(colorComboBox->withRanges, (float*)0);
1173 
1174   values = g_malloc(sizeof(float) * TOOL_MATERIAL_N_VALUES);
1175   for (i = 0; i < TOOL_MATERIAL_N_VALUES; i++)
1176     values[i] = (float)gtk_range_get_value(GTK_RANGE(colorComboBox->materialRanges[i]));
1177 
1178   return values;
1179 }
1180 /**
1181  * visu_ui_color_combobox_getRangeColor:
1182  * @colorComboBox: a #VisuUiColorCombobox widget.
1183  *
1184  * If the @colorComboBox uses ranges (see visu_ui_color_combobox_newWithRanges()), this method
1185  * is used to get the values from the color ranges.
1186  *
1187  * Returns: (array fixed-size=4) (transfer full): a newly created
1188  * array of size 4. Use g_free() to delete it.
1189  *
1190  * Since: 3.2
1191  */
visu_ui_color_combobox_getRangeColor(VisuUiColorCombobox * colorComboBox)1192 float* visu_ui_color_combobox_getRangeColor(VisuUiColorCombobox *colorComboBox)
1193 {
1194   int i;
1195   float *values;
1196 
1197   g_return_val_if_fail(VISU_IS_UI_COLOR_COMBOBOX(colorComboBox), (float*)0);
1198   g_return_val_if_fail(colorComboBox->withRanges, (float*)0);
1199 
1200   values = g_malloc(sizeof(float) * 4);
1201   for (i = 0; i < 4; i++)
1202     values[i] = (float)gtk_range_get_value(GTK_RANGE(colorComboBox->rgbRanges[i]));
1203 
1204   return values;
1205 }
1206 
1207 
1208 /* Under developpement method, not used at the present time. */
1209 /* void createColorSelectionCustomList(GtkColorSelectionDialog *selection) */
1210 /* { */
1211 /*   GtkWidget *hbox; */
1212 /*   GtkWidget *buttonF, *buttonB, *button; */
1213 /*   GtkWidget *image; */
1214 /*   GtkWidget *table; */
1215 /*   GtkWidget *label; */
1216 /*   GtkWidget *align; */
1217 /*   gboolean validIter; */
1218 /*   GdkPixbuf *pixbuf; */
1219 /*   int i; */
1220 /*   gboolean usedPrevNext; */
1221 /*   #define N_SHOW_COLOR 15 */
1222 /*   GtkTreeIter iter; */
1223 /*   GtkWidget *imageGroup; */
1224 /*   GtkTreeIter *iterStored; */
1225 
1226 /*   hbox = gtk_hbox_new(FALSE, 0); */
1227 /*   gtk_widget_show(hbox); */
1228 /*   gtk_box_pack_start(GTK_BOX(GTK_DIALOG(selection)->vbox), hbox, FALSE, FALSE, 2); */
1229 
1230 /*   label = gtk_label_new(_("Stored colors:")); */
1231 /*   gtk_misc_set_alignment(GTK_MISC(label), 0., 0.5); */
1232 /*   gtk_widget_show(label); */
1233 /*   gtk_box_pack_start(GTK_BOX(hbox), label, TRUE, TRUE, 2); */
1234 
1235 /*   button = gtk_button_new_from_stock(GTK_STOCK_REMOVE); */
1236 /*   gtk_widget_show(button); */
1237 /*   gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 2); */
1238 
1239 /*   usedPrevNext = (gtk_tree_model_iter_n_children(GTK_TREE_MODEL(listStoredColors), NULL) >= N_SHOW_COLOR); */
1240 
1241 /*   hbox = gtk_hbox_new(FALSE, 0); */
1242 /*   gtk_widget_show(hbox); */
1243 /*   gtk_box_pack_start(GTK_BOX(GTK_DIALOG(selection)->vbox), hbox, FALSE, FALSE, 2); */
1244 
1245 /*   if (usedPrevNext) */
1246 /*     { */
1247 /*       buttonB = gtk_button_new (); */
1248 /*       gtk_widget_show(buttonB); */
1249 /*       gtk_box_pack_start(GTK_BOX(hbox), buttonB, FALSE, FALSE, 2); */
1250 /*       image = gtk_image_new_from_stock(GTK_STOCK_GO_BACK, GTK_ICON_SIZE_BUTTON); */
1251 /*       gtk_widget_show (image); */
1252 /*       gtk_container_add(GTK_CONTAINER(buttonB), image); */
1253 /*     } */
1254 
1255 /*   align= gtk_alignment_new(0.5, 0.5, 0., 0.); */
1256 /*   gtk_widget_show(align); */
1257 /*   gtk_box_pack_start(GTK_BOX(hbox), align, FALSE, FALSE, 2); */
1258 /*   table = gtk_table_new(1, 10, FALSE); */
1259 /*   gtk_widget_show(table); */
1260 /*   gtk_container_add(GTK_CONTAINER(align), table); */
1261 
1262 /*   if (usedPrevNext) */
1263 /*     { */
1264 /*       buttonF = gtk_button_new (); */
1265 /*       gtk_widget_show(buttonF); */
1266 /*       gtk_box_pack_start(GTK_BOX(hbox), buttonF, FALSE, FALSE, 2); */
1267 /*       image = gtk_image_new_from_stock(GTK_STOCK_GO_FORWARD, GTK_ICON_SIZE_BUTTON); */
1268 /*       gtk_widget_show (image); */
1269 /*       gtk_container_add(GTK_CONTAINER(buttonF), image); */
1270 /*     } */
1271 
1272   /* Put all the colors. */
1273 /*   imageGroup = (GtkWidget*)0; */
1274 /*   i = 0; */
1275 /*   validIter = gtk_tree_model_get_iter_first(GTK_TREE_MODEL(listStoredColors), &iter); */
1276 /*   while (validIter && i < N_SHOW_COLOR) */
1277 /*     { */
1278 /*       pixbuf = (GdkPixbuf*)0; */
1279 /*       gtk_tree_model_get(GTK_TREE_MODEL(listStoredColors), */
1280 /* 			 &iter, COLUMN_COLOR_PIXBUF_ALPHA, */
1281 /* 			 &pixbuf, -1); */
1282 /*       if (pixbuf) */
1283 /* 	{ */
1284 /* 	  if (!imageGroup) */
1285 /* 	    { */
1286 /* 	      imageGroup = gtk_radio_button_new(NULL); */
1287 /* 	      button = imageGroup; */
1288 /* 	    } */
1289 /* 	  else */
1290 /* 	    button = gtk_radio_button_new_from_widget(GTK_RADIO_BUTTON(imageGroup)); */
1291 /* 	  gtk_widget_show(button); */
1292 /* 	  gtk_table_attach(GTK_TABLE(table), button, i, i + 1, 0, 1, GTK_FILL, GTK_FILL, 2, 2); */
1293 /* 	  image = gtk_image_new_from_pixbuf(pixbuf); */
1294 /* 	  gtk_widget_show(image); */
1295 /* 	  gtk_container_add(GTK_CONTAINER(button), image); */
1296 
1297 /* 	  iterStored = gtk_tree_iter_copy(&iter); */
1298 /* 	  i += 1; */
1299 /* 	} */
1300 /*       validIter = gtk_tree_model_iter_next(GTK_TREE_MODEL(listStoredColors), &iter); */
1301 /*     } */
1302 /* } */
1303