/* Chrysalide - Outil d'analyse de fichiers binaires
 * easygtk.c - mise en place rapide de composants GTK
 *
 * Copyright (C) 2008-2013 Cyrille Bagard
 *
 *  This file is part of Chrysalide.
 *
 *  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 "easygtk.h"


#include <assert.h>


#include "support.h"



/* Termine la construction d'un composant 'GtkButton'. */
static void _finish_button_with_img(GtkWidget *, GObject *, const char *, GtkWidget *, const char *);



/******************************************************************************
*                                                                             *
*  Paramètres  : widget = composant graphique visé par la procédure.          *
*                xalign = alignement horizontal à appliquer.                  *
*                yalign = alignement vertical à appliquer.                    *
*                                                                             *
*  Description : Aligne un composant GTK par rapport à son parent.            *
*                                                                             *
*  Retour      : -                                                            *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/

void qck_set_alignment(GtkWidget *widget, GtkAlign xalign, GtkAlign yalign)
{
    gtk_widget_set_halign(widget, xalign);
    gtk_widget_set_valign(widget, yalign);

}


/******************************************************************************
*                                                                             *
*  Paramètres  : widget = composant graphique visé par la procédure.          *
*                pt     = espace imposé à la zone supérieure.                 *
*                pb     = espace imposé à la zone inférieure.                 *
*                pl     = espace imposé à la zone gauche.                     *
*                pr     = espace imposé à la zone droite.                     *
*                                                                             *
*  Description : Définit des bordures extérieures à appliquer à un composant. *
*                                                                             *
*  Retour      : -                                                            *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/

void qck_set_margins(GtkWidget *widget, guint pt, guint pb, guint pl, guint pr)
{
    gtk_widget_set_margin_top(widget, pt);
    gtk_widget_set_margin_bottom(widget, pb);

    gtk_widget_set_margin_start(widget, pl);
    gtk_widget_set_margin_end(widget, pr);

}


/******************************************************************************
*                                                                             *
*  Paramètres  : caption = contenu de l'étiqutte à placer.                    *
*                content = composant en place à poser sur le conteneur.       *
*                pt      = espace imposé à la zone supérieure.                *
*                pb      = espace imposé à la zone inférieure.                *
*                pl      = espace imposé à la zone gauche.                    *
*                pr      = espace imposé à la zone droite.                    *
*                                                                             *
*  Description : Met en place une frame.                                      *
*                                                                             *
*  Retour      : Composant 'GtkWidget' ici créé.                              *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/

GtkWidget *qck_create_frame(const char *caption, GtkWidget *content, guint pt, guint pb, guint pl, guint pr)
{
    GtkWidget *result;                      /* Instance à renvoyer         */
    GtkWidget *label;                       /* Etiquette à utiliser        */

    result = gtk_frame_new(NULL);
    gtk_widget_show(result);

    gtk_frame_set_shadow_type(GTK_FRAME(result), GTK_SHADOW_NONE);

    label = qck_create_label(NULL, NULL, caption);
    gtk_frame_set_label_widget(GTK_FRAME(result), label);
    gtk_label_set_use_markup(GTK_LABEL(label), TRUE);

    qck_set_margins(content, pt, pb, pl, pr);
    gtk_container_add(GTK_CONTAINER(result), content);

    return result;

}


/******************************************************************************
*                                                                             *
*  Paramètres  : object = espace dédié à l'inscription de références.         *
*                name   = nom à donner au nouveau composant.                  *
*                                                                             *
*  Description : Met en place un support à onglets.                           *
*                                                                             *
*  Retour      : Composant 'GtkWidget' ici créé.                              *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/

GtkWidget *qck_create_notebook(GObject *object, const char *name)
{
    GtkWidget *result;                      /* Instance à renvoyer         */

    result = gtk_notebook_new();

    if (G_IS_OBJECT(object) && name != NULL)
    {
        g_object_ref(G_OBJECT(result));
        g_object_set_data_full(object, name, result, (GDestroyNotify)g_object_unref);
    }

    gtk_widget_show(result);

    return result;

}


