Logo Search packages:      
Sourcecode: guifications version File versions  Download package

gf_item.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 <gdk/gdk.h>

#include <debug.h>

#include "gf_event_info.h"
#include "gf_internal.h"
#include "gf_item.h"
#include "gf_item_icon.h"
#include "gf_item_image.h"
#include "gf_item_offset.h"
#include "gf_item_text.h"
#include "gf_notification.h"
#include "gf_preferences.h"
#include "gf_theme.h"

/* This setup sucks, but meh.. it works... be sure to update both the translated and the
 * english versions if you add or remove anything.  The english is used only for the
 * files, so they're case insentive.  The i18n are used in the theme editor.
 *
 * I'd fix this.. But whats translated doesn't match what is in the themes, and
 * while we could use the text that's used in the theme's as display text, why
 * mess with it while this, as ugly as it is, does work.
 */
const gchar *items_norm[] = { "icon", "image", "text", NULL };
const gchar *items_i18n[] = { N_("Icon"), N_("Image"), N_("Text"), NULL };

const gchar *positions_norm[] = { "north-west", "north", "north-east",
                                                  "west", "center", "east",
                                                  "south-west", "south", "south-east",
                                                  NULL };
const gchar *positions_i18n[] = { N_("North West"), N_("North"), N_("North East"),
                                                  N_("West"), N_("Center"), N_("East"),
                                                  N_("South West"), N_("South"), N_("South East"),
                                                  NULL };

struct _GfItem {
      GfNotification *notification;
      GfItemType type;
      GfItemPosition position;
      GfItemOffset *h_offset;
      GfItemOffset *v_offset;

      union {
            GfItemIcon *icon;
            GfItemText *text;
            GfItemImage *image;
      } u;
};

void
gf_item_get_render_position(gint *x, gint *y, gint width, gint height,
                                          gint img_width, gint img_height, GfItem *item)
{
      gint north, east, south, west, lat, lon;
      gint item_h_w, item_h_h;
      gint img_h_w, img_h_h;
      gint h_offset, v_offset;

      g_return_if_fail(item);

      item_h_w = width / 2;
      item_h_h = height / 2;
      img_h_w = img_width / 2;
      img_h_h = img_height / 2;

      if(item->h_offset) {
            if(gf_item_offset_get_is_percentage(item->h_offset))
                  h_offset = (img_width * gf_item_offset_get_value(item->h_offset)) / 100;
            else
                  h_offset = gf_item_offset_get_value(item->h_offset);
      } else {
            h_offset = 0;
      }

      if(item->v_offset) {
            if(gf_item_offset_get_is_percentage(item->v_offset))
                  v_offset = (img_height * gf_item_offset_get_value(item->v_offset)) / 100;
            else
                  v_offset = gf_item_offset_get_value(item->v_offset);
      } else {
            v_offset = 0;
      }

      north = v_offset;
      east = img_width - width + h_offset;
      south = img_height - height + v_offset;
      west = h_offset;
      lon = img_h_w - item_h_w + h_offset;
      lat = img_h_h - item_h_h + v_offset;

      switch(item->position) {
            case GF_ITEM_POSITION_NW:     *x = west;  *y = north; break;
            case GF_ITEM_POSITION_N:      *x = lon;   *y = north; break;
            case GF_ITEM_POSITION_NE:     *x = east;  *y = north; break;
            case GF_ITEM_POSITION_W:      *x = west;  *y = lat;   break;
            case GF_ITEM_POSITION_C:      *x = lon;   *y = lat;   break;
            case GF_ITEM_POSITION_E:      *x = east;  *y = lat;   break;
            case GF_ITEM_POSITION_SW:     *x = west;  *y = south; break;
            case GF_ITEM_POSITION_S:      *x = lon;   *y = south; break;
            case GF_ITEM_POSITION_SE:     *x = east;  *y = south; break;
            default:                            *x = 0;           *y = 0;           break;
      }
}

const gchar *
gf_item_type_to_string(GfItemType type, gboolean i18n) {
      g_return_val_if_fail(type < GF_ITEM_TYPE_UNKNOWN, NULL);
      g_return_val_if_fail(type >= 0, NULL);

      if(i18n)
            return _(items_i18n[type]);
      else
            return items_norm[type];
}

