/*   EXTRAITS DE LA LICENCE
	Copyright CEA, contributeurs : Damien
	CALISTE, laboratoire L_Sim, (2016)
  
	Adresse 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 : Damien
	CALISTE, laboratoire L_Sim, (2016)

	E-mail address:
	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_dataChooser.h"

#include <support.h>
#include <visu_gtk.h>
#include <visu_dataatomic.h>
#include <visu_dataspin.h>
#include <visu_configFile.h>
#include <openGLFunctions/view.h>
#include <visu_extset.h>
#include <extensions/nodes.h>
#include <extensions/box.h>

/* Parameters. */
#define FLAG_PARAMETER_PREVIEW "main_usePreview"
#define DESC_PARAMETER_PREVIEW "Automatically compute preview in filechooser ; boolean"
static gboolean usePreview;

/**
 * SECTION:gtk_dataChooser
 * @short_description: A customed file chooser, allowing to slect one
 * or several files a create a #VisuDataLoadable object accordingly.
 *
 * <para>This is a standard file chooser with additional combo box to
 * select which kind of #VisuDataLoadable we want to select, simple
 * atomic or spin files.</para>
 */


/* enum { */
/*   PROP_0, */
/*   N_PROPS */
/* }; */
/* static GParamSpec *_properties[N_PROPS]; */

/**
 * VisuUiDataChooserPrivate:
 *
 * Private data.
 */
struct _VisuUiDataChooserPrivate
{
  gboolean dispose_has_run;

  GtkWidget *comboMethod, *boxMethod;
  
  GtkWidget *checkPreview;
  GtkWidget *image;
  GtkWidget *boxDescr;
  guint worker;

  GtkWidget *checkAtomic, *checkSpin;
  GtkWidget *labelPosition, *labelSpin;

  gchar *atomicFile, *spinFile;
  VisuDataLoader *atomicFormat, *spinFormat;
};

static void visu_ui_data_chooser_dispose(GObject* obj);

static void _setMethod(VisuUiDataChooser *this);
static void _updatePreview(VisuUiDataChooser *this);
static gboolean _setFile(VisuUiDataChooser *this);
static void exportParameters(GString *data, VisuData *dataObj);

/* Pointset interface. */
G_DEFINE_TYPE_WITH_CODE(VisuUiDataChooser, visu_ui_data_chooser, GTK_TYPE_FILE_CHOOSER_DIALOG,
                        G_ADD_PRIVATE(VisuUiDataChooser))

static void visu_ui_data_chooser_class_init(VisuUiDataChooserClass *klass)
{
  VisuConfigFileEntry *entry;

  G_OBJECT_CLASS(klass)->dispose = visu_ui_data_chooser_dispose;

  /* Set private variables. */
  usePreview = TRUE;
  entry = visu_config_file_addBooleanEntry(VISU_CONFIG_FILE_PARAMETER,
                                           FLAG_PARAMETER_PREVIEW,
                                           DESC_PARAMETER_PREVIEW,
                                           &usePreview, FALSE);
  visu_config_file_entry_setVersion(entry, 3.4f);
  visu_config_file_addExportFunction(VISU_CONFIG_FILE_PARAMETER,
                                     exportParameters);
}
static void visu_ui_data_chooser_init(VisuUiDataChooser *obj)
{
  obj->priv = visu_ui_data_chooser_get_instance_private(obj);
  obj->priv->dispose_has_run = FALSE;
  obj->priv->atomicFile = (gchar*)0;
  obj->priv->spinFile = (gchar*)0;
  obj->priv->atomicFormat = (VisuDataLoader*)0;
  obj->priv->spinFormat = (VisuDataLoader*)0;
}
static void visu_ui_data_chooser_dispose(GObject* obj)
{
  VisuUiDataChooser *this;

  this = VISU_UI_DATA_CHOOSER(obj);
  if (this->priv->dispose_has_run)
    return;
  this->priv->dispose_has_run = TRUE;

  g_free(this->priv->atomicFile);
  g_free(this->priv->spinFile);
  if (this->priv->worker)
    g_source_remove(this->priv->worker);

  G_OBJECT_CLASS(visu_ui_data_chooser_parent_class)->dispose(obj);
}

/**
 * visu_ui_data_chooser_new:
 * @parent: (allow-none): a #GtkWindow parent.
 *
 * Creates a dialog allowing to select files to load.
 *
 * Since: 3.8
 *
 * Returns: (transfer full): a newly created #VisuUiDataChooser object.
 **/
