/*
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_image.h"


static GtkIconSize scol_gtk_image_get_icon_size (int param)
{
    switch (param)
    {
         case ICON_SIZE_MENU :
            return GTK_ICON_SIZE_MENU;

        case ICON_SIZE_SMALL_TOOLBAR :
            return GTK_ICON_SIZE_SMALL_TOOLBAR;

        case ICON_SIZE_LARGE_TOOLBAR :
            return GTK_ICON_SIZE_LARGE_TOOLBAR;

        case ICON_SIZE_DND :
            return GTK_ICON_SIZE_DND;

        case ICON_SIZE_DIALOG :
            return GTK_ICON_SIZE_DIALOG;

        case ICON_SIZE_BUTTON :
            return GTK_ICON_SIZE_BUTTON;

        default :
            return GTK_ICON_SIZE_INVALID;
    }
}

void scol_gtk_image_new (GtkWidget *image, mmachine m, int data, int param, int flag, int set)
{
    GtkIconSize is;

    if (data == NIL)
        return;

    is = scol_gtk_image_get_icon_size (MTOI (param));
    switch (flag)
    {
        case (SCIMAGE_EMPTY) :
            image = gtk_image_new ();
            break;

        case (SCIMAGE_FILE) :
            if (set == 0)
                image = gtk_image_new_from_file (MMstartstr (m, MTOP (data)));
            else
                gtk_image_set_from_file (GTK_IMAGE (image), MMstartstr (m, MTOP (data)));
            break;

        case (SCIMAGE_PIX) :
            g_object_ref (gtk_image_get_pixbuf (GTK_IMAGE (image)));
            if (set ==0)
                image = gtk_image_new_from_pixbuf ((GdkPixbuf*) MMfetch (m, MTOP (data), OBJ2DGTK_PIX_HANDLE));
            else
                gtk_image_set_from_pixbuf (GTK_IMAGE (image), (GdkPixbuf*) MMfetch (m, MTOP (data), OBJ2DGTK_PIX_HANDLE));
            break;

        case (SCIMAGE_STOCK) :
            if (set == 0)
                image = gtk_image_new_from_stock (MMstartstr (m, MTOP (data)), is);
            else
                gtk_image_set_from_stock (GTK_IMAGE (image), MMstartstr (m, MTOP (data)), is);
            break;

        case (SCIMAGE_PIXANIM) :
            if (set == 0)
                image = gtk_image_new_from_animation ((GdkPixbufAnimation*) MMfetch (m, MTOP (data), OBJ2DGTK_PIX_HANDLE));
            else
                gtk_image_set_from_animation (GTK_IMAGE (image), (GdkPixbufAnimation*) MMfetch (m, MTOP (data), OBJ2DGTK_PIX_HANDLE));
            break;

        case (SCIMAGE_ICON) :
            if (set == 0)
                image = gtk_image_new_from_icon_name (MMstartstr (m, MTOP (data)), is);
            else
                gtk_image_set_from_icon_name (GTK_IMAGE (image), MMstartstr (m, MTOP (data)), is);
            break;

        default :
        ;
    }
    return;
}

static int scol_gtk_image_get_type (GtkImage *image)
{
    GtkImageType t;
    int r;

    t = gtk_image_get_storage_type (image);
    switch (t)
    {
        case (GTK_IMAGE_EMPTY) :
            r = SCIMAGE_EMPTY;
            break;

        case (GTK_IMAGE_PIXBUF) :
            r = SCIMAGE_PIX;
            break;

        case (GTK_IMAGE_STOCK) :
            r = SCIMAGE_STOCK;
            break;

        case (GTK_IMAGE_ANIMATION) :
            r = SCIMAGE_PIXANIM;
            break;

        case (GTK_IMAGE_ICON_NAME) :
            r = SCIMAGE_ICON;
            break;

        #ifdef SCOL_GTK_2
        case (GTK_IMAGE_PIXMAP) :   /* Obsolete GTK 3 */
        case (GTK_IMAGE_IMAGE) :    /* Obsolete GTK 3 */
        #endif
        case (GTK_IMAGE_ICON_SET) :
        case (GTK_IMAGE_GICON) :
        default :
            r = NIL;
    }
    return r;
}

