Logo Search packages:      
Sourcecode: v-sim version File versions  Download package

panelPlanes.c

/*   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 "panelPlanes.h"

#include <GL/gl.h>
#include <GL/glu.h> 

#include <visu_object.h>
#include <support.h>
#include <gtk_main.h>
#include <openGLFunctions/objectList.h>
#include <visu_extension.h>
#include <coreTools/toolMatrix.h>

#include <extraFunctions/plane.h>
#include <extraGtkFunctions/gtk_toolPanelWidget.h>
#include <extraGtkFunctions/gtk_colorComboBoxWidget.h>
#include <extraGtkFunctions/gtk_numericalEntryWidget.h>

#include "visuConfig.h"

#define PANEL_PLANES_NO_PLANE_LIST _("<span font_desc=\"smaller\"><i>none</i></span>")

GtkWidget *panelPlanes;
GtkWidget *vBoxPlanes;
GtkWidget *checkUsePlanes;
GtkWidget *spinbuttonNVect[3];
GtkWidget *spinbuttonDistance;
GtkWidget *widgetColorPlane;
GtkWidget *treeviewPlanes;
GtkListStore *listStoredPlanes;
GtkWidget *labelDistance;
GtkWidget *buttonRotate;
GtkWidget *hboxHidingMode;
GtkWidget *vboxDistChange;
GtkWidget *entryDistFrom, *entryDistTo, *entryDistStep, *spinDistDelay;
GtkWidget *imageDistPlay, *imageDistStop;


/* Variables for the IO tab. */
GtkWidget *hboxSaveList;
gchar *currentSaveListFile;
GtkWidget *buttonSaveList;
GtkWidget *labelPlaneList;

/* Callbacks for the IO tab. */
static void onPlaneListOpen(GtkButton *button, gpointer data);
static void onPlaneListSave(GtkButton *button, gpointer data);
static void onPlaneListSaveAs(GtkButton *button, gpointer data);

gulong onAskForHide_signal_id;
guint isPlayingDistanceId;
gdouble directionDist;

/* Local callbacks. */
void onPlaneUsed(GtkToggleButton *button, gpointer data);
void onPlaneAdd(GtkButton *button, gpointer data);
void onPlaneRemove(GtkButton *button, gpointer data);
void onSpinNVectChange(GtkSpinButton *spin, gpointer data);
void onSpinDistanceChange(GtkSpinButton *spin, gpointer data);
void onPlaneColorChange(ColorComboBox *combo, Color *selectedColor, gpointer data);
void rebuildListPlanes(VisuData *dataObj);
static void onDataReadyForRendering(GObject *obj, VisuData *dataObj, gpointer data);
static void onNewFileLoaded(GObject *obj, VisuData *dataObj, gpointer data);
void onTreeSelectionChanged(GtkTreeSelection *tree, gpointer data);
void onNodePositionChanged(VisuData *dataObj, gpointer data);
void onSetCameraPosition(GtkButton *button, gpointer data);
void onSpinBoundsChangeDistance(GObject *obj, gfloat val, gpointer data);
void onGtkPlanesDrawnToggled(GtkCellRendererToggle *cell_renderer,
                       gchar *path, gpointer user_data);
void onGtkPlanesHideToggled(GtkCellRendererToggle *cell_renderer,
                      gchar *path, gpointer user_data);
void onGtkPlanesHidingModeToggled(GtkToggleButton *toggle, gpointer data);
static void onAskForHideNodes(VisuData *visuData, gboolean *redraw, gpointer data);
static void onPlayStopDist(GtkButton *button, gpointer data);
static void onSpinDistDelayChange(GtkSpinButton *spin, gpointer data);
static void onPlanesEnter(ToolPanel *planes, gpointer data);

/* Local methods. */
static void stopPlayStop(gpointer data);
static gboolean playDistances(gpointer data);
/* Call createInteriorPlanes() to create all the widgets,
   and if dataObj is not null, it set callbacks as if
   a new VisuData has been loaded. */
static void createAndInitPlanePanel(VisuData *dataObj);
static void createInteriorPlanes();

gboolean isPlanesInitialised;

OpenGLExtension *extensionPlanes;
int identifierAllPlanes;

/* String used to labelled planes, dist. means 'distance' and
   norm. means 'normal' (50 chars max). */
#define LABEL_PLANE _("<b>norm.</b>: (%3d;%3d;%3d)\n<b>distance</b>: %6.2f")

ToolPanel* initPanelPlanes()
{
  /* Long description */
  char *cl = _("Drawing planes");
  /* Short description */
  char *tl = _("Planes");

  panelPlanes = toolPanelNew_withIconFromPath("Panel_planes", cl, tl, "stock-channels-16.png");
  if (!panelPlanes)
    return (ToolPanel*)0;
  toolPanelSet_dockable(TOOL_PANEL(panelPlanes), TRUE);

  vBoxPlanes = gtk_vbox_new (FALSE, 0);
  gtk_widget_set_sensitive(vBoxPlanes, FALSE);

  isPlanesInitialised = FALSE;
  checkUsePlanes = (GtkWidget*)0;
  isPlayingDistanceId = 0;
  currentSaveListFile = (gchar*)0;
  /* Create the listModel */
  listStoredPlanes = gtk_list_store_new (N_COLUMN_PLANE,
                               G_TYPE_BOOLEAN,
                               G_TYPE_STRING,
                               G_TYPE_BOOLEAN,
                               G_TYPE_BOOLEAN,
                               GDK_TYPE_PIXBUF,
                               G_TYPE_OBJECT);

  /* Book some OpenGL list to draw planes. */
  identifierAllPlanes = openGLObjectList_new(1);
  extensionPlanes = OpenGLExtension_new(_("Planes"), _("Draw some planes."),
                              identifierAllPlanes, rebuildListPlanes);
  extensionPlanes->used = 0;
  OpenGLExtensionSet_priority(extensionPlanes, OPENGL_EXTENSION_PRIORITY_NORMAL + 10);
  OpenGLExtensionSet_sensitiveToRenderingMode(extensionPlanes, TRUE);
  OpenGLExtensionRegister(extensionPlanes);

  /* Add the signal for the vBoxPlanes. */
  g_signal_connect(G_OBJECT(visu), "dataReadyForRendering",
               G_CALLBACK(onDataReadyForRendering), (gpointer)0);
  g_signal_connect(G_OBJECT(panelPlanes), "page-entered",
               G_CALLBACK(onPlanesEnter), (gpointer)0);

  return TOOL_PANEL(panelPlanes);
}

GtkListStore* panelPlanesGet_listStore()
{
  return listStoredPlanes;
}