/******************************************************************************
*                                                                             *
*  Paramètres  : object = espace dédié à l'inscription de références.         *
*                name   = nom à donner au nouveau composant.                  *
*                                                                             *
*  Description : Met en place un support avec défilement automatique.         *
*                                                                             *
*  Retour      : Composant 'GtkWidget' ici créé.                              *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/

GtkWidget *qck_create_scrolled_window(GObject *object, const char *name)
{
    GtkWidget *result;                      /* Instance à renvoyer         */

    result = gtk_scrolled_window_new(NULL, NULL);
    gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(result),
                                   GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);

    if (G_IS_OBJECT(object) && name != NULL)
    {
        g_object_ref(G_OBJECT(result));
        g_object_set_data_full(object, name, result, (GDestroyNotify)g_object_unref);
    }

    gtk_widget_show(result);

    return result;

}


/******************************************************************************
*                                                                             *
*  Paramètres  : object   = espace dédié à l'inscription de références.       *
*                name     = nom à donner au nouveau composant.                *
*                filename = chemin d'accès complet au fichier à afficher.     *
*                                                                             *
*  Description : Crée un composant 'GtkImage'.                                *
*                                                                             *
*  Retour      : Image mise en place.                                         *
*                                                                             *
*  Remarques   : Si le chemin est libérable, il est libéré de la mémoire.     *
*                                                                             *
******************************************************************************/

GtkWidget *qck_create_image(GObject *object, const char *name, gchar *filename)
{
    GtkWidget *result;                      /* Résultat à renvoyer         */

    if (filename == NULL)
        result = gtk_image_new();

    else
    {
        result = gtk_image_new_from_file(filename);
        g_free(filename);
    }

    if (G_IS_OBJECT(object) && name != NULL)
    {
        g_object_ref(G_OBJECT(result));
        g_object_set_data_full(object, name, result, (GDestroyNotify)g_object_unref);
    }

    gtk_widget_show(result);

	return result;

}


/******************************************************************************
*                                                                             *
*  Paramètres  : object  = espace dédié à l'inscription de références.        *
*                name    = nom à donner au nouveau composant.                 *
*                caption = intitulé apparaissant sur le composant.            *
*                                                                             *
*  Description : Crée un composant 'GtkLabel'.                                *
*                                                                             *
*  Retour      : Champ d'indication mis en place.                             *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/

GtkWidget *qck_create_label(GObject *object, const char *name, const char *caption)
{
    GtkWidget *result;                      /* Résultat à renvoyer         */

    result = gtk_label_new(caption);

    if (G_IS_OBJECT(object) && name != NULL)
    {
        g_object_ref(G_OBJECT(result));
        g_object_set_data_full(object, name, result, (GDestroyNotify)g_object_unref);
    }

    gtk_widget_show(result);
    gtk_widget_set_halign(result, GTK_ALIGN_START);
    gtk_widget_set_valign(result, GTK_ALIGN_CENTER);

	return result;

}


/******************************************************************************
*                                                                             *
*  Paramètres  : object = espace dédié à l'inscription de références.         *
*                name   = nom à donner au nouveau composant.                  *
*                text   = éventuel contenu initial du champ de saisie.        *
*                                                                             *
*  Description : Crée et enregistre un composant 'GtkEntry'.                  *
*                                                                             *
*  Retour      : Champ de saisie mis en place.                                *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/

GtkWidget *qck_create_entry(GObject *object, const char *name, const char *text)
{
    GtkWidget *result;                      /* Résultat à renvoyer         */

    result = gtk_entry_new();

    if (G_IS_OBJECT(object) && name != NULL)
    {
        g_object_ref(G_OBJECT(result));
        g_object_set_data_full(object, name, result, (GDestroyNotify)g_object_unref);
    }

    gtk_widget_show(result);

	if (text != NULL)
	    gtk_entry_set_text(GTK_ENTRY(result), text);

	return result;

}


/******************************************************************************
*                                                                             *
*  Paramètres  : object  = espace dédié à l'inscription de références.        *
*                name    = nom à donner au nouveau composant.                 *
*                handler = éventuelle fonction de sélection associée.         *
*                data    = données à transmettre avec l'événement si besoin.  *
*                                                                             *
*  Description : Crée et enregistre un composant 'GtkTextView'.               *
*                                                                             *
*  Retour      : Champ de saisie mis en place.                                *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/

GtkWidget *qck_create_textview(GObject *object, const char *name, GCallback handler, gpointer data)
{
    GtkWidget *result;                      /* Résultat à renvoyer         */
    GtkTextBuffer *buffer;                  /* Tampon créé en interne GTK  */

    result = gtk_text_view_new();

    if (G_IS_OBJECT(object) && name != NULL)
    {
        g_object_ref(G_OBJECT(result));
        g_object_set_data_full(object, name, result, (GDestroyNotify)g_object_unref);
    }

    gtk_widget_show(result);

    if (handler != NULL)
    {
        buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(result));
        g_signal_connect(buffer, "changed", handler, data);
    }

	return result;

}


