Logo Search packages:      
Sourcecode: guifications version File versions

gf_item_icon.c

/*
 * Guifications - The end all, be all, toaster popup plugin
 * Copyright (C) 2003-2004 Gary Kramlich
 *
 * This program 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 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 General Public License for more details.
 *
 * You should have received a copy of the GNU 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.
 */
#include <glib.h>
#include <gtk/gtk.h>
#include <gdk/gdk.h>

#include <account.h>
#include <buddyicon.h>
#include <debug.h>
#include <xmlnode.h>
#include <gtkblist.h>

#include "gf_gtk_utils.h"
#include "gf_internal.h"
#include "gf_item.h"
#include "gf_item_icon.h"

struct _GfItemIcon {
      GfItem *item;

      GfItemIconType type;
      GfItemIconSize size;
};

static GfItemIconType
item_icon_type_from_string(const gchar *string) {
      g_return_val_if_fail(string, GF_ITEM_ICON_TYPE_UNKNOWN);

      if(!g_ascii_strcasecmp(string, "protocol"))
            return GF_ITEM_ICON_TYPE_PROTOCOL;
      else if(!g_ascii_strcasecmp(string, "buddy"))
            return GF_ITEM_ICON_TYPE_BUDDY;
      else if(!g_ascii_strcasecmp(string, "status"))
            return GF_ITEM_ICON_TYPE_STATUS;
      else
            return GF_ITEM_ICON_TYPE_UNKNOWN;
}

static const gchar *
item_icon_type_to_string(GfItemIconType type) {
      g_return_val_if_fail(type != GF_ITEM_ICON_TYPE_UNKNOWN, NULL);

      switch(type) {
            case GF_ITEM_ICON_TYPE_BUDDY:       return "buddy";         break;
            case GF_ITEM_ICON_TYPE_PROTOCOL:    return "protocol";      break;
            case GF_ITEM_ICON_TYPE_STATUS:            return "status";        break;
            case GF_ITEM_ICON_TYPE_UNKNOWN:
            default:                                        return NULL;            break;
      }
}

static GfItemIconSize
item_icon_size_from_string(const gchar *string) {
      g_return_val_if_fail(string, GF_ITEM_ICON_SIZE_UNKNOWN);

      if(!g_ascii_strcasecmp(string, "tiny"))
            return GF_ITEM_ICON_SIZE_TINY;
      else if(!g_ascii_strcasecmp(string, "small"))
            return GF_ITEM_ICON_SIZE_SMALL;
      else if(!g_ascii_strcasecmp(string, "little"))
            return GF_ITEM_ICON_SIZE_LITTLE;
      else if(!g_ascii_strcasecmp(string, "normal"))
            return GF_ITEM_ICON_SIZE_NORMAL;
      else if(!g_ascii_strcasecmp(string, "big"))
            return GF_ITEM_ICON_SIZE_BIG;
      else if(!g_ascii_strcasecmp(string, "large"))
            return GF_ITEM_ICON_SIZE_LARGE;
      else if(!g_ascii_strcasecmp(string, "huge"))
            return GF_ITEM_ICON_SIZE_HUGE;
      else
            return GF_ITEM_ICON_SIZE_UNKNOWN;
}

static const gchar *
item_icon_size_to_string(GfItemIconSize size) {
      g_return_val_if_fail(size != GF_ITEM_ICON_SIZE_UNKNOWN, NULL);

      switch(size) {
            case GF_ITEM_ICON_SIZE_HUGE:  return "huge";    break;
            case GF_ITEM_ICON_SIZE_LARGE: return "large";   break;
            case GF_ITEM_ICON_SIZE_BIG:         return "big";     break;
            case GF_ITEM_ICON_SIZE_NORMAL:      return "normal";  break;
            case GF_ITEM_ICON_SIZE_LITTLE:      return "little";  break;
            case GF_ITEM_ICON_SIZE_SMALL: return "small";   break;
            case GF_ITEM_ICON_SIZE_TINY:  return "tiny";    break;
            case GF_ITEM_ICON_SIZE_UNKNOWN:
            default:                                  return NULL;      break;
      }
}

