/* EXTRAITS DE LA LICENCE Copyright CEA, contributeurs : Luc BILLARD et Damien CALISTE, laboratoire L_Sim, (2001-2005) Adresse mèl : BILLARD, non joignable par mèl ; CALISTE, damien P caliste AT cea P fr. Ce logiciel est un programme informatique servant à visualiser des structures atomiques dans un rendu pseudo-3D. Ce logiciel est régi par la licence CeCILL soumise au droit français et respectant les principes de diffusion des logiciels libres. Vous pouvez utiliser, modifier et/ou redistribuer ce programme sous les conditions de la licence CeCILL telle que diffusée par le CEA, le CNRS et l'INRIA sur le site "http://www.cecill.info". Le fait que vous puissiez accéder à cet en-tête signifie que vous avez pris connaissance de la licence CeCILL, et que vous en avez accepté les termes (cf. le fichier Documentation/licence.fr.txt fourni avec ce logiciel). */ /* LICENCE SUM UP Copyright CEA, contributors : Luc BILLARD et Damien CALISTE, laboratoire L_Sim, (2001-2005) E-mail address: BILLARD, not reachable any more ; CALISTE, damien P caliste AT cea P fr. This software is a computer program whose purpose is to visualize atomic configurations in 3D. This software is governed by the CeCILL license under French law and abiding by the rules of distribution of free software. You can use, modify and/ or redistribute the software under the terms of the CeCILL license as circulated by CEA, CNRS and INRIA at the following URL "http://www.cecill.info". The fact that you are presently reading this means that you have had knowledge of the CeCILL license and that you accept its terms. You can find a copy of this licence shipped with this software at Documentation/licence.en.txt. */ #include <gtk/gtk.h> #include <glib.h> #include <locale.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> /* For the access markers R_OK, W_OK ... */ #include <sys/stat.h> #include <sys/types.h> #include "interface.h" #include "support.h" #include "callbacks.h" #include "gtk_main.h" #include "gtk_observePick.h" #include "gtk_pairs.h" #include "gtk_about.h" #include "gtk_renderingWindowWidget.h" #include "extraGtkFunctions/gtk_colorComboBoxWidget.h" #include "extraGtkFunctions/gtk_numericalEntryWidget.h" #include "panelModules/externalModules.h" #include "panelModules/externalRenderingMethods_gtk.h" #include "panelModules/panelDataFile.h" #include "panelModules/panelPlanes.h" #include "panelModules/panelSurfaces.h" #include "renderingMethods/renderingAtomic.h" #include "renderingMethods/renderingSpin.h" #include "opengl.h" #include "visu_object.h" #include "visu_rendering.h" #include "visu_data.h" #include "visu_configFile.h" #include "visu_basic.h" /* To have loadDataFromFile */ #include "visu_pairs.h" /* To have setPairsOnOff */ #include "visu_commandLine.h" /* To have getArgFilename and getXWindowGeometry*/ #include "visu_pickMesure.h" #include "OSOpenGL/visu_openGL.h" #include "renderingBackend/visu_windowInterface.h" #include "coreTools/toolShade.h" #include "coreTools/toolOptions.h" /****************/ /* Private part */ /****************/ /* Initialisation */ int initGtkMain(); void createCallBacksMain(); gboolean initVisuPostGTK(gpointer data); gboolean commandLineLoadWithGtk(gpointer data); /* Fuctions to rule the combobox. */ void initSubPanel(); void initListeSubPanel(); /* pointer on different buttons. */ GtkWidget *loadButton; GtkWidget *pairsButton; GtkWidget *pickObserveButton; /* Miscelaneous functions with gtk */ void loadFileWithGtk(VisuData **visuData); void setRenderingButtonSensitive(gboolean bool); void gtkMainAsk_optionValues(OptionTable *table, gpointer data); /* Local callbacks */ void checkPairsChanged(GtkToggleButton *togglebutton, gpointer user_data); void setFileButtonSensitive(GObject *obj, gpointer bool); static void onResourcesLoaded(GObject *visu, gpointer data); void onFileChange(GObject *obj, VisuData *dataObj, gpointer bool); void onHideNextTime(GtkToggleButton *button, gpointer data); static void onQuitButton(GtkButton *button, gpointer data); static gboolean onKillRenderingWindowEvent(GtkWidget *widget, GdkEvent *event, gpointer user_data); /* Parameter to store the position of windows. */ int rememberWindowPosition; GHashTable *windowPosition; #define PARAMETER_GTKMAIN_REMEMBER_DEFAULT 1 /* Parameter to change the policy of the warning quit dialog. */ gboolean warningWhenQuit; #define FLAG_PARAMETER_GTKMAIN_QUIT "main_confirmQuit" #define DESC_PARAMETER_GTKMAIN_QUIT "Show up a dialog to confirm when quit button is clicked ; boolean 0 or 1" #define PARAMETER_GTKMAIN_QUIT_DEFAULT TRUE gboolean readMainQuitPolicy(gchar **lines, int nbLines, int position, GString *errorMessage); #define FLAG_PARAMETER_GTKMAIN_PANEL "main_panelStatus" #define DESC_PARAMETER_GTKMAIN_PANEL "Attach a panel to a tool window ; panel_name window_name (or None or Main)" gboolean readMainPanelStatus(gchar **lines, int nbLines, int position, GString *errorMessage); #define FLAG_PARAMETER_GTKMAIN_DOCK "main_dock" #define DESC_PARAMETER_GTKMAIN_DOCK "Define the characteristic of a dock window ; size(x,y) position(w,h) visibility window_name" gboolean readMainDock(gchar **lines, int nbLines, int position, GString *errorMessage); gboolean exportParametersGtkMain(GString *data, int *nbLinesWritten, VisuData *dataObj); /* Store the last open directory. It is initialised to current working directory. */ gchar *lastOpenDirectory; /* Number of time V_Sim try to attach the OpenGL context. */ #define GTK_MAIN_N_MAX_OPENGL 10 /* Store some informations on gtk method associated with different rendering methods. */ struct renderingMethod_gtkMain_struct { createGtkWidgetFunc createOpenAddOn; createGtkLoadWidgetFunc createLoadAction; }; GHashTable *renderingMethod_gtkMain; /* Local variable for the statusbar stack */ gboolean statusInfo_isPicked; GtkWidget *vboxMain; int mainWithGtk(int argc, char *argv[]) { int width, height; gtk_init (&argc, &argv); /* Creating the visu object to handle the signals. */ visu = g_object_new (VISU_TYPE, NULL); /* Nullify uninitialized pointers. */ mainWindow = (GtkWidget*)0; /* Règle l'accès aux images */ add_pixmap_directory(v_sim_pixmaps_dir); initVisuMain(); DBG_fprintf(stderr,"--- Initialising the rendering window ---\n"); commandLineGet_XWindowGeometry(&width, &height); currentRenderingWindow = renderingWindow_new("V_Sim", "v_sim_render", "V_Sim", width, height); if (!currentRenderingWindow) exit(1); DBG_fprintf(stderr,"--- Initialising the new gtk classes ---\n"); /* Force the creation of the ColorComboBoxClass. */ g_type_class_ref(colorComboBox_get_type()); /* Force the creation of the VisuData class. */ g_type_class_ref(visu_data_get_type()); initGtkMain(); /* Others elements linked to the main window. */ DBG_fprintf(stderr, " | Gtk Pick and Observe"); initObserveAndPickWindow(); DBG_fprintf(stderr, " ... OK.\n"); DBG_fprintf(stderr, " | Gtk Pairs"); initPairsWindow(); DBG_fprintf(stderr, " ... OK.\n"); DBG_fprintf(stderr, " | Gtk About"); initAboutWindow(); DBG_fprintf(stderr, " ... OK.\n"); DBG_fprintf(stderr, "GTK Main : adding loading parameters and resources" " callbacks in the queue.\n"); g_idle_add(initVisuPostGTK, (gpointer)0); createCallBacksMain(); DBG_fprintf(stderr, "GTK Main : Creating callbacks.\n"); DBG_fprintf(stderr, "Gtk Main : starting main GTK loop.\n"); gtk_main (); return 0; } int initGtkMain() { int i; VisuConfigFileEntry *resourceEntry; /* Init the signal object for gtk stuffs. */ visuGtkObject = g_object_new(VISU_GTK_TYPE, NULL); /* Set local variables */ statusInfo_isPicked = FALSE; /* Retrieve the current working directory. */ setLastOpenDirectory((char*)g_get_current_dir()); /* Create the hashtable to store windows and their position. */ windowPosition = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, freeInt); setRememberPosition(PARAMETER_GTKMAIN_REMEMBER_DEFAULT); /* Create parameters. */ warningWhenQuit = PARAMETER_GTKMAIN_QUIT_DEFAULT; resourceEntry = visuConfigFileAdd_entry(VISU_CONFIGFILE_PARAMETER, FLAG_PARAMETER_GTKMAIN_QUIT, DESC_PARAMETER_GTKMAIN_QUIT, 1, readMainQuitPolicy); resourceEntry = visuConfigFileAdd_entry(VISU_CONFIGFILE_PARAMETER, FLAG_PARAMETER_GTKMAIN_PANEL, DESC_PARAMETER_GTKMAIN_PANEL, 1, readMainPanelStatus); resourceEntry = visuConfigFileAdd_entry(VISU_CONFIGFILE_PARAMETER, FLAG_PARAMETER_GTKMAIN_DOCK, DESC_PARAMETER_GTKMAIN_DOCK, 1, readMainDock); visuConfigFileAdd_exportFunction(VISU_CONFIGFILE_PARAMETER, exportParametersGtkMain); /* Create the hashtable of rendering method gtk functions. */ renderingMethod_gtkMain = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, freeGPointer); for (i = 0; listInitRendenringGtkFunc[i]; i++) listInitRendenringGtkFunc[i](); /* Initialise dependant gtk elements. */ DBG_fprintf(stderr, "--- Initialising the GTK interface ---\n"); DBG_fprintf(stderr, " | Gtk Main"); mainWindow = create_main_window (); gtk_window_set_wmclass(GTK_WINDOW(mainWindow), "v_sim_commandPanel", "V_Sim"); DBG_fprintf(stderr, " ... OK.\n"); /* Signals and naming of widgets specific to the main window. */ vboxMain = lookup_widget(mainWindow, "vboxMainWindow"); loadButton = lookup_widget(mainWindow, "loadButton"); pairsButton = lookup_widget(mainWindow, "pairsButton"); pickObserveButton = lookup_widget(mainWindow, "pickObserveButton"); /* init the sub panel contains. */ initSubPanel(); return 1; } void createCallBacksMain() { GtkWidget *wd; /* Initialise the interface. */ wd = lookup_widget(mainWindow, "checkPairs"); g_signal_connect(G_OBJECT(wd), "toggled", G_CALLBACK(checkPairsChanged), (gpointer)0); wd = lookup_widget(mainWindow, "buttonQuit"); g_signal_connect(G_OBJECT(wd), "clicked", G_CALLBACK(onQuitButton), (gpointer)0); /* Set the quit and destroy signals. */ g_signal_connect(G_OBJECT(mainWindow), "delete-event", G_CALLBACK(onKillRenderingWindowEvent), (gpointer)0); g_signal_connect(G_OBJECT(mainWindow), "destroy-event", G_CALLBACK(onKillRenderingWindowEvent), (gpointer)0); g_signal_connect(G_OBJECT(visu), "dataReadyForRendering", G_CALLBACK(onFileChange), (gpointer)0); g_signal_connect(G_OBJECT(visu), "renderingChanged", G_CALLBACK(setFileButtonSensitive), (gpointer)0); g_signal_connect(G_OBJECT(visu), "resourcesLoaded", G_CALLBACK(onResourcesLoaded), (gpointer)0); } gboolean initVisuPostGTK(gpointer data) { char* path; int res; char *filename, *spin_filename; gchar *dirname, *normDir; GtkWidget *wd; VisuData *newData; GString *errorMessage; int width, height; /* struct timespec timeToSleep; */ commandLineGet_XWindowGeometry(&width, &height); OpenGLViewSet_windowSize((OpenGLView*)0, (guint)width, (guint)height); DBG_fprintf(stderr,"--- Initialising the parameters ---\n"); /* Save the gtk tag as a known tag to allow to read such parameters. */ visuConfigFileAdd_knownTag("gtk"); /* Look for parameters file */ path = visuConfigFileGet_validPath(VISU_CONFIGFILE_PARAMETER, R_OK, 0); if (path) { errorMessage = (GString*)0; res = visuConfigFileLoad(VISU_CONFIGFILE_PARAMETER, path, &errorMessage); if (!res && errorMessage) raiseAlertDialogWithScrollView(errorMessage->str); if (errorMessage) g_string_free(errorMessage, TRUE); free(path); } else raiseAlertDialog(_("Unable to find a valid parameters file. Starting with defaults.")); DBG_fprintf(stderr,"--- Initialising resources ---\n"); /* Look for resources file */ path = visuConfigFileGet_validPath(VISU_CONFIGFILE_RESOURCE, R_OK, 0); if (path) { errorMessage = (GString*)0; res = visuConfigFileLoad(VISU_CONFIGFILE_RESOURCE, path, &errorMessage); if (!res && errorMessage) raiseAlertDialogWithScrollView(errorMessage->str); if (errorMessage) g_string_free(errorMessage, TRUE); free(path); } newData = (VisuData*)0; filename = commandLineGet_ArgFilename(); spin_filename = commandLineGet_ArgSpinFileName(); if (spin_filename && filename) { setRenderingMethodInUse(pointerOnRenderingSpinMethod); newData = visuDataNew(); if (!newData) exit(1); dirname = g_path_get_dirname(filename); normDir = normalize_path(dirname); setLastOpenDirectory((char*)normDir); g_free(dirname); g_free(normDir); visuDataAdd_file(newData, filename, FILE_KIND_POSITION, (FileFormat*)0); visuDataAdd_file(newData, spin_filename, FILE_KIND_SPIN, (FileFormat*)0); free(spin_filename); free(filename); spin_filename = (char*)0; filename = (char*)0; DBG_fprintf(stderr, "GTK Main : adding the load call back in the queue.\n"); g_idle_add(commandLineLoadWithGtk, (gpointer)newData); } else if (filename) { setRenderingMethodInUse(pointerOnRenderingAtomicMethod); newData = visuDataNew(); if (!newData) exit(1); dirname = g_path_get_dirname(filename); normDir = normalize_path(dirname); setLastOpenDirectory((char*)normDir); g_free(dirname); g_free(normDir); visuDataAdd_file(newData, filename, FILE_KIND_POSITION, (FileFormat*)0); free(filename); filename = (char*)0; DBG_fprintf(stderr, "GTK Main : adding the load call back in the queue.\n"); g_idle_add(commandLineLoadWithGtk, (gpointer)newData); } else { setRenderingButtonSensitive(FALSE); } if (spin_filename) free(spin_filename); if (filename) free(filename); /* Initialise the buttons of the main interface. */ wd = lookup_widget(mainWindow, "checkPairs"); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(wd), (gboolean)getPairsOnOff()); gtk_widget_show (mainWindow); return FALSE; } gboolean commandLineLoadWithGtk(gpointer data) { int i, somethingIsLoaded, presetShade, nb; gboolean res; gchar *colorizeFilename, *planeFile, *surfFile; float *values; int *colUsed; float *translations; GList *list; Shade *shade; VisuData *obj; GError *error; OptionTable *table; gchar **names; obj = (VisuData*)data; loadFileWithGtk(&obj); /* Post loading sequence, corresponding to all other arguments given to command line. */ /* translate argument */ if (obj) { translations = commandLineGet_translation(); if (translations) { visuDataSet_XYZtranslation(obj, translations); visuData_constrainedInTheBox(obj); } } visuRenderingWindowSet_visuData(visuRenderingWindowGet_current(), obj); if (!obj) { return FALSE; } /* Post loading sequence, corresponding to all other arguments given to command line. */ /* colorize argument */ colorizeFilename = commandLineGet_colorizeFileName(); if (colorizeFilename) { somethingIsLoaded = panelDataFileLoad_file(obj, colorizeFilename); if (somethingIsLoaded) { colUsed = commandLineGet_colorizeColUsed(); if (colUsed) for (i = 0; i < 3; i++) dataFileSet_colUsed(obj, colUsed[i] - 1, i); else { presetShade = commandLineGet_colorizePresetColor(); if (presetShade < 0) presetShade = 0; list = toolShadeBuild_presetList(); if (list) { shade = (Shade*)g_list_nth_data(list, presetShade); if (shade) dataFileSet_shade(obj, shade); } } } } /* plane file argument */ planeFile = commandLineGet_planesFileName(); if (planeFile) { panelPlanesSet_use(obj, TRUE); error = (GError*)0; res = panelPlanesLoad_file(obj, planeFile, &error); if (error) { raiseAlertDialog(error->message); g_clear_error(&error); } else if (res) panelPlanesApply_hidingScheme(obj); } /* iso-surface argument. */ table = commandLineGet_options(); surfFile = commandLineGet_isoSurfacesFileName(); if (surfFile) { res = panelIsosurfacesLoad_file(surfFile, commandLineGet_fitToBox(), obj, table); if (!res) { panelIsosurfacesShow_all(TRUE); panelIsosurfacesSet_used(obj, TRUE); } } /* scalar field argument. */ surfFile = commandLineGet_scalarFieldFileName(); if (surfFile) { res = panelIsosurfacesLoad_file(surfFile, commandLineGet_fitToBox(), obj, table); if (!res) { values = commandLineGet_isoValues(&nb); names = commandLineGet_isoNames(&nb); for (i = 0; i < nb; i++) panelIsosurfacesAdd_withValue(surfFile, values[i], names[i]); panelIsosurfacesShow_all(TRUE); panelIsosurfacesSet_used(obj, TRUE); } } visuData_createAllNodes(obj); g_signal_emit (visu, VISU_GET_CLASS (visu)->OpenGLAskForReDraw_signal_id, 0 , NULL); return FALSE; } gboolean loadAndRenderFileWithGtk(gpointer data) { VisuData *obj; obj = VISU_DATA(data); loadFileWithGtk(&obj); visuRenderingWindowSet_visuData(visuRenderingWindowGet_current(), obj); if (!obj) return FALSE; visuData_createAllNodes(obj); g_signal_emit (visu, VISU_GET_CLASS (visu)->OpenGLAskForReDraw_signal_id, 0 , NULL); return FALSE; } /**********************************/ /* Fuctions to rule the notebook. */ /**********************************/ void initSubPanel() { int i; ToolPanel *panel; DockWindow *dockMain; GtkWidget *wd; dockMain = toolPanelClassGet_commandPanel(); wd = dockWindowGet_container(dockMain); gtk_box_pack_start(GTK_BOX(vboxMain), wd, TRUE, TRUE, 0); gtk_widget_show_all(wd); for (i = 0; listSubPanelInitFunc[i]; i++) { panel = listSubPanelInitFunc[i](); if (!panel) g_error("Can't initialise subpanel number %d.\n", i); toolPanelAttach(panel, dockMain); gtk_widget_show(GTK_WIDGET(panel)); DBG_fprintf(stderr, "Gtk Main : initialise '%s' subpanel OK.\n", toolPanelGet_label(panel)); } } /*******************/ /* Local callbacks */ /*******************/ void setRenderingButtonSensitive(gboolean bool) { gtk_widget_set_sensitive(pairsButton, bool); gtk_widget_set_sensitive(pickObserveButton, bool); } void onFileChange(GObject *obj, VisuData *dataObj, gpointer bool) { if (dataObj) setRenderingButtonSensitive(TRUE); else setRenderingButtonSensitive(FALSE); toolPanelClassSet_visuData(dataObj); } static void onResourcesLoaded(GObject *visu, gpointer data) { GtkWidget *wd; wd = lookup_widget(mainWindow, "checkPairs"); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(wd), (gboolean)getPairsOnOff()); } void setFileButtonSensitive(GObject *obj, gpointer bool) { if (getRenderingMethodInUse()) gtk_widget_set_sensitive(loadButton, TRUE); else gtk_widget_set_sensitive(loadButton, FALSE); setRenderingButtonSensitive(FALSE); } void checkPairsChanged(GtkToggleButton *togglebutton, gpointer user_data) { gboolean res; RenderingWindow *window; res = gtk_toggle_button_get_active(togglebutton); setPairsOnOff(res); if (res) { window = RENDERING_WINDOW(visuRenderingWindowGet_current()); g_return_if_fail(window); if (createPairs(renderingWindowGet_visuData(window))) g_signal_emit (visu, VISU_GET_CLASS (visu)->OpenGLAskForReDraw_signal_id, 0 , NULL); } else g_signal_emit (visu, VISU_GET_CLASS (visu)->OpenGLAskForReDraw_signal_id, 0 , NULL); } /*****************/ /* Miscellaneous */ /*****************/ char* getLastOpenDirectory() { DBG_fprintf(stderr, "Gtk Main : get the last open directory : '%s'.\n", lastOpenDirectory); return lastOpenDirectory; } void setLastOpenDirectory(char* directory) { if (lastOpenDirectory) g_free(lastOpenDirectory); if (!g_path_is_absolute(directory)) lastOpenDirectory = g_build_filename(g_get_current_dir(), directory, NULL); else lastOpenDirectory = g_build_filename(directory, NULL); DBG_fprintf(stderr, "Gtk Main : set the last open directory to '%s', OK.\n", lastOpenDirectory); } /* This method loads the general function to load data from file and deals with errors with gtkDialogs. */ void loadFileWithGtk(VisuData **visuData) { GError *error; VisuData *prevData; gboolean changeElement, res; RenderingWindow *window; if (!visuData) return; window = RENDERING_WINDOW(visuRenderingWindowGet_current()); g_return_if_fail(window); prevData = renderingWindowGet_visuData(window); DBG_fprintf(stderr, "Gtk main : loading process ... %p points to" " previous VisuData.\n", (gpointer)prevData); error = (GError*)0; res = visuBasicLoad_dataFromFile(*visuData, (FileFormat*)0, &error); if (error) { raiseAlertDialog(error->message); g_error_free(error); } if (!res) { g_object_unref(*visuData); *visuData = (VisuData*)0; if (!error) g_warning("No error message!"); } DBG_fprintf(stderr, "Gtk main : loading process ... %p points to" " previous VisuData.\n", (gpointer)prevData); if (prevData && *visuData) { changeElement = visuData_compareElements(prevData, *visuData); visuDataSet_changeElementFlag(*visuData, changeElement); } return; } void setRememberPosition(int val) { DBG_fprintf(stderr, "GTK Main : set the remember parameter to %d.\n", val); rememberWindowPosition = val; } int getRememberPosition() { return rememberWindowPosition; } gchar* getSelectedDirectory() { GtkWidget *file_selector; gchar *dirname; char *directory; /* Create the selector */ file_selector = gtk_file_chooser_dialog_new(_("Choose a directory"), GTK_WINDOW(mainWindow), GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_OPEN, GTK_RESPONSE_OK, NULL); directory = getLastOpenDirectory(); if (directory) gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(file_selector), directory); gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(file_selector), FALSE); gtk_widget_set_name(file_selector, "filesel"); gtk_window_set_position(GTK_WINDOW(file_selector), GTK_WIN_POS_CENTER_ON_PARENT); gtk_window_set_modal(GTK_WINDOW (file_selector), TRUE); if (gtk_dialog_run (GTK_DIALOG (file_selector)) == GTK_RESPONSE_OK) { dirname = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER (file_selector)); setLastOpenDirectory(dirname); } else dirname = (gchar*)0; gtk_widget_destroy (file_selector); return dirname; } /* This method hides the specified window and save its coordinates if it is specified by a parameter. */ void visuHideWindow(GtkWindow *win) { int *val; if (!win) return; if (rememberWindowPosition) { val = (int*)g_hash_table_lookup(windowPosition, win); if (!val) { val = malloc(sizeof(int) * 2); if (!val) { allocationProblems(); exit(1); } g_hash_table_insert(windowPosition, (gpointer)win, (gpointer)val); } gtk_window_get_position(win, &val[0], &val[1]); DBG_fprintf(stderr, "Gtk Main : store position (%d,%d) for window %d.\n", val[0], val[1], GPOINTER_TO_INT(win)); } gtk_widget_hide(GTK_WIDGET(win)); } /* This method shows the specified window and try to put it at its former position if the good parameter is used. */ void visuShowWindow(GtkWindow *win) { int *val; if (!win) return; if (rememberWindowPosition) { val = (int*)g_hash_table_lookup(windowPosition, win); if (val) { gtk_window_move(win, val[0], val[1]); DBG_fprintf(stderr, "Gtk Main : set position (%d,%d) for window %d.\n", val[0], val[1], GPOINTER_TO_INT(win)); } } gtk_widget_show(GTK_WIDGET(win)); } /* Draw the alert window with the specified message. */ void raiseAlertDialog(char *message) { GtkWidget *alert; GtkWidget *label; GtkWidget *wd; alert = create_alertDialog (); label = lookup_widget(alert, "alertLabel"); gtk_label_set_text(GTK_LABEL(label), message); gtk_widget_set_name(alert, "error"); wd = lookup_widget(alert, "buttonAlert"); gtk_widget_set_name(wd, "error_button"); gtk_widget_show (alert); /* block in a loop waiting for reply. */ gtk_dialog_run (GTK_DIALOG (alert)); gtk_widget_destroy(alert); } /* Draw the alert window with the specified message. */ void raiseAlertDialogWithScrollView(char *message) { GtkWidget *alert; GtkWidget *text; GtkWidget *wd; GtkTextBuffer *buf; alert = create_alertDialogLong (); text = lookup_widget(alert, "alertText"); buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW(text)); if (message) gtk_text_buffer_set_text (GTK_TEXT_BUFFER(buf), message, -1); else gtk_text_buffer_set_text (GTK_TEXT_BUFFER(buf), _("INTERNAL ERROR! No message available!"), -1); gtk_widget_set_name(alert, "error"); wd = lookup_widget(alert, "buttonAlert"); gtk_widget_set_name(wd, "error_button"); gtk_widget_show (alert); /* block in a loop waiting for reply. */ gtk_dialog_run (GTK_DIALOG (alert)); gtk_widget_destroy(alert); } /* This function must be called in a blocking loop to update different things like the gtk for example. */ void visuWaitFunction() { while(gtk_events_pending()) gtk_main_iteration(); } GList* gtkMainCreate_fileChooserFilter(GList *list, GtkWidget *fileChooser) { GtkFileFilter *filter, *filterAll; GList *tmpLst, *tmpLst2; char *name; FileFilterCustom *data; GList *returnedFilters; DBG_fprintf(stderr, "Gtk Main : creating list of filters.\n"); returnedFilters = (GList*)0; filterAll = gtk_file_filter_new (); gtk_file_filter_set_name(filterAll, _("All supported formats")); tmpLst = list; while(tmpLst) { filter = gtk_file_filter_new (); name = fileFormatGet_label((FileFormat*)tmpLst->data); if (name) gtk_file_filter_set_name(filter, name); else gtk_file_filter_set_name(filter, _("No description")); tmpLst2 = ((FileFormat*)tmpLst->data)->fileType; while (tmpLst2) { gtk_file_filter_add_pattern (filter, (char*)tmpLst2->data); gtk_file_filter_add_pattern (filterAll, (char*)tmpLst2->data); tmpLst2 = g_list_next(tmpLst2); } data = g_malloc(sizeof(FileFilterCustom)); data->gtkFilter = filter; data->visuFilter = (FileFormat*)tmpLst->data; returnedFilters = g_list_append(returnedFilters, (gpointer)data); tmpLst = g_list_next(tmpLst); } data = g_malloc(sizeof(FileFilterCustom)); data->gtkFilter = filterAll; data->visuFilter = (FileFormat*)0; returnedFilters = g_list_append(returnedFilters, (gpointer)data); filter = gtk_file_filter_new (); gtk_file_filter_set_name(filter, "All files"); gtk_file_filter_add_pattern (filter, "*"); data = g_malloc(sizeof(FileFilterCustom)); data->gtkFilter = filter; data->visuFilter = (FileFormat*)0; returnedFilters = g_list_append(returnedFilters, (gpointer)data); DBG_fprintf(stderr, "Gtk Main : attach list to the given filechooser.\n"); tmpLst = returnedFilters; while(tmpLst) { gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(fileChooser), ((FileFilterCustom*)tmpLst->data)->gtkFilter); tmpLst = g_list_next(tmpLst); } gtk_file_chooser_set_filter(GTK_FILE_CHOOSER(fileChooser), filterAll); return returnedFilters; } int gtkMainCreate_defaultFileChooser(VisuData *data, GtkFileChooser **fileChooser, GtkWidget **fileWidget) { GtkWidget *fileSelection; GList *filters, *tmpLst; RenderingMethod *method; gchar* directory, *filename; FileFormat *selectedFormat; GtkFileFilter *filterDefault; int res; if (!data) return 0; method = getRenderingMethodInUse(); g_return_val_if_fail(method, -1); fileSelection = gtk_file_chooser_dialog_new(_("Load session"), GTK_WINDOW(mainWindow), GTK_FILE_CHOOSER_ACTION_OPEN, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_OPEN, GTK_RESPONSE_OK, NULL); *fileChooser = GTK_FILE_CHOOSER(fileSelection); *fileWidget = fileSelection; directory = getLastOpenDirectory(); if (directory) gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(fileSelection), directory); gtk_widget_set_name(fileSelection, "filesel"); gtk_window_set_position(GTK_WINDOW(fileSelection), GTK_WIN_POS_CENTER_ON_PARENT); gtk_window_set_modal(GTK_WINDOW(fileSelection), TRUE); filters = gtkMainCreate_fileChooserFilter(method->fileType[0], fileSelection); if (gtk_dialog_run(GTK_DIALOG(fileSelection)) == GTK_RESPONSE_OK) { /* Get the selected filter. */ selectedFormat = (FileFormat*)0; filterDefault = gtk_file_chooser_get_filter(GTK_FILE_CHOOSER(fileSelection)); tmpLst = filters; while(tmpLst) { if (filterDefault == ((FileFilterCustom*)tmpLst->data)->gtkFilter) selectedFormat = ((FileFilterCustom*)tmpLst->data)->visuFilter; tmpLst = g_list_next(tmpLst); } filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(fileSelection)); visuDataAdd_file(data, filename, 0, selectedFormat); g_free(filename); res = 1; } else res = 0; /* Free the filters list. */ DBG_fprintf(stderr, "Gtk Main : free load dialog.\n"); tmpLst = filters; while(tmpLst) { g_free(tmpLst->data); tmpLst = g_list_next(tmpLst); } g_list_free(filters); return res; } void gtkMainSet_renderingSpecificMethods(RenderingMethod *method, createGtkWidgetFunc createLoadWidget, createGtkLoadWidgetFunc methodLoad) { struct renderingMethod_gtkMain_struct *container; if (!method) return; container = malloc(sizeof(struct renderingMethod_gtkMain_struct)); if (!container) { allocationProblems(); exit(1); } container->createOpenAddOn = createLoadWidget; container->createLoadAction = methodLoad; g_hash_table_insert(renderingMethod_gtkMain, (gpointer)method, (gpointer)container); } createGtkLoadWidgetFunc gtkMainGet_renderingSpecificOpen(RenderingMethod *method) { struct renderingMethod_gtkMain_struct *container; if (!method) return (createGtkLoadWidgetFunc)0; DBG_fprintf(stderr, "Gtk Main : looking for a specific load interface for rendering" " method '%s'...\n", method->name); container = (struct renderingMethod_gtkMain_struct *) g_hash_table_lookup(renderingMethod_gtkMain, (gpointer)method); if (!container) return (createGtkLoadWidgetFunc)0; if (container->createLoadAction) return container->createLoadAction; else return gtkMainCreate_defaultFileChooser; } void onHideNextTime(GtkToggleButton *button, gpointer data) { char *posNext; gchar *path, *bufferR, *pos; GString *errorMessage, *bufferW, *bufferW2; gboolean resOk; int lines; GIOChannel *file; GError *err; gsize taille; GIOStatus statOK; g_return_if_fail(data); path = (gchar*)data; DBG_fprintf(stderr, "Gtk Main : change the warning dialog parameter in file '%s'.\n", path); warningWhenQuit = !gtk_toggle_button_get_active(button); /* If no file exists in the given path, we create it. */ if (!g_file_test(path, G_FILE_TEST_EXISTS)) { errorMessage = (GString*)0; resOk = visuConfigFileSave(VISU_CONFIGFILE_PARAMETER, path, &errorMessage, &lines, (VisuData*)0); if (!resOk) { if (errorMessage) raiseAlertDialogWithScrollView(errorMessage->str); } if (errorMessage) { DBG_fprintf(stderr, "Gtk Main : trace from exporting par...\n%s", errorMessage->str); g_string_free(errorMessage, TRUE); } return; } /* If a parameter file already exist, we then just change the right line. */ err = (GError*)0; file = g_io_channel_new_file(path, "r", &err); if (err) { raiseAlertDialogWithScrollView(err->message); g_error_free(err); return; } bufferR = (gchar*)0; err = (GError*)0; statOK = g_io_channel_read_to_end(file, &bufferR, &taille, &err); if (err) { raiseAlertDialogWithScrollView(err->message); g_error_free(err); g_io_channel_shutdown(file, FALSE, (GError**)0); g_io_channel_unref(file); return; } g_io_channel_shutdown(file, FALSE, (GError**)0); g_io_channel_unref(file); /* We reopen the channel in write acces. */ err = (GError*)0; file = g_io_channel_new_file(path, "w", &err); if (err) { raiseAlertDialogWithScrollView(err->message); g_error_free(err); return; } bufferW = g_string_new(bufferR); g_free(bufferR); /* Try to find the flag of the parameter. */ pos = g_strrstr(bufferW->str, "\n"FLAG_PARAMETER_GTKMAIN_QUIT); if (!pos) { /* We append it at the end of the file. */ DBG_fprintf(stderr, " | Can't find the option, appending it.\n"); exportParametersGtkMain(bufferW, &lines, (VisuData*)0); err = (GError*)0; statOK = g_io_channel_write_chars(file, bufferW->str, -1, &taille, &err); if (err) { raiseAlertDialogWithScrollView(err->message); g_error_free(err); } } else { DBG_fprintf(stderr, " | Option found, changing its value.\n"); /* We erase the line and rewrite it. */ *(pos + 1) = '\0'; bufferW2 = g_string_new(bufferW->str); g_string_append_printf(bufferW2, "%s[gtk]: %i\n", FLAG_PARAMETER_GTKMAIN_QUIT, (int)warningWhenQuit); posNext = strstr(pos + 2, "\n"); if (posNext) g_string_append(bufferW2, posNext + 1); err = (GError*)0; statOK = g_io_channel_write_chars(file, bufferW2->str, -1, &taille, &err); if (err) { raiseAlertDialogWithScrollView(err->message); g_error_free(err); } g_string_free(bufferW2, TRUE); } g_io_channel_shutdown(file, TRUE, (GError**)0); g_io_channel_unref(file); g_string_free(bufferW, TRUE); } static void onAddHomedir(GtkButton *button, gpointer quitDialog) { GtkWidget *wd; GList *dirs, *tmplst; gchar *path; DBG_fprintf(stderr, "Gtk Main: try to create the local home directory.\n"); #if SYSTEM_X11 == 1 if (mkdir(v_sim_local_conf_dir, 750)) #endif #if SYSTEM_WIN32 == 1 if (mkdir(v_sim_local_conf_dir)) #endif { /* Failed. */ raiseAlertDialog(_("Can't create the directory '$HOME/.v_sim'.")); } else { /* Succeed hide the warning. */ wd = lookup_widget(GTK_WIDGET(quitDialog), "hboxHomedir"); gtk_widget_hide(wd); /* Retest the path. */ dirs = (GList*)0; dirs = g_list_prepend(dirs, (gpointer)v_sim_conf_dir); dirs = g_list_prepend(dirs, (gpointer)v_sim_local_conf_dir); tmplst = dirs; path = (gchar*)0; path = visuConfigFileGet_nextValidPath(VISU_CONFIGFILE_PARAMETER, W_OK, &tmplst, 0); if (path) { wd = lookup_widget(GTK_WIDGET(quitDialog), "hboxWarning"); gtk_widget_hide(wd); wd = lookup_widget(GTK_WIDGET(quitDialog), "checkbuttonHideNextTime"); gtk_widget_set_sensitive(wd, TRUE); g_signal_connect(G_OBJECT(wd), "toggled", G_CALLBACK(onHideNextTime), (gpointer)path); } g_list_free(dirs); } } static gboolean onKillRenderingWindowEvent(GtkWidget *widget, GdkEvent *event, gpointer user_data) { onQuitButton((GtkButton *)0, (gpointer)0); return TRUE; } static void onQuitButton(GtkButton *button, gpointer data) { GtkWidget *quitDialog, *wd; GList *dirs, *tmplst; gchar *path; if (!warningWhenQuit) { gtk_main_quit(); return; } quitDialog = create_quitDialog(); /* Try to find installDir/v_sim.par or ~/.v_sim/v_sim.par that is writable to store the preference of the hiding mode of the dialog. */ dirs = (GList*)0; dirs = g_list_prepend(dirs, (gpointer)v_sim_conf_dir); dirs = g_list_prepend(dirs, (gpointer)v_sim_local_conf_dir); tmplst = dirs; path = (gchar*)0; path = visuConfigFileGet_nextValidPath(VISU_CONFIGFILE_PARAMETER, W_OK, &tmplst, 0); if (!path) { wd = lookup_widget(quitDialog, "hboxWarning"); gtk_widget_show(wd); } g_list_free(dirs); /* Attach a create the homedir method to the button. */ wd = lookup_widget(quitDialog, "buttonAddHomedir"); g_signal_connect(G_OBJECT(wd), "clicked", G_CALLBACK(onAddHomedir), (gpointer)quitDialog); /* Show the warning if the homedir is not existing and no path was found. */ if (!g_file_test(v_sim_local_conf_dir, G_FILE_TEST_IS_DIR) && !path) { wd = lookup_widget(quitDialog, "hboxHomedir"); gtk_widget_show(wd); } /* Attach a modify the parameter to the checkbox. */ wd = lookup_widget(quitDialog, "checkbuttonHideNextTime"); if (!path) gtk_widget_set_sensitive(wd, FALSE); else g_signal_connect(G_OBJECT(wd), "toggled", G_CALLBACK(onHideNextTime), (gpointer)path); if (gtk_dialog_run(GTK_DIALOG(quitDialog)) == GTK_RESPONSE_OK) gtk_main_quit(); else gtk_widget_destroy(quitDialog); } gboolean readMainQuitPolicy(gchar **lines, int nbLines, int position, GString *errorMessage) { int res; int bool; res = sscanf(lines[0],"%d", &bool); if (res != 1) { if (errorMessage) g_string_append_printf(errorMessage, _("WARNING! Parse error at line %d," " 1 boolean value must appear" " after the %s markup.\n"), position, FLAG_PARAMETER_GTKMAIN_QUIT); warningWhenQuit = PARAMETER_GTKMAIN_QUIT_DEFAULT; return FALSE; } if (bool) warningWhenQuit = TRUE; else warningWhenQuit = FALSE; return TRUE; } gboolean readMainPanelStatus(gchar **lines, int nbLines, int position, GString *errorMessage) { gchar **tokens; ToolPanel *toolpanel; char *pt; tokens = g_strsplit(g_strchug(lines[0]), " ", 2); if (!tokens[0] || !tokens[1]) { if (errorMessage) g_string_append_printf(errorMessage, _("WARNING! Parse error at line %d," " 'id id' awaited.\n"), position); g_strfreev(tokens); return FALSE; } toolpanel = toolPanelClassGet_toolPanelById(tokens[0]); if (!toolpanel) { if (errorMessage) g_string_append_printf(errorMessage, _("WARNING! Parse error at line %d," " unknown panel id '%s'.\n"), position, tokens[0]); g_strfreev(tokens); return FALSE; } pt = strchr(tokens[1], '\n'); if (pt) *pt = ' '; toolPanelSet_containerId(toolpanel, g_strchomp(tokens[1])); g_strfreev(tokens); return TRUE; } gboolean readMainDock(gchar **lines, int nbLines, int position, GString *errorMessage) { int res; gchar **tokens, *values; gboolean visible; int x, y, width, height; tokens = g_strsplit(g_strchug(lines[0]), " ", 4); if (!tokens[0] || !tokens[1] || !tokens[2] || !tokens[3]) { if (errorMessage) g_string_append_printf(errorMessage, _("WARNING! Parse error at line %d," " 'values id' awaited.\n"), position); g_strfreev(tokens); return FALSE; } values = g_strjoin(" ", tokens[0], tokens[1], tokens[2], NULL); res = sscanf(values, "%d %dx%d %dx%d", (int*)&visible, &x, &y, &width, &height); g_free(values); if (res != 5) { if (errorMessage) g_string_append_printf(errorMessage, _("WARNING! Parse error at line %d," " can't read dock characteristics" " value from '%s'.\n"), position, values); g_strfreev(tokens); return FALSE; } toolPanelClassSet_windowSize(g_strchomp(tokens[3]), (guint)width, (guint)height); toolPanelClassSet_windowPosition(tokens[3], (guint)x, (guint)y); toolPanelClassSet_windowVisibility(tokens[3], visible); g_strfreev(tokens); return TRUE; } gboolean exportParametersGtkMain(GString *data, int *nbLinesWritten, VisuData* dataObj) { GList *tmplst, *panelLst, *dockLst; gint x, y, width, height; gboolean visilibity; gchar *id; g_string_append_printf(data, "# %s\n", DESC_PARAMETER_GTKMAIN_QUIT); g_string_append_printf(data, "%s[gtk]: %i\n\n", FLAG_PARAMETER_GTKMAIN_QUIT, (int)warningWhenQuit); *nbLinesWritten = 3; /* Write the panel list. */ panelLst = toolPanelClassGet_allToolPanels(); if (panelLst) { g_string_append_printf(data, "# %s\n", DESC_PARAMETER_GTKMAIN_PANEL); *nbLinesWritten += 1; } tmplst = panelLst; while(tmplst) { g_string_append_printf(data, "%s[gtk]: %s %s\n", FLAG_PARAMETER_GTKMAIN_PANEL, toolPanelGet_id(TOOL_PANEL(tmplst->data)), toolPanelGet_containerId(TOOL_PANEL(tmplst->data))); *nbLinesWritten += 1; tmplst = g_list_next(tmplst); } if (panelLst) { g_string_append_printf(data, "\n"); *nbLinesWritten += 1; } g_list_free(panelLst); /* Write the panel list. */ dockLst = toolPanelClassGet_allWindows(); if (dockLst) { g_string_append_printf(data, "# %s\n", DESC_PARAMETER_GTKMAIN_DOCK); *nbLinesWritten += 1; } tmplst = dockLst; while(tmplst) { toolPanelClassGet_windowCharacteristics((DockWindow*)(tmplst->data), &id, &visilibity, &x, &y, &width, &height); g_string_append_printf(data, "%s[gtk]: %d %dx%d %dx%d %s\n", FLAG_PARAMETER_GTKMAIN_DOCK, (int)visilibity, x, y, width, height, id); *nbLinesWritten += 1; tmplst = g_list_next(tmplst); } if (dockLst) { g_string_append_printf(data, "\n"); *nbLinesWritten += 1; } g_list_free(dockLst); return TRUE; }