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

gtk_renderingWindowWidget.c

/*   EXTRAITS DE LA LICENCE
      Copyright CEA, contributeurs : Luc BILLARD et Damien
      CALISTE, laboratoire L_Sim, (2001-2006)
  
      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-2006)

      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.
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include "gtk_renderingWindowWidget.h"

#include <gtk/gtk.h>
#include <gdk/gdkkeysyms.h>
#include <math.h> /* for sqrt function... */

#include <pixmaps/icone-observe.xpm>

#include "support.h"
#include "visu_tools.h"
#include "visu_object.h"
#include "visu_data.h"
#include "visu_pickMesure.h"
#include "visu_extension.h"
#include "OSOpenGL/visu_openGL.h"
#include "renderingBackend/visu_actionInterface.h"
#include "gtk_main.h"
#include "gtk_openGLWidget.h"
#include "coreTools/toolFileFormat.h"
#include "extraGtkFunctions/gtk_dumpDialogWidget.h"
#include "openGLFunctions/objectList.h"
#include "opengl.h"


static void renderingWindow_class_init          (RenderingWindowClass *klass);
static void renderingWindow_init                (RenderingWindow *renderingWindow);


GtkWindowClass *parent_class;

typedef enum
  {
    event_button_press,
    event_button_release,
    event_motion_notify,
    event_key_press,
    event_scroll
  } InteractiveEventsId;

struct InteractiveEvents_struct
{
  gulong callbackId;
  InteractiveEventsId id;
};
typedef struct InteractiveEvents_struct InteractiveEvents;


struct GtkInfoArea_struct
{
  GtkWidget *area;

  GtkWidget *hboxFileInfo;
  GtkWidget *labelSize;
  GtkWidget *labelNb;
  GtkWidget *labelFileInfo;
  gboolean fileInfoFreeze;

  GtkWidget *dumpButton;
  GtkWidget *loadButton;
  GtkWidget *raiseButton;

  GtkWidget *statusInfo;
  guint statusInfoId;
};
typedef struct GtkInfoArea_struct GtkInfoArea;

#define GTK_STATUSINFO_NOFILEINFO _("<span style=\"italic\">No description is available</span>")
#define GTK_STATUSINFO_NONB       _("<span style=\"italic\">Nothing is loaded</span>")

/* Internal gtkStatusInfo functions. */
GtkInfoArea *gtkStatusInfo_createBar(RenderingWindow *window, gint width, gint height);
/**
 * gtkStatusInfo_setOpenGLSize:
 * @info: the #GtkInfoArea that needs modifications ;
 * @width: size of the OpenGL area ;
 * @height: idem.
 *
 * Set the label of the size for the OpenGL area.
 */
void gtkStatusInfo_setOpenGLSize(GtkInfoArea *info, gint width, gint height);
/**
 * gtkStatusInfo_setFileInfo:
 * @info: the #GtkInfoArea that needs modifications ;
 * @message: an UTF8 string to print on the status bar.
 *
 * Use this method to display the commentary associated to a file.
 */
void gtkStatusInfo_setFileDescription(GtkInfoArea *info, gchar *message);
/**
 * gtkStatusInfo_setNbNodes:
 * @info: the #GtkInfoArea that needs modifications ;
 * @nb: number of loaded nodes (-1 if no file loaded).
 *
 * Use this method to display the commentary associated to the number of allocated nodes.
 */
void gtkStatusInfo_setNbNodes(GtkInfoArea *info, gint nb);
/* Local callbacks */
void onFileInfoToggled(GtkToggleButton *button, gpointer data);
void onLoadFileClicked(RenderingWindow *window, gpointer data);
void onRefreshViewClicked(GtkButton *button, gpointer data);
static void onDumpButtonClicked(GtkButton *button, gpointer user_data);
static void onRaiseButtonClicked(GtkButton *button, gpointer user_data);
void displayFileInfoOnDataLoaded(RenderingWindow *window);
void onRenderingMethodChanged(RenderingWindow *window, gpointer data);
void setDumpButtonSensitive(RenderingWindow *window);


struct RenderingWindow_struct
{
  GtkWindow topRenderedWindow;

  /*********************************/
  /* Dealing with the OpenGL area. */
  /*********************************/
  /* The OpenGL area and it's notification zone. */
  GtkWidget *openGLArea;
  /* Stored size of the OpenGL area. */
  gint socketWidth, socketHeight;
  /* A flag to store if the rendering window
     is in an interactive mode. */
  gboolean interactiveModeIsActive;
  /* A flag to prevent default interactive
     mode to bring up on signals. */
  gboolean interactiveModeIsBlocked;
  /* This pointer give the possibility to store
     several picked nodes and manage marks on them. */
  PickMesure *pickMesure;
  /* This is a list of currently connected
     signal for the interactive mode. */
  GList *interactiveEventsId;
  /* A pointer on the current used cursor. */
  GdkCursor *currentCursor;
  /* Callbacks associated to interactive mode. */
  CallbackFunctions callbacksInInteractiveMode;
  /* A pixbuf that can be display in the OpenGL area. */
  GdkPixbuf *backLogo;


  /*************************************/
  /* Dealing with the information bar. */
  /*************************************/
  /* TO BE INTEGRATED. */
  GtkInfoArea *info;
  /* TO BE INTEGRATED. */
  int nbStatusMessage;

  /* a pointer to the currently loaded VisuData. */
  VisuData *currentData;
};

struct RenderingWindowClass_struct
{
  GtkWindowClass parent_class;

  void (*renderingWindow) (RenderingWindow *window);

  GdkCursor *cursorRotate;
  GdkCursor *cursorWatch;
  GdkCursor *cursorPointer;
  GdkCursor *cursorPirate;
  GdkCursor *currentCursor;
};

/* Local callbacks */
static gboolean onKillRenderingWindowEvent(GtkWidget *widget, GdkEvent *event,
                                 gpointer user_data);
/* Alert user when size of the OpenGL area is changed. */
static void onSizeChangeEvent(GtkWidget *widget, GtkAllocation *allocation, gpointer user_data);
static void onRedraw(RenderingWindow *window, gpointer data);
static void onForceRedraw(RenderingWindow *window, gpointer data);
static void onRealiseEvent(GtkWidget *wd, gpointer data);

/* Interactive mode listeners. */
static gboolean onKeyPressed(GtkWidget *widget, GdkEventKey *event, gpointer user_data);
static gboolean onMouseMotion(GtkWidget *widget, GdkEventMotion *event, gpointer user_data);
static gboolean onScrollEvent(GtkWidget *widget, GdkEventScroll *event, gpointer user_data);
static gboolean onButtonAction(RenderingWindow *window, GdkEventButton *event, gpointer user_data);