/******************************************************************************
*                                                                             *
*  Paramètres  : object  = espace dédié à l'inscription de références.        *
*                name    = nom à donner au nouveau composant.                 *
*                caption = intitulé du bouton à créer.                        *
*                handler = éventuelle fonction de sélection associée.         *
*                data    = données à transmettre avec l'événement si besoin.  *
*                                                                             *
*  Description : Crée et enregistre un composant 'GtkButton'.                 *
*                                                                             *
*  Retour      : Simple bouton mis en place.                                  *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/

GtkWidget *qck_create_button(GObject *object, const char *name, const char *caption, GCallback handler, gpointer data)
{
    GtkWidget *result;                      /* Résultat à renvoyer         */

    result = gtk_button_new_with_mnemonic(caption);
    gtk_widget_set_can_default(result, TRUE);

    if (G_IS_OBJECT(object) && name != NULL)
    {
        g_object_ref(G_OBJECT(result));
        g_object_set_data_full(object, name, result, (GDestroyNotify)g_object_unref);
    }

    gtk_widget_show(result);

    if (handler != NULL)
        g_signal_connect(result, "clicked", handler, data);

	return result;

}


/******************************************************************************
*                                                                             *
*  Paramètres  : object  = espace dédié à l'inscription de références.        *
*                name    = nom à donner au nouveau composant.                 *
*                image   = nom de l'image stockée dans GTK.                   *
*                handler = éventuelle fonction de sélection associée.         *
*                data    = données à transmettre avec l'événement si besoin.  *
*                                                                             *
*  Description : Crée et enregistre un composant 'GtkButton'.                 *
*                                                                             *
*  Retour      : Simple bouton mis en place.                                  *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/

GtkWidget *qck_create_button_with_img(GObject *object, const char *name, const char *image, GCallback handler, gpointer data)
{
    GtkWidget *result;                      /* Résultat à renvoyer         */
    GtkWidget *render;                      /* Image à ajouter au bouton   */

    result = gtk_button_new();
    gtk_widget_set_can_default(result, TRUE);

    render = gtk_image_new_from_icon_name(image, GTK_ICON_SIZE_BUTTON);
    gtk_widget_show(render);
    gtk_container_add(GTK_CONTAINER(result), render);

    if (G_IS_OBJECT(object) && name != NULL)
    {
        g_object_ref(G_OBJECT(result));
        g_object_set_data_full(object, name, result, (GDestroyNotify)g_object_unref);
    }

    gtk_widget_show(result);

    if (handler != NULL)
        g_signal_connect(result, "clicked", handler, data);

	return result;

}


/******************************************************************************
*                                                                             *
*  Paramètres  : button  = composant graphique dont la définition est à finir.*
*                object  = espace dédié à l'inscription de références.        *
*                name    = nom à donner au nouveau composant.                 *
*                picture = éventuelle image sous forme de composant GTK.      *
*                label   = contenu de l'étiquette éventuelle associée.        *
*                                                                             *
*  Description : Termine la construction d'un composant 'GtkButton'.          *
*                                                                             *
*  Retour      : -                                                            *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/

static void _finish_button_with_img(GtkWidget *button, GObject *object, const char *name, GtkWidget *picture, const char *label)
{
    GtkWidget *caption;                     /* Etiquette à coller          */
    GtkWidget *hbox;                        /* Séparation horizontale      */

    /* Création des éléments internes (2/2) */

    if (label != NULL)
    {
        caption = gtk_label_new_with_mnemonic(label);
        gtk_widget_show(caption);
    }

    /* Mise en place */

    if (picture != NULL && label != NULL)
    {
        hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 2);
        gtk_widget_show(hbox);
        gtk_container_add(GTK_CONTAINER(button), hbox);

        gtk_box_pack_start(GTK_BOX(hbox), picture, FALSE, FALSE, 0);
        gtk_box_pack_start(GTK_BOX(hbox), caption, FALSE, FALSE, 0);

    }

    else if (picture != NULL)
        gtk_container_add(GTK_CONTAINER(button), picture);

    else if (label != NULL)
        gtk_container_add(GTK_CONTAINER(button), caption);

    else
        assert(0);

    /* Interactions GTK... */

    if (G_IS_OBJECT(object) && name != NULL)
    {
        g_object_ref(G_OBJECT(button));
        g_object_set_data_full(object, name, button, (GDestroyNotify)g_object_unref);
    }

    gtk_widget_show(button);

}