GtkWidget* visu_ui_data_chooser_new(GtkWindow *parent)
{
  VisuUiDataChooser *this;
  GtkWidget *vbox, *label;
  GtkWidget *hbox;
  GtkWidget *frame;

#if GTK_MAJOR_VERSION == 2 && GTK_MINOR_VERSION < 12
  GtkTooltips *tooltips;

  tooltips = gtk_tooltips_new ();
#endif

  this = g_object_new(VISU_TYPE_UI_DATA_CHOOSER, "title", _("Load session"), NULL);
  gtk_widget_set_name(GTK_WIDGET(this), "filesel");
  gtk_window_set_transient_for(GTK_WINDOW(this), parent);
  gtk_window_set_position(GTK_WINDOW(this), GTK_WIN_POS_CENTER_ON_PARENT);
  gtk_window_set_modal(GTK_WINDOW(this), TRUE);
  gtk_dialog_add_buttons(GTK_DIALOG(this),
                         TOOL_ICON_CANCEL, GTK_RESPONSE_CANCEL,
                         TOOL_ICON_OPEN, GTK_RESPONSE_OK,
                         NULL);
  gtk_file_chooser_set_action(GTK_FILE_CHOOSER(this), GTK_FILE_CHOOSER_ACTION_OPEN);

  vbox = gtk_dialog_get_content_area(GTK_DIALOG(this));

  hbox = gtk_hbox_new(FALSE, 0);
  gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
  this->priv->boxMethod = gtk_hbox_new(FALSE, 0);
  gtk_box_pack_start(GTK_BOX(vbox), this->priv->boxMethod, FALSE, FALSE, 0);

  label = gtk_label_new(_("Rendering method:"));
  gtk_box_pack_start(GTK_BOX(hbox), label, TRUE, TRUE, 0);
  gtk_label_set_xalign(GTK_LABEL(label), 0.);
  this->priv->comboMethod = gtk_combo_box_text_new();
  gtk_combo_box_text_append(GTK_COMBO_BOX_TEXT(this->priv->comboMethod),
                            "atomic", _("display node as atoms"));
  gtk_combo_box_text_append(GTK_COMBO_BOX_TEXT(this->priv->comboMethod),
                            "spin", _("display node as spins"));
  g_signal_connect_swapped(this->priv->comboMethod, "changed",
                           G_CALLBACK(_setMethod), this);
  gtk_combo_box_set_active(GTK_COMBO_BOX(this->priv->comboMethod), 0);
  gtk_box_pack_end(GTK_BOX(hbox), this->priv->comboMethod, FALSE, FALSE, 0);

  /* The preview widget. */
  vbox = gtk_vbox_new(FALSE, 0);
  gtk_widget_set_hexpand(vbox, FALSE);

  this->priv->checkPreview = gtk_check_button_new_with_mnemonic(_("_Preview:"));
  gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(this->priv->checkPreview),
                               usePreview);
  gtk_box_pack_start(GTK_BOX(vbox), this->priv->checkPreview, FALSE, FALSE, 5);

  frame = gtk_frame_new(NULL);
  gtk_widget_set_size_request(frame, 150, 150);
  gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_ETCHED_IN);
  gtk_widget_set_vexpand(frame, FALSE);
  gtk_box_pack_start(GTK_BOX(vbox), frame, TRUE, FALSE, 0);
  this->priv->image = gtk_image_new();
  gtk_container_add(GTK_CONTAINER(frame), this->priv->image);
  this->priv->boxDescr = gtk_hbox_new(FALSE, 0);
  gtk_box_pack_start(GTK_BOX(vbox), this->priv->boxDescr, FALSE, FALSE, 0);

  gtk_widget_show_all(vbox);
  
  gtk_file_chooser_set_preview_widget(GTK_FILE_CHOOSER(this), vbox);
  gtk_file_chooser_set_use_preview_label(GTK_FILE_CHOOSER(this), FALSE);
  gtk_file_chooser_set_preview_widget_active(GTK_FILE_CHOOSER(this), TRUE);

  g_signal_connect(this, "update-preview", G_CALLBACK(_updatePreview), (gpointer)0);

/*   /\* The additional widgets. *\/ */