GType renderingWindow_get_type(void)
{
  static GType renderingWindow_type = 0;

  if (!renderingWindow_type)
    {
      static const GTypeInfo renderingWindow_info =
      {
        sizeof (RenderingWindowClass),
        NULL, /* base_init */
        NULL, /* base_finalize */
        (GClassInitFunc) renderingWindow_class_init,
        NULL, /* class_finalize */
        NULL, /* class_data */
        sizeof (RenderingWindow),
        0,
        (GInstanceInitFunc) renderingWindow_init,
      0
      };
      renderingWindow_type = g_type_register_static(GTK_TYPE_WINDOW, "RenderingWindow",
                                        &renderingWindow_info, 0);
      DBG_fprintf(stderr, "Gtk RenderingWindow : creating the type RenderingWindow %p.\n",
              (gpointer)renderingWindow_type);
    }

  return renderingWindow_type;
}

static void renderingWindow_class_init(RenderingWindowClass *klass)
{
  DBG_fprintf(stderr, "Gtk RenderingWindow : creating the class of the widget.\n");

  parent_class = g_type_class_peek_parent(klass);
  
  /* Initialisation des crseurs utiles. */
  klass->cursorPirate = gdk_cursor_new(GDK_PIRATE);
  klass->cursorRotate = gdk_cursor_new(GDK_BOX_SPIRAL);
  klass->cursorWatch = gdk_cursor_new(GDK_WATCH);
  klass->cursorPointer = gdk_cursor_new(GDK_DOTBOX);
}

static void renderingWindow_init(RenderingWindow *renderingWindow)
{
  DBG_fprintf(stderr, "Gtk RenderingWindow : initializing new object (%p).\n",
            (gpointer)renderingWindow);

  renderingWindow->currentData = (VisuData*)0;
}


GtkWidget* renderingWindow_new(char* windowRef, char* window_name,
                         char* class_name, int width, int height)
{
  RenderingWindow *renderingWindow;

  GdkPixbuf *iconPixBuf;
  GtkWidget *wd, *vbox;

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

  renderingWindow = RENDERING_WINDOW(g_object_new(renderingWindow_get_type(), NULL));

  /* We create the rendering window. */
  gtk_window_set_title(GTK_WINDOW(renderingWindow), windowRef);
  gtk_window_set_wmclass(GTK_WINDOW(renderingWindow), window_name, class_name);
  g_signal_connect(G_OBJECT(renderingWindow), "delete-event",
               G_CALLBACK(onKillRenderingWindowEvent), (gpointer)0);
  g_signal_connect(G_OBJECT(renderingWindow), "destroy-event",
               G_CALLBACK(onKillRenderingWindowEvent), (gpointer)0);

  iconPixBuf = gdk_pixbuf_new_from_xpm_data((const char**)icone_observe_xpm);
  gtk_window_set_icon(GTK_WINDOW(renderingWindow), iconPixBuf);

  vbox = gtk_vbox_new(FALSE, 0);
  gtk_container_add(GTK_CONTAINER(renderingWindow), vbox);
  gtk_widget_show(vbox);

  /* We create the statusinfo area. */
  renderingWindow->info = gtkStatusInfo_createBar(renderingWindow, width, height);
  wd = renderingWindow->info->area;
  gtk_box_pack_end(GTK_BOX(vbox), wd, FALSE, FALSE, 0);
  gtk_widget_show_all(wd);

  renderingWindow->openGLArea = openGLWidgetNew(TRUE);
  g_signal_connect(G_OBJECT(renderingWindow->openGLArea), "realize",
               G_CALLBACK(onRealiseEvent), (gpointer)0);
  gtk_widget_set_size_request(renderingWindow->openGLArea, width, height);
  /* Attach the default redraw method. */
  openGLWidgetSet_redraw(OPENGL_WIDGET(renderingWindow->openGLArea),
                   openGL_drawToEmpty, (gpointer)0);
  gtk_box_pack_start(GTK_BOX(vbox), renderingWindow->openGLArea, TRUE, TRUE, 0);
  gtk_widget_show(renderingWindow->openGLArea);
  
  /* We physically show the window. */
  gtk_widget_show(GTK_WIDGET(renderingWindow));

  gdk_window_set_cursor(GDK_WINDOW(renderingWindow->openGLArea->window),
                  RENDERING_WINDOW_CLASS(G_OBJECT_GET_CLASS(renderingWindow))->cursorPirate);

  /* Unset the size request. */
  gtk_widget_set_size_request(renderingWindow->openGLArea, 30, 30);
  renderingWindow->socketWidth = width;
  renderingWindow->socketHeight = height;
  /* Set a listener on the size to show the warning icon accordingly. */
  g_signal_connect(G_OBJECT(renderingWindow->openGLArea), "size-allocate",
               G_CALLBACK(onSizeChangeEvent), (gpointer)renderingWindow);

  /* Set local variables. */
  renderingWindow->interactiveModeIsActive = FALSE;
  renderingWindow->nbStatusMessage = 0;
  renderingWindow->interactiveEventsId = (GList*)0;
  renderingWindow->currentCursor = 
    RENDERING_WINDOW_CLASS(G_OBJECT_GET_CLASS(renderingWindow))->cursorPirate;
  renderingWindow->backLogo = (GdkPixbuf*)0;
  renderingWindow->interactiveModeIsBlocked = FALSE;
  renderingWindow->pickMesure = (PickMesure*)0;

  g_signal_connect_swapped(G_OBJECT(visu), "OpenGLAskForReDraw",
                     G_CALLBACK(onRedraw), (gpointer)renderingWindow);
  g_signal_connect_swapped(G_OBJECT(visu), "OpenGLForceReDraw",
                     G_CALLBACK(onForceRedraw), (gpointer)renderingWindow);

  DBG_fprintf(stderr, "Visu window GTK : Building OK.\n");

  return GTK_WIDGET(renderingWindow);
}

