/*
This source file is part of Scol
For the latest info, see http://www.scolring.org

Copyright (c) 2010 Stephane Bisaro, aka Iri <iri@irizone.net>

This program is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any later
version.

This program 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 Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public License along with
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
Place - Suite 330, Boston, MA 02111-1307, USA, or go to
http://www.gnu.org/copyleft/lesser.txt

For others informations, please contact us from http://www.scolring.org/
*/


#include "../include/scol_gtk_dialog.h"


/**
    This function is a hack
    See https://bugzilla.gnome.org/show_bug.cgi?id=609886

    [French]
    Il est impératif de rester dans la partition active lors de la navigation
    dans une boite de dialogue de fichiers.
    En attendant que cela soit nativement géré par GTK+, ce hack empêche
    l'utilisateur d'aller voir là où il n'a pas à voir ... !
    1- Lors de la construction du dialog, le signal "current-folder-changed" :
    g_signal_connect (dialog, "current-folder-changed", G_CALLBACK (scol_gtkDialogFileChooserNewCBfolderChanged), NULL);
    2- Ce signal est émis à chaque fois que l'utilisateur change de dossier.
    On vérifie alors la filiation entre le dossier courant choisi par l'utilisateur
    et le dossier racine de la partition active.
    Il existe plusieurs méthodes pour ça, j'ai choisi une fonction de la GLib :
    "g_file_has_prefix".
    Si la filiation est confirmée, on continue. Dans le cas contraire, on replace la
    sélection au niveau de la racine de la partition active.
*/
void scol_gtkDialogFileChooserNewCBfolderChanged (GtkFileChooser *dialog, gpointer ud)
{
    GFile *file, *fpack;
    gchar *uri;

    file = gtk_file_chooser_get_current_folder_file (dialog);
    if (!file)
        return;
    fpack = g_file_new_for_path (Firstpack->path);
    if (!fpack)
        return;

    if (!(g_file_has_prefix (file, fpack)))
    {
        uri = g_strconcat (Firstpack->path, "logo.bmp", NULL);
        gtk_file_chooser_select_filename (GTK_FILE_CHOOSER (dialog), uri);
        g_free (uri);
    }

    g_object_unref (file);
    g_object_unref (fpack);
    return;
}

void scol_gtk_dialog_cb_file_response (GtkWidget *dialog, mmachine m)
{
    int cb, len;
    char *filename, *pf;

    cb = OBJbeginreflex (m, ObjGtkWidgetType, (int) dialog, OBJ2DGTK_DIALOG_CB_FILE_RESPONSE);
    if (cb)
    {
        g_message ("scol_gtk_dialog_cb_file_response error : no callback defined ! errcode = %d", cb);
        return;
    }

    filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
    /* No selectded file */
    if (filename == NULL)
    {
        gtk_widget_destroy (dialog);
        OBJdelTH (m, ObjGtkWidgetType, (int) dialog);
        return;
    }
    else
    {
        /* char name[SIZESIGN];
        if (!SPfindfile ((packdir) SCgetExtra("FirstPack"), pf, NULL, name))*/

        len = strlen (filename);
        pf = (char *) g_malloc (sizeof (char) * len);
        memmove (pf, filename + strlen (Firstpack->path), len);
        pf[len] = '\0';
        pf = g_strdelimit (pf, "\\", '/');  /* Here strip invalid chars */
        g_strdelimit (filename, "\\", '/');
        g_strdelimit (Firstpack->path, "\\", '/');
        if (g_str_has_prefix (filename, Firstpack->path))
            Mpushstrbloc (m, pf);
        else
            MMpush (m, NIL);
        g_free (filename);
        g_free (pf);

        OBJcallreflex (m, 1);

        gtk_widget_destroy (GTK_WIDGET (dialog));
        OBJdelTH (m, ObjGtkWidgetType, (int) dialog);
        return;
    }
}


/**
 * \brief Create a file chooser dialog box
 *
 * Open or Save a file, Create or Select a folder
 *
 * \param filters : [[S S] r1] : filter, name (example : ["*.png" "Images PNG"] :: ["scol*" "File begins scol"] ::: nil)
 * \param action : I : SCOL_GTK_ACTION_OPEN, SCOL_GTK_ACTION_SAVE, SCOL_GTK_ACTION_SELECT_FOLDER, SCOL_GTK_ACTION_CREATE_FOLDER
 * \param file : P : initial selection (by default). Can be nil.
 * \param title : S : title of the dialog box
 * \param parent : ObjGtkWidget : parent :typically a window
 * \param channel : Chn : the channel
 * \return ObjGtkWidget : the new dialog box
 */