/******************************************************************************
*                                                                             *
*  Paramètres  : object  = espace dédié à l'inscription de références.        *
*                name    = nom à donner au nouveau composant.                 *
*                image   = nom de l'image stockée dans GTK.                   *
*                size    = taille de l'image éventuelle à faire figurer.      *
*                label   = contenu de l'étiquette éventuelle associée.        *
*                handler = éventuelle fonction de sélection associée.         *
*                data    = données à transmettre avec l'événement si besoin.  *
*                                                                             *
*  Description : Crée et enregistre un composant 'GtkButton'.                 *
*                                                                             *
*  Retour      : Simple bouton mis en place.                                  *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/

GtkWidget *qck_create_button_with_named_img(GObject *object, const char *name, const char *image, GtkIconSize size, const char *label, GCallback handler, gpointer data)
{
    GtkWidget *result;                      /* Résultat à renvoyer         */
    GtkWidget *picture;                     /* Image de représentation     */

    result = gtk_button_new();
    gtk_widget_set_can_default(result, TRUE);

    /* Création des éléments internes (1/2) */

    if (image != NULL)
    {
        picture = gtk_image_new_from_icon_name(image, size);
        gtk_widget_show(picture);
    }
    else
        picture = NULL;

    _finish_button_with_img(result, object, name, picture, label);

    if (handler != NULL)
        g_signal_connect(result, "clicked", handler, data);

	return result;

}


/******************************************************************************
*                                                                             *
*  Paramètres  : object  = espace dédié à l'inscription de références.        *
*                name    = nom à donner au nouveau composant.                 *
*                image   = nom de l'image stockée dans GTK.                   *
*                label   = contenu de l'étiquette éventuelle associée.        *
*                handler = éventuelle fonction de sélection associée.         *
*                data    = données à transmettre avec l'événement si besoin.  *
*                                                                             *
*  Description : Crée et enregistre un composant 'GtkButton'.                 *
*                                                                             *
*  Retour      : Simple bouton mis en place.                                  *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/

GtkWidget *qck_create_button_with_css_img(GObject *object, const char *name, const char *image, const char *label, GCallback handler, gpointer data)
{
    GtkWidget *result;                      /* Résultat à renvoyer         */
    GtkWidget *picture;                     /* Image de représentation     */

    result = gtk_button_new();
    gtk_widget_set_can_default(result, TRUE);

    /* Création des éléments internes (1/2) */

    if (image != NULL)
    {
        picture = gtk_image_new();
        gtk_widget_show(picture);

        gtk_widget_set_name(picture, image);

    }
    else
        picture = NULL;

    _finish_button_with_img(result, object, name, picture, label);

    if (handler != NULL)
        g_signal_connect(result, "clicked", handler, data);

	return result;

}


/******************************************************************************
*                                                                             *
*  Paramètres  : object  = espace dédié à l'inscription de références.        *
*                name    = nom à donner au nouveau composant.                 *
*                image   = nom de l'image stockée dans GTK.                   *
*                size    = taille de l'image éventuelle à faire figurer.      *
*                label   = contenu de l'étiquette éventuelle associée.        *
*                handler = éventuelle fonction de sélection associée.         *
*                data    = données à transmettre avec l'événement si besoin.  *
*                                                                             *
*  Description : Crée et enregistre un composant 'GtkCheckButton'.            *
*                                                                             *
*  Retour      : Simple bouton mis en place.                                  *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/

GtkWidget *qck_create_toggle_button_with_named_img(GObject *object, const char *name, const char *image, GtkIconSize size, const char *label, GCallback handler, gpointer data)
{
    GtkWidget *result;                      /* Résultat à renvoyer         */
    GtkWidget *picture;                     /* Image de représentation     */

    result = gtk_toggle_button_new();
    gtk_widget_set_can_default(result, TRUE);

    /* Création des éléments internes (1/2) */

    if (image != NULL)
    {
        picture = gtk_image_new_from_icon_name(image, size);
        gtk_widget_show(picture);
    }
    else
        picture = NULL;

    _finish_button_with_img(result, object, name, picture, label);

    if (handler != NULL)
        g_signal_connect(result, "toggled", handler, data);

	return result;

}