GtkInfoArea *gtkStatusInfo_createBar(RenderingWindow *window, gint width, gint height)
{
  GtkWidget *hbox;
  GtkWidget *wd, *image;
  GtkTooltips *tooltips;
  GtkInfoArea *info;

  GtkWidget *handle, *hboxHandle;

  info = g_malloc(sizeof(GtkInfoArea));

  info->area = gtk_vbox_new(FALSE, 0);

  tooltips = gtk_tooltips_new ();

  info->fileInfoFreeze = FALSE;
  info->hboxFileInfo = gtk_hbox_new(FALSE, 0);
  gtk_box_pack_start(GTK_BOX(info->area), info->hboxFileInfo, FALSE, FALSE, 1);

  /* Size info */
  wd = gtk_hbox_new(FALSE, 0);
  gtk_box_pack_start(GTK_BOX(info->hboxFileInfo), wd, FALSE, FALSE, 5);
  info->labelSize = gtk_label_new("");
  gtk_label_set_use_markup(GTK_LABEL(info->labelSize), TRUE);
  gtkStatusInfo_setOpenGLSize(info, width, height);
  gtk_box_pack_start(GTK_BOX(wd), info->labelSize, FALSE, FALSE, 0);

  wd = gtk_vseparator_new();
  gtk_box_pack_start(GTK_BOX(info->hboxFileInfo), wd, FALSE, FALSE, 0);

  /* Nb nodes */
  info->labelNb = gtk_label_new("");
  gtk_label_set_use_markup(GTK_LABEL(info->labelNb), TRUE);
  gtkStatusInfo_setNbNodes(info, -1);
  gtk_box_pack_start(GTK_BOX(info->hboxFileInfo), info->labelNb, FALSE, FALSE, 5);

  wd = gtk_vseparator_new();
  gtk_box_pack_start(GTK_BOX(info->hboxFileInfo), wd, FALSE, FALSE, 0);

  /* File info */
  wd = gtk_hbox_new(FALSE, 0);
  gtk_box_pack_start(GTK_BOX(info->hboxFileInfo), wd, TRUE, TRUE, 5);
  image = gtk_image_new_from_stock(GTK_STOCK_SAVE,
                           GTK_ICON_SIZE_MENU);
  gtk_box_pack_start(GTK_BOX(wd), image, FALSE, FALSE, 1);
  info->labelFileInfo = gtk_label_new("");
  gtk_label_set_use_markup(GTK_LABEL(info->labelFileInfo), TRUE);
  gtk_misc_set_alignment(GTK_MISC(info->labelFileInfo), 0., 0.5);
#if GTK_MINOR_VERSION > 5
  gtk_label_set_ellipsize(GTK_LABEL(info->labelFileInfo), PANGO_ELLIPSIZE_END);
#endif
  gtkStatusInfo_setFileDescription(info, GTK_STATUSINFO_NOFILEINFO);
  gtk_box_pack_start(GTK_BOX(wd), info->labelFileInfo, TRUE, TRUE, 0);

  /* Status */
  hbox = gtk_hbox_new(FALSE, 0);
  gtk_box_pack_start(GTK_BOX(info->area), hbox, FALSE, FALSE, 0);

  /* Handle box for action buttons. */
  handle = gtk_handle_box_new();
  gtk_box_pack_start(GTK_BOX(hbox), handle, FALSE, FALSE, 0);
  hboxHandle = gtk_hbox_new(TRUE, 1);
  gtk_container_add(GTK_CONTAINER(handle), hboxHandle);
  /* Load button */
  info->loadButton = gtk_button_new();
  gtk_widget_set_sensitive(info->loadButton, FALSE);
  gtk_tooltips_set_tip (tooltips, info->loadButton,
                  _("Open"), NULL);
  g_signal_connect_swapped(G_OBJECT(info->loadButton), "clicked",
                     G_CALLBACK(onLoadFileClicked), (gpointer)window);
  image = gtk_image_new_from_stock(GTK_STOCK_OPEN,
                           GTK_ICON_SIZE_MENU);
  gtk_container_add(GTK_CONTAINER(info->loadButton), image);
  gtk_box_pack_start(GTK_BOX(hboxHandle), info->loadButton, FALSE, FALSE, 0);
  /* Refresh button */
  wd = gtk_button_new();
  gtk_tooltips_set_tip (tooltips, wd,
                  _("Refresh"), NULL);
  g_signal_connect(G_OBJECT(wd), "clicked",
               G_CALLBACK(onRefreshViewClicked), (gpointer)window);
  image = gtk_image_new_from_stock(GTK_STOCK_REFRESH,
                           GTK_ICON_SIZE_MENU);
  gtk_container_add(GTK_CONTAINER(wd), image);
  gtk_box_pack_start(GTK_BOX(hboxHandle), wd, FALSE, FALSE, 0);
  /* Save button */
  info->dumpButton = gtk_button_new();
  gtk_tooltips_set_tip (tooltips, info->dumpButton,
                  _("Export"), NULL);
  g_signal_connect(G_OBJECT(info->dumpButton), "clicked",
               G_CALLBACK(onDumpButtonClicked), (gpointer)window);
  gtk_widget_set_sensitive(info->dumpButton, FALSE);
  image = gtk_image_new_from_stock(GTK_STOCK_SAVE_AS,
                           GTK_ICON_SIZE_MENU);
  gtk_container_add(GTK_CONTAINER(info->dumpButton), image);
  gtk_box_pack_start(GTK_BOX(hboxHandle), info->dumpButton, FALSE, FALSE, 0);
  /* Auto-raise command panel button */
  info->raiseButton = gtk_button_new();
  gtk_tooltips_set_tip (tooltips, info->raiseButton,
                  _("Raise the command panel window."), NULL);
  g_signal_connect(G_OBJECT(info->raiseButton), "clicked",
               G_CALLBACK(onRaiseButtonClicked), (gpointer)0);
  image = gtk_image_new_from_stock(GTK_STOCK_GO_UP,
                           GTK_ICON_SIZE_MENU);
  gtk_container_add(GTK_CONTAINER(info->raiseButton), image);
  gtk_box_pack_start(GTK_BOX(hboxHandle), info->raiseButton, FALSE, FALSE, 0);

  /* Hide button */
  wd = gtk_toggle_button_new();
  gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(wd), TRUE);
  g_object_set(G_OBJECT(wd), "can-default", FALSE, "can-focus", FALSE,
             "has-default", FALSE, "has-focus", FALSE, NULL);
  g_signal_connect(G_OBJECT(wd), "toggled",
               G_CALLBACK(onFileInfoToggled), (gpointer)window);
  gtk_tooltips_set_tip (tooltips, wd,
                  _("Show/hide miscellaneous informations."), NULL);
  image = gtk_image_new_from_stock(GTK_STOCK_DIALOG_QUESTION,
                           GTK_ICON_SIZE_MENU);
  gtk_container_add(GTK_CONTAINER(wd), image);
  gtk_box_pack_start(GTK_BOX(hbox), wd, FALSE, FALSE, 5);

  info->statusInfo = gtk_statusbar_new();
  gtk_box_pack_start(GTK_BOX(hbox), info->statusInfo, TRUE, TRUE, 0);
  gtk_statusbar_set_has_resize_grip(GTK_STATUSBAR(info->statusInfo), FALSE);

  info->statusInfoId = gtk_statusbar_get_context_id(GTK_STATUSBAR(info->statusInfo),
                                        "OpenGL statusbar.");
  
  g_signal_connect_swapped(G_OBJECT(visu), "renderingChanged",
                     G_CALLBACK(onRenderingMethodChanged), (gpointer)window);

  return info;
}


static gboolean onKillRenderingWindowEvent(GtkWidget *widget, GdkEvent *event, gpointer user_data)
{
  DBG_fprintf(stderr, "Gtk RenderingWindow : delete or destroy event cancelled.\n");
  return TRUE;
}

static void onSizeChangeEvent(GtkWidget *widget, GtkAllocation *allocation, gpointer user_data)
{
  RenderingWindow *window;

  window = RENDERING_WINDOW(user_data);
  g_return_if_fail(window);

  /* Return if no changes in size (this event is called even the size
     is not really changed but has been negociated. */
  if (window->socketWidth == allocation->width &&
      window->socketHeight == allocation->height)
    return;

  window->socketWidth = allocation->width;
  window->socketHeight = allocation->height;
  gtkStatusInfo_setOpenGLSize(window->info,
                        window->socketWidth,
                        window->socketHeight);

  /* If data are currently rendered on this window,
     we ask these data to update to the new size. */
  if (window->currentData)
    visuDataSet_sizeOfView(window->currentData,
                     allocation->width, allocation->height);
}

