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

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

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

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

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

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

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

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

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

#include <visu_gtk.h>
#include <gtk_main.h>
#include "gtk_dumpDialogWidget.h"
#include <support.h>
#include <dumpModules/fileDump.h>
#include <dumpModules/glDump.h>

/**
 * SECTION:gtk_dumpDialogWidget
 * @short_description: Defines a widget to export into different file
 * formats.
 * 
 * <para>This widget is based on the #GtkFileChooser in the save
 * mode. It proposes the user to choose a file to save to. In
 * addition, it automatically build a list of filters, corresponding
 * to the available export routines in V_Sim. By default, the filter
 * is set on 'auto', which means that the filter method is selected
 * with the file extension. The dialog also has a progress bar.</para>
 *
 * <para>This widget is also a dialog, and should be used with
 * gtk_dialog_run(). After the response GTK_RESPONSE_ACCEPT has been
 * recieved, one can grep the selected filename with
 * visu_ui_dump_dialog_getFilename(). The dialog does not call the exporting
 * routine by itself, the calling method should take care of
 * that. When doing it, the filechoosing part should be made
 * insensitive, using visu_ui_dump_dialog_start() and the progress bar should be
 * updated accordingly (get it with
 * visu_ui_dump_dialog_getProgressBar()).</para>
 *
 * <para>The user interface propose also to change the size  (see
 * visu_ui_dump_dialog_getHeight() and visu_ui_dump_dialog_getWidth()) and if
 * some options are associated to a file format, these options are
 * displayed.</para>
 */

static void visu_ui_dump_dialog_dispose (GObject *obj);
static void visu_ui_dump_dialog_finalize(GObject *obj);

struct _VisuUiDumpDialog
{
  GtkDialog dialog;

  GtkWidget *fileChooser;

  GtkWidget *hBoxOptions;
  GtkWidget *comboType;
  VisuDump  *selectedToolFileFormat;
  GtkWidget *expanderToolFileFormat;
  GtkWidget *checkFileExtension;
  GtkWidget *spinWidth, *spinHeight;

  GtkWidget *infoBar;
  GtkWidget *progressBar;
  GtkWidget *cancelButton;

  gchar     *dumpFileName;

  VisuData  *dataObj;

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

struct _VisuUiDumpDialogClass
{
  GtkDialogClass parent_class;

  guint width, height;
  gchar *current_dir;

  guint formatId;

  void (*dumpDialog) (VisuUiDumpDialog *dump);
};

/* Local callbacks */
static void onWidthHeightChanged(GtkSpinButton *spin, gpointer data);
static void onSpinPropertyChange(GtkSpinButton *spin, gpointer data);
static void onCheckPropertyChange(GtkToggleButton *toggle, gpointer data);
static void onComboToolFileFormatChange(GtkComboBox *combo, gpointer data);
static void onVisuUiDumpDialogResponse(GtkDialog *dialog, gint id, gpointer *data);

G_DEFINE_TYPE(VisuUiDumpDialog, visu_ui_dump_dialog, GTK_TYPE_DIALOG)

static void visu_ui_dump_dialog_class_init(VisuUiDumpDialogClass *klass)
{
  DBG_fprintf(stderr, "Gtk VisuUiDumpDialog: creating the class of the widget.\n");

  klass->width  = 0;
  klass->height = 0;
  klass->current_dir = (gchar*)0;
  klass->formatId = 0;

  G_OBJECT_CLASS(klass)->dispose = visu_ui_dump_dialog_dispose;
  G_OBJECT_CLASS(klass)->finalize = visu_ui_dump_dialog_finalize;
}

static void visu_ui_dump_dialog_init(VisuUiDumpDialog *dumpDialog)
{
  DBG_fprintf(stderr, "Gtk VisuUiDumpDialog: initializing new object (%p).\n",
	      (gpointer)dumpDialog);

  dumpDialog->selectedToolFileFormat = (VisuDump*)0;
  dumpDialog->dumpFileName = (gchar*)0;
  dumpDialog->dataObj = (VisuData*)0;

  g_signal_connect(G_OBJECT(dumpDialog), "response",
		   G_CALLBACK(onVisuUiDumpDialogResponse), (gpointer)dumpDialog);
}

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

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