/******************************************************************************
*                                                                             *
*  Paramètres  : object  = espace dédié à l'inscription de références.        *
*                name    = nom à donner au nouveau composant.                 *
*                caption = désignation apparaîssant sur le corps de l'objet.  *
*                handler = éventuelle fonction de sélection associée.         *
*                data    = données à transmettre avec l'événement si besoin.  *
*                                                                             *
*  Description : Crée et enregistre un composant 'GtkCheckButton'.            *
*                                                                             *
*  Retour      : Composant mis en place.                                      *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/

GtkWidget *qck_create_check_button(GObject *object, const char *name, const char *caption, GCallback handler, gpointer data)
{
    GtkWidget *result;                      /* Résultat à renvoyer         */

	result = gtk_check_button_new_with_label(caption);

    if (G_IS_OBJECT(object) && name != NULL)
    {
        g_object_ref(G_OBJECT(result));
        g_object_set_data_full(object, name, result, (GDestroyNotify)g_object_unref);
    }

    gtk_widget_show(result);

    if (handler != NULL)
        g_signal_connect(result, "toggled", handler, data);

	return result;

}


/******************************************************************************
*                                                                             *
*  Paramètres  : object  = espace dédié à l'inscription de références.        *
*                name    = nom à donner au nouveau composant.                 *
*                caption = désignation apparaîssant sur le corps de l'objet.  *
*                member  = membre de la liste des autres boutons.             *
*                handler = éventuelle fonction de sélection associée.         *
*                data    = données à transmettre avec l'événement si besoin.  *
*                                                                             *
*  Description : Crée et enregistre un composant 'GtkRadioButton'.            *
*                                                                             *
*  Retour      : Composant mis en place.                                      *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/

GtkWidget *qck_create_radio_button(GObject *object, const char *name, const char *caption, GtkRadioButton *member, GCallback handler, gpointer data)
{
    GtkWidget *result;                      /* Résultat à renvoyer         */

	result = gtk_radio_button_new_with_label_from_widget(member, caption);

    if (G_IS_OBJECT(object) && name != NULL)
    {
        g_object_ref(G_OBJECT(result));
        g_object_set_data_full(object, name, result, (GDestroyNotify)g_object_unref);
    }

    gtk_widget_show(result);

    if (handler != NULL)
        g_signal_connect(result, "toggled", handler, data);

	return result;

}


/******************************************************************************
*                                                                             *
*  Paramètres  : object  = espace dédié à l'inscription de références.        *
*                name    = nom à donner au nouveau composant.                 *
*                handler = éventuelle fonction de sélection associée.         *
*                data    = données à transmettre avec l'événement si besoin.  *
*                                                                             *
*  Description : Crée et enregistre un composant 'GtkComboBox'.               *
*                                                                             *
*  Retour      : Composant mis en place.                                      *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/

GtkWidget *qck_create_combobox(GObject *object, const char *name, GCallback handler, gpointer data)
{
    GtkWidget *result;                      /* Résultat à renvoyer         */

    result = gtk_combo_box_text_new();

    if (G_IS_OBJECT(object) && name != NULL)
    {
        g_object_ref(G_OBJECT(result));
        g_object_set_data_full(object, name, result, (GDestroyNotify)g_object_unref);
    }

    gtk_widget_show(result);

    if (handler != NULL)
        g_signal_connect(result, "changed", handler, data);

	return result;

}


/******************************************************************************
*                                                                             *
*  Paramètres  : object  = espace dédié à l'inscription de références.        *
*                name    = nom à donner au nouveau composant.                 *
*                handler = éventuelle fonction de sélection associée.         *
*                data    = données à transmettre avec l'événement si besoin.  *
*                                                                             *
*  Description : Crée et enregistre un composant 'GtkComboBox'.               *
*                                                                             *
*  Retour      : Composant mis en place.                                      *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/

GtkWidget *qck_create_combobox2(GObject *object, const char *name, GCallback handler, gpointer data)
{
    GtkWidget *result;                      /* Résultat à renvoyer         */

    result = gtk_combo_box_text_new();

    if (G_IS_OBJECT(object) && name != NULL)
    {
        g_object_ref(G_OBJECT(result));
        g_object_set_data_full(object, name, result, (GDestroyNotify)g_object_unref);
    }

    gtk_widget_show(result);

    if (handler != NULL)
        g_signal_connect(result, "changed", handler, data);

	return result;

}


