#ifndef CODE_CARD_CXX
#define CODE_CARD_CXX

/*-----------------------------------------------------------------------
 * Xclasses code file
 * ($Id: card.cxx,v 1.2 1998/07/31 06:35:21 beckerr 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 "types.h"
#include <Xclasses/gadget.h>
#include <Xclasses/group.h>
#include <Xclasses/card.h>
#include "include/card_p.h"

#define BLOCK 10

card::card() : gadget(), Ddraw(this)
{
	while (!(p=new pcard))
	{
		outOfMemory("card");
	}
	p->o=this;
	Name("card");
	BorderSize(2);
	NoKeyBorder();
	StripesMark();
}
pcard::pcard()
{
	anzahl=0;
	groesse=0;
	selected=0;
	sel=0;
	allcards=NULL;
	key=0;
}
pcard::~pcard()
{
}
card::~card()
{
	if (win) Free();
	if (p) delete p;
}

void card::Add(char *n,group *gp)
{
	p->anzahl++;
	if (p->anzahl>p->groesse)
	{
		struct cards *c;
		if (c=new cards[p->groesse+BLOCK])
		{
			for(int i=0;i<(p->anzahl-1);i++)
			{
				c[i]=p->allcards[i];
			}
			if (p->allcards) delete p->allcards;
			p->allcards=c;
			p->groesse+=BLOCK;
		}
		else
		{
			p->anzahl--;
			return;
		}
	}
	gp->ParentClass(this);
	p->allcards[p->anzahl-1].gp=gp;
	p->allcards[p->anzahl-1].name.Text(n);
	p->allcards[p->anzahl-1].name.Adjust(ADJUST_CENTER|ADJUST_MIDDLE);
	if (p->anzahl>1)
	{
		p->allcards[0].gp->AddShadow(gp);
	}
}

void card::Selected(int s)
{
	p->selected=s;
	if (p->selected>=p->anzahl) p->selected=p->anzahl-1;
	if (p->selected<0) p->selected=0;
	p->sel=p->selected;
	if (win) p->draw();
	p->allcards[p->selected].gp->Show();
}
int card::Selected(void)
{
	return p->selected;
}
void card::Free(void)
{
	if (p->anzahl>0) p->allcards[0].gp->Free();
	gadget::Free();
	if (p->allcards)
	{
		delete [] p->allcards;
		p->allcards=NULL;
		p->groesse=0;
		p->anzahl=0;
	}
}

int card::Create(void)
{
	Background(col_background());
	if (p->selected>=p->anzahl) p->selected=p->anzahl-1;
	if (p->selected<0) p->selected=0;
	p->sel=p->selected;

	char *r=GetResource("selected");
	if (r)
	{
		Selected(atoi(r));
	}
	
    if (gadget::Create())
    {
        Mode(GM_BUTTON1|GM_ONEEXPOSE|GM_KEY);
        if (p->allcards)
        {
        	if (!setlimit) GSetLimits();
	        p->allcards[0].gp->Create(win,p->bw1,p->bh1+BY,width-p->bw2,height-p->bh2);
		}
		return 1;
    } 
    return 0;
}
void card::Resize(int w,int h)
{
	gadget::Resize(w,h);
	p->allcards[0].gp->Resize(w-p->bw1-p->bw2,h-p->bh1-p->bh2-BY);
}

void pcard::draw(void)
{
	int x=0,si=0;

	for(int i=0;i<anzahl;i++)
	{
		allcards[i].x1=x;
		allcards[i].y1=TOPDOWN;
		allcards[i].x2=x+allcards[i].name.width(o)+BUTWIDTH;
		allcards[i].y2=0+bh1;
		x+=allcards[i].name.width(o)+BUTWIDTH;
	}
	XSetForeground(o->display(),o->gc,o->col_background());
	XFillRectangle(o->display(),o->win,o->gc,0,0,x+1,TOPDOWN);

	for(int i=anzahl-1;i>=0;i--)
	{
		o->borderUpFill(o,allcards[i].x1,TOPDOWN,allcards[i].name.width(o)+BUTWIDTH+1,bh1-TOPDOWN);
		if (o->locked)
			allcards[i].name.draw_locked(o,allcards[i].x1,TOPDOWN,allcards[i].name.width(o)+BUTWIDTH,bh1-TOPDOWN);
		else
			allcards[i].name.draw_normal(o,allcards[i].x1,TOPDOWN,allcards[i].name.width(o)+BUTWIDTH,bh1-TOPDOWN);
		if (o->locked) o->borderlocked(o,allcards[i].x1,TOPDOWN,allcards[i].name.width(o)+BUTWIDTH+1,bh1-TOPDOWN);

		if (i==selected)
		{
			si=i;
		}
	}

	o->borderUpFill(o,allcards[si].x1,0,allcards[si].name.width(o)+BUTWIDTH+1,bh1);
	if (o->locked)
		allcards[si].name.draw_locked(o,allcards[si].x1,0,allcards[si].name.width(o)+BUTWIDTH,bh1);
	else
		allcards[si].name.draw_normal(o,allcards[si].x1,0,allcards[si].name.width(o)+BUTWIDTH,bh1);
	if (o->locked) o->borderlocked(o,allcards[si].x1,0,allcards[si].name.width(o)+BUTWIDTH+1,bh1);

	o->borderUp(o,0,bh1-o->RealSize(),o->width,o->height-bh1+o->RealSize());
	XSetForeground(o->display(),o->gc,o->col_background());
	XFillRectangle(o->display(),o->win,o->gc,allcards[si].x1+o->RealSize(),bh1-o->RealSize(),allcards[si].name.width(o)+BUTWIDTH+1-o->RealSize()-o->RealSize(),o->RealSize());
	if (key) kborder();
}
void pcard::kborder(void)
{
	int r=o->RealSize();
	o->KeyBorder();
	o->bordermark(o,allcards[sel].x1+r+1,
					allcards[sel].y1+r+1,
					(allcards[sel].x2-allcards[sel].x1)-r*2-2,
					(allcards[sel].y2-allcards[sel].y1)-r*2-2);
	o->NoKeyBorder();
}
void pcard::nkborder(void)
{
	int r=o->RealSize();
	o->KeyBorder();
	o->borderunmark(o,allcards[sel].x1+r+1,
					allcards[sel].y1+r+1,
					(allcards[sel].x2-allcards[sel].x1)-r*2-2,
					(allcards[sel].y2-allcards[sel].y1)-r*2-2);
	o->NoKeyBorder();
}


void card::Lock(void)
{
	gadget::Lock();
}
void card::Unlock(void)
{
	gadget::Unlock();
}
void card::Block(int b)
{
	gadget::Block(b);
	p->allcards[0].gp->Block(b);
}
void card::Unblock(int b)
{
	p->allcards[0].gp->Unblock(b);
	gadget::Unblock(b);
}

void card::GExpose(XEvent *event)
{
	p->draw();
}
void card::GActionPress(int mx,int my,int rx,int ry,unsigned int state,int button,int reason)
{
	if (reason&GB_KEY)
	{
		p->key=1;
		p->kborder();
	}
}
void card::GActionRelease(int mx,int my,int rx,int ry,unsigned int state,int button,int reason)
{
	if (reason&GB_KEY)
	{
		p->nkborder();
		p->key=0;
	}
}
int card::GActivate(XEvent *event,int why)
{
	switch (why)
	{
		case GA_BUTTONPRESS:
			{
				ActivateKey();
				for(int i=0;i<p->anzahl;i++)
				{
					if (event->xbutton.x>=p->allcards[i].x1 && event->xbutton.x<=p->allcards[i].x2
					 && event->xbutton.y>=p->allcards[i].y1 && event->xbutton.y<=p->allcards[i].y2)
					{
						p->nkborder();
						p->sel=i;
						p->kborder();
						return GAR_ACTIVE;
					}
				}
				return 0;
			}
			break;
		case GA_KEY:
			{
				int r;
				r=DefaultKeyHandler(event);
				if (r==DKH_SELECT)
				{
					return GAR_ACTIVE;
				}
				else if (r==DKH_NOTHING)
				{
					int c;
					char taste[5];
					KeySym key;
					c=XLookupString((XKeyEvent*)event,taste,sizeof(taste),&key,0);

					switch (key)
					{
						case XK_Left:
							p->nkborder();
							p->sel--;
							if (p->sel<0) p->sel=0;
							p->kborder();
							break;
						case XK_Right:
							p->nkborder();
							p->sel++;
							if (p->sel>=p->anzahl) p->sel=p->anzahl-1;
							p->kborder();
							break;
					}
				}
		    }
	}
    return 0;
}
int card::GSelected(XEvent *event,int why,int wasabove)
{
	switch (why)
	{
		case GA_BUTTONPRESS:
			for(int i=0;i<p->anzahl;i++)
			{
				if (event->xbutton.x>=p->allcards[i].x1 && event->xbutton.x<=p->allcards[i].x2
				 && event->xbutton.y>=p->allcards[i].y1 && event->xbutton.y<=p->allcards[i].y2)
				{
					if (i==p->sel)
					{
						p->nkborder();
						p->allcards[i].gp->Show();
						p->selected=p->sel;
						p->draw();
						return GSR_SELECTION|GSR_MESSAGE;
					}
				}
			}
			break;
		case GA_KEY:
			p->nkborder();
			p->selected=p->sel;
			p->allcards[p->selected].gp->Show();
			p->draw();
			return GSR_SELECTION|GSR_MESSAGE;
			break;
	}
	return 0;
}
void card::GSetLimits(void)
{
	int mw=0,mh=0,tl=0;
	p->bh1=0;
	minheight=0;
	minwidth=0;

	if (p->allcards)
	{
		p->allcards[0].gp->GSetLimits();
		minheight=p->allcards[0].gp->gg_minheight();
		maxheight=p->allcards[0].gp->gg_maxheight();
		minwidth =p->allcards[0].gp->gg_minwidth();
		maxwidth =p->allcards[0].gp->gg_maxwidth();
	}
	for (int i=0;i<p->anzahl;i++)
	{
		mw=p->allcards[i].name.width(this)+BUTWIDTH+RealSize();
		tl+=mw;
		mh=p->allcards[i].name.height(this)+BUTHEIGHT+RealSize();
		if (mh>p->bh1) p->bh1=mh;
	}
	if (tl>minwidth) minwidth=tl;
	p->bh2=RealSize()+BY+RealSize();
	p->bw1=RealSize()+BX+RealSize();
	p->bw2=RealSize()+BX+RealSize();
	minheight+=p->bh1+p->bh2+BY;
	if (maxheight!=NO_LIMIT) maxheight+=p->bh1+p->bh2+BY;
	minwidth+=p->bw1+p->bw2;
	if (maxwidth!=NO_LIMIT) maxwidth+=p->bw1+p->bw2;
	if (minwidth>maxwidth) maxwidth=minwidth;
	if (minheight>maxheight) maxheight=minheight;
	setlimit=1;
}

#endif