gboolean drawPlanes(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
{
  Plane *plane;
  gboolean used;

  g_return_val_if_fail(IS_VISU_DATA_TYPE(data), FALSE);

  used = FALSE;
  gtk_tree_model_get(model, iter, COLUMN_PLANE_DRAWN, &used, -1);
  if (used)
    {
      gtk_tree_model_get(model, iter, COLUMN_PLANE_POINTER, &plane, -1);
      if (plane)
      {
        /* Because the get action increase the counter... */
        g_object_unref(G_OBJECT(plane));
        planeDraw(plane, visuDataGet_openGLView(VISU_DATA(data)));
      }
    }  
  return FALSE;
}

void rebuildListPlanes(VisuData *dataObj)
{
  DBG_fprintf(stderr, "Panel planes : rebuilding object list for planes.\n");
  glNewList(identifierAllPlanes, GL_COMPILE);

  /* Set blend if not present. */
  glEnable(GL_BLEND);
  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

  gtk_tree_model_foreach(GTK_TREE_MODEL(listStoredPlanes), drawPlanes, (gpointer)dataObj);
  glEndList();
}

static void createAndInitPlanePanel(VisuData *dataObj)
{
  createInteriorPlanes();
  isPlanesInitialised = TRUE;
  /* Force to connect signal if a file is already loaded. */
  if (dataObj)
    onNewFileLoaded(visu, dataObj, (gpointer)0);
}

static void onPlanesEnter(ToolPanel *planes, gpointer data)
{
  DBG_fprintf(stderr, "Panel Planes : caught the 'page-entered' signal.\n");
  if (!isPlanesInitialised)
    createAndInitPlanePanel(toolPanelGet_visuData(TOOL_PANEL(panelPlanes)));
}

static void createInteriorPlanes()
{
  GtkWidget *alignment1;
  GtkWidget *hbox1, *hbox;
  GtkWidget *image1;
  GtkWidget *label1, *label;
  GtkWidget *scrolledPlanes;
  GtkWidget *hbox2;
  GtkWidget *alignment3;
  GtkWidget *vbox3, *vboxIO;
  GtkWidget *hbox4;
  GtkWidget *label2;
  GtkObject *spinbuttonNVect_adj[3];
  GtkWidget *hbox5;
  GtkObject *spinbuttonDistance_adj;
  GtkWidget *hbox3;
  GtkWidget *label4;
  GtkWidget *alignment2;
  GtkWidget *vbox2, *vbox;
  GtkWidget *buttonPlaneAdd, *buttonDistPlayStop;
  GtkWidget *image2;
  GtkWidget *buttonPlaneRemove, *button;
  GtkWidget *image4;
  GtkCellRenderer *renderer;
  GtkTreeViewColumn *column;
  GtkWidget *image;
  GtkTooltips *tooltips;
  GSList *radiobuttonHideUnion_group;
  GtkWidget *radiobuttonHideInter, *radiobuttonHideUnion;
  GtkWidget *notebook;

  int i;

  tooltips = gtk_tooltips_new ();

  gtk_widget_show(vBoxPlanes);

  checkUsePlanes = gtk_check_button_new ();
  gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(checkUsePlanes), extensionPlanes->used);
  gtk_widget_show (checkUsePlanes);
  gtk_box_pack_start (GTK_BOX (vBoxPlanes), checkUsePlanes, FALSE, FALSE, 0);

  alignment1 = gtk_alignment_new (0.5, 0.5, 0, 0);
  gtk_widget_show (alignment1);
  gtk_container_add (GTK_CONTAINER (checkUsePlanes), alignment1);

  hbox1 = gtk_hbox_new (FALSE, 2);
  gtk_widget_show (hbox1);
  gtk_container_add (GTK_CONTAINER (alignment1), hbox1);

  image1 = create_pixmap (mainWindow, "stock-channels-16.png");
  gtk_widget_show (image1);
  gtk_box_pack_start (GTK_BOX (hbox1), image1, FALSE, FALSE, 0);

  label1 = gtk_label_new_with_mnemonic (_("Use planes"));
  gtk_widget_set_name(label1, "label_head");
  gtk_widget_show (label1);
  gtk_box_pack_start (GTK_BOX (hbox1), label1, FALSE, FALSE, 0);

  scrolledPlanes = gtk_scrolled_window_new (NULL, NULL);
  gtk_widget_show (scrolledPlanes);
  gtk_box_pack_start (GTK_BOX (vBoxPlanes), scrolledPlanes, TRUE, TRUE, 0);
  gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolledPlanes), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
  gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolledPlanes), GTK_SHADOW_IN);

  treeviewPlanes = gtk_tree_view_new ();
  gtk_widget_show (treeviewPlanes);
  gtk_container_add (GTK_CONTAINER (scrolledPlanes), treeviewPlanes);
  gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (treeviewPlanes), TRUE);

  notebook = gtk_notebook_new();
  gtk_widget_show(notebook);
  gtk_box_pack_start(GTK_BOX(vBoxPlanes), notebook, FALSE, FALSE, 2);

  /* Page 1  : simple tools*/
  vbox = gtk_vbox_new(FALSE, 0);
  gtk_widget_show(vbox);
  label = gtk_label_new(_("Simple tools"));
  gtk_widget_show(label);
  gtk_notebook_append_page(GTK_NOTEBOOK(notebook), vbox, label);

  /* Hiding Mode */
  hboxHidingMode = gtk_hbox_new (FALSE, 0);
  gtk_widget_show(hboxHidingMode);
  gtk_box_pack_start(GTK_BOX(vbox), hboxHidingMode, FALSE, FALSE, 2);

  label1 = gtk_label_new(_("Hiding mode: "));
  gtk_widget_show(label1);
  gtk_box_pack_start(GTK_BOX(hboxHidingMode), label1, FALSE, FALSE, 0);

  radiobuttonHideUnion = gtk_radio_button_new(NULL);
  gtk_widget_show(radiobuttonHideUnion);
  gtk_box_pack_start(GTK_BOX(hboxHidingMode), radiobuttonHideUnion, FALSE, FALSE, 0);
  gtk_radio_button_set_group(GTK_RADIO_BUTTON(radiobuttonHideUnion), (GSList*)0);
  radiobuttonHideUnion_group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(radiobuttonHideUnion));
  gtk_tooltips_set_tip(tooltips, radiobuttonHideUnion,
                   _("Hide all elements that are hidden by al least one plane."), NULL);
  hbox1 = gtk_hbox_new (FALSE, 2);
  gtk_widget_show(hbox1);
  gtk_container_add(GTK_CONTAINER(radiobuttonHideUnion), hbox1);
  image1 = create_pixmap(mainWindow, "stock-union.png");
  gtk_widget_show(image1);
  gtk_box_pack_start(GTK_BOX(hbox1), image1, FALSE, FALSE, 0);
  label1 = gtk_label_new(_("Union"));
  gtk_widget_show(label1);
  gtk_box_pack_start(GTK_BOX(hbox1), label1, FALSE, FALSE, 0);

  radiobuttonHideInter = gtk_radio_button_new(NULL);
  gtk_widget_show(radiobuttonHideInter);
  gtk_box_pack_start(GTK_BOX(hboxHidingMode), radiobuttonHideInter, FALSE, FALSE, 0);
  gtk_radio_button_set_group(GTK_RADIO_BUTTON(radiobuttonHideInter), radiobuttonHideUnion_group);
  radiobuttonHideUnion_group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(radiobuttonHideInter));
  gtk_tooltips_set_tip(tooltips, radiobuttonHideInter,
                   _("Hide elements only if they are hidden by all planes."), NULL);
  hbox1 = gtk_hbox_new (FALSE, 2);
  gtk_widget_show(hbox1);
  gtk_container_add(GTK_CONTAINER(radiobuttonHideInter), hbox1);
  image1 = create_pixmap(mainWindow, "stock-inter.png");
  gtk_widget_show(image1);
  gtk_box_pack_start(GTK_BOX(hbox1), image1, FALSE, FALSE, 0);
  label1 = gtk_label_new(_("Intersection"));
  gtk_widget_show(label1);
  gtk_box_pack_start(GTK_BOX(hbox1), label1, FALSE, FALSE, 0);

  gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(radiobuttonHideUnion), TRUE);
  gtk_widget_set_sensitive(hboxHidingMode, FALSE);

  /* Planes parameters */
  hbox2 = gtk_hbox_new (FALSE, 0);
  gtk_widget_show (hbox2);
  gtk_box_pack_start (GTK_BOX (vbox), hbox2, FALSE, FALSE, 0);

  vbox3 = gtk_vbox_new (FALSE, 3);
  gtk_widget_show (vbox3);
  gtk_box_pack_start(GTK_BOX(hbox2), vbox3, FALSE, FALSE, 2);
  buttonRotate = gtk_button_new();
  gtk_tooltips_set_tip(tooltips, buttonRotate, _("Set the camera to look in the direction"
                                     " of the normal of the selected plane."), NULL);
  gtk_box_pack_start(GTK_BOX(vbox3), buttonRotate, TRUE, FALSE, 0);
  gtk_widget_show(buttonRotate);
  image = create_pixmap(mainWindow, "stock_rotate_20.png");
  gtk_widget_show(image);
  gtk_container_add(GTK_CONTAINER(buttonRotate), image);
  gtk_widget_set_sensitive(buttonRotate, FALSE);
  

  alignment3 = gtk_alignment_new (0.5, 0.5, 0, 0);
  gtk_widget_show (alignment3);
  gtk_box_pack_start (GTK_BOX (hbox2), alignment3, TRUE, TRUE, 0);

  vbox3 = gtk_vbox_new (FALSE, 0);
  gtk_widget_show (vbox3);
  gtk_container_add (GTK_CONTAINER (alignment3), vbox3);

  hbox4 = gtk_hbox_new (FALSE, 0);
  gtk_widget_show (hbox4);
  gtk_box_pack_start (GTK_BOX (vbox3), hbox4, TRUE, TRUE, 0);

  label2 = gtk_label_new (_("Normal: "));
  gtk_widget_show (label2);
  gtk_box_pack_start (GTK_BOX (hbox4), label2, TRUE, TRUE, 0);
  gtk_misc_set_alignment (GTK_MISC (label2), 1, 0.5);

  for (i = 0; i < 3; i++)
    {
      spinbuttonNVect_adj[i] = gtk_adjustment_new (1, -20, 20, 1, 3, 3);
      spinbuttonNVect[i] = gtk_spin_button_new (GTK_ADJUSTMENT (spinbuttonNVect_adj[i]), 1, 0);
      gtk_widget_show (spinbuttonNVect[i]);
      gtk_box_pack_start (GTK_BOX (hbox4), spinbuttonNVect[i], FALSE, FALSE, 0);
      gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (spinbuttonNVect[i]), TRUE);
    }

  hbox5 = gtk_hbox_new (FALSE, 0);
  gtk_widget_show (hbox5);
  gtk_box_pack_start (GTK_BOX (vbox3), hbox5, TRUE, TRUE, 0);

  labelDistance = gtk_label_new ("");
  if (panelConfigGet_spinBoundsValue() == 1.)
    gtk_label_set_text(GTK_LABEL(labelDistance),
                   _("Distance from origin: "));
  else
    {
      gtk_label_set_text(GTK_LABEL(labelDistance),
                   _("Dist. from origin <span style=\"italic\" size=\"smaller\""
                     " foreground=\"red\">\303\227 mult.</span>: "));
      gtk_label_set_use_markup(GTK_LABEL(labelDistance), TRUE);
    }
  gtk_widget_show (labelDistance);
  gtk_box_pack_start (GTK_BOX (hbox5), labelDistance, TRUE, TRUE, 0);
  gtk_misc_set_alignment (GTK_MISC (labelDistance), 1, 0.5);

  spinbuttonDistance_adj = gtk_adjustment_new (1, -1000, 1000, 0.25, 2, 2);
  spinbuttonDistance = gtk_spin_button_new (GTK_ADJUSTMENT (spinbuttonDistance_adj), 1, 2);
  gtk_widget_show (spinbuttonDistance);
  gtk_box_pack_start (GTK_BOX (hbox5), spinbuttonDistance, FALSE, FALSE, 0);
  gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (spinbuttonDistance), TRUE);

  hbox3 = gtk_hbox_new (FALSE, 0);
  gtk_widget_show (hbox3);
  gtk_box_pack_start (GTK_BOX (vbox3), hbox3, TRUE, TRUE, 0);

  label4 = gtk_label_new (_("Color: "));
  gtk_widget_show (label4);
  gtk_box_pack_start (GTK_BOX (hbox3), label4, TRUE, TRUE, 0);
  gtk_misc_set_alignment (GTK_MISC (label4), 1, 0.5);

  widgetColorPlane = colorComboBox_new(TRUE);
  gtk_widget_show(widgetColorPlane);
  gtk_box_pack_start(GTK_BOX(hbox3), widgetColorPlane, FALSE, FALSE, 0);


  alignment2 = gtk_alignment_new (0.5, 0.5, 1, 0);
  gtk_widget_show (alignment2);
  gtk_box_pack_start (GTK_BOX (hbox2), alignment2, FALSE, FALSE, 0);

  vbox2 = gtk_vbox_new (FALSE, 2);
  gtk_widget_show (vbox2);
  gtk_container_add (GTK_CONTAINER (alignment2), vbox2);
