#include <classes/Layouter/Windows.h>

#pragma -
#include <pragma/graphics_lib.h>
#include <pragma/utility_lib.h>
#pragma +

LayouterSizeHandlerC::LayouterSizeHandlerC(LayouterWindowC &w)
	: WindowNewsizeHandlerC(w),
	  window(w)
{
}

VOID LayouterSizeHandlerC::newsize()
{
	window.root.layout(0,0,
		window.window()->Width,
		window.window()->Height);
	EraseRect(window.rastPort(),
		window.window()->BorderLeft,
		window.window()->BorderTop,
		window.window()->Width - window.window()->BorderRight - 1,
		window.window()->Height - window.window()->BorderBottom - 1);
	window.refreshFrame();
	window.gadgets.rebuild(TRUE);
}

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

LayouterVerifyHandlerC::LayouterVerifyHandlerC(LayouterWindowC &w)
	: WindowSizeverifyHandlerC(w),
	  window(w)
{
}

VOID LayouterVerifyHandlerC::verify()
{
	window.clearGadgetList(FALSE,FALSE);
}

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

LayouterMinsizeHandlerC::LayouterMinsizeHandlerC(LayouterWindowC &w)
	: WindowChangeHandlerC(w),
	  window(w),
	  active(FALSE)
{
}

VOID LayouterMinsizeHandlerC::change()
{
	if (active)
	{
		window.limits(window.window()->Width,window.window()->Height,
			window.maxWSet ? window.window()->Width : ~0,
			window.maxHSet ? window.window()->Height : ~0);
		active = FALSE;
	};
}

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

BorderTransparentGroupC::BorderTransparentGroupC()
	: TransparentGroupLayoutC()
{
	innerTop = 0;
	innerBottom = 0;
	innerLeft = 0;
	innerRight = 0;
}

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

LayouterWindowC::LayouterWindowC(GTIDCMPortC &port, ScreenC &s,
		TextAttrC &font, Tag tag1type, ...)
	: GTWindowC(port, (struct TagItem *) &tag1type),
	  root(),
	  innerL(), leftL(), rightL(), topL(), bottomL(),
	  sizeTop(0,0), sizeBottom(0,0), sizeLeft(0,0), sizeRight(0,0),
	  sizeTopGeo(sizeTop,
	   LAYOUT_GROUP,NULL,0,LAYOUT_SIZE,NULL,0,
	   LAYOUT_GROUP,NULL,0,LAYOUT_SIZE,NULL,0),
	  sizeBottomGeo(sizeBottom,
	   LAYOUT_SIZE,NULL,0,LAYOUT_GROUP,NULL,0,
	   LAYOUT_SIZE,NULL,0,LAYOUT_GROUP,NULL,0),
	  sizeLeftGeo(sizeLeft,
	   LAYOUT_GROUP,NULL,0,LAYOUT_SIZE,NULL,0,
	   LAYOUT_GROUP,NULL,0,LAYOUT_SIZE,NULL,0),
	  sizeRightGeo(sizeRight,
	   LAYOUT_SIZE,NULL,0,LAYOUT_GROUP,NULL,0,
	   LAYOUT_SIZE,NULL,0,LAYOUT_GROUP,NULL,0),
	  innerGeo(innerL,
	  	LAYOUT_OPPBORDER,&topGeo,0,LAYOUT_OPPBORDER,&bottomGeo,0,
	  	LAYOUT_OPPBORDER,&leftGeo,0,LAYOUT_OPPBORDER,&rightGeo,0),
	  leftGeo(leftL,
	  	LAYOUT_OPPBORDER,&topGeo,0,LAYOUT_OPPBORDER,&bottomGeo,0,
	  	LAYOUT_GROUP,NULL,0,LAYOUT_SIZE,NULL,0),
	  rightGeo(rightL,
	  	LAYOUT_OPPBORDER,&topGeo,0,LAYOUT_GROUP,NULL,0,
	  	LAYOUT_SIZE,NULL,0,LAYOUT_GROUP,NULL,0),
	  topGeo(topL,
	  	LAYOUT_GROUP,NULL,0,LAYOUT_SIZE,NULL,0,
	  	LAYOUT_GROUP,NULL,0,LAYOUT_GROUP,NULL,0),
	  bottomGeo(bottomL,
	  	LAYOUT_SIZE,NULL,0,LAYOUT_GROUP,NULL,0,
	  	LAYOUT_GROUP,NULL,0,LAYOUT_GROUP,NULL,0),
	  vinfo(),
	  gadgets(*this),
	  titlegadgets(),
	  gtgadgets(font,vinfo,*this),
	  refreshhandler(*this),
	  sizehandler(*this),
	  verifyhandler(*this),
	  minsizehandler(*this),
	  maxWSet(FALSE),
	  maxHSet(FALSE)
{
	addIDCMP(IDCMP_GADGETUP);
	wScreen = &s;
	gadgets.add(titlegadgets);
	gadgets.add(gtgadgets);
	guiFont = &font;
	guiFallback = &font;
	titleFont = &font;
	titleFallback = &font;
	leftGeo.add(sizeLeftGeo);
	rightGeo.add(sizeRightGeo);
	topGeo.add(sizeTopGeo);
	bottomGeo.add(sizeBottomGeo);
	root.add(innerGeo);
	root.add(leftGeo);
	root.add(topGeo);
	root.add(rightGeo);
	root.add(bottomGeo);
}