/*   /\* Hiding mode button *\/ */
/*   hbox = gtk_hbox_new(FALSE, 0); */
/*   gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 2); */
/*   label = gtk_label_new(LABEL_SPIN_POLICY); */
/*   gtk_widget_set_name(label, "label_head_2"); */
/*   gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 2); */
/*   hiding_mode = createHidingModeRadioWidgets(); */
/*   gtk_box_pack_start(GTK_BOX(hbox), hiding_mode, FALSE, FALSE, 2); */

  gtk_widget_show_all(GTK_WIDGET(this));
  
  return GTK_WIDGET(this);
}

static GtkWidget* _getDescr(VisuDataLoadable *previewData)
{
  GtkWidget *table, *wd;
  const gchar *comment;
  gchar *text;
  VisuNodeArrayIter iter;

  /* We reset the flag of material. */
  comment = visu_data_getDescription(VISU_DATA(previewData));
  visu_node_array_iter_new(VISU_NODE_ARRAY(previewData), &iter);
  table = gtk_grid_new();
  tool_grid_resize(table, iter.nElements + 1, 2);
  wd = gtk_label_new(_("<i>Box composition:</i>"));
  gtk_label_set_use_markup(GTK_LABEL(wd), TRUE);
  gtk_label_set_xalign(GTK_LABEL(wd), 0.);
  gtk_widget_set_hexpand(wd, TRUE);
  gtk_grid_attach(GTK_GRID(table), wd, 0, 0, 2, 1);
  for (visu_node_array_iterStart(VISU_NODE_ARRAY(previewData), &iter); iter.element;
       visu_node_array_iterNextElement(VISU_NODE_ARRAY(previewData), &iter, FALSE))
    {
      wd = gtk_label_new("");
      text = g_markup_printf_escaped(_("<span size=\"small\"><b>%s:</b></span>"),
                                     iter.element->name);
      gtk_label_set_markup(GTK_LABEL(wd), text);
      gtk_label_set_xalign(GTK_LABEL(wd), 1.);
      gtk_widget_set_hexpand(wd, TRUE);
      g_free(text);
      gtk_grid_attach(GTK_GRID(table), wd, 0, iter.iElement + 1, 1, 1);
      wd = gtk_label_new("");
      if (iter.nStoredNodes > 1)
        text = g_markup_printf_escaped
          (_("<span size=\"small\">%d nodes</span>"),
           iter.nStoredNodes);
      else if (iter.nStoredNodes == 1)
        text = g_strdup(_("<span size=\"small\">1 node</span>"));
      else
        text = g_strdup_printf("negative node number %d", iter.nStoredNodes);
      gtk_label_set_markup(GTK_LABEL(wd), text);
      gtk_label_set_xalign(GTK_LABEL(wd), 0.);
      gtk_widget_set_hexpand(wd, TRUE);
      g_free(text);
      gtk_grid_attach(GTK_GRID(table), wd, 1, iter.iElement + 1, 1, 1);
    }
  if (comment && comment[0])
    {
      wd = gtk_label_new(_("<i>Description:</i>"));
      gtk_label_set_use_markup(GTK_LABEL(wd), TRUE);
      gtk_label_set_xalign(GTK_LABEL(wd), 0.);
      gtk_widget_set_hexpand(wd, TRUE);
      gtk_grid_attach(GTK_GRID(table), wd, 0, iter.nElements + 2, 2, 1);
      wd = gtk_label_new("");
      text = g_markup_printf_escaped("<span size=\"small\">%s</span>",
                                     comment);
      gtk_label_set_markup(GTK_LABEL(wd), text);
      g_free(text);
      gtk_label_set_xalign(GTK_LABEL(wd), 0.);
      gtk_label_set_justify(GTK_LABEL(wd), GTK_JUSTIFY_FILL);
      gtk_label_set_line_wrap(GTK_LABEL(wd), TRUE);
      gtk_widget_set_size_request(wd, 150, -1);
      gtk_widget_set_hexpand(wd, TRUE);
      gtk_grid_attach(GTK_GRID(table), wd, 0, iter.nElements + 3, 2, 1);
    }
  gtk_widget_show_all(table);
  return table;
}

