/* gkrellsun.c * Copyright (C) 2001, Norman Walsh. Derived from gkrellmoon by * Dale P. Smith and wmSun by Mike Henderson * * $Id: gkrellsun.c,v 1.2 2001/11/10 15:08:47 ndw Exp $ * */ #include #include "uvsun.xpm" #include "digits.xpm" #define SUN_XPM uvsun_xpm #define HEIGHT 55 #define SUN_WIDTH 54 #define SUN_HEIGHT 54 #define SUN_COUNT 1 #define DIGIT_WIDTH 7 #define DIGIT_HEIGHT 11 #define DIGIT_COUNT 15 #define DIGIT_COLON 10 #define DIGIT_DASH 11 #define DIGIT_AM 12 #define DIGIT_PM 13 #define DIGIT_SPACE 14 #define STYLE_NAME "sun" #define PLUGIN_CONFIG_KEYWORD "sun" #define SUNCLOCK_MAJOR_VERSION 0 #define SUNCLOCK_MINOR_VERSION 2 typedef struct { int longitude; int latitude; } Options; static Panel *panel; static Options options; static gint style_id; static GtkWidget *longitude_spin_button; static GtkWidget *latitude_spin_button; static GdkPixmap *sun_image = NULL; static GdkBitmap *sun_mask = NULL; static Decal *sun = NULL; static GdkPixmap *digit_image = NULL; static GdkBitmap *digit_mask = NULL; #define RISEHOUR_X 16 #define RISEHOUR_Y 10 static Decal *riseHour10 = NULL; static Decal *riseHour01 = NULL; static Decal *riseHourC = NULL; static Decal *riseMin10 = NULL; static Decal *riseMin01 = NULL; static Decal *riseTimeAP = NULL; #define SETHOUR_X 16 #define SETHOUR_Y 36 static Decal *setHour10 = NULL; static Decal *setHour01 = NULL; static Decal *setHourC = NULL; static Decal *setMin10 = NULL; static Decal *setMin01 = NULL; static Decal *setTimeAP = NULL; static GtkTooltips *tooltip; #include "CalcEphem.h" extern void SunRise(int, int, int, double, double *, double *); typedef struct CTrans SunData; typedef struct _Sun Sun; struct _Sun { SunData data; }; static Sun sununit; double Glon, SinGlat, CosGlat, TimeZone; static void update_tooltip(Sun *sun); static void update_sun_data(Sun * sun) { struct tm *time_struc; /* The tm struct is defined in */ time_t current_gmt; gdouble local_std_time, univ_time, eot; glong date; gint day_of_month, month, year; current_gmt = time(CurrentTime); /* CurrentTime defined in */ time_struc = gmtime(¤t_gmt); univ_time = time_struc->tm_hour + time_struc->tm_min / 60.0 + time_struc->tm_sec / 3600.0; /* The date needs to be the date in UTC, i.e. in greenwich, so * be sure not to call the localtime function until after date * has been set (there's only one tm structure). */ year = time_struc->tm_year + 1900; month = time_struc->tm_mon + 1; day_of_month = time_struc->tm_mday; date = year * 10000 + month * 100 + day_of_month; time_struc = localtime(¤t_gmt); local_std_time = time_struc->tm_hour + time_struc->tm_min / 60.0 + time_struc->tm_sec / 3600.0; sun->data.Glat = options.latitude; sun->data.Glon = options.longitude; CalcEphem(date, univ_time, &sun->data); sun->data.LST = local_std_time; sun->data.LMT = univ_time - sun->data.Glon / 15.0; if (sun->data.LMT < 0.0) sun->data.LMT += 24.0; if (sun->data.LMT > 24.0) sun->data.LMT -= 24.0; /* eot is the equation of time. gmst is Greenwich Sidereal * Time. This equation below is correct, but confusing at * first. It's easy to see when you draw the following * picture: A sphere with 0 and 180 degree longitude, North on * top, a meridian for the real sun, a meridian for a fictive * average sun, a meridian denoting the vernal equinox. Note * that universal time is the hour angle between 180 degrees * and the fictive sun's meridian measured clockwise. gmst is * the hour angle between 0 degrees and the meridian of the * vernal equinox measured clockwise. RA_sun/15.0 is the hour * angle of the real sun measured counterclockwise from the * vernal equinox. eot is the difference between the real and * the fictive sun. Looking at the picture, it's easy to see * that 12=RA_sun/15-gmst+eot+utc (12 hours = 180 deg.) */ eot = 12.0 - univ_time + sun->data.gmst - sun->data.RA_sun / 15.0; if (eot < 0.0) eot += 24.0; if (eot > 24.0) eot -= 24.0; sun->data.LAT = sun->data.LMT + eot; if (sun->data.LAT < 0.0) sun->data.LAT += 24.0; if (sun->data.LAT > 24.0) sun->data.LAT -= 24.0; update_tooltip(sun); } static int sun_image_number(Sun * sun) { return 0; } static void sun_update_plugin() { static int image_number; double val; int H, M; int am = 1; /* Draw plugin specific data on the chart */ /* Use xlib or gdk functions, or gkrellm_draw_chart() if applicable */ if (GK.minute_tick) { update_sun_data(&sununit); } image_number = sun_image_number(&sununit); gkrellm_draw_decal_pixmap(panel, sun, image_number); if (sununit.data.Rise) { val = sununit.data.LTRise; H = (int)val; val = (val-H)*60.0; M = (int)val; if (H >= 12) { am = 0; if (H > 12) { H -= 12; } } gkrellm_draw_decal_pixmap(panel, riseHour10, (int)(H / 10)); gkrellm_draw_decal_pixmap(panel, riseHour01, H % 10); gkrellm_draw_decal_pixmap(panel, riseHourC, DIGIT_COLON); gkrellm_draw_decal_pixmap(panel, riseMin10, (int)(M / 10)); gkrellm_draw_decal_pixmap(panel, riseMin01, M % 10); if (am) { gkrellm_draw_decal_pixmap(panel, riseTimeAP, DIGIT_AM); } else { gkrellm_draw_decal_pixmap(panel, riseTimeAP, DIGIT_PM); } } else { gkrellm_draw_decal_pixmap(panel, riseHour10, DIGIT_DASH); gkrellm_draw_decal_pixmap(panel, riseHour01, DIGIT_DASH); gkrellm_draw_decal_pixmap(panel, riseHourC, DIGIT_COLON); gkrellm_draw_decal_pixmap(panel, riseMin10, DIGIT_DASH); gkrellm_draw_decal_pixmap(panel, riseMin01, DIGIT_DASH); gkrellm_draw_decal_pixmap(panel, riseTimeAP, DIGIT_SPACE); } am = 1; if (sununit.data.Set) { val = sununit.data.LTSet; H = (int)val; val = (val-H)*60.0; M = (int)val; if (H >= 12) { am = 0; if (H > 12) { H -= 12; } } gkrellm_draw_decal_pixmap(panel, setHour10, (int)(H / 10)); gkrellm_draw_decal_pixmap(panel, setHour01, H % 10); gkrellm_draw_decal_pixmap(panel, setHourC, DIGIT_COLON); gkrellm_draw_decal_pixmap(panel, setMin10, (int)(M / 10)); gkrellm_draw_decal_pixmap(panel, setMin01, M % 10); if (am) { gkrellm_draw_decal_pixmap(panel, setTimeAP, DIGIT_AM); } else { gkrellm_draw_decal_pixmap(panel, setTimeAP, DIGIT_PM); } } else { gkrellm_draw_decal_pixmap(panel, setHour10, DIGIT_DASH); gkrellm_draw_decal_pixmap(panel, setHour01, DIGIT_DASH); gkrellm_draw_decal_pixmap(panel, setHourC, DIGIT_COLON); gkrellm_draw_decal_pixmap(panel, setMin10, DIGIT_DASH); gkrellm_draw_decal_pixmap(panel, setMin01, DIGIT_DASH); gkrellm_draw_decal_pixmap(panel, setTimeAP, DIGIT_SPACE); } gkrellm_draw_layers(panel); } static void update_tooltip(Sun *sun) { GString *mboxes = NULL; gchar buf[128]; double val; int H,M; if (tooltip == NULL) return; mboxes = g_string_sized_new(512); snprintf(buf, sizeof(buf), "Location: %d lat %d lon\n", options.latitude, options.longitude); g_string_append(mboxes, buf); if (sun->data.Rise) { val = sun->data.LTRise; H = (int)val; val = (val-H)*60.0; M = (int)val; if (H >= 12) { if (H > 12) { H -= 12; } snprintf(buf, sizeof(buf), "Sunrise: %d:%02dp\n", H, M); } else { snprintf(buf, sizeof(buf), "Sunrise: %d:%02da\n", H, M); } } else { snprintf(buf, sizeof(buf), "Sunrise: never\n"); } g_string_append(mboxes, buf); if (sun->data.Set) { val = sun->data.LTSet; H = (int)val; val = (val-H)*60.0; M = (int)val; if (H >= 12) { if (H > 12) { H -= 12; } snprintf(buf, sizeof(buf), "Sunset: %d:%02dp\n", H, M); } else { snprintf(buf, sizeof(buf), "Sunset: %d:%02da\n", H, M); } } else { snprintf(buf, sizeof(buf), "Sunset: never\n"); } g_string_append(mboxes, buf); gtk_tooltips_set_tip(tooltip, panel->drawing_area, mboxes->str, NULL); gtk_tooltips_set_delay(tooltip, 750); gtk_tooltips_enable(tooltip); if (mboxes) g_string_free(mboxes, TRUE); } static gint panel_expose_event(GtkWidget *widget, GdkEventExpose *ev) { gdk_draw_pixmap(widget->window, widget->style->fg_gc[GTK_WIDGET_STATE (widget)], panel->pixmap, ev->area.x, ev->area.y, ev->area.x, ev->area.y, ev->area.width, ev->area.height); return FALSE; } static void load_images() { GdkImlibImage *image = NULL; gkrellm_load_image(NULL, SUN_XPM, &image, NULL); gkrellm_render_to_pixmap(image, &sun_image, &sun_mask, 0, 0); gkrellm_load_image(NULL, digits_xpm, &image, NULL); gkrellm_render_to_pixmap(image, &digit_image, &digit_mask, 0, 0); } static void sun_create_plugin(GtkWidget *vbox, gint first_create) { Style *style = NULL; int image_x_offset; int image_y_offset; load_images(); if (first_create) panel = gkrellm_panel_new0(); else { gkrellm_destroy_decal_list(panel); } style = gkrellm_meter_style(style_id); image_x_offset = (gkrellm_chart_width() - SUN_WIDTH) / 2; image_y_offset = (HEIGHT - SUN_HEIGHT) / 2; sun = gkrellm_create_decal_pixmap(panel, sun_image, sun_mask, SUN_COUNT, style, image_x_offset, image_y_offset); image_x_offset = RISEHOUR_X; image_y_offset = RISEHOUR_Y; riseHour10 = gkrellm_create_decal_pixmap(panel, digit_image, digit_mask, DIGIT_COUNT, style, image_x_offset, image_y_offset); image_x_offset += DIGIT_WIDTH; riseHour01 = gkrellm_create_decal_pixmap(panel, digit_image, digit_mask, DIGIT_COUNT, style, image_x_offset, image_y_offset); image_x_offset += DIGIT_WIDTH - 2; riseHourC = gkrellm_create_decal_pixmap(panel, digit_image, digit_mask, DIGIT_COUNT, style, image_x_offset, image_y_offset); image_x_offset += DIGIT_WIDTH - 3; riseMin10 = gkrellm_create_decal_pixmap(panel, digit_image, digit_mask, DIGIT_COUNT, style, image_x_offset, image_y_offset); image_x_offset += DIGIT_WIDTH; riseMin01 = gkrellm_create_decal_pixmap(panel, digit_image, digit_mask, DIGIT_COUNT, style, image_x_offset, image_y_offset); image_x_offset += DIGIT_WIDTH; riseTimeAP = gkrellm_create_decal_pixmap(panel, digit_image, digit_mask, DIGIT_COUNT, style, image_x_offset, image_y_offset); image_x_offset = SETHOUR_X; image_y_offset = SETHOUR_Y; setHour10 = gkrellm_create_decal_pixmap(panel, digit_image, digit_mask, DIGIT_COUNT, style, image_x_offset, image_y_offset); image_x_offset += DIGIT_WIDTH; setHour01 = gkrellm_create_decal_pixmap(panel, digit_image, digit_mask, DIGIT_COUNT, style, image_x_offset, image_y_offset); image_x_offset += DIGIT_WIDTH - 2; setHourC = gkrellm_create_decal_pixmap(panel, digit_image, digit_mask, DIGIT_COUNT, style, image_x_offset, image_y_offset); image_x_offset += DIGIT_WIDTH - 3; setMin10 = gkrellm_create_decal_pixmap(panel, digit_image, digit_mask, DIGIT_COUNT, style, image_x_offset, image_y_offset); image_x_offset += DIGIT_WIDTH; setMin01 = gkrellm_create_decal_pixmap(panel, digit_image, digit_mask, DIGIT_COUNT, style, image_x_offset, image_y_offset); image_x_offset += DIGIT_WIDTH; setTimeAP = gkrellm_create_decal_pixmap(panel, digit_image, digit_mask, DIGIT_COUNT, style, image_x_offset, image_y_offset); panel->textstyle = gkrellm_meter_textstyle(style_id); panel->label->h_panel = HEIGHT; /* Whatever height you need */ gkrellm_create_panel(vbox, panel, gkrellm_bg_meter_image(style_id)); gkrellm_monitor_height_adjust(panel->h); if (first_create) { gtk_signal_connect(GTK_OBJECT(panel->drawing_area), "expose_event", (GtkSignalFunc) panel_expose_event, NULL); tooltip=gtk_tooltips_new(); } update_sun_data(&sununit); gkrellm_draw_decal_pixmap(panel, sun, sun_image_number(&sununit)); gkrellm_draw_layers(panel); } static void sun_create_tab(GtkWidget *tab_vbox) { GtkWidget *tabs; GtkWidget *vbox; tabs = gtk_notebook_new(); gtk_notebook_set_tab_pos(GTK_NOTEBOOK(tabs), GTK_POS_TOP); gtk_box_pack_start(GTK_BOX(tab_vbox), tabs, TRUE, TRUE, 0); /* --Setup Tab */ vbox = gkrellm_create_tab(tabs, _("Setup")); gkrellm_spin_button(vbox, &longitude_spin_button, (gfloat) options.longitude, -180.0, 180.0, 1.0, 1.0, 0, 60, NULL, NULL, FALSE, _("Longitude (decimal degrees + = W, - = E)")); gkrellm_spin_button(vbox, &latitude_spin_button, (gfloat) options.latitude, -90.0, 90.0, 1.0, 1.0, 0, 60, NULL, NULL, FALSE, _("Latitude (decimal degrees + = N, - = S)")); /* ----------------- about text --------------------*/ { gchar *plugin_about_text; GtkWidget *label, *text; plugin_about_text = g_strdup_printf( "SunClock %d.%d\n" "GKrellM SunClock Plugin\n\n" "Copyright (C) 2001 Norman Walsh\n" "ndw@nwalsh.com\n\n" "Derived from MoonClock 0.3 Copyright (C) 2001 Dale P. Smith\n" "and wmSun 1.03 Copyright (C) 1999 Mike Hnderson\n\n" "Released under the GNU Public Licence", SUNCLOCK_MAJOR_VERSION, SUNCLOCK_MINOR_VERSION); text = gtk_label_new(plugin_about_text); label = gtk_label_new("About"); gtk_notebook_append_page(GTK_NOTEBOOK(tabs),text,label); g_free(plugin_about_text); } } static void sun_apply_config() { options.longitude = gtk_spin_button_get_value_as_int( GTK_SPIN_BUTTON(longitude_spin_button)); options.latitude = gtk_spin_button_get_value_as_int( GTK_SPIN_BUTTON(latitude_spin_button)); } static void sun_save_config (FILE *f) { fprintf(f, "%s longitude %d\n", PLUGIN_CONFIG_KEYWORD, options.longitude); fprintf(f, "%s latitude %d\n", PLUGIN_CONFIG_KEYWORD, options.latitude); } static void sun_load_config (gchar *arg) { gchar config[64], item[256]; gint n; n = sscanf(arg, "%s %[^\n]", config, item); if (n != 2) return; if (strcmp(config, "longitude") == 0) sscanf(item, "%d\n", &(options.longitude)); if (strcmp(config, "latitude") == 0) sscanf(item, "%d\n", &(options.latitude)); } static Monitor plugin_mon = { "Sun Clock", /* Name, for config tab. */ 0, /* Id, 0 if a plugin */ sun_create_plugin, /* The create_plugin() function */ sun_update_plugin, /* The update_plugin() function */ sun_create_tab, /* The create_plugin_tab() config function */ sun_apply_config, /* The apply_plugin_config() function */ sun_save_config, /* The save_plugin_config() function */ sun_load_config, /* The load_plugin_config() function */ PLUGIN_CONFIG_KEYWORD, /* config keyword */ NULL, /* Undefined 2 */ NULL, /* Undefined 1 */ NULL, /* private */ MON_INSERT_AFTER|MON_CLOCK, /* Insert plugin before this monitor. */ NULL, /* Handle if a plugin, filled in by GKrellM */ NULL /* path if a plugin, filled in by GKrellM */ }; Monitor * init_plugin(void) { options.longitude = 72; /* Where I live! */ options.latitude = 42; style_id = gkrellm_add_meter_style(&plugin_mon, STYLE_NAME); return &plugin_mon; }