/* 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 <gkrellm/gkrellm.h>
#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.h> */
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 <X11/X.h> */
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;
}
syntax highlighted by Code2HTML, v. 0.9.1