/*   gtk_container_set_border_width (GTK_CONTAINER (vbox2), 3); */

  buttonPlaneAdd = gtk_button_new ();
  gtk_widget_show (buttonPlaneAdd);
  gtk_box_pack_start (GTK_BOX (vbox2), buttonPlaneAdd, FALSE, FALSE, 0);

  image2 = gtk_image_new_from_stock ("gtk-add", GTK_ICON_SIZE_BUTTON);
  gtk_widget_show (image2);
  gtk_container_add (GTK_CONTAINER (buttonPlaneAdd), image2);

  buttonPlaneRemove = gtk_button_new ();
  gtk_widget_show (buttonPlaneRemove);
  gtk_box_pack_start (GTK_BOX (vbox2), buttonPlaneRemove, FALSE, FALSE, 0);

  image4 = gtk_image_new_from_stock ("gtk-remove", GTK_ICON_SIZE_BUTTON);
  gtk_widget_show (image4);
  gtk_container_add (GTK_CONTAINER (buttonPlaneRemove), image4);

  /* Page   : advanced tools*/
  vboxDistChange = gtk_vbox_new(FALSE, 0);
  gtk_widget_set_sensitive(vboxDistChange, FALSE);
  gtk_widget_show(vboxDistChange);
  label = gtk_label_new(_("Advanced tools"));
  gtk_widget_show(label);
  gtk_notebook_append_page(GTK_NOTEBOOK(notebook), vboxDistChange, label);

  label = gtk_label_new(_("Change selected plane distance"));
  gtk_misc_set_alignment(GTK_MISC(label), 0., 0.5);
  gtk_widget_show(label);
  gtk_box_pack_start(GTK_BOX(vboxDistChange), label, FALSE, FALSE, 3);
  hbox = gtk_hbox_new(FALSE, 0);
  gtk_widget_show(hbox);

  gtk_box_pack_start(GTK_BOX(vboxDistChange), hbox, FALSE, FALSE, 0);
  label = gtk_label_new(_("From: "));
  gtk_misc_set_alignment(GTK_MISC(label), 1., 0.5);
  gtk_widget_show(label);
  gtk_box_pack_start(GTK_BOX(hbox), label, TRUE, TRUE, 0);
  entryDistFrom = numericalEntry_new(0.);
  gtk_entry_set_width_chars(GTK_ENTRY(entryDistFrom), 7);
  gtk_widget_show(entryDistFrom);
  gtk_box_pack_start(GTK_BOX(hbox), entryDistFrom, FALSE, FALSE, 0);
  label = gtk_label_new(_("to: "));
  gtk_misc_set_alignment(GTK_MISC(label), 1., 0.5);
  gtk_widget_show(label);
  gtk_box_pack_start(GTK_BOX(hbox), label, TRUE, TRUE, 0);
  entryDistTo = numericalEntry_new(0.);
  gtk_entry_set_width_chars(GTK_ENTRY(entryDistTo), 7);
  gtk_widget_show(entryDistTo);
  gtk_box_pack_start(GTK_BOX(hbox), entryDistTo, FALSE, FALSE, 0);
  label = gtk_label_new(_("step: "));
  gtk_misc_set_alignment(GTK_MISC(label), 1., 0.5);
  gtk_widget_show(label);
  gtk_box_pack_start(GTK_BOX(hbox), label, TRUE, TRUE, 0);
  entryDistStep = numericalEntry_new(1.);
  gtk_entry_set_width_chars(GTK_ENTRY(entryDistStep), 7);
  gtk_widget_show(entryDistStep);
  gtk_box_pack_start(GTK_BOX(hbox), entryDistStep, FALSE, FALSE, 0);

  hbox = gtk_hbox_new(FALSE, 0);
  gtk_widget_show(hbox);
  gtk_box_pack_start(GTK_BOX(vboxDistChange), hbox, FALSE, FALSE, 0);
  label = gtk_label_new (_("Play at "));
  gtk_widget_show(label);
  gtk_box_pack_start(GTK_BOX(hbox), label, TRUE, TRUE, 0);
  gtk_misc_set_alignment(GTK_MISC(label), 1., 0.5);
  spinDistDelay = gtk_spin_button_new_with_range(10, 10000, 25);
  gtk_spin_button_set_value(GTK_SPIN_BUTTON(spinDistDelay), 500.);
  gtk_widget_show(spinDistDelay);
  gtk_box_pack_start(GTK_BOX(hbox), spinDistDelay, FALSE, TRUE, 0);
  gtk_spin_button_set_numeric(GTK_SPIN_BUTTON(spinDistDelay), TRUE);
  label = gtk_label_new(_(" ms"));
  gtk_widget_show(label);
  gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
  gtk_misc_set_alignment(GTK_MISC(label), 0., 0.5);
  buttonDistPlayStop = gtk_button_new();
  gtk_tooltips_set_tip(tooltips, buttonDistPlayStop,
                   _("Change the distance parameter of he selected file"
                   " at the given rate."), NULL);
  gtk_widget_show(buttonDistPlayStop);
  gtk_box_pack_start(GTK_BOX(hbox), buttonDistPlayStop, FALSE, FALSE, 15);
  hbox1 = gtk_hbox_new(FALSE, 0);
  gtk_widget_show(hbox1);
  gtk_container_add(GTK_CONTAINER(buttonDistPlayStop), hbox1);
  imageDistPlay = create_pixmap(mainWindow, "stock_media-play.png");
  gtk_widget_show(imageDistPlay);
  gtk_box_pack_start(GTK_BOX(hbox1), imageDistPlay, TRUE, TRUE, 0);
  imageDistStop = create_pixmap(mainWindow, "stock_media-stop.png");
  gtk_box_pack_start(GTK_BOX(hbox1), imageDistStop, TRUE, TRUE, 0);

  /* The IO tab. */
  vboxIO = gtk_vbox_new(FALSE, 0);
  gtk_widget_show(vboxIO);
  label = gtk_label_new(_("File tools"));
  gtk_widget_show(label);
  gtk_notebook_append_page(GTK_NOTEBOOK(notebook), vboxIO, label);
  
  hbox = gtk_hbox_new(FALSE, 0);
  gtk_widget_show(hbox);
  gtk_box_pack_start(GTK_BOX(vboxIO), hbox, FALSE, FALSE, 0);
  label = gtk_label_new(_("Load a plane list:"));
  gtk_widget_show(label);
  gtk_box_pack_start(GTK_BOX(hbox), label, TRUE, TRUE, 0);
  gtk_misc_set_alignment(GTK_MISC(label), 0., 0.5);
  button = gtk_button_new_from_stock(GTK_STOCK_OPEN);
  gtk_widget_show(button);
  gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
  g_signal_connect(G_OBJECT(button), "clicked",
               G_CALLBACK(onPlaneListOpen), (gpointer)0);

  label = gtk_label_new(_("Current loaded list:"));
  gtk_widget_show(label);
  gtk_box_pack_start(GTK_BOX(vboxIO), label, TRUE, TRUE, 0);
  gtk_misc_set_alignment(GTK_MISC(label), 0., 0.5);

  labelPlaneList = gtk_label_new("");
  gtk_label_set_use_markup(GTK_LABEL(labelPlaneList), TRUE);
  gtk_label_set_markup(GTK_LABEL(labelPlaneList), PANEL_PLANES_NO_PLANE_LIST);
  gtk_widget_show(labelPlaneList);
  gtk_box_pack_start(GTK_BOX(vboxIO), labelPlaneList, TRUE, TRUE, 0);
  gtk_misc_set_alignment(GTK_MISC(labelPlaneList), 0., 0.5);