static void _freeUChar(guchar *pixels, gpointer data _U_)
{
  g_free(pixels);
}
static gboolean _renderPreview(VisuUiDataChooser *this)
{
  GError *error;
  gboolean valid;
  VisuGlView *view;
  VisuGlExtNodes *nodes;
  VisuGlExtBox *box;
  VisuGlExtSet *set;
  GArray* image;
  GdkPixbuf *pixbuf;
  VisuDataLoadable *preview;

  this->priv->worker = 0;

  DBG_fprintf(stderr, "Gtk DataChooser: rendering preview.\n");
  error = (GError*)0;
  switch (gtk_combo_box_get_active(GTK_COMBO_BOX(this->priv->comboMethod)))
    {
    case 0:
      if (!this->priv->atomicFile)
        return G_SOURCE_REMOVE;
      preview = VISU_DATA_LOADABLE(visu_data_atomic_new(this->priv->atomicFile, this->priv->atomicFormat));
      break;
    case 1:
      if (!this->priv->atomicFile || !this->priv->spinFile)
        return G_SOURCE_REMOVE;
      preview = VISU_DATA_LOADABLE(visu_data_spin_new(this->priv->atomicFile,
                                                      this->priv->spinFile,
                                                      (VisuDataLoader*)0,
                                                      (VisuDataLoader*)0));
      break;
    default:
      preview = (VisuDataLoadable*)0;
      break;
    }
  valid = visu_data_loadable_load(preview, 0, (GCancellable*)0, &error);
  if (!valid)
    {
      if (preview)
        g_object_unref(preview);
      gtk_image_set_from_icon_name(GTK_IMAGE(this->priv->image),
                                   "dialog-question", GTK_ICON_SIZE_DIALOG);
      gtk_box_pack_start(GTK_BOX(this->priv->boxDescr),
                         gtk_label_new(_("Not a V_Sim file")), TRUE, FALSE, 0);
      gtk_widget_show_all(this->priv->boxDescr);

      return FALSE;
    }
  if (error)
    {
      if (preview)
        g_object_unref(preview);
      gtk_image_set_from_icon_name(GTK_IMAGE(this->priv->image),
                                   "dialog-error", GTK_ICON_SIZE_DIALOG);
      gtk_box_pack_start(GTK_BOX(this->priv->boxDescr),
                         gtk_label_new(_("This file has errors")), TRUE, FALSE, 0);
      gtk_widget_show_all(this->priv->boxDescr);

      return FALSE;
    }

  gtk_box_pack_start(GTK_BOX(this->priv->boxDescr),
                     _getDescr(preview), FALSE, FALSE, 0);
  
  view = visu_gl_view_new_withSize((guint)150, (guint)150);
  g_object_set(G_OBJECT(view), "auto-adjust", TRUE, NULL);
  visu_boxed_setBox(VISU_BOXED(view), VISU_BOXED(preview));
  /* Setup extensions for the preview. */
  set = visu_gl_ext_set_new();
  nodes = visu_gl_ext_nodes_new();
  visu_gl_ext_set_add(set, VISU_GL_EXT(nodes));
  g_object_unref(nodes);
  visu_node_array_renderer_setNodeArray(VISU_NODE_ARRAY_RENDERER(nodes),
                                        VISU_NODE_ARRAY(preview));
  g_object_unref(preview);
  box = visu_gl_ext_box_new("box preview");
  visu_gl_ext_set_add(set, VISU_GL_EXT(box));
  g_object_unref(box);
  visu_gl_ext_box_setBox(box, visu_boxed_getBox(VISU_BOXED(preview)));
  visu_gl_ext_set_setGlView(set, view);
  g_object_unref(view);
  image = visu_gl_ext_set_getPixmapData(set, 0, 0, FALSE);
  g_object_unref(set);

  pixbuf =
    gdk_pixbuf_new_from_data((guchar*)image->data, GDK_COLORSPACE_RGB,
                             FALSE, 8, 150, 150, 3 * 150,
                             (GdkPixbufDestroyNotify)_freeUChar, (gpointer)0);
  g_array_free(image, FALSE);
  gtk_image_set_from_pixbuf(GTK_IMAGE(this->priv->image), pixbuf);
  g_object_unref(pixbuf);

  return FALSE;
}

static void _updatePreview(VisuUiDataChooser *this)
{
  GList *lst, *child;

  lst = gtk_container_get_children(GTK_CONTAINER(this->priv->boxDescr));
  for (child = lst; child; child = g_list_next(child))
    gtk_widget_destroy(GTK_WIDGET(child->data));
  g_list_free(lst);
  gtk_image_clear(GTK_IMAGE(this->priv->image));

  if (!gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(this->priv->checkPreview)) ||
      !_setFile(this))
    return;

  if (!this->priv->worker)
    this->priv->worker = g_idle_add((GSourceFunc)_renderPreview, this);
}