  VISU_UI_DUMP_DIALOG(obj)->dispose_has_run = TRUE;
  /* Chain up to the parent class */
  G_OBJECT_CLASS(visu_ui_dump_dialog_parent_class)->dispose(obj);
}
static void visu_ui_dump_dialog_finalize(GObject *obj)
{
  VisuUiDumpDialog *dialog;

  g_return_if_fail(obj);

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

  dialog = VISU_UI_DUMP_DIALOG(obj);
  if (dialog->dumpFileName)
    /* Free the stored filename. */
    g_free(dialog->dumpFileName);

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

  DBG_fprintf(stderr, "Gtk VisuUiDumpDialog: freeing ... OK.\n");
}

/**
 * visu_ui_dump_dialog_new :
 * @dataObj: (allow-none): a #VisuData object (can be NULL) ;
 * @parent: (allow-none): the parent window ;
 * @suggestedFilename: (allow-none): a string or NULL.
 * @suggestedWidth: a positive suggested width for exportation or a
 * negative value to get the default.
 * @suggestedHeight: idem for height.
 *
 * A #VisuUiDumpDialog widget is complete dialog window widget, but it is already
 * prepared for dumping, proposing known file formats. It is usefull to get
 * an filename to export to. It has also a progress bar that can illustrate
 * the process. The given @dataObj argument is used to initialize some
 * values related to the data to be dumped.
 *
 * Returns: a newly created #VisuUiDumpDialog widget.
 */