void
gf_item_icon_destroy(GfItemIcon *item_icon) {
      g_return_if_fail(item_icon);

      item_icon->item = NULL;
      item_icon->type = GF_ITEM_ICON_TYPE_UNKNOWN;
      item_icon->size = GF_ITEM_ICON_SIZE_UNKNOWN;

      g_free(item_icon);
      item_icon = NULL;
}

GfItemIcon *
gf_item_icon_new(GfItem *item) {
      GfItemIcon *item_icon;

      g_return_val_if_fail(item, NULL);

      item_icon = g_new0(GfItemIcon, 1);
      item_icon->item = item;

      return item_icon;
}

GfItemIcon *
gf_item_icon_new_from_xmlnode(GfItem *item, xmlnode *node) {
      GfItemIcon *item_icon;

      g_return_val_if_fail(item, NULL);
      g_return_val_if_fail(node, NULL);

      item_icon = gf_item_icon_new(item);

      item_icon->type = item_icon_type_from_string(xmlnode_get_attrib(node, "type"));
      if(item_icon->type == GF_ITEM_ICON_TYPE_UNKNOWN) {
            gaim_debug_info("Guifications", "** Error loading icon item: 'Unknown icon type'\n");
            gf_item_icon_destroy(item_icon);
            return NULL;
      }

      item_icon->size = item_icon_size_from_string(xmlnode_get_attrib(node, "size"));
      if(item_icon->size == GF_ITEM_ICON_SIZE_UNKNOWN) {
            gaim_debug_info("Guifications", "** Error loading icon item: 'Unknown icon size'\n");
            gf_item_icon_destroy(item_icon);
            return NULL;
      }

      return item_icon;
}

GfItemIcon *
gf_item_icon_copy(GfItemIcon *icon) {
      GfItemIcon *new_icon;

      g_return_val_if_fail(icon, NULL);

      new_icon = gf_item_icon_new(icon->item);

      new_icon->type = icon->type;
      new_icon->size = icon->size;

      return new_icon;
}

xmlnode *
gf_item_icon_to_xmlnode(GfItemIcon *icon) {
      xmlnode *parent;

      parent = xmlnode_new("icon");
      xmlnode_set_attrib(parent, "type", item_icon_type_to_string(icon->type));
      xmlnode_set_attrib(parent, "size", item_icon_size_to_string(icon->size));

      return parent;
}

void
gf_item_icon_set_type(GfItemIcon *icon, GfItemIconType type) {
      g_return_if_fail(icon);
      g_return_if_fail(type != GF_ITEM_ICON_TYPE_UNKNOWN);

      icon->type = type;
}

GfItemIconType
gf_item_icon_get_type(GfItemIcon *icon) {
      g_return_val_if_fail(icon, GF_ITEM_ICON_TYPE_UNKNOWN);

      return icon->type;
}

void
gf_item_icon_set_size(GfItemIcon *icon, GfItemIconSize size) {
      g_return_if_fail(icon);
      g_return_if_fail(size != GF_ITEM_ICON_SIZE_UNKNOWN);

      icon->size = size;
}

GfItemIconSize
gf_item_icon_get_size(GfItemIcon *icon) {
      g_return_val_if_fail(icon, GF_ITEM_ICON_SIZE_UNKNOWN);

      return icon->size;
}

void
gf_item_icon_set_item(GfItemIcon *icon, GfItem *item) {
      g_return_if_fail(icon);
      g_return_if_fail(item);

      icon->item = item;
}

GfItem *
gf_item_icon_get_item(GfItemIcon *icon) {
      g_return_val_if_fail(icon, NULL);

      return icon->item;
}