#if GTK_MINOR_VERSION > 5
  gtk_label_set_ellipsize(GTK_LABEL(labelPlaneList), PANGO_ELLIPSIZE_START);
#endif

  hboxSaveList = gtk_hbox_new(FALSE, 0);
  gtk_widget_set_sensitive(hboxSaveList, FALSE);
  gtk_widget_show(hboxSaveList);
  gtk_box_pack_start(GTK_BOX(vboxIO), hboxSaveList, FALSE, FALSE, 0);
  alignment2 = gtk_alignment_new(1., 0.5, 0, 0);
  gtk_widget_show(alignment2);
  gtk_box_pack_start(GTK_BOX(hboxSaveList), alignment2, TRUE, TRUE, 0);
  buttonSaveList = gtk_button_new_from_stock(GTK_STOCK_SAVE);
  gtk_widget_set_sensitive(buttonSaveList, FALSE);
  gtk_widget_show(buttonSaveList);
  gtk_container_add(GTK_CONTAINER(alignment2), buttonSaveList);
  g_signal_connect(G_OBJECT(buttonSaveList), "clicked",
               G_CALLBACK(onPlaneListSave), (gpointer)0);
  button = gtk_button_new_from_stock(GTK_STOCK_SAVE_AS);
  gtk_widget_show(button);
  gtk_box_pack_start(GTK_BOX(hboxSaveList), button, FALSE, FALSE, 0);
  g_signal_connect(G_OBJECT(button), "clicked",
               G_CALLBACK(onPlaneListSaveAs), (gpointer)0);

  /* Add the callback methods. */
  g_signal_connect(G_OBJECT(checkUsePlanes), "toggled",
               G_CALLBACK(onPlaneUsed), (gpointer)0);

  g_signal_connect(G_OBJECT(buttonPlaneAdd), "clicked",
               G_CALLBACK(onPlaneAdd), (gpointer)0);
  g_signal_connect(G_OBJECT(buttonPlaneRemove), "clicked",
               G_CALLBACK(onPlaneRemove), (gpointer)0);

  for (i = 0; i < 3; i++)
    g_signal_connect(G_OBJECT(spinbuttonNVect[i]), "value-changed",
                 G_CALLBACK(onSpinNVectChange), GINT_TO_POINTER(i));

  g_signal_connect(G_OBJECT(spinbuttonDistance), "value-changed",
               G_CALLBACK(onSpinDistanceChange), (gpointer)0);

  g_signal_connect(G_OBJECT(widgetColorPlane), "color-selected",
               G_CALLBACK(onPlaneColorChange), (gpointer)0);

  g_signal_connect(G_OBJECT(visu), "dataNew",
               G_CALLBACK(onNewFileLoaded), (gpointer)0);

  g_signal_connect(gtk_tree_view_get_selection(GTK_TREE_VIEW(treeviewPlanes)),
               "changed", G_CALLBACK(onTreeSelectionChanged), (gpointer)0);

  g_signal_connect(G_OBJECT(buttonRotate), "clicked",
               G_CALLBACK(onSetCameraPosition), (gpointer)0);

  g_signal_connect(G_OBJECT(visuGtkObject), "spinBoundsChanged",
               G_CALLBACK(onSpinBoundsChangeDistance), (gpointer)0);

  g_signal_connect(G_OBJECT(radiobuttonHideUnion), "toggled",
               G_CALLBACK(onGtkPlanesHidingModeToggled), GINT_TO_POINTER(plane_hideUnion));
  g_signal_connect(G_OBJECT(radiobuttonHideInter), "toggled",
               G_CALLBACK(onGtkPlanesHidingModeToggled), GINT_TO_POINTER(plane_hideInter));

  g_signal_connect(G_OBJECT(buttonDistPlayStop), "clicked",
               G_CALLBACK(onPlayStopDist), (gpointer)0);
  g_signal_connect(G_OBJECT(spinDistDelay), "value-changed",
               G_CALLBACK(onSpinDistDelayChange), (gpointer)0);

  /* Render the associated tree */
  renderer = gtk_cell_renderer_toggle_new ();
  g_signal_connect(G_OBJECT(renderer), "toggled",
               G_CALLBACK(onGtkPlanesDrawnToggled), (gpointer)0);
  column = gtk_tree_view_column_new_with_attributes (_("Drawn"),
                                         renderer,
                                         "active", COLUMN_PLANE_DRAWN,
                                         NULL);
  gtk_tree_view_append_column (GTK_TREE_VIEW(treeviewPlanes), column);
  renderer = gtk_cell_renderer_text_new ();
  column = gtk_tree_view_column_new_with_attributes (_("Parameters"),
                                         renderer,
                                         "markup", COLUMN_PLANE_LABEL,
                                         NULL);
  gtk_tree_view_column_set_expand(column, TRUE);
  gtk_tree_view_column_set_alignment(column, 0.5);
  gtk_tree_view_append_column (GTK_TREE_VIEW (treeviewPlanes), column);
  renderer = gtk_cell_renderer_toggle_new ();
  g_signal_connect(G_OBJECT(renderer), "toggled",
               G_CALLBACK(onGtkPlanesHideToggled), GINT_TO_POINTER(0));
  column = gtk_tree_view_column_new_with_attributes (_("Mask"),
                                         renderer,
                                         "active", COLUMN_PLANE_HIDE_IS_ON,
                                         NULL);
  gtk_tree_view_append_column (GTK_TREE_VIEW(treeviewPlanes), column);
  renderer = gtk_cell_renderer_toggle_new ();
  g_signal_connect(G_OBJECT(renderer), "toggled",
               G_CALLBACK(onGtkPlanesHideToggled), GINT_TO_POINTER(1));
  column = gtk_tree_view_column_new_with_attributes (_("Invert"),
                                         renderer,
                                         "active", COLUMN_PLANE_HIDDEN_SIDE,
                                         NULL);
  gtk_tree_view_append_column (GTK_TREE_VIEW(treeviewPlanes), column);
  renderer = gtk_cell_renderer_pixbuf_new ();
  column = gtk_tree_view_column_new_with_attributes (_("Color"),
                                         renderer,
                                         "pixbuf", COLUMN_PLANE_COLOR_PIXBUF,
                                         NULL);
  gtk_tree_view_append_column (GTK_TREE_VIEW(treeviewPlanes), column);

  gtk_tree_selection_set_mode(gtk_tree_view_get_selection(GTK_TREE_VIEW(treeviewPlanes)),
                        GTK_SELECTION_SINGLE);
  gtk_tree_view_set_model(GTK_TREE_VIEW(treeviewPlanes), GTK_TREE_MODEL(listStoredPlanes));

  gtk_container_add(GTK_CONTAINER(panelPlanes), vBoxPlanes);
}

GList* getListOfAllPlanes(gboolean maskingPlanesOnly)
{
  GList *planeList;
  GtkTreeIter iter;
  Plane *plane;
  
  DBG_fprintf(stderr, "Panel Plane : building plane list...\n");
  /* Build the list of all planes. */
  planeList = (GList*)0;
  if (gtk_tree_model_get_iter_first(GTK_TREE_MODEL(listStoredPlanes), &iter))
    do
      {
      gtk_tree_model_get(GTK_TREE_MODEL(listStoredPlanes),
                     &iter, COLUMN_PLANE_POINTER, &plane, -1);
      /* Because the get action increase the counter... */
      g_object_unref(G_OBJECT(plane));
      if (!maskingPlanesOnly || (planeGet_hiddenState(plane) != PLANE_SIDE_NONE))
        {
          planeList = g_list_append(planeList, plane);
          DBG_fprintf(stderr, " | found one plane %p.\n", (gpointer)plane);
        }
      }
    while (gtk_tree_model_iter_next(GTK_TREE_MODEL(listStoredPlanes), &iter));

  return planeList;
}