int SCOL_gtkDialogFileChooserNew (mmachine m)
{
    int mchannel, mparent, mtitle, mfile, maction, mfilters, mfun, mup;
    int len, result_run;
    GtkFileChooserAction action;
    gchar *title, *file;
    const gchar *button;
    GtkWidget *dialog, *parent;
    GtkFileFilter *filter;

    g_message ("SCOL_gtkDialogFileChooserNew : entering");

    mup = MMpull (m);
    mfun = MMpull (m);
    mfilters = MTOP (MMpull (m));
    maction = MTOI (MMpull (m));
    mfile = MTOP (MMpull (m));
    mtitle = MTOP (MMpull (m));
    mparent = MTOP (MMpull (m));
    mchannel = MMget (m, 0);

    if (mchannel == NIL)
    {
        g_warning ("SCOL_gtkDialogFileChooserNew error : channel is nil");
        MMpull (m);
        MMpush (m, NIL);
        return 0;
    }

    switch (maction)
    {
        case (ACTION_OPEN) :
            action = GTK_FILE_CHOOSER_ACTION_OPEN;
            button = GTK_STOCK_OPEN;
            break;

        case (ACTION_SAVE) :
            action = GTK_FILE_CHOOSER_ACTION_SAVE;
            button = GTK_STOCK_SAVE;
            break;

        case (ACTION_SELECT_FOLDER) :
            action = GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER;
            button = GTK_STOCK_OK;
            break;

        case (ACTION_CREATE_FOLDER) :
            action = GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER;
            button = GTK_STOCK_OK;
            break;

        default :
            g_warning ("SCOL_gtkDialogFileChooserNew error : bad action !");
            MMpull (m);
            MMpush (m, NIL);
            return 0;
    }

    if (mtitle == NIL)
    {
        len = 1 + strlen (DEFAULT_STRING);
        title = (gchar *) g_malloc (sizeof (gchar) * len);
        if (title == NULL)
        {
            MMpull (m);
            g_error ("SCOL_gtkDialogFileChooserNew : not enough memory");
        }
        strcpy (title, (gchar *) DEFAULT_STRING);
    }
    else
    {
        len = 1 + MMsizestr (m, mtitle);
        title = (gchar *) g_malloc (sizeof (gchar) * len);
        if (title == NULL)
        {
            MMpull (m);
            g_error ("SCOL_gtkDialogFileChooserNew : not enough memory");
        }
        strcpy (title, (gchar *) MMstartstr (m, mtitle));
    }
    title[len] = '\0';
    title = SCOLUTF8 (title);

    if (mparent == NIL)
        parent = NULL;
    else
        parent = (GtkWidget *) MMfetch (m, mparent, OBJ2DGTK_WIDGET_HANDLE);
    dialog = gtk_file_chooser_dialog_new (title, GTK_WINDOW (parent), action, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, button, GTK_RESPONSE_ACCEPT, NULL);

    if (mfile == NIL)
        file = g_strconcat (Firstpack->path, NULL);
    else
        file = g_strconcat (Firstpack->path, MMstartstr (m, mfile), NULL);

    if (mfilters == NIL)
    {
        filter = gtk_file_filter_new ();
        gtk_file_filter_add_pattern (filter, "*");
        gtk_file_filter_set_name (filter, "All");
        gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
    }
    else
    {
        while (mfilters !=NIL)
        {
            int f, typ;

            f = MTOP (MMfetch (m, mfilters, 0));
            if (f != NIL)
            {
                filter = gtk_file_filter_new ();
                typ = MMfetch (m, f, 0);
                if (typ == 1)
                    gtk_file_filter_add_mime_type (filter, MMstartstr (m, MTOP (MMfetch (m, f, 1))));
                else if (typ == 2)
                    gtk_file_filter_add_pixbuf_formats (filter);
                else
                    gtk_file_filter_add_pattern (filter, MMstartstr (m, MTOP (MMfetch (m, f, 1))));
                gtk_file_filter_set_name (filter, MMstartstr (m, MTOP (MMfetch (m, f, 2))));
                gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
            }
            mfilters = MTOP (MMfetch (m, mfilters, 1));
        }
    }

    gtk_file_chooser_set_local_only (GTK_FILE_CHOOSER (dialog), TRUE);

    g_signal_connect (dialog, "current-folder-changed", G_CALLBACK (scol_gtkDialogFileChooserNewCBfolderChanged), NULL);
    /*gtk_dialog_run (GTK_DIALOG (dialog));*/
    gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), SCOLUTF8 (file));

    g_free (title);
    g_free (file);

    SCOL_gtk_memory_createObjectTAB (m, dialog, ObjGtkWidgetType, OBJ2DGTK_WIDGET_HANDLE);
    MMpush (m, mfun);
    MMpush (m, mup);
    OBJaddreflex (m, ObjGtkWidgetType, OBJ2DGTK_DIALOG_CB_FILE_RESPONSE);

    result_run = gtk_dialog_run (GTK_DIALOG (dialog));
    switch (result_run)
    {
        case (GTK_RESPONSE_CANCEL) :
        case (GTK_RESPONSE_DELETE_EVENT) :
            gtk_widget_destroy (GTK_WIDGET (dialog));
            OBJdelTH (m, ObjGtkWidgetType, (int) dialog);
            break;
        default :
            scol_gtk_dialog_cb_file_response (dialog, m);
    }

    return 0; /*SCOL_gtk_memory_createObjectTAB (m, dialog, ObjGtkWidgetType, OBJ2DGTK_WIDGET_HANDLE);*/
}