LayouterWindowC::LayouterWindowC(GTIDCMPortC &port, ScreenC &s,
		TextAttrC &font, struct TagItem *tags)
	: GTWindowC(port, tags),
	  root(),
	  innerL(), leftL(), rightL(), topL(), bottomL(),
	  sizeTop(0,0), sizeBottom(0,0), sizeLeft(0,0), sizeRight(0,0),
	  sizeTopGeo(sizeTop,
	   LAYOUT_GROUP,NULL,0,LAYOUT_SIZE,NULL,0,
	   LAYOUT_GROUP,NULL,0,LAYOUT_SIZE,NULL,0),
	  sizeBottomGeo(sizeBottom,
	   LAYOUT_SIZE,NULL,0,LAYOUT_GROUP,NULL,0,
	   LAYOUT_SIZE,NULL,0,LAYOUT_GROUP,NULL,0),
	  sizeLeftGeo(sizeLeft,
	   LAYOUT_GROUP,NULL,0,LAYOUT_SIZE,NULL,0,
	   LAYOUT_GROUP,NULL,0,LAYOUT_SIZE,NULL,0),
	  sizeRightGeo(sizeRight,
	   LAYOUT_SIZE,NULL,0,LAYOUT_GROUP,NULL,0,
	   LAYOUT_SIZE,NULL,0,LAYOUT_GROUP,NULL,0),
	  innerGeo(innerL,
	  	LAYOUT_OPPBORDER,&topGeo,0,LAYOUT_OPPBORDER,&bottomGeo,0,
	  	LAYOUT_OPPBORDER,&leftGeo,0,LAYOUT_OPPBORDER,&rightGeo,0),
	  leftGeo(leftL,
	  	LAYOUT_OPPBORDER,&topGeo,0,LAYOUT_OPPBORDER,&bottomGeo,0,
	  	LAYOUT_GROUP,NULL,0,LAYOUT_SIZE,NULL,0),
	  rightGeo(rightL,
	  	LAYOUT_OPPBORDER,&topGeo,0,LAYOUT_GROUP,NULL,0,
	  	LAYOUT_SIZE,NULL,0,LAYOUT_GROUP,NULL,0),
	  topGeo(topL,
	  	LAYOUT_GROUP,NULL,0,LAYOUT_SIZE,NULL,0,
	  	LAYOUT_GROUP,NULL,0,LAYOUT_GROUP,NULL,0),
	  bottomGeo(bottomL,
	  	LAYOUT_SIZE,NULL,0,LAYOUT_GROUP,NULL,0,
	  	LAYOUT_GROUP,NULL,0,LAYOUT_GROUP,NULL,0),
	  vinfo(),
	  gadgets(*this),
	  titlegadgets(),
	  gtgadgets(font,vinfo,*this),
	  refreshhandler(*this),
	  sizehandler(*this),
	  verifyhandler(*this),
	  minsizehandler(*this),
	  maxWSet(FALSE),
	  maxHSet(FALSE)
{
	addIDCMP(IDCMP_GADGETUP);
	wScreen = &s;
	gadgets.add(titlegadgets);
	gadgets.add(gtgadgets);
	guiFont = &font;
	guiFallback = &font;
	titleFont = &font;
	titleFallback = &font;
	leftGeo.add(sizeLeftGeo);
	rightGeo.add(sizeRightGeo);
	topGeo.add(sizeTopGeo);
	bottomGeo.add(sizeBottomGeo);
	root.add(leftGeo);
	root.add(topGeo);
	root.add(rightGeo);
	root.add(bottomGeo);
	root.add(innerGeo);
}