static void onAskForHideNodes(VisuData *visuData, gboolean *redraw, gpointer data)
{
  GList *listOfPlanes;

  if (!checkUsePlanes || !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(checkUsePlanes)))
    return;

  DBG_fprintf(stderr, "Panel Planes : caught the 'NodeAskForShowHide' signal for"
            " VisuData %p.\n", (gpointer)visuData);
  listOfPlanes = getListOfAllPlanes(TRUE);
  if (listOfPlanes)
    {
      *redraw = planeShowHide_all(visuData, listOfPlanes) || *redraw;
      g_list_free(listOfPlanes);
    }
}
gboolean panelPlanesSet_use(VisuData *dataObj, gboolean value)
{
  int val;
  GtkTreeIter iter;

  if (extensionPlanes->used == value)
    return FALSE;

  extensionPlanes->used = value;
  
  if (!isPlanesInitialised)
    createAndInitPlanePanel(dataObj);

  /* Test if any planes are stored. */
  if (!gtk_tree_model_get_iter_first(GTK_TREE_MODEL(listStoredPlanes), &iter))
    return FALSE;

  val = panelPlanesApply_hidingScheme(dataObj);

  return (gboolean)val;
}
void onPlaneUsed(GtkToggleButton *button, gpointer data)
{
  VisuData *dataObj;
  gboolean res;

  dataObj = toolPanelGet_visuData(TOOL_PANEL(panelPlanes));

  res = panelPlanesSet_use(dataObj, gtk_toggle_button_get_active(button));
  if (res)
    visuData_createAllNodes(dataObj);

  g_signal_emit (visu, VISU_GET_CLASS (visu)->OpenGLAskForReDraw_signal_id,
             0 /* details */,
             NULL);
}
void onPlaneAdd(GtkButton *button, gpointer userData)
{
  Plane* plane;
  float vect[3];
  int i;
  GtkTreeIter iter;
  Color *color;
  gchar str[256];
  float dist;
  GdkPixbuf *pixbufColorAlphaBox;
  VisuData *dataObj;

  dataObj = toolPanelGet_visuData(TOOL_PANEL(panelPlanes));

  pixbufColorAlphaBox = colorComboBoxGet_selectedPixbuf(COLOR_COMBOX(widgetColorPlane));
  color = colorComboBoxGet_selectedColor(COLOR_COMBOX(widgetColorPlane));
  for (i = 0; i < 3; i++)
    vect[i] = (float)gtk_spin_button_get_value(GTK_SPIN_BUTTON(spinbuttonNVect[i]));
  dist = (float)gtk_spin_button_get_value(GTK_SPIN_BUTTON(spinbuttonDistance));
  plane = planeNew(visuDataGet_openGLView(dataObj), vect, dist, color);
  
  /* String used to labelled planes, dist. means 'distance' and
     norm. means 'normal' (50 chars max). */
  sprintf(str, LABEL_PLANE, (int)vect[0], (int)vect[1], (int)vect[2], dist);
  gtk_list_store_append(listStoredPlanes, &iter);
  gtk_list_store_set(listStoredPlanes, &iter,
                 COLUMN_PLANE_DRAWN, planeGet_rendered(plane),
                 COLUMN_PLANE_LABEL, str,
                 COLUMN_PLANE_HIDE_IS_ON, FALSE,
                 COLUMN_PLANE_HIDDEN_SIDE, FALSE,
                 COLUMN_PLANE_COLOR_PIXBUF, (gpointer)pixbufColorAlphaBox,
                 COLUMN_PLANE_POINTER, (gpointer)plane,
                 -1);
  
  /* We count down the counter on plane since it has been added to the list. */
  g_object_unref(G_OBJECT(plane));

  rebuildListPlanes((VisuData*)dataObj);
  gtk_tree_selection_select_iter(gtk_tree_view_get_selection(GTK_TREE_VIEW(treeviewPlanes)), &iter);
  if (gtk_tree_model_iter_n_children(GTK_TREE_MODEL(listStoredPlanes), (GtkTreeIter*)0) > 1)
    gtk_widget_set_sensitive(hboxHidingMode, TRUE);
  if (extensionPlanes->used)
    g_signal_emit (visu, VISU_GET_CLASS (visu)->OpenGLAskForReDraw_signal_id,
               0 /* details */,
               NULL);
}
void onPlaneRemove(GtkButton *button, gpointer data)
{
  gboolean res;
  GtkTreeModel *tmpList;
  GtkTreeIter iter;
  int val;
  VisuData *dataObj;

  DBG_fprintf(stderr, "Panel Plane : removing plane...\n");
  res = gtk_tree_selection_get_selected(gtk_tree_view_get_selection(GTK_TREE_VIEW(treeviewPlanes)),
                              &tmpList, &iter);
  if (res)
    {
      dataObj = toolPanelGet_visuData(TOOL_PANEL(panelPlanes));

      res = TRUE;
      if (!gtk_list_store_remove(GTK_LIST_STORE(listStoredPlanes), &iter))
      res = gtk_tree_model_get_iter_first(GTK_TREE_MODEL(listStoredPlanes), &iter);

      DBG_fprintf(stderr, "Panel Plane : OK plane found and removed.\n");

      if (gtk_tree_model_iter_n_children(GTK_TREE_MODEL(listStoredPlanes), (GtkTreeIter*)0) < 2)
      gtk_widget_set_sensitive(hboxHidingMode, FALSE);

      rebuildListPlanes((VisuData*)dataObj);
      /* If extension is not used, we leave here. */
      if (!extensionPlanes->used)
      return;

      /* Modify nodes visibility accordingly. */
      val = panelPlanesApply_hidingScheme(dataObj);
      if (val)
      visuData_createAllNodes(dataObj);
      if (extensionPlanes->used)
      g_signal_emit (visu, VISU_GET_CLASS (visu)->OpenGLAskForReDraw_signal_id,
                   0 /* details */,
                   NULL);

      if (res)
      gtk_tree_selection_select_iter(gtk_tree_view_get_selection(GTK_TREE_VIEW(treeviewPlanes)),
                               &iter);
    }
}
void onSpinNVectChange(GtkSpinButton *spin, gpointer data)
{
  gboolean res;
  GtkTreeModel *tmpList;
  GtkTreeIter iter;
  Plane *plane;
  char str[256];
  float dist;
  float vect[3];
  gboolean hide, side;
  int i;
  int val;
  VisuData *dataObj;

  i = GPOINTER_TO_INT(data);
  if (i < 0 || i > 2)
    return;

  /* Get the VisuData to deal with. */
  dataObj = toolPanelGet_visuData(TOOL_PANEL(panelPlanes));

  res = gtk_tree_selection_get_selected(gtk_tree_view_get_selection(GTK_TREE_VIEW(treeviewPlanes)),
                              &tmpList, &iter);
  if (res)
    {
      plane = (Plane*)0;
      hide = FALSE;
      side = FALSE;
      gtk_tree_model_get(GTK_TREE_MODEL(listStoredPlanes), &iter,
                   COLUMN_PLANE_POINTER, &plane,
                   COLUMN_PLANE_HIDE_IS_ON, &hide,
                   COLUMN_PLANE_HIDDEN_SIDE, &side,
                   -1);
      if (plane)
      {
        /* Because the get action increase the counter... */
        g_object_unref(G_OBJECT(plane));

        planeGet_nVectUser(plane, vect);
        vect[i] = (float)gtk_spin_button_get_value(spin);
        val = planeSet_normalVector(plane, vect);
        if (val < 0)
          {
            fprintf(stderr, "WARNING! Something goes wrong when assigning"
                  " the new normal vector : (%f; %f; %f).\n",
                  vect[0], vect[1], vect[2]);
            planeGet_nVectUser(plane, vect);
            for (i = 0; i < 3; i++)
            gtk_spin_button_set_value(GTK_SPIN_BUTTON(spinbuttonNVect[i]), vect[i]);
            return;
          }
        else if (val == 0)
          return;
        planeComputeInter(plane, visuDataGet_openGLView(dataObj));
        planeGet_distanceFromOrigin(plane, &dist);
        sprintf(str, LABEL_PLANE,
              (int)vect[0], (int)vect[1], (int)vect[2], dist);
        gtk_list_store_set(listStoredPlanes, &iter, COLUMN_PLANE_LABEL, str, -1);
        /* Redraw all planes. */
        rebuildListPlanes((VisuData*)dataObj);
        /* If extension is not used, we leave here. */
        if (!extensionPlanes->used)
          return;

        /* Need to modify the nodes visibility only if the current
           plane use the masking function (hiddenState != PLANE_SIDE_NONE). */
        if (planeGet_hiddenState(plane) != PLANE_SIDE_NONE)
          {
            /* Modify nodes visibility accordingly. */
            val = panelPlanesApply_hidingScheme(dataObj);
            if (val)
            visuData_createAllNodes(dataObj);
          }
        if (extensionPlanes->used)
          g_signal_emit (visu, VISU_GET_CLASS (visu)->OpenGLAskForReDraw_signal_id,
                     0 /* details */,
                     NULL);
      }
    }
}
void onSpinDistanceChange(GtkSpinButton *spin, gpointer data)
{
  gboolean res;
  GtkTreeModel *tmpList;
  GtkTreeIter iter;
  Plane *plane;
  char str[256];
  float dist, mult;
  float vect[3];
  gboolean hide, side;
  int val;
  VisuData *dataObj;

  /* Get the VisuData to deal with. */
  dataObj = toolPanelGet_visuData(TOOL_PANEL(panelPlanes));

  res = gtk_tree_selection_get_selected(gtk_tree_view_get_selection(GTK_TREE_VIEW(treeviewPlanes)),
                              &tmpList, &iter);
  if (res)
    {
      plane = (Plane*)0;
      hide = FALSE;
      side = FALSE;
      gtk_tree_model_get(GTK_TREE_MODEL(listStoredPlanes), &iter,
                   COLUMN_PLANE_POINTER, &plane,
                   COLUMN_PLANE_HIDE_IS_ON, &hide,
                   COLUMN_PLANE_HIDDEN_SIDE, &side,
                   -1);
      if (plane)
      {
        /* Because the get action increase the counter... */
        g_object_unref(G_OBJECT(plane));

        mult = panelConfigGet_spinBoundsValue();
        dist = (float)gtk_spin_button_get_value(spin);
        val = planeSet_distanceFromOrigin(plane, dist * mult);
        if (val < 0)
          {
            fprintf(stderr, "WARNING! Something goes wrong when assigning"
                  " the new distance from origin : %f.\n",
                  dist);
            gtk_spin_button_set_value(GTK_SPIN_BUTTON(spinbuttonDistance), 0.);
            return;
          }
        else if (val == 0)
          return;
        planeComputeInter(plane, visuDataGet_openGLView(dataObj));
        planeGet_nVectUser(plane, vect);
        sprintf(str, LABEL_PLANE,
              (int)vect[0], (int)vect[1], (int)vect[2], dist);
        gtk_list_store_set(listStoredPlanes, &iter, COLUMN_PLANE_LABEL, str, -1);
        /* Redraw all planes. */
        rebuildListPlanes((VisuData*)dataObj);
        /* If extension is not used, we leave here. */
        if (!extensionPlanes->used)
          return;

        /* Need to modify the nodes visibility only if the current
           plane use the masking function (hiddenState != PLANE_SIDE_NONE). */
        if (planeGet_hiddenState(plane) != PLANE_SIDE_NONE)
          {
            /* Modify nodes visibility accordingly. */
            val = panelPlanesApply_hidingScheme(dataObj);
            if (val)
            visuData_createAllNodes(dataObj);
          }
        if (extensionPlanes->used)
          g_signal_emit (visu, VISU_GET_CLASS (visu)->OpenGLAskForReDraw_signal_id,
                     0 /* details */,
                     NULL);
      }
    }
}
void onSpinBoundsChangeDistance(GObject *obj, gfloat mult, gpointer data)
{
  DBG_fprintf(stderr, "Panel Plane : catch the 'spinBoundsChanged' signal,"
            " should adjust the distance from origin (multiplier : %f).\n", mult);

  if (panelConfigGet_spinBoundsValue() == 1.)
    gtk_label_set_text(GTK_LABEL(labelDistance),
                   _("Distance from origin: "));
  else
    {
      gtk_label_set_text(GTK_LABEL(labelDistance),
                   _("Dist. from origin <span style=\"italic\" size=\"smaller\""
                     " foreground=\"red\">\303\227 mult.</span>: "));
      gtk_label_set_use_markup(GTK_LABEL(labelDistance), TRUE);
    }
}
void onPlaneColorChange(ColorComboBox *combo, Color *color, gpointer data)
{
  gboolean res;
  GtkTreeModel *tmpList;
  GtkTreeIter iter;
  Plane *plane;
  int val;
  GdkPixbuf *pixbufColorAlphaBox;
  VisuData *dataObj;

  /* Get the VisuData to deal with. */
  dataObj = toolPanelGet_visuData(TOOL_PANEL(panelPlanes));

  DBG_fprintf(stderr, "Panel Plane : Catch the 'color-selected' signal.\n");

  pixbufColorAlphaBox = colorComboBoxGet_selectedPixbuf(combo);

  /* Get the plane */
  res = gtk_tree_selection_get_selected(gtk_tree_view_get_selection(GTK_TREE_VIEW(treeviewPlanes)),
                              &tmpList, &iter);
  if (!res)
    return;
  plane = (Plane*)0;
  gtk_tree_model_get(GTK_TREE_MODEL(listStoredPlanes), &iter, COLUMN_PLANE_POINTER, &plane, -1);
  if (!plane)
    return;

  /* Because the get action increase the counter... */
  g_object_unref(G_OBJECT(plane));

  /* Change the color value. */
  val = planeSet_color(plane, color);
  if (val < 0)
    {
      fprintf(stderr, "WARNING! Something goes wrong when assigning"
            " the new color : %p.\n", (gpointer)color);
      return;
    }
  else if (val == 0)
    return;

  DBG_fprintf(stderr, "Panel Plane : color combobox changed to %p (%f,%f,%f,%f).\n",
            (gpointer)color, color->rgba[0], color->rgba[1], color->rgba[2], color->rgba[3]);
  DBG_fprintf(stderr, "Panel Plane : Changed color (%p) for plane : %p.\n",
            (gpointer)color, (gpointer)plane);

  gtk_list_store_set(listStoredPlanes, &iter, COLUMN_PLANE_COLOR_PIXBUF, pixbufColorAlphaBox, -1);
  rebuildListPlanes(dataObj);
  if (extensionPlanes->used)
    g_signal_emit (visu, VISU_GET_CLASS (visu)->OpenGLAskForReDraw_signal_id,
               0 /* details */,
               NULL);
}

