1 /*   EXTRAITS DE LA LICENCE
2 	Copyright CEA, contributeurs : Damien
3 	CALISTE, laboratoire L_Sim, (2016)
4 
5 	Adresse mèl :
6 	CALISTE, damien P caliste AT cea P fr.
7 
8 	Ce logiciel est un programme informatique servant à visualiser des
9 	structures atomiques dans un rendu pseudo-3D.
10 
11 	Ce logiciel est régi par la licence CeCILL soumise au droit français et
12 	respectant les principes de diffusion des logiciels libres. Vous pouvez
13 	utiliser, modifier et/ou redistribuer ce programme sous les conditions
14 	de la licence CeCILL telle que diffusée par le CEA, le CNRS et l'INRIA
15 	sur le site "http://www.cecill.info".
16 
17 	Le fait que vous puissiez accéder à cet en-tête signifie que vous avez
18 	pris connaissance de la licence CeCILL, et que vous en avez accepté les
19 	termes (cf. le fichier Documentation/licence.fr.txt fourni avec ce logiciel).
20 */
21 
22 /*   LICENCE SUM UP
23 	Copyright CEA, contributors : Damien
24 	CALISTE, laboratoire L_Sim, (2016)
25 
26 	E-mail address:
27 	CALISTE, damien P caliste AT cea P fr.
28 
29 	This software is a computer program whose purpose is to visualize atomic
30 	configurations in 3D.
31 
32 	This software is governed by the CeCILL  license under French law and
33 	abiding by the rules of distribution of free software.  You can  use,
34 	modify and/ or redistribute the software under the terms of the CeCILL
35 	license as circulated by CEA, CNRS and INRIA at the following URL
36 	"http://www.cecill.info".
37 
38 	The fact that you are presently reading this means that you have had
39 	knowledge of the CeCILL license and that you accept its terms. You can
40 	find a copy of this licence shipped with this software at Documentation/licence.en.txt.
41 */
42 
43 #include "gtk_dataChooser.h"
44 
45 #include <support.h>
46 #include <visu_gtk.h>
47 #include <visu_dataatomic.h>
48 #include <visu_dataspin.h>
49 #include <visu_configFile.h>
50 #include <openGLFunctions/view.h>
51 #include <visu_extset.h>
52 #include <extensions/nodes.h>
53 #include <extensions/box.h>
54 
55 /* Parameters. */
56 #define FLAG_PARAMETER_PREVIEW "main_usePreview"
57 #define DESC_PARAMETER_PREVIEW "Automatically compute preview in filechooser ; boolean"
58 static gboolean usePreview;
59 
60 /**
61  * SECTION:gtk_dataChooser
62  * @short_description: A customed file chooser, allowing to slect one
63  * or several files a create a #VisuDataLoadable object accordingly.
64  *
65  * <para>This is a standard file chooser with additional combo box to
66  * select which kind of #VisuDataLoadable we want to select, simple
67  * atomic or spin files.</para>
68  */
69 
70 
71 /* enum { */
72 /*   PROP_0, */
73 /*   N_PROPS */
74 /* }; */
75 /* static GParamSpec *_properties[N_PROPS]; */
76 
77 /**
78  * VisuUiDataChooserPrivate:
79  *
80  * Private data.
81  */
82 struct _VisuUiDataChooserPrivate
83 {
84   gboolean dispose_has_run;
85 
86   GtkWidget *comboMethod, *boxMethod;
87 
88   GtkWidget *checkPreview;
89   GtkWidget *image;
90   GtkWidget *boxDescr;
91   guint worker;
92 
93   GtkWidget *checkAtomic, *checkSpin;
94   GtkWidget *labelPosition, *labelSpin;
95 
96   gchar *atomicFile, *spinFile;
97   VisuDataLoader *atomicFormat, *spinFormat;
98 };
99 
100 static void visu_ui_data_chooser_dispose(GObject* obj);
101 
102 static void _setMethod(VisuUiDataChooser *this);
103 static void _updatePreview(VisuUiDataChooser *this);
104 static gboolean _setFile(VisuUiDataChooser *this);
105 static void exportParameters(GString *data, VisuData *dataObj);
106 
107 /* Pointset interface. */
G_DEFINE_TYPE_WITH_CODE(VisuUiDataChooser,visu_ui_data_chooser,GTK_TYPE_FILE_CHOOSER_DIALOG,G_ADD_PRIVATE (VisuUiDataChooser))108 G_DEFINE_TYPE_WITH_CODE(VisuUiDataChooser, visu_ui_data_chooser, GTK_TYPE_FILE_CHOOSER_DIALOG,
109                         G_ADD_PRIVATE(VisuUiDataChooser))
110 
111 static void visu_ui_data_chooser_class_init(VisuUiDataChooserClass *klass)
112 {
113   VisuConfigFileEntry *entry;
114 
115   G_OBJECT_CLASS(klass)->dispose = visu_ui_data_chooser_dispose;
116 
117   /* Set private variables. */
118   usePreview = TRUE;
119   entry = visu_config_file_addBooleanEntry(VISU_CONFIG_FILE_PARAMETER,
120                                            FLAG_PARAMETER_PREVIEW,
121                                            DESC_PARAMETER_PREVIEW,
122                                            &usePreview, FALSE);
123   visu_config_file_entry_setVersion(entry, 3.4f);
124   visu_config_file_addExportFunction(VISU_CONFIG_FILE_PARAMETER,
125                                      exportParameters);
126 }
visu_ui_data_chooser_init(VisuUiDataChooser * obj)127 static void visu_ui_data_chooser_init(VisuUiDataChooser *obj)
128 {
129   obj->priv = visu_ui_data_chooser_get_instance_private(obj);
130   obj->priv->dispose_has_run = FALSE;
131   obj->priv->atomicFile = (gchar*)0;
132   obj->priv->spinFile = (gchar*)0;
133   obj->priv->atomicFormat = (VisuDataLoader*)0;
134   obj->priv->spinFormat = (VisuDataLoader*)0;
135 }
visu_ui_data_chooser_dispose(GObject * obj)136 static void visu_ui_data_chooser_dispose(GObject* obj)
137 {
138   VisuUiDataChooser *this;
139 
140   this = VISU_UI_DATA_CHOOSER(obj);
141   if (this->priv->dispose_has_run)
142     return;
143   this->priv->dispose_has_run = TRUE;
144 
145   g_free(this->priv->atomicFile);
146   g_free(this->priv->spinFile);
147   if (this->priv->worker)
148     g_source_remove(this->priv->worker);
149 
150   G_OBJECT_CLASS(visu_ui_data_chooser_parent_class)->dispose(obj);
151 }
152 
153 /**
154  * visu_ui_data_chooser_new:
155  * @parent: (allow-none): a #GtkWindow parent.
156  *
157  * Creates a dialog allowing to select files to load.
158  *
159  * Since: 3.8
160  *
161  * Returns: (transfer full): a newly created #VisuUiDataChooser object.
162  **/
visu_ui_data_chooser_new(GtkWindow * parent)163 GtkWidget* visu_ui_data_chooser_new(GtkWindow *parent)
164 {
165   VisuUiDataChooser *this;
166   GtkWidget *vbox, *label;
167   GtkWidget *hbox;
168   GtkWidget *frame;
169 
170 #if GTK_MAJOR_VERSION == 2 && GTK_MINOR_VERSION < 12
171   GtkTooltips *tooltips;
172 
173   tooltips = gtk_tooltips_new ();
174 #endif
175 
176   this = g_object_new(VISU_TYPE_UI_DATA_CHOOSER, "title", _("Load session"), NULL);
177   gtk_widget_set_name(GTK_WIDGET(this), "filesel");
178   gtk_window_set_transient_for(GTK_WINDOW(this), parent);
179   gtk_window_set_position(GTK_WINDOW(this), GTK_WIN_POS_CENTER_ON_PARENT);
180   gtk_window_set_modal(GTK_WINDOW(this), TRUE);
181   gtk_dialog_add_buttons(GTK_DIALOG(this),
182                          TOOL_ICON_CANCEL, GTK_RESPONSE_CANCEL,
183                          TOOL_ICON_OPEN, GTK_RESPONSE_OK,
184                          NULL);
185   gtk_file_chooser_set_action(GTK_FILE_CHOOSER(this), GTK_FILE_CHOOSER_ACTION_OPEN);
186 
187   vbox = gtk_dialog_get_content_area(GTK_DIALOG(this));
188 
189   hbox = gtk_hbox_new(FALSE, 0);
190   gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
191   this->priv->boxMethod = gtk_hbox_new(FALSE, 0);
192   gtk_box_pack_start(GTK_BOX(vbox), this->priv->boxMethod, FALSE, FALSE, 0);
193 
194   label = gtk_label_new(_("Rendering method:"));
195   gtk_box_pack_start(GTK_BOX(hbox), label, TRUE, TRUE, 0);
196   gtk_label_set_xalign(GTK_LABEL(label), 0.);
197   this->priv->comboMethod = gtk_combo_box_text_new();
198   gtk_combo_box_text_append(GTK_COMBO_BOX_TEXT(this->priv->comboMethod),
199                             "atomic", _("display node as atoms"));
200   gtk_combo_box_text_append(GTK_COMBO_BOX_TEXT(this->priv->comboMethod),
201                             "spin", _("display node as spins"));
202   g_signal_connect_swapped(this->priv->comboMethod, "changed",
203                            G_CALLBACK(_setMethod), this);
204   gtk_combo_box_set_active(GTK_COMBO_BOX(this->priv->comboMethod), 0);
205   gtk_box_pack_end(GTK_BOX(hbox), this->priv->comboMethod, FALSE, FALSE, 0);
206 
207   /* The preview widget. */
208   vbox = gtk_vbox_new(FALSE, 0);
209   gtk_widget_set_hexpand(vbox, FALSE);
210 
211   this->priv->checkPreview = gtk_check_button_new_with_mnemonic(_("_Preview:"));
212   gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(this->priv->checkPreview),
213                                usePreview);
214   gtk_box_pack_start(GTK_BOX(vbox), this->priv->checkPreview, FALSE, FALSE, 5);
215 
216   frame = gtk_frame_new(NULL);
217   gtk_widget_set_size_request(frame, 150, 150);
218   gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_ETCHED_IN);
219   gtk_widget_set_vexpand(frame, FALSE);
220   gtk_box_pack_start(GTK_BOX(vbox), frame, TRUE, FALSE, 0);
221   this->priv->image = gtk_image_new();
222   gtk_container_add(GTK_CONTAINER(frame), this->priv->image);
223   this->priv->boxDescr = gtk_hbox_new(FALSE, 0);
224   gtk_box_pack_start(GTK_BOX(vbox), this->priv->boxDescr, FALSE, FALSE, 0);
225 
226   gtk_widget_show_all(vbox);
227 
228   gtk_file_chooser_set_preview_widget(GTK_FILE_CHOOSER(this), vbox);
229   gtk_file_chooser_set_use_preview_label(GTK_FILE_CHOOSER(this), FALSE);
230   gtk_file_chooser_set_preview_widget_active(GTK_FILE_CHOOSER(this), TRUE);
231 
232   g_signal_connect(this, "update-preview", G_CALLBACK(_updatePreview), (gpointer)0);
233 
234 /*   /\* The additional widgets. *\/ */
235 
236 /*   /\* Hiding mode button *\/ */
237 /*   hbox = gtk_hbox_new(FALSE, 0); */
238 /*   gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 2); */
239 /*   label = gtk_label_new(LABEL_SPIN_POLICY); */
240 /*   gtk_widget_set_name(label, "label_head_2"); */
241 /*   gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 2); */
242 /*   hiding_mode = createHidingModeRadioWidgets(); */
243 /*   gtk_box_pack_start(GTK_BOX(hbox), hiding_mode, FALSE, FALSE, 2); */
244 
245   gtk_widget_show_all(GTK_WIDGET(this));
246 
247   return GTK_WIDGET(this);
248 }
249 
_getDescr(VisuDataLoadable * previewData)250 static GtkWidget* _getDescr(VisuDataLoadable *previewData)
251 {
252   GtkWidget *table, *wd;
253   const gchar *comment;
254   gchar *text;
255   VisuNodeArrayIter iter;
256 
257   /* We reset the flag of material. */
258   comment = visu_data_getDescription(VISU_DATA(previewData));
259   visu_node_array_iter_new(VISU_NODE_ARRAY(previewData), &iter);
260   table = gtk_grid_new();
261   tool_grid_resize(table, iter.nElements + 1, 2);
262   wd = gtk_label_new(_("<i>Box composition:</i>"));
263   gtk_label_set_use_markup(GTK_LABEL(wd), TRUE);
264   gtk_label_set_xalign(GTK_LABEL(wd), 0.);
265   gtk_widget_set_hexpand(wd, TRUE);
266   gtk_grid_attach(GTK_GRID(table), wd, 0, 0, 2, 1);
267   for (visu_node_array_iterStart(VISU_NODE_ARRAY(previewData), &iter); iter.element;
268        visu_node_array_iterNextElement(VISU_NODE_ARRAY(previewData), &iter, FALSE))
269     {
270       wd = gtk_label_new("");
271       text = g_markup_printf_escaped(_("<span size=\"small\"><b>%s:</b></span>"),
272                                      iter.element->name);
273       gtk_label_set_markup(GTK_LABEL(wd), text);
274       gtk_label_set_xalign(GTK_LABEL(wd), 1.);
275       gtk_widget_set_hexpand(wd, TRUE);
276       g_free(text);
277       gtk_grid_attach(GTK_GRID(table), wd, 0, iter.iElement + 1, 1, 1);
278       wd = gtk_label_new("");
279       if (iter.nStoredNodes > 1)
280         text = g_markup_printf_escaped
281           (_("<span size=\"small\">%d nodes</span>"),
282            iter.nStoredNodes);
283       else if (iter.nStoredNodes == 1)
284         text = g_strdup(_("<span size=\"small\">1 node</span>"));
285       else
286         text = g_strdup_printf("negative node number %d", iter.nStoredNodes);
287       gtk_label_set_markup(GTK_LABEL(wd), text);
288       gtk_label_set_xalign(GTK_LABEL(wd), 0.);
289       gtk_widget_set_hexpand(wd, TRUE);
290       g_free(text);
291       gtk_grid_attach(GTK_GRID(table), wd, 1, iter.iElement + 1, 1, 1);
292     }
293   if (comment && comment[0])
294     {
295       wd = gtk_label_new(_("<i>Description:</i>"));
296       gtk_label_set_use_markup(GTK_LABEL(wd), TRUE);
297       gtk_label_set_xalign(GTK_LABEL(wd), 0.);
298       gtk_widget_set_hexpand(wd, TRUE);
299       gtk_grid_attach(GTK_GRID(table), wd, 0, iter.nElements + 2, 2, 1);
300       wd = gtk_label_new("");
301       text = g_markup_printf_escaped("<span size=\"small\">%s</span>",
302                                      comment);
303       gtk_label_set_markup(GTK_LABEL(wd), text);
304       g_free(text);
305       gtk_label_set_xalign(GTK_LABEL(wd), 0.);
306       gtk_label_set_justify(GTK_LABEL(wd), GTK_JUSTIFY_FILL);
307       gtk_label_set_line_wrap(GTK_LABEL(wd), TRUE);
308       gtk_widget_set_size_request(wd, 150, -1);
309       gtk_widget_set_hexpand(wd, TRUE);
310       gtk_grid_attach(GTK_GRID(table), wd, 0, iter.nElements + 3, 2, 1);
311     }
312   gtk_widget_show_all(table);
313   return table;
314 }
315 
_freeUChar(guchar * pixels,gpointer data _U_)316 static void _freeUChar(guchar *pixels, gpointer data _U_)
317 {
318   g_free(pixels);
319 }
_renderPreview(VisuUiDataChooser * this)320 static gboolean _renderPreview(VisuUiDataChooser *this)
321 {
322   GError *error;
323   gboolean valid;
324   VisuGlView *view;
325   VisuGlExtNodes *nodes;
326   VisuGlExtBox *box;
327   VisuGlExtSet *set;
328   GArray* image;
329   GdkPixbuf *pixbuf;
330   VisuDataLoadable *preview;
331 
332   this->priv->worker = 0;
333 
334   DBG_fprintf(stderr, "Gtk DataChooser: rendering preview.\n");
335   error = (GError*)0;
336   switch (gtk_combo_box_get_active(GTK_COMBO_BOX(this->priv->comboMethod)))
337     {
338     case 0:
339       if (!this->priv->atomicFile)
340         return G_SOURCE_REMOVE;
341       preview = VISU_DATA_LOADABLE(visu_data_atomic_new(this->priv->atomicFile, this->priv->atomicFormat));
342       break;
343     case 1:
344       if (!this->priv->atomicFile || !this->priv->spinFile)
345         return G_SOURCE_REMOVE;
346       preview = VISU_DATA_LOADABLE(visu_data_spin_new(this->priv->atomicFile,
347                                                       this->priv->spinFile,
348                                                       (VisuDataLoader*)0,
349                                                       (VisuDataLoader*)0));
350       break;
351     default:
352       preview = (VisuDataLoadable*)0;
353       break;
354     }
355   valid = visu_data_loadable_load(preview, 0, (GCancellable*)0, &error);
356   if (!valid)
357     {
358       if (preview)
359         g_object_unref(preview);
360       gtk_image_set_from_icon_name(GTK_IMAGE(this->priv->image),
361                                    "dialog-question", GTK_ICON_SIZE_DIALOG);
362       gtk_box_pack_start(GTK_BOX(this->priv->boxDescr),
363                          gtk_label_new(_("Not a V_Sim file")), TRUE, FALSE, 0);
364       gtk_widget_show_all(this->priv->boxDescr);
365 
366       return FALSE;
367     }
368   if (error)
369     {
370       if (preview)
371         g_object_unref(preview);
372       gtk_image_set_from_icon_name(GTK_IMAGE(this->priv->image),
373                                    "dialog-error", GTK_ICON_SIZE_DIALOG);
374       gtk_box_pack_start(GTK_BOX(this->priv->boxDescr),
375                          gtk_label_new(_("This file has errors")), TRUE, FALSE, 0);
376       gtk_widget_show_all(this->priv->boxDescr);
377 
378       return FALSE;
379     }
380 
381   gtk_box_pack_start(GTK_BOX(this->priv->boxDescr),
382                      _getDescr(preview), FALSE, FALSE, 0);
383 
384   view = visu_gl_view_new_withSize((guint)150, (guint)150);
385   g_object_set(G_OBJECT(view), "auto-adjust", TRUE, NULL);
386   visu_boxed_setBox(VISU_BOXED(view), VISU_BOXED(preview));
387   /* Setup extensions for the preview. */
388   set = visu_gl_ext_set_new();
389   nodes = visu_gl_ext_nodes_new();
390   visu_gl_ext_set_add(set, VISU_GL_EXT(nodes));
391   g_object_unref(nodes);
392   visu_node_array_renderer_setNodeArray(VISU_NODE_ARRAY_RENDERER(nodes),
393                                         VISU_NODE_ARRAY(preview));
394   g_object_unref(preview);
395   box = visu_gl_ext_box_new("box preview");
396   visu_gl_ext_set_add(set, VISU_GL_EXT(box));
397   g_object_unref(box);
398   visu_gl_ext_box_setBox(box, visu_boxed_getBox(VISU_BOXED(preview)));
399   visu_gl_ext_set_setGlView(set, view);
400   g_object_unref(view);
401   image = visu_gl_ext_set_getPixmapData(set, 0, 0, FALSE);
402   g_object_unref(set);
403 
404   pixbuf =
405     gdk_pixbuf_new_from_data((guchar*)image->data, GDK_COLORSPACE_RGB,
406                              FALSE, 8, 150, 150, 3 * 150,
407                              (GdkPixbufDestroyNotify)_freeUChar, (gpointer)0);
408   g_array_free(image, FALSE);
409   gtk_image_set_from_pixbuf(GTK_IMAGE(this->priv->image), pixbuf);
410   g_object_unref(pixbuf);
411 
412   return FALSE;
413 }
414 
_updatePreview(VisuUiDataChooser * this)415 static void _updatePreview(VisuUiDataChooser *this)
416 {
417   GList *lst, *child;
418 
419   lst = gtk_container_get_children(GTK_CONTAINER(this->priv->boxDescr));
420   for (child = lst; child; child = g_list_next(child))
421     gtk_widget_destroy(GTK_WIDGET(child->data));
422   g_list_free(lst);
423   gtk_image_clear(GTK_IMAGE(this->priv->image));
424 
425   if (!gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(this->priv->checkPreview)) ||
426       !_setFile(this))
427     return;
428 
429   if (!this->priv->worker)
430     this->priv->worker = g_idle_add((GSourceFunc)_renderPreview, this);
431 }
432 
_createFilter(GtkFileChooser * chooser,GList * list)433 static void _createFilter(GtkFileChooser *chooser, GList *list)
434 {
435   GtkFileFilter *filter, *filterAll;
436   const GList *tmpLst2, *tmpLst;
437   const char *name;
438 
439   GSList *filters, *it;
440 
441   filters = gtk_file_chooser_list_filters(chooser);
442   for (it = filters; it; it = g_slist_next(it))
443     gtk_file_chooser_remove_filter(chooser, GTK_FILE_FILTER(it->data));
444 
445   filters = (GSList*)0;
446   filterAll = gtk_file_filter_new();
447   gtk_file_filter_set_name(filterAll, _("All supported formats"));
448   for (tmpLst = list; tmpLst; tmpLst = g_list_next(tmpLst))
449     {
450       filter = gtk_file_filter_new();
451       name = tool_file_format_getLabel(TOOL_FILE_FORMAT(tmpLst->data));
452       if (name)
453 	gtk_file_filter_set_name(filter, name);
454       else
455 	gtk_file_filter_set_name(filter, _("No description"));
456       for (tmpLst2 = tool_file_format_getFilePatterns(TOOL_FILE_FORMAT(tmpLst->data));
457            tmpLst2; tmpLst2 = g_list_next(tmpLst2))
458 	{
459 	  gtk_file_filter_add_pattern(filter, (gchar*)tmpLst2->data);
460 	  gtk_file_filter_add_pattern(filterAll, (gchar*)tmpLst2->data);
461 	}
462       g_object_set_data(G_OBJECT(filter), "_VisuDataLoader", tmpLst->data);
463       filters = g_slist_append(filters, (gpointer)filter);
464     }
465   filters = g_slist_append(filters, (gpointer)filterAll);
466   filter = gtk_file_filter_new();
467   gtk_file_filter_set_name(filter, _("All files"));
468   gtk_file_filter_add_pattern (filter, "*");
469   filters = g_slist_append(filters, (gpointer)filter);
470 
471   for (it = filters; it; it = g_slist_next(it))
472     gtk_file_chooser_add_filter(chooser, GTK_FILE_FILTER(it->data));
473   gtk_file_chooser_set_filter(chooser, filterAll);
474 
475   g_slist_free(filters);
476 }
477 
_setSpinInput(VisuUiDataChooser * this)478 static void _setSpinInput(VisuUiDataChooser *this)
479 {
480   if (gtk_combo_box_get_active(GTK_COMBO_BOX(this->priv->comboMethod)) != 1)
481     return;
482 
483   if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(this->priv->checkAtomic)))
484     _createFilter(GTK_FILE_CHOOSER(this), visu_data_atomic_class_getLoaders());
485   else if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(this->priv->checkSpin)))
486     _createFilter(GTK_FILE_CHOOSER(this), visu_data_spin_class_getLoaders());
487 }
488 
_setMethod(VisuUiDataChooser * this)489 static void _setMethod(VisuUiDataChooser *this)
490 {
491   GList *lst, *child;
492   GtkWidget *table;
493 
494   g_free(this->priv->atomicFile);
495   this->priv->atomicFile = (gchar*)0;
496   g_free(this->priv->spinFile);
497   this->priv->spinFile = (gchar*)0;
498 
499   lst = gtk_container_get_children(GTK_CONTAINER(this->priv->boxMethod));
500   for (child = lst; child; child = g_list_next(child))
501     gtk_widget_destroy(GTK_WIDGET(child->data));
502 
503   switch (gtk_combo_box_get_active(GTK_COMBO_BOX(this->priv->comboMethod)))
504     {
505     case 0:
506       _createFilter(GTK_FILE_CHOOSER(this), visu_data_atomic_class_getLoaders());
507       break;
508     case 1:
509       /* The table for the two file types selections (spin & position). */
510       table = gtk_grid_new();
511       tool_grid_resize(table, 2, 4);
512       gtk_box_pack_start(GTK_BOX(this->priv->boxMethod), table, TRUE, TRUE, 2);
513 
514       /* Position button. */
515       this->priv->checkAtomic = gtk_radio_button_new_with_label(NULL, _("Positions:"));
516       gtk_grid_attach(GTK_GRID(table), this->priv->checkAtomic, 0, 0, 1, 1);
517       g_signal_connect_swapped(this->priv->checkAtomic, "toggled",
518                                G_CALLBACK(_setSpinInput), this);
519 
520       /* Spin button */
521       this->priv->checkSpin = gtk_radio_button_new_with_label_from_widget
522         (GTK_RADIO_BUTTON(this->priv->checkAtomic), _("Spins:"));
523       gtk_grid_attach(GTK_GRID(table), this->priv->checkSpin, 0, 1, 1, 1);
524       g_signal_connect_swapped(this->priv->checkSpin, "toggled",
525                                G_CALLBACK(_setSpinInput), this);
526 
527       this->priv->labelPosition = gtk_label_new(_("None"));
528       gtk_widget_set_hexpand(this->priv->labelPosition, TRUE);
529       gtk_label_set_xalign(GTK_LABEL(this->priv->labelPosition), 0.);
530       gtk_widget_set_margin_start(this->priv->labelPosition, 10);
531       gtk_grid_attach(GTK_GRID(table), this->priv->labelPosition, 3, 0, 1, 1);
532 
533       this->priv->labelSpin = gtk_label_new(_("None"));
534       gtk_widget_set_hexpand(this->priv->labelSpin, TRUE);
535       gtk_label_set_xalign(GTK_LABEL(this->priv->labelSpin), 0.);
536       gtk_widget_set_margin_start(this->priv->labelSpin, 10);
537       gtk_grid_attach(GTK_GRID(table), this->priv->labelSpin, 3, 1, 1, 1);
538 
539       gtk_widget_show_all(table);
540 
541       _setSpinInput(this);
542       break;
543     default:
544       break;
545     }
546 }
547 
_setFile(VisuUiDataChooser * this)548 static gboolean _setFile(VisuUiDataChooser *this)
549 {
550   gchar *filename;
551   VisuDataLoader *format;
552 
553   filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(this));
554   format = VISU_DATA_LOADER(g_object_get_data(G_OBJECT(gtk_file_chooser_get_filter(GTK_FILE_CHOOSER(this))), "_VisuDataLoader"));
555 
556   switch (gtk_combo_box_get_active(GTK_COMBO_BOX(this->priv->comboMethod)))
557     {
558     case 0:
559       g_free(this->priv->atomicFile);
560       this->priv->atomicFile = filename;
561       this->priv->atomicFormat = format;
562       return TRUE;
563     case 1:
564       if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(this->priv->checkAtomic)))
565         {
566           g_free(this->priv->atomicFile);
567           this->priv->atomicFile = filename;
568           this->priv->atomicFormat = format;
569           if (filename)
570             gtk_label_set_text(GTK_LABEL(this->priv->labelPosition), filename);
571           else
572             gtk_label_set_text(GTK_LABEL(this->priv->labelPosition), _("None"));
573         }
574       else if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(this->priv->checkSpin)))
575         {
576           g_free(this->priv->spinFile);
577           this->priv->spinFile = filename;
578           this->priv->spinFormat = format;
579           if (filename)
580             gtk_label_set_text(GTK_LABEL(this->priv->labelSpin), filename);
581           else
582             gtk_label_set_text(GTK_LABEL(this->priv->labelSpin), _("None"));
583         }
584       return this->priv->atomicFile && this->priv->spinFile;
585     default:
586       break;
587     }
588   return FALSE;
589 }
590 
591 /**
592  * visu_ui_data_chooser_run:
593  * @this: a #VisuUiDataChooser object.
594  *
595  * Runs a file dialog chooser to select a #VisuDataLoadable file.
596  *
597  * Since: 3.8
598  *
599  * Returns: (transfer full): a newly created #VisuDataLoadable object.
600  **/
visu_ui_data_chooser_run(VisuUiDataChooser * this)601 VisuDataLoadable* visu_ui_data_chooser_run(VisuUiDataChooser *this)
602 {
603   gint status;
604 
605   do
606     {
607       status = gtk_dialog_run(GTK_DIALOG(this));
608       if (status != GTK_RESPONSE_OK)
609         return (VisuDataLoadable*)0;
610 
611     } while (!_setFile(this));
612 
613   switch (gtk_combo_box_get_active(GTK_COMBO_BOX(this->priv->comboMethod)))
614     {
615     case 0:
616       return VISU_DATA_LOADABLE(visu_data_atomic_new(this->priv->atomicFile,
617                                                      this->priv->atomicFormat));
618     case 1:
619       return VISU_DATA_LOADABLE(visu_data_spin_new(this->priv->atomicFile,
620                                                    this->priv->spinFile,
621                                                    this->priv->atomicFormat,
622                                                    this->priv->spinFormat));
623     default:
624       break;
625     }
626   return (VisuDataLoadable*)0;
627 }
628 
exportParameters(GString * data,VisuData * dataObj _U_)629 static void exportParameters(GString *data, VisuData *dataObj _U_)
630 {
631   g_string_append_printf(data, "# %s\n", DESC_PARAMETER_PREVIEW);
632   g_string_append_printf(data, "%s[gtk]: %d\n\n", FLAG_PARAMETER_PREVIEW,
633 			 usePreview);
634 }
635