#ifndef CODE_XCLOCK_CXX
#define CODE_XCLOCK_CXX

/*-----------------------------------------------------------------------
 * Xclasses code file
 * ($Id: xclock.cxx,v 1.4 2001/01/02 23:22:07 schmitzj Exp $)
 * 
 * Copyright (C) 1998 Jürgen Schmitz
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library 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
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA  02111-1307, USA.
 *-----------------------------------------------------------------------
 */

#include <math.h>
#include <time.h>
#include "types.h"
#include <Xclasses/gadget.h>
#include <Xclasses/Xcolors.h>
#include <Xclasses/Ddraw.h>
#include <Xclasses/xclock.h>
#include "../include/callback.h"
#include "include/xclock_p.h"

xclock::xclock(): gadget(), Ddraw(this)
{
	while (!(p=new pxclock))
	{
		outOfMemory("xclock");
	}
	p->o=this;
	Name("xclock");
}
pxclock::pxclock() : tcb()
{
	mx1=0; mx2=0;
	my1=0; my2=0;
	hx1=0; hx2=0;
	hy1=0; hy2=0;
	sx1=0; sx2=0;
	sy1=0; sy2=0;
	ot=0;
	lw=0;
	seconds=0;
	exact=0;
	small=0;
	nominutes=0;
	
	form=0;
}
pxclock::~pxclock()
{
}
xclock::~xclock()
{
	if (win) Free();
	if (p) delete p;
}
int xclock::Create(void)
{ 
	Background(col_selected());
	BorderSize(1);
	
    if (gadget::Create())
    {
        Mode(GM_ONEEXPOSE|GM_NORMALTICK);
        return 1;
    } 
    return 0;
}
//#define VX	-4
//#define VY	-4
#define VX	-(o->height/100)
#define VY	VX
void pxclock::zeiger(time_t t)
{
	struct tm *tmp;
	int mx,my,lx1,ly1,lx2,ly2,lx3,ly3;

	my=o->height>>1;
	ly1=my-o->height/25;
	ly2=my-o->height/15;
	ly3=my-o->height/5;

	mx=o->width>>1;
	lx1=mx-o->width/25;
	lx2=mx-o->width/15;
	lx3=mx-o->width/5;

	tmp=localtime(&t);

	if (ot)
	{
		XSetLineAttributes(o->display(),o->gc,2*lw,LineSolid,CapRound,JoinRound);

		XSetForeground(o->display(),o->gc,o->col_selected());
		XDrawLine(o->display(),o->win,o->gc,mx+mx1,my+my1,mx+mx2,my+my2); XSPEC;
		XDrawLine(o->display(),o->win,o->gc,mx+hx1,my+hy1,mx+hx2,my+hy2); XSPEC;
		XDrawLine(o->display(),o->win,o->gc,mx+sx1,my+sy1,mx+sx2,my+sy2); XSPEC;
		XDrawLine(o->display(),o->win,o->gc,mx+mx1+VX,my+my1+VY,mx+mx2+VX,my+my2+VY); XSPEC;
		XDrawLine(o->display(),o->win,o->gc,mx+hx1+VX,my+hy1+VY,mx+hx2+VX,my+hy2+VY); XSPEC;
		XDrawLine(o->display(),o->win,o->gc,mx+sx1+VX,my+sy1+VY,mx+sx2+VX,my+sy2+VY); XSPEC;
	}
	ot=t;

	char txt[50];
	if (tcb.iscallback())
	{
		tcb.call((void*)tmp,(void*)txt,(void*)sizeof(txt));
		XSetForeground(o->display(),o->gc,o->col_selected());
		XFillRectangle(o->display(),o->win,o->gc,o->RealSize(),my,o->width-o->RealSize()-o->RealSize(),my-o->RealSize());

//		o->borderlockedtext(o,o->RealSize(),my,o->width-o->RealSize()-o->RealSize(),my-o->RealSize(),txt,ADJUST_CENTER|ADJUST_TOP);
//		o->bordertext(o,o->RealSize(),my,o->width-o->RealSize()-o->RealSize(),my-o->RealSize(),txt,ADJUST_CENTER|ADJUST_TOP);
	}

	ziffern();

	sx1=X(tmp->tm_sec*6-90,lx1);
	sy1=Y(tmp->tm_sec*6-90,ly1);
	if (small)
	{
		sx2=X(tmp->tm_sec*6-90,lx1-o->width/8);
		sy2=Y(tmp->tm_sec*6-90,ly1-o->height/8);
	}
	else
	{
		sx2=0;
		sy2=0;
	}

	if (exact)
	{
		mx1=X(tmp->tm_min*6-90,lx2);
		my1=Y(tmp->tm_min*6-90,ly2);
	}
	else
	{
		mx1=X((tmp->tm_min*60+tmp->tm_sec)/10-90,lx2);
		my1=Y((tmp->tm_min*60+tmp->tm_sec)/10-90,ly2);
	}
	mx2=0;
	my2=0;

	hx1=X(((tmp->tm_hour%12)*60+tmp->tm_min)/2-90,lx3);
	hy1=Y(((tmp->tm_hour%12)*60+tmp->tm_min)/2-90,ly3);
	hx2=0;
	hy2=0;

	for(int i=0;i<2;i++)
	{
		if (i)
		{
			XSetForeground(o->display(),o->gc,o->col_white());
			mx+=VX;
			my+=VY;
		}
		else
		{
			XSetForeground(o->display(),o->gc,o->col_shadow());
		}

		XSetLineAttributes(o->display(),o->gc,lw,LineSolid,CapRound,JoinRound);
		XDrawLine(o->display(),o->win,o->gc,mx+mx1,my+my1,mx+mx2,my+my2); XSPEC;

		XSetLineAttributes(o->display(),o->gc,lw*2,LineSolid,CapRound,JoinRound);
		XDrawLine(o->display(),o->win,o->gc,mx+hx1,my+hy1,mx+hx2,my+hy2); XSPEC;

		if (seconds)
		{
			XSetLineAttributes(o->display(),o->gc,(lw+3)/4,LineSolid,CapRound,JoinRound);
			XDrawLine(o->display(),o->win,o->gc,mx+sx1,my+sy1,mx+sx2,my+sy2);
		}
	}

	if (tcb.iscallback())
	{
		int w=o->textlength(o,txt);
		int h=o->textheight(o,txt);
		o->borderEmbossFill(o,mx-(w>>1)-o->RealSize(),my,w+o->RealSize()*2+2,h+o->RealSize()*2+2);
		o->bordertext(o,o->RealSize(),my+o->RealSize()+1,o->width-o->RealSize()-o->RealSize(),my-o->RealSize(),txt,ADJUST_CENTER|ADJUST_TOP);
	}
}
void pxclock::ziffern(void)
{
	int x1,x2,y1,y2,mx,my,lx1,ly1,lx2,ly2;

	XSetLineAttributes(o->display(),o->gc,0,LineSolid,CapRound,JoinRound);
		
	lw=(o->width/70);

	my=o->height>>1;
	ly1=my-o->height/25;
	ly2=my-o->height/10;
	
	mx=o->width>>1;
	lx1=mx-o->width/25;
	lx2=my-o->width/10;

	XSetLineAttributes(o->display(),o->gc,lw,LineSolid,CapRound,JoinRound);
	XSetForeground(o->display(),o->gc,o->col_white());
	for(int w=0;w<360;w+=6)
	{
		x1=mx+X(w,lx1);
		y1=my+Y(w,ly1);
		if (w%30)
		{
			if (!nominutes)
			{
				x2=mx+X(w,lx1-1);
				y2=my+Y(w,ly1-1);
				XDrawLine(o->display(),o->win,o->gc,x1,y1,x2,y2); XSPEC;
			}
		}
		else
		{
			x2=mx+X(w,lx2);
			y2=my+Y(w,ly2);
			XDrawLine(o->display(),o->win,o->gc,x1,y1,x2,y2); XSPEC;
		}
	}
}
int pxclock::X(int w,int l)
{
	double c=0;
	switch (form)
	{
		case 0:
			c=cos(w*M_PI/180);
			break;
		case 1:
			c=cos(w*M_PI/180);
		    c=c-fabs(sin(w*M_PI/180))/4;
		    break;
		case 2:
			c=cos(w*M_PI/180);
			c=(c+(1-sin(w*M_PI/180))/2);
			break;
	}
	return (int)(l*c);
}
int pxclock::Y(int w,int l)
{
	double s=0;
	switch (form)
	{
		case 0:
			s=sin(w*M_PI/180);
			break;
		case 1:
			s=sin(w*M_PI/180);
			s=s-fabs(cos(w*M_PI/180))/4;
			break;
		case 2:
			s=sin(w*M_PI/180);
			s=(s+(1-cos(w*M_PI/180))/2);
			break;
	}
	return (int)(l*s);
}
void xclock::GExpose(XEvent *event)
{
	borderDownFill(this,0,0,width,height);
	time_t t;
	time(&t);
	p->ot=0; p->zeiger(t);
}
int xclock::GActivate(XEvent *event,int why)
{
	if (why==GA_TICK)
	{
		time_t t;
		time(&t);
		if (t!=p->ot)
		{
			p->zeiger(t);
		}
	}
	return 0;
}
int xclock::GSelected(XEvent *event,int why,int wasabove)
{
	return 0;
}
void xclock::GActionPress(int mx,int my,int rx,int ry,unsigned int state,int button,int reason)
{
}
void xclock::GActionRelease(int mx,int my,int rx,int ry,unsigned int state,int button,int reason)
{
}
void xclock::GSetLimits(void)
{
	minwidth=50;
	minheight=50;
	minxaspect=1;
	minyaspect=1;
	maxxaspect=1;
	maxyaspect=1;
}
void xclock::TextCallback(void cfunc(struct tm *tm,char *buf,int maxsize))
{
	p->tcb.set((CBCAST) cfunc);
}
void xclock::TextCallback(callable *cl,void (callable::*cfunc)(struct tm *tm,char *buf,int maxsize))
{
	p->tcb.set(cl,(CALLFUNCTION) cfunc);
}

void xclock::Seconds(void)		{ p->seconds=1; };
void xclock::NoSeconds(void)	{ p->seconds=0; };
void xclock::ExactMinutes(void)	{ p->exact=1; };
void xclock::NiceMinutes(void)	{ p->exact=0; };
void xclock::SmallSeconds(void)	{ p->small=1; };
void xclock::LongSeconds(void)	{ p->small=0; };
void xclock::NoMinutes(void)	{ p->nominutes=1; };
void xclock::Minutes(void)		{ p->nominutes=0; };

void xclock::FormCircel(void)	{ p->form=0; };
void xclock::FormCrazy(void)	{ p->form=1; };

#endif