GtkWidget* visu_ui_dump_dialog_new(VisuData *dataObj, GtkWindow *parent,
                                   const gchar *suggestedFilename,
                                   gint suggestedWidth, gint suggestedHeight)
{
  VisuUiDumpDialog *dumpDialog;
  VisuUiDumpDialogClass *klass;
  const gchar *directory;
  const gchar *filename, *labelType;
  GList *format;
  GtkWidget *hbox2, *hbox;
  GtkWidget *label;
  GtkWidget *wd;
  GtkWidget *vbox;

  if (!parent)
    parent = visu_ui_getRenderWindow();

  DBG_fprintf(stderr, "Gtk VisuUiDumpDialog: creating a new VisuUiDumpDialog object.\n");

  dumpDialog = VISU_UI_DUMP_DIALOG(g_object_new(VISU_TYPE_UI_DUMP_DIALOG, NULL));
  gtk_window_set_title(GTK_WINDOW(dumpDialog),
		       _("Export to a file (image, atomic structures...)"));
  klass = VISU_UI_DUMP_DIALOG_CLASS(G_OBJECT_GET_CLASS(dumpDialog));
  /* This is to avoid a bug in gtk 2.4 */
#if GTK_MAJOR_VERSION > 2 || GTK_MINOR_VERSION > 5
  gtk_window_set_modal(GTK_WINDOW(dumpDialog), TRUE);
#endif
  gtk_window_set_transient_for(GTK_WINDOW(dumpDialog), GTK_WINDOW(parent));
  gtk_window_set_position(GTK_WINDOW(dumpDialog), GTK_WIN_POS_CENTER_ON_PARENT);

  dumpDialog->cancelButton = gtk_dialog_add_button(GTK_DIALOG(dumpDialog),
                                                   TOOL_ICON_CANCEL, GTK_RESPONSE_CANCEL);
  gtk_dialog_add_button(GTK_DIALOG(dumpDialog), TOOL_ICON_SAVE, GTK_RESPONSE_ACCEPT);
  gtk_dialog_set_default_response(GTK_DIALOG(dumpDialog), GTK_RESPONSE_ACCEPT);

  /* Create the file chooser part. */
  dumpDialog->fileChooser = gtk_file_chooser_widget_new(GTK_FILE_CHOOSER_ACTION_SAVE);
  gtk_widget_set_size_request(dumpDialog->fileChooser, -1, 350);
#if GTK_MAJOR_VERSION > 2 || GTK_MINOR_VERSION > 7
  gtk_file_chooser_set_do_overwrite_confirmation
    (GTK_FILE_CHOOSER(dumpDialog->fileChooser), TRUE);
#endif
  gtk_box_pack_start(GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(dumpDialog))),
		     dumpDialog->fileChooser, TRUE, TRUE, 2);
  gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(dumpDialog->fileChooser),
				       FALSE);
  /* We set the suggested filename, either a previous one
     or the one given. */
  filename = (const gchar*)0;
  dumpDialog->dataObj = dataObj;
  if (dataObj)
    filename = (const gchar*)g_object_get_data(G_OBJECT(dataObj),
					       "visu_ui_dump_dialog_filename");
  if (!filename)
    filename = suggestedFilename;
  if (filename)
    gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(dumpDialog->fileChooser),
				      filename);

  /* Create the file options part. */
  dumpDialog->hBoxOptions = gtk_hbox_new(FALSE, 0);
  gtk_file_chooser_set_extra_widget(GTK_FILE_CHOOSER(dumpDialog->fileChooser),
				    dumpDialog->hBoxOptions);

  vbox = gtk_vbox_new(FALSE, 0);
  gtk_box_pack_start(GTK_BOX(dumpDialog->hBoxOptions), vbox, TRUE, TRUE, 2);
  hbox = gtk_hbox_new(FALSE, 0);
  gtk_box_pack_start(GTK_BOX(vbox),
		     hbox, FALSE, FALSE, 0);
  /* Label to introduce the combobox which allow to choose the format */
  label = gtk_label_new(_("Choose the file format : "));
  gtk_label_set_xalign(GTK_LABEL(label), 0.);
  gtk_box_pack_start(GTK_BOX(hbox), label, TRUE, TRUE, 0);
  dumpDialog->comboType = gtk_combo_box_text_new();
  /* Set the combo entry that let V_Sim detect the desired format through the extension. */
  gtk_combo_box_text_append(GTK_COMBO_BOX_TEXT(dumpDialog->comboType),
                            (const gchar*)0, _("Autodetect format"));
  gtk_box_pack_start(GTK_BOX(hbox), dumpDialog->comboType, FALSE, FALSE, 0);
  /* Add an expander for file format options. */
  dumpDialog->expanderToolFileFormat = gtk_expander_new(_("File format option:"));
  gtk_widget_set_sensitive(dumpDialog->expanderToolFileFormat, FALSE);
  gtk_box_pack_start(GTK_BOX(vbox),
		     dumpDialog->expanderToolFileFormat, FALSE, FALSE, 0);
  g_signal_connect(G_OBJECT(dumpDialog->comboType), "changed",
		   G_CALLBACK(onComboToolFileFormatChange), (gpointer)dumpDialog);
  /* Add a separator. */
  wd = gtk_vseparator_new();
  gtk_box_pack_start(GTK_BOX(dumpDialog->hBoxOptions),
		     wd, FALSE, FALSE, 0);
  /* Create common options part. */
  vbox = gtk_vbox_new(FALSE, 0);
  gtk_box_pack_start(GTK_BOX(dumpDialog->hBoxOptions), vbox, TRUE, TRUE, 2);
  dumpDialog->checkFileExtension = gtk_check_button_new_with_label(_("Add extension"));
  gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dumpDialog->checkFileExtension), TRUE);
  gtk_widget_set_sensitive(dumpDialog->checkFileExtension, FALSE);
  gtk_box_pack_start(GTK_BOX(vbox), dumpDialog->checkFileExtension, FALSE, FALSE, 0);
  hbox = gtk_hbox_new(FALSE, 0);
  gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
  label = gtk_label_new(_("Width: "));
  gtk_label_set_xalign(GTK_LABEL(label), 0.);
  gtk_box_pack_start(GTK_BOX(hbox), label, TRUE, TRUE, 0);
  dumpDialog->spinWidth = gtk_spin_button_new_with_range(1., 2000., 1.);
  if (klass->width > 0)
    gtk_spin_button_set_value(GTK_SPIN_BUTTON(dumpDialog->spinWidth),
			      (gdouble)klass->width);
  else if (suggestedWidth > 0)
    gtk_spin_button_set_value(GTK_SPIN_BUTTON(dumpDialog->spinWidth),
			      (gdouble)suggestedWidth);
  gtk_box_pack_start(GTK_BOX(hbox), dumpDialog->spinWidth, FALSE, FALSE, 0);
  label = gtk_label_new(_("px"));
  gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
  hbox = gtk_hbox_new(FALSE, 0);
  gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
  label = gtk_label_new(_("Height: "));
  gtk_label_set_xalign(GTK_LABEL(label), 0.);
  gtk_box_pack_start(GTK_BOX(hbox), label, TRUE, TRUE, 0);
  dumpDialog->spinHeight = gtk_spin_button_new_with_range(1., 2000., 1.);
  if (klass->height > 0)
    gtk_spin_button_set_value(GTK_SPIN_BUTTON(dumpDialog->spinHeight),
			      (gdouble)klass->height);
  else if (suggestedHeight > 0)
    gtk_spin_button_set_value(GTK_SPIN_BUTTON(dumpDialog->spinHeight),
			      (gdouble)suggestedHeight);
  gtk_box_pack_start(GTK_BOX(hbox), dumpDialog->spinHeight, FALSE, FALSE, 0);
  label = gtk_label_new(_("px"));
  gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
  g_signal_connect(G_OBJECT(dumpDialog->spinWidth), "value-changed",
		   G_CALLBACK(onWidthHeightChanged), (gpointer)&klass->width);
  g_signal_connect(G_OBJECT(dumpDialog->spinHeight), "value-changed",
		   G_CALLBACK(onWidthHeightChanged), (gpointer)&klass->height);

  
  /* Create the progress bar part. */
  hbox2 = gtk_hbox_new(FALSE, 0);
  gtk_box_pack_start(GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(dumpDialog))),
		     hbox2, FALSE, FALSE, 2);
  /* Label to introduce the progress bar */
  label = gtk_label_new(_("Dump progress : "));
  gtk_label_set_xalign(GTK_LABEL(label), 0.);
  gtk_box_pack_start(GTK_BOX(hbox2), label, FALSE, FALSE, 0);
  dumpDialog->progressBar = gtk_progress_bar_new();
  gtk_box_pack_start(GTK_BOX(hbox2), dumpDialog->progressBar, TRUE, TRUE, 2);

  /* Add an info bar for warning and so on. */
