/* Gtk Widget Factory generated widget
* http://gwf.sourceforge.net
* Copyright (c) 1999-2000 Jeroen Benckhuijsen
*/
/* This file is Copyrighted (C) 1999-2000 by Ishan Chattopadhyaya (ishanchattopadhyaya@hclinfinet.com)
* Please read the license agreement below
*/
/* 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.
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <gtk/gtk.h>
#include "gtkclock.h"
#include <math.h>
static GtkObjectClass *parent_class = NULL;
static void gtk_clock_class_init (GtkClockClass *klass);
static void gtk_clock_init (GtkClock *clock);
static void gtk_clock_destroy (GtkObject *object);
static void gtk_clock_draw (GtkWidget *widget, GdkRectangle *area);
static void gtk_clock_size_request (GtkWidget *widget, GtkRequisition *req);
static void gtk_clock_realize (GtkWidget *widget);
int get_current_time (int *hr, int *mn, int *sc);
void gtk_clock_obtain_coordinates (int *xcood, int *ycood, int h, int k, int value, int max_radius, int max_val);
guint
gtk_clock_get_type (void)
{
static guint gtk_clock_type = 0;
if (!gtk_clock_type)
{
GtkTypeInfo gtk_clock_info =
{
"GtkClock",
sizeof (GtkClock),
sizeof (GtkClockClass),
(GtkClassInitFunc) gtk_clock_class_init,
(GtkObjectInitFunc) gtk_clock_init,
/* reserved_1 */ NULL,
/* reserved_2 */ NULL,
(GtkClassInitFunc) NULL,
};
gtk_clock_type = gtk_type_unique (gtk_widget_get_type (), >k_clock_info);
}
return gtk_clock_type;
}
static void
gtk_clock_class_init (GtkClockClass *klass)
{
GtkObjectClass *object_class;
GtkWidgetClass *widget_class;
object_class = (GtkObjectClass*) klass;
widget_class = (GtkWidgetClass*) klass;
object_class->destroy = gtk_clock_destroy;
parent_class = gtk_type_class (gtk_widget_get_type());
widget_class->realize = gtk_clock_realize;
widget_class->size_request = gtk_clock_size_request;
}
static void
gtk_clock_init (GtkClock *clock)
{
/* Start the clock, refresh every 1ms */
gtk_timeout_add (1, gtk_clock_construct, (gpointer)(clock));
}
static void
gtk_clock_destroy (GtkObject *object)
{
parent_class->destroy(object);
}
GtkWidget*
gtk_clock_new(void)
{
GtkWidget *clock;
clock = GTK_WIDGET( gtk_type_new ( gtk_clock_get_type()));
return clock;
}
static void gtk_clock_size_request (GtkWidget *widget,
GtkRequisition *req)
{
req->width = 200; // Default value
req->height = 200; // Default value
}
static void gtk_clock_realize (GtkWidget *widget)
{
GtkClock *darea;
GdkWindowAttr attributes;
gint attributes_mask;
g_return_if_fail (widget != NULL);
g_return_if_fail (GTK_IS_CLOCK (widget));
darea = GTK_CLOCK (widget);
GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
attributes.window_type = GDK_WINDOW_CHILD;
attributes.x = widget->allocation.x;
attributes.y = widget->allocation.y;
attributes.width = widget->allocation.width;
attributes.height = widget->allocation.height;
attributes.wclass = GDK_INPUT_OUTPUT;
attributes.visual = gtk_widget_get_visual (widget);
attributes.colormap = gtk_widget_get_colormap (widget);
attributes.event_mask = gtk_widget_get_events (widget) | GDK_EXPOSURE_MASK;
attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
widget->window = gdk_window_new (gtk_widget_get_parent_window (widget), &attributes, attributes_mask);
gdk_window_set_user_data (widget->window, darea);
widget->style = gtk_style_attach (widget->style, widget->window);
gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
}
gint
gtk_clock_construct (gpointer data)
{
GtkClock *clock = data;
if (!GTK_WIDGET_DRAWABLE (clock))
return 0;
get_current_time ( &clock->hour, &clock->min, &clock->sec );
gtk_clock_draw (GTK_WIDGET(clock), NULL);
return 1;
}
static void
gtk_clock_draw (GtkWidget *widget, GdkRectangle *area)
{
GtkClock *clock;
int loop1;
int max_radius;
int min=0, hour=0, sec=0;
int yc, xc;
int alloc_width, alloc_height;
GdkColor colors[4];
GdkGC *clock_gc = gdk_gc_new (widget->window);
if (GTK_WIDGET_DRAWABLE (widget))
{
clock = GTK_CLOCK (widget);
alloc_width = widget->allocation.width - 1;
alloc_height = widget->allocation.height - 1;
gdk_window_clear_area (widget->window, 0, 0, alloc_width, alloc_height);
gdk_color_parse("Red", &colors[0]);
gdk_color_parse("DarkGreen", &colors[1]);
gdk_color_parse("RoyalBlue", &colors[2]);
gdk_color_parse("Black", &colors[3]);
min = clock->min; hour = clock->hour; sec = clock->sec;
max_radius = (alloc_width < alloc_height)? (alloc_width/2) : (alloc_height/2);
for (loop1=0; loop1<60; loop1+=5)
{
gtk_clock_obtain_coordinates (&xc, &yc, max_radius, max_radius, loop1, max_radius-10, 60);
gdk_gc_set_line_attributes (clock_gc, 10, GDK_LINE_SOLID, 0, 0);
gdk_draw_line (widget->window, widget->style->black_gc, xc, yc,xc+1,yc+1);
gdk_draw_line (widget->window, widget->style->black_gc, xc+1, yc,xc,yc+1);
}
gdk_gc_set_line_attributes (clock_gc, 2, GDK_LINE_SOLID, 0, 0);
/* Obtain coordinates for minute and draw a line from center to that point */
gtk_clock_obtain_coordinates (&xc, &yc, max_radius, max_radius, min, max_radius, 60);
gdk_colormap_alloc_color (gdk_colormap_get_system(), &colors[0], FALSE, TRUE);
gdk_gc_set_foreground (clock_gc, colors+0); /* Red */
gdk_draw_line (widget->window, clock_gc, xc, yc, max_radius, max_radius);
/* Obtain coordinates for hour and draw a line from center to that point */
gtk_clock_obtain_coordinates (&xc, &yc, max_radius, max_radius, (hour!=12)?hour*60+min:min, max_radius*0.65, 12*60);
gdk_colormap_alloc_color (gdk_colormap_get_system(), &colors[1], FALSE, TRUE);
gdk_gc_set_foreground (clock_gc, colors+1); /* Green */
gdk_draw_line (widget->window, clock_gc, xc, yc, max_radius, max_radius);
/* Obtain coordinates for seconds and draw a line from center to that point */
gtk_clock_obtain_coordinates (&xc, &yc, max_radius, max_radius, sec, max_radius*.85, 60);
gdk_colormap_alloc_color (gdk_colormap_get_system(), &colors[2], FALSE, TRUE);
gdk_gc_set_foreground (clock_gc, colors+2); /* Blue */
gdk_draw_line (widget->window, clock_gc, xc, yc, max_radius, max_radius);
}
}
/* ----------------------------------------------------------------------------------*/
/* UTILITY FUNCTIONS */
// TODO: replace this function with a better one. Due to lack of time,
// this one is still buggy.
int get_current_time (int *hr, int *mn, int *sc)
{
long hour = *hr, min = *mn, sec= *sc;
hour = time(NULL);
min=hour; sec = hour; sec=hour%60;
min=min-min%60; min=min/60; min=min%60;
hour=hour/(60*60); hour=hour%12; hour = (hour+6)%12;
if (min<30) min = min+30;
else min = min-30;
if(!hour) hour=12; if (min>30) hour--; if(hour<1) hour=12;
*sc = sec; *mn = min; *hr = hour;
return 1;
}
void gtk_clock_obtain_coordinates (int *xcood, int *ycood, int h, int k, int value, int max_radius, int max_val)
{
int yc=*ycood, xc=*xcood, f;
float t=0, s=0;
t=(float)(value*360.0/(float)max_val) * 3.14159/180;
s=sin(t/2);
yc=(int)(k+ 2*max_radius*(pow(s,2)) -max_radius);
f=-max_radius*max_radius+h*h+(yc-k)*(yc-k);
if (value<max_val/2)
xc=h + (float)(pow(h*h-f, .5));
else
xc=h - (float)(pow(h*h-f, .5));
*ycood=yc; *xcood=xc;
}