static void
get_icon_dimensions(gint *width, gint *height, GfItemIconSize size) {
      switch(size) {
            case GF_ITEM_ICON_SIZE_TINY:
                  *width = *height = 16; break;
            case GF_ITEM_ICON_SIZE_SMALL:
                  *width = *height = 24; break;
            case GF_ITEM_ICON_SIZE_LITTLE:
                  *width = *height = 32; break;
            case GF_ITEM_ICON_SIZE_BIG:
                  *width = *height = 64; break;
            case GF_ITEM_ICON_SIZE_LARGE:
                  *width = *height = 96; break;
            case GF_ITEM_ICON_SIZE_HUGE:
                  *width = *height = 144; break;
            case GF_ITEM_ICON_SIZE_NORMAL:
            default:
                  *width = *height = 48; break;
      }
}

static void
get_icon_position(gint *x, gint *y,
                          gint img_width, gint img_height,
                          GfItemIcon *item_icon)
{
      gint width = 0, height = 0;

      g_return_if_fail(item_icon);

      get_icon_dimensions(&width, &height, item_icon->size);

      gf_item_get_render_position(x, y, width, height, img_width, img_height,
                                                item_icon->item);
}

void
gf_item_icon_render(GfItemIcon *item_icon, GdkPixbuf *pixbuf, GfEventInfo *info)
{
      GfEvent *event;
      GdkPixbuf *original = NULL, *scaled = NULL;
      gint x, y;
      gint width, height;
      gboolean is_contact;

      g_return_if_fail(item_icon);
      g_return_if_fail(pixbuf);
      g_return_if_fail(info);

      event = gf_event_info_get_event(info);

      is_contact = gf_event_info_get_is_contact(info);

      if(item_icon->type == GF_ITEM_ICON_TYPE_PROTOCOL) {
            if(is_contact) {
                  gchar *filename;

                  filename = g_build_filename(DATADIR, "pixmaps", "gaim.png", NULL);
                  original = gdk_pixbuf_new_from_file(filename, NULL);
                  g_free(filename);
            } else {
                  original = create_prpl_icon(gf_event_info_get_account(info));
            }
      } else if(item_icon->type == GF_ITEM_ICON_TYPE_BUDDY) {
            GaimBuddyIcon *icon = NULL;
            GdkPixbufLoader *loader;
            const guchar *data;
            size_t len;

            icon = gaim_buddy_icons_find(gf_event_info_get_account(info),
                                                       gf_event_info_get_target(info));
            if(icon) {
                  loader = gdk_pixbuf_loader_new();
                  data = gaim_buddy_icon_get_data(icon, &len);
                  gdk_pixbuf_loader_write(loader, data, len, NULL);
      
                  if((original = gdk_pixbuf_loader_get_pixbuf(loader)))
                        g_object_ref(G_OBJECT(original));
      
                  gdk_pixbuf_loader_close(loader, NULL);
                  g_object_unref(G_OBJECT(loader));
            }
      } else if(item_icon->type == GF_ITEM_ICON_TYPE_STATUS) {
            GaimBuddy *buddy = NULL;

            if((buddy = gf_event_info_get_buddy(info))) {
                  original = gaim_gtk_blist_get_status_icon((GaimBlistNode *)buddy,
                                                                                GAIM_STATUS_ICON_LARGE);
            }
      }

      /* if the original doesn't work for whatever reason we fallback to the protocol or
       * the gaim guy if it is a contact notification, this will be optional when we
       * "enhance" the theme format.  If it fails we return like we used to.
       */
      if(!original) {
            if(!(original = create_prpl_icon(gf_event_info_get_account(info))))
                  return;
      }

      get_icon_position(&x, &y,
                                gdk_pixbuf_get_width(pixbuf),
                                gdk_pixbuf_get_height(pixbuf),
                                item_icon);

      get_icon_dimensions(&width, &height, item_icon->size);
      scaled = gdk_pixbuf_scale_simple(original, width, height, GDK_INTERP_BILINEAR);
      g_object_unref(G_OBJECT(original));

      gf_gtk_pixbuf_clip_composite(scaled, x, y, pixbuf);

      g_object_unref(G_OBJECT(scaled));
}

Generated by  Doxygen 1.6.0   Back to index