1 /*   EXTRAITS DE LA LICENCE
2 	Copyright CEA, contributeurs : Luc BILLARD et Damien
3 	CALISTE, laboratoire L_Sim, (2001-2005)
4 
5 	Adresse mèl :
6 	BILLARD, non joignable par mèl ;
7 	CALISTE, damien P caliste AT cea P fr.
8 
9 	Ce logiciel est un programme informatique servant à visualiser des
10 	structures atomiques dans un rendu pseudo-3D.
11 
12 	Ce logiciel est régi par la licence CeCILL soumise au droit français et
13 	respectant les principes de diffusion des logiciels libres. Vous pouvez
14 	utiliser, modifier et/ou redistribuer ce programme sous les conditions
15 	de la licence CeCILL telle que diffusée par le CEA, le CNRS et l'INRIA
16 	sur le site "http://www.cecill.info".
17 
18 	Le fait que vous puissiez accéder à cet en-tête signifie que vous avez
19 	pris connaissance de la licence CeCILL, et que vous en avez accepté les
20 	termes (cf. le fichier Documentation/licence.fr.txt fourni avec ce logiciel).
21 */
22 
23 /*   LICENCE SUM UP
24 	Copyright CEA, contributors : Luc BILLARD et Damien
25 	CALISTE, laboratoire L_Sim, (2001-2005)
26 
27 	E-mail address:
28 	BILLARD, not reachable any more ;
29 	CALISTE, damien P caliste AT cea P fr.
30 
31 	This software is a computer program whose purpose is to visualize atomic
32 	configurations in 3D.
33 
34 	This software is governed by the CeCILL  license under French law and
35 	abiding by the rules of distribution of free software.  You can  use,
36 	modify and/ or redistribute the software under the terms of the CeCILL
37 	license as circulated by CEA, CNRS and INRIA at the following URL
38 	"http://www.cecill.info".
39 
40 	The fact that you are presently reading this means that you have had
41 	knowledge of the CeCILL license and that you accept its terms. You can
42 	find a copy of this licence shipped with this software at Documentation/licence.en.txt.
43 */
44 
45 #include <gtk/gtk.h>
46 #include <gdk/gdkkeysyms.h>
47 #include <string.h>
48 
49 #include "gtk_toolPanelWidget.h"
50 
51 #include <support.h>
52 #include <visu_basic.h>
53 #include <visu_tools.h>
54 #include <visu_configFile.h>
55 #include <gtk_main.h>
56 #include <visu_gtk.h>
57 #include <gtk_renderingWindowWidget.h>
58 
59 /**
60  * SECTION:gtk_toolPanelWidget
61  * @short_description: Defines a widget that hold a set of V_Sim panel.
62  *
63  * <para>This widget is a complex association of a #GtkComboBox and a
64  * #GtkNotebook with V_Sim panels. It can have its own window or be
65  * attached into the main command panel.</para>
66  *
67  * <para>This widget also has a built-in menu to exchange V_Sim panel
68  * between different instances of a #VisuUiPanel. A #VisuUiPanel is
69  * refered by its name and has a position and a size. These values can
70  * be stored in the parameter files.</para>
71  */
72 
73 enum {
74   NOTEBOOK_ENTERED,
75   LAST_SIGNAL
76 };
77 
78 enum
79   {
80     TOOL_LIST_ICON,            /* The icon shown */
81     TOOL_LIST_STOCK,           /* or the stock icon shown */
82     TOOL_LIST_NAME,            /* The label shown */
83     TOOL_LIST_POINTER_TO_DATA, /* Pointer to the tool panel. */
84     TOOL_LIST_N_COLUMNS
85   };
86 
87 /**
88  * VisuUiDockWindow:
89  *
90  * Short name for the structure of containers of #VisuUiPanel.
91  */
92 struct _VisuUiDockWindow
93 {
94   guint refCount;
95 
96   /* The name of the dock window. */
97   gchar *name;
98   /* The window holding the notebook of tools.
99      Maybe NULL if the VisuUiDockWindow is integrated
100      in something else.*/
101   GtkWidget *window;
102   /* The top container widget for the VisuUiDockWindow. */
103   GtkWidget *vbox;
104   /* The header line with the combobox. */
105   GtkWidget *hbox;
106   /* The notebook holding the tools. */
107   GtkWidget *notebook;
108   /* The combo list of accessible tool panels. */
109   GtkWidget *combo;
110   /* The list store associated to the combo. */
111   GtkListStore *list;
112   /* Handler on the change signals. */
113   gulong notebookChanged, comboChanged;
114   /* TRUE if the dock is visible. */
115   gboolean show;
116 };
117 
118 /**
119  * VisuUiPanel
120  *
121  * Short form for a #VisuUiPanel_struct structure.
122  */
123 struct _VisuUiPanel
124 {
125   GtkFrame alignment;
126 
127   /* Set if the visu_ui_panel can be separate from the main
128      window and be hosted in its own window. */
129   gboolean dockable;
130 
131   /* An id, untranslated, used to identify the panel
132      in a configuration file. It should not contain
133      any space character. */
134   gchar *id;
135 
136   /* Value that is shown in the combo box, which
137      is a "long" label. */
138   gchar *comboLabel;
139 
140   /* Value that appears in te tab of the
141      GtkNoteBook */
142   gchar *tabLabel;
143 
144   /* An image representing the tool. */
145   GtkWidget *icon;
146   gchar *stockIcon;
147 
148   /* The hosting container. */
149   VisuUiDockWindow *container;
150 
151   /* Internal widgets. */
152   GtkWidget *headerWidget;
153 
154   /* Memory gestion. */
155   gboolean dispose_has_run;
156 };
157 /**
158  * VisuUiPanelClass
159  *
160  * Opaque structure.
161  */
162 struct _VisuUiPanelClass
163 {
164   GtkFrameClass parent_class;
165 
166   void (*visu_ui_panel) (VisuUiPanel *tool);
167 
168   /* This list holds pointer on active hosting windows. */
169   GList* hostingWindows;
170 
171   /* This list holds tools than have no containers. */
172   GList* orphanVisuUiPanel;
173 
174   /* This is the VisuUiDockWindow of the command panel. */
175   VisuUiDockWindow *commandPanel;
176 
177   /* Give a quick access from id of tool panels to pointers. */
178   GHashTable *allVisuUiPanels;
179 
180   /* Pointer on current handled VisuData.
181      No reference is hold. */
182   VisuData *dataObj;
183   VisuGlView *viewObj;
184 
185   /* If TRUE, the labels are always shown in the tabs. */
186   gboolean showHeader;
187 };
188 
189 /**
190  * visu_ui_panel_get_type
191  *
192  * #GType are unique numbers to identify objects.
193  *
194  * Returns: the #GType associated with #VisuUiPanel objects.
195  */
196 G_DEFINE_TYPE(VisuUiPanel, visu_ui_panel, GTK_TYPE_FRAME)
197 
198 #define MAIN_PANEL_NAME _("Command panel")
199 
200 #define FLAG_PARAMETER_TABVIEW_CONFIG   "config_subPanelTabView"
201 #define DESC_PARAMETER_TABVIEW_CONFIG   "See or not the labels on tabs ; boolean 0 or 1"
202 #define PARAMETER_CONFIG_TABVIEW_DEFAULT   FALSE
203 static gboolean _tabView = PARAMETER_CONFIG_TABVIEW_DEFAULT;
204 
205 /* Local variables. */
206 static VisuUiPanelClass *local_class = NULL;
207 static GQuark CURRENT_TOOLPANEL_POINTER;
208 static guint visu_ui_panel_signals[LAST_SIGNAL] = { 0 };
209 
210 /* Local methods. */
211 static void visu_ui_panel_class_init(VisuUiPanelClass *klass);
212 static void visu_ui_panel_init(VisuUiPanel *visu_ui_panel);
213 static void visu_ui_panel_dispose(GObject *visu_ui_panel);
214 static void visu_ui_panel_finalize(GObject *obj);
215 static GtkWidget* buildDockMenu(VisuUiPanel *visu_ui_panel, GList *listOfDocks);
216 static GtkWidget* buildMainMenu(VisuUiDockWindow *window);
217 static VisuUiDockWindow* dock_window_new(gchar *name, gboolean withWindow);
218 static VisuUiDockWindow* dock_window_ref(VisuUiDockWindow *dock);
219 static void dock_window_unref(VisuUiDockWindow *dock);
220 static void exportParameters(GString *data, VisuData* dataObj);
221 
222 /* Local callbacks. */
223 static gboolean onHomePressed(GtkWidget *widget _U_, GdkEventKey *event,
224 			      gpointer data);
225 static void onDockButtonClicked(VisuUiPanel *visu_ui_panel, gpointer data);
226 static void onMainButtonClicked(GtkButton *button, gpointer data);
227 static void onRaiseButtonClicked(GtkButton *button, gpointer data);
228 static void onDockMenuClicked(GtkMenuItem *menuitem, gpointer user_data);
229 static void onDockMenuNewClicked(GtkMenuItem *menuitem, gpointer user_data);
230 static void onDockMenuHideClicked(GtkMenuItem *menuitem, gpointer user_data);
231 static void onDockMenuSelected(GtkMenuShell *menushell, gpointer user_data);
232 static void onMainMenuClicked(GtkMenuItem *menuitem, gpointer user_data);
233 static void onMainMenuShowClicked(GtkMenuItem *menuitem, gpointer user_data);
234 static void onMainMenuHideClicked(GtkMenuItem *menuitem, gpointer user_data);
235 static void onMainMenuSelected(GtkMenuShell *menushell, gpointer user_data);
236 static gboolean onKillVisuUiDockWindowEvent(GtkWidget *widget, GdkEvent *event, gpointer user_data);
237 static void onPageChanged(GtkNotebook *book, GtkWidget *child,
238 			  gint num, gpointer data);
239 static void onComboChanged(GtkComboBox *combo, gpointer data);
240 static void onEntryTabview(VisuConfigFile *obj, VisuConfigFileEntry *entry, VisuUiPanelClass *klass);
241 
visu_ui_panel_class_init(VisuUiPanelClass * klass)242 static void visu_ui_panel_class_init(VisuUiPanelClass *klass)
243 {
244   DBG_fprintf(stderr, "Gtk VisuUiPanel : creating the class of the widget.\n");
245 
246   local_class  = klass;
247 
248   DBG_fprintf(stderr, "                     - adding new signals ;\n");
249   /**
250    * VisuUiPanel::page-entered:
251    * @panel: the #VisuUiPanel that emits the signal.
252    *
253    * This signal is emitted when a page of the #GtkNotebook with all
254    * the V_Sim panels is entered.
255    *
256    * Since: 3.3
257    */
258   visu_ui_panel_signals[NOTEBOOK_ENTERED] =
259     g_signal_new ("page-entered",
260 		  G_TYPE_FROM_CLASS(klass),
261 		  G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION,
262 		  G_STRUCT_OFFSET(VisuUiPanelClass, visu_ui_panel),
263 		  NULL,
264 		  NULL,
265 		  g_cclosure_marshal_VOID__VOID,
266 		  G_TYPE_NONE, 0, NULL);
267 
268   DBG_fprintf(stderr, "                     - initializing the list of hosting windows.\n");
269   klass->hostingWindows = (GList*)0;
270   klass->orphanVisuUiPanel = (GList*)0;
271   klass->commandPanel = (VisuUiDockWindow*)0;
272   klass->dataObj = (VisuData*)0;
273   klass->viewObj = (VisuGlView*)0;
274   klass->allVisuUiPanels = g_hash_table_new_full(g_str_hash, g_str_equal,
275 					       NULL, NULL);
276   klass->showHeader = PARAMETER_CONFIG_TABVIEW_DEFAULT;
277 
278   visu_config_file_addBooleanEntry(VISU_CONFIG_FILE_PARAMETER,
279                                    FLAG_PARAMETER_TABVIEW_CONFIG,
280                                    DESC_PARAMETER_TABVIEW_CONFIG,
281                                    &_tabView, FALSE);
282   g_signal_connect(VISU_CONFIG_FILE_PARAMETER, "parsed::" FLAG_PARAMETER_TABVIEW_CONFIG,
283                    G_CALLBACK(onEntryTabview), klass);
284   visu_config_file_addExportFunction(VISU_CONFIG_FILE_PARAMETER,
285                                      exportParameters);
286 
287   CURRENT_TOOLPANEL_POINTER =
288     g_quark_from_static_string("VisuUiPanel_currentVisuUiPanel");
289 
290   /* Set the pixmap directory for the Glade stuff. */
291   add_pixmap_directory(visu_basic_getPixmapsDir());
292 
293   /* Connect freeing methods. */
294   G_OBJECT_CLASS(klass)->dispose = visu_ui_panel_dispose;
295   G_OBJECT_CLASS(klass)->finalize = visu_ui_panel_finalize;
296 }
297 
298 /* This method can be called several times.
299    It should unref all of its reference to
300    GObjects. */
visu_ui_panel_dispose(GObject * visu_ui_panel)301 static void visu_ui_panel_dispose(GObject *visu_ui_panel)
302 {
303   DBG_fprintf(stderr, "Gtk VisuUiPanel : dispose object %p (%s).\n",
304 	      (gpointer)visu_ui_panel, VISU_UI_PANEL(visu_ui_panel)->id);
305 
306   if (VISU_UI_PANEL(visu_ui_panel)->dispose_has_run)
307     return;
308 
309   VISU_UI_PANEL(visu_ui_panel)->dispose_has_run = TRUE;
310   /* Chain up to the parent class */
311   G_OBJECT_CLASS(visu_ui_panel_parent_class)->dispose(visu_ui_panel);
312 }
313 /* This method is called once only. */
visu_ui_panel_finalize(GObject * obj)314 static void visu_ui_panel_finalize(GObject *obj)
315 {
316   VisuUiPanel *visu_ui_panel;
317 
318   g_return_if_fail(obj);
319 
320   DBG_fprintf(stderr, "Gtk VisuUiPanel : finalize object %p.\n", (gpointer)obj);
321 
322   visu_ui_panel = VISU_UI_PANEL(obj);
323 
324   /* Remove me from the list of visu_ui_panels. */
325   g_hash_table_remove(local_class->allVisuUiPanels, visu_ui_panel->id);
326 
327   if (visu_ui_panel->comboLabel)
328     g_free(visu_ui_panel->comboLabel);
329   if (visu_ui_panel->tabLabel)
330     g_free(visu_ui_panel->tabLabel);
331   if (visu_ui_panel->id)
332     g_free(visu_ui_panel->id);
333   if (visu_ui_panel->stockIcon)
334     g_free(visu_ui_panel->stockIcon);
335   if (visu_ui_panel->headerWidget)
336     g_object_unref(visu_ui_panel->headerWidget);
337 
338   /* Chain up to the parent class */
339   G_OBJECT_CLASS(visu_ui_panel_parent_class)->finalize(obj);
340 
341   DBG_fprintf(stderr, "Gtk VisuUiPanel : freeing ... OK.\n");
342 }
343 
344 
visu_ui_panel_init(VisuUiPanel * visu_ui_panel)345 static void visu_ui_panel_init(VisuUiPanel *visu_ui_panel)
346 {
347   DBG_fprintf(stderr, "Gtk VisuUiPanel : initializing new object (%p).\n",
348 	      (gpointer)visu_ui_panel);
349 
350   visu_ui_panel->dispose_has_run = FALSE;
351 
352   visu_ui_panel->dockable     = FALSE;
353   visu_ui_panel->id           = (gchar*)0;
354   visu_ui_panel->comboLabel   = (gchar*)0;
355   visu_ui_panel->tabLabel     = (gchar*)0;
356   visu_ui_panel->icon         = (GtkWidget*)0;
357   visu_ui_panel->stockIcon    = (gchar*)0;
358   visu_ui_panel->headerWidget = (GtkWidget*)0;
359   visu_ui_panel->container    = (VisuUiDockWindow*)0;
360 
361   gtk_frame_set_shadow_type(GTK_FRAME(visu_ui_panel), GTK_SHADOW_NONE);
362 }
363 
364 /**
365  * visu_ui_panel_new:
366  * @id: (type filename): a string without space and non internationalised ;
367  * @name: a string in UTF-8 that can be internationalised ;
368  * @tabName: a shorter name than @name, in UTF-8 that can be
369  * internationalised.
370  *
371  * Create a new #VisuUiPanel with the given @id, displaying @name in the
372  * combo box of a #VisuUiDockWindow and @tabName in the tab of the page
373  * notebook.
374  *
375  * Returns: a newly created widget.
376  */
visu_ui_panel_new(gchar * id,gchar * name,gchar * tabName)377 GtkWidget* visu_ui_panel_new(gchar *id, gchar* name, gchar *tabName)
378 {
379   VisuUiPanel *visu_ui_panel;
380 
381   g_return_val_if_fail(id && id[0] && !strstr(id, " "), (GtkWidget*)0);
382   g_return_val_if_fail(name && name[0], (GtkWidget*)0);
383   g_return_val_if_fail(tabName && tabName[0], (GtkWidget*)0);
384 
385   visu_ui_panel = VISU_UI_PANEL(g_object_new(visu_ui_panel_get_type(), NULL));
386 
387   DBG_fprintf(stderr, "Gtk VisuUiPanel : creating new object '%s' : %p.\n",
388 	      name, (gpointer)visu_ui_panel);
389 
390   visu_ui_panel->id         = g_strdup(id);
391   visu_ui_panel->comboLabel = g_strdup(name);
392   visu_ui_panel->tabLabel   = g_strdup(tabName);
393 
394   /* Add me to the list of visu_ui_panels. */
395   g_hash_table_insert(local_class->allVisuUiPanels, visu_ui_panel->id,
396 		      (gpointer)visu_ui_panel);
397 
398   return GTK_WIDGET(visu_ui_panel);
399 }
400 /**
401  * visu_ui_panel_newWithIconFromPath:
402  * @id: a string without space and non internationalised ;
403  * @name: a string in UTF-8 that can be internationalised ;
404  * @tabName: a shorter name than @name, in UTF-8 that can be
405  * internationalised ;
406  * @iconPath: a path to an icon (should be 20x20).
407  *
408  * Create a new #VisuUiPanel with the given @id, displaying @name in the
409  * combo box of a #VisuUiDockWindow and @tabName in the tab of the page
410  * notebook. The displayed icon will be read from the @iconPath.
411  *
412  * Returns: (transfer full): a newly created widget.
413  */
visu_ui_panel_newWithIconFromPath(gchar * id,gchar * name,gchar * tabName,const gchar * iconPath)414 GtkWidget* visu_ui_panel_newWithIconFromPath(gchar *id, gchar* name, gchar *tabName,
415 					 const gchar* iconPath)
416 {
417   VisuUiPanel *visu_ui_panel;
418 
419   visu_ui_panel = VISU_UI_PANEL(visu_ui_panel_new(id, name, tabName));
420   if (!visu_ui_panel)
421     return (GtkWidget*)0;
422 
423   /* TODO : mettre un truc qui limite la taille des images
424      effichées à 20x20 par exemple en chargeant de GdkImage et en
425      regardant sa taille. */
426   visu_ui_panel->icon = create_pixmap((GtkWidget*)0, iconPath);
427   return GTK_WIDGET(visu_ui_panel);
428 }
429 /**
430  * visu_ui_panel_newWithIconFromIconName:
431  * @id: a string without space and non internationalised ;
432  * @name: a string in UTF-8 that can be internationalised ;
433  * @tabName: a shorter name than @name, in UTF-8 that can be
434  * internationalised ;
435  * @icon: the name of a stock icon.
436  *
437  * Create a new #VisuUiPanel with the given @id, displaying @name in the
438  * combo box of a #VisuUiDockWindow and @tabName in the tab of the page
439  * notebook. The displayed icon will be taken from the @stock.
440  *
441  * Returns: (transfer full): a newly created widget.
442  */
visu_ui_panel_newWithIconFromIconName(gchar * id,gchar * name,gchar * tabName,const gchar * icon)443 GtkWidget* visu_ui_panel_newWithIconFromIconName(gchar *id, gchar* name, gchar *tabName,
444                                                  const gchar* icon)
445 {
446   VisuUiPanel *visu_ui_panel;
447 
448   visu_ui_panel = VISU_UI_PANEL(visu_ui_panel_new(id, name, tabName));
449   if (!visu_ui_panel)
450     return (GtkWidget*)0;
451 
452   visu_ui_panel->stockIcon = g_strdup(icon);
453   visu_ui_panel->icon = gtk_image_new_from_icon_name(icon, GTK_ICON_SIZE_MENU);
454   return GTK_WIDGET(visu_ui_panel);
455 }
456 /**
457  * visu_ui_panel_getHeaderWidget:
458  * @visu_ui_panel: a #VisuUiPanel.
459  *
460  * The #VisuUiPanel should be used in a page of a #GtkNotebook. This
461  * routine is used to get the widget that should be used in the
462  * tab. This widget is a container with an icon and a label.
463  *
464  * Returns: (transfer none): a container widget that should be put in the tab of a
465  * #GtkNotebook.
466  */
visu_ui_panel_getHeaderWidget(VisuUiPanel * visu_ui_panel)467 GtkWidget* visu_ui_panel_getHeaderWidget(VisuUiPanel *visu_ui_panel)
468 {
469   GtkWidget *label, *wd, *image;
470 #if GTK_MAJOR_VERSION == 2 && GTK_MINOR_VERSION < 12
471   GtkTooltips *tooltips;
472 #endif
473 
474   g_return_val_if_fail(visu_ui_panel, (GtkWidget*)0);
475 
476   /* If the header has never been created,
477      we do it now. */
478   if (!visu_ui_panel->headerWidget)
479     {
480 #if GTK_MAJOR_VERSION == 2 && GTK_MINOR_VERSION < 12
481       tooltips = gtk_tooltips_new ();
482 #endif
483 
484       visu_ui_panel->headerWidget = gtk_hbox_new(FALSE, 0);
485       wd = gtk_event_box_new();
486       gtk_event_box_set_visible_window(GTK_EVENT_BOX(wd), FALSE);
487       gtk_box_pack_start(GTK_BOX(visu_ui_panel->headerWidget),
488 			 wd, FALSE, FALSE, 0);
489       gtk_widget_set_tooltip_text(wd, visu_ui_panel->comboLabel);
490       if (visu_ui_panel->icon)
491 	gtk_container_add(GTK_CONTAINER(wd), visu_ui_panel->icon);
492       else
493 	gtk_container_add(GTK_CONTAINER(wd),
494 			  gtk_image_new_from_icon_name("image-missing",
495                                                        GTK_ICON_SIZE_MENU));
496       label = gtk_label_new(visu_ui_panel->tabLabel);
497       gtk_widget_set_margin_start(label, 2);
498       gtk_box_pack_start(GTK_BOX(visu_ui_panel->headerWidget), label, FALSE, FALSE, 0);
499 
500       if (visu_ui_panel->dockable)
501 	{
502 	  wd = gtk_button_new();
503           gtk_widget_set_no_show_all(wd, TRUE);
504 	  gtk_box_pack_start(GTK_BOX(visu_ui_panel->headerWidget), wd, TRUE, TRUE, 0);
505 	  gtk_button_set_relief(GTK_BUTTON(wd), GTK_RELIEF_NONE);
506 	  g_signal_connect_swapped(G_OBJECT(wd), "clicked",
507 				   G_CALLBACK(onDockButtonClicked), (gpointer)visu_ui_panel);
508 	  image = create_pixmap((GtkWidget*)0, "stock-menu-detach.png");
509 	  gtk_container_add(GTK_CONTAINER(wd), image);
510 
511 	  gtk_widget_set_tooltip_text(wd,
512 			       _("Manage this subpanel: attach/detach"
513 				 " or hide it."));
514           gtk_widget_show(image);
515 	}
516 
517       g_object_ref(G_OBJECT(visu_ui_panel->headerWidget));
518       gtk_widget_show_all(visu_ui_panel->headerWidget);
519       gtk_widget_hide(label);
520     }
521 
522   return visu_ui_panel->headerWidget;
523 }
524 /**
525  * visu_ui_panel_getLabel:
526  * @visu_ui_panel: a #VisuUiPanel.
527  *
528  * The #VisuUiPanel has two label, a short one, used in the tab of a
529  * #GtkNotebook and one longer. This routine gets the longer.
530  *
531  * Returns: an UTF-8 internationalised name (property of V_Sim, should
532  * not be freed).
533  */
visu_ui_panel_getLabel(VisuUiPanel * visu_ui_panel)534 const gchar* visu_ui_panel_getLabel(VisuUiPanel *visu_ui_panel)
535 {
536   g_return_val_if_fail(visu_ui_panel, (gchar*)0);
537 
538   return visu_ui_panel->comboLabel;
539 }
540 /**
541  * visu_ui_panel_getId:
542  * @visu_ui_panel: a #VisuUiPanel.
543  *
544  * The #VisuUiPanel can be identifyed by an id (a string without space,
545  * usually using ASCII characters only).
546  *
547  * Returns: a constant string identifying this #VisuUiPanel.
548  */
visu_ui_panel_getId(VisuUiPanel * visu_ui_panel)549 const gchar* visu_ui_panel_getId(VisuUiPanel *visu_ui_panel)
550 {
551   g_return_val_if_fail(visu_ui_panel, (gchar*)0);
552 
553   return visu_ui_panel->id;
554 }
555 /**
556  * visu_ui_panel_setDockable:
557  * @visu_ui_panel: a #VisuUiPanel ;
558  * @value: a boolean.
559  *
560  * A #VisuUiPanel can be moved between different #VisuUiDockWindow or
561  * not. This ability is controlled by the dockable flag. Change it
562  * with this method. If @visu_ui_panel is set dockable, then, it can be
563  * hidden or moved to another or a new #VisuUiDockWindow with the pop-up
564  * memu that is triggered by a small button in the header widget (see
565  * visu_ui_panel_getHeaderWidget()).
566  */
visu_ui_panel_setDockable(VisuUiPanel * visu_ui_panel,gboolean value)567 void visu_ui_panel_setDockable(VisuUiPanel *visu_ui_panel, gboolean value)
568 {
569   g_return_if_fail(visu_ui_panel);
570 
571   visu_ui_panel->dockable = value;
572 }
573 /**
574  * visu_ui_panel_getContainer:
575  * @visu_ui_panel: a #VisuUiPanel.
576  *
577  * Return the #VisuUiDockWindow that the given @visu_ui_panel is attached to or
578  * NULL if the @visu_ui_panel is currently dettached.
579  *
580  * Returns: a #VisuUiDockWindow object.
581  */
visu_ui_panel_getContainer(VisuUiPanel * visu_ui_panel)582 VisuUiDockWindow* visu_ui_panel_getContainer(VisuUiPanel *visu_ui_panel)
583 {
584   g_return_val_if_fail(VISU_IS_UI_PANEL(visu_ui_panel), (VisuUiDockWindow*)0);
585 
586   return visu_ui_panel->container;
587 }
588 /**
589  * visu_ui_panel_getContainerWindow:
590  * @visu_ui_panel: a #VisuUiPanel.
591  *
592  * Return the #GtkWindow that the given @visu_ui_panel is rendered in or
593  * NULL if the @visu_ui_panel is currently dettached.
594  *
595  * Returns: (transfer none): a #GtkWindow object.
596  */
visu_ui_panel_getContainerWindow(VisuUiPanel * visu_ui_panel)597 GtkWindow* visu_ui_panel_getContainerWindow(VisuUiPanel *visu_ui_panel)
598 {
599   g_return_val_if_fail(VISU_IS_UI_PANEL(visu_ui_panel), (GtkWindow*)0);
600 
601   if (visu_ui_panel->container)
602     {
603       if (visu_ui_panel->container->window)
604 	return GTK_WINDOW(visu_ui_panel->container->window);
605       else
606 	return GTK_WINDOW(visu_ui_main_class_getCurrentPanel());
607     }
608   else
609     return (GtkWindow*)0;
610 }
611 /**
612  * visu_ui_panel_setContainer:
613  * @visu_ui_panel: a #VisuUiPanel ;
614  * @window: a #VisuUiDockWindow.
615  *
616  * Change the container of a visu_ui_panel. If it is currently attached to
617  * a #VisuUiDockWindow, it firstly detachs it.
618  */
visu_ui_panel_setContainer(VisuUiPanel * visu_ui_panel,VisuUiDockWindow * container)619 void visu_ui_panel_setContainer(VisuUiPanel *visu_ui_panel, VisuUiDockWindow *container)
620 {
621   g_return_if_fail(VISU_IS_UI_PANEL(visu_ui_panel));
622 
623   if (container == visu_ui_panel->container)
624     return;
625 
626   /* If the panel is already attached, we detach it. */
627   if (visu_ui_panel->container)
628     {
629       DBG_fprintf(stderr, "Gtk VisuUiPanel : detaching panel '%s' (%p).\n",
630 		  visu_ui_panel->tabLabel, (gpointer)visu_ui_panel);
631       g_object_ref(G_OBJECT(visu_ui_panel));
632       visu_ui_panel_detach(visu_ui_panel);
633     }
634 
635   /* If a new container is given, we attach it. */
636   if (container)
637     {
638       DBG_fprintf(stderr, "Gtk VisuUiPanel : attaching panel '%s' (%p) to %p.\n",
639 		  visu_ui_panel->tabLabel, (gpointer)visu_ui_panel, (gpointer)container);
640       visu_ui_panel_attach(visu_ui_panel, container);
641       g_object_unref(G_OBJECT(visu_ui_panel));
642     }
643 }
644 /**
645  * visu_ui_panel_getContainerId:
646  * @visu_ui_panel: a #VisuUiPanel.
647  *
648  * Return the identifying string of the #VisuUiDockWindow that the given
649  * @visu_ui_panel is attached to or NULL if the @visu_ui_panel is currently dettached.
650  *
651  * Returns: a string owned by V_Sim.
652  */
visu_ui_panel_getContainerId(VisuUiPanel * visu_ui_panel)653 const gchar* visu_ui_panel_getContainerId(VisuUiPanel *visu_ui_panel)
654 {
655   g_return_val_if_fail(VISU_IS_UI_PANEL(visu_ui_panel), (gchar*)0);
656 
657   if (!visu_ui_panel->container)
658     return "None";
659 
660   if (visu_ui_panel->container == VISU_UI_PANEL_CLASS(G_OBJECT_GET_CLASS(visu_ui_panel))->commandPanel)
661     return "Main";
662 
663   return visu_ui_panel->container->name;
664 }
665 /**
666  * visu_ui_panel_setContainerId:
667  * @visu_ui_panel: a #VisuUiPanel ;
668  * @id: a #VisuUiDockWindow identifier.
669  *
670  * Change the container of a visu_ui_panel using the given @id. If it is
671  * currently attached to a #VisuUiDockWindow, it firstly detachs it.
672  */
visu_ui_panel_setContainerId(VisuUiPanel * visu_ui_panel,const gchar * id)673 void visu_ui_panel_setContainerId(VisuUiPanel *visu_ui_panel, const gchar *id)
674 {
675   g_return_if_fail(VISU_IS_UI_PANEL(visu_ui_panel) && id && id[0]);
676 
677   visu_ui_panel_setContainer(visu_ui_panel, visu_ui_panel_class_getDockById(id));
678 }
679 /**
680  * visu_ui_panel_getData:
681  * @visu_ui_panel: a #VisuUiPanel.
682  *
683  * The @visu_ui_panel is supposed to work on a #VisuData, this routine can
684  * be used to get it.
685  *
686  * Returns: (transfer none): the currently focused #VisuData (can be NULL if none).
687  */
visu_ui_panel_getData(VisuUiPanel * visu_ui_panel)688 VisuData* visu_ui_panel_getData(VisuUiPanel *visu_ui_panel)
689 {
690   g_return_val_if_fail(VISU_IS_UI_PANEL(visu_ui_panel), (VisuData*)0);
691 
692   return VISU_UI_PANEL_CLASS(G_OBJECT_GET_CLASS(visu_ui_panel))->dataObj;
693 }
694 /**
695  * visu_ui_panel_getFocused:
696  * @visu_ui_panel: a #VisuUiPanel.
697  *
698  * Retrieves the currently focused #VisuBoxed object in the default #VisuUiRenderingWindow.
699  *
700  * Since: 3.7
701  *
702  * Returns: (transfer none) (allow-none): the currently focused
703  * #VisuBoxed (can be %NULL if none).
704  */
visu_ui_panel_getFocused(VisuUiPanel * visu_ui_panel)705 VisuBoxed* visu_ui_panel_getFocused(VisuUiPanel *visu_ui_panel)
706 {
707   g_return_val_if_fail(VISU_IS_UI_PANEL(visu_ui_panel), (VisuBoxed*)0);
708 
709   return VISU_BOXED(VISU_UI_PANEL_CLASS(G_OBJECT_GET_CLASS(visu_ui_panel))->dataObj);
710 }
711 /**
712  * visu_ui_panel_getView:
713  * @visu_ui_panel: a #VisuUiPanel object.
714  *
715  * Convenient routine to get the current #VisuGlView, see
716  * visu_ui_panel_class_setCurrent().
717  *
718  * Since: 3.7
719  *
720  * Returns: (transfer none): the current #VisuGlView, or NULL.
721  */
visu_ui_panel_getView(VisuUiPanel * visu_ui_panel)722 VisuGlView* visu_ui_panel_getView(VisuUiPanel *visu_ui_panel)
723 {
724   g_return_val_if_fail(VISU_IS_UI_PANEL(visu_ui_panel), (VisuGlView*)0);
725 
726   return VISU_UI_PANEL_CLASS(G_OBJECT_GET_CLASS(visu_ui_panel))->viewObj;
727 }
728 /**
729  * visu_ui_panel_getVisible:
730  * @visu_ui_panel: a #VisuUiPanel.
731  *
732  * This is used to retrieve if the @visu_ui_panel is currently realised
733  * and the visualised page of the #GtkNotebook it is associated to.
734  *
735  * Returns: TRUE if the given @visu_ui_panel is potentialy visible to the user.
736  */
visu_ui_panel_getVisible(VisuUiPanel * visu_ui_panel)737 gboolean visu_ui_panel_getVisible(VisuUiPanel *visu_ui_panel)
738 {
739   g_return_val_if_fail(VISU_IS_UI_PANEL(visu_ui_panel), FALSE);
740 
741   /* If the tool panel is not shown, we return fFALSE. */
742   if (!visu_ui_panel->container || !visu_ui_panel->container->show)
743     return FALSE;
744 
745   /* If the tool panel is attached to a visible dock, we
746      test if the current page of the notebook is our tool panel. */
747   return (visu_ui_panel == VISU_UI_PANEL(gtk_notebook_get_nth_page
748 	  (GTK_NOTEBOOK(visu_ui_panel->container->notebook),
749 	   gtk_notebook_get_current_page
750 	   (GTK_NOTEBOOK(visu_ui_panel->container->notebook)))));
751 }
752 
753 
754 /*****************/
755 /* Menu gestion. */
756 /*****************/
onDockButtonClicked(VisuUiPanel * visu_ui_panel,gpointer data)757 static void onDockButtonClicked(VisuUiPanel *visu_ui_panel, gpointer data)
758 {
759   GtkWidget *wd;
760 
761   g_return_if_fail(VISU_IS_UI_PANEL(visu_ui_panel));
762 
763   wd = buildDockMenu(visu_ui_panel, VISU_UI_PANEL_CLASS(G_OBJECT_GET_CLASS(visu_ui_panel))->hostingWindows);
764   g_signal_connect(G_OBJECT(wd), "selection-done",
765 		   G_CALLBACK(onDockMenuSelected), (gpointer)0);
766 
767   gtk_widget_show_all(wd);
768 #if GTK_MAJOR_VERSION < 2 || (GTK_MAJOR_VERSION == 3 && GTK_MINOR_VERSION < 22)
769   gtk_menu_popup(GTK_MENU(wd), NULL, NULL, NULL, NULL,
770 		 1, gtk_get_current_event_time());
771   (void)data;
772 #else
773   gtk_menu_popup_at_widget(GTK_MENU(wd), GTK_WIDGET(data), GDK_GRAVITY_SOUTH, GDK_GRAVITY_NORTH, NULL);
774 #endif
775 }
776 
buildDockMenu(VisuUiPanel * visu_ui_panel,GList * listOfDocks)777 static GtkWidget* buildDockMenu(VisuUiPanel *visu_ui_panel, GList *listOfDocks)
778 {
779   GtkWidget *menu, *item;
780   VisuUiDockWindow *window;
781   gchar *lbl;
782 
783   menu = gtk_menu_new();
784 
785   /* All dock windows. */
786   while (listOfDocks)
787     {
788       window = (VisuUiDockWindow*)listOfDocks->data;
789       if (window->show)
790 	{
791 	  lbl = g_strdup_printf(_("Send to '%s'"), window->name);
792 	  item = gtk_menu_item_new_with_label(lbl);
793 	  g_free(lbl);
794 	  g_signal_connect(G_OBJECT(item), "activate",
795 			   G_CALLBACK(onDockMenuClicked), listOfDocks->data);
796 	  g_object_set_qdata_full(G_OBJECT(item), CURRENT_TOOLPANEL_POINTER,
797 				  (gpointer)visu_ui_panel, NULL);
798 	  gtk_widget_set_sensitive(item, (visu_ui_panel->container != window));
799 	  gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
800 	}
801       listOfDocks = g_list_next(listOfDocks);
802     }
803   /* Separator. */
804   item = gtk_separator_menu_item_new();
805   gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
806   /* Create a new dock window. */
807   item = gtk_menu_item_new_with_label(_("New dock"));
808   g_signal_connect(G_OBJECT(item), "activate",
809 		   G_CALLBACK(onDockMenuNewClicked), (gpointer)visu_ui_panel);
810   gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
811   /* Remove the current tool panel. */
812   lbl = g_strdup_printf(_("Hide tool '%s'"), visu_ui_panel->tabLabel);
813   item = gtk_menu_item_new_with_label(lbl);
814   g_free(lbl);
815   g_signal_connect(G_OBJECT(item), "activate",
816 		   G_CALLBACK(onDockMenuHideClicked), (gpointer)visu_ui_panel);
817   gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
818 
819   DBG_fprintf(stderr, "Gtk VisuUiPanel : create the dock menu %p.\n", (gpointer)menu);
820 
821   return menu;
822 }
823 
onDockMenuClicked(GtkMenuItem * menuitem,gpointer user_data)824 static void onDockMenuClicked(GtkMenuItem *menuitem, gpointer user_data)
825 {
826   VisuUiPanel *visu_ui_panel;
827 
828   visu_ui_panel = (VisuUiPanel*)0;
829   visu_ui_panel = VISU_UI_PANEL(g_object_get_qdata(G_OBJECT(menuitem),
830 					    CURRENT_TOOLPANEL_POINTER));
831   g_return_if_fail(VISU_IS_UI_PANEL(visu_ui_panel));
832 
833   visu_ui_panel_setContainer(visu_ui_panel, (VisuUiDockWindow*)user_data);
834 }
onDockMenuNewClicked(GtkMenuItem * menuitem _U_,gpointer user_data)835 static void onDockMenuNewClicked(GtkMenuItem *menuitem _U_, gpointer user_data)
836 {
837   GList **lst;
838   VisuUiPanel *visu_ui_panel;
839   VisuUiDockWindow *window;
840   guint nb;
841   gchar *name;
842 
843   lst = &local_class->hostingWindows;
844   nb = g_list_length(*lst);
845   name = g_strdup_printf(_("Dock window (%d)"), nb);
846   window = dock_window_new(name, TRUE);
847   *lst = g_list_append(*lst, (gpointer)window);
848   window->show = TRUE;
849   gtk_widget_show_all(window->window);
850 
851   visu_ui_panel = VISU_UI_PANEL(user_data);
852   if (visu_ui_panel)
853     visu_ui_panel_setContainer(visu_ui_panel, window);
854 }
onDockMenuHideClicked(GtkMenuItem * menuitem _U_,gpointer user_data)855 static void onDockMenuHideClicked(GtkMenuItem *menuitem _U_, gpointer user_data)
856 {
857   DBG_fprintf(stderr, "Gtk VisuUiPanel : hide the panel %p.\n", (gpointer)user_data);
858   visu_ui_panel_setContainer(VISU_UI_PANEL(user_data), (VisuUiDockWindow*)0);
859 }
860 
onDockMenuSelected(GtkMenuShell * menushell,gpointer user_data _U_)861 static void onDockMenuSelected(GtkMenuShell *menushell, gpointer user_data _U_)
862 {
863   DBG_fprintf(stderr, "Gtk VisuUiPanel : destroy the dock menu %p.\n", (gpointer)menushell);
864   gtk_widget_destroy(GTK_WIDGET(menushell));
865 }
866 
emitPageEnter(gpointer data)867 static gboolean emitPageEnter(gpointer data)
868 {
869   g_return_val_if_fail(VISU_IS_UI_PANEL(data), FALSE);
870 
871   DBG_fprintf(stderr, "Gtk VisuUiPanel: '%s' (%p) emits 'page-entered' signal.\n",
872 	      VISU_UI_PANEL(data)->id, data);
873   g_signal_emit(G_OBJECT(data), visu_ui_panel_signals[NOTEBOOK_ENTERED],
874 		0, NULL);
875 
876   return FALSE;
877 }
878 
changeHeaderVisibility(VisuUiPanel * panel,gboolean status)879 static void changeHeaderVisibility(VisuUiPanel *panel, gboolean status)
880 {
881   GList *list, *tmpLst;
882 
883   g_return_if_fail(VISU_IS_UI_PANEL(panel) && panel->headerWidget);
884 
885   list = gtk_container_get_children(GTK_CONTAINER(panel->headerWidget));
886   tmpLst = list->next;
887   while(tmpLst)
888     {
889       if (status)
890 	gtk_widget_show(GTK_WIDGET(tmpLst->data));
891       else
892 	gtk_widget_hide(GTK_WIDGET(tmpLst->data));
893       tmpLst = g_list_next(tmpLst);
894     }
895   g_list_free(list);
896 }
897 
onHomePressed(GtkWidget * widget _U_,GdkEventKey * event,gpointer data)898 static gboolean onHomePressed(GtkWidget *widget _U_, GdkEventKey *event,
899 			      gpointer data)
900 {
901   DBG_fprintf(stderr, "Gtk VisuUiPanel: get key pressed.\n");
902   if(event->keyval == GDK_KEY_Home)
903     {
904       onRaiseButtonClicked((GtkButton*)0, data);
905       return TRUE;
906     }
907   return FALSE;
908 }
onPageChanged(GtkNotebook * book,GtkWidget * child,gint num,gpointer data)909 static void onPageChanged(GtkNotebook *book, GtkWidget *child,
910 			  gint num, gpointer data)
911 {
912   VisuUiDockWindow *window;
913   int numOld;
914 #if GTK_MAJOR_VERSION == 2
915   child = gtk_notebook_get_nth_page(book, num);
916 #endif
917 
918   window = (VisuUiDockWindow*)data;
919   g_return_if_fail(window);
920   g_return_if_fail(VISU_IS_UI_PANEL(child));
921 
922   DBG_fprintf(stderr, "Gtk VisuUiPanel: caught 'page-switch' signal, jump to %d.\n", num);
923   /* Change the visibility of the header labels. */
924   if (!local_class->showHeader)
925     {
926       numOld = gtk_combo_box_get_active(GTK_COMBO_BOX(window->combo));
927       if ((gint)num != numOld)
928 	{
929 	  /* We don't come from the combo so we change the
930 	     visibility. */
931 	  changeHeaderVisibility
932 	    (VISU_UI_PANEL(gtk_notebook_get_nth_page(book, numOld)), FALSE);
933 	  changeHeaderVisibility
934 	    (VISU_UI_PANEL(gtk_notebook_get_nth_page(book, num)), TRUE);
935 	}
936     }
937 
938   /* Change the combo to the right one. */
939   g_signal_handler_block(G_OBJECT(window->combo), window->comboChanged);
940   gtk_combo_box_set_active(GTK_COMBO_BOX(window->combo), num);
941   g_signal_handler_unblock(G_OBJECT(window->combo), window->comboChanged);
942 
943   g_idle_add(emitPageEnter, child);
944 }
945 
onComboChanged(GtkComboBox * combo,gpointer data)946 static void onComboChanged(GtkComboBox *combo, gpointer data)
947 {
948   int index, numOld;
949   VisuUiDockWindow *window;
950   GtkNotebook *book;
951 
952   window = (VisuUiDockWindow*)data;
953   g_return_if_fail(window);
954 
955   index = gtk_combo_box_get_active(combo);
956 
957   /* Change the visibility of the header labels. */
958   if (!local_class->showHeader)
959     {
960       book = GTK_NOTEBOOK(window->notebook);
961       numOld = gtk_notebook_get_current_page(book);
962       changeHeaderVisibility
963 	(VISU_UI_PANEL(gtk_notebook_get_nth_page(book, numOld)), FALSE);
964       changeHeaderVisibility
965 	(VISU_UI_PANEL(gtk_notebook_get_nth_page(book, index)), TRUE);
966     }
967 
968   /* Change the page to the right one. */
969   gtk_notebook_set_current_page(GTK_NOTEBOOK(window->notebook), index);
970 }
971 
972 
onKillVisuUiDockWindowEvent(GtkWidget * widget,GdkEvent * event _U_,gpointer user_data)973 static gboolean onKillVisuUiDockWindowEvent(GtkWidget *widget, GdkEvent *event _U_,
974 				      gpointer user_data)
975 {
976   g_return_val_if_fail(user_data, TRUE);
977 
978   DBG_fprintf(stderr, "Gtk VisuUiPanel: delete or destroy event cancelled.\n");
979   gtk_widget_hide(widget);
980   ((VisuUiDockWindow*)user_data)->show = FALSE;
981   return TRUE;
982 }
983 
984 /**
985  * visu_ui_panel_attach:
986  * @visu_ui_panel: a #VisuUiPanel ;
987  * @dock: a #VisuUiDockWindow.
988  *
989  * Put the given @visu_ui_panel in the given @dock window. It adds in this
990  * dock window a new page in the #GtkNotebook using as tab header the
991  * widget returned by visu_ui_panel_getHeaderWidget().
992  */
visu_ui_panel_attach(VisuUiPanel * visu_ui_panel,VisuUiDockWindow * dock)993 void visu_ui_panel_attach(VisuUiPanel *visu_ui_panel, VisuUiDockWindow *dock)
994 {
995   GtkTreeIter iter;
996   VisuUiPanelClass *klass;
997   GdkPixbuf *pixbuf;
998 
999   DBG_fprintf(stderr, "Gtk VisuUiPanel: attach a visu_ui_panel (%p) to a dock"
1000 	      " window (%s).\n", (gpointer)visu_ui_panel, dock->name);
1001 
1002   g_return_if_fail(dock && visu_ui_panel);
1003 
1004   if (visu_ui_panel->icon &&
1005       gtk_image_get_storage_type(GTK_IMAGE(visu_ui_panel->icon)) == GTK_IMAGE_PIXBUF)
1006     pixbuf = gtk_image_get_pixbuf(GTK_IMAGE(visu_ui_panel->icon));
1007   else
1008     pixbuf = (GdkPixbuf*)0;
1009 
1010   /* We add the window in the list store. */
1011   gtk_list_store_append(dock->list, &iter);
1012   gtk_list_store_set(dock->list, &iter,
1013 		     TOOL_LIST_ICON, pixbuf,
1014                      TOOL_LIST_STOCK, visu_ui_panel->stockIcon,
1015 		     TOOL_LIST_NAME, visu_ui_panel->comboLabel,
1016 		     TOOL_LIST_POINTER_TO_DATA, visu_ui_panel,
1017 		     -1);
1018 
1019   gtk_notebook_append_page(GTK_NOTEBOOK(dock->notebook), GTK_WIDGET(visu_ui_panel),
1020 			   visu_ui_panel_getHeaderWidget(visu_ui_panel));
1021   gtk_widget_show(GTK_WIDGET(visu_ui_panel));
1022   visu_ui_panel->container = dock;
1023 
1024   if (gtk_notebook_get_n_pages(GTK_NOTEBOOK(dock->notebook)) > 1)
1025     gtk_widget_show(dock->hbox);
1026   else
1027     gtk_widget_hide(dock->hbox);
1028 
1029   klass = VISU_UI_PANEL_CLASS(G_OBJECT_GET_CLASS(visu_ui_panel));
1030   klass->orphanVisuUiPanel = g_list_remove(klass->orphanVisuUiPanel,
1031 					 (gpointer)visu_ui_panel);
1032 
1033 }
1034 /**
1035  * visu_ui_panel_detach:
1036  * @visu_ui_panel: a #VisuUiPanel.
1037  *
1038  * Remove the given @visu_ui_panel from its current container and add it
1039  * to the list of hidden tool panels. It can be added again using the
1040  * pop-up menu of any #VisuUiDockWindow.
1041  */
visu_ui_panel_detach(VisuUiPanel * visu_ui_panel)1042 void visu_ui_panel_detach(VisuUiPanel *visu_ui_panel)
1043 {
1044   gint page;
1045   VisuUiDockWindow *window;
1046   GtkTreeIter iter;
1047   GtkTreePath* path;
1048   gboolean valid;
1049   VisuUiPanelClass *klass;
1050 
1051   g_return_if_fail(visu_ui_panel && visu_ui_panel->container);
1052 
1053   window = visu_ui_panel->container;
1054 
1055   /* Get the id. */
1056   page = gtk_notebook_page_num(GTK_NOTEBOOK(window->notebook), GTK_WIDGET(visu_ui_panel));
1057 
1058   DBG_fprintf(stderr, "Gtk VisuUiPanel : detach a visu_ui_panel (%s) from page %d of dock"
1059 	      " (%s).\n", visu_ui_panel->tabLabel, page, window->name);
1060 
1061   /* We remove the page for the notebook. */
1062   gtk_notebook_remove_page(GTK_NOTEBOOK(window->notebook), page);
1063 
1064   if (gtk_notebook_get_n_pages(GTK_NOTEBOOK(window->notebook)) < 2)
1065     gtk_widget_hide(window->hbox);
1066 
1067   /* We remove the tool from the combo list. */
1068   path = gtk_tree_path_new_from_indices(page, -1);
1069   valid = gtk_tree_model_get_iter(GTK_TREE_MODEL(window->list), &iter, path);
1070   if (valid)
1071     gtk_list_store_remove(window->list, &iter);
1072   gtk_tree_path_free(path);
1073 
1074   /* If there is no more tool in this window, we delete it. */
1075   if (gtk_notebook_get_n_pages(GTK_NOTEBOOK(window->notebook)) == 0 &&
1076       window != VISU_UI_PANEL_CLASS(G_OBJECT_GET_CLASS(visu_ui_panel))->commandPanel)
1077     {
1078       DBG_fprintf(stderr, "Gtk VisuUiPanel: destroying dock window %p (%s).\n",
1079 		  (gpointer)window, window->name);
1080       gtk_widget_destroy(window->window);
1081       VISU_UI_PANEL_CLASS(G_OBJECT_GET_CLASS(visu_ui_panel))->hostingWindows =
1082 	g_list_remove(VISU_UI_PANEL_CLASS(G_OBJECT_GET_CLASS(visu_ui_panel))->hostingWindows,
1083 		      (gconstpointer)window);
1084       g_free(window->name);
1085       g_object_unref(window->list);
1086       g_free(window);
1087     }
1088 
1089   visu_ui_panel->container = (VisuUiDockWindow*)0;
1090   klass = VISU_UI_PANEL_CLASS(G_OBJECT_GET_CLASS(visu_ui_panel));
1091   klass->orphanVisuUiPanel = g_list_prepend(klass->orphanVisuUiPanel,
1092 					  (gpointer)visu_ui_panel);
1093   DBG_fprintf(stderr, "Gtk VisuUiPanel: number of orphan tool panels %d.\n",
1094 	      g_list_length(klass->orphanVisuUiPanel));
1095 }
1096 
onMainButtonClicked(GtkButton * button,gpointer data)1097 static void onMainButtonClicked(GtkButton *button, gpointer data)
1098 {
1099   GtkWidget *wd;
1100 
1101   wd = buildMainMenu((VisuUiDockWindow*)data);
1102   g_signal_connect(G_OBJECT(wd), "selection-done",
1103 		   G_CALLBACK(onMainMenuSelected), (gpointer)0);
1104 
1105   gtk_widget_show_all(wd);
1106 #if GTK_MAJOR_VERSION < 2 || (GTK_MAJOR_VERSION == 3 && GTK_MINOR_VERSION < 22)
1107   gtk_menu_popup(GTK_MENU(wd), NULL, NULL, NULL, NULL,
1108 		 1, gtk_get_current_event_time());
1109   (void)button;
1110 #else
1111   gtk_menu_popup_at_widget(GTK_MENU(wd), GTK_WIDGET(button), GDK_GRAVITY_SOUTH, GDK_GRAVITY_NORTH, NULL);
1112 #endif
1113 }
1114 
buildMainMenu(VisuUiDockWindow * window)1115 static GtkWidget* buildMainMenu(VisuUiDockWindow *window)
1116 {
1117   GtkWidget *menu, *item;
1118   GList* tmpLst;
1119   gchar *label;
1120   VisuUiPanel *panel;
1121   VisuUiDockWindow *dock;
1122   gboolean haveHiddenDock;
1123 
1124   menu = gtk_menu_new();
1125 
1126   tmpLst = local_class->orphanVisuUiPanel;
1127   /* All dock windows. */
1128   while (tmpLst)
1129     {
1130       panel = (VisuUiPanel*)tmpLst->data;
1131       label = g_strdup_printf(_("Show '%s'"), panel->comboLabel);
1132       item = gtk_menu_item_new_with_label(label);
1133       g_free(label);
1134       g_signal_connect(G_OBJECT(item), "activate",
1135 		       G_CALLBACK(onMainMenuClicked), window);
1136       g_object_set_qdata_full(G_OBJECT(item), CURRENT_TOOLPANEL_POINTER,
1137 			      (gpointer)panel, NULL);
1138       gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
1139       tmpLst = g_list_next(tmpLst);
1140     }
1141   if (!local_class->orphanVisuUiPanel)
1142     {
1143       item = gtk_menu_item_new_with_label(_("No hidden tool"));
1144       gtk_widget_set_sensitive(item, FALSE);
1145       gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
1146     }
1147   /* Separator. */
1148   item = gtk_separator_menu_item_new();
1149   gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
1150   /* Hidden dock. */
1151   haveHiddenDock = FALSE;
1152   tmpLst = local_class->hostingWindows;
1153   while (tmpLst)
1154     {
1155       dock = (VisuUiDockWindow*)tmpLst->data;
1156       if (!dock->show)
1157 	{
1158 	  haveHiddenDock = TRUE;
1159 	  label = g_strdup_printf(_("Show '%s'"), dock->name);
1160 	  item = gtk_menu_item_new_with_label(label);
1161 	  g_free(label);
1162 	  g_signal_connect(G_OBJECT(item), "activate",
1163 			   G_CALLBACK(onMainMenuShowClicked), dock);
1164 	  gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
1165 	}
1166       tmpLst = g_list_next(tmpLst);
1167     }
1168   if (!haveHiddenDock)
1169     {
1170       item = gtk_menu_item_new_with_label(_("No hidden dock"));
1171       gtk_widget_set_sensitive(item, FALSE);
1172       gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
1173     }
1174   if (window->window)
1175     {
1176       /* Separator. */
1177       item = gtk_separator_menu_item_new();
1178       gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
1179       /* Hide action */
1180       item = gtk_menu_item_new_with_label(_("Hide dock"));
1181       g_signal_connect(G_OBJECT(item), "activate",
1182 		       G_CALLBACK(onMainMenuHideClicked), window);
1183       gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
1184     }
1185 
1186   DBG_fprintf(stderr, "Gtk VisuUiPanel: create the main menu %p.\n", (gpointer)menu);
1187 
1188   return menu;
1189 }
onMainMenuClicked(GtkMenuItem * menuitem,gpointer user_data)1190 static void onMainMenuClicked(GtkMenuItem *menuitem, gpointer user_data)
1191 {
1192   VisuUiPanel *visu_ui_panel;
1193   VisuUiDockWindow *window;
1194 
1195   visu_ui_panel = (VisuUiPanel*)0;
1196   visu_ui_panel = VISU_UI_PANEL(g_object_get_qdata(G_OBJECT(menuitem),
1197 					    CURRENT_TOOLPANEL_POINTER));
1198   g_return_if_fail(VISU_IS_UI_PANEL(visu_ui_panel));
1199 
1200   window = (VisuUiDockWindow*)user_data;
1201 
1202   DBG_fprintf(stderr, "Gtk VisuUiPanel: attaching panel '%s' (%p) to %p.\n",
1203 	      visu_ui_panel->tabLabel, (gpointer)visu_ui_panel, (gpointer)window);
1204   visu_ui_panel_attach(visu_ui_panel, window);
1205   g_object_unref(G_OBJECT(visu_ui_panel));
1206 }
onMainMenuShowClicked(GtkMenuItem * menuitem _U_,gpointer user_data)1207 static void onMainMenuShowClicked(GtkMenuItem *menuitem _U_, gpointer user_data)
1208 {
1209   VisuUiDockWindow *dock;
1210 
1211   g_return_if_fail(user_data);
1212 
1213   dock = (VisuUiDockWindow*)user_data;
1214   if (dock->window)
1215     gtk_widget_show(dock->window);
1216   dock->show = TRUE;
1217 }
onMainMenuHideClicked(GtkMenuItem * menuitem _U_,gpointer user_data)1218 static void onMainMenuHideClicked(GtkMenuItem *menuitem _U_, gpointer user_data)
1219 {
1220   VisuUiDockWindow *dock;
1221 
1222   g_return_if_fail(user_data);
1223 
1224   dock = (VisuUiDockWindow*)user_data;
1225   if (dock->window)
1226     gtk_widget_hide(dock->window);
1227   dock->show = FALSE;
1228 }
onMainMenuSelected(GtkMenuShell * menushell,gpointer user_data _U_)1229 static void onMainMenuSelected(GtkMenuShell *menushell, gpointer user_data _U_)
1230 {
1231   DBG_fprintf(stderr, "Gtk VisuUiPanel: destroy the main menu %p.\n", (gpointer)menushell);
1232   gtk_widget_destroy(GTK_WIDGET(menushell));
1233 }
onRaiseButtonClicked(GtkButton * button _U_,gpointer data _U_)1234 static void onRaiseButtonClicked(GtkButton *button _U_, gpointer data _U_)
1235 {
1236   GtkWindow *window;
1237 
1238   window = visu_ui_getRenderWindow();
1239   g_return_if_fail(window);
1240   /* We raised the rendering window, if required. */
1241   gtk_window_present(window);
1242 }
1243 
1244 
1245 /******************/
1246 /* Class methods. */
1247 /******************/
1248 
1249 /**
1250  * visu_ui_panel_class_getCommandPanel:
1251  *
1252  * There is always a #VisuUiDockWindow that is inside the command
1253  * panel. This routine gets it.
1254  *
1255  * Returns: (transfer none):the #VisuUiDockWindow that is inside the command panel.
1256  */
visu_ui_panel_class_getCommandPanel(void)1257 VisuUiDockWindow* visu_ui_panel_class_getCommandPanel(void)
1258 {
1259   if (!local_class)
1260     g_type_class_ref(VISU_TYPE_UI_PANEL);
1261 
1262   if (!local_class->commandPanel)
1263     {
1264       local_class->commandPanel = dock_window_new(MAIN_PANEL_NAME, FALSE);
1265       local_class->hostingWindows = g_list_prepend(local_class->hostingWindows,
1266 						   local_class->commandPanel);
1267     }
1268 
1269   return local_class->commandPanel;
1270 }
1271 /**
1272  * visu_ui_panel_class_setCurrent:
1273  * @dataObj: a #VisuData object.
1274  * @view: a #VisuGlView object.
1275  *
1276  * Set the currently focussed #VisuData. It then can be retrieve using
1277  * visu_ui_panel_getData().
1278  *
1279  * Since: 3.7
1280  */
visu_ui_panel_class_setCurrent(VisuData * dataObj,VisuGlView * view)1281 void visu_ui_panel_class_setCurrent(VisuData *dataObj, VisuGlView *view)
1282 {
1283   if (!local_class)
1284     g_type_class_ref(VISU_TYPE_UI_PANEL);
1285 
1286   local_class->dataObj = dataObj;
1287   local_class->viewObj = view;
1288 }
1289 /**
1290  * visu_ui_panel_class_getPanelById:
1291  * @id: a #VisuUiPanel identifier.
1292  *
1293  * This routine associates a #VisuUiPanel identifier to the object pointer.
1294  *
1295  * Returns: (transfer none): the #VisuUiPanel that corresponds to this identifier or NULL
1296  * if none exists.
1297  */
visu_ui_panel_class_getPanelById(const gchar * id)1298 VisuUiPanel* visu_ui_panel_class_getPanelById(const gchar *id)
1299 {
1300   gpointer panel;
1301 
1302   if (!local_class)
1303     g_type_class_ref(VISU_TYPE_UI_PANEL);
1304 
1305   DBG_fprintf(stderr, "Gtk VisuUiPanel: search panel '%s'.\n", id);
1306   panel = g_hash_table_lookup(local_class->allVisuUiPanels, id);
1307   if (!panel)
1308     return (VisuUiPanel*)0;
1309   else
1310     return VISU_UI_PANEL(panel);
1311 }
1312 /**
1313  * visu_ui_panel_class_getDockById:
1314  * @id: a #VisuUiDockWindow identifier.
1315  *
1316  * This routine associates a #VisuUiDockWindow identifier to the object pointer.
1317  *
1318  * Returns: the #VisuUiDockWindow that corresponds to this identifier. The
1319  * dock window is built if not currently exist.
1320  */
visu_ui_panel_class_getDockById(const gchar * id)1321 VisuUiDockWindow* visu_ui_panel_class_getDockById(const gchar *id)
1322 {
1323   VisuUiDockWindow *window;
1324   GList *tmplst;
1325 
1326   if (!local_class)
1327     g_type_class_ref(VISU_TYPE_UI_PANEL);
1328 
1329   if (!strcmp(id, "None"))
1330     return (VisuUiDockWindow*)0;
1331 
1332   if (!strcmp(id, "Main"))
1333     return local_class->commandPanel;
1334 
1335   tmplst = local_class->hostingWindows;
1336   while (tmplst)
1337     {
1338       if (!strcmp(((VisuUiDockWindow*)tmplst->data)->name, id))
1339 	return (VisuUiDockWindow*)tmplst->data;
1340       tmplst = g_list_next(tmplst);
1341     };
1342   /* No matching name found, we create a new window. */
1343   window = dock_window_new(g_strdup(id), TRUE);
1344   local_class->hostingWindows = g_list_prepend(local_class->hostingWindows,
1345 					      (gpointer)window);
1346 
1347   return window;
1348 }
1349 /**
1350  * visu_ui_panel_class_getAllPanels:
1351  *
1352  * This routine can be used to know all existing #VisuUiPanel.
1353  *
1354  * Returns: (transfer full) (element-type VisuUiPanel*): a newly
1355  * created list (use g_list_free() on it after use).
1356  */
visu_ui_panel_class_getAllPanels(void)1357 GList* visu_ui_panel_class_getAllPanels(void)
1358 {
1359   GList *tmplst, *returnlst;
1360   gboolean valid;
1361   GtkTreeIter iter;
1362   VisuUiPanel *tool;
1363   GtkTreeModel *treeModel;
1364 
1365   if (!local_class)
1366     g_type_class_ref(VISU_TYPE_UI_PANEL);
1367 
1368   DBG_fprintf(stderr, "Gtk VisuUiPanel: create list of all panels.\n");
1369   returnlst = (GList*)0;
1370   tmplst = local_class->hostingWindows;
1371   while (tmplst)
1372     {
1373       treeModel = GTK_TREE_MODEL(((VisuUiDockWindow*)tmplst->data)->list);
1374       valid = gtk_tree_model_get_iter_first(treeModel, &iter);
1375       while (valid)
1376 	{
1377 	  gtk_tree_model_get(treeModel, &iter, TOOL_LIST_POINTER_TO_DATA, &tool, -1);
1378 	  DBG_fprintf(stderr, " | add '%s'\n", tool->id);
1379 	  returnlst = g_list_prepend(returnlst, (gpointer)tool);
1380 	  valid = gtk_tree_model_iter_next(treeModel, &iter);
1381 	}
1382       tmplst = g_list_next(tmplst);
1383     }
1384   returnlst = g_list_concat(returnlst, g_list_copy(local_class->orphanVisuUiPanel));
1385   return returnlst;
1386 }
1387 /**
1388  * visu_ui_panel_class_getAllWindows:
1389  *
1390  * This routine can be used to know all existing #VisuUiDockWindow.
1391  *
1392  * Returns: (transfer container) (element-type VisuUiDockWindow*): a
1393  * newly created list (use g_list_free() on it after use).
1394  */
visu_ui_panel_class_getAllWindows(void)1395 GList* visu_ui_panel_class_getAllWindows(void)
1396 {
1397   GList *returnlst;
1398 
1399   if (!local_class)
1400     g_type_class_ref(VISU_TYPE_UI_PANEL);
1401 
1402   DBG_fprintf(stderr, "Gtk VisuUiPanel : create list of all windows.\n");
1403   returnlst = g_list_copy(local_class->hostingWindows);
1404   returnlst = g_list_remove(returnlst, local_class->commandPanel);
1405   return returnlst;
1406 }
1407 /**
1408  * visu_ui_panel_class_setHeaderVisibility:
1409  * @status: a boolean.
1410  *
1411  * The header can be represented using the full image and label always
1412  * or only the image when the tab is not on top.
1413  */
visu_ui_panel_class_setHeaderVisibility(gboolean status)1414 void visu_ui_panel_class_setHeaderVisibility(gboolean status)
1415 {
1416   GList *tmpLst;
1417   int num, i;
1418   GtkNotebook *notebook;
1419 
1420   if (!local_class)
1421     g_type_class_ref(VISU_TYPE_UI_PANEL);
1422 
1423   DBG_fprintf(stderr, "Gtk VisuUiPanel : set the header visibility.\n");
1424   if (local_class->showHeader == status)
1425     return;
1426 
1427   tmpLst = local_class->hostingWindows;
1428   while(tmpLst)
1429     {
1430       notebook = GTK_NOTEBOOK(((VisuUiDockWindow*)tmpLst->data)->notebook);
1431       num = gtk_notebook_get_current_page(notebook);
1432       for (i = 0; i < gtk_notebook_get_n_pages(notebook); i++)
1433 	changeHeaderVisibility(VISU_UI_PANEL(gtk_notebook_get_nth_page(notebook, i)),
1434 			       status || (i == num));
1435       tmpLst = g_list_next(tmpLst);
1436     }
1437   local_class->showHeader = status;
1438 }
1439 /**
1440  * visu_ui_panel_class_getHeaderVisibility:
1441  *
1442  * The header can be represented using the full image and label always
1443  * or only the image when the tab is not on top.
1444  *
1445  * Since: 3.8
1446  *
1447  * Returns: TRUE if the header uses text and label.
1448  **/
visu_ui_panel_class_getHeaderVisibility(void)1449 gboolean visu_ui_panel_class_getHeaderVisibility(void)
1450 {
1451   if (!local_class)
1452     g_type_class_ref(VISU_TYPE_UI_PANEL);
1453 
1454   return local_class->showHeader;
1455 }
1456 
1457 /************************/
1458 /* Dock window methods. */
1459 /************************/
visu_ui_dock_window_get_type(void)1460 GType visu_ui_dock_window_get_type(void)
1461 {
1462   static GType g_define_type_id = 0;
1463 
1464   if (g_define_type_id == 0)
1465     g_define_type_id =
1466       g_boxed_type_register_static("VisuUiDockWindow",
1467                                    (GBoxedCopyFunc)dock_window_ref,
1468                                    (GBoxedFreeFunc)dock_window_unref);
1469   return g_define_type_id;
1470 }
dock_window_new(gchar * name,gboolean withWindow)1471 static VisuUiDockWindow* dock_window_new(gchar *name, gboolean withWindow)
1472 {
1473   VisuUiDockWindow *window;
1474   GtkWidget *wd, *image;
1475   GtkCellRenderer *renderer;
1476 /*   GtkBindingSet *keys; */
1477 #if GTK_MAJOR_VERSION == 2 && GTK_MINOR_VERSION < 12
1478   GtkTooltips *tooltips;
1479 
1480   tooltips = gtk_tooltips_new ();
1481 #endif
1482 
1483   window = g_malloc(sizeof(VisuUiDockWindow));
1484   window->refCount = 1;
1485 
1486   DBG_fprintf(stderr, "Gtk VisuUiPanel: create a new dock window %p (%s).\n",
1487 	      (gpointer)window, name);
1488 
1489   window->name = name;
1490 
1491   window->show = !strcmp(name, MAIN_PANEL_NAME);
1492 
1493   window->vbox = gtk_vbox_new(FALSE, 0);
1494 
1495   if (withWindow)
1496     {
1497       window->window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
1498       gtk_window_set_title(GTK_WINDOW(window->window), window->name);
1499       gtk_window_set_default_size(GTK_WINDOW(window->window), 350, 350);
1500       gtk_window_set_type_hint(GTK_WINDOW(window->window), GDK_WINDOW_TYPE_HINT_UTILITY);
1501       gtk_window_set_skip_pager_hint(GTK_WINDOW(window->window), TRUE);
1502       g_signal_connect(G_OBJECT(window->window), "delete-event",
1503 		       G_CALLBACK(onKillVisuUiDockWindowEvent), (gpointer)window);
1504       g_signal_connect(G_OBJECT(window->window), "destroy-event",
1505 		       G_CALLBACK(onKillVisuUiDockWindowEvent), (gpointer)window);
1506       g_signal_connect(G_OBJECT(window->window), "key-press-event",
1507 		       G_CALLBACK(onHomePressed), (gpointer)window);
1508 
1509       gtk_container_set_border_width(GTK_CONTAINER(window->window), 3);
1510       gtk_container_add(GTK_CONTAINER(window->window), window->vbox);
1511 /*       gtk_widget_show(window->window); */
1512     }
1513   else
1514     window->window = (GtkWidget*)0;
1515 
1516   window->notebook = gtk_notebook_new();
1517   gtk_widget_set_margin_top(window->notebook, 5);
1518   gtk_notebook_set_scrollable(GTK_NOTEBOOK(window->notebook), TRUE);
1519   gtk_box_pack_end(GTK_BOX(window->vbox), window->notebook, TRUE, TRUE, 0);
1520   window->notebookChanged =
1521     g_signal_connect(G_OBJECT(window->notebook), "switch-page",
1522 		     G_CALLBACK(onPageChanged), (gpointer)window);
1523 
1524   window->hbox = gtk_hbox_new(FALSE, 0);
1525   gtk_box_pack_start(GTK_BOX(window->vbox), window->hbox, FALSE, FALSE, 0);
1526 
1527   /* Define the key bindings. */
1528 /*   keys = gtk_binding_set_new("commandPanel"); */
1529 /*   gtk_binding_entry_add_signal(keys, GDK_KEY_space, 0, "clicked", 1, (gpointer)window); */
1530 
1531   /* Raise render area. */
1532   wd = gtk_button_new();
1533   g_object_set(G_OBJECT(wd), "can-default", TRUE, "can-focus", TRUE,
1534 	       "has-default", FALSE, "has-focus", FALSE, NULL);
1535 /*   gtk_button_set_relief(GTK_BUTTON(wd), GTK_RELIEF_NONE); */
1536   gtk_box_pack_start(GTK_BOX(window->hbox), wd, FALSE, FALSE, 0);
1537   g_signal_connect(G_OBJECT(wd), "clicked",
1538 		   G_CALLBACK(onRaiseButtonClicked), (gpointer)window);
1539   image = gtk_image_new_from_icon_name("go-up", GTK_ICON_SIZE_MENU);
1540   gtk_container_add(GTK_CONTAINER(wd), image);
1541   gtk_widget_set_tooltip_text(wd, _("Raise the rendering window.\n"
1542 				    "  Use <home> as key binding."));
1543 
1544   /* The Label to introduce the combo list. */
1545   wd = gtk_label_new(_("Tool: "));
1546   gtk_box_pack_start(GTK_BOX(window->hbox), wd, FALSE, FALSE, 2);
1547 
1548   /* We create the list store. */
1549   window->list = gtk_list_store_new(TOOL_LIST_N_COLUMNS,
1550 				    GDK_TYPE_PIXBUF, G_TYPE_STRING,
1551 				    G_TYPE_STRING, G_TYPE_POINTER);
1552   /* The combo list. */
1553   window->combo = gtk_combo_box_new_with_model(GTK_TREE_MODEL(window->list));
1554   renderer = gtk_cell_renderer_pixbuf_new();
1555   gtk_cell_renderer_set_fixed_size(renderer, 22, -1);
1556   gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(window->combo), renderer, FALSE);
1557   gtk_cell_layout_add_attribute(GTK_CELL_LAYOUT(window->combo),
1558 				renderer, "pixbuf", TOOL_LIST_ICON);
1559   gtk_cell_layout_add_attribute(GTK_CELL_LAYOUT(window->combo),
1560 				renderer, "stock-id", TOOL_LIST_STOCK);
1561   renderer = gtk_cell_renderer_text_new();
1562   gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(window->combo), renderer, FALSE);
1563   gtk_cell_layout_add_attribute(GTK_CELL_LAYOUT(window->combo),
1564 				renderer, "text", TOOL_LIST_NAME);
1565   gtk_box_pack_start(GTK_BOX(window->hbox), window->combo, TRUE, TRUE, 0);
1566   window->comboChanged = g_signal_connect(G_OBJECT(window->combo), "changed",
1567 					  G_CALLBACK(onComboChanged),
1568 					  (gpointer)window);
1569 
1570   /* Add a menu button. */
1571   wd = gtk_button_new();
1572   gtk_button_set_relief(GTK_BUTTON(wd), GTK_RELIEF_NONE);
1573   gtk_box_pack_start(GTK_BOX(window->hbox), wd, FALSE, FALSE, 2);
1574   g_signal_connect(G_OBJECT(wd), "clicked",
1575 		   G_CALLBACK(onMainButtonClicked), (gpointer)window);
1576   image = create_pixmap((GtkWidget*)0, "stock-menu-detach.png");
1577   gtk_container_add(GTK_CONTAINER(wd), image);
1578   gtk_widget_set_tooltip_text(wd,
1579 		       _("Manage hidden subpanels and dock windows."));
1580 
1581   /* Add a help tooltips. */
1582   wd = gtk_event_box_new();
1583   gtk_event_box_set_visible_window(GTK_EVENT_BOX(wd), FALSE);
1584   gtk_widget_set_tooltip_text(wd,
1585 		       _("Positions, sizes, names, contains... of dock" \
1586 			 " windows are stored in the parameters file, " \
1587 			 "see the 'Config. files' button on the command panel."));
1588   gtk_box_pack_end(GTK_BOX(window->hbox), wd, FALSE, FALSE, 2);
1589   image = gtk_image_new_from_icon_name("help-browser", GTK_ICON_SIZE_MENU);
1590   gtk_container_add(GTK_CONTAINER(wd), image);
1591 
1592   gtk_widget_show_all(window->vbox);
1593   return window;
1594 }
dock_window_ref(VisuUiDockWindow * dock)1595 static VisuUiDockWindow* dock_window_ref(VisuUiDockWindow *dock)
1596 {
1597   dock->refCount += 1;
1598   return dock;
1599 }
dock_window_unref(VisuUiDockWindow * dock)1600 static void dock_window_unref(VisuUiDockWindow *dock)
1601 {
1602   dock->refCount -= 1;
1603   if (!dock->refCount)
1604     {
1605       if (dock->window)
1606         gtk_widget_destroy(dock->window);
1607       else
1608         gtk_widget_destroy(dock->vbox);
1609     }
1610 }
1611 /**
1612  * visu_ui_dock_window_getCharacteristics:
1613  * @dock: a #VisuUiDockWindow object ;
1614  * @id: a location to store the identifier (owned by V_Sim) ;
1615  * @visibility: a location to store the status of the dock, hidden or
1616  * not ;
1617  * @x: a location to store its x position on the root window ;
1618  * @y: a location to store its y position on the root window ;
1619  * @width: a location to store its width ;
1620  * @height: a location to store its height.
1621  *
1622  * A routine to know everything about a #VisuUiDockWindow.
1623  */
visu_ui_dock_window_getCharacteristics(VisuUiDockWindow * dock,gchar ** id,gboolean * visibility,gint * x,gint * y,gint * width,gint * height)1624 void visu_ui_dock_window_getCharacteristics(VisuUiDockWindow *dock, gchar **id,
1625 					     gboolean *visibility,
1626 					     gint *x, gint *y,
1627 					     gint *width, gint *height)
1628 {
1629   g_return_if_fail(dock);
1630 
1631   *id = dock->name;
1632   *visibility = dock->show;
1633   gtk_window_get_position(GTK_WINDOW(dock->window), x, y);
1634   gtk_window_get_size(GTK_WINDOW(dock->window), width, height);
1635 }
1636 /**
1637  * visu_ui_dock_window_getContainer:
1638  * @dock: a dock window descriptor.
1639  *
1640  * A dock window is a small utility window with a list of #VisuUiPanel.
1641  * This window can be embedded in a container or have its own
1642  * GtkWindow. This routine get the top-level container inside a given
1643  * #VisuUiDockWindow. If you prefer to get the GtkWindow containing the
1644  * #VisuUiDockWindow use visu_ui_dock_window_getWindow() instead.
1645  *
1646  * Returns: (transfer none): a top-level container (usually a #GtkVBox).
1647  */
visu_ui_dock_window_getContainer(VisuUiDockWindow * dock)1648 GtkWidget* visu_ui_dock_window_getContainer(VisuUiDockWindow *dock)
1649 {
1650   g_return_val_if_fail(dock, (GtkWidget*)0);
1651 
1652   return dock->vbox;
1653 }
1654 /**
1655  * visu_ui_dock_window_getNotebook:
1656  * @dock: a dock window descriptor.
1657  *
1658  * A dock window is a small utility window with a list of #VisuUiPanel.
1659  * All #VisuUiPanel are contained in a #GtkNotebook. This routine gets it.
1660  *
1661  * Returns: (transfer none): the #GtkNotebook containing the #VisuUiPanel of this
1662  * #VisuUiDockWindow.
1663  */
visu_ui_dock_window_getNotebook(VisuUiDockWindow * dock)1664 GtkWidget* visu_ui_dock_window_getNotebook(VisuUiDockWindow *dock)
1665 {
1666   g_return_val_if_fail(dock, (GtkWidget*)0);
1667 
1668   return dock->notebook;
1669 }
1670 /**
1671  * visu_ui_dock_window_getWindow:
1672  * @dock: a dock window descriptor.
1673  *
1674  * A dock window is a small utility window with a list of #VisuUiPanel.
1675  * This window can be embedded in a container or have its own
1676  * GtkWindow. This routine get the #GtkWindow containing the
1677  * #VisuUiDockWindow in the case the dock is stand-alone. If not NULL is returned.
1678  *
1679  * Returns: (transfer none): a top-level container (usually a #GtkWindow) or NULL.
1680  */
visu_ui_dock_window_getWindow(VisuUiDockWindow * dock)1681 GtkWidget* visu_ui_dock_window_getWindow(VisuUiDockWindow *dock)
1682 {
1683   g_return_val_if_fail(dock, (GtkWidget*)0);
1684 
1685   if (dock->window)
1686     return dock->window;
1687   else
1688     return GTK_WIDGET(visu_ui_main_class_getCurrentPanel());
1689 }
1690 /**
1691  * visu_ui_dock_window_setSize:
1692  * @dock: a #VisuUiDockWindow object ;
1693  * @width: the requested width ;
1694  * @height: the requested height.
1695  *
1696  * Change the size of the given #VisuUiDockWindow. The size is possibly
1697  * adapted to avoid been out of screen.
1698  */
visu_ui_dock_window_setSize(VisuUiDockWindow * dock,guint width,guint height)1699 void visu_ui_dock_window_setSize(VisuUiDockWindow *dock, guint width, guint height)
1700 {
1701   GdkScreen *screen;
1702   gint widthScreen, heightScreen;
1703   gint widthSet, heightSet;
1704 
1705   g_return_if_fail(dock && dock->window);
1706   g_return_if_fail(dock != visu_ui_panel_class_getCommandPanel());
1707 
1708   /* Before setting (width, height), we check that it is coherent with
1709      the screen size. */
1710   if (gtk_widget_is_drawable(dock->window))
1711     screen = gdk_window_get_screen
1712       (GDK_WINDOW(gtk_widget_get_window(dock->window)));
1713   else
1714     screen = gdk_screen_get_default();
1715 #if GTK_MAJOR_VERSION < 3 || (GTK_MAJOR_VERSION == 3 && GTK_MINOR_VERSION < 22)
1716   widthScreen = gdk_screen_get_width(screen);
1717   heightScreen = gdk_screen_get_height(screen);
1718 #else
1719   (void)screen;
1720   widthScreen = 10240;
1721   heightScreen = 10240;
1722 #endif
1723 
1724   widthSet = ((gint)width > widthScreen)?widthScreen:(gint)width;
1725   heightSet = ((gint)height > heightScreen)?heightScreen:(gint)height;
1726   if (widthSet < 0) widthSet = 50;
1727   if (heightSet < 0) heightSet = 50;
1728   DBG_fprintf(stderr, "Gtk VisuUiPanel: set window (%s) size %dx%d.\n",
1729 	      dock->name, widthSet, heightSet);
1730   gtk_window_resize(GTK_WINDOW(dock->window), widthSet, heightSet);
1731 }
1732 /**
1733  * visu_ui_dock_window_setPosition:
1734  * @dock: a #VisuUiDockWindow object ;
1735  * @x: the requested x position ;
1736  * @y: the requested y position.
1737  *
1738  * Change the position of the given #VisuUiDockWindow. The position is possibly
1739  * adapted to avoid been out of screen.
1740  */
visu_ui_dock_window_setPosition(VisuUiDockWindow * dock,guint x,guint y)1741 void visu_ui_dock_window_setPosition(VisuUiDockWindow *dock, guint x, guint y)
1742 {
1743   GdkScreen *screen;
1744   gint xScreen, yScreen;
1745   gint xPosition, yPosition;
1746   gint width, height;
1747 
1748   g_return_if_fail(dock && dock->window);
1749   g_return_if_fail(dock != visu_ui_panel_class_getCommandPanel());
1750 
1751   /* Before setting (x, y), we check that it is coherent with
1752      the screen definition. */
1753   if (gtk_widget_is_drawable(dock->window))
1754     screen = gdk_window_get_screen
1755       (GDK_WINDOW(gtk_widget_get_window(dock->window)));
1756   else
1757     screen = gdk_screen_get_default();
1758 #if GTK_MAJOR_VERSION < 3 || (GTK_MAJOR_VERSION == 3 && GTK_MINOR_VERSION < 22)
1759   xScreen = gdk_screen_get_width(screen);
1760   yScreen = gdk_screen_get_height(screen);
1761 #else
1762   (void)screen;
1763   xScreen = 10240;
1764   yScreen = 10240;
1765 #endif
1766   gtk_window_get_size(GTK_WINDOW(dock->window), &width, &height);
1767 
1768   xPosition = ((gint)x + width > xScreen)?xScreen - width:(gint)x;
1769   yPosition = ((gint)y + height > yScreen)?yScreen - height:(gint)y;
1770   if (xPosition < 0) xPosition = 0;
1771   if (yPosition < 0) yPosition = 0;
1772   DBG_fprintf(stderr, "Gtk VisuUiPanel: set window (%s) position %dx%d.\n",
1773 	      dock->name, xPosition, yPosition);
1774   gtk_window_move(GTK_WINDOW(dock->window), xPosition, yPosition);
1775 }
1776 /**
1777  * visu_ui_dock_window_setVisibility:
1778  * @dock: a #VisuUiDockWindow object ;
1779  * @visible: a boolean.
1780  *
1781  * Change the visibility of a #VisuUiDockWindow. If hidden, the dock is
1782  * added to the list of hidden #VisuUiDockWindow that can be shown again
1783  * using the pop-up menu on every visible #VisuUiDockWindow. The 'Main' dock
1784  * window can not be hidden.
1785  */
visu_ui_dock_window_setVisibility(VisuUiDockWindow * dock,gboolean visible)1786 void visu_ui_dock_window_setVisibility(VisuUiDockWindow *dock, gboolean visible)
1787 {
1788   g_return_if_fail(dock && dock->window);
1789   g_return_if_fail(dock != visu_ui_panel_class_getCommandPanel());
1790 
1791   dock->show = visible;
1792   if (!visible)
1793     gtk_widget_hide(dock->window);
1794   else
1795     gtk_widget_show(dock->window);
1796 }
1797 
onEntryTabview(VisuConfigFile * obj _U_,VisuConfigFileEntry * entry _U_,VisuUiPanelClass * klass _U_)1798 static void onEntryTabview(VisuConfigFile *obj _U_, VisuConfigFileEntry *entry _U_, VisuUiPanelClass *klass _U_)
1799 {
1800   visu_ui_panel_class_setHeaderVisibility(_tabView);
1801 }
1802 /* These functions write all the element list to export there associated resources. */
exportParameters(GString * data,VisuData * dataObj _U_)1803 static void exportParameters(GString *data, VisuData *dataObj _U_)
1804 {
1805   g_string_append_printf(data, "# %s\n", DESC_PARAMETER_TABVIEW_CONFIG);
1806   g_string_append_printf(data, "%s[gtk]: %d\n\n", FLAG_PARAMETER_TABVIEW_CONFIG,
1807 			 local_class->showHeader);
1808 }
1809