/*  GadTools layout toolkit
**
**  Copyright © 1993-1995 by Olaf `Olsen' Barthel
**  Freely distributable.
*/

#include "gtlayout_global.h"

#ifdef DO_LEVEL_KIND
VOID __regargs
LTP_DrawLevelImageLeft(struct RastPort *RPort,struct DrawInfo *DrawInfo,LevelImageInfo *Level,struct Image *Image,WORD Left,WORD Top,WORD Width,WORD Height,WORD OffsetX,WORD OffsetY)
{
	WORD	BorderTop	= Level -> KnobTop,
			BorderLeft	= Level -> KnobWidth;

	Left	+= OffsetX;
	Top		+= OffsetY;

	if(Width > 0)
	{
		LTP_SetAPen(RPort,DrawInfo -> dri_Pens[SHADOWPEN]);

		Move(RPort,Left,Top);
		Draw(RPort,Left,Top + Height - 1);

		if(Width > 1)
		{
			Move(RPort,Left + 1,Top);
			Draw(RPort,Left + 1,Top + Height - 2);

			LTP_SetAPen(RPort,DrawInfo -> dri_Pens[SHINEPEN]);

			WritePixel(RPort,Left + 1,Top + Height - 1);

			if(Width > 2)
			{
				Move(RPort,Left + 2,Top + Height - 1);
				Draw(RPort,Left + Width - 1,Top + Height - 1);

				LTP_SetAPen(RPort,DrawInfo -> dri_Pens[SHADOWPEN]);

				Move(RPort,Left + 2,Top);
				Draw(RPort,Left + Width - 1,Top);

				LTP_SetAPen(RPort,DrawInfo -> dri_Pens[FILLPEN]);

				RectFill(RPort,Left + 2,Top + 1,Left + Width - 1,Top + Height - 2);
			}
		}

		LTP_SetAPen(RPort,DrawInfo -> dri_Pens[BACKGROUNDPEN]);

		RectFill(RPort,Left,Top - BorderTop,Left + Width - 1,Top - 1);
		RectFill(RPort,Left,Top + Height,Left + Width - 1,Top + Height + BorderTop - 1);
		RectFill(RPort,Left - BorderLeft,Top - BorderTop,Left - 1,Top + Height + BorderTop - 1);
	}
	else
	{
		if(Level -> Position < BorderLeft)
		{
			LTP_SetAPen(RPort,DrawInfo -> dri_Pens[BACKGROUNDPEN]);

			Left	= Image -> LeftEdge + OffsetX;
			Width	= Level -> Position;

			if(Width > 0)
				RectFill(RPort,Left,Top - BorderTop,Left + Width - 1,Top + Height + BorderTop - 1);
		}
	}
}


/*****************************************************************************/