BOOL LayouterWindowC::isValid()
{
	BOOL retval = vinfo.isValid() && screen()->isOpen();
	return retval;
}

VOID LayouterWindowC::setFallbackFonts(TextAttrC *font, TextAttrC *titlefont)
{
	if (font)
	{
		guiFallback = font;
	};
	if (titlefont)
	{
		titleFallback = titlefont;
	};
}

VOID LayouterWindowC::open(struct TagItem *tags)
{
	if (isOpen())
	{
		toFront();
		activate();
	}
	else {
		if (!vinfo.isValid())
			vinfo.getInfo(*wScreen);
		if (!isValid())
			throw WindowX();

		topL.setInnerTopBorder(screen()->screen()->Font->ta_YSize + 1);
		topL.setInnerLeftBorder(screen()->screen()->WBorLeft);
		topL.setInnerRightBorder(screen()->screen()->WBorRight);
		bottomL.setInnerLeftBorder(screen()->screen()->WBorLeft);
		leftL.setInnerTopBorder(screen()->screen()->WBorTop);
		rightL.setInnerTopBorder(screen()->screen()->WBorTop);
		BOOL sizeB = GetTagData(WA_SizeBBottom,FALSE,tags)
			|| creationTags().getData(WA_SizeBBottom,FALSE);
		BOOL sizeR = GetTagData(WA_SizeBRight,FALSE,tags)
			|| creationTags().getData(WA_SizeBRight,FALSE);
		BOOL sizeG = GetTagData(WA_SizeGadget,FALSE,tags)
			|| creationTags().getData(WA_SizeGadget,FALSE);
		BOOL hires = (screen()->screen()->Flags & SCREENHIRES) != NULL;
		if (sizeG)
		{
			if (hires)
			{
				rightL.setInnerBottomBorder(10);
				bottomL.setInnerRightBorder(18);
			}
			else {
				rightL.setInnerBottomBorder(11);
				bottomL.setInnerRightBorder(13);
			};
		};
		sizeTop.setHeight(screen()->screen()->WBorTop);
		sizeLeft.setWidth(screen()->screen()->WBorLeft);
		if (sizeB)
		{
			if (hires)
				sizeBottom.setHeight(10)
			else
				sizeBottom.setHeight(11);
		}
		else {
			sizeBottom.setHeight(screen()->screen()->WBorBottom);
		};
		if (sizeR || (!sizeB && sizeG))
		{
			if (hires)
				sizeRight.setWidth(18)
			else
				sizeRight.setWidth(13);
		}
		else {
			sizeRight.setWidth(screen()->screen()->WBorRight);
		};

		setTextAttrs(guiFont,titleFont);
		root.layout(0,0,LAYOUT_AUTOSIZE,LAYOUT_AUTOSIZE);
		WORD minW = root.width();
		WORD minH = root.height();
		BOOL reLayout = FALSE;
		WORD width = GetTagData(WA_Width,creationTags().getData(WA_Width,0),tags);
		if (width <= root.width())
			width = root.width()
		else
			reLayout = TRUE;
		WORD height = GetTagData(WA_Height,creationTags().getData(WA_Height,0),tags);
		if (height <= root.height())
			height = root.height()
		else
			reLayout = TRUE;
		if (reLayout)
		{
			root.layout(0,0,width,height);
		};
		gadgets.rebuild();
		maxWSet = FALSE;
		WORD maxW = GetTagData(WA_MaxWidth,creationTags().getData(WA_MaxWidth,~0),tags);
		if (maxW == 0)
		{
			maxW = width;
			maxWSet = TRUE;
		};
		maxHSet = FALSE;
		WORD maxH = GetTagData(WA_MaxHeight,creationTags().getData(WA_MaxHeight,~0),tags);
		if (maxH == 0)
		{
			maxH = height;
			maxHSet = TRUE;
		};
		GTWindowC::open(
			WA_MinWidth, minW,
			WA_MinHeight, minH,
			WA_AutoAdjust, TRUE,
			WA_Width, width,
			WA_Height, height,
			WA_MaxWidth, maxW,
			WA_MaxHeight, maxH,
			screen()->screen()->Flags & PUBLICSCREEN ?
				WA_PubScreen : WA_CustomScreen, screen()->screen(),
			TAG_MORE,tags);
	};
}