static void onDataReadyForRendering(GObject *obj, VisuData *dataObj, gpointer data)
{
  GList *list, *tmplst;
  int val;
  gboolean needShowHide;
  OpenGLView *view;

  DBG_fprintf(stderr, "Panel Plane : caught 'dataReadyForRendering' signal\n"
            " | setting sensitivity.\n");
  if (dataObj)
    gtk_widget_set_sensitive(vBoxPlanes, TRUE);
  else
    gtk_widget_set_sensitive(vBoxPlanes, FALSE);

  if (!extensionPlanes->used)
    return;

  DBG_fprintf(stderr, " | recalculating intersections and masking set.\n");

  view = visuDataGet_openGLView(dataObj);
  g_return_if_fail(view);

  needShowHide = FALSE;
  list = getListOfAllPlanes(FALSE);
  tmplst = list;
  while (tmplst)
    {
      /* Compute the intersection with the new box */
      planeComputeInter((Plane*)tmplst->data, view);
      /* Test if one of the plane at least need to mask some nodes. */
      needShowHide = needShowHide ||
      (planeGet_hiddenState((Plane*)tmplst->data) != PLANE_SIDE_NONE);
      tmplst = g_list_next(tmplst);
    }
  /* Compute the masking state */
  if (needShowHide)
    val = panelPlanesApply_hidingScheme(dataObj);
  g_list_free(list);
  rebuildListPlanes((VisuData*)dataObj);
}

void onNewFileLoaded(GObject *obj, VisuData *dataObj, gpointer data)
{
  DBG_fprintf(stderr, "Panel Plane : caught 'dataNew' signal,"
            " connecting local signals.\n");
  
  onAskForHide_signal_id =
    g_signal_connect(G_OBJECT(dataObj), "NodeAskForShowHide",
                 G_CALLBACK(onAskForHideNodes), (gpointer)0);
  g_signal_connect(G_OBJECT(dataObj), "NodePositionChanged",
               G_CALLBACK(onNodePositionChanged), (gpointer)0);
}

void onNodePositionChanged(VisuData *dataObj, gpointer data)
{
  GList *list;
  gboolean needShowHide;

  DBG_fprintf(stderr, "Panel Plane : catch 'NodePositionChanged' signal,"
            " recalculating masking properties.\n");

  needShowHide = FALSE;
  list = getListOfAllPlanes(TRUE);
  if (list)
    panelPlanesApply_hidingScheme(dataObj);
  g_list_free(list);
/*   rebuildListPlanes((VisuData*)dataObj); */
}


void onTreeSelectionChanged(GtkTreeSelection *tree, gpointer data)
{
  gboolean res;
  GtkTreeModel *tmpList;
  GtkTreeIter iter;
  Plane *plane;
  float val, nPlane[3], dist, mult;
  int i;
  Color *colorPlane, *colorCombo;

  DBG_fprintf(stderr, "Panel Plane : catch 'changed' signal from "
            " the gtkTreeSelection.\n");

  res = gtk_tree_selection_get_selected(tree, &tmpList, &iter);
  if (res)
    {
      plane = (Plane*)0;
      gtk_tree_model_get(GTK_TREE_MODEL(listStoredPlanes), &iter,
                   COLUMN_PLANE_POINTER, &plane,
                   -1);
      /* Because the get action increase the counter... */
      g_object_unref(G_OBJECT(plane));

      planeGet_nVectUser(plane, nPlane);
      for (i = 0; i < 3; i++)
      {
        val = gtk_spin_button_get_value(GTK_SPIN_BUTTON(spinbuttonNVect[i]));
        if (val != nPlane[i])
          gtk_spin_button_set_value(GTK_SPIN_BUTTON(spinbuttonNVect[i]), nPlane[i]);
      }
      planeGet_distanceFromOrigin(plane, &dist);
      mult = panelConfigGet_spinBoundsValue();
      val = gtk_spin_button_get_value(GTK_SPIN_BUTTON(spinbuttonDistance));
      if (val != dist / mult)
      gtk_spin_button_set_value(GTK_SPIN_BUTTON(spinbuttonDistance), dist / mult);
      planeGet_color(plane, &colorPlane);
      colorCombo = colorComboBoxGet_selectedColor(COLOR_COMBOX(widgetColorPlane));
      if (colorPlane != colorCombo)
      colorComboBoxSet_selectionByColor(COLOR_COMBOX(widgetColorPlane), colorPlane);

      gtk_widget_set_sensitive(buttonRotate, TRUE);
      gtk_widget_set_sensitive(vboxDistChange, TRUE);
      gtk_widget_set_sensitive(hboxSaveList, TRUE);
    }
  else
    {
      gtk_widget_set_sensitive(buttonRotate, FALSE);
      gtk_widget_set_sensitive(vboxDistChange, FALSE);
      gtk_widget_set_sensitive(hboxSaveList, FALSE);
    }
}