VOID __regargs
LTP_DrawLevelImageRight(struct RastPort *RPort,struct DrawInfo *DrawInfo,LevelImageInfo *Level,struct Image *Image,WORD Left,WORD Top,WORD Width,WORD Height,WORD OffsetX,WORD OffsetY)
{
	WORD	BorderTop	= Level -> KnobTop,
			BorderLeft	= Level -> KnobWidth;

	Left	+= OffsetX;
	Top		+= OffsetY;

	if(Width > 0)
	{
		LTP_SetAPen(RPort,DrawInfo -> dri_Pens[SHINEPEN]);

		Move(RPort,Left + Width - 1,Top);
		Draw(RPort,Left + Width - 1,Top + Height - 1);

		if(Width > 1)
		{
			Move(RPort,Left + Width - 2,Top + 1);
			Draw(RPort,Left + Width - 2,Top + Height - 1);

			LTP_SetAPen(RPort,DrawInfo -> dri_Pens[SHADOWPEN]);

			WritePixel(RPort,Left + Width - 2,Top);

			if(Width > 2)
			{
				Move(RPort,Left,Top);
				Draw(RPort,Left + Width - 3,Top);

				LTP_SetAPen(RPort,DrawInfo -> dri_Pens[SHINEPEN]);

				Move(RPort,Left,Top + Height - 1);
				Draw(RPort,Left + Width - 3,Top + Height - 1);

				LTP_SetAPen(RPort,DrawInfo -> dri_Pens[BACKGROUNDPEN]);

				RectFill(RPort,Left,Top + 1,Left + Width - 3,Top + Height - 2);
			}
		}

		LTP_SetAPen(RPort,DrawInfo -> dri_Pens[BACKGROUNDPEN]);

		RectFill(RPort,Left,Top - BorderTop,Left + Width - 1,Top - 1);
		RectFill(RPort,Left,Top + Height,Left + Width - 1,Top + Height + BorderTop - 1);
		RectFill(RPort,Left + Width,Top - BorderTop,Left + Width + BorderLeft - 1,Top + Height + BorderTop - 1);
	}
	else
	{
		Width = Image -> Width - (Level -> Position + 2 * BorderLeft);

		if(Width > 0)
		{
			LTP_SetAPen(RPort,DrawInfo -> dri_Pens[BACKGROUNDPEN]);

			Left = Image -> LeftEdge + OffsetX + 2 * BorderLeft + Level -> Position;

			if(Width > 0)
				RectFill(RPort,Left,Top - BorderTop,Left + Width - 1,Top + Height + BorderTop - 1);
		}
	}
}


/*****************************************************************************/


VOID __regargs
LTP_DrawLevelImageKnob(struct RastPort *RPort,struct DrawInfo *DrawInfo,WORD Left,WORD Top,WORD Width,WORD Height,LevelImageInfo *Level,BOOL Selected)
{
	UWORD	Shine	= DrawInfo -> dri_Pens[SHINEPEN],
			Shadow	= DrawInfo -> dri_Pens[SHADOWPEN],
			Fill	= Selected ? DrawInfo -> dri_Pens[FILLPEN] : DrawInfo -> dri_Pens[BACKGROUNDPEN],
			Back	= DrawInfo -> dri_Pens[BACKGROUNDPEN];

	Width = Level -> KnobWidth * 2;

	Left += Level -> Position - Level -> KnobWidth;

	if((Fill == Shine || Fill == Shadow) && Fill != Back)
		Shine = Shadow = Back;

	LTP_SetAPen(RPort,Fill);

	RectFill(RPort,Left + 2,Top + 1,Left + 2 + Width - 3,Top + Height - 1);

	LTP_SetAPen(RPort,Shine);

	Move(RPort,Left + 1,Top + 1);
	Draw(RPort,Left + 1,Top + Height - 2);
	Draw(RPort,Left,Top + Height - 1);
	Draw(RPort,Left,Top);
	Draw(RPort,Left + Width - 2,Top);

	Move(RPort,Left + Width / 2,Top + 2);
	Draw(RPort,Left + Width / 2,Top + Height - 3);

	LTP_SetAPen(RPort,Shadow);

	Move(RPort,Left + Width - 2,Top + Height - 2);
	Draw(RPort,Left + Width - 2,Top + 1);
	Draw(RPort,Left + Width - 1,Top);
	Draw(RPort,Left + Width - 1,Top + Height - 1);
	Draw(RPort,Left + 1,Top + Height - 1);

	Move(RPort,Left + Width / 2 - 1,Top + 2);
	Draw(RPort,Left + Width / 2 - 1,Top + Height - 3);
}


/*****************************************************************************/


