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

#include "gtlayout_global.h"

VOID __regargs
LTP_LayoutGroup(LayoutHandle *Handle,ObjectNode *Group)
{
	if(!Handle -> Failed)
	{
		ObjectNode	*Node;
		ObjectNode	*ReturnKey;
		ObjectNode	*EscKey;
		ObjectNode	*CursorKey;
		ObjectNode	*TabKey;
		LONG		 Left;
		LONG		 Top;
		LONG		 Width;
		LONG		 Height;

		Left		= 0;
		Top		= 0;
		ReturnKey	= NULL;
		EscKey		= NULL;
		CursorKey	= NULL;
		TabKey		= NULL;

		if(Group -> Special . Group . SameSize)
		{
			LONG MaxWidth  = 0;
			LONG MaxHeight = 0;

			SCANGROUP(Group,Node)
			{
				LTP_DetermineSize(Handle,Node);

				if(Node -> Type == BUTTON_KIND)
				{
					if(Node -> Special . Button . ReturnKey)
						ReturnKey = Node;
					else
					{
						if(Node -> Special . Button . EscKey)
							EscKey = Node;
					}
				}

				if(Node -> Type == CYCLE_KIND)
				{
					if(Node -> Special . Cycle . TabKey)
						TabKey = Node;
				}

				if(Node -> Type == MX_KIND)
				{
					if(Node -> Special . Radio . TabKey)
						TabKey = Node;
				}

				if(Node -> Type == LISTVIEW_KIND && Node -> Special . List . CursorKey)
					CursorKey = Node;

				if(Node -> Width > MaxWidth)
					MaxWidth = Node -> Width;

				if(Node -> Height > MaxHeight)
					MaxHeight = Node -> Height;
			}

			if(ReturnKey)
			{
				SCANGROUP(Group,Node)
				{
					Node -> GroupIndent = TRUE;

					Node -> Width	+= 4 + 4;
					Node -> Height	+= 2 + 2;

					if(Node -> Width > MaxWidth)
						MaxWidth = Node -> Width;

					if(Node -> Height > MaxHeight)
						MaxHeight = Node -> Height;
				}
			}

			SCANGROUP(Group,Node)
			{
				if(Node -> Width < MaxWidth)
				{
					if(Node -> Type == GROUP_KIND)
						Node -> Special . Group . ExtraLeft += (MaxWidth - Node -> Width) / 2;

					Node -> Width = MaxWidth;
				}

				if(Node -> Height < MaxHeight)
				{
					if(Node -> Type == GROUP_KIND)
						Node -> Special . Group . ExtraTop += (MaxHeight - Node -> Height) / 2;

					Node -> Height = MaxHeight;
				}
			}
		}
		else
		{
			SCANGROUP(Group,Node)
			{
				LTP_DetermineSize(Handle,Node);

				if(Node -> Type == BUTTON_KIND)
				{
					if(Node -> Special . Button . ReturnKey)
						ReturnKey = Node;
					else
					{
						if(Node -> Special . Button . EscKey)
							EscKey = Node;
					}
				}

				if(Node -> Type == LISTVIEW_KIND && Node -> Special . List . CursorKey)
					CursorKey = Node;

				if(Node -> Type == CYCLE_KIND)
				{
					if(Node -> Special . Cycle . TabKey)
						TabKey = Node;
				}

				if(Node -> Type == MX_KIND)
				{
					if(Node -> Special . Radio . TabKey)
						TabKey = Node;
				}
			}

			if(ReturnKey)
			{
				SCANGROUP(Group,Node)
				{
					Node -> GroupIndent = TRUE;

					Node -> Width	+= 4 + 4;
					Node -> Height	+= 2 + 2;
				}
			}
		}

		if(Group -> Special . Group . Horizontal)
		{
			LONG x,y,w,MaxTop = 0,MaxWidth = 0,MaxHeight = 0,Count = 0;

			if(Group -> Node . mln_Pred -> mln_Pred && Group -> Special . Group . LastAttributes)
			{
				ObjectNode *LastGroup = (ObjectNode *)Group -> Node . mln_Pred;

				MaxTop		= LastGroup -> Special . Group . MaxOffset;
				MaxHeight	= LastGroup -> Special . Group . MaxSize;
			}

			SCANGROUP(Group,Node)
			{
				if(!LIKE_STRING_KIND(Node) || Node -> Special . String . LinkID == -1)
				{
					if(!Group -> Special . Group . Paging && Count++)
					{
						if(Node -> ExtraSpace > 0)
							x = Left + Node -> ExtraSpace * Handle -> InterWidth;
						else
						{
							if(Node -> ExtraSpace < 0)
								x = Left - Node -> ExtraSpace;
							else
								x = Left + Handle -> InterWidth;
						}
					}
					else
						x = Left;

					y = Top;
					w = Node -> Width;

					switch(Node -> LabelPlace)
					{
						case PLACE_LEFT:

							if(Node -> Type == MX_KIND)
							{
								x += Node -> Special . Radio . LabelWidth + INTERWIDTH;

								if(Node -> Label)
								{
									if(Node -> Special . Radio . TitlePlace == PLACETEXT_LEFT)
										x += Node -> LabelWidth + INTERWIDTH;
									else
										w += INTERWIDTH + Node -> LabelWidth;
								}
							}
							else
							{
								if(Node -> Label || Node -> Type == BOX_KIND)
									x += Node -> LabelWidth + INTERWIDTH;
							}

							break;

						case PLACE_RIGHT:

							if(Node -> Type == MX_KIND)
							{
								w += INTERWIDTH + Node -> Special . Radio . LabelWidth;

								if(Node -> Label)
								{
									if(Node -> Special . Radio . TitlePlace == PLACETEXT_LEFT)
										x += Node -> LabelWidth + INTERWIDTH;
									else
										w += INTERWIDTH + Node -> LabelWidth;
								}
							}
							else
							{
								if(Node -> Label || Node -> Type == BOX_KIND)
									w += INTERWIDTH + Node -> LabelWidth;
							}

							break;

						case PLACE_ABOVE:

							if(Node -> Label || Node -> Type == BOX_KIND)
								y += Handle -> RPort . TxHeight + INTERHEIGHT;

							break;

						case PLACE_BELOW:

							break;

						case PLACE_IN:

							break;
					}

					if(Node -> Type == SLIDER_KIND)
					{
						if(Node -> Special . Slider . LevelPlace == PLACETEXT_RIGHT)
							w += INTERWIDTH + Node -> Special . Slider . LevelWidth;

						if(Node -> Special . Slider . LevelPlace == PLACETEXT_LEFT && Node -> LabelPlace != PLACE_LEFT)
							x += INTERWIDTH + Node -> Special . Slider . LevelWidth;
					}

#ifdef DO_LEVEL_KIND
					if(Node -> Type == LEVEL_KIND)
					{
						if(Node -> Special . Level . LevelPlace == PLACETEXT_RIGHT)
							w += INTERWIDTH + Node -> Special . Level . MaxLevelWidth;

						if(Node -> Special . Level . LevelPlace == PLACETEXT_LEFT && Node -> LabelPlace != PLACE_LEFT)
							x += INTERWIDTH + Node -> Special . Level . MaxLevelWidth;
					}
#endif	/* DO_LEVEL_KIND */

					if(Node -> Type == LISTVIEW_KIND && Node -> Special . List . ExtraLabelWidth)
						x += Node -> Special . List . ExtraLabelWidth + INTERWIDTH;

					if(y > MaxTop)
						MaxTop = y;

					if(Node -> Height > MaxHeight)
						MaxHeight = Node -> Height;

					if(Node -> LabelPlace == PLACE_BELOW && Node -> Label)
					{
						LONG Height = Node -> Height + INTERHEIGHT + Handle -> RPort . TxHeight;

						if(Height > MaxHeight)
							MaxHeight = Height;
					}
					else
					{
						if(Node -> Height > MaxHeight)
							MaxHeight = Node -> Height;
					}

					if(x + w > MaxWidth)
						MaxWidth = x+w;

					Node -> Left = x;

					if(!Group -> Special . Group . Paging)
						Left = x + w;
				}
			}

			SCANGROUP(Group,Node)
			{
				if(!LIKE_STRING_KIND(Node) || Node -> Special . String . LinkID == -1)
				{
					Node -> Top = MaxTop;

					if(Node -> Height < MaxHeight)
					{
						if(Node -> Type == LISTVIEW_KIND || Node -> Type == PALETTE_KIND)
							Node -> Height = MaxHeight;
						else
						{
							if(Node -> Type == GROUP_KIND)
							{
								if(Node -> Special . Group . Spread)
									LTP_Spread(Handle,Node,Node -> Width,MaxHeight);
								else
									Node -> Special . Group . ExtraTop += (MaxHeight - Node -> Height) / 2; /* !FIX! */

								Node -> Height = MaxHeight;
							}
						}
					}
				}
			}

			Group -> Special . Group . MaxOffset = MaxTop;
			Group -> Special . Group . MaxSize   = MaxHeight;

			if(Group -> Special . Group . Paging)
				Width = MaxWidth;
			else
				Width = Left;

			Height	= MaxTop + MaxHeight;
		}
		else
		{
			LONG x,y,w,MaxLeft = 0,MaxWidth = 0,MaxHeight = 0,Count = 0;

			if(Group -> Node . mln_Pred -> mln_Pred && Group -> Special . Group . LastAttributes)
			{
				ObjectNode *LastGroup = (ObjectNode *)Group -> Node . mln_Pred;

				MaxLeft 	= LastGroup -> Special . Group . MaxOffset;
				MaxWidth	= LastGroup -> Special . Group . MaxSize;
			}

			SCANGROUP(Group,Node)
			{
				if(!LIKE_STRING_KIND(Node) || Node -> Special . String . LinkID == -1)
				{
					if(!Group -> Special . Group . Paging && Count++)
					{
						if(Node -> ExtraSpace > 0)
							y = Top + Node -> ExtraSpace * Handle -> InterHeight;
						else
						{
							if(Node -> ExtraSpace < 0)
								y = Top - Node -> ExtraSpace;
							else
								y = Top + Handle -> InterHeight;
						}
					}
					else
						y = Top;

					w = Node -> Width;
					x = Left;

					switch(Node -> LabelPlace)
					{
						case PLACE_LEFT:

							if(Node -> Type == MX_KIND)
							{
								x += Node -> Special . Radio . LabelWidth + INTERWIDTH;

								if(Node -> Label)
								{
									if(Node -> Special . Radio . TitlePlace == PLACETEXT_LEFT)
										x += Node -> LabelWidth + INTERWIDTH;
								}
							}
							else
							{
								if(Node -> Label || Node -> Type == BOX_KIND)
									x += Node -> LabelWidth + INTERWIDTH;
							}

							break;

						case PLACE_RIGHT:

							if(Node -> Type == MX_KIND)
							{
								w += INTERWIDTH + Node -> Special . Radio . LabelWidth;

								if(Node -> Label)
								{
									if(Node -> Special . Radio . TitlePlace == PLACETEXT_LEFT)
										x += Node -> LabelWidth + INTERWIDTH;
									else
										w += INTERWIDTH + Node -> LabelWidth;
								}
							}
							else
							{
								if(Node -> Label || Node -> Type == BOX_KIND)
									w += INTERWIDTH + Node -> LabelWidth;
							}

							break;

						case PLACE_ABOVE:

							if(Node -> Label || Node -> Type == BOX_KIND)
								y += Handle -> RPort . TxHeight + INTERHEIGHT;

							break;

						case PLACE_BELOW:

							break;

						case PLACE_IN:

							break;
					}

					if(Node -> Type == SLIDER_KIND)
					{
						if(Node -> Special . Slider . LevelPlace == PLACETEXT_RIGHT)
							w += INTERWIDTH + Node -> Special . Slider . LevelWidth;

						if(Node -> Special . Slider . LevelPlace == PLACETEXT_LEFT && Node -> LabelPlace != PLACE_LEFT)
							x += INTERWIDTH + Node -> Special . Slider . LevelWidth;
					}

#ifdef DO_LEVEL_KIND
					if(Node -> Type == LEVEL_KIND)
					{
						if(Node -> Special . Level . LevelPlace == PLACETEXT_RIGHT)
							w += INTERWIDTH + Node -> Special . Level . MaxLevelWidth;

						if(Node -> Special . Level . LevelPlace == PLACETEXT_LEFT && Node -> LabelPlace != PLACE_LEFT)
							x += INTERWIDTH + Node -> Special . Level . MaxLevelWidth;
					}
#endif	/* DO_LEVEL_KIND */
					if(Node -> Type == LISTVIEW_KIND && Node -> Special . List . ExtraLabelWidth)
						x += Node -> Special . List . ExtraLabelWidth + INTERWIDTH;

					if(x > MaxLeft)
						MaxLeft = x;

					if(w > MaxWidth)
						MaxWidth = w;

					if(y + Node -> Height > MaxHeight)
						MaxHeight = y + Node -> Height;

					Node -> Top = y;

					if(!Group -> Special . Group . Paging)
						Top = y + Node -> Height;

					if(Node -> LabelPlace == PLACE_BELOW && Node -> Label)
						Top += INTERHEIGHT + Handle -> RPort . TxHeight;
				}
			}

			SCANGROUP(Group,Node)
			{
				if(!LIKE_STRING_KIND(Node) || Node -> Special . String . LinkID == -1)
				{
					Node -> Left = MaxLeft;

					if(Node -> Type == GROUP_KIND && Group -> Special . Group . Paging)
						Node -> Special . Group . ExtraTop += (MaxHeight - Node -> Height) / 2;

					if(Node -> Width < MaxWidth)
					{
						if(Node -> Type == GROUP_KIND)
						{
							if(Node -> Special . Group . Spread)
								LTP_Spread(Handle,Node,MaxWidth,Node -> Height);
							else
								Node -> Special . Group . ExtraLeft += (MaxWidth - Node -> Width) / 2;

							Node -> Width = MaxWidth;
						}
						else
						{
							if(Node -> Type == LISTVIEW_KIND || Node -> Type == TEXT_KIND || Node -> Type == GAUGE_KIND || Node -> Type == NUMBER_KIND || Node -> Type == CYCLE_KIND || Node -> Type == PALETTE_KIND || LIKE_STRING_KIND(Node) || Node -> Type == INTEGER_KIND || Node -> Type == BUTTON_KIND || Node -> Type == SLIDER_KIND || Node -> Type == BOX_KIND || Node -> Type == SCROLLER_KIND || Node -> Type == LEVEL_KIND)
							{
								if(Node -> Type != LISTVIEW_KIND || !Node -> Special . List . LockSize)
								{
									if(Node -> Label && Node -> LabelPlace == PLACE_RIGHT)
										Node -> Width = MaxWidth - (INTERWIDTH + Node -> LabelWidth);
									else
										Node -> Width = MaxWidth;
								}
							}
							else
							{
								if(Node -> Type == SLIDER_KIND)
								{
									if(Node -> Special . Slider . LevelPlace == PLACE_RIGHT)
									{
										if(Node -> Width + Node -> Special . Slider . LevelWidth + INTERWIDTH < MaxWidth)
											Node -> Width = MaxWidth - (Node -> Special . Slider . LevelWidth + INTERWIDTH);
									}
									else
										Node -> Width = MaxWidth;
								}

#ifdef DO_LEVEL_KIND
								if(Node -> Type == LEVEL_KIND)
								{
									if(Node -> Special . Level . LevelPlace == PLACE_RIGHT)
									{
										if(Node -> Width + Node -> Special . Level . MaxLevelWidth + INTERWIDTH < MaxWidth)
											Node -> Width = MaxWidth - (Node -> Special . Level . MaxLevelWidth + INTERWIDTH);
									}
									else
										Node -> Width = MaxWidth;
								}
#endif	/* DO_LEVEL_KIND */
							}
						}
					}
				}
			}

			Group -> Special . Group . MaxOffset  = MaxLeft;
			Group -> Special . Group . MaxSize    = MaxWidth;

			if(Group -> Special . Group . Paging)
				Height = MaxHeight;
			else
				Height = Top;

			Width = MaxLeft + MaxWidth;
		}

		Group -> Left	= 0;
		Group -> Top	= 0;
		Group -> Width	= Width;
		Group -> Height = Height;

		if(Group -> Label || Group -> Special . Group . Frame)
		{
			if(Group -> Label)
			{
				Group -> LabelWidth = LT_LabelWidth(Handle,Group -> Label) + 2 * Handle -> GlyphWidth;

				Group -> Height += Handle -> RPort . TxHeight + 2 * Handle -> InterHeight + 3;
			}
			else
			{
				Group -> LabelWidth = 0;

				Group -> Height += 2 + 2 * Handle -> InterHeight + 3;
			}

			if(Group -> LabelWidth > Group -> Width)
			{
				Group -> Special . Group . ExtraLeft += (Group -> LabelWidth - Group -> Width) / 2;

				Group -> Width = Group -> LabelWidth;
			}

			Group -> Width += 2 * (Handle -> GlyphWidth + Handle -> InterWidth) + 8;
		}

		if(ReturnKey)
			Handle -> ReturnKey = ReturnKey;

		if(EscKey)
			Handle -> EscKey = EscKey;

		if(CursorKey)
			Handle -> CursorKey = CursorKey;

		if(TabKey)
			Handle -> TabKey = TabKey;
	}
}
