summaryrefslogtreecommitdiff
path: root/src/gtkext/gtkdockpanel.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/gtkext/gtkdockpanel.c')
-rw-r--r--src/gtkext/gtkdockpanel.c652
1 files changed, 652 insertions, 0 deletions
diff --git a/src/gtkext/gtkdockpanel.c b/src/gtkext/gtkdockpanel.c
new file mode 100644
index 0000000..f48f31a
--- /dev/null
+++ b/src/gtkext/gtkdockpanel.c
@@ -0,0 +1,652 @@
+
+/* OpenIDA - Outil d'analyse de fichiers binaires
+ * gtkdockpanel.c - manipulation et affichage de panneaux dockables
+ *
+ * Copyright (C) 2008 Cyrille Bagard
+ *
+ * This file is part of OpenIDA.
+ *
+ * OpenIDA is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * OpenIDA is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "gtkdockpanel.h"
+
+
+#include <malloc.h>
+#include <string.h>
+
+
+#include "gtkdropwindow.h"
+
+
+
+/* Valide ou non le terme d'un "Drag and drop". */
+static gboolean gtk_dock_panel_drag_drop_cb(GtkDockPanel *, GdkDragContext *, gint, gint, guint, gpointer);
+
+/* Procède au "Drag and drop" effectif. */
+static void gtk_dock_panel_drag_data_received_cb(GtkDockPanel *, GdkDragContext *, gint, gint, GtkSelectionData *, guint, guint, gpointer);
+
+/* Accompagne le déplacement sur une cible de "Drag and drop". */
+static gboolean gtk_dock_panel_drag_motion_cb(GtkDockPanel *, GdkDragContext *, gint, gint, guint, gpointer);
+
+/* Note la fin des visites sur une cible de "Drag and drop". */
+static void gtk_dock_panel_drag_leave_cb(GtkDockPanel *, GdkDragContext *, guint, gpointer);
+
+/* Procède au démarrage d'un "Drag and drop". */
+static void gtk_dock_panel_drag_begin_cb(GtkDockPanel *, GdkDragContext *, gpointer);
+
+/* Procède à l'envoi depuis la source à la destination. */
+static void gtk_dock_panel_drag_data_get_cb(GtkDockPanel *, GdkDragContext *, GtkSelectionData *, guint, guint, gpointer );
+
+/* Marque l'arrêt d'un "Drag and drop". */
+static void gtk_dock_panel_drag_end_cb(GtkDockPanel *, GdkDragContext *, gpointer);
+
+/* Nettoie les traces d'un "Drag and drop". */
+static void gtk_dock_panel_drag_data_delete_cb(GtkDockPanel *, GdkDragContext *, gpointer);
+
+/* Met à jour le titre du support de panneaux dockables. */
+static gboolean gtk_dock_panel_update_title(GtkNotebook *, GtkNotebookPage *, guint, gpointer);
+
+
+
+/******************************************************************************/
+#define _BYTE 8
+#define _WORD 16
+#define _DWORD 32
+
+
+/******************************************************************************/
+/* Define a list of data types called "targets" that a destination widget will
+ * accept. The string type is arbitrary, and negotiated between DnD widgets by
+ * the developer. An enum or GQuark can serve as the integer target id. */
+enum {
+ TARGET_INT32,
+ TARGET_STRING,
+ TARGET_DOCKITEM,
+ TARGET_ROOTWIN
+};
+
+/* datatype (string), restrictions on DnD (GtkTargetFlags), datatype (int) */
+static GtkTargetEntry target_list[] = {
+ { "INTEGER", 0, TARGET_INT32 },
+ { "STRING", 0, TARGET_STRING },
+ { "OpenIDA/dock-item", 0, TARGET_DOCKITEM },
+ { "application/x-rootwindow-drop", 0, TARGET_ROOTWIN }
+};
+
+static guint n_targets = G_N_ELEMENTS (target_list);
+
+
+
+
+
+
+
+/* Détermine le type du composant d'affichage des morceaux. */
+G_DEFINE_TYPE(GtkDockPanel, gtk_dock_panel, GTK_TYPE_VBOX)
+
+
+
+
+/******************************************************************************
+* *
+* Paramètres : class = classe GTK à initialiser. *
+* *
+* Description : Procède à l'initialisation de l'afficheur de morceaux. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void gtk_dock_panel_class_init(GtkDockPanelClass *class)
+{
+
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : dpanel = composant GTK à initialiser. *
+* *
+* Description : Procède à l'initialisation de la station dockable. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void gtk_dock_panel_init(GtkDockPanel *dpanel)
+{
+
+ GtkWidget *eventbox1;
+ GtkWidget *hbox1;
+ GtkWidget *button1;
+ GtkWidget *image1;
+ GtkWidget *button2;
+ GtkWidget *image2;
+
+
+
+ eventbox1 = gtk_event_box_new ();
+ gtk_widget_show (eventbox1);
+ gtk_box_pack_start (GTK_BOX (dpanel), eventbox1, FALSE, TRUE, 0);
+
+ hbox1 = gtk_hbox_new (FALSE, 0);
+ gtk_widget_show (hbox1);
+ gtk_container_add (GTK_CONTAINER (eventbox1), hbox1);
+
+ dpanel->title = GTK_LABEL(gtk_label_new(("<b>titre</b>")));
+ gtk_widget_show(GTK_WIDGET(dpanel->title));
+ gtk_box_pack_start(GTK_BOX (hbox1), GTK_WIDGET(dpanel->title), TRUE, TRUE, 0);
+ gtk_label_set_use_markup(GTK_LABEL(dpanel->title), TRUE);
+ gtk_misc_set_alignment(GTK_MISC(dpanel->title), 0, 0.5);
+
+ button1 = gtk_button_new ();
+ gtk_widget_show (button1);
+ gtk_box_pack_start (GTK_BOX (hbox1), button1, FALSE, FALSE, 0);
+ gtk_button_set_relief (GTK_BUTTON (button1), GTK_RELIEF_NONE);
+
+ image1 = gtk_image_new_from_stock ("gtk-media-play", GTK_ICON_SIZE_MENU);
+ gtk_widget_show (image1);
+ gtk_container_add (GTK_CONTAINER (button1), image1);
+ gtk_widget_set_size_request (image1, 10, 10);
+
+ button2 = gtk_button_new ();
+ gtk_widget_show (button2);
+ gtk_box_pack_start (GTK_BOX (hbox1), button2, FALSE, FALSE, 0);
+ gtk_button_set_relief (GTK_BUTTON (button2), GTK_RELIEF_NONE);
+
+ image2 = gtk_image_new_from_stock ("gtk-close", GTK_ICON_SIZE_MENU);
+ gtk_widget_show (image2);
+ gtk_container_add (GTK_CONTAINER (button2), image2);
+ gtk_widget_set_size_request (image2, 10, 10);
+
+ dpanel->notebook = gtk_notebook_new ();
+ gtk_widget_show (dpanel->notebook);
+ gtk_box_pack_start (GTK_BOX (dpanel), dpanel->notebook, TRUE, TRUE, 0);
+ gtk_notebook_set_show_border (GTK_NOTEBOOK (dpanel->notebook), FALSE);
+ gtk_notebook_set_tab_pos (GTK_NOTEBOOK (dpanel->notebook), GTK_POS_BOTTOM);
+ gtk_notebook_set_scrollable (GTK_NOTEBOOK (dpanel->notebook), TRUE);
+
+
+
+
+ /* Make the "well label" a DnD destination. */
+ gtk_drag_dest_set
+ (
+ GTK_WIDGET(dpanel), /* widget that will accept a drop */
+ GTK_DEST_DEFAULT_MOTION /* default actions for dest on DnD */
+ | GTK_DEST_DEFAULT_HIGHLIGHT,
+ target_list, /* lists of target to support */
+ n_targets, /* size of list */
+ GDK_ACTION_COPY /* what to do with data after dropped */
+ );
+
+ /* Make the "coin button" a DnD source. */
+ /* Why doesn't GtkLabel work here? */
+ gtk_drag_source_set
+ (
+ GTK_WIDGET(dpanel), /* widget will be drag-able */
+ GDK_BUTTON1_MASK, /* modifier that will start a drag */
+ target_list, /* lists of target to support */
+ n_targets, /* size of list */
+ GDK_ACTION_COPY /* what to do with data after dropped */
+ );
+
+
+ /* Côté destination */
+ g_signal_connect(dpanel, "drag-drop", G_CALLBACK(gtk_dock_panel_drag_drop_cb), NULL);
+ g_signal_connect(dpanel, "drag-data-received", G_CALLBACK(gtk_dock_panel_drag_data_received_cb), NULL);
+ g_signal_connect(dpanel, "drag-motion", G_CALLBACK(gtk_dock_panel_drag_motion_cb), NULL);
+ g_signal_connect(dpanel, "drag-leave", G_CALLBACK(gtk_dock_panel_drag_leave_cb), NULL);
+
+ /* Côté source */
+ g_signal_connect(dpanel, "drag-begin", G_CALLBACK(gtk_dock_panel_drag_begin_cb), NULL);
+ g_signal_connect(dpanel, "drag-data-get", G_CALLBACK(gtk_dock_panel_drag_data_get_cb), NULL);
+ g_signal_connect(dpanel, "drag-end", G_CALLBACK(gtk_dock_panel_drag_end_cb), NULL);
+ //g_signal_connect(dpanel, "drag-data-delete", G_CALLBACK(gtk_dock_panel_drag_data_delete_cb), NULL);
+
+
+ g_signal_connect(dpanel->notebook, "switch-page", G_CALLBACK(gtk_dock_panel_update_title), dpanel);
+
+
+
+
+ dpanel->dropwin = gtk_drop_window_new();
+
+
+
+ /* Make the "well label" a DnD destination. */
+ gtk_drag_dest_set
+ (
+ dpanel->dropwin, /* widget that will accept a drop */
+ GTK_DEST_DEFAULT_MOTION /* default actions for dest on DnD */
+ | GTK_DEST_DEFAULT_HIGHLIGHT,
+ target_list, /* lists of target to support */
+ n_targets, /* size of list */
+ GDK_ACTION_COPY /* what to do with data after dropped */
+ );
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Crée un nouveau composant pour station dockable. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GtkWidget *gtk_dock_panel_new(void)
+{
+ return g_object_new(GTK_TYPE_DOCK_PANEL, NULL);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : dpanel = composant à l'origine de la manoeuvre. *
+* context = contexte de l'opération de "Drag and drop". *
+* x = abscisse du pointeur relaché. *
+* y = ordonnée du pointeur relaché. *
+* time = date de l'opération. *
+* data = adresse non utilisée ici. *
+* *
+* Description : Valide ou non le terme d'un "Drag and drop". *
+* *
+* Retour : TRUE si l'opération peut continuer, FALSE sinon. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static gboolean gtk_dock_panel_drag_drop_cb(GtkDockPanel *dpanel, GdkDragContext *context, gint x, gint y, guint time, gpointer data)
+{
+ gboolean result; /* Ordre à retourner */
+ GdkAtom target; /* Type d'élément à déplacer */
+
+ result = (context->targets != NULL);
+
+ printf(" ## DRAG DROP ## %p\n", dpanel);
+
+ if (context->targets != NULL)
+ {
+ target = GDK_POINTER_TO_ATOM(g_list_nth_data(context->targets, TARGET_DOCKITEM));
+ gtk_drag_get_data(GTK_WIDGET(dpanel), context, target, time);
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : dpanel = composant à l'origine de la manoeuvre. *
+* context = contexte de l'opération de "Drag and drop". *
+* x = abscisse du pointeur relaché. *
+* y = ordonnée du pointeur relaché. *
+* selection = réceptacle pour la transmission. *
+* target = type de données demandé. *
+* time = date de l'opération. *
+* data = adresse non utilisée ici. *
+* *
+* Description : Procède au "Drag and drop" effectif. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void gtk_dock_panel_drag_data_received_cb(GtkDockPanel *dpanel, GdkDragContext *context, gint x, gint y, GtkSelectionData *selection, guint target, guint time, gpointer data)
+{
+ GtkDockItem *ditem; /* Elément transféré */
+ gboolean success; /* Bilan de l'opération */
+
+ success = FALSE;
+
+ if (selection != NULL && selection->length >= 0)
+ switch (target)
+ {
+ case TARGET_DOCKITEM:
+ success = (selection->length == sizeof(GtkDockItem *));
+
+ printf(" ## DRAG DATA RCV ## %p\n", dpanel);
+
+ printf(" -- source :: %p\n", gtk_drag_get_source_widget(context));
+ printf(" -- dest :: %p\n", dpanel);
+
+ if (success)
+ {
+ ditem = GTK_DOCK_ITEM(*((GtkDockItem **)selection->data));
+
+ printf(" :: get ? %p - %d\n", ditem, GTK_IS_DOCK_ITEM(ditem));
+
+ gtk_dock_panel_remove_item(gtk_drag_get_source_widget(context), ditem);
+ gtk_dock_panel_add_item(dpanel, ditem);
+
+ }
+
+ break;
+
+ }
+
+ gtk_drag_finish(context, success, context->action == GDK_ACTION_MOVE, time);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : dpanel = composant à l'origine de la manoeuvre. *
+* context = contexte de l'opération de "Drag and drop". *
+* x = abscisse du pointeur relaché. *
+* y = ordonnée du pointeur relaché. *
+* time = date de l'opération. *
+* data = adresse non utilisée ici. *
+* *
+* Description : Accompagne le déplacement sur une cible de "Drag and drop". *
+* *
+* Retour : TRUE pour continuer la propagation, FALSE sinon. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static gboolean gtk_dock_panel_drag_motion_cb(GtkDockPanel *dpanel, GdkDragContext *context, gint x, gint y, guint time, gpointer data)
+{
+ gint new_x; /* Abscisse de la fenêtre */
+ gint new_y; /* Ordonnée de la fenêtre */
+ GtkRequisition req; /* Taille actuelle du panneau */
+
+ if (!GTK_WIDGET_VISIBLE(dpanel->dropwin))
+ {
+ gdk_window_get_origin(GTK_WIDGET(dpanel)->window, &new_x, &new_y);
+
+ new_x += GTK_WIDGET(dpanel)->allocation.x + (GTK_WIDGET(dpanel)->allocation.width - 89) / 2;
+ new_y += GTK_WIDGET(dpanel)->allocation.y + (GTK_WIDGET(dpanel)->allocation.height - 89) / 2;
+
+ gtk_widget_set_uposition(dpanel->dropwin, new_x, new_y);
+
+ gtk_widget_show(dpanel->dropwin);
+
+ }
+
+ return FALSE;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : dpanel = composant à l'origine de la manoeuvre. *
+* context = contexte de l'opération de "Drag and drop". *
+* x = abscisse du pointeur relaché. *
+* y = ordonnée du pointeur relaché. *
+* time = date de l'opération. *
+* data = adresse non utilisée ici. *
+* *
+* Description : Note la fin des visites sur une cible de "Drag and drop". *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void gtk_dock_panel_drag_leave_cb(GtkDockPanel *dpanel, GdkDragContext *context, guint time, gpointer data)
+{
+ gtk_widget_hide(dpanel->dropwin);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : dpanel = composant à l'origine de la manoeuvre. *
+* context = contexte de l'opération de "Drag and drop". *
+* data = adresse non utilisée ici. *
+* *
+* Description : Procède au démarrage d'un "Drag and drop". *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void gtk_dock_panel_drag_begin_cb(GtkDockPanel *dpanel, GdkDragContext *context, gpointer data)
+{
+ printf(" ## DRAG BEGIN ## %p\n", dpanel);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : dpanel = composant à l'origine de la manoeuvre. *
+* context = contexte de l'opération de "Drag and drop". *
+* selection = réceptacle pour la transmission. *
+* target = type de données demandé. *
+* time = date de l'opération. *
+* data = adresse non utilisée ici. *
+* *
+* Description : Procède à l'envoi depuis la source à la destination. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void gtk_dock_panel_drag_data_get_cb(GtkDockPanel *dpanel, GdkDragContext *context, GtkSelectionData *selection, guint target, guint time, gpointer data)
+{
+ gint current; /* Indice de l'onglet courant */
+ GtkDockItem *ditem; /* Elément à transférer */
+
+ switch (target)
+ {
+ case TARGET_DOCKITEM:
+
+ printf(" ## DRAG GET DATA ## %p\n", dpanel);
+
+ current = gtk_notebook_get_current_page(dpanel->notebook);
+
+ ditem = GTK_DOCK_ITEM(g_list_nth_data(dpanel->ditems, current));
+
+ printf(" %d nth item is %p\n", current, ditem);
+
+ printf(" :: set ? %p - %d\n", ditem, GTK_IS_DOCK_ITEM(ditem));
+
+ gtk_selection_data_set(selection, selection->target,
+ 32, (guchar *)&ditem, sizeof(GtkDockItem *));
+
+ break;
+
+ }
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : dpanel = composant à l'origine de la manoeuvre. *
+* context = contexte de l'opération de "Drag and drop". *
+* data = adresse non utilisée ici. *
+* *
+* Description : Marque l'arrêt d'un "Drag and drop". *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void gtk_dock_panel_drag_end_cb(GtkDockPanel *dpanel, GdkDragContext *context, gpointer data)
+{
+ printf(" ## DRAG END ## %p\n", dpanel);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : dpanel = composant à l'origine de la manoeuvre. *
+* context = contexte de l'opération de "Drag and drop". *
+* data = adresse non utilisée ici. *
+* *
+* Description : Nettoie les traces d'un "Drag and drop". *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void gtk_dock_panel_drag_data_delete_cb(GtkDockPanel *dpanel, GdkDragContext *context, gpointer data)
+{
+
+
+
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : dpanel = composant GTK à compléter. *
+* ditem = nouvel élément à intégrer. *
+* *
+* Description : Ajoute un paquet d'informations à la station dockable. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void gtk_dock_panel_add_item(GtkDockPanel *dpanel, GtkDockItem *ditem)
+{
+ GtkWidget *label; /* Etiquette d'onglet */
+
+ dpanel->ditems = g_list_append(dpanel->ditems, ditem);
+
+ printf("[add %p to %p] list len :: %u\n", ditem, dpanel, g_list_length(dpanel->ditems));
+
+ gtk_container_add(GTK_CONTAINER(dpanel->notebook), gtk_dock_item_get_panel(ditem));
+
+ label = gtk_label_new(gtk_dock_item_get_name(ditem));
+ gtk_widget_show(label);
+
+ gtk_notebook_set_tab_label(dpanel->notebook,
+ gtk_notebook_get_nth_page(dpanel->notebook, gtk_notebook_get_n_pages(dpanel->notebook) - 1),
+ label);
+
+ gtk_notebook_set_show_tabs(dpanel->notebook, g_list_length(dpanel->ditems) > 1);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : dpanel = composant GTK à mettre à jour. *
+* ditem = nouvel élément à sortir. *
+* *
+* Description : Supprime un paquet d'informations à la station dockable. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void gtk_dock_panel_remove_item(GtkDockPanel *dpanel, GtkDockItem *ditem)
+{
+ gint pos; /* Position de l'élément visé */
+
+ pos = g_list_index(dpanel->ditems, ditem);
+
+ dpanel->ditems = g_list_remove(dpanel->ditems, ditem);
+
+ printf("[rem %p from %p] list len :: %u\n", ditem, dpanel, g_list_length(dpanel->ditems));
+
+ gtk_container_remove(GTK_CONTAINER(dpanel->notebook), gtk_dock_item_get_panel(ditem));
+
+ //gtk_notebook_remove_page(dpanel->notebook, pos);
+
+ gtk_notebook_set_show_tabs(dpanel->notebook, g_list_length(dpanel->ditems) > 1);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : notebook = support à l'origine de la mise à jour. *
+* page = onglet mis en avant. *
+* index = indice de l'onglet actuellement actif. *
+* data = adresse du conteneur supérieur. *
+* *
+* Description : Met à jour le titre du support de panneaux dockables. *
+* *
+* Retour : TRUE ? *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static gboolean gtk_dock_panel_update_title(GtkNotebook *notebook, GtkNotebookPage *page, guint index, gpointer data)
+{
+ GtkDockItem *ditem; /* Elément nouvellement actif */
+ const gchar *desc; /* Description à afficher */
+ char *str; /* Valeur finale reconstituée */
+
+
+ printf("[%p] list len :: %u / %u\n", data, index, g_list_length(GTK_DOCK_PANEL(data)->ditems));
+
+ if (index >= g_list_length(GTK_DOCK_PANEL(data)->ditems)) return FALSE;
+
+ printf(" >> ditem = %p\n", g_list_nth_data(GTK_DOCK_PANEL(data)->ditems, index));
+
+ printf(" >> index :: %u vs %d\n", index, gtk_notebook_get_current_page(GTK_DOCK_PANEL(data)->notebook));
+
+ ditem = GTK_DOCK_ITEM(g_list_nth_data(GTK_DOCK_PANEL(data)->ditems, index));
+
+ desc = gtk_dock_item_get_desc(ditem);
+ if (desc == NULL) desc = gtk_dock_item_get_name(ditem);
+
+ str = calloc(strlen("<b>") + strlen(desc) + strlen("</b>") + 1, sizeof(char));
+
+ strcpy(str, "<b>");
+ strcat(str, desc);
+ strcat(str, "</b>");
+
+ gtk_label_set_markup(GTK_DOCK_PANEL(data)->title, str);
+
+ free(str);
+
+ return TRUE;
+
+}