VOID __regargs
LTP_DrawLevelImageComplete(struct Image *Image,struct RastPort *RPort,struct DrawInfo *DrawInfo,LevelImageInfo *Level,WORD OffsetX,WORD OffsetY,BOOL Selected)
{
	WORD	BorderTop	= Level -> KnobTop,
			BorderLeft	= Level -> KnobWidth,
			Left,Top,
			Width,Height;
	LONG	Position;

	Left	= Image -> LeftEdge + BorderLeft;
	Top		= Image -> TopEdge + BorderTop;
	Width	= Image -> Width - 2 * BorderLeft;
	Height	= Image -> Height - 2 * BorderTop;

	Position = Level -> Position + Left;

	SetAfPt(RPort,NULL,0);

	LTP_DrawLevelImageKnob(RPort,DrawInfo,Image -> LeftEdge + BorderLeft + OffsetX,Image -> TopEdge + OffsetY,Image -> Width - 2 * BorderLeft,Image -> Height,Level,Selected);
	LTP_DrawLevelImageLeft(RPort,DrawInfo,Level,Image,Left,Top,Position - BorderLeft - Left,Height,OffsetX,OffsetY);
	LTP_DrawLevelImageRight(RPort,DrawInfo,Level,Image,Position + BorderLeft,Top,Left + Width - (Position + BorderLeft),Height,OffsetX,OffsetY);
}


/*****************************************************************************/


ULONG __regargs
LTP_LevelClassDraw(struct Image *Image,struct impDraw *DrawMsg,LevelImageInfo *Level)
{
	struct RastPort *RPort = DrawMsg -> imp_RPort;

	if(RPort -> Layer)
		LockLayerRom(RPort -> Layer);

	LTP_DrawLevelImageComplete(Image,RPort,Level -> DrawInfo,Level,DrawMsg -> imp_Offset . X,DrawMsg -> imp_Offset . Y,DrawMsg -> imp_State == IDS_SELECTED);

	if(DrawMsg -> imp_State == IDS_DISABLED)
	{
		WORD	Left	= Image -> LeftEdge	+ DrawMsg -> imp_Offset . X,
				Top		= Image -> TopEdge	+ DrawMsg -> imp_Offset . Y;

//		LTP_SetPens(RPort,Level -> DrawInfo -> dri_Pens[BLOCKPEN],0,JAM1);
		LTP_SetPens(RPort,Level -> DrawInfo -> dri_Pens[BACKGROUNDPEN],0,JAM1);

//		SetAfPt(RPort,(UWORD *)&ghostingPat,1);
		SetAfPt(RPort,(UWORD *)&checkPat,1);
		RectFill(RPort,Left,Top,Left + Image -> Width - 1,Top + Image -> Height - 1);
		SetAfPt(RPort,NULL,0);
	}

	if(RPort -> Layer)
		UnlockLayerRom(RPort -> Layer);

	return(TRUE);
}


/*****************************************************************************/


ULONG __regargs
LTP_LevelClassSet(Class *class,struct Image *Image,struct opSet *SetMsg)
{
	LevelImageInfo	*Level = (LevelImageInfo *)INST_DATA(class,Image);
	struct TagItem	*Item,*List,*PositionItem = NULL;
	LONG			 Width = Image -> Width - 2 * Level -> KnobWidth;

	List = SetMsg -> ops_AttrList;

	while(Item = NextTagItem(&List))
	{
		switch(Item -> ti_Tag)
		{
			case LVIA_Current:

				Level -> Current = Item -> ti_Data;
				break;

			case LVIA_Max:

				Level -> Max = Item -> ti_Data;
				break;

			case LVIA_Position:

				PositionItem = Item;
				break;
		}
	}

	if(PositionItem)
	{
		LONG Position = (LONG)PositionItem -> ti_Data;

		if(Position < 0 || !Level -> Max)
			Position = 0;
		else
		{
			if(Position > Width)
				Position = Width;
		}

		Level -> Position = Position;
	}
	else
	{
		if(Level -> Max)
			Level -> Position = (Width * Level -> Current) / Level -> Max;
		else
			Level -> Position = 0;
	}

	return(DoSuperMethodA(class,(Object *)Image,SetMsg));
}


/*****************************************************************************/