static void onRealiseEvent(GtkWidget *wd, gpointer data)
{
  DBG_fprintf(stderr, "Gtk RenderingWindow : initializing OpenGL variable for"
            "the new OpenGL area.\n");
  /* Set V_Sim OpenGL options. */
  openGLInit_context();
}

void minimalPickInfo(const VisuPick *info, gpointer data)
{
  float posSelect[3], posRef[3], dist;
  GString *str;
  RenderingWindow *window;
  VisuNode *node, *ref;
  int i;

  window = RENDERING_WINDOW(data);
  g_return_if_fail(window && window->pickMesure);

  while (window->nbStatusMessage > 1)
    {
      renderingWindowPop_message(window);
      window->nbStatusMessage -= 1;
    }

  marksAndMesures(info, window->pickMesure);
  if (pickMesureGet_newsAvailable(window->pickMesure))
    {
      node = pickMesureGet_selectedNode(window->pickMesure);
      ref = pickMesureGet_firstReference(window->pickMesure);

      /* No ref, then only position informations are displayed */
      if (!ref && node)
      {
        visuDataGet_nodePosition(window->currentData, node, posSelect);
        str = g_string_new(_("Selected node number "));
        g_string_append_printf(str, "%d - (x, y, z) = (%7.3f;%7.3f;%7.3f)", node->number,
                         posSelect[0], posSelect[1], posSelect[2]);
        renderingWindowPush_message(window, str->str);
        window->nbStatusMessage += 1;
        g_string_free(str, TRUE);
      }
      /* Have a ref and a selected node, then distance informations is compued. */
      if (ref && node)
      {
        visuDataGet_nodePosition(window->currentData, node, posSelect);
        visuDataGet_nodePosition(window->currentData, ref, posRef);
        str = g_string_new(_("Distance between nodes "));
        dist = 0.;
        for (i = 0; i < 3; i++)
          dist += (posRef[i] - posSelect[i]) * (posRef[i] - posSelect[i]);
        dist = sqrt(dist);
        g_string_append_printf(str, _("%d and %d : %7.3f"),
                         ref->number, node->number, dist);
        renderingWindowPush_message(window, str->str);
        window->nbStatusMessage += 1;
        g_string_free(str, TRUE);
      }
      /* Have a ref only, give some text info. */
      if (ref && !node)
      {
        renderingWindowPush_message(window, _("<shift> right-clic on background to unset reference"));
        window->nbStatusMessage += 1;
      }
    }
}

void emptyInteractiveEventListeners(RenderingWindow *window)
{
  GList* ptList;

  g_return_if_fail(IS_RENDERING_WINDOW(window));

  DBG_fprintf(stderr, "Gtk RenderingWindow : removing current interactive listeners.\n");
  ptList = window->interactiveEventsId;
  while (ptList)
    {
      DBG_fprintf(stderr, "  | disconnecting %ld signal.\n", *(gulong*)ptList->data);
      g_signal_handler_disconnect(G_OBJECT(window->openGLArea), *(gulong*)ptList->data);
      g_free(ptList->data);
      ptList = g_list_next(ptList);
    }
  if (window->interactiveEventsId)
    g_list_free(window->interactiveEventsId);
  window->interactiveEventsId = (GList*)0;
}
gulong addInteractiveEventListeners(RenderingWindow *window, InteractiveEventsId id)
{
  GList* ptList;
  InteractiveEvents *event;
  gboolean found;

  g_return_val_if_fail(IS_RENDERING_WINDOW(window), (gulong)0);

  found  = FALSE;
  for (ptList = window->interactiveEventsId; ptList && !found; ptList = g_list_next(ptList))
    {
      event = (InteractiveEvents*)ptList->data;
      if (event->id == id)
      found = TRUE;
    }
  if (found)
    return (gulong)0;

  event = g_malloc(sizeof(InteractiveEvents));
  event->id = id;
  switch (id)
    {
    case event_button_press:
      event->callbackId = g_signal_connect_swapped(G_OBJECT(window->openGLArea),
                                       "button-press-event",
                                       G_CALLBACK(onButtonAction), (gpointer)window);
      break;
    case event_button_release:
      event->callbackId = g_signal_connect_swapped(G_OBJECT(window->openGLArea),
                                       "button-release-event",
                                       G_CALLBACK(onButtonAction), (gpointer)window);
      break;
    case event_motion_notify:
      event->callbackId = g_signal_connect(G_OBJECT(window->openGLArea),
                                 "motion-notify-event",
                                 G_CALLBACK(onMouseMotion), (gpointer)window);
      break;
    case event_key_press:
      event->callbackId = g_signal_connect(G_OBJECT(window->openGLArea),
                                 "key-press-event",
                                 G_CALLBACK(onKeyPressed), (gpointer)window);
      break;
    case event_scroll:
      event->callbackId = g_signal_connect(G_OBJECT(window->openGLArea),
                                 "scroll-event",
                                 G_CALLBACK(onScrollEvent), (gpointer)window);
      break;
    default:
      g_warning("Unknown event to add.");
      g_free(event);
      return (gulong)0;
    };
  window->interactiveEventsId = g_list_prepend(window->interactiveEventsId,
                                     (gpointer)event);
  return event->callbackId;
}
gulong removeInteractiveEventListeners(RenderingWindow *window, InteractiveEventsId id)
{
  GList* ptList;
  InteractiveEvents *event;
  gulong callid;

  g_return_val_if_fail(IS_RENDERING_WINDOW(window), (gulong)0);

  for (ptList = window->interactiveEventsId; ptList; ptList = g_list_next(ptList))
    {
      event = (InteractiveEvents*)ptList->data;
      if (event->id == id)
      {
        g_signal_handler_disconnect(G_OBJECT(window->openGLArea),
                              event->callbackId);
        window->interactiveEventsId = g_list_remove(window->interactiveEventsId,
                                          (gpointer)event);
        callid = event->callbackId;
        g_free(event);
        return callid;
      }
    }
  return (gulong)0;
}
void renderingWindowRemove_interactiveEventListener(RenderingWindow *window)
{
  emptyInteractiveEventListeners(window);
  gdk_window_set_cursor(GDK_WINDOW(window->openGLArea->window),
                  RENDERING_WINDOW_CLASS(G_OBJECT_GET_CLASS(window))->cursorPirate);
  window->currentCursor = RENDERING_WINDOW_CLASS(G_OBJECT_GET_CLASS(window))->cursorPirate;
}
void renderingWindowSet_observeEventListener(RenderingWindow *window,
                                   CallbackFunctions *userCallbacks)
{
  gulong id;

  g_return_if_fail(IS_RENDERING_WINDOW(window) && userCallbacks && userCallbacks->action);

  gdk_window_set_cursor(GDK_WINDOW(window->openGLArea->window),
                  RENDERING_WINDOW_CLASS(G_OBJECT_GET_CLASS(window))->cursorRotate);
  window->currentCursor = RENDERING_WINDOW_CLASS(G_OBJECT_GET_CLASS(window))->cursorRotate;

  DBG_fprintf(stderr, "Gtk RenderingWindow : setting current interactive listeners.\n");
  id = addInteractiveEventListeners(window, event_button_release);
  if (id)
    DBG_fprintf(stderr, "  | disconnecting %ld signal.\n", id);
  id = addInteractiveEventListeners(window, event_button_press);
  if (id)
    DBG_fprintf(stderr, "  | connecting %ld signal.\n", id);
  id = addInteractiveEventListeners(window, event_motion_notify);
  if (id)
    DBG_fprintf(stderr, "  | connecting %ld signal.\n", id);
  id = addInteractiveEventListeners(window, event_key_press);
  if (id)
    DBG_fprintf(stderr, "  | connecting %ld signal.\n", id);
  id = addInteractiveEventListeners(window, event_scroll);
  if (id)
    DBG_fprintf(stderr, "  | connecting %ld signal.\n", id);
      
  window->callbacksInInteractiveMode.action = userCallbacks->action;
  window->callbacksInInteractiveMode.stop = userCallbacks->stop;
}
void renderingWindowSet_pickEventListener(RenderingWindow *window,
                                CallbackFunctions *userCallbacks)
{
  gulong id;

  g_return_if_fail(IS_RENDERING_WINDOW(window) && userCallbacks && userCallbacks->action);

  gdk_window_set_cursor(GDK_WINDOW(window->openGLArea->window),
                  RENDERING_WINDOW_CLASS(G_OBJECT_GET_CLASS(window))->cursorPointer);
  window->currentCursor = RENDERING_WINDOW_CLASS(G_OBJECT_GET_CLASS(window))->cursorPointer;

  DBG_fprintf(stderr, "Gtk RenderingWindow : setting current interactive listeners.\n");
  id = addInteractiveEventListeners(window, event_button_press);
  if (id)
    DBG_fprintf(stderr, "  | connecting %ld signal.\n", id);
  id = addInteractiveEventListeners(window, event_button_release);
  if (id)
    DBG_fprintf(stderr, "  | connecting %ld signal.\n", id);
  id = addInteractiveEventListeners(window, event_motion_notify);
  if (id)
    DBG_fprintf(stderr, "  | connecting %ld signal.\n", id);
  id = removeInteractiveEventListeners(window, event_key_press);
  if (id)
    DBG_fprintf(stderr, "  | disconnecting %ld signal.\n", id);
  id = removeInteractiveEventListeners(window, event_scroll);
  if (id)
    DBG_fprintf(stderr, "  | disconnecting %ld signal.\n", id);
/*   id = addInteractiveEventListeners(window, event_key_press); */
/*   if (id) */
/*     DBG_fprintf(stderr, "  | connecting %ld signal.\n", id); */
/*   id = addInteractiveEventListeners(window, event_scroll); */
/*   if (id) */
/*     DBG_fprintf(stderr, "  | connecting %ld signal.\n", id); */
      
  window->callbacksInInteractiveMode.action = userCallbacks->action;
  window->callbacksInInteractiveMode.stop = userCallbacks->stop;
}