/******************************************************************************
*                                                                             *
*  Paramètres  : object  = espace dédié à l'inscription de références.        *
*                name    = nom à donner au nouveau composant.                 *
*                handler = éventuelle fonction de sélection associée.         *
*                data    = données à transmettre avec l'événement si besoin.  *
*                                                                             *
*  Description : Crée et enregistre un composant 'GtkComboBox'.               *
*                                                                             *
*  Retour      : Composant mis en place.                                      *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/

GtkWidget *qck_create_combobox_with_entry(GObject *object, const char *name, GCallback handler, gpointer data)
{
    GtkWidget *result;                      /* Résultat à renvoyer         */

    result = gtk_combo_box_text_new_with_entry();

    if (G_IS_OBJECT(object) && name != NULL)
    {
        g_object_ref(G_OBJECT(result));
        g_object_set_data_full(object, name, result, (GDestroyNotify)g_object_unref);
    }

    gtk_widget_show(result);

    if (handler != NULL)
        g_signal_connect(result, "changed", handler, data);

	return result;

}


/******************************************************************************
*                                                                             *
*  Paramètres  : object  = espace dédié à l'inscription de références.        *
*                name    = nom à donner au nouveau composant.                 *
*                caption = intitulé du menu à créer.                          *
*                handler = éventuelle fonction de sélection associée.         *
*                data    = données à transmettre avec l'événement si besoin.  *
*                                                                             *
*  Description : Crée et enregistre un composant 'GtkMenuItem'.               *
*                                                                             *
*  Retour      : Simple élément de menu mis en place.                         *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/

GtkWidget *qck_create_menu_item(GObject *object, const char *name, const char *caption, GCallback handler, gpointer data)
{
    GtkWidget *result;                      /* Résultat à renvoyer         */

    result = gtk_menu_item_new_with_mnemonic(caption);

    if (G_IS_OBJECT(object) && name != NULL)
    {
        g_object_ref(G_OBJECT(result));
        g_object_set_data_full(object, name, result, (GDestroyNotify)g_object_unref);
    }

    gtk_widget_show(result);

    if (handler != NULL)
        g_signal_connect(result, "activate", handler, data);

	return result;

}


/******************************************************************************
*                                                                             *
*  Paramètres  : object  = espace dédié à l'inscription de références.        *
*                name    = nom à donner au nouveau composant.                 *
*                caption = intitulé du menu à créer.                          *
*                handler = éventuelle fonction de sélection associée.         *
*                data    = données à transmettre avec l'événement si besoin.  *
*                                                                             *
*  Description : Crée et enregistre un composant 'GtkCheckMenuItem'.          *
*                                                                             *
*  Retour      : Simple élément de menu mis en place.                         *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/

GtkWidget *qck_create_check_menu_item(GObject *object, const char *name, const char *caption, GCallback handler, gpointer data)
{
    GtkWidget *result;                      /* Résultat à renvoyer         */

    result = gtk_check_menu_item_new_with_mnemonic(caption);

    if (G_IS_OBJECT(object) && name != NULL)
    {
        g_object_ref(G_OBJECT(result));
        g_object_set_data_full(object, name, result, (GDestroyNotify)g_object_unref);
    }

    gtk_widget_show(result);

    if (handler != NULL)
        g_signal_connect(result, "toggled", handler, data);

	return result;

}


/******************************************************************************
*                                                                             *
*  Paramètres  : object  = espace dédié à l'inscription de références.        *
*                name    = nom à donner au nouveau composant.                 *
*                rgroup  = groupe d'apparatenance pour les radios.            *
*                caption = intitulé du menu à créer.                          *
*                handler = éventuelle fonction de sélection associée.         *
*                data    = données à transmettre avec l'événement si besoin.  *
*                                                                             *
*  Description : Crée et enregistre un composant 'GtkRadioMenuItem'.          *
*                                                                             *
*  Retour      : Simple élément de menu mis en place.                         *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/

GtkWidget *qck_create_radio_menu_item(GObject *object, const char *name, GSList *rgroup, const char *caption, GCallback handler, gpointer data)
{
    GtkWidget *result;                      /* Résultat à renvoyer         */

    result = gtk_radio_menu_item_new_with_mnemonic(rgroup, caption);

    if (G_IS_OBJECT(object) && name != NULL)
    {
        g_object_ref(G_OBJECT(result));
        g_object_set_data_full(object, name, result, (GDestroyNotify)g_object_unref);
    }

    gtk_widget_show(result);

    if (handler != NULL)
        g_signal_connect(result, "toggled", handler, data);

	return result;

}


