#ifndef CODE_INDICATOR_CXX
#define CODE_INDICATOR_CXX

/*-----------------------------------------------------------------------
 * Xclasses code file
 * ($Id: indicator.cxx,v 1.5 1998/12/31 00:53:49 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 <string.h>
#include <math.h>
#include "types.h"
#include <Xclasses/gadget.h>
#include <Xclasses/Xcolors.h>
#include <Xclasses/Ddraw.h>
#include <Xclasses/indicator.h>
#include "include/indicator_p.h"


#define BORDERSIZE	1
#define PBORDER		(o->RealSize())
#define BORDER		(RealSize())

indicator::indicator(void) : gadget(), Ddraw(this)
{
	while (!(p=new pindicator))
	{
		outOfMemory("indicator");
	}
	p->o=this;
	Name("indicator");
	BorderSize(BORDERSIZE);
	NoKeyBorder();
}
pindicator::pindicator()
{
	fasc=-1;
	maxvalue=100;
	value=0;
	title=NULL;
	text=NULL;
	orig=pindicator::HORIZ;
	mark=0;
}
pindicator::~pindicator()
{
}
indicator::~indicator()
{
	if (win) Free();
	if (p) delete p;
}
void indicator::VertIndicator(void)
{
	p->orig=pindicator::VERT;
}
void indicator::HorizIndicator(void)
{
	p->orig=pindicator::HORIZ;
}
void indicator::CircleIndicator(void)
{
	p->orig=pindicator::CIRCLE;
}
void indicator::Title(char *t)
{
	p->title=t;
	if (win) GExpose(NULL);
}
int indicator::Create(void)
{
	Background(col_background());
	if (!setlimit) GSetLimits();

    if (gadget::Create())
    {
//        MCursor(XC_sailboat); 
        Mode(GM_ONEEXPOSE);
        return 1;
    }
    return 0;

}
void indicator::Value(int v)
{
	p->value=v;
	if (p->value<0) p->value=0;
	if (p->value>p->maxvalue) p->value=p->maxvalue;	
	if (win) p->update();
}
void indicator::Value(int v,char *t)
{
	p->value=v;
	if (p->value<0) p->value=0;
	if (p->value>p->maxvalue) p->value=p->maxvalue;	
	p->text=t;	
	if (win) p->update();
}
void indicator::Text(char *t)
{
	p->text=t;
	if (win) p->update();
}
void pindicator::update(void)
{
	if (fasc==-1) 
	{
		o->GExpose(NULL);
		return;
	}

	if (orig==HORIZ)
	{
		int v;
		v=((o->width-PBORDER-PBORDER)*(100*value/maxvalue))/100;
		if (v>(o->width-PBORDER-PBORDER)) v=(o->width-PBORDER-PBORDER);
		if (v<0) v=0;

		if (v>0)
		{
			XSetForeground(o->display(),o->gc,o->col_active());
			XFillRectangle(o->display(),o->win,o->gc,PBORDER,PBORDER*2+h,
						   v,o->height-h-PBORDER-PBORDER*2);
			o->borderUp(o,PBORDER,PBORDER+h,v,o->height-h-PBORDER-PBORDER);
			XSPEC;
		}
		if (v<(o->width-2-PBORDER-PBORDER))
		{
			XSetForeground(o->display(),o->gc,o->col_background());
			XFillRectangle(o->display(),o->win,o->gc,PBORDER+v+1,PBORDER+h,
						   o->width-PBORDER-(PBORDER+v+1),o->height-h-PBORDER-PBORDER);
			XSPEC;
		}
		if (mark>0)
		{
			int x=0,i=0;
			XSetForeground(o->display(),o->gc,o->col_darkbackground());		
			while (x<(o->width-PBORDER-PBORDER) && i<maxvalue)
			{
				x=PBORDER+((o->width-PBORDER-PBORDER)*(1000*i/maxvalue))/1000;
				XDrawLine(o->display(),o->win,o->gc,x,PBORDER+h,x,o->height-PBORDER-1); XSPEC;
				i+=mark;
			}
		}
		if (text && (o->height-h-2-PBORDER-PBORDER)>(fdec+fasc))
		{
			o->bordertext(o,0,h,o->width,o->height-h,text);
		}
	}
	else if (orig==CIRCLE)
	{
		int mx,my,v;

		v=(1000*value/maxvalue)*23040/1000;
		if (v>23040) v=23040;
		if (v<0) v=0;

		my=h;
		mx=PBORDER+1+o->width/2-(o->height-h)/2;

		XSetArcMode(o->display(),o->gc,ArcPieSlice);

		if (v<23040)
		{
			XSetForeground(o->display(),o->gc,o->col_selected());
			XFillArc(o->display(),o->win,o->gc,mx,my,o->height-h-(PBORDER+1)*2,o->height-h-(PBORDER+1)*2,64*90,23040-v); XSPEC;
		}
		if (v>0)
		{
			XSetForeground(o->display(),o->gc,o->col_active());
			XFillArc(o->display(),o->win,o->gc,mx,my,o->height-h-(PBORDER+1)*2,o->height-h-(PBORDER+1)*2,64*90,-v); XSPEC;
		}
		if (mark>0)
		{
			int v=0,i=0,x1,y1,x2,y2;
			y1=my+(o->height-h-(PBORDER+1)*2)/2;
			x1=mx+(o->height-h-(PBORDER+1)*2)/2;

			XSetForeground(o->display(),o->gc,o->col_darkbackground());		
			while (v<360 && i<maxvalue)
			{
				v=90-(1000*i/maxvalue)*360/1000;
				x2=x1+(int)((o->height-h-(PBORDER+1)*2)*cos(v*M_PI/180))/2;
				y2=y1+(int)((o->height-h-(PBORDER+1)*2)*sin(v*M_PI/180))/2;
				XDrawLine(o->display(),o->win,o->gc,x1,y1,x2,y2); XSPEC;
				i+=mark;
			}
		}
		XSetForeground(o->display(),o->gc,o->col_text());
		XDrawArc(o->display(),o->win,o->gc,mx,my,o->height-h-(PBORDER+1)*2,o->height-h-(PBORDER+1)*2,0,23040); XSPEC;

		if (text && (o->height-h-(PBORDER+1)*2)>(fdec+fasc))
		{
			o->borderselectedtext(o,mx,my,o->height-h-(PBORDER+1)*2,o->height-h-(PBORDER+1)*2,text);
		}
	}
}

void indicator::GExpose(XEvent *event)
{
	XCharStruct cs;
	int dhint;

	XTextExtents(gg_font(),"O",1,&dhint,&p->fasc,&p->fdec,&cs);
	if (p->title)	
	{
		p->h=p->fasc+p->fdec+3+BORDER;
		bordertext(this,0,BORDER,width,p->fasc+p->fdec,p->title);
	}
	else
	{
		p->h=0;
	}
	if (p->orig==pindicator::CIRCLE)
	{
		borderDown(this,0,0,width,height);
	}
	else
	{
		borderDown(this,0,p->h,width,height-p->h);
	}

	p->update();
}
void indicator::GSetLimits(void)
{
	int w=0,h=0;
	if (p->text)
	{
		w=textlength(this,p->text);
		h=textheight(this,p->text);
	}
	h+=BORDER;
	minwidth=textlength(this,p->title)+BORDER*2;
	minheight=textheight(this,p->title)+8+BORDER*2;
	minwidth=(minwidth>w)?minwidth:w;
	minheight=(minheight>h)?minheight:h;
	if (p->orig==pindicator::CIRCLE)
	{
		minxaspect=1; maxxaspect=1;
		minyaspect=1; maxyaspect=1;
	}
	setlimit=1;
}
int indicator::GActivate(XEvent *event,int why)
{
	return 0;
}

void indicator::MaxValue(int v)
{
	p->maxvalue=v; p->mark=0;
};
void indicator::MaxValue(int v,int smark)
{
	p->maxvalue=v; p->mark=smark;
	if (win) p->update();
};

#endif