static gboolean onButtonAction(RenderingWindow *window, GdkEventButton *event, gpointer user_data)
{
  SimplifiedEvents ev;

  ev.button = 0;
  ev.motion = 0;
  ev.letter = '\0';

  gdk_window_set_cursor(GDK_WINDOW(window->openGLArea->window),
                  RENDERING_WINDOW_CLASS(G_OBJECT_GET_CLASS(window))->cursorWatch);
  ev.x = event->x;
  ev.y = event->y;
  ev.button = event->button;
  ev.shiftMod = event->state & GDK_SHIFT_MASK;
  ev.controlMod = event->state & GDK_CONTROL_MASK;
  ev.buttonType = 0;
  if (event->type == GDK_BUTTON_PRESS)
    ev.buttonType = BUTTON_TYPE_PRESS;
  else if (event->type == GDK_BUTTON_RELEASE)
    ev.buttonType = BUTTON_TYPE_RELEASE;

  if (window->callbacksInInteractiveMode.action(&ev, window->currentData) &&
      window->callbacksInInteractiveMode.stop)
    window->callbacksInInteractiveMode.stop((gpointer)0);

  gdk_window_set_cursor(GDK_WINDOW(window->openGLArea->window),
                  window->currentCursor);

  return TRUE;
}
static gboolean onScrollEvent(GtkWidget *widget, GdkEventScroll *event, gpointer user_data)
{
  SimplifiedEvents ev;
  RenderingWindow *window;

  window = RENDERING_WINDOW(user_data);
  g_return_val_if_fail(window, TRUE);

  ev.button = 0;
  ev.motion = 0;
  ev.letter = '\0';

  ev.x = event->x;
  ev.y = event->y;
  if (event->direction == GDK_SCROLL_UP)
    ev.button = 4;
  else if (event->direction == GDK_SCROLL_DOWN)
    ev.button = 5;
  ev.shiftMod = event->state & GDK_SHIFT_MASK;
  ev.controlMod = event->state & GDK_CONTROL_MASK;

  if (ev.button)
    {
      gdk_window_set_cursor(GDK_WINDOW(window->openGLArea->window),
                  RENDERING_WINDOW_CLASS(G_OBJECT_GET_CLASS(window))->cursorWatch);
      window->callbacksInInteractiveMode.action(&ev, window->currentData);
      gdk_window_set_cursor(GDK_WINDOW(window->openGLArea->window),
                  window->currentCursor);
    }

  return TRUE;
}
static gboolean onMouseMotion(GtkWidget *widget, GdkEventMotion *event, gpointer user_data)
{
  GdkWindow *windowMove;
  gint x, y;
  GdkModifierType mask;
  SimplifiedEvents ev;
  RenderingWindow *window;

  window = RENDERING_WINDOW(user_data);
  g_return_val_if_fail(window, TRUE);

  ev.button = 0;
  ev.motion = 1;
  ev.letter = '\0';

  windowMove = gdk_window_get_pointer(GDK_WINDOW(window->openGLArea->window),
                              &x, &y, &mask);

  ev.x = x;
  ev.y = y;
  if (event->state & GDK_BUTTON1_MASK)
    ev.button = 1;
  else if (event->state & GDK_BUTTON2_MASK)
    ev.button = 2;
  else if (event->state & GDK_BUTTON3_MASK)
    ev.button = 3;
  ev.shiftMod = event->state & GDK_SHIFT_MASK;
  ev.controlMod = event->state & GDK_CONTROL_MASK;

  if (ev.button == 1 || ev.button == 2)
    {
      gdk_window_set_cursor(GDK_WINDOW(window->openGLArea->window),
                  RENDERING_WINDOW_CLASS(G_OBJECT_GET_CLASS(window))->cursorWatch);
      window->callbacksInInteractiveMode.action(&ev, window->currentData);
      gdk_window_set_cursor(GDK_WINDOW(window->openGLArea->window),
                  window->currentCursor);
    }

  return TRUE;
}
static gboolean onKeyPressed(GtkWidget *widget, GdkEventKey *event, gpointer user_data)
{
  SimplifiedEvents ev;
  RenderingWindow *window;

  window = RENDERING_WINDOW(user_data);
  g_return_val_if_fail(window, TRUE);

  ev.button = 0;
  ev.motion = 0;
  ev.letter = '\0';

  gdk_window_set_cursor(GDK_WINDOW(window->openGLArea->window),
                  RENDERING_WINDOW_CLASS(G_OBJECT_GET_CLASS(window))->cursorWatch);
  if(event->keyval == GDK_r || event->keyval == GDK_R)
    ev.letter = 'r';
  if(event->keyval == GDK_space)
    ev.letter = ' ';

  window->callbacksInInteractiveMode.action(&ev, window->currentData);
  gdk_window_set_cursor(GDK_WINDOW(window->openGLArea->window),
                  window->currentCursor);

  return TRUE;
}