/******************************************************************************
*                                                                             *
*  Paramètres  : item        = élément d'un menu à mettre à jour.             *
*                accelerator = description sous forme de chaîne de caractères.*
*                group       = groupe d'appartenance du raccourci.            *
*                                                                             *
*  Description : Ajoute un accélérateur à un élément de menu existant.        *
*                                                                             *
*  Retour      : -                                                            *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/

void add_accelerator_to_menu_item(GtkWidget *item, const char *accelerator, GtkAccelGroup *group)
{
    guint key;                              /* Touche concernée            */
    GdkModifierType mods;                   /* Eventuels modificateurs     */

    gtk_accelerator_parse(accelerator, &key, &mods);

    gtk_widget_add_accelerator(item, "activate", group,
                               key, mods, GTK_ACCEL_VISIBLE);

}


/******************************************************************************
*                                                                             *
*  Paramètres  : -                                                            *
*                                                                             *
*  Description : Crée et enregistre un composant 'GtkSeparatorMenuItem'.      *
*                                                                             *
*  Retour      : Simple élément de menu mis en place.                         *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/

GtkWidget *qck_create_menu_separator(void)
{
    GtkWidget *result;                      /* Résultat à renvoyer         */

    result = gtk_separator_menu_item_new();
    gtk_widget_show(result);

    return result;

}










/******************************************************************************
*                                                                             *
*  Paramètres  : object   = espace dédié à l'inscription de références.       *
*                name     = nom à donner au nouveau composant.                *
*                caption  = étquette pour le bouton ou NULL.                  *
*                filename = nom du fichier d'image à charger.                 *
*                handler  = éventuelle fonction de sélection associée.        *
*                data     = données à transmettre avec l'événement si besoin. *
*                                                                             *
*  Description : Crée et enregistre un composant 'GtkToolButton'.             *
*                                                                             *
*  Retour      : Simple élément de barre d'outils mis en place.               *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/

GtkWidget *qck_create_tool_button(GObject *object, const char *name, const char *caption, const char *filename, GCallback handler, gpointer data)
{
    GtkWidget *result;                      /* Résultat à renvoyer         */
    GtkWidget *image;                       /* Image de représentation     */

    image = get_image_from_file(filename);
    result = GTK_WIDGET(gtk_tool_button_new(image, caption));

    if (G_IS_OBJECT(object) && name != NULL)
    {
        g_object_ref(G_OBJECT(result));
        g_object_set_data_full(object, name, result, (GDestroyNotify)g_object_unref);
    }

    gtk_widget_show(result);

    if (handler != NULL)
        g_signal_connect(result, "clicked", handler, data);

	return result;

}


/******************************************************************************
*                                                                             *
*  Paramètres  : object   = espace dédié à l'inscription de références.       *
*                name     = nom à donner au nouveau composant.                *
*                caption  = étquette pour le bouton ou NULL.                  *
*                filename = nom du fichier d'image à charger.                 *
*                handler  = éventuelle fonction de sélection associée.        *
*                data     = données à transmettre avec l'événement si besoin. *
*                                                                             *
*  Description : Crée et enregistre un composant 'GtkToggleToolButton'.       *
*                                                                             *
*  Retour      : Simple élément de barre d'outils mis en place.               *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/

GtkWidget *qck_create_toggle_tool_button(GObject *object, const char *name, const char *caption, const char *filename, GCallback handler, gpointer data)
{
    GtkWidget *result;                      /* Résultat à renvoyer         */
    GtkWidget *image;                       /* Image de représentation     */

    result = GTK_WIDGET(gtk_toggle_tool_button_new());

    if (caption != NULL)
        gtk_tool_button_set_label(GTK_TOOL_BUTTON(result), caption);

    image = get_image_from_file(filename);
    gtk_tool_button_set_icon_widget(GTK_TOOL_BUTTON(result), image);

    if (G_IS_OBJECT(object) && name != NULL)
    {
        g_object_ref(G_OBJECT(result));
        g_object_set_data_full(object, name, result, (GDestroyNotify)g_object_unref);
    }

    gtk_widget_show(result);

    if (handler != NULL)
        g_signal_connect(result, "toggled", handler, data);

	return result;

}