BOOL LayouterWindowC::changeFont(TextAttrC *gui, TextAttrC *title,
		BOOL avoidResize)
{
	BOOL retval = TRUE;
	TextAttrC *oldfont = font();
	TextAttrC *oldtitle = titlefont();
	clearGadgetList(FALSE,FALSE);
	if (!setFonts(gui,title,avoidResize))
	{
		if (!setFonts(guiFallback, titleFallback,avoidResize))
		{
			// hier sollte man auf keinen Fall reinkommen - die Fallbacks
			// sollten immer funktionieren.
			if (!setFonts(oldfont,oldtitle,FALSE))
			{
				// Dieser Alert kommt hoffentlich nie...
				// DisplayAlert(RECOVERY_ALERT,"\0\0\0Illegal fonts.\0",40);
			};
			retval = FALSE;
		};
	};
	return retval;
}

BOOL LayouterWindowC::reLayout(BOOL avoidResize)
{
	if (isOpen())
	{
		WORD w = root.width();
		WORD h = root.height();
		clearGadgetList(FALSE,FALSE);
		root.layout(0,0,LAYOUT_AUTOSIZE,LAYOUT_AUTOSIZE);
		WORD width = root.width();
		WORD height = root.height();
		if (!avoidResize || width > w || height > h)
		{
			limits(1,1,~0,~0);
			minsizehandler.activate(TRUE);
			BOOL retval = changeSize(width,height);
			return retval;
		}
		else {
			limits(maxWSet ? w : width, maxHSet ? h : height,
				maxWSet ? w : ~0,maxHSet ? h : ~0);
			root.layout(0,0,w,h);
			if (isOpen())
			{
				EraseRect(rastPort(),
					window()->BorderLeft,
					window()->BorderTop,
					window()->Width - window()->BorderRight - 1,
					window()->Height - window()->BorderBottom - 1);
			};
			refreshFrame();
			gadgets.rebuild(TRUE);
			return TRUE;
		};
	};
	return TRUE;
}

VOID LayouterWindowC::setTextAttrs(TextAttrC *font, TextAttrC *titlefont)
{
	if (font)
	{
		guiFont = font;
	}
	if (titlefont)
	{
		titleFont = titlefont;
	};
	gadgets.setTextAttr(guiFont);
	titlegadgets.setTextAttr(titleFont);
}

BOOL LayouterWindowC::setFonts(TextAttrC *font, TextAttrC *titlefont,
	BOOL avoidResize)
{
	setTextAttrs(font,titlefont);
	return reLayout(avoidResize);
}

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

LayouterWindowListC::LayouterWindowListC()
{
}

VOID LayouterWindowListC::add(LayouterWindowC &w)
{
	WindowListC::add(w);
}