/* Push the Scol pix object in a Scol image object. If the pix object is not existed, it will be created */
static void scol_gtk_image_push_scol_pix_object (GtkImage *image, mmachine m, int flag)
{
    GdkPixbuf *pix;
    GdkPixbufAnimation *apix;
    int exist;

    if (flag == SCIMAGE_PIX)
    {
        pix = gtk_image_get_pixbuf (image);
        if (pix == NULL)
        {
            MMpush (m, NIL);
            return;
        }
        exist = OBJfindTH (m, ObjGtkPixType, (int) pix);
        if (exist == -1)    /* pix not already created because not found in the current machine. So we create it ! */
        {
            MMpush (m, MMgetglobal (m, OFFSCCUR));  /*  set the current channel */
            SCOL_gtk_memory_createObjectTAB (m, pix, ObjGtkPixType, OBJ2DGTK_PIX_HANDLE);
            return;
        }
        MMpush (m, MMfetch (m, exist, OFFOBJMAG));
        return;
    }
    else if (flag == SCIMAGE_PIXANIM)
    {
        apix = gtk_image_get_animation (image);
        if (apix == NULL)
        {
            MMpush (m, NIL);
            return;
        }
        exist = OBJfindTH (m, ObjGtkPixType, (int) apix);
        if (exist == -1)    /* apix not already created because not found in the current machine. So we create it ! */
        {
            MMpush (m, MMgetglobal (m, OFFSCCUR));  /*  set the current channel */
            SCOL_gtk_memory_createObjectTAB (m, apix, ObjGtkPixType, OBJ2DGTK_PIX_HANDLE);
            return;
        }
        MMpush (m, MMfetch (m, exist, OFFOBJMAG));
        return;
    }

    MMpush (m, NIL);
    return;
}

static void scol_gtk_image_push_scol_string_and_size (GtkImage *image, mmachine m, int flag)
{
    gchar *s = NULL; /* don't free it after use ! */
    GtkIconSize is = GTK_ICON_SIZE_INVALID;

    if (flag == SCIMAGE_STOCK)
        gtk_image_get_stock (image, &s, &is);
    else if (flag == SCIMAGE_ICON)
        gtk_image_get_icon_name (image, (const gchar **) &s, &is);

    if (s != NULL)
        Mpushstrbloc (m, s);
    else
        MMpush (m, NIL);

    switch (is)
    {
        case (GTK_ICON_SIZE_MENU) :
            MMpush (m, ITOM (ICON_SIZE_MENU));
            break;
        case (GTK_ICON_SIZE_SMALL_TOOLBAR) :
            MMpush (m, ITOM (ICON_SIZE_SMALL_TOOLBAR));
            break;
        case (GTK_ICON_SIZE_LARGE_TOOLBAR) :
            MMpush (m, ITOM (ICON_SIZE_LARGE_TOOLBAR));
            break;
        case (GTK_ICON_SIZE_BUTTON) :
            MMpush (m, ITOM (ICON_SIZE_BUTTON));
            break;
        case (GTK_ICON_SIZE_DND) :
            MMpush (m, ITOM (ICON_SIZE_DND));
            break;
        case (GTK_ICON_SIZE_DIALOG) :
            MMpush (m, ITOM (ICON_SIZE_DIALOG));
            break;
        case (GTK_ICON_SIZE_INVALID) :
        default:
            MMpush (m, NIL);
    }
    return;
}






/*                                                                            *
 *                                                                            *
 *    SCOL API                                                                *
 *                                                                            *
 *                                                                            *
 *                                                                            */

/**
 * \brief _gtkImageNew : Createsa new image object
 * fun [Chn I u0 u1] ObjGtkWidget
 * \param Chn : a channel
 * \param I : a flag : SCOL_IMAGE_EMPTY, SCOL_IMAGE_FILE (from an image file), SCOL_IMAGE_PIX (from a pix object), SCOL_IMAGE_PIXANIM (from an animated pix object), SCOL_IMAGE_STOCK (from a stock item) or SCOL_IMAGE_ICON (from the current icon theme)
 * \param u0 : if flag is SCOL_IMAGE_ICON, SCOL_IMAGE_FILE or SCOL_IMAGE_STOCK, param is a string (S). If flag is SCOL_IMAGE_PIX or SCOL_IMAGE_PIXANIM, param is a pix object (ObjGtkPix). Otherwise, can be nil.
 * \param u1 : if flag is SCOL_IMAGE_ICON or SCOL_IMAGE_STOCK, param is a string (I). Otherwise, can be nil.
 * \return ObjGtkWidget : a new image object or nil if error
 *
 * Internally, the image Scol object is a GtkEventBox, not a GtkImage ! Be careful !
 */
int SCOL_gtkImageNew (mmachine m)
{
    int mchannel, mflag, mdata, mparam;
    GtkWidget *image = NULL;
    GtkWidget *event_box;

    g_message ("SCOL_gtkImageNew : entering");

    mparam = MMpull (m);
    mdata = MMpull (m);
    mflag = MTOI (MMpull (m));
    mchannel = MMget (m, 0);
    if (mchannel == NIL)
    {
        g_warning ("SCOL_gtkImageNew error : channel is nil");
        MMpull (m);
        MMpush (m, NIL);
        return 0;
    }

    scol_gtk_image_new (image, m, mdata, mparam, mflag, 0);
    /*if (image == NULL)
        return MMpush (m, NIL);*/

    event_box = gtk_event_box_new ();
    gtk_container_add (GTK_CONTAINER (event_box), image);
    return SCOL_gtk_memory_createObjectTAB (m, event_box, ObjGtkWidgetType, OBJ2DGTK_WIDGET_HANDLE);
}