void onSetCameraPosition(GtkButton *button, gpointer data)
{
  gboolean res;
  GtkTreeModel *tmpList;
  GtkTreeIter iter;
  float spherical[3];
  Plane *plane;
  float nPlane[3];

  res = gtk_tree_selection_get_selected(gtk_tree_view_get_selection(GTK_TREE_VIEW(treeviewPlanes)),
                              &tmpList, &iter);
  if (res)
    {
      plane = (Plane*)0;
      gtk_tree_model_get(GTK_TREE_MODEL(listStoredPlanes), &iter,
                   COLUMN_PLANE_POINTER, &plane,
                   -1);
      /* Because the get action increase the counter... */
      g_object_unref(G_OBJECT(plane));

      DBG_fprintf(stderr, "Panel Planes : Set the camera position to be"
              " normal to the selected plane (%p).\n", (gpointer)plane);
      planeGet_nVectUser(plane, nPlane);
      matrix_cartesianToSpherical(spherical, nPlane);
      visuDataSet_angleOfView(toolPanelGet_visuData(TOOL_PANEL(panelPlanes)),
                        spherical[1], spherical[2], 0.,
                       MASK_THETA | MASK_PHI);
      g_signal_emit (visu, VISU_GET_CLASS (visu)->OpenGLAskForReDraw_signal_id,
                 0 , NULL);
    }
}
void onGtkPlanesDrawnToggled(GtkCellRendererToggle *cell_renderer,
                       gchar *path, gpointer user_data)
{
  gboolean validIter, rendered;
  GtkTreeIter iter;
  Plane *plane;

  validIter = gtk_tree_model_get_iter_from_string(GTK_TREE_MODEL(listStoredPlanes), &iter, path);
  if (!validIter)
    {
      fprintf(stderr, "INTERNAL ERROR! Wrong 'path' argument in"
            " 'onGtkPlanesDrawnToggled' method.\n");
      return;
    }
  gtk_tree_model_get(GTK_TREE_MODEL(listStoredPlanes), &iter,
                 COLUMN_PLANE_POINTER, &plane, -1);
  rendered = planeGet_rendered(plane);
  planeSet_rendered(plane, !rendered);
  gtk_list_store_set(listStoredPlanes, &iter,
                 COLUMN_PLANE_DRAWN, !rendered, -1);
  DBG_fprintf(stderr, "Panel planes : use state (%d) for plane at path '%s'.\n",
            !rendered, path);

  rebuildListPlanes(toolPanelGet_visuData(TOOL_PANEL(panelPlanes)));
  if (extensionPlanes->used)
    g_signal_emit (visu, VISU_GET_CLASS (visu)->OpenGLAskForReDraw_signal_id,
               0 /* details */,
               NULL);
}
void onGtkPlanesHideToggled(GtkCellRendererToggle *cell_renderer,
                      gchar *path, gpointer user_data)
{
  gboolean validIter, checked, side;
  GtkTreeIter iter;
  int val;
  Plane *plane;
  VisuData *dataObj;

  validIter = gtk_tree_model_get_iter_from_string(GTK_TREE_MODEL(listStoredPlanes), &iter, path);
  if (!validIter)
    {
      fprintf(stderr, "INTERNAL ERROR! Wrong 'path' argument in"
            " 'onGtkPlanesHideToggled' method.\n");
      return;
    }

  gtk_tree_model_get(GTK_TREE_MODEL(listStoredPlanes), &iter,
                 COLUMN_PLANE_POINTER, &plane,
                 COLUMN_PLANE_HIDE_IS_ON, &checked,
                 COLUMN_PLANE_HIDDEN_SIDE, &side, -1);
  /* Because the get action increase the counter... */
  g_object_unref(G_OBJECT(plane));

  if (GPOINTER_TO_INT(user_data) == 0)
    {
      checked = !checked;
      gtk_list_store_set(listStoredPlanes, &iter,
                   COLUMN_PLANE_HIDE_IS_ON, checked, -1);
    }
  else
    {
      side = !side;
      gtk_list_store_set(listStoredPlanes, &iter,
                   COLUMN_PLANE_HIDDEN_SIDE, side, -1);
    }
  /* Set the hidden status */
  if (!checked)
    val = planeSet_hiddenState(plane, PLANE_SIDE_NONE);
  else
    {
      if (side)
      val = planeSet_hiddenState(plane, PLANE_SIDE_MINUS);
      else
      val = planeSet_hiddenState(plane, PLANE_SIDE_PLUS);
    }
  if (!extensionPlanes->used)
    return;
  if (val)
    {
      /* Get the VisuData to deal with. */
      dataObj = toolPanelGet_visuData(TOOL_PANEL(panelPlanes));
      /* Modify nodes visibility accordingly. */
      val = panelPlanesApply_hidingScheme(dataObj);
      if (val)
      {
        visuData_createAllNodes(dataObj);
        g_signal_emit (visu, VISU_GET_CLASS (visu)->OpenGLAskForReDraw_signal_id,
                   0 /* details */,
                   NULL);
      }
    }
}
void onGtkPlanesHidingModeToggled(GtkToggleButton *toggle, gpointer data)
{
  int res;
  GList *planeList, *tmplst;
  gboolean needShowHide;
  VisuData *dataObj;

  if (!gtk_toggle_button_get_active(toggle))
    return;

  DBG_fprintf(stderr, "Panel planes : set hiding mode to %d.\n", GPOINTER_TO_INT(data));

  res = planeSet_hidingMode(GPOINTER_TO_INT(data));
  if (!res || !extensionPlanes->used)
    return;
  /* Build the list of all planes. */
  planeList = getListOfAllPlanes(FALSE);
  if (!planeList || !planeList->next)
    return;
  /* Test if one of the plane has a mask attribute. */
  needShowHide = FALSE;
  tmplst = planeList;
  while (tmplst)
    {
      /* Test if one of the plane at least need to mask some nodes. */
      needShowHide = needShowHide ||
      (planeGet_hiddenState((Plane*)tmplst->data) != PLANE_SIDE_NONE);
      tmplst = g_list_next(tmplst);
    }
  res = 0;
  /* Get the VisuData to deal with. */
  dataObj = toolPanelGet_visuData(TOOL_PANEL(panelPlanes));
  if (needShowHide)
    /* Modify nodes visibility accordingly. */
    res = panelPlanesApply_hidingScheme(dataObj);
  g_list_free(planeList);
  if (res)
    {
      visuData_createAllNodes(dataObj);
      g_signal_emit (visu, VISU_GET_CLASS (visu)->OpenGLAskForReDraw_signal_id,
                 0 /* details */,
                 NULL);
    }
}
gboolean panelPlanesApply_hidingScheme(VisuData *data)
{
  gboolean redraw;

  visuDataEmit_askForShowHideNodes(data, &redraw);

  if (redraw)
    visuDataEmit_nodeRenderedChange(data);

  return redraw;
}


static void onPlayStopDist(GtkButton *button, gpointer data)
{
  DBG_fprintf(stderr, "Panel Plane : push the play/stop button.\n");

  if (!isPlayingDistanceId)
    {
      /* Launch play */
      gtk_widget_hide(imageDistPlay);
      gtk_widget_show(imageDistStop);

      gtk_spin_button_set_value(GTK_SPIN_BUTTON(spinbuttonDistance),
                        numericalEntryGet_value(NUMERICAL_ENTRY(entryDistFrom)));
      directionDist = 1.;
      isPlayingDistanceId =
      g_timeout_add_full(G_PRIORITY_DEFAULT + 30,
                     (gint)gtk_spin_button_get_value(GTK_SPIN_BUTTON(spinDistDelay)),
                     playDistances, (gpointer)0,
                     stopPlayStop);
    }
  else
    {
      /* Stop play */
      g_source_remove(isPlayingDistanceId);
    }
}
static void stopPlayStop(gpointer data)
{
  isPlayingDistanceId = 0;
  gtk_widget_hide(imageDistStop);
  gtk_widget_show(imageDistPlay);
}
static gboolean playDistances(gpointer data)
{
  gdouble val, step;
  gboolean changed;
  
  if (gtk_tree_model_iter_n_children(GTK_TREE_MODEL(listStoredPlanes), NULL) == 0)
    return FALSE;

  val = gtk_spin_button_get_value(GTK_SPIN_BUTTON(spinbuttonDistance));
  step = numericalEntryGet_value(NUMERICAL_ENTRY(entryDistStep));
  changed = FALSE;
  if (directionDist > 0.)
    {
      if (val + step > numericalEntryGet_value(NUMERICAL_ENTRY(entryDistTo)))
      directionDist = -1.;
      else
      changed = TRUE;
    }
  else
    changed = TRUE;
  if (directionDist < 0.)
    {
      if (val - step < numericalEntryGet_value(NUMERICAL_ENTRY(entryDistFrom)))
      directionDist = +1.;
      else
      changed = TRUE;
    }
  /* If the direction has been changed twice in a row,
     then the step is too wide for the range, we stop. */
  if (!changed)
    return FALSE;

  DBG_fprintf(stderr, "Panel Planes : set new distance to %g.\n", val + directionDist * step);
  gtk_spin_button_set_value(GTK_SPIN_BUTTON(spinbuttonDistance),
                      val + directionDist * step);
  return TRUE;
}
static void onSpinDistDelayChange(GtkSpinButton *spin, gpointer data)
{
  if (isPlayingDistanceId)
    {
      /* Stop play. */
      g_source_remove(isPlayingDistanceId);
      /* Launch play. */
      gtk_widget_hide(imageDistPlay);
      gtk_widget_show(imageDistStop);
      isPlayingDistanceId =
      g_timeout_add_full(G_PRIORITY_DEFAULT + 30,
                     (gint)gtk_spin_button_get_value(GTK_SPIN_BUTTON(spinDistDelay)),
                     playDistances, (gpointer)0,
                     stopPlayStop);
    }
}