void renderingWindowStop_defaultIneractiveMode(RenderingWindow *window)
{
  g_return_if_fail(IS_RENDERING_WINDOW(window));

  if (!window->interactiveModeIsActive)
    return;
  
  window->interactiveModeIsActive = FALSE;
  /* Stop and free the measurements of several nodes. */
/*   endPickMesure(window->pickMesure); */
  /* Stop the observe mode */
  openGLInteractiveEnd_session();
  while (window->nbStatusMessage > 0)
    {
      window->nbStatusMessage -= 1;
      renderingWindowPop_message(window);
    }
}
void renderingWindowStart_defaultIneractiveMode(RenderingWindow *window)
{
  g_return_if_fail(IS_RENDERING_WINDOW(window));

  if (window->interactiveModeIsBlocked)
    return;

  /* Retrieve the PickMesure object to enable the storage of several
     nodes and the printing of marks. */
  window->pickMesure = (PickMesure*)visuDataGet_property(window->currentData, "pickMesure_data");
  if (!window->pickMesure)
    g_warning("No PickMesure object associated to the current VisuData object.");
  pickMesureSet_formatedOutput(window->pickMesure, FALSE);

  /* If we interactive mode is already active,
     we just flush the status bar. */
  if (window->interactiveModeIsActive)
    {
      /* Reset the statusbar informations. */
      while (window->nbStatusMessage > 0)
      {
        window->nbStatusMessage -= 1;
        renderingWindowPop_message(window);
      }
      /* Put a commentary in the statusbar. */
      renderingWindowPush_message(window,
                          _("Observe mode & right-clic and <shift> right-clic to pick."));
      window->nbStatusMessage += 1;
      return;
    }

  /* If not, we enable the interactive mode. */
  window->interactiveModeIsActive = TRUE;
  /* Enter in the observe mode as default. */
  openGLInteractiveInit_session(window, minimalPickInfo, window, (GDestroyNotify)0);
  openGLInteractiveBegin_pickAndObserve();
  /* Put a commentary in the statusbar. */
  renderingWindowPush_message(window,
                      _("Observe mode & right-clic and <shift> right-clic to pick."));
  window->nbStatusMessage += 1;
}
void renderingWindowBlock_defaultIneractiveMode(RenderingWindow *window)
{
  g_return_if_fail(IS_RENDERING_WINDOW(window));

  if (window->interactiveModeIsBlocked)
    return;
  renderingWindowStop_defaultIneractiveMode(window);
  window->interactiveModeIsBlocked = TRUE;
}
void renderingWindowUnblock_defaultIneractiveMode(RenderingWindow *window)
{
  g_return_if_fail(IS_RENDERING_WINDOW(window));

  window->interactiveModeIsBlocked = FALSE;
  renderingWindowStart_defaultIneractiveMode(window);
}

void renderingWindowPush_message(RenderingWindow *window, gchar *message)
{
  g_return_if_fail(IS_RENDERING_WINDOW(window));

  gtk_statusbar_push(GTK_STATUSBAR(window->info->statusInfo),
                 window->info->statusInfoId, message);
}
void renderingWindowPop_message(RenderingWindow *window)
{
  g_return_if_fail(IS_RENDERING_WINDOW(window));

  gtk_statusbar_pop(GTK_STATUSBAR(window->info->statusInfo),
                window->info->statusInfoId);
}
void renderingWindowGet_openGLAreaSize(RenderingWindow *window,
                               unsigned int *width, unsigned int *height)
{
  g_return_if_fail(IS_RENDERING_WINDOW(window) && width && height);

  gdk_drawable_get_size(GDK_DRAWABLE(window->openGLArea->window),
                  (gint*)width, (gint*)height);
}
GdkPixbuf* renderingWindowGet_backgroundImage(RenderingWindow *window,
                                   guchar **rowData, gboolean *hasAlphaChannel,
                                   int *width, int *height)
{
  g_return_val_if_fail(IS_RENDERING_WINDOW(window), (GdkPixbuf*)0);

  g_return_val_if_fail(rowData && hasAlphaChannel && width && height, (GdkPixbuf*)0);

  if (!window->backLogo)
    window->backLogo = create_pixbuf("logo_grey.png");
  g_return_val_if_fail(window->backLogo, (GdkPixbuf*)0);

  *rowData = gdk_pixbuf_get_pixels(window->backLogo);
  *hasAlphaChannel = gdk_pixbuf_get_has_alpha(window->backLogo);
  *width = gdk_pixbuf_get_width(window->backLogo);
  *height = gdk_pixbuf_get_height(window->backLogo);
  g_object_ref(G_OBJECT(window->backLogo));
  return window->backLogo;
}
void renderingWindowFree_backgroundImage(RenderingWindow *window)
{
  g_return_if_fail(IS_RENDERING_WINDOW(window));

  if (window->backLogo)
    g_object_unref(G_OBJECT(window->backLogo));
  window->backLogo = (GdkPixbuf*)0;
}
void renderingWindowSet_visuData(RenderingWindow *window, VisuData* data)
{
  gboolean noEmit;
  gchar *nom, *file;
  guint w, h;
  VisuData *oldData;

  g_return_if_fail(IS_RENDERING_WINDOW(window));

  DBG_fprintf(stderr, "Gtk renderingWindow : attach %p VisuData to %p window.\n",
            (gpointer)data, (gpointer)window);
  noEmit = (!window->currentData && !data);
  oldData = window->currentData;
  if (window->currentData != data)
    {
      if (window->currentData)
      visuDataSet_renderingWindow(window->currentData, (GenericRenderingWindow)0);
      window->currentData = data;
    }

  if (data)
    {
      /* Set the window as attachingRenderingWindow for the given VisuData. */
      visuDataSet_renderingWindow(data, (GenericRenderingWindow)window);
      renderingWindowGet_openGLAreaSize(window, &w, &h);
      visuDataSet_sizeOfView(data, w, h);
      /* Change the name of the window, according to the file loaded. */
      nom = visuDataGet_file(data, 0, (FileFormat**)0);
      if (nom)
      file = g_path_get_basename(nom);
      else
      {
        g_warning("Can't find the filename to label the rendering window.\n");
        file = g_strdup(_("No filename"));
      }
      gtk_window_set_title(GTK_WINDOW(window), file);
      g_free(file);

      /* Attach the default redraw method. */
      openGLWidgetSet_redraw(OPENGL_WIDGET(window->openGLArea),
                       openGL_reDraw, (gpointer)data);
    }
  else
    {
      /* Erase the name of the window. */
      gtk_window_set_title(GTK_WINDOW(window), _("No file loaded"));

      /* Attach the default redraw method. */
      openGLWidgetSet_redraw(OPENGL_WIDGET(window->openGLArea),
                       openGL_drawToEmpty, (gpointer)0);

      /* Ask for redraw. */
      renderingWindowRedraw(window, TRUE);
    }
  displayFileInfoOnDataLoaded(window);
  setDumpButtonSensitive(window);

  if (!noEmit)
    {
      DBG_fprintf(stderr, "Gtk renderingWindow : emitting the 'dataReadyForRendering' signal.\n");
      g_signal_emit(visu, VISU_GET_CLASS (visu)->dataReadyForRendering_signal_id,
                0 /* details */, (gpointer)data, NULL);
      DBG_fprintf(stderr, "Gtk renderingWindow : emitting done.\n");
    }

  if (data)
    /* Start an observe session. */
    renderingWindowStart_defaultIneractiveMode(window);
  else
    /* Stop the observe session. */
    renderingWindowStop_defaultIneractiveMode(window);

  /* Update properties of new data from old one.
     TODO : This should be trgiggered by a signal. */
  pickMesureUpdate(window->currentData, oldData);

  if (oldData != window->currentData && oldData)
    g_object_unref(oldData);
}
VisuData* renderingWindowGet_visuData(RenderingWindow *window)
{
  g_return_val_if_fail(IS_RENDERING_WINDOW(window), (VisuData*)0);
  return window->currentData;
}