GfItemType
gf_item_type_from_string(const gchar *string, gboolean i18n) {
      gint i;
      const gchar *val;

      g_return_val_if_fail(string, GF_ITEM_TYPE_UNKNOWN);

      for(i = 0; i < GF_ITEM_TYPE_UNKNOWN; i++) {
            if(i18n)
                  val = _(items_i18n[i]);
            else
                  val = items_norm[i];

            if(!val)
                  return GF_ITEM_TYPE_UNKNOWN;

            if(!g_ascii_strcasecmp(string, val))
                  return i;
      }

      return GF_ITEM_TYPE_UNKNOWN;
}

const gchar *
gf_item_position_to_string(GfItemPosition position, gboolean i18n) {
      g_return_val_if_fail(position < GF_ITEM_POSITION_UNKNOWN, NULL);
      g_return_val_if_fail(position >= 0, NULL);

      if(i18n)
            return _(positions_i18n[position]);
      else
            return positions_norm[position];
}

GfItemPosition
gf_item_position_from_string(const gchar *position, gboolean i18n) {
      gint i;
      const gchar *val;

      g_return_val_if_fail(position, GF_ITEM_POSITION_UNKNOWN);

      for(i = 0; i < GF_ITEM_POSITION_UNKNOWN; i++) {
            if(i18n)
                  val = _(positions_i18n[i]);
            else
                  val = positions_norm[i];

            if(!val)
                  return GF_ITEM_POSITION_UNKNOWN;

            if(!g_ascii_strcasecmp(val, position))
                  return i;
      }

      return GF_ITEM_POSITION_UNKNOWN;
}

GfItem *
gf_item_new(GfNotification *notification) {
      GfItem *item;

      g_return_val_if_fail(notification, NULL);

      item = g_new0(GfItem, 1);
      item->notification = notification;

      return item;
}

GfItem *
gf_item_new_from_xmlnode(GfNotification *notification, xmlnode *node) {
      GfItem *item;
      xmlnode *child;

      g_return_val_if_fail(node, NULL);
      g_return_val_if_fail(notification, NULL);

      item = gf_item_new(notification);

      if(!item)
            return NULL;

      item->type = gf_item_type_from_string(xmlnode_get_attrib(node, "type"), FALSE);
      if(item->type == GF_ITEM_TYPE_UNKNOWN) {
            gaim_debug_info("Guifications", "** Error: unknown item type\n");
            gf_item_destroy(item);
            return NULL;
      }

      if((child = xmlnode_get_child(node, "position"))) {
            item->position = gf_item_position_from_string(xmlnode_get_attrib(child, "value"), FALSE);
            if(item->position == GF_ITEM_POSITION_UNKNOWN) {
                  gaim_debug_info("Guifications", "** Error: invalid position\n");
                  gf_item_destroy(item);
                  return NULL;
            }
      } else { /* if we don't have a position we drop the item */
            gaim_debug_info("Guifications", "** Error: no positioning found for item\n");
            gf_item_destroy(item);
            return NULL;
      }

      /* if we don't have an offset node, we create it anyways so it can be changed in the
       * theme editor.
       */
      if((child = xmlnode_get_child(node, "h_offset")))
            item->h_offset = gf_item_offset_new_from_xmlnode(item, child);
      if(!item->h_offset)
            item->h_offset = gf_item_offset_new(item);

      if((child = xmlnode_get_child(node, "v_offset")))
            item->v_offset = gf_item_offset_new_from_xmlnode(item, child);
      if(!item->v_offset)
            item->v_offset = gf_item_offset_new(item);

      switch(item->type) {
            case GF_ITEM_TYPE_ICON:
                  if((child = xmlnode_get_child(node, "icon"))) {
                        item->u.icon = gf_item_icon_new_from_xmlnode(item, child);
                        if(!item->u.icon) {
                              gf_item_destroy(item);
                              return NULL;
                        }
                  } else {
                        gaim_debug_info("Guifications", "** Error loading icon item: 'No icon element found'\n");
                        gf_item_destroy(item);
                        return NULL;
                  }

                  break;
            case GF_ITEM_TYPE_IMAGE:
                  if((child = xmlnode_get_child(node, "image"))) {
                        item->u.image = gf_item_image_new_from_xmlnode(item, child);
                        if(!item->u.image) {
                              gf_item_destroy(item);
                              return NULL;
                        }
                  } else {
                        gaim_debug_info("Guifications", "** Error loading image item: 'No image element found'\n");
                        gf_item_destroy(item);
                        return NULL;
                  }

                  break;
            case GF_ITEM_TYPE_TEXT:
                  if((child = xmlnode_get_child(node, "text"))) {
                        item->u.text = gf_item_text_new_from_xmlnode(item, child);
                        if(!item->u.text) {
                              gf_item_destroy(item);
                              return NULL;
                        }
                  } else {
                        gaim_debug_info("Guifications", "** Error loading text item: 'No text element found'\n");
                        gf_item_destroy(item);
                        return NULL;
                  }

                  break;
            case GF_ITEM_TYPE_UNKNOWN:
            default:
                  gaim_debug_info("Guifications", "** Error loading item: 'Unknown item type'\n");
                  gf_item_destroy(item);
                  return NULL;
                  break;
      }

      return item;
}