#if GTK_MAJOR_VERSION > 2 || GTK_MINOR_VERSION > 17 
  dumpDialog->infoBar = gtk_info_bar_new();
  gtk_widget_set_no_show_all(dumpDialog->infoBar, TRUE);
  gtk_info_bar_set_message_type(GTK_INFO_BAR(dumpDialog->infoBar),
                                GTK_MESSAGE_WARNING);
  label = gtk_label_new(_("Current box has translations applied,"
                          " do you want to proceed to exportation anyway?"));
  gtk_widget_show(label);
  gtk_container_add
    (GTK_CONTAINER(gtk_info_bar_get_content_area(GTK_INFO_BAR(dumpDialog->infoBar))),
     label);
  gtk_box_pack_start(GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(dumpDialog))),
		     dumpDialog->infoBar, FALSE, FALSE, 2);
#endif

  /* Setting default values. */
  gtk_widget_set_name(GTK_WIDGET(dumpDialog), "filesel");
  directory = visu_ui_main_getLastOpenDirectory(visu_ui_main_class_getCurrentPanel());
  if (klass->current_dir)
    gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dumpDialog->fileChooser),
					klass->current_dir);
  else if (directory)
    gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dumpDialog->fileChooser),
					directory);
  for (format = visu_dump_pool_getAllModules(); format; format = g_list_next(format))
    {
      labelType = tool_file_format_getLabel(TOOL_FILE_FORMAT(format->data));
      if (labelType)
	gtk_combo_box_text_append(GTK_COMBO_BOX_TEXT(dumpDialog->comboType),
                                  (const gchar*)0, labelType);
    }
  gtk_combo_box_set_active(GTK_COMBO_BOX(dumpDialog->comboType), klass->formatId);

  gtk_widget_show_all(GTK_WIDGET(dumpDialog));
  return GTK_WIDGET(dumpDialog);
}