static void _createFilter(GtkFileChooser *chooser, GList *list)
{
  GtkFileFilter *filter, *filterAll;
  const GList *tmpLst2, *tmpLst;
  const char *name;

  GSList *filters, *it;

  filters = gtk_file_chooser_list_filters(chooser);
  for (it = filters; it; it = g_slist_next(it))
    gtk_file_chooser_remove_filter(chooser, GTK_FILE_FILTER(it->data));

  filters = (GSList*)0;
  filterAll = gtk_file_filter_new();
  gtk_file_filter_set_name(filterAll, _("All supported formats"));
  for (tmpLst = list; tmpLst; tmpLst = g_list_next(tmpLst))
    {
      filter = gtk_file_filter_new();
      name = tool_file_format_getLabel(TOOL_FILE_FORMAT(tmpLst->data));
      if (name)
	gtk_file_filter_set_name(filter, name);
      else
	gtk_file_filter_set_name(filter, _("No description"));
      for (tmpLst2 = tool_file_format_getFilePatterns(TOOL_FILE_FORMAT(tmpLst->data));
           tmpLst2; tmpLst2 = g_list_next(tmpLst2))
	{
	  gtk_file_filter_add_pattern(filter, (gchar*)tmpLst2->data);
	  gtk_file_filter_add_pattern(filterAll, (gchar*)tmpLst2->data);
	}
      g_object_set_data(G_OBJECT(filter), "_VisuDataLoader", tmpLst->data);
      filters = g_slist_append(filters, (gpointer)filter);
    }
  filters = g_slist_append(filters, (gpointer)filterAll);
  filter = gtk_file_filter_new();
  gtk_file_filter_set_name(filter, _("All files"));
  gtk_file_filter_add_pattern (filter, "*");
  filters = g_slist_append(filters, (gpointer)filter);
  
  for (it = filters; it; it = g_slist_next(it))
    gtk_file_chooser_add_filter(chooser, GTK_FILE_FILTER(it->data));
  gtk_file_chooser_set_filter(chooser, filterAll);

  g_slist_free(filters);
}

static void _setSpinInput(VisuUiDataChooser *this)
{
  if (gtk_combo_box_get_active(GTK_COMBO_BOX(this->priv->comboMethod)) != 1)
    return;

  if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(this->priv->checkAtomic)))
    _createFilter(GTK_FILE_CHOOSER(this), visu_data_atomic_class_getLoaders());
  else if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(this->priv->checkSpin)))
    _createFilter(GTK_FILE_CHOOSER(this), visu_data_spin_class_getLoaders());
}

static void _setMethod(VisuUiDataChooser *this)
{
  GList *lst, *child;
  GtkWidget *table;

  g_free(this->priv->atomicFile);
  this->priv->atomicFile = (gchar*)0;
  g_free(this->priv->spinFile);
  this->priv->spinFile = (gchar*)0;

  lst = gtk_container_get_children(GTK_CONTAINER(this->priv->boxMethod));
  for (child = lst; child; child = g_list_next(child))
    gtk_widget_destroy(GTK_WIDGET(child->data));

  switch (gtk_combo_box_get_active(GTK_COMBO_BOX(this->priv->comboMethod)))
    {
    case 0:
      _createFilter(GTK_FILE_CHOOSER(this), visu_data_atomic_class_getLoaders());
      break;
    case 1:
      /* The table for the two file types selections (spin & position). */
      table = gtk_grid_new();
      tool_grid_resize(table, 2, 4);
      gtk_box_pack_start(GTK_BOX(this->priv->boxMethod), table, TRUE, TRUE, 2);
  
      /* Position button. */
      this->priv->checkAtomic = gtk_radio_button_new_with_label(NULL, _("Positions:"));
      gtk_grid_attach(GTK_GRID(table), this->priv->checkAtomic, 0, 0, 1, 1);
      g_signal_connect_swapped(this->priv->checkAtomic, "toggled",
                               G_CALLBACK(_setSpinInput), this);

      /* Spin button */
      this->priv->checkSpin = gtk_radio_button_new_with_label_from_widget
        (GTK_RADIO_BUTTON(this->priv->checkAtomic), _("Spins:"));
      gtk_grid_attach(GTK_GRID(table), this->priv->checkSpin, 0, 1, 1, 1);
      g_signal_connect_swapped(this->priv->checkSpin, "toggled",
                               G_CALLBACK(_setSpinInput), this);

      this->priv->labelPosition = gtk_label_new(_("None"));
      gtk_widget_set_hexpand(this->priv->labelPosition, TRUE);
      gtk_label_set_xalign(GTK_LABEL(this->priv->labelPosition), 0.);
      gtk_widget_set_margin_start(this->priv->labelPosition, 10);
      gtk_grid_attach(GTK_GRID(table), this->priv->labelPosition, 3, 0, 1, 1);

      this->priv->labelSpin = gtk_label_new(_("None"));
      gtk_widget_set_hexpand(this->priv->labelSpin, TRUE);
      gtk_label_set_xalign(GTK_LABEL(this->priv->labelSpin), 0.);
      gtk_widget_set_margin_start(this->priv->labelSpin, 10);
      gtk_grid_attach(GTK_GRID(table), this->priv->labelSpin, 3, 1, 1, 1);

      gtk_widget_show_all(table);

      _setSpinInput(this);
      break;
    default:
      break;
    }
}