ULONG __regargs
LTP_LevelClassGet(Class *class,struct Image *Image,struct opGet *GetMsg)
{
	LevelImageInfo *Level = (LevelImageInfo *)INST_DATA(class,Image);

	switch(GetMsg -> opg_AttrID)
	{
		case LVIA_Current:

			*GetMsg -> opg_Storage = Level -> Current;

			return(TRUE);

		case LVIA_Max:

			*GetMsg -> opg_Storage = Level -> Max;

			return(TRUE);

		case LVIA_Position:

			*GetMsg -> opg_Storage = Level -> Position;

			return(TRUE);

		case LVIA_KnobWidth:

			*GetMsg -> opg_Storage = Level -> KnobWidth;

			return(TRUE);

		case IA_SupportsDisable:

			*GetMsg -> opg_Storage = TRUE;

			return(TRUE);
	}

	return(DoSuperMethodA(class,(Object *)Image,GetMsg));
}


/*****************************************************************************/


ULONG __regargs
LTP_LevelClassNew(Class *class,Object *object,struct opSet *SetMsg)
{
	LONG			 Width		= 0,
					 Height 	= 0;
	UWORD			 FontWidth	= 0;
	LONG			 Current	= 0,
					 Max		= 0;
	struct DrawInfo *DrawInfo	= NULL;
	struct TagItem	*List,
					*Item;

	List = SetMsg -> ops_AttrList;

	while(Item = NextTagItem(&List))
	{
		switch(Item -> ti_Tag)
		{
			case IA_Width:

				Width = Item -> ti_Data;
				break;

			case IA_Height:

				Height = Item -> ti_Data;
				break;

			case LVIA_FontWidth:

				FontWidth = Item -> ti_Data;
				break;

			case LVIA_DrawInfo:

				DrawInfo = (struct DrawInfo *)Item -> ti_Data;
				break;

			case LVIA_Current:

				Current = (LONG)Item -> ti_Data;
				break;

			case LVIA_Max:

				Max = (LONG)Item -> ti_Data;
				break;
		}
	}

	if(Width && Height >= 4 && DrawInfo)
	{
		struct Image *Image;

		if(Image = (struct Image *)DoSuperMethodA(class,object,(Msg)SetMsg))
		{
			LevelImageInfo	*Level = (LevelImageInfo *)INST_DATA(class,Image);
			WORD			 QuarterWidth,
							 KnobWidth,
							 LevelHeight;

			QuarterWidth	= (FontWidth + 3) / 4,
			KnobWidth		= 3 * QuarterWidth,
			LevelHeight		= (KnobWidth * DrawInfo -> dri_Resolution . X) / DrawInfo -> dri_Resolution . Y;

			if(LevelHeight >= Height)
				LevelHeight = Height / 4;

			if(LevelHeight < 4)
			{
				if(Height > 4)
					LevelHeight = 4;
				else
					LevelHeight = Height;
			}

			Level -> KnobWidth		= KnobWidth;
			Level -> KnobTop		= (Height - LevelHeight) / 2;
			Level -> LevelHeight	= LevelHeight;
			Level -> Max			= Max;
			Level -> Current		= Current;
			Level -> DrawInfo		= DrawInfo;

			if(Max)
				Level -> Position = ((Width - 2 * KnobWidth) * Current) / Max;
			else
				Level -> Position = 0;

			return((ULONG)Image);
		}
	}

	return(NULL);
}


/*****************************************************************************/


ULONG __saveds __asm
LTP_LevelClassDispatcher(register __a0 Class *class,register __a2 Object *object,register __a1 Msg msg)
{
	switch(msg -> MethodID)
	{
		case IM_DRAW:

			return(LTP_LevelClassDraw((struct Image *)object,(struct impDraw *)msg,(LevelImageInfo *)INST_DATA(class,object)));

		case OM_SET:

			return(LTP_LevelClassSet(class,(struct Image *)object,(struct opSet *)msg));

		case OM_GET:

			return(LTP_LevelClassGet(class,(struct Image *)object,(struct opGet *)msg));

		case OM_NEW:

			return(LTP_LevelClassNew(class,object,(struct opSet *)msg));

		default:

			return(DoSuperMethodA(class,object,msg));
	}
}
#endif	/* DO_LEVEL_KIND */