/**
 * \brief _gtkImageSet : Modify the content of an image object
 * fun [ObjGtkWidget I u0 u1] ObjGtkWidget
 * \param ObjGtkWidget : a channel
 * \param I : a flag : SCOL_IMAGE_EMPTY, SCOL_IMAGE_FILE (from an image file), SCOL_IMAGE_PIX (from a pix object), SCOL_IMAGE_PIXANIM (from an animated pix object), SCOL_IMAGE_STOCK (from a stock item) or SCOL_IMAGE_ICON (from the current icon theme)
 * \param u0 : if flag is SCOL_IMAGE_ICON, SCOL_IMAGE_FILE or SCOL_IMAGE_STOCK, param is a string (S). If flag is SCOL_IMAGE_PIX or SCOL_IMAGE_PIXANIM, param is a pix object (ObjGtkPix). Otherwise, can be nil.
 * \param u1 : if flag is SCOL_IMAGE_ICON or SCOL_IMAGE_STOCK, param is a string (I). Otherwise, can be nil.
 * \return ObjGtkWidget : a new image object or nil if error
 */
int SCOL_gtkImageSet (mmachine m)
{
    int mimage, mflag, mdata, mparam;
    GtkWidget *image = NULL;
    GtkWidget *event_box;

    g_message ("SCOL_gtkImageSet : entering");

    mparam = MMpull (m);
    mdata = MMpull (m);
    mflag = MTOI (MMpull (m));
    /*mimage = MMget (m, 0);*/
    mimage = MMpull (m);
    if (mimage == NIL)
    {
        g_warning ("SCOL_gtkImageSet error : object is nil");
        /*MMpull (m);*/
        MMpush (m, NIL);
        return 0;
    }

    event_box = (GtkWidget*) MMfetch (m, MTOP (mimage), OBJ2DGTK_WIDGET_HANDLE);
    image = gtk_bin_get_child (GTK_BIN (event_box));
    scol_gtk_image_new (image, m, mdata, mparam, mflag, 1);
    if (image == NULL)
    {
        g_warning ("SCOL_gtkImageSet error : image is nil");
        /*MMset (m, 0, NIL);*/
    }
    MMpush (m, mimage);
    return 0;
}

/**
 * \brief _gtkImageRst : reset the content of an image object.
 * fun [ObjGtkWidget] ObjGtkWidget
 * \param ObjGtkWidget : an image object
 * \return : the same object or nil if error
 */
int SCOL_gtkImageRst (mmachine m)
{
    int mimage;
    GtkWidget *image;
    GtkWidget *event_box;

    g_message ("SCOL_gtkImageRst : entering");

    mimage = MMpull (m);
    if (mimage == NIL)
    {
        g_warning ("SCOL_gtkImageRst error : object is nil");
        MMpush (m, NIL);
        return 0;
    }

    event_box = (GtkWidget*) MMfetch (m, MTOP (mimage), OBJ2DGTK_WIDGET_HANDLE);
    image = gtk_bin_get_child (GTK_BIN (event_box));
    gtk_image_clear (GTK_IMAGE (image));
    MMpush (m, mimage);
    return 0;
}

/**
 * \brief _gtkImageGetType : Returns the type of an image object
 * fun [ObjGtkWidget] I
 * \param ObjGtkWidget : an image object
 * \return : the type or nil if eror or unknown
 */
int SCOL_gtkImageGetType (mmachine m)
{
    int mimage;
    int t;
    GtkWidget *image;
    GtkWidget *event_box;

    g_message ("SCOL_gtkImageGetType : entering");

    mimage = MMpull (m);
    if (mimage == NIL)
    {
        g_warning ("SCOL_gtkImageGetType error : object is nil");
        MMpush (m, NIL);
        return 0;
    }
    event_box = (GtkWidget*) MMfetch (m, MTOP (mimage), OBJ2DGTK_WIDGET_HANDLE);
    image = gtk_bin_get_child (GTK_BIN (event_box));
    t = scol_gtk_image_get_type (GTK_IMAGE (image));
    MMpush (m, ITOM (t));
    return 0;
}

/**
 * \brief _gtkImageGetContent : returns the content of an image object
 * fun [ObjGtkWidget] [ObjGtkPix S I]
 * \param ObjGtkWidget : any image object
 * \return [ObjGtkPix S I] : a pix object or the name of the icon : stock item and the size
 */