/*******************/
/* Local callbacks */
/*******************/
static void onSpinPropertyChange(GtkSpinButton *spin, gpointer data)
{
  GValue *val;

  val = (GValue*)data;
  g_value_set_int(val, (int)gtk_spin_button_get_value(spin));
  DBG_fprintf(stderr, "Gtk VisuUiDumpDialog: set property spin to %d.\n",
              g_value_get_int(val));
}
static void onCheckPropertyChange(GtkToggleButton *toggle, gpointer data)
{
  GValue *val;

  val = (GValue*)data;
  g_value_set_boolean(val, gtk_toggle_button_get_active(toggle));
  DBG_fprintf(stderr, "Gtk VisuUiDumpDialog: set property check to %d.\n",
              g_value_get_boolean(val));
}
static void onComboToolFileFormatChange(GtkComboBox *combo, gpointer data)
{
  int formatInt, i;
  GList *dumpTypes;
  ToolFileFormatIter iter;
  GtkWidget *wd, *label, *hbox, *vbox;

  g_return_if_fail(VISU_IS_UI_DUMP_DIALOG(data));

  /* Empty the expander for properties. */
  wd = gtk_bin_get_child(GTK_BIN(VISU_UI_DUMP_DIALOG(data)->expanderToolFileFormat));
  if (wd)
    gtk_widget_destroy(wd);

  dumpTypes = visu_dump_pool_getAllModules();
  formatInt = gtk_combo_box_get_active(combo);
  VISU_UI_DUMP_DIALOG_GET_CLASS(data)->formatId = (guint)formatInt;
  DBG_fprintf(stderr, "Gtk VisuUiDumpDialog: On file format change (%d).\n", formatInt);
  /* Select auto file format -> no properties. */
  if (formatInt == 0)
    {
      gtk_widget_set_sensitive(VISU_UI_DUMP_DIALOG(data)->expanderToolFileFormat, FALSE);
      gtk_widget_set_sensitive(VISU_UI_DUMP_DIALOG(data)->checkFileExtension, FALSE);
      return;
    }
  else
    /* Search for the selected property. */
    for(i = 0; i < formatInt - 1; i++) dumpTypes = g_list_next(dumpTypes);
  /* Set the check box for extension auto completion. */
  gtk_widget_set_sensitive(VISU_UI_DUMP_DIALOG(data)->checkFileExtension, TRUE);
  /* Get properties if exist for this format. */
  iter.lst = (GList*)0;
  tool_file_format_iterNextProperty(TOOL_FILE_FORMAT(dumpTypes->data), &iter);
  if (!iter.lst)
    {
      gtk_widget_set_sensitive(VISU_UI_DUMP_DIALOG(data)->expanderToolFileFormat, FALSE);
      return;
    }
  gtk_widget_set_sensitive(VISU_UI_DUMP_DIALOG(data)->expanderToolFileFormat, TRUE);
  vbox = gtk_vbox_new(FALSE, 0);
  gtk_container_add(GTK_CONTAINER(VISU_UI_DUMP_DIALOG(data)->expanderToolFileFormat), vbox);
  iter.lst = (GList*)0;
  for (tool_file_format_iterNextProperty(TOOL_FILE_FORMAT(dumpTypes->data), &iter); iter.lst;
       tool_file_format_iterNextProperty(TOOL_FILE_FORMAT(dumpTypes->data), &iter))
    {
      hbox = gtk_hbox_new(FALSE, 0);
      gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
      label = gtk_label_new(iter.label);
      gtk_label_set_xalign(GTK_LABEL(label), 1.);
      gtk_widget_set_margin_start(label, 10);
      gtk_box_pack_start(GTK_BOX(hbox), label, TRUE, TRUE, 0);
      switch (G_VALUE_TYPE(iter.val))
	{
	case G_TYPE_INT:
	  wd = gtk_spin_button_new_with_range(0., 100., 1.);
	  gtk_spin_button_set_value(GTK_SPIN_BUTTON(wd), (gdouble)g_value_get_int(iter.val));
	  gtk_box_pack_start(GTK_BOX(hbox), wd, FALSE, FALSE, 0);
	  g_signal_connect(G_OBJECT(wd), "value-changed",
			   G_CALLBACK(onSpinPropertyChange), iter.val);
	  break;
	case G_TYPE_BOOLEAN:
	  wd = gtk_check_button_new();
	  gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(wd), g_value_get_boolean(iter.val));
	  gtk_box_pack_start(GTK_BOX(hbox), wd, FALSE, FALSE, 0);
	  g_signal_connect(G_OBJECT(wd), "toggled",
			   G_CALLBACK(onCheckPropertyChange), iter.val);
	  break;
	default:
	  g_warning("Unknown, or nsupprted file format property"
		    " given to 'onComboToolFileFormatChange'.");
	};
    }
  gtk_widget_show_all(vbox);
  /* Expand the option expander. */
  gtk_expander_set_expanded(GTK_EXPANDER(VISU_UI_DUMP_DIALOG(data)->expanderToolFileFormat), TRUE);
}
static void onVisuUiDumpDialogResponse(GtkDialog *dialog, gint id, gpointer *data)
{
  gchar *filename;
  int formatInt;
  gchar *ext, *pattern;
  GList *dumpTypes;
  VisuUiDumpDialog *dumpDialog;
  VisuUiDumpDialogClass *klass;

  g_return_if_fail(VISU_IS_UI_DUMP_DIALOG(data));

  dumpDialog = VISU_UI_DUMP_DIALOG(data);

  DBG_fprintf(stderr, "Gtk VisuUiDumpDialog: catch the 'response' signal:"
	      " %d (ACCEPT is %d).\n", id, GTK_RESPONSE_ACCEPT);
  /* Get the filename. */
  filename = (gchar*)0;
  formatInt = -1;
  if (id == GTK_RESPONSE_ACCEPT)
    {
      filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dumpDialog->fileChooser));
      formatInt = gtk_combo_box_get_active(GTK_COMBO_BOX(dumpDialog->comboType));
      if (!filename)
	{
	  /* Autodetect failed, no format match the given filename */
	  visu_ui_raiseWarning(_("Saving a file"),
			       _("No filename chosen."),
			       GTK_WINDOW(dialog));
	  g_signal_stop_emission_by_name(G_OBJECT(dumpDialog), "response");
	  return;
	}
    }

  if (formatInt >= 0)
    {
      dumpTypes = visu_dump_pool_getAllModules();
      if (formatInt == 0)
	/* The automatic format has been selected, we look in the pattern list to
	   find a matching pattern. */
	while (dumpTypes && !tool_file_format_match
               (TOOL_FILE_FORMAT(dumpTypes->data), filename))
	  dumpTypes = g_list_next(dumpTypes);
      else
        dumpTypes = g_list_nth(dumpTypes, formatInt - 1);
      if (!dumpTypes)
	{
	  /* Autodetect failed, no format match the given filename */
	  visu_ui_raiseWarning(_("Saving a file"),
			       _("The filename doesn't match any known format."),
			       GTK_WINDOW(dialog));
	  g_free(filename);
	  g_signal_stop_emission_by_name(G_OBJECT(dumpDialog), "response");
	  return;
	}
      DBG_fprintf(stderr, "Gtk VisuUiDumpDialog: export to dump %p.\n", dumpTypes->data);

      /* Special warning for non bitmap exportation with translations. */
#if GTK_MAJOR_VERSION > 2 || GTK_MINOR_VERSION > 17
      if (VISU_IS_DUMP_DATA(dumpTypes->data) &&
          visu_pointset_getTranslationPeriodicStatus(VISU_POINTSET(dumpDialog->dataObj)) &&
          !gtk_widget_get_visible(dumpDialog->infoBar))
        {
          gtk_widget_show(dumpDialog->infoBar);
	  g_free(filename);
	  g_signal_stop_emission_by_name(G_OBJECT(dumpDialog), "response");
	  return;
        }
#endif
      
      if (formatInt > 0 &&
	  gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dumpDialog->checkFileExtension)))
	{
	  if (tool_file_format_canMatch(TOOL_FILE_FORMAT(dumpTypes->data)) &&
              !tool_file_format_match(TOOL_FILE_FORMAT(dumpTypes->data), filename))
	    {
	      pattern = (gchar*) tool_file_format_getFilePatterns
                (TOOL_FILE_FORMAT(dumpTypes->data))->data;
	      ext = g_strrstr(pattern, ".");
	      dumpDialog->dumpFileName = g_strdup_printf("%s%s", filename, ext);
	      g_free(filename);
	    }
	  else
	    dumpDialog->dumpFileName = filename;
	}
      else
	dumpDialog->dumpFileName = filename;
      dumpDialog->selectedToolFileFormat = VISU_DUMP(dumpTypes->data);
      DBG_fprintf(stderr, "Gtk VisuUiDumpDialog: '%s' file format chosen.\n",
		  tool_file_format_getName(TOOL_FILE_FORMAT(dumpDialog->selectedToolFileFormat)));
      /* Save the filename in a property of the VisuData object. */
      filename = g_path_get_basename(dumpDialog->dumpFileName);
      g_object_set_data_full(G_OBJECT(dumpDialog->dataObj), "visu_ui_dump_dialog_filename",
			     (gpointer)filename, g_free);

      /* Save the dirname in the class. */
      klass = VISU_UI_DUMP_DIALOG_CLASS(G_OBJECT_GET_CLASS(dumpDialog));
      if (klass->current_dir)
	g_free(klass->current_dir);
      klass->current_dir = g_path_get_dirname(dumpDialog->dumpFileName);
    }
}
static void onWidthHeightChanged(GtkSpinButton *spin, gpointer data)
{
  *(guint*)data = (guint)gtk_spin_button_get_value(spin);
}