/***************************/
/* GtkStatusInfo functions */
/***************************/
void gtkStatusInfo_setOpenGLSize(GtkInfoArea *info, gint width, gint height)
{
  GString *str;

  g_return_if_fail(info);

  if (info->fileInfoFreeze)
    return;

  str = g_string_new("<span size=\"smaller\">");
  g_string_append_printf(str, _("<b>Size:</b> %dx%d"), width, height);
  g_string_append_printf(str, "</span>");
  gtk_label_set_markup(GTK_LABEL(info->labelSize), str->str);
  g_string_free(str, TRUE);
}
void gtkStatusInfo_setFileDescription(GtkInfoArea *info, gchar* message)
{
  GString *str;

  g_return_if_fail(info);

  str = g_string_new("<span size=\"smaller\">");
  g_string_append_printf(str, _("<b>File info:</b> %s"), message);
  g_string_append_printf(str, "</span>");
  gtk_label_set_markup(GTK_LABEL(info->labelFileInfo), str->str);
  g_string_free(str, TRUE);
}
void gtkStatusInfo_setNbNodes(GtkInfoArea *info, gint nb)
{
  GString *str;

  g_return_if_fail(info);

  str = g_string_new("<span size=\"smaller\">");
  if (nb > 0)
    g_string_append_printf(str, _("<b>Nb nodes:</b> %d"), nb);
  else
    g_string_append(str, GTK_STATUSINFO_NONB);
  g_string_append_printf(str, "</span>");
  gtk_label_set_markup(GTK_LABEL(info->labelNb), str->str);
  g_string_free(str, TRUE);
}
void onFileInfoToggled(GtkToggleButton *button, gpointer data)
{
  unsigned int w, h;
  RenderingWindow *window;

  window = RENDERING_WINDOW(data);
  g_return_if_fail(window);

  window->info->fileInfoFreeze = TRUE;

  if (gtk_toggle_button_get_active(button))
    gtk_widget_show(GTK_WIDGET(window->info->hboxFileInfo));
  else
    gtk_widget_hide(GTK_WIDGET(window->info->hboxFileInfo));

  while(gtk_events_pending())
    gtk_main_iteration();

  renderingWindowGet_openGLAreaSize(window, &w, &h);
  if (window->currentData)
    visuDataSet_sizeOfView(window->currentData, w, h);
  else
    OpenGLViewSet_windowSize((OpenGLView*)0, w, h);

  if (gtk_toggle_button_get_active(button))
    window->info->fileInfoFreeze = FALSE;

  gtkStatusInfo_setOpenGLSize(window->info, w, h);

  g_signal_emit(visu, VISU_GET_CLASS(visu)->OpenGLForceReDraw_signal_id,
            0 , NULL);
}

void displayFileInfoOnDataLoaded(RenderingWindow *window)
{
  gchar* message;

  g_return_if_fail(window);

  if (window->currentData)
    {
      message = visuDataGet_fileCommentary((VisuData*)window->currentData);
      gtkStatusInfo_setNbNodes(window->info,
                         ((VisuData*)window->currentData)->nbOfAllStoredNodes);
    }
  else
    {
      message = (gchar*)0;
      gtkStatusInfo_setNbNodes(window->info, -1);
    }
  if (message)
    gtkStatusInfo_setFileDescription(window->info, message);
  else
    gtkStatusInfo_setFileDescription(window->info,
                             GTK_STATUSINFO_NOFILEINFO);
}

void renderingWindowLoad_file(RenderingWindow *window)
{
  onLoadFileClicked(window, (gpointer)0);
}

void onLoadFileClicked(RenderingWindow *window, gpointer data)
{
  GtkFileChooser *fileChooser;
  GtkWidget *dialog;
  int res;
  createGtkLoadWidgetFunc loadAction;
  gchar *directory;
  RenderingMethod* method;
  VisuData *newData;

  method = getRenderingMethodInUse();
  g_return_if_fail(method);

  loadAction = gtkMainGet_renderingSpecificOpen(method);
  g_return_if_fail(loadAction);

  if (window->currentData)
    newData = visuDataNew_withOpenGLView(visuDataGet_openGLView(window->currentData));
  else
    newData = visuDataNew();
  g_return_if_fail(newData);

  res = loadAction(newData, &fileChooser, &dialog);
  DBG_fprintf(stderr, "Gtk RenderingWindow : 'loadAction' OK.\n");
  
  directory = gtk_file_chooser_get_current_folder(fileChooser);
  setLastOpenDirectory((char*)directory);
  g_free(directory);

  if (res)
    {
      gtk_widget_destroy(dialog);
      visuWaitFunction();
      g_idle_add(loadAndRenderFileWithGtk, (gpointer)newData);
    }
  else
    {
      gtk_widget_destroy(dialog);
      g_object_unref(newData);
    }
}

void onRefreshViewClicked(GtkButton *button, gpointer data)
{
  renderingWindowRedraw(RENDERING_WINDOW(data), TRUE);
}

