grim/guifications2
Clone
Summary
Browse
Changes
Graph
[gf2-migrate @ 81]
org.guifications.gf2
2006-09-07, Gary Kramlich
d41d000101e1
[gf2-migrate @ 81]
i like my guifications to compile correctly... installing correctly is still evading me...
/*
* Guifications - The end all, be all, toaster popup plugin
* Copyright (C) 2003-2005 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
;
}