/******************************************************************************
*                                                                             *
*  Paramètres  : object = espace dédié à l'inscription de références.         *
*                name   = nom à donner au nouveau composant.                  *
*                                                                             *
*  Description : Crée et enregistre un composant 'GtkSeparatorToolItem'.      *
*                                                                             *
*  Retour      : Simple élément de barre d'outils mis en place.               *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/

GtkWidget *qck_create_tool_separator(GObject *object, const char *name)
{
    GtkWidget *result;                      /* Résultat à renvoyer         */

    result = GTK_WIDGET(gtk_separator_tool_item_new());

    if (G_IS_OBJECT(object) && name != NULL)
    {
        g_object_ref(G_OBJECT(result));
        g_object_set_data_full(object, name, result, (GDestroyNotify)g_object_unref);
    }

    gtk_widget_show(result);

	return result;

}






/******************************************************************************
*                                                                             *
*  Paramètres  : parent   = fenêtre parente pour la modalité d'affichage.     *
*                title    = titre de la boîte de dialogue.                    *
*                question = teneur de la question posée.                      *
*                                                                             *
*  Description : Affiche une boîte de dialogue offrant un choix "Oui/Non".    *
*                                                                             *
*  Retour      : Identifiant de la réponse choisie.                           *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/

gint qck_show_question(GtkWindow *parent, const char *title, const char *question)
{
    gint result;                            /* Choix arrêté à renvoyer     */
    GtkWidget *dialog;                      /* Boîte de dialogue affichée  */

    dialog = gtk_message_dialog_new(parent,
                                    GTK_DIALOG_DESTROY_WITH_PARENT,
                                    GTK_MESSAGE_QUESTION,
                                    GTK_BUTTONS_YES_NO,
                                    "%s", question);

    gtk_window_set_title(GTK_WINDOW(dialog), title);

    result = gtk_dialog_run(GTK_DIALOG(dialog));

    gtk_widget_destroy(dialog);

    return result;

}


/******************************************************************************
*                                                                             *
*  Paramètres  : menu   = menu GTK à placer à l'écran.                        *
*                x      = abscisse absolue du coin supérieur du menu. [OUT]   *
*                y      = ordonnée absolue du coin supérieur du menu. [OUT]   *
*                push   = indique les relations avec les bordures. [OUT]      *
*                widget = composant auquel le menu doit être attaché.         *
*                                                                             *
*  Description : Détermine la position d'un menu associé à un composant.      *
*                                                                             *
*  Retour      : -                                                            *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/

void attach_popup_menu_to_widget(GtkMenu *menu, gint *x, gint *y, gboolean *push, GtkWidget *widget)
{
    GtkTextDirection dir;                   /* Direction de l'affichage    */
    GtkAllocation alloc;                    /* Emplacement alloué          */
    GtkStyleContext *context;               /* Style associé pour le rendu */
    GtkStateFlags state;                    /* Etat courant du composant   */
    GtkBorder border;                       /* Bordure #1 à considérer     */
    GtkBorder padding;                      /* Bordure #2 à considérer     */
    GtkRequisition req;                     /* Taille requis               */

    *x = 0;
    *y = 0;

    dir = gtk_widget_get_direction(widget);

    /* Emplacement du composant */

    gtk_widget_get_allocation(widget, &alloc);

    if (!gtk_widget_get_has_window(widget))
    {
        *x += alloc.x;
        *y += alloc.y;
    }

    gdk_window_get_root_coords(gtk_widget_get_window(widget), *x, *y, x, y);

    /* Extension supplémentaire */

    context = gtk_widget_get_style_context(widget);
    state = gtk_style_context_get_state(context);

    gtk_style_context_get_border(context, state, &border);
    gtk_style_context_get_padding(context, state, &padding);

    if (dir == GTK_TEXT_DIR_RTL)
        *x += border.left + padding.left;
    else
        *x -= (border.left + padding.left);

    *y += border.top + padding.top;

    /* Sens de lecture */

    if (dir == GTK_TEXT_DIR_RTL)
    {
        gtk_widget_get_preferred_size(GTK_WIDGET(menu), NULL, &req);

        *x += alloc.width - req.width;

    }

    /* Finalisation... */

    *y += alloc.height;

    *push = TRUE;

}