/* 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 (Gnome Fish Applet) * Mark McLoughlin (Gnome Fish Applet) * Josh Buhl */ #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 "); 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; iimage) 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; ihilit_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)