/* IO tab. */
static void setCurrentSaveFile()
{
  gchar *filenameUTF8, *markup;

  if (!currentSaveListFile)
    return;

  /* Print the filename to screen. */
  filenameUTF8 = getStringInUTF8(currentSaveListFile);
  markup = g_markup_printf_escaped(_("<span style=\"italic\" size=\"smaller\">%s</span>"),
                           filenameUTF8);
  g_free(filenameUTF8);
  gtk_label_set_markup(GTK_LABEL(labelPlaneList), markup);
  g_free(markup);

  /* Since we've got a file name, save button can be activated. */
  gtk_widget_set_sensitive(buttonSaveList, TRUE);
}
gboolean panelPlanesLoad_file(VisuData *dataObj, gchar *filename, GError **error)
{
  GList *list, *tmplst;
  gboolean res;
  OpenGLView *view;
  float vect[3];
  float dist;
  Color *color;
  int hide;
  gchar str[256];
  GdkPixbuf *pixbufColorAlphaBox;
  GtkTreeIter iter;

  g_return_val_if_fail(dataObj && filename && error && *error == (GError*)0, FALSE);

  g_return_val_if_fail(isPlanesInitialised, FALSE);

  /* Try to load the file. */
  res = planesParse_XMLFile(filename, &list, error);
  if (!res)
    return FALSE;

  view = visuDataGet_openGLView(dataObj);
  g_return_val_if_fail(view, FALSE);

  DBG_fprintf(stderr, "Panel Planes : found %d planes in file '%s'.\n", 
            g_list_length(list), filename);
  /* Begin to compute intersections of all planes and then
     add then to the list. */
  gtk_list_store_clear(listStoredPlanes);
  tmplst = list;
  while (tmplst)
    {
      planeComputeInter((Plane*)tmplst->data, view);

      /* String used to labelled planes, dist. means 'distance' and
       norm. means 'normal' (50 chars max). */
      planeGet_nVectUser((Plane*)tmplst->data, vect);
      planeGet_distanceFromOrigin((Plane*)tmplst->data, &dist);
      planeGet_color((Plane*)tmplst->data, &color);
      hide = planeGet_hiddenState((Plane*)tmplst->data);
      sprintf(str, LABEL_PLANE, (int)vect[0], (int)vect[1], (int)vect[2], dist);
      pixbufColorAlphaBox =
      colorComboBoxGet_pixbufFromColor(COLOR_COMBOX(widgetColorPlane), color);
      gtk_list_store_append(listStoredPlanes, &iter);
      gtk_list_store_set(listStoredPlanes, &iter,
                   COLUMN_PLANE_DRAWN, planeGet_rendered(PLANE(tmplst->data)),
                   COLUMN_PLANE_LABEL, str,
                   COLUMN_PLANE_HIDE_IS_ON, (hide != 0),
                   COLUMN_PLANE_HIDDEN_SIDE, (hide == -1),
                   COLUMN_PLANE_COLOR_PIXBUF, (gpointer)pixbufColorAlphaBox,
                   COLUMN_PLANE_POINTER, tmplst->data,
                   -1);
      g_object_unref(G_OBJECT(tmplst->data));
      tmplst = g_list_next(tmplst);
    }
  /* Change the OpenGL list containing planes. */
  rebuildListPlanes(dataObj);
  /* Set the last iter as selected iter. */
  gtk_tree_selection_select_iter(gtk_tree_view_get_selection(GTK_TREE_VIEW(treeviewPlanes)), &iter);
  /* If several planes exist, set the sensitivity of
     the masking mode. */
  if (gtk_tree_model_iter_n_children(GTK_TREE_MODEL(listStoredPlanes), (GtkTreeIter*)0) > 1)
    gtk_widget_set_sensitive(hboxHidingMode, TRUE);
  g_list_free(list);

  /* Save the file name. */
  if (currentSaveListFile)
    g_free(currentSaveListFile);
  currentSaveListFile = g_strdup(filename);

  setCurrentSaveFile();

  return extensionPlanes->used;
}
static void onPlaneListOpen(GtkButton *button, gpointer data)
{
  GtkWidget *openDialog;
  gchar *filename, *directory;
  VisuData *dataObj;
  gboolean res;
  GError *error;
  
  dataObj = toolPanelGet_visuData(TOOL_PANEL(panelPlanes));
  g_return_if_fail(dataObj);

  openDialog = gtk_file_chooser_dialog_new(_("Choose a file with a list of planes"),
                                           GTK_WINDOW(mainWindow), GTK_FILE_CHOOSER_ACTION_OPEN,
                                 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
                                 GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
                                 NULL);
  gtk_window_set_modal(GTK_WINDOW(openDialog), TRUE);
  gtk_window_set_transient_for(GTK_WINDOW(openDialog), GTK_WINDOW(mainWindow));
  gtk_window_set_position(GTK_WINDOW(openDialog), GTK_WIN_POS_CENTER_ON_PARENT);
  directory = getLastOpenDirectory();
  if (directory)
    gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(openDialog), directory);
  gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(openDialog), FALSE);
  if (gtk_dialog_run(GTK_DIALOG(openDialog)) != GTK_RESPONSE_ACCEPT)
    {
      gtk_widget_destroy(openDialog);
      return;
    }
  filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(openDialog));
  gtk_widget_destroy(openDialog);
  error = (GError*)0;
  res = panelPlanesLoad_file(dataObj, filename, &error);
  g_free(filename);
  if (error)
    {
      raiseAlertDialog(error->message);
      g_clear_error(&error);
      return;
    }
  /* If the extension is actually used, recompute the visibility of nodes. */
  if (res)
    {
      res = panelPlanesApply_hidingScheme(dataObj);
      if (res)
      visuData_createAllNodes(dataObj);
      g_signal_emit (visu, VISU_GET_CLASS (visu)->OpenGLAskForReDraw_signal_id,
                 0 /* details */,
                 NULL);
    }
}
static gboolean callbackSave(gchar* filename)
{
  GList *list;
  GError *error;
  gboolean res;

  g_return_val_if_fail(filename, FALSE);

  /* Get all planes in a list. */
  list = getListOfAllPlanes(FALSE);

  /* Give the list to the save method. */
  error = (GError*)0;
  res = planesExport_XMLFile(filename, list, &error);
  if (!res)
    {
      raiseAlertDialog(error->message);
      g_clear_error(&error);
      return FALSE;
    }

  /* Free the used list. */
  g_list_free(list);

  return TRUE;
}
static void onPlaneListSave(GtkButton *button, gpointer data)
{
  callbackSave(currentSaveListFile);
}
static void onPlaneListSaveAs(GtkButton *button, gpointer data)
{
  GtkWidget *saveDialog;
  gchar *directory, *filename;
  gboolean res;

  saveDialog = gtk_file_chooser_dialog_new(_("Choose a file to save the list of planes"),
                                           GTK_WINDOW(mainWindow), GTK_FILE_CHOOSER_ACTION_SAVE,
                                 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
                                 GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
                                 NULL);
  gtk_window_set_modal(GTK_WINDOW(saveDialog), TRUE);
  gtk_window_set_transient_for(GTK_WINDOW(saveDialog), GTK_WINDOW(mainWindow));
  gtk_window_set_position(GTK_WINDOW(saveDialog), GTK_WIN_POS_CENTER_ON_PARENT);
  directory = getLastOpenDirectory();
  if (directory)
    gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(saveDialog), directory);
  gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(saveDialog), FALSE);
  gtk_dialog_set_default_response(GTK_DIALOG(saveDialog), GTK_RESPONSE_ACCEPT);
  if (gtk_dialog_run(GTK_DIALOG(saveDialog)) != GTK_RESPONSE_ACCEPT)
    {
      gtk_widget_destroy(saveDialog);
      return;
    }
  filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(saveDialog));
  gtk_widget_destroy(saveDialog);

  res = callbackSave(filename);
  if (res)
    {
      currentSaveListFile = filename;
      setCurrentSaveFile();
    }
  else
    g_free(filename);
}

Generated by  Doxygen 1.6.0   Back to index