VOID LayouterWindowListC::setFallbackFonts(TextAttrC *font,
		TextAttrC *titlefont)
{
	ListCursorC lc(*this);
	while (!lc.isDone())
	{
		((LayouterWindowC *) lc.item())->setFallbackFonts(font,titlefont);
		lc.next();
	};
}

BOOL LayouterWindowListC::changeFont(TextAttrC *font, TextAttrC *titlefont,
		BOOL avoidResize)
{
	ListCursorC lc(*this);
	while (!lc.isDone())
	{
		((LayouterWindowC *) lc.item())->changeFont(font,titlefont,avoidResize);
		lc.next();
	};
	return TRUE;
}

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

StandardWindowC::StandardWindowC(GTIDCMPortC &p, ScreenC &s,
	GadgetC *defaultGadget, Tag tag1type, ...)
	: LayouterWindowC(p,s,defaultF,
		WA_DepthGadget, TRUE,
		WA_DragBar, TRUE,
		WA_CloseGadget, GetTagData(WA_CloseGadget,TRUE,(struct TagItem *) &tag1type),
		WA_SizeGadget, GetTagData(WA_SizeGadget,TRUE,(struct TagItem *) &tag1type),
		TAG_MORE, (struct TagItem *) &tag1type),
	  defaultF("topaz.font",8),
	  textF(new LTextAttrC(defaultF)),
	  titleF(new LTextAttrC(defaultF)),
	  textFB(new LTextAttrC(defaultF)),
	  titleFB(new LTextAttrC(defaultF)),
	  bold(NULL,0,FSF_BOLD),
	  defgadget(defaultGadget),
	  firstOpened(FALSE)
{
	bold.assign(*font());
}

StandardWindowC::StandardWindowC(GTIDCMPortC &p, ScreenC &s,
	GadgetC *defaultGadget, struct TagItem *tags)
	: LayouterWindowC(p,s,defaultF,
		WA_DepthGadget, TRUE,
		WA_DragBar, TRUE,
		WA_CloseGadget, GetTagData(WA_CloseGadget,TRUE,tags),
		WA_SizeGadget, GetTagData(WA_SizeGadget,TRUE,tags),
		TAG_MORE, tags),
	  defaultF("topaz.font",8),
	  textF(new LTextAttrC(defaultF)),
	  titleF(new LTextAttrC(defaultF)),
	  textFB(new LTextAttrC(defaultF)),
	  titleFB(new LTextAttrC(defaultF)),
	  bold(NULL,0,FSF_BOLD),
	  defgadget(defaultGadget),
	  firstOpened(FALSE)
{
	bold.assign(*font());
}

VOID StandardWindowC::open(struct TagItem *tags)
{
	if (!firstOpened)
	{
		if (screen()->isOpen())
		{
			firstOpened = TRUE;
			changeFont(&TextAttrC(*screen()->screen()->Font),
				&TextAttrC(*screen()->screen()->Font));
		};
	};
	LayouterWindowC::open(tags);
}

VOID StandardWindowC::setFallbackFonts(TextAttrC *font, TextAttrC *titlefont)
{
	LayouterWindowC::setFallbackFonts(font,titlefont);
}

BOOL StandardWindowC::changeFont(TextAttrC *font, TextAttrC *titlefont,
		BOOL avoidResize)
{
	LTextAttrC *f = NULL;
	if (font)
	{
		f = new LTextAttrC(*font->attr());
	};
	LTextAttrC *tf = NULL;
	if (titlefont)
	{
		tf = new LTextAttrC(*titlefont->attr());
	};
	BOOL retval = LayouterWindowC::changeFont(f,tf,avoidResize);
	if (retval)
	{
		if (textF)
			delete textF;
		textF = f;
		if (titleF)
			delete titleF;
		titleF = tf;
	};
	return retval;
}

VOID StandardWindowC::setTextAttrs(TextAttrC *font, TextAttrC *titlefont)
{
	if (font)
	{
		bold.assign(*font);
	};
	LayouterWindowC::setTextAttrs(font,titlefont);
	if (font)
	{
		if (defgadget)
			defgadget->setTextAttr(&bold);
	};
}

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