/* Flags */
int SCOL_GTK_ACTION_OPEN (mmachine m) { MMpush (m, ITOM (ACTION_OPEN)); return 0; }
int SCOL_GTK_ACTION_SAVE (mmachine m) { MMpush (m, ITOM (ACTION_SAVE)); return 0; }
int SCOL_GTK_ACTION_SELECT_FOLDER (mmachine m) { MMpush (m, ITOM (ACTION_SELECT_FOLDER)); return 0; }
int SCOL_GTK_ACTION_CREATE_FOLDER (mmachine m) { MMpush (m, ITOM (ACTION_CREATE_FOLDER)); return 0; }

int SCOL_GTK_DIALOG_FILTER_PATTERN (mmachine m) { MMpush (m, ITOM (0)); return 0; }
int SCOL_GTK_DIALOG_FILTER_MIMETYPE (mmachine m) { MMpush (m, ITOM (1)); return 0; }
int SCOL_GTK_DIALOG_FILTER_IMAGE (mmachine m) { MMpush (m, ITOM (2)); return 0; }







/* API définitions : */

char* gtk_dlg_name[GTK_DIALOG_PKG_NB]=
{
    "SCOL_GTK_ACTION_OPEN", "SCOL_GTK_ACTION_SAVE", "SCOL_GTK_ACTION_SELECT_FOLDER",
    "SCOL_GTK_ACTION_CREATE_FOLDER",

    "SCOL_GTK_DIALOG_FILTER_PATTERN", "SCOL_GTK_DIALOG_FILTER_MIMETYPE", "SCOL_GTK_DIALOG_FILTER_IMAGE",

    "_gtkDialogFileChooserNew"
};

int (*gtk_dlg_fun[GTK_DIALOG_PKG_NB])(mmachine m)=
{
    SCOL_GTK_ACTION_OPEN, SCOL_GTK_ACTION_SAVE, SCOL_GTK_ACTION_SELECT_FOLDER,
    SCOL_GTK_ACTION_CREATE_FOLDER,

    SCOL_GTK_DIALOG_FILTER_PATTERN, SCOL_GTK_DIALOG_FILTER_MIMETYPE, SCOL_GTK_DIALOG_FILTER_IMAGE,

    SCOL_gtkDialogFileChooserNew
};

int gtk_dlg_narg[GTK_DIALOG_PKG_NB]=
{
    0, 0, 0,
    0,

    0, 0, 0,

    8
};

char* gtk_dlg_type[GTK_DIALOG_PKG_NB]=
{
    "fun [] I", "fun [] I", "fun [] I",
    "fun [] I",

    "fun [] I", "fun [] I", "fun [] I",

    "fun [Chn ObjGtkWidget S S I [[I S S] r1] fun [ObjGtkWidget u0 S] u1 u0] ObjGtkWidget"
};

int SCOLloadGTKdialog (mmachine m)
{
    int k;

    MMechostr (0, "SCOLloadGTKdialog : entering\n");

    k = PKhardpak (m, "GTK2DdialogEngine", GTK_DIALOG_PKG_NB, gtk_dlg_name, gtk_dlg_fun, gtk_dlg_narg, gtk_dlg_type);
    return k;
}