int SCOL_gtkImageGetContent (mmachine m)
{
    int mimage;
    int t;
    GtkWidget *image;
    GtkWidget *event_box;

    g_message ("SCOL_gtkImageGetContent : entering");

    mimage = MMpull (m);
    if (mimage == NIL)
    {
        g_warning ("SCOL_gtkImageGetContent error : object is nil");
        MMpush (m, NIL);
        return 0;
    }
    event_box = (GtkWidget*) MMfetch (m, MTOP (mimage), OBJ2DGTK_WIDGET_HANDLE);
    image = gtk_bin_get_child (GTK_BIN (event_box));
    t = scol_gtk_image_get_type (GTK_IMAGE (image));
    switch (t)
    {
        case (SCIMAGE_PIX) :
        case (SCIMAGE_PIXANIM) :
            scol_gtk_image_push_scol_pix_object (GTK_IMAGE (image), m, t);
            MMpush (m, NIL);
            MMpush (m, NIL);
            break;

        case (SCIMAGE_ICON) :
        case (SCIMAGE_STOCK) :
            MMpush (m, NIL);
            scol_gtk_image_push_scol_string_and_size (GTK_IMAGE (image), m, t);
            break;

        default:
            MMpush (m, NIL);
            MMpush (m, NIL);
            MMpush (m, NIL);
    }
    MMpush (m, ITOM (3));
    MBdeftab (m);
    return 0;
}



/* FLAGS */
int SCOL_IMAGE_EMPTY (mmachine m) { MMpush (m, ITOM (SCIMAGE_EMPTY)); return 0; }
int SCOL_IMAGE_FILE (mmachine m) { MMpush (m, ITOM (SCIMAGE_FILE)); return 0; }
int SCOL_IMAGE_PIX (mmachine m) { MMpush (m, ITOM (SCIMAGE_PIX)); return 0; }
int SCOL_IMAGE_STOCK (mmachine m) { MMpush (m, ITOM (SCIMAGE_STOCK)); return 0; }
int SCOL_IMAGE_PIXANIM (mmachine m) { MMpush (m, ITOM (SCIMAGE_PIXANIM)); return 0; }
int SCOL_IMAGE_ICON (mmachine m) { MMpush (m, ITOM (SCIMAGE_ICON)); return 0; }

/* API definitions */
char* gtk_img_name[GTK_IMAGE_PKG_NB]=
{
    "SCOL_IMAGE_EMPTY", "SCOL_IMAGE_FILE", "SCOL_IMAGE_PIX",
    "SCOL_IMAGE_STOCK", "SCOL_IMAGE_PIXANIM", "SCOL_IMAGE_ICON",

    "_gtkImageNew",
    "_gtkImageSet",
    "_gtkImageRst",
    "_gtkImageGetType",
    "_gtkImageGetContent"
};

int (*gtk_img_fun[GTK_IMAGE_PKG_NB])(mmachine m)=
{
    SCOL_IMAGE_EMPTY, SCOL_IMAGE_FILE, SCOL_IMAGE_PIX,
    SCOL_IMAGE_STOCK, SCOL_IMAGE_PIXANIM, SCOL_IMAGE_ICON,

    SCOL_gtkImageNew,
    SCOL_gtkImageSet,
    SCOL_gtkImageRst,
    SCOL_gtkImageGetType,
    SCOL_gtkImageGetContent
};

int gtk_img_narg[GTK_IMAGE_PKG_NB]=
{
    0, 0, 0,
    0, 0, 0,

    4,              /* SCOL_gtkImageNew */
    4,              /* SCOL_gtkImageSet */
    1,              /* SCOL_gtkImageRst */
    1,               /* SCOL_gtkImageGetType */
    1              /* SCOL_gtkImageGetContent */
};

char* gtk_img_type[GTK_IMAGE_PKG_NB]=
{
    "fun [] I", "fun [] I", "fun [] I",
    "fun [] I", "fun [] I", "fun [] I",

    "fun [Chn I u0 u1] ObjGtkWidget",                           /* SCOL_gtkImageNew */
    "fun [ObjGtkWidget I u0 u1] ObjGtkWidget",                  /* SCOL_gtkImageSet */
    "fun [ObjGtkWidget] ObjGtkWidget",                          /* SCOL_gtkImageRst */
    "fun [ObjGtkWidget] I",                                      /* _gtkImageGetType */
    "fun [ObjGtkWidget] [ObjGtkPix S I]"                         /* SCOL_gtkImageGetContent */
};

int SCOLloadGTKimage (mmachine m)
{
    int k;

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

    k = PKhardpak (m, "GTK2DimageEngine", GTK_IMAGE_PKG_NB, gtk_img_name, gtk_img_fun, gtk_img_narg, gtk_img_type);
    return k;
}