/******************/
/* Public methods */
/******************/
gchar* visu_ui_dump_dialog_getFilename(VisuUiDumpDialog *dialog)
{
  g_return_val_if_fail(dialog, (gchar*)0);
  return dialog->dumpFileName;
}
VisuDump* visu_ui_dump_dialog_getType(VisuUiDumpDialog *dialog)
{
  g_return_val_if_fail(dialog, (VisuDump*)0);
  return dialog->selectedToolFileFormat;
}
GtkProgressBar* visu_ui_dump_dialog_getProgressBar(VisuUiDumpDialog *dialog)
{
  g_return_val_if_fail(dialog, (GtkProgressBar*)0);
  return GTK_PROGRESS_BAR(dialog->progressBar);
}
GtkButton* visu_ui_dump_dialog_getCancelButton(VisuUiDumpDialog *dialog)
{
  g_return_val_if_fail(dialog, (GtkButton*)0);
  return GTK_BUTTON(dialog->cancelButton);
}
gint visu_ui_dump_dialog_getWidth(VisuUiDumpDialog *dialog)
{
  g_return_val_if_fail(dialog, 0);
  return (gint)gtk_spin_button_get_value(GTK_SPIN_BUTTON(dialog->spinWidth));
}
gint visu_ui_dump_dialog_getHeight(VisuUiDumpDialog *dialog)
{
  g_return_val_if_fail(dialog, 0);
  return (gint)gtk_spin_button_get_value(GTK_SPIN_BUTTON(dialog->spinHeight));
}
void visu_ui_dump_dialog_start(VisuUiDumpDialog *dialog)
{
  /* Put everything except the progress bar insensitive */
  gtk_widget_set_sensitive(dialog->fileChooser, FALSE);
  gtk_widget_set_sensitive(dialog->hBoxOptions, FALSE);
}
void visu_ui_dump_dialog_stop(VisuUiDumpDialog *dialog)
{
  /* Put everything except the progress bar sensitive */
  gtk_widget_set_sensitive(dialog->fileChooser, TRUE);
  gtk_widget_set_sensitive(dialog->hBoxOptions, TRUE);
}
