/* glunarclock.c:
*
* 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.
*
* Copyright (C) 2003-2004 Josh Buhl
*
* This was originally the fish.c file from the Gnome Fish Applet
* which I've mangled into the glunarclock applet. -- Josh Buhl
*
* Original Copyright (C) 1998-2002 Free Software Foundation, Inc.
*
* Authors:
* George Lebl <jirka@5z.com> (Gnome Fish Applet)
* Mark McLoughlin <mark@skynet.ie> (Gnome Fish Applet)
* Josh Buhl <jbuhl@users.sourceforge.net>
*/
#include "glunarclock.h"
#include "moondata.h"
#define UPDATE_APPLET_INTERVAL 1 /* seconds */
#define FALLBACK_MOONIMAGE_FILE "glunarclock/moon_56frames.png"
#define FALLBACK_MOONIMAGE_FRAMES 56
#define ALTERNATIVE_MOONIMAGE_FILE "glunarclock/cartoonmoon_12frames.png"
#define ALTERNATIVE_MOONIMAGE_FRAMES 12
static void update_moon(MoonApplet * moon);
static void update_image_number(MoonApplet * moon);
static void compose_image (MoonApplet *moon);
static gboolean load_moon_image (MoonApplet *moon);
static GType moon_applet_get_type (void);
static GObjectClass *parent_class;
void
show_error(gchar * message1, gchar * message2){
GtkWidget *dialog;
dialog = gtk_message_dialog_new (
NULL,
GTK_DIALOG_DESTROY_WITH_PARENT,
GTK_MESSAGE_ERROR,
GTK_BUTTONS_CLOSE,
message1, message2);
g_signal_connect (dialog, "response",
G_CALLBACK (gtk_widget_destroy),
NULL);
gtk_window_set_resizable (GTK_WINDOW (dialog), FALSE);
/* gtk_window_set_screen (GTK_WINDOW (dialog), */
/* gtk_widget_get_screen (GTK_WIDGET (moon))); */
gtk_widget_show (dialog);
}
void
show_help (MoonApplet *moon, const char *link_id)
{
GError *error = NULL;
egg_screen_help_display (
gtk_widget_get_screen (GTK_WIDGET (moon)),
"glunarclock-applet-2", link_id, &error);
if (error) {
show_error(_("There was an error displaying help: %s"),
error->message);
g_error_free (error);
}
}
static void
image_value_changed (GtkEntry *entry,
MoonApplet *moon)
{ char *path;
path = gnome_file_entry_get_full_path (
GNOME_FILE_ENTRY (moon->pixmap_entry), TRUE);
if (!path || !path [0]) {
g_free (path);
return;
}
panel_applet_gconf_set_string (PANEL_APPLET (moon), "image", path, NULL);
g_free (path);
}
static void
ns_value_changed (GtkToggleButton *toggle,
MoonApplet *moon)
{
panel_applet_gconf_set_bool (
PANEL_APPLET (moon), "is_north",
gtk_toggle_button_get_active (toggle), NULL);
}
static void
ew_value_changed (GtkToggleButton *toggle,
MoonApplet *moon)
{
panel_applet_gconf_set_bool (
PANEL_APPLET (moon), "is_east",
gtk_toggle_button_get_active (toggle), NULL);
}
static void
latitude_value_changed (GtkSpinButton *button,
MoonApplet *moon)
{
panel_applet_gconf_set_float (
PANEL_APPLET (moon), "latitude",
gtk_spin_button_get_value_as_float (button), NULL);
}
static void
longitude_value_changed (GtkSpinButton *button,
MoonApplet *moon)
{
panel_applet_gconf_set_float (
PANEL_APPLET (moon), "longitude",
gtk_spin_button_get_value_as_float (button), NULL);
}
static void
n_frames_value_changed (GtkSpinButton *button,
MoonApplet *moon)
{
panel_applet_gconf_set_int (
PANEL_APPLET (moon), "frames",
gtk_spin_button_get_value_as_int (button), NULL);
}
static void
flip_value_changed (GtkToggleButton *toggle,
MoonApplet *moon)
{
panel_applet_gconf_set_bool (
PANEL_APPLET (moon), "flip",
gtk_toggle_button_get_active (toggle), NULL);
}
static gboolean
delete_event (GtkWidget *widget,
MoonApplet *moon)
{
gtk_widget_hide (widget);
}
static gboolean
close_dialog (GtkWidget *widget,
MoonApplet *moon)
{
gtk_widget_hide (moon->preferences_dialog);
}
static void
handle_response (GtkWidget *widget,
int id,
MoonApplet *moon)
{
if (id == GTK_RESPONSE_HELP) {
show_help (moon, "glunarclock-settings");
return;
}
gtk_widget_hide (moon->preferences_dialog);
}
static void
display_help_dialog (BonoboUIComponent *uic,
MoonApplet *moon,
const char *verbname)
{
show_help (moon, NULL);
}
static void
display_about_dialog (BonoboUIComponent *uic,
MoonApplet *moon,
const char *verbname)
{
char *authors [6];
GdkPixbuf *pixbuf;
GError *error = NULL;
char *file;
const char *about = _("GNOME Lunar Clock displays the current phase of the moon "
"and pertinent astronomical data.");
if (moon->about_dialog) {
gtk_window_set_screen (GTK_WINDOW (moon->about_dialog),
gtk_widget_get_screen (GTK_WIDGET (moon)));
gtk_window_present (GTK_WINDOW (moon->about_dialog));
return;
}
authors [0] = _("Josh Buhl <jbuhl@users.sourceforge.net>");
authors [1] = _("Mike Henderson: wmMoonClock");
authors [2] = _("Wanda & George: Applet Stuff");
authors [3] = _("Nissen: cartoon moon graphics");
authors [4] = _("Lots of friendly translators: po files");
authors [5] = NULL;
file = gnome_program_locate_file (NULL, GNOME_FILE_DOMAIN_PIXMAP,
"glunarclock-logo.png", FALSE, NULL);
pixbuf = gdk_pixbuf_new_from_file (file, &error);
g_free (file);
if (error) {
g_warning (G_STRLOC ": cannot open %s: %s", file, error->message);
g_error_free (error);
}
moon->about_dialog =
gnome_about_new (_("GNOME Lunar Clock"),
VERSION,
"Copyright \xc2\xa9 1999-2005 Josh Buhl, et al.",
(const char *) about,
(const char **) authors,
NULL,
NULL,
pixbuf);
if (pixbuf)
gdk_pixbuf_unref (pixbuf);
gtk_window_set_wmclass (GTK_WINDOW (moon->about_dialog), "moon", "Moon");
gtk_window_set_screen (GTK_WINDOW (moon->about_dialog),
gtk_widget_get_screen (GTK_WIDGET (moon)));
gnome_window_icon_set_from_file (GTK_WINDOW (moon->about_dialog),
GNOME_ICONDIR"/glunarclock-logo.png");
g_signal_connect (moon->about_dialog, "destroy",
G_CALLBACK (gtk_widget_destroyed),
&moon->about_dialog);
gtk_widget_show (moon->about_dialog);
}
static void
display_preferences_dialog (BonoboUIComponent *uic,
MoonApplet *moon,
const char *verbname)
{
GladeXML *xml;
GtkWidget *button;
if (moon->preferences_dialog) {
gtk_window_set_screen (GTK_WINDOW (moon->preferences_dialog),
gtk_widget_get_screen (GTK_WIDGET (moon)));
gtk_window_present (GTK_WINDOW (moon->preferences_dialog));
return;
}
xml = glade_xml_new (MOON_GLADEDIR "/glunarclock.glade",
"moon_preferences_dialog", NULL);
moon->preferences_dialog = glade_xml_get_widget (xml, "moon_preferences_dialog");
g_object_add_weak_pointer (G_OBJECT (moon->preferences_dialog),
(void**) &moon->preferences_dialog);
gtk_window_set_wmclass (GTK_WINDOW (moon->preferences_dialog),
"moon", "Moon");
gtk_dialog_set_default_response (GTK_DIALOG (moon->preferences_dialog),
GTK_RESPONSE_OK);
gnome_window_icon_set_from_file (GTK_WINDOW (moon->preferences_dialog),
GNOME_ICONDIR"/glunarclock-logo.png");
moon->pixmap_entry = glade_xml_get_widget (xml, "image_entry");
moon->image_entry = gnome_file_entry_gtk_entry (
GNOME_FILE_ENTRY (moon->pixmap_entry));
gtk_entry_set_text (GTK_ENTRY (moon->image_entry), moon->image);
g_signal_connect (moon->image_entry, "changed",
G_CALLBACK (image_value_changed), moon);
moon->frames_spin = glade_xml_get_widget (xml, "frames_spin");
gtk_spin_button_set_value (GTK_SPIN_BUTTON (moon->frames_spin),
moon->n_frames);
g_signal_connect (moon->frames_spin, "value_changed",
G_CALLBACK (n_frames_value_changed), moon);
moon->latitude_spin = glade_xml_get_widget (xml, "latitude_spin");
gtk_spin_button_set_value (GTK_SPIN_BUTTON (moon->latitude_spin),
moon->latitude);
g_signal_connect (moon->latitude_spin, "value_changed",
G_CALLBACK (latitude_value_changed), moon);
moon->longitude_spin = glade_xml_get_widget (xml, "longitude_spin");
gtk_spin_button_set_value (GTK_SPIN_BUTTON (moon->longitude_spin),
moon->longitude);
g_signal_connect (moon->longitude_spin, "value_changed",
G_CALLBACK (longitude_value_changed), moon);
moon->flip_toggle = glade_xml_get_widget (xml, "flip_toggle");
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (moon->flip_toggle),
moon->flip);
g_signal_connect (moon->flip_toggle, "toggled",
G_CALLBACK (flip_value_changed), moon);
moon->lat_radio = glade_xml_get_widget (xml, "latitude_north");
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (moon->lat_radio),
moon->is_north);
button = glade_xml_get_widget (xml, "latitude_south");
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button),
!(moon->is_north));
g_signal_connect (G_OBJECT(moon->lat_radio), "toggled",
G_CALLBACK (ns_value_changed), moon);
moon->long_radio = glade_xml_get_widget (xml, "longitude_east");
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (moon->long_radio),
moon->is_east);
button = glade_xml_get_widget (xml, "longitude_west");
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button),
!(moon->is_east));
g_signal_connect (G_OBJECT(moon->long_radio), "toggled",
G_CALLBACK (ew_value_changed), moon);
g_signal_connect (moon->preferences_dialog, "delete_event",
G_CALLBACK (delete_event), moon);
g_signal_connect (moon->preferences_dialog, "response",
G_CALLBACK (handle_response), moon);
button = glade_xml_get_widget (xml, "done_button");
g_signal_connect (button, "clicked", G_CALLBACK (close_dialog), moon);
gtk_window_set_screen (GTK_WINDOW (moon->preferences_dialog),
gtk_widget_get_screen (GTK_WIDGET (moon)));
gtk_window_present (GTK_WINDOW (moon->preferences_dialog));
g_object_unref (xml);
}
static void
image_changed_notify (GConfClient *client,
guint cnxn_id,
GConfEntry *entry,
MoonApplet *moon)
{
const char *value;
char *path = NULL;
if (!entry->value || entry->value->type != GCONF_VALUE_STRING)
return;
value = gconf_value_get_string (entry->value);
if (!value [0] || (moon->image && !strcmp (moon->image, value)))
return;
if (moon->image)
g_free (moon->image);
moon->image = g_strdup (value);
path = gnome_program_locate_file (NULL, GNOME_FILE_DOMAIN_APP_PIXMAP,
ALTERNATIVE_MOONIMAGE_FILE, FALSE, NULL);
if ((!strcmp(moon->image,ALTERNATIVE_MOONIMAGE_FILE)) ||
(!strcmp(moon->image, path))) {
moon->rotation_type = MIRROR;
panel_applet_gconf_set_int (
PANEL_APPLET (moon), "frames",
ALTERNATIVE_MOONIMAGE_FRAMES, NULL);
}
else
moon->rotation_type = ROTATE;
g_free(path);
path = gnome_program_locate_file (NULL, GNOME_FILE_DOMAIN_APP_PIXMAP,
FALLBACK_MOONIMAGE_FILE, FALSE, NULL);
if ((!strcmp(moon->image,FALLBACK_MOONIMAGE_FILE)) ||
(!strcmp(moon->image, path))) {
panel_applet_gconf_set_int (
PANEL_APPLET (moon), "frames",
FALLBACK_MOONIMAGE_FRAMES, NULL);
}
g_free(path);
update_image_number(moon);
load_moon_image (moon);
compose_image (moon);
if (moon->image_entry &&
strcmp (gtk_entry_get_text (GTK_ENTRY (moon->image_entry)), moon->image))
gtk_entry_set_text (GTK_ENTRY (moon->image_entry), moon->image);
}
static void
n_frames_changed_notify (GConfClient *client,
guint cnxn_id,
GConfEntry *entry,
MoonApplet *moon)
{
int value;
if (!entry->value || entry->value->type != GCONF_VALUE_INT)
return;
value = gconf_value_get_int (entry->value);
if (moon->n_frames == value)
return;
moon->n_frames = value;
if (moon->n_frames <= 0)
moon->n_frames = 24;
update_image_number(moon);
load_moon_image(moon);
compose_image(moon);
if (moon->frames_spin &&
gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (moon->frames_spin)) != moon->n_frames)
gtk_spin_button_set_value (GTK_SPIN_BUTTON (moon->frames_spin), moon->n_frames);
}
static void
flip_changed_notify (GConfClient *client,
guint cnxn_id,
GConfEntry *entry,
MoonApplet *moon)
{
gboolean value;
if (!entry->value || entry->value->type != GCONF_VALUE_BOOL)
return;
value = gconf_value_get_bool (entry->value);
if (moon->flip == value)
return;
moon->flip = value;
load_moon_image(moon);
compose_image (moon);
if (moon->flip_toggle &&
gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (moon->flip_toggle))
!= moon->flip)
gtk_toggle_button_set_active (
GTK_TOGGLE_BUTTON (moon->flip_toggle), moon->flip);
}
static void
ns_changed_notify (GConfClient *client,
guint cnxn_id,
GConfEntry *entry,
MoonApplet *moon)
{
gboolean value;
if (!entry->value || entry->value->type != GCONF_VALUE_BOOL)
return;
value = gconf_value_get_bool (entry->value);
if (moon->is_north == value)
return;
moon->is_north = value;
if ( moon->flip ){
load_moon_image(moon);
compose_image (moon);
}
update_moon(moon);
if (moon->lat_radio &&
gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (moon->lat_radio))
!= moon->is_north)
gtk_toggle_button_set_active (
GTK_TOGGLE_BUTTON (moon->lat_radio), moon->is_north);
}
static void
ew_changed_notify (GConfClient *client,
guint cnxn_id,
GConfEntry *entry,
MoonApplet *moon)
{
gboolean value;
if (!entry->value || entry->value->type != GCONF_VALUE_BOOL)
return;
value = gconf_value_get_bool (entry->value);
if (moon->is_east == value)
return;
moon->is_east = value;
update_moon(moon);
if (moon->long_radio &&
gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (moon->long_radio)) != moon->is_east)
gtk_toggle_button_set_active (
GTK_TOGGLE_BUTTON (moon->long_radio), moon->is_east);
}
static void
latitude_changed_notify (GConfClient *client,
guint cnxn_id,
GConfEntry *entry,
MoonApplet *moon)
{
gfloat value;
if (!entry->value || entry->value->type != GCONF_VALUE_FLOAT)
return;
value = gconf_value_get_float (entry->value);
if (moon->latitude == value)
return;
moon->latitude = value;
update_moon(moon);
if (moon->flip_toggle &&
gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (moon->flip_toggle)) != moon->flip)
gtk_toggle_button_set_active (
GTK_TOGGLE_BUTTON (moon->flip_toggle), moon->flip);
}
static void
longitude_changed_notify (GConfClient *client,
guint cnxn_id,
GConfEntry *entry,
MoonApplet *moon)
{
gfloat value;
if (!entry->value || entry->value->type != GCONF_VALUE_FLOAT)
return;
value = gconf_value_get_float (entry->value);
if (moon->longitude == value)
return;
moon->longitude = value;
update_moon(moon);
if (moon->flip_toggle &&
gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (moon->flip_toggle)) != moon->flip)
gtk_toggle_button_set_active (
GTK_TOGGLE_BUTTON (moon->flip_toggle), moon->flip);
}
static void
set_tooltip (MoonApplet *moon)
{
GtkTooltips *tooltips;
gchar *tooltip;
tooltips = gtk_tooltips_new ();
g_object_ref (tooltips);
gtk_object_sink (GTK_OBJECT (tooltips));
g_object_set_data (G_OBJECT (moon), "tooltips", tooltips);
tooltip = (visible(moon)) ?
g_strdup_printf(_("The moon is currently above the horizon."))
:
g_strdup_printf(_("The moon is currently below the horizon."));
gtk_tooltips_set_tip (tooltips, GTK_WIDGET (moon),
tooltip, NULL);
}
static void
destroy_tooltip (MoonApplet *moon)
{
GtkTooltips *tooltips;
tooltips = g_object_get_data (G_OBJECT (moon), "tooltips");
if (tooltips) {
g_object_unref (tooltips);
g_object_set_data (G_OBJECT (moon), "tooltips", NULL);
}
}
static void
update_image_number (MoonApplet * moon)
{
gdouble image_float;
gint image_int;
/* MoonPhase expresses phase of moon as fraction of 1; 0.5=full. */
image_float = moonphase() * (gdouble) (moon->n_frames);
image_int = (gint) image_float;
/* ergo image number ranges from 0 to (frames - 1), which is why
* it's mod frames and not mod (frames + 1). */
moon->image_number = ((image_float - image_int) >= 0.5) ?
(image_int + 1)
% moon->n_frames : image_int % moon->n_frames;
return;
}
static void
update_moon(MoonApplet * moon)
{
/* gboolean has_focus = FALSE; */
gboolean old_visible;
gint old_image_number;
old_image_number = moon->image_number;
old_visible = visible(moon);
update_moondata(moon);
update_image_number(moon);
if (moon->moondata_dialog)
update_moondata_dialog(moon);
if (old_image_number != moon->image_number) {
load_moon_image(moon);
/* has_focus = GTK_WIDGET_HAS_FOCUS(moon->applet); */
/* compose_image(moon, has_focus); */
compose_image(moon);
gtk_widget_queue_draw(moon->drawing_area);
}
if(old_visible != visible(moon)) {
destroy_tooltip(moon);
set_tooltip(moon);
}
return;
}
static gboolean
timeout_handler (gpointer data)
{
MoonApplet *moon = (MoonApplet *) data;
update_moon(moon);
return TRUE;
}
static void
setup_timeout (MoonApplet *moon)
{
if (moon->timeout)
g_source_remove (moon->timeout);
moon->timeout = g_timeout_add (1000 * UPDATE_APPLET_INTERVAL,
timeout_handler, moon);
}
static void
setup_gconf (MoonApplet *moon)
{
PanelApplet *applet = (PanelApplet *) moon;
char *key;
int i = 0;
key = panel_applet_gconf_get_full_key (applet, "image");
moon->listeners [i++] = gconf_client_notify_add (
moon->client, key,
(GConfClientNotifyFunc) image_changed_notify,
moon, NULL, NULL);
g_free (key);
key = panel_applet_gconf_get_full_key (applet, "frames");
moon->listeners [i++] = gconf_client_notify_add (
moon->client, key,
(GConfClientNotifyFunc)
n_frames_changed_notify,
moon, NULL, NULL);
g_free (key);
key = panel_applet_gconf_get_full_key (applet, "flip");
moon->listeners [i++] = gconf_client_notify_add (
moon->client, key,
(GConfClientNotifyFunc) flip_changed_notify,
moon, NULL, NULL);
g_free (key);
key = panel_applet_gconf_get_full_key (applet, "longitude");
moon->listeners [i++] = gconf_client_notify_add (
moon->client, key,
(GConfClientNotifyFunc)
longitude_changed_notify,
moon, NULL, NULL);
g_free (key);
key = panel_applet_gconf_get_full_key (applet, "latitude");
moon->listeners [i++] = gconf_client_notify_add (
moon->client, key,
(GConfClientNotifyFunc) latitude_changed_notify,
moon, NULL, NULL);
g_free (key);
key = panel_applet_gconf_get_full_key (applet, "is_north");
moon->listeners [i++] = gconf_client_notify_add (
moon->client, key,
(GConfClientNotifyFunc) ns_changed_notify,
moon, NULL, NULL);
g_free (key);
key = panel_applet_gconf_get_full_key (applet, "is_east");
moon->listeners [i++] = gconf_client_notify_add (
moon->client, key,
(GConfClientNotifyFunc) ew_changed_notify,
moon, NULL, NULL);
g_free (key);
g_assert (i == N_MOON_PREFS);
}
static void free_pixbuf(guchar * rgb, gpointer data)
{
g_free(rgb);
return;
}
static GdkPixbuf *
flip_image(const GdkPixbuf * pb, RotationType flip_type)
{
GdkPixbuf *new_pb;
gboolean has_alpha;
guchar *rgb, *new_rgb;
gint i,j,k, width, height, bytepp, rowstride;
has_alpha = gdk_pixbuf_get_has_alpha(pb);
rowstride = gdk_pixbuf_get_rowstride(pb);
width = gdk_pixbuf_get_width(pb);
height = gdk_pixbuf_get_height(pb);
bytepp= (has_alpha) ? 4:3;
new_rgb = g_new0(guchar, height * rowstride);
g_assert(new_rgb);
rgb = gdk_pixbuf_get_pixels(pb);
switch(flip_type){
case ROTATE :
/*rotate 180 degrees*/
for(i=0; i<rowstride*height; i+=bytepp){
j=i;
for(k = rowstride*height-i-bytepp;
k<rowstride*height-i; k++){
new_rgb[k] = rgb[j++];
}
}
break;
case MIRROR :
/*mirror along vertical axis*/
for(i=0; i<height; i++){
for(j=0; j<rowstride; j+=bytepp){
for(k = 0; k<bytepp; k++){
new_rgb[i*rowstride+rowstride-j+k]
= rgb[i*rowstride+j+k];
}
}
}
break;
default :
g_error("invalid flip type parameter %d", flip_type);
}
new_pb= gdk_pixbuf_new_from_data(new_rgb,
GDK_COLORSPACE_RGB,
has_alpha, 8, width,
height, rowstride,
free_pixbuf, NULL);
return new_pb;
}
static gboolean
load_moon_image (MoonApplet *moon)
{
GdkPixbuf *frame_pb, *test_pb;
GdkPixbuf *pixbuf = NULL;
GError *error = NULL;
char *path = NULL;
if (!moon->image)
return FALSE;
if (g_path_is_absolute (moon->image))
path = g_strdup (moon->image);
else {
path = gnome_program_locate_file (
NULL, GNOME_FILE_DOMAIN_PIXMAP,
moon->image, FALSE, NULL);
if (!path)
path = gnome_program_locate_file (
NULL, GNOME_FILE_DOMAIN_APP_PIXMAP,
moon->image, FALSE, NULL);
}
if (!path) {
g_warning ("Cannot locate '%s'", moon->image);
show_error("Cannot locate '%s'", moon->image);
} else {
pixbuf = gdk_pixbuf_new_from_file (path, &error);
if (error) {
g_warning ("Cannot load '%s': %s", path, error->message);
show_error(_("There was an error loading moon image: %s"),
error->message);
g_error_free(error);
}
g_free (path);
}
if (pixbuf) {
guchar *frame_rgb, *rgb;
gint width, height, xsrc, i, rowstride;
gboolean has_alpha;
width = gdk_pixbuf_get_width(pixbuf) / moon->n_frames;
height = gdk_pixbuf_get_height(pixbuf);
xsrc = moon->image_number * width;
frame_pb = gdk_pixbuf_new(GDK_COLORSPACE_RGB, TRUE, 8,
width, height);
if (!frame_pb)
g_error("cannot allocate image pixbuf.");
gdk_pixbuf_scale(pixbuf, frame_pb, 0, 0, width,
height, -xsrc, 0, 1, 1,
GDK_INTERP_HYPER);
has_alpha = gdk_pixbuf_get_has_alpha(frame_pb);
rowstride = gdk_pixbuf_get_rowstride(frame_pb);
if(moon->flip && ! moon->is_north){
test_pb = flip_image (frame_pb, moon->rotation_type);
gdk_pixbuf_unref(frame_pb);
frame_pb = test_pb;
}
/* rgb = g_new0(guchar, height * rowstride); */
/* if(rgb){ */
/* frame_rgb = gdk_pixbuf_get_pixels(frame_pb); */
/* /\* Hilight moon image for mouseover. */
/* * Alpha transparency should not be changed. *\/ */
/* for(i=0; i<rowstride*height; i++){ */
/* rgb[i] = (!has_alpha || i % 4 != 3) ? */
/* MIN(255, frame_rgb[i] + 24) */
/* : */
/* frame_rgb[i]; */
/* } */
/* } */
/* moon->hilit_image_pb = */
/* gdk_pixbuf_new_from_data(rgb, GDK_COLORSPACE_RGB, */
/* has_alpha, 8, width, */
/* height, rowstride, */
/* free_pixbuf, NULL); */
gdk_pixbuf_unref(pixbuf);
pixbuf = NULL;
} else {
guchar *rgb;
gint rowstride=120;
gint height=40;
gint width=40;
rgb = g_new0(guchar, height * rowstride);
frame_pb =
gdk_pixbuf_new_from_data(rgb, GDK_COLORSPACE_RGB,
FALSE, 8, width,
height, rowstride,
free_pixbuf, NULL);
moon->hilit_image_pb = NULL;
}
if (moon->image_pb)
g_object_unref (moon->image_pb);
moon->image_pb = frame_pb;
return TRUE;
}
static void
compose_image (MoonApplet *moon)
{
GtkWidget *widget = moon->drawing_area;
GdkPixbuf *composite_pb, *bg_pb;
GdkGC *gc;
int width = -1;
int height = -1;
int rowstride = 4;
int pixbuf_width = -1;
int pixbuf_height = -1;
gboolean rotate = FALSE;
gdouble scale = 1.0;
guchar *rgb;
int i;
if (!GTK_WIDGET_REALIZED (widget) ||
widget->allocation.width <= 0 ||
widget->allocation.height <= 0)
return;
if (moon->orientation == PANEL_APPLET_ORIENT_LEFT ||
moon->orientation == PANEL_APPLET_ORIENT_RIGHT)
rotate = TRUE;
if (moon->image_pb || load_moon_image (moon)) {
pixbuf_width = gdk_pixbuf_get_width (moon->image_pb);
pixbuf_height = gdk_pixbuf_get_height (moon->image_pb);
if (moon->orientation == PANEL_APPLET_ORIENT_UP ||
moon->orientation == PANEL_APPLET_ORIENT_DOWN) {
height = widget->allocation.height;
width = pixbuf_width * ((gdouble) height / pixbuf_height);
widget->requisition.width = width;
} else {
if (!rotate) {
width = widget->allocation.width;
height = pixbuf_height * ((gdouble) width / pixbuf_width);
widget->requisition.height = height;
} else {
width = widget->allocation.width;
height = pixbuf_width * ((gdouble) width / pixbuf_height);
widget->requisition.height = height;
}
}
} else {
if (rotate) {
width = widget->allocation.width;
height = widget->allocation.height;
} else {
height = widget->allocation.height;
width = widget->allocation.width;
}
}
g_assert (width != -1 && height != -1);
if (width == 0 || height == 0)
return;
scale = ((gdouble) height/pixbuf_height);
if (moon->pixmap)
g_object_unref (moon->pixmap);
moon->pixmap = gdk_pixmap_new (widget->window, width, height, -1);
if (!moon->image_pb)
return;
gtk_widget_queue_resize (widget);
g_assert (pixbuf_width != -1 && pixbuf_height != -1);
composite_pb = gdk_pixbuf_new(GDK_COLORSPACE_RGB, TRUE, 8,
width, height);
if (!composite_pb)
g_error("cannot allocate composing pixbuf.");
gdk_pixbuf_composite_color(moon->image_pb, composite_pb,
0, 0, width, height,
0, 0, scale, scale,
GDK_INTERP_HYPER, 255, 0,10,10,0,0);
gdk_pixbuf_render_to_drawable_alpha(composite_pb,
moon->pixmap, 0, 0, 0,
0, width, height,
GDK_PIXBUF_ALPHA_FULL,
128, GDK_RGB_DITHER_NORMAL, 0,
0);
gdk_pixbuf_unref(composite_pb);
composite_pb = NULL;
}
static gboolean
moon_applet_expose_event (GtkWidget *widget,
GdkEventExpose *event,
MoonApplet *moon)
{
g_return_val_if_fail (moon->pixmap != NULL, FALSE);
gdk_draw_pixmap (widget->window,
widget->style->fg_gc [GTK_WIDGET_STATE (widget)],
moon->pixmap,
event->area.x, event->area.y,
event->area.x, event->area.y,
event->area.width, event->area.height);
return FALSE;
}
/*******************************************************************************/
static gint
mouse_enter_cb(GtkWidget * widget, GdkEvent * e, MoonApplet * moon)
{
/* g_message("mouse enter event"); */
/* compose_image(moon, TRUE); */
gtk_widget_queue_draw(moon->drawing_area);
return TRUE;
}
static gint
mouse_leave_cb(GtkWidget * widget, GdkEvent * e, MoonApplet * moon)
{
/* g_message("mouse leave event"); */
/* compose_image(moon, FALSE); */
gtk_widget_queue_draw(moon->drawing_area);
return TRUE;
}
/*******************************************************************************/
static void
moon_applet_size_allocate (GtkWidget *widget,
GtkAllocation *allocation,
MoonApplet *moon)
{
if (widget->allocation.width != moon->prev_allocation.width ||
widget->allocation.height != moon->prev_allocation.height)
compose_image (moon);
moon->prev_allocation = *allocation;
}
static void
moon_applet_realize (GtkWidget *widget,
MoonApplet *moon)
{
if (!moon->pixmap)
compose_image (moon);
}
static void
moon_applet_unrealize (GtkWidget *widget,
MoonApplet *moon)
{
if (moon->pixmap)
g_object_unref (moon->pixmap);
moon->pixmap = NULL;
}
static void
moon_applet_change_orient (PanelApplet *applet,
PanelAppletOrient orientation)
{
MoonApplet *moon = (MoonApplet *) applet;
if (moon->orientation == orientation)
return;
moon->orientation = orientation;
if (moon->pixmap)
compose_image (moon);
}
static gboolean
handle_keypress (GtkWidget *widget,
GdkEventKey *event,
MoonApplet *moon)
{
switch (event->keyval) {
case GDK_space:
case GDK_KP_Space:
case GDK_Return:
case GDK_KP_Enter:
case GDK_ISO_Enter:
case GDK_3270_Enter:
display_moondata_dialog (moon);
break;
default:
return FALSE;
break;
}
return TRUE;
}
static gboolean
handle_button_press (GtkWidget *widget,
GdkEventButton *event,
MoonApplet *moon)
{
if (event->button != 1)
return FALSE;
display_moondata_dialog (moon);
return TRUE;
}
static void
setup_moon_widget (MoonApplet *moon)
{
GtkWidget *widget = (GtkWidget *) moon;
moon->frame = gtk_frame_new (NULL);
gtk_frame_set_shadow_type (GTK_FRAME (moon->frame), GTK_SHADOW_IN);
gtk_container_add (GTK_CONTAINER (widget), moon->frame);
moon->drawing_area = gtk_drawing_area_new ();
gtk_container_add (GTK_CONTAINER (moon->frame), moon->drawing_area);
g_signal_connect (moon->drawing_area, "realize",
G_CALLBACK (moon_applet_realize), moon);
g_signal_connect (moon->drawing_area, "unrealize",
G_CALLBACK (moon_applet_unrealize), moon);
g_signal_connect (moon->drawing_area, "size-allocate",
G_CALLBACK (moon_applet_size_allocate), moon);
g_signal_connect (moon->drawing_area, "expose-event",
G_CALLBACK (moon_applet_expose_event), moon);
gtk_widget_set_events ( moon->drawing_area,
gtk_widget_get_events (moon->drawing_area) |
GDK_BUTTON_PRESS_MASK | GDK_ENTER_NOTIFY_MASK |
GDK_LEAVE_NOTIFY_MASK );
g_signal_connect (moon->drawing_area, "button_press_event",
G_CALLBACK (handle_button_press), moon);
g_signal_connect(moon->drawing_area, "enter_notify_event",
G_CALLBACK(mouse_enter_cb), moon);
g_signal_connect(moon->drawing_area, "leave_notify_event",
G_CALLBACK(mouse_leave_cb), moon);
update_moon(moon);
load_moon_image (moon);
compose_image (moon);
set_tooltip (moon);
setup_timeout (moon);
g_signal_connect (moon, "key_press_event",
G_CALLBACK (handle_keypress), moon);
gtk_widget_show_all (widget);
}
static const BonoboUIVerb moon_menu_verbs [] = {
BONOBO_UI_UNSAFE_VERB ("Preferences", display_preferences_dialog),
BONOBO_UI_UNSAFE_VERB ("Help", display_help_dialog),
BONOBO_UI_UNSAFE_VERB ("About", display_about_dialog),
BONOBO_UI_VERB_END
};
static gboolean
moon_applet_fill (MoonApplet *moon)
{
PanelApplet *applet = (PanelApplet *) moon;
GError *error = NULL;
char *path = NULL;
moon->orientation = panel_applet_get_orient (applet);
panel_applet_add_preferences (
applet, "/schemas/apps/glunarclock_applet/prefs", NULL);
setup_gconf (moon);
moon->image = panel_applet_gconf_get_string (applet, "image", &error);
if (error) {
g_warning ("Error getting 'image' preference: %s", error->message);
g_error_free (error);
error = NULL;
}
if (!moon->image)
moon->image = g_strdup ( FALLBACK_MOONIMAGE_FILE ); /* Fallback */
path = gnome_program_locate_file (NULL, GNOME_FILE_DOMAIN_APP_PIXMAP,
ALTERNATIVE_MOONIMAGE_FILE, FALSE, NULL);
if((!strcmp (moon->image,ALTERNATIVE_MOONIMAGE_FILE)) || (!strcmp(moon->image, path)))
moon->rotation_type = MIRROR;
else
moon->rotation_type = ROTATE;
g_free(path);
moon->n_frames = panel_applet_gconf_get_int (applet, "frames", &error);
if (error) {
g_warning ("Error getting 'frames' preference: %s", error->message);
g_error_free (error);
error = NULL;
}
path = gnome_program_locate_file (NULL, GNOME_FILE_DOMAIN_APP_PIXMAP,
FALLBACK_MOONIMAGE_FILE, FALSE, NULL);
if (moon->n_frames <= 0 && ((!strcmp(moon->image, path)) ||
(!strcmp (moon->image, FALLBACK_MOONIMAGE_FILE ))))
moon->n_frames = FALLBACK_MOONIMAGE_FRAMES;
else if (moon->n_frames <= 0 && (moon->rotation_type == MIRROR))
moon->n_frames = ALTERNATIVE_MOONIMAGE_FRAMES;
else if (moon->n_frames <= 0)
moon->n_frames = 20; /* Fallback */
g_free(path);
moon->latitude = panel_applet_gconf_get_float (applet, "latitude", &error);
if (error) {
g_warning ("Error getting 'latitude' preference: %s", error->message);
g_error_free (error);
error = NULL;
moon->latitude = 50.7; /* Fallback */
}
if (moon->latitude <= 0)
moon->latitude = 0.0;
moon->longitude = panel_applet_gconf_get_float (applet, "longitude", &error);
if (error) {
g_warning ("Error getting 'longitude' preference: %s", error->message);
g_error_free (error);
error = NULL;
moon->longitude = 7.1; /* Fallback */
}
if (moon->longitude <= 0)
moon->longitude = 0.0;
moon->flip = panel_applet_gconf_get_bool (applet, "flip", &error);
if (error) {
g_warning ("Error getting 'flip' preference: %s", error->message);
g_error_free (error);
error = NULL;
moon->flip = TRUE; /* Fallback */
}
moon->is_north = panel_applet_gconf_get_bool (applet, "is_north", &error);
if (error) {
g_warning ("Error getting 'North South' preference: %s", error->message);
g_error_free (error);
error = NULL;
moon->is_north = TRUE; /* Fallback */
}
moon->is_east = panel_applet_gconf_get_bool (applet, "is_east", &error);
if (error) {
g_warning ("Error getting 'East West' preference: %s", error->message);
g_error_free (error);
error = NULL;
moon->is_east = TRUE; /* Fallback */
}
panel_applet_setup_menu_from_file (
applet, NULL, "GNOME_GLunarclockApplet.xml",
NULL, moon_menu_verbs, moon);
setup_moon_widget (moon);
return TRUE;
}
static gboolean
glunarclock_applet_factory (PanelApplet *applet,
const char *iid,
gpointer data)
{
gboolean retval = FALSE;
if (!strcmp (iid, "OAFIID:GNOME_GLunarclockApplet"))
retval = moon_applet_fill (MOON_APPLET (applet));
return retval;
}
static void
moon_applet_destroy (GtkObject *object)
{
MoonApplet *moon = (MoonApplet *) object;
int i;
if (moon->timeout)
g_source_remove (moon->timeout);
moon->timeout = 0;
for (i = 0; i < N_MOON_PREFS; i++) {
if (moon->client)
gconf_client_notify_remove (
moon->client, moon->listeners [i]);
moon->listeners [i] = 0;
}
if (moon->image)
g_free (moon->image);
moon->image = NULL;
if (moon->client)
g_object_unref (moon->client);
moon->client = NULL;
if (moon->pixmap)
g_object_unref (moon->pixmap);
moon->pixmap = NULL;
if (moon->image_pb)
g_object_unref (moon->image_pb);
moon->image_pb = NULL;
if (moon->hilit_image_pb)
g_object_unref (moon->hilit_image_pb);
moon->hilit_image_pb = NULL;
if (moon->about_dialog)
gtk_widget_destroy (moon->about_dialog);
moon->about_dialog = NULL;
if (moon->preferences_dialog)
gtk_widget_destroy (moon->preferences_dialog);
moon->preferences_dialog = NULL;
if (moon->moondata_dialog)
gtk_widget_destroy (moon->moondata_dialog);
moon->moondata_dialog = NULL;
destroy_tooltip (moon);
GTK_OBJECT_CLASS (parent_class)->destroy (object);
}
static void
moon_applet_instance_init (MoonApplet *moon,
MoonAppletClass *klass)
{
int i;
moon->client = gconf_client_get_default ();
moon->image = NULL;
moon->n_frames = 1;
moon->flip = FALSE;
moon->is_north = FALSE;
moon->is_east = FALSE;
moon->latitude = 0.0;
moon->longitude = 0.0;
moon->rotation_type = ROTATE;
moon->orientation = PANEL_APPLET_ORIENT_UP;
moon->frame = NULL;
moon->drawing_area = NULL;
moon->pixmap = NULL;
moon->timeout = 0;
moon->image_number = 0;
moon->prev_allocation.x = -1;
moon->prev_allocation.y = -1;
moon->prev_allocation.width = -1;
moon->prev_allocation.height = -1;
moon->image_pb = NULL;
moon->hilit_image_pb = NULL;
moon->about_dialog = NULL;
moon->preferences_dialog = NULL;
moon->pixmap_entry = NULL;
moon->image_entry = NULL;
moon->frames_spin = NULL;
moon->longitude_spin = NULL;
moon->latitude_spin = NULL;
moon->flip_toggle = NULL;
moon->lat_radio = NULL;
moon->long_radio = NULL;
moon->moondata_dialog = NULL;
for (i = 0; i < N_MOON_PREFS; i++)
moon->listeners [i] = 0;
panel_applet_set_flags (PANEL_APPLET (moon),
PANEL_APPLET_EXPAND_MINOR);
}
static void
moon_applet_class_init (MoonAppletClass *klass)
{
PanelAppletClass *applet_class = (PanelAppletClass *) klass;
GtkObjectClass *gtkobject_class = (GtkObjectClass *) klass;
parent_class = g_type_class_peek_parent (klass);
applet_class->change_orient = moon_applet_change_orient;
gtkobject_class->destroy = moon_applet_destroy;
}
static GType
moon_applet_get_type (void)
{
static GType type = 0;
if (!type) {
static const GTypeInfo info = {
sizeof (PanelAppletClass),
NULL, NULL,
(GClassInitFunc) moon_applet_class_init,
NULL, NULL,
sizeof (MoonApplet),
0,
(GInstanceInitFunc) moon_applet_instance_init,
NULL
};
type = g_type_register_static (
PANEL_TYPE_APPLET, "GLunarclockApplet", &info, 0);
}
return type;
}
PANEL_APPLET_BONOBO_FACTORY ("OAFIID:GNOME_GLunarclockApplet_Factory",
moon_applet_get_type (),
"glunarclock-applet-2",
"0",
glunarclock_applet_factory,
NULL)
syntax highlighted by Code2HTML, v. 0.9.1