void onRenderingMethodChanged(RenderingWindow *window, gpointer data)
{
  /* First free attached visuData. */
  renderingWindowSet_visuData(window, (VisuData*)0);

  /* Customize interface according to new method. */
  if (getRenderingMethodInUse())
    {
      renderingWindowPop_message(window);
      gtk_widget_set_sensitive(window->info->loadButton, TRUE);
      renderingWindowPush_message(window, _("Use the 'open' button to render a file."));
    }
  else
    {
      gtk_widget_set_sensitive(window->info->loadButton, FALSE);
      renderingWindowPop_message(window);
    }
}

void setDumpButtonSensitive(RenderingWindow *window)
{
  g_return_if_fail(window);

  if (window->currentData)
    gtk_widget_set_sensitive(window->info->dumpButton, TRUE);
  else
    gtk_widget_set_sensitive(window->info->dumpButton, FALSE);
}

void updateDumpProgressBar(gpointer data)
{
  gdouble val;

  g_return_if_fail(GTK_PROGRESS_BAR(data));

  gtk_progress_bar_set_text(GTK_PROGRESS_BAR(data), _("Saving image..."));
  val = gtk_progress_bar_get_fraction(GTK_PROGRESS_BAR(data));
  if (val + 0.01 <= 1.0 && val >= 0.)
    gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(data), val + 0.01);
  visuWaitFunction();
}

void redrawOffScreen(guint width, guint height, gpointer data)
{
  openGLInit_context();
  visuDataSet_sizeOfView(VISU_DATA(data), width, height);
  openGLViewCompute_matrixAndView(visuDataGet_openGLView(VISU_DATA(data))); 
  rebuildAllExtensionsLists(VISU_DATA(data));
  openGL_reDraw(width, height, data);
}

gboolean renderingWindowDump(RenderingWindow *window, DumpType *format, GString *buffer,
                       char* fileName, gint width, gint height,
                       voidDataFunc functionWait, gpointer data)
{
  guchar *imageData;
  int res;

  g_return_val_if_fail(IS_RENDERING_WINDOW(window), FALSE);
  g_return_val_if_fail(window->currentData, FALSE);

  g_return_val_if_fail(format && fileName && buffer, FALSE);

  if (format->bitmap)
    {
      DBG_fprintf(stderr, "Gtk RenderingWindow : dumping current OpenGL area.\n");
      DBG_fprintf(stderr, " | requested size %dx%d.\n", width, height);
      openGLWidgetSet_redraw(OPENGL_WIDGET(window->openGLArea),
                       redrawOffScreen, (gpointer)window->currentData);
      imageData = openGLWidgetGet_pixmapData(OPENGL_WIDGET(window->openGLArea),
                                   &width, &height, TRUE);
      visuDataSet_sizeOfView(VISU_DATA(window->currentData),
                       window->socketWidth, window->socketHeight);
      openGLWidgetSet_redraw(OPENGL_WIDGET(window->openGLArea),
                       openGL_reDraw, (gpointer)window->currentData);
      DBG_fprintf(stderr, " | allocated size %dx%d.\n", width, height);
      if (!imageData)
      {
        g_string_append_printf(buffer, _("Error! Can't dump OpenGL area to data.\n"));
        return FALSE;
      }
    }
  else
    imageData = (guchar*)0;

  res = format->writeFunc(format->fileType, buffer, fileName,
                    width, height, window->currentData,
                    imageData, functionWait, data);

  if (imageData)
    g_free(imageData);
  return (gboolean)!res;
}

static void onDumpButtonClicked(GtkButton *button, gpointer user_data)
{
  GtkWidget *dump;
  char *filename;
  DumpType *format;
  gboolean res;
  GString *buffer;
  GdkCursor *cursorWatch;
  GtkProgressBar *dumpBar;

  dump = dumpDialog_new(RENDERING_WINDOW(user_data)->currentData);
  if (gtk_dialog_run(GTK_DIALOG(dump)) != GTK_RESPONSE_ACCEPT)
    {
      gtk_widget_destroy(dump);
      return;
    }

  filename = dumpDialogGet_fileName(DUMP_DIALOG(dump));
  format = dumpDialogGet_dumpType(DUMP_DIALOG(dump));

  if (!format || !filename)
    {
      fprintf(stderr, "INTERNAL ERROR! The dump dialog doesn't"
            " return the desired format nor the chosen name.\n");
      exit(1);
    }
  DBG_fprintf(stderr, "Gtk StatusInfo : dump image to the file '%s' (format : %s)\n",
            filename, format->fileType->description);
  if (format->writeFunc)
    {
      cursorWatch = gdk_cursor_new(GDK_WATCH);
      dumpBar = dumpDialogGet_progressBar(DUMP_DIALOG(dump));
      gtk_progress_bar_set_fraction(dumpBar, 0.);
      buffer = g_string_new(_("Dumping the view to image file"));
      g_string_append_printf(buffer, _(" (format '%s').\n"), format->fileType->description);
      g_string_append_printf(buffer, _("Write to '%s'.\n\n"), filename);
      if (format->bitmap)
      gtk_progress_bar_set_text(dumpBar,
                          _("Waiting for generating image in memory..."));
      visuWaitFunction();
      gdk_window_set_cursor(GDK_WINDOW((GTK_WIDGET(dump))->window), cursorWatch);
      
      res = renderingWindowDump(RENDERING_WINDOW(user_data), format, buffer, filename,
                        dumpDialogGet_widthValue(DUMP_DIALOG(dump)),
                        dumpDialogGet_heightValue(DUMP_DIALOG(dump)),
                        updateDumpProgressBar, (gpointer)dumpBar);

      if (!res)
      raiseAlertDialog(buffer->str);
      gdk_window_set_cursor(GDK_WINDOW((GTK_WIDGET(dump))->window), NULL);
      g_string_free(buffer, TRUE);
    }
  gtk_widget_destroy(dump);
}

static void onRaiseButtonClicked(GtkButton *button, gpointer user_data)
{
  DBG_fprintf(stderr, "Gtk RenderingWindow : get a raise main window event.\n");

  /* During first run, the main window may not exist... */
  if (!mainWindow || !GDK_IS_WINDOW(mainWindow->window))
    return;

  /* We raised the command panel, if required. */
  gdk_window_raise(GDK_WINDOW(mainWindow->window));
}

void renderingWindowRedraw(RenderingWindow *window, gboolean forceRedraw)
{
  g_return_if_fail(IS_RENDERING_WINDOW(window));

  if (!getImmediateDrawing() && !forceRedraw)
    {
      DBG_fprintf(stderr, "Redraw rejected since drawing is deferred and not forced.\n");
      return;
    }
  DBG_fprintf(stderr, "Redraw accepted let's go...\n");

  openGLWidgetRedraw(OPENGL_WIDGET(window->openGLArea));
}

static void onRedraw(RenderingWindow *window, gpointer data)
{
  renderingWindowRedraw(window, FALSE);
}
static void onForceRedraw(RenderingWindow *window, gpointer data)
{
  renderingWindowRedraw(window, TRUE);
}


Generated by  Doxygen 1.6.0   Back to index