GfItem *
gf_item_copy(GfItem *item) {
      GfItem *new_item;

      g_return_val_if_fail(item, NULL);

      new_item = gf_item_new(item->notification);
      new_item->type = item->type;
      new_item->position = item->position;
      new_item->h_offset = gf_item_offset_copy(item->h_offset);
      new_item->v_offset = gf_item_offset_copy(item->v_offset);

      if(item->type == GF_ITEM_TYPE_ICON)
            new_item->u.icon = gf_item_icon_copy(item->u.icon);
      else if(item->type == GF_ITEM_TYPE_ICON)
            new_item->u.image = gf_item_image_copy(item->u.image);
      else if(item->type == GF_ITEM_TYPE_TEXT)
            new_item->u.text = gf_item_text_copy(item->u.text);
      else {
            gf_item_destroy(new_item);
            new_item = NULL;
      }

      return new_item;
}

xmlnode *
gf_item_to_xmlnode(GfItem *item) {
      gchar *offset;
      xmlnode *parent, *child;

      parent = xmlnode_new("item");
      xmlnode_set_attrib(parent, "type", gf_item_type_to_string(item->type, FALSE));

      child = xmlnode_new_child(parent, "position");
      xmlnode_set_attrib(child, "value", gf_item_position_to_string(item->position, FALSE));

      child = xmlnode_new_child(parent, "h_offset");
      offset = g_strdup_printf("%d%s", gf_item_offset_get_value(item->h_offset),
                                           gf_item_offset_get_is_percentage(item->h_offset) ? "%" : "");
      xmlnode_set_attrib(child, "value", offset);
      g_free(offset);

      child = xmlnode_new_child(parent, "v_offset");
      offset = g_strdup_printf("%d%s", gf_item_offset_get_value(item->v_offset),
                                           gf_item_offset_get_is_percentage(item->v_offset) ? "%" : "");
      xmlnode_set_attrib(child, "value", offset);
      g_free(offset);

      switch(item->type) {
            case GF_ITEM_TYPE_ICON:
                  child = gf_item_icon_to_xmlnode(item->u.icon);
                  break;
            case GF_ITEM_TYPE_IMAGE:
                  child = gf_item_image_to_xmlnode(item->u.image);
                  break;
            case GF_ITEM_TYPE_TEXT:
                  child = gf_item_text_to_xmlnode(item->u.text);
                  break;
            case GF_ITEM_TYPE_UNKNOWN:
            default:
                  child = NULL;
      }

      if(child)
            xmlnode_insert_child(parent, child);

      return parent;
}

void
gf_item_destroy(GfItem *item) {
      g_return_if_fail(item);

      if(item->h_offset) {
            gf_item_offset_destroy(item->h_offset);
            item->h_offset = NULL;
      }

      if(item->v_offset) {
            gf_item_offset_destroy(item->v_offset);
            item->v_offset = NULL;
      }

      if(item->type == GF_ITEM_TYPE_ICON && item->u.icon) {
            gf_item_icon_destroy(item->u.icon);
            item->u.icon = NULL;
      }

      if(item->type == GF_ITEM_TYPE_IMAGE && item->u.image) {
            gf_item_image_destroy(item->u.image);
            item->u.image = NULL;
      }

      if(item->type == GF_ITEM_TYPE_TEXT && item->u.text) {
            gf_item_text_destroy(item->u.text);
            item->u.text = NULL;
      }

      g_free(item);
      item = NULL;
}

void
gf_item_set_type(GfItem *item, GfItemType type) {
      g_return_if_fail(item);
      g_return_if_fail(type != GF_ITEM_TYPE_UNKNOWN);

      item->type = type;
}

GfItemType
gf_item_get_type(GfItem *item) {
      g_return_val_if_fail(item, GF_ITEM_TYPE_UNKNOWN);

      return item->type;
}

void
gf_item_set_notification(GfItem *item, GfNotification *notification) {
      g_return_if_fail(item);
      g_return_if_fail(notification);

      item->notification = notification;
}

GfNotification *
gf_item_get_notification(GfItem *item) {
      g_return_val_if_fail(item, NULL);

      return item->notification;
}

void
gf_item_set_horz_offset(GfItem *item, GfItemOffset *offset) {
      g_return_if_fail(item);
      g_return_if_fail(offset);

      item->h_offset = offset;
}

GfItemOffset *
gf_item_get_horz_offset(GfItem *item) {
      g_return_val_if_fail(item, NULL);

      return item->h_offset;
}

void
gf_item_set_vert_offset(GfItem *item, GfItemOffset *offset) {
      g_return_if_fail(item);
      g_return_if_fail(offset);

      item->v_offset = offset;
}

GfItemOffset *
gf_item_get_vert_offset(GfItem *item) {
      g_return_val_if_fail(item, NULL);

      return item->v_offset;
}

void
gf_item_set_position(GfItem *item, GfItemPosition position) {
      g_return_if_fail(item);
      g_return_if_fail(position != GF_ITEM_POSITION_UNKNOWN);

      item->position = position;
}

GfItemPosition
gf_item_get_position(GfItem *item) {
      g_return_val_if_fail(item, GF_ITEM_POSITION_UNKNOWN);

      return item->position;
}

static void
gf_item_free_old_subtype(GfItem *item) {
      if(item->type == GF_ITEM_TYPE_ICON && item->u.icon)
            gf_item_icon_destroy(item->u.icon);
      else if(item->type == GF_ITEM_TYPE_IMAGE && item->u.image)
            gf_item_image_destroy(item->u.image);
      else if(item->type == GF_ITEM_TYPE_TEXT && item->u.text)
            gf_item_text_destroy(item->u.text);
}

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

      gf_item_free_old_subtype(item);

      item->u.icon = icon;
}

GfItemIcon *
gf_item_get_item_icon(GfItem *item) {
      g_return_val_if_fail(item->type == GF_ITEM_TYPE_ICON, NULL);

      return item->u.icon;
}

void
gf_item_set_item_image(GfItem *item, GfItemImage *image) {
      g_return_if_fail(item);
      g_return_if_fail(image);

      gf_item_free_old_subtype(item);

      item->u.image = image;
}

GfItemImage *
gf_item_get_item_image(GfItem *item) {
      g_return_val_if_fail(item->type == GF_ITEM_TYPE_IMAGE, NULL);

      return item->u.image;
}

void
gf_item_set_item_text(GfItem *item, GfItemText *text) {
      g_return_if_fail(item);
      g_return_if_fail(text);

      gf_item_free_old_subtype(item);

      item->u.text = text;
}

GfItemText *
gf_item_get_item_text(GfItem *item) {
      g_return_val_if_fail(item->type == GF_ITEM_TYPE_TEXT, NULL);

      return item->u.text;
}

void
gf_item_render(GfItem *item, GdkPixbuf *pixbuf, GfEventInfo *info) {
      g_return_if_fail(item);
      g_return_if_fail(pixbuf);
      g_return_if_fail(info);

      switch(item->type) {
            case GF_ITEM_TYPE_ICON:
                  gf_item_icon_render(item->u.icon, pixbuf, info);
                  break;
            case GF_ITEM_TYPE_TEXT:
                  gf_item_text_render(item->u.text, pixbuf, info);
                  break;
            case GF_ITEM_TYPE_IMAGE:
                  gf_item_image_render(item->u.image, pixbuf, info);
                  break;
            default:
                  break;
      }
};

void
gf_items_swap(GfItem *item1, GfItem *item2) {
      GfItem *item = NULL;
      GList *l = NULL, *l1 = NULL, *l2 = NULL;

      g_return_if_fail(item1);
      g_return_if_fail(item2);

      g_return_if_fail(item1->notification == item2->notification);

      for(l = gf_notification_get_items(item1->notification); l; l = l->next) {
            if(l->data == item1)
                  l1 = l;
            if(l->data == item2)
                  l2 = l;
      }

      g_return_if_fail(l1);
      g_return_if_fail(l2);

      item = l1->data;
      l1->data = l2->data;
      l2->data = item;
}


Generated by  Doxygen 1.6.0   Back to index