/*
 *  xfce-icontheme - a themed icon lookup class
 *
 *  Copyright (c) 2004 Brian Tarricone <bjt23@cornell.edu>
 *
 * This library 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 library 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 library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 */

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include <libxfcegui4/libxfcegui4.h>

#include "icons.h"
#include "xfce-icontheme.h"

#define XFCE_ICON_THEME_GET_PRIVATE(o)    (G_TYPE_INSTANCE_GET_PRIVATE ((o), XFCE_TYPE_ICON_THEME, XfceIconThemePriv))

struct _XfceIconThemePriv
{
    GtkIconTheme *icon_theme;
};

enum {
    XFCEIC_SIG_CHANGED,
    XFCEIC_N_SIGNALS
};

static void xfce_icon_theme_class_init(XfceIconThemeClass *klass);
static void xfce_icon_theme_init(XfceIconTheme *icon_theme);
static void xfce_icon_theme_finalize(GObject *object);

static guint icon_theme_signals[XFCEIC_N_SIGNALS] = { 0 };
static GObjectClass *parent_class = NULL;

static void
xfce_icon_theme_changed_cb(GtkIconTheme *gtk_icon_theme,
                           XfceIconTheme *xfce_icon_theme)
{
    g_signal_emit(G_OBJECT(xfce_icon_theme),
                  icon_theme_signals[XFCEIC_SIG_CHANGED], 0);
}

GType
xfce_icon_theme_get_type()
{
    static GType icon_theme_type = 0;
    
    if(!icon_theme_type) {
        static const GTypeInfo icon_theme_info = {
            sizeof(XfceIconThemeClass),
            NULL,    /* base_init */
            NULL,    /* base_finalize */
            (GClassInitFunc)xfce_icon_theme_class_init,
            NULL,    /* class_finalize */
            NULL,    /* class_data */
            sizeof(XfceIconTheme),
            0,    /* n_preallocs */
            (GInstanceInitFunc)xfce_icon_theme_init,
            NULL    /* value_table */
        };
        
        icon_theme_type = g_type_register_static(G_TYPE_OBJECT,
                "XfceIconTheme", &icon_theme_info, 0);
    }
    
    return icon_theme_type;
}

static void
xfce_icon_theme_class_init(XfceIconThemeClass *klass)
{
    GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
    
    g_type_class_add_private (klass, sizeof (XfceIconThemePriv));
        
    parent_class = g_type_class_peek_parent(klass);
    
    gobject_class->finalize = xfce_icon_theme_finalize;
    
/**
 * XfceIconTheme::changed
 * @icon_theme: the icon theme
 * 
 * Emitted when the current icon theme is switched or GTK+ detects that a change
 * has occurred in the contents of the current icon theme.
 *
 * Since 4.1
 **/
    icon_theme_signals[XFCEIC_SIG_CHANGED] = g_signal_new("changed",
        G_TYPE_FROM_CLASS(klass), G_SIGNAL_RUN_LAST,
        G_STRUCT_OFFSET(XfceIconThemeClass, changed), NULL, NULL,
        g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
}

static void
xfce_icon_theme_init(XfceIconTheme *icon_theme)
{
    icon_theme->priv = XFCE_ICON_THEME_GET_PRIVATE (icon_theme);
}


static void
xfce_icon_theme_finalize(GObject *object)
{
    XfceIconTheme *icon_theme = XFCE_ICON_THEME(object);
    
    g_signal_handlers_disconnect_by_func(G_OBJECT(icon_theme->priv->icon_theme),
                                         G_CALLBACK(xfce_icon_theme_changed_cb),
                                         icon_theme);
    
    G_OBJECT_CLASS(parent_class)->finalize(object);
}

/**
 * xfce_icon_theme_get_for_screen:
 * @screen: A #GdkScreen, or %NULL.
 *
 * Retrieves the icon theme for the specified GdkScreen (or %NULL for the
 * default screen), creating it if necessary.
 *
 * Since 4.1
 *
 * Return value: A new #XfceIconTheme.
 **/
XfceIconTheme *
xfce_icon_theme_get_for_screen(GdkScreen *screen)
{
    XfceIconTheme *icon_theme = g_object_new(XFCE_TYPE_ICON_THEME, NULL);
    
    if(GDK_IS_SCREEN(screen))
        icon_theme->priv->icon_theme = gtk_icon_theme_get_for_screen(screen);
    else
        icon_theme->priv->icon_theme = gtk_icon_theme_get_default();
    
    g_signal_connect(G_OBJECT(icon_theme->priv->icon_theme), "changed",
                     G_CALLBACK(xfce_icon_theme_changed_cb), icon_theme);
    
    return icon_theme;
}

/**
 * xfce_icon_theme_lookup:
 * @icon_theme: An #XfceIconTheme.
 * @icon_name: The name of an icon to look up.
 * @icon_size: The preferred icon size.
 *
 * Tries to find @icon_name in the current theme.  This function may return
 * a filename of a size different than that requested in @icon_size, if a
 * scalable icon is found.
 *
 * Since 4.1
 *
 * Return value: A filename (free with g_free() when done), or %NULL if no
 *               suitable icon could be found.
 **/
gchar *
xfce_icon_theme_lookup(XfceIconTheme *icon_theme, const gchar *icon_name,
        gint icon_size)
{
    return xfce_themed_icon_lookup(icon_name, icon_size);
}

/**
 * xfce_icon_theme_lookup_list:
 * @icon_theme: An #XfceIconTheme.
 * @icon_names: A list of names of icons to look up, in order of preference.
 * @icon_size: The preferred icon size.
 *
 * Tries to find one of @icon_names in the current theme.  This function may
 * return a filename of a size different than that requested in @icon_size, if a
 * scalable icon is found.
 *
 * Since 4.1
 *
 * Return value: A filename (free with g_free() when done), or %NULL if no
 *               suitable icon could be found.
 **/
gchar *
xfce_icon_theme_lookup_list(XfceIconTheme *icon_theme, GList *icon_names,
        gint icon_size)
{
    return xfce_themed_icon_lookup_list(icon_names, icon_size);
}

/**
 * xfce_icon_theme_lookup_category:
 * @icon_theme: An #XfceIconTheme.
 * @category: The type of icon to look up.
 * @icon_size: The preferred icon size.
 *
 * Tries to find an icon of type @category in the current theme.  This function
 * may return a filename of a size different than that requested in @icon_size,
 * if a scalable icon is found.  The @category can be a builtin
 * #XfceIconThemeCategory, or a custom category registered with
 * xfce_icon_theme_register_category().
 *
 * Since 4.1
 *
 * Return value: A filename (free with g_free() when done), or %NULL if no
 *               suitable icon could be found.
 **/
gchar *
xfce_icon_theme_lookup_category(XfceIconTheme *icon_theme,
        XfceIconThemeCategory category, gint icon_size)
{
    return xfce_themed_icon_lookup_category(category, icon_size);
}

/**
 * xfce_icon_theme_load:
 * @icon_theme: An #XfceIconTheme.
 * @icon_name: The name of an icon to look up.
 * @icon_size: The preferred icon size.
 *
 * Tries to find @icon_name in the current theme.  If a suitable icon can be
 * found, this function will always return an icon of the specified @icon_size,
 * even if it requires scaling to do so.
 *
 * Since 4.1
 *
 * Return value: A new #GdkPixbuf (free with g_object_unref() when done), or
 *               %NULL if no suitable icon could be found.
 **/
GdkPixbuf *
xfce_icon_theme_load(XfceIconTheme *icon_theme, const gchar *icon_name,
        gint icon_size)
{
    return xfce_themed_icon_load(icon_name, icon_size);
}

/**
 * xfce_icon_theme_load_list:
 * @icon_theme: An #XfceIconTheme.
 * @icon_names: The names of icons to look up.
 * @icon_size: The preferred icon size.
 *
 * Tries to find one of @icon_names in the current theme.  If a suitable icon
 * can be found, this function will always return an icon of the specified
 * @icon_size, even if it requires scaling to do so.
 *
 * Since 4.1
 *
 * Return value: A new #GdkPixbuf (free with g_object_unref() when done), or
 *               %NULL if no suitable icon could be found.
 **/
GdkPixbuf *
xfce_icon_theme_load_list(XfceIconTheme *icon_theme, GList *icon_names,
        gint icon_size)
{
    return xfce_themed_icon_load_list(icon_names, icon_size);
}

/**
 * xfce_icon_theme_load_category:
 * @icon_theme: An #XfceIconTheme.
 * @category: The type of icon to look up.
 * @icon_size: The preferred icon size.
 *
 * Tries to find an icon of type @category in the current theme.  If a suitable
 * icon can be found, this function will always return an icon of the specified
 * @icon_size, even if it requires scaling to do so.  The @category can be a
 * builtin #XfceIconThemeCategory, or a custom category registered with
 * xfce_icon_theme_register_category().
 *
 * Since 4.1
 *
 * Return value: A new #GdkPixbuf (free with g_object_unref() when done), or
 *               %NULL if no suitable icon could be found.
 **/
GdkPixbuf *
xfce_icon_theme_load_category(XfceIconTheme *icon_theme,
        XfceIconThemeCategory category, gint icon_size)
{
    return xfce_themed_icon_load_category(category, icon_size);
}

/**
 * xfce_icon_theme_get_search_path:
 * @icon_theme: An #XfceIconTheme.
 *
 * Retrieves the current icon search path.
 *
 * Since 4.1
 *
 * Return value: A GList of search paths.  Free with g_list_free() when done.
 **/
GList *
xfce_icon_theme_get_search_path(XfceIconTheme *icon_theme)
{
    GList *new_list = NULL;
    gchar **path = NULL;
    gint n_elements = 0, i;
    
    g_return_val_if_fail(XFCE_IS_ICON_THEME(icon_theme), NULL);
    
    gtk_icon_theme_get_search_path(icon_theme->priv->icon_theme, &path,
                                   &n_elements);
    
    for(i = 0; i < n_elements; ++i)
        new_list = g_list_prepend(new_list, path[i]);
    
    g_free(path);
    
    return g_list_reverse(new_list);
}

/**
 * xfce_icon_theme_set_search_path:
 * @icon_theme: An #XfceIconTheme.
 * @search_paths: A GList of path names, each one terminated with '/'.
 *
 * Sets the current search path to the list of @search_paths.  Note that this
 * will discard any currently-set search path.
 *
 * Since 4.1
 **/
void
xfce_icon_theme_set_search_path(XfceIconTheme *icon_theme, GList *search_paths)
{
    gchar **path = NULL;
    gint i, n_elements;
    
    g_return_if_fail(XFCE_IS_ICON_THEME(icon_theme));
    
    n_elements = g_list_length(search_paths);
    
    path = g_new(gchar *,  n_elements + 1);
    for(i = 0; i < n_elements; ++i)
        path[i] = g_list_nth_data(search_paths, i);
    path[n_elements] = NULL;
    
    gtk_icon_theme_set_search_path(icon_theme->priv->icon_theme,
                                   (const char **)path, n_elements);
    
    g_strfreev(path);
}

/**
 * xfce_icon_theme_prepend_search_path:
 * @icon_theme: An #XfceIconTheme.
 * @search_path: A pathname, terminated with '/'.
 *
 * Prepends @search_path to the current icon theme search path.
 *
 * Since 4.1
 **/
void
xfce_icon_theme_prepend_search_path(XfceIconTheme *icon_theme,
        const gchar *search_path)
{
    g_return_if_fail(XFCE_IS_ICON_THEME(icon_theme) && search_path);
    
    gtk_icon_theme_prepend_search_path(icon_theme->priv->icon_theme,
                                       search_path);
}

/**
 * xfce_icon_theme_append_search_path:
 * @icon_theme: An #XfceIconTheme.
 * @search_path: A pathname, terminated with '/'.
 *
 * Appends @search_path to the current icon theme search path.
 *
 * Since 4.1
 **/
void
xfce_icon_theme_append_search_path(XfceIconTheme *icon_theme,
        const gchar *search_path)
{
    g_return_if_fail(XFCE_IS_ICON_THEME(icon_theme) && search_path);
    
    gtk_icon_theme_append_search_path(icon_theme->priv->icon_theme,
                                      search_path);
}

/**
 * xfce_icon_theme_register_category:
 * @icon_theme: An #XfceIconTheme.
 * @icon_names: A GList of icon names.
 *
 * Registers a new #XfceIconThemeCategory for use with
 * #xfce_icon_theme_lookup_category() and xfce_icon_theme_load_category().
 *
 * Since 4.1
 *
 * Return value: An identifier that can be used for future category lookups.
 **/
XfceIconThemeCategory
xfce_icon_theme_register_category(XfceIconTheme *icon_theme, GList *icon_names)
{    
    g_return_val_if_fail(XFCE_IS_ICON_THEME(icon_theme) && icon_names, -1);
    
    g_warning("xfce_icon_theme_register_category() is deprecated and no longer " \
              "does anything useful.  Use xfce_themed_icon_load/lookup_list() instead.");
    
    return -1;
}

/**
 * xfce_icon_theme_unregister_category:
 * @icon_theme: An #XfceIconTheme.
 * @category: An #XfceIconThemeCategory registered previously with
 *            xfce_icon_theme_register_category().
 *
 * Unregisters @category, which must have been registered previously with
 * xfce_icon_theme_register_category().  After this call, the category may no
 * longer be used for icon lookups.
 *
 * Since 4.1
 **/
void
xfce_icon_theme_unregister_category(XfceIconTheme *icon_theme,
        XfceIconThemeCategory category)
{
    /* no-op */
}

/**
 * xfce_icon_theme_set_use_svg:
 * @icon_theme: An #XfceIconTheme.
 * @use_svg: Whether or not to use SVG icons.
 *
 * Sets whether or not to include SVG icons in icon lookups and loads.  This
 * option defaults to %TRUE.
 *
 * Since 4.1.91
 **/
void
xfce_icon_theme_set_use_svg(XfceIconTheme *icon_theme, gboolean use_svg)
{
    g_warning("xfce_icon_theme_set_use_svg() is deprecated and no longer " \
              "does anything useful.  Use GtkIconTheme directly to avoid " \
              "searching for SVG icons.");
}

/**
 * xfce_icon_theme_get_use_svg:
 * @icon_theme: An #XfceIconTheme.
 *
 * Reports whether or not the icon theme is set to return SVG icons.
 *
 * Since 4.1.91
 **/
gboolean
xfce_icon_theme_get_use_svg(XfceIconTheme *icon_theme)
{
    /* no-op */
    return TRUE;
}