static gboolean _setFile(VisuUiDataChooser *this)
{
  gchar *filename;
  VisuDataLoader *format;

  filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(this));
  format = VISU_DATA_LOADER(g_object_get_data(G_OBJECT(gtk_file_chooser_get_filter(GTK_FILE_CHOOSER(this))), "_VisuDataLoader"));

  switch (gtk_combo_box_get_active(GTK_COMBO_BOX(this->priv->comboMethod)))
    {
    case 0:
      g_free(this->priv->atomicFile);
      this->priv->atomicFile = filename;
      this->priv->atomicFormat = format;
      return TRUE;
    case 1:
      if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(this->priv->checkAtomic)))
        {
          g_free(this->priv->atomicFile);
          this->priv->atomicFile = filename;
          this->priv->atomicFormat = format;
          if (filename)
            gtk_label_set_text(GTK_LABEL(this->priv->labelPosition), filename);
          else
            gtk_label_set_text(GTK_LABEL(this->priv->labelPosition), _("None"));
        }
      else if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(this->priv->checkSpin)))
        {
          g_free(this->priv->spinFile);
          this->priv->spinFile = filename;
          this->priv->spinFormat = format;
          if (filename)
            gtk_label_set_text(GTK_LABEL(this->priv->labelSpin), filename);
          else
            gtk_label_set_text(GTK_LABEL(this->priv->labelSpin), _("None"));
        }
      return this->priv->atomicFile && this->priv->spinFile;
    default:
      break;
    }
  return FALSE;
}

/**
 * visu_ui_data_chooser_run:
 * @this: a #VisuUiDataChooser object.
 *
 * Runs a file dialog chooser to select a #VisuDataLoadable file.
 *
 * Since: 3.8
 *
 * Returns: (transfer full): a newly created #VisuDataLoadable object.
 **/
VisuDataLoadable* visu_ui_data_chooser_run(VisuUiDataChooser *this)
{
  gint status;

  do
    {
      status = gtk_dialog_run(GTK_DIALOG(this));
      if (status != GTK_RESPONSE_OK)
        return (VisuDataLoadable*)0;

    } while (!_setFile(this));

  switch (gtk_combo_box_get_active(GTK_COMBO_BOX(this->priv->comboMethod)))
    {
    case 0:
      return VISU_DATA_LOADABLE(visu_data_atomic_new(this->priv->atomicFile,
                                                     this->priv->atomicFormat));
    case 1:
      return VISU_DATA_LOADABLE(visu_data_spin_new(this->priv->atomicFile,
                                                   this->priv->spinFile,
                                                   this->priv->atomicFormat,
                                                   this->priv->spinFormat));
    default:
      break;
    }
  return (VisuDataLoadable*)0;
}

static void exportParameters(GString *data, VisuData *dataObj _U_)
{
  g_string_append_printf(data, "# %s\n", DESC_PARAMETER_PREVIEW);
  g_string_append_printf(data, "%s[gtk]: %d\n\n", FLAG_PARAMETER_PREVIEW,
			 usePreview);
}
