Procházet zdrojové kódy

FrameSet Stacking Windows into TabBooks

This updates allows windows to be stacked into tab books.
Peter Robinson před 2 roky
rodič
revize
048d9a568d

+ 98 - 0
editor/EditorCore/Themes/BaseTheme/BaseTheme.cs

@@ -2079,9 +2079,107 @@ function BaseTheme::makeFrameSetProfile(%this)
 		fillColor = %this.adjustValue(%this.color1, 10); 
 		fillColor = %this.adjustValue(%this.color1, 10); 
 		fillColorHL = %this.color2; 
 		fillColorHL = %this.color2; 
 		fillColorSL = %this.setAlpha(%this.color4, 50); 
 		fillColorSL = %this.setAlpha(%this.color4, 50); 
+		
+		fontColor = %this.color4;
+		fontColorHL = %this.color5;
 
 
 		borderDefault = %borderProfile;
 		borderDefault = %borderProfile;
 	};
 	};
+	%windowBorderH = new GuiBorderProfile()
+	{
+		padding = 10;
+		paddingHL = 10;
+		paddingSL = 10;
+		paddingNA = 4;
+
+		border = 1;
+		borderHL = 1;
+		borderSL = 1;
+		borderNA = 1;
+
+		borderColor = %this.color1;
+		borderColorHL = %this.color1;
+		borderColorSL = %this.color1;
+		borderColorNA = %this.color1;
+
+		margin = 1;
+		marginHL = 1;
+		marginSL = 1;
+		marginNA = 1;
+	};
+
+
+	%windowBorderT = new GuiBorderProfile()
+	{
+		border = 1;
+		borderHL = 1;
+		borderSL = 2;
+		borderNA = 1;
+
+		borderColor = %this.color1;
+		borderColorHL = %this.color1;
+		borderColorSL = %this.color5;
+		borderColorNA = %this.color1;
+
+		margin = 3;
+		marginHL = 3;
+		marginSL = 3;
+		marginNA = 3;
+
+		padding = 1;
+		paddingHL = 1;
+		paddingSL = 0;
+		paddingNA = 1;
+	};
+
+	%this.frameSetTabProfile = new GuiControlProfile()
+	{
+		fillColor = %this.color2;
+		fillColorHL = %this.adjustValue(%this.color2, 1);
+		fillColorSL = %this.adjustValue(%this.color2, 5);
+		fillColorNA = %this.adjustValue(%this.color1, 5);
+
+		fontType = %this.font[2];
+		fontDirectory = %this.fontDirectory;
+		fontSize = %this.fontSize - 1;
+		fontColor = %this.color3;
+		fontColorHL = %this.adjustValue(%this.color3, 10);
+		fontColorSL = %this.color5;
+		fontColorNA = %this.color2;
+		align = center;
+		vAlign = bottom;
+
+		borderLeft = %windowBorderH;
+		borderRight = %windowBorderH;
+		borderTop = %windowBorderT;
+		borderBottom = %this.emptyBorder;
+	};
+
+	%this.frameSetTabBookProfile = new GuiControlProfile()
+	{
+		fillColor = %this.adjustValue(%this.color1, 10); 
+		fillColorHL = %this.adjustValue(%this.color1, 20); 
+		fillColorSL = %this.color4; 
+		fillColorNA = %this.color2; 
+		
+		borderDefault = %this.emptyBorder;
+
+		tab = false;
+		canKeyFocus = true;
+	};
+
+	%this.frameSetTabPageProfile = new GuiControlProfile()
+	{
+		fillColor = %this.color1; 
+		fillColorHL = %this.color1; 
+		fillColorSL = %this.color1; 
+		fillColorNA = %this.color1; 
+		
+		borderDefault = %this.emptyBorder;
+
+		tab = false;
+		canKeyFocus = true;
+	};
 }
 }
 
 
 //Positive values are brighter, negative are darker
 //Positive values are brighter, negative are darker

+ 3 - 0
editor/GuiEditor/GuiEditor.cs

@@ -43,6 +43,9 @@ function GuiEditor::create( %this )
 	};
 	};
     ThemeManager.setProfile(%this.content, "frameSetProfile");
     ThemeManager.setProfile(%this.content, "frameSetProfile");
     ThemeManager.setProfile(%this.content, "dropButtonProfile", "dropButtonProfile");
     ThemeManager.setProfile(%this.content, "dropButtonProfile", "dropButtonProfile");
+    ThemeManager.setProfile(%this.content, "frameSetTabBookProfile", "tabBookProfile");
+    ThemeManager.setProfile(%this.content, "frameSetTabProfile", "tabProfile");
+    ThemeManager.setProfile(%this.content, "frameSetTabPageProfile", "tabPageProfile");
     %this.guiPage.add(%this.content);
     %this.guiPage.add(%this.content);
 
 
     %idList = %this.content.createHorizontalSplit(1);
     %idList = %this.content.createHorizontalSplit(1);

+ 168 - 2
engine/source/gui/containers/guiFrameSetCtrl.cc

@@ -26,6 +26,9 @@
 #include "gui/guiDefaultControlRender.h"
 #include "gui/guiDefaultControlRender.h"
 #include "gui/guiCanvas.h"
 #include "gui/guiCanvas.h"
 #include "gui/containers/guiWindowCtrl.h"
 #include "gui/containers/guiWindowCtrl.h"
+#include "graphics/dgl.h"
+#include "gui/containers/guiTabBookCtrl.h"
+#include "gui/containers/guiTabPageCtrl.h"
 
 
 #include "guiFrameSetCtrl_ScriptBinding.h"
 #include "guiFrameSetCtrl_ScriptBinding.h"
 
 
@@ -133,6 +136,8 @@ void GuiFrameSetCtrl::Frame::sizeInsertButtons(const Point2I& newPosition, const
 		mTopButtonRect = RectI(newPosition.x + ((newExtent.x - size) / 2), newPosition.y + gutter, size, size);
 		mTopButtonRect = RectI(newPosition.x + ((newExtent.x - size) / 2), newPosition.y + gutter, size, size);
 		mBottomButtonRect = RectI(newPosition.x + ((newExtent.x - size) / 2), newPosition.y + newExtent.y - (gutter + size), size, size);
 		mBottomButtonRect = RectI(newPosition.x + ((newExtent.x - size) / 2), newPosition.y + newExtent.y - (gutter + size), size, size);
 	}
 	}
+
+	mCenterButtonRect = RectI(newPosition.x + ((newExtent.x - size) / 2), newPosition.y + ((newExtent.y - size) / 2), size, size);
 }
 }
 
 
 GuiFrameSetCtrl::Frame* GuiFrameSetCtrl::Frame::findFrame(const S32 frameID)
 GuiFrameSetCtrl::Frame* GuiFrameSetCtrl::Frame::findFrame(const S32 frameID)
@@ -269,6 +274,13 @@ GuiFrameSetCtrl::GuiFrameSetCtrl()
 	mDropButtonProfile = NULL;
 	mDropButtonProfile = NULL;
 	setField("dropButtonProfile", "GuiButtonProfile");
 	setField("dropButtonProfile", "GuiButtonProfile");
 
 
+	mTabBookProfile = NULL;
+	mTabProfile = NULL;
+	mTabPageProfile = NULL;
+	setField("tabBookProfile", "GuiDefaultProfile");
+	setField("tabProfile", "GuiTabProfile");
+	setField("tabPageProfile", "GuiDefaultProfile");
+
 	mLeftRightCursor = NULL;
 	mLeftRightCursor = NULL;
 	mUpDownCursor = NULL;
 	mUpDownCursor = NULL;
 }
 }
@@ -288,6 +300,9 @@ void GuiFrameSetCtrl::initPersistFields()
 	addField("dropButtonProfile", TypeGuiProfile, Offset(mDropButtonProfile, GuiFrameSetCtrl));
 	addField("dropButtonProfile", TypeGuiProfile, Offset(mDropButtonProfile, GuiFrameSetCtrl));
 	addField("leftRightCursor", TypeGuiCursor, Offset(mLeftRightCursor, GuiFrameSetCtrl));
 	addField("leftRightCursor", TypeGuiCursor, Offset(mLeftRightCursor, GuiFrameSetCtrl));
 	addField("upDownCursor", TypeGuiCursor, Offset(mUpDownCursor, GuiFrameSetCtrl));
 	addField("upDownCursor", TypeGuiCursor, Offset(mUpDownCursor, GuiFrameSetCtrl));
+	addProtectedField("TabBookProfile", TypeGuiProfile, Offset(mTabBookProfile, GuiFrameSetCtrl), &setBookProfileFn, &defaultProtectedGetFn, &defaultProtectedWriteFn, "");
+	addProtectedField("TabProfile", TypeGuiProfile, Offset(mTabProfile, GuiFrameSetCtrl), &setTabProfileFn, &defaultProtectedGetFn, &defaultProtectedWriteFn, "");
+	addProtectedField("TabPageProfile", TypeGuiProfile, Offset(mTabPageProfile, GuiFrameSetCtrl), &setPageProfileFn, &defaultProtectedGetFn, &defaultProtectedWriteFn, "");
 }
 }
 
 
 //------------------------------------------------------------------------------
 //------------------------------------------------------------------------------
@@ -300,6 +315,15 @@ bool GuiFrameSetCtrl::onWake()
 	if (mDropButtonProfile != NULL)
 	if (mDropButtonProfile != NULL)
 		mDropButtonProfile->incRefCount();
 		mDropButtonProfile->incRefCount();
 
 
+	if (mTabBookProfile != NULL)
+		mTabBookProfile->incRefCount();
+
+	if (mTabProfile != NULL)
+		mTabProfile->incRefCount();
+
+	if (mTabPageProfile != NULL)
+		mTabPageProfile->incRefCount();
+
 	return true;
 	return true;
 }
 }
 
 
@@ -311,6 +335,15 @@ void GuiFrameSetCtrl::onSleep()
 
 
 	if (mDropButtonProfile != NULL)
 	if (mDropButtonProfile != NULL)
 		mDropButtonProfile->decRefCount();
 		mDropButtonProfile->decRefCount();
+
+	if (mTabBookProfile != NULL)
+		mTabBookProfile->decRefCount();
+
+	if (mTabProfile != NULL)
+		mTabProfile->decRefCount();
+
+	if (mTabPageProfile != NULL)
+		mTabPageProfile->decRefCount();
 }
 }
 
 
 //------------------------------------------------------------------------------
 //------------------------------------------------------------------------------
@@ -684,6 +717,11 @@ void GuiFrameSetCtrl::renderDropOptions(GuiWindowCtrl* window)
 			renderDropButton(frame, frame->mTopButtonRect, cursorPt, frame->localPosition, fillExt, GuiDirection::Up);
 			renderDropButton(frame, frame->mTopButtonRect, cursorPt, frame->localPosition, fillExt, GuiDirection::Up);
 			renderDropButton(frame, frame->mBottomButtonRect, cursorPt, Point2I(frame->localPosition.x, frame->localPosition.y + frame->extent.y - height), fillExt, GuiDirection::Down);
 			renderDropButton(frame, frame->mBottomButtonRect, cursorPt, Point2I(frame->localPosition.x, frame->localPosition.y + frame->extent.y - height), fillExt, GuiDirection::Down);
 		}
 		}
+
+		if (frame->isAnchored || (!frame->control && !frame->child1 && !frame->child2))
+		{
+			renderDropButton(frame, frame->mCenterButtonRect, cursorPt, frame->localPosition, frame->extent, GuiDirection::Center);
+		}
 	}
 	}
 }
 }
 
 
@@ -701,9 +739,20 @@ void GuiFrameSetCtrl::renderDropButton(const GuiFrameSetCtrl::Frame* frame, cons
 	RectI globalButtonRect = RectI(localToGlobalCoord(buttonRect.point), buttonRect.extent);
 	RectI globalButtonRect = RectI(localToGlobalCoord(buttonRect.point), buttonRect.extent);
 	renderUniversalRect(globalButtonRect, mDropButtonProfile, state);
 	renderUniversalRect(globalButtonRect, mDropButtonProfile, state);
 
 
-	dglSetBitmapModulation(getFontColor(mDropButtonProfile, state));
 	ColorI triColor = getFontColor(mDropButtonProfile, state);
 	ColorI triColor = getFontColor(mDropButtonProfile, state);
-	renderTriangleIcon(globalButtonRect, triColor, direction, 10);
+	if(direction != GuiDirection::Center)
+	{
+		renderTriangleIcon(globalButtonRect, triColor, direction, 10);
+	}
+	else
+	{
+		RectI iconRect = RectI(buttonRect);
+		iconRect.inset(15, 15);
+		RectI lineH = RectI(localToGlobalCoord(Point2I(iconRect.point.x, iconRect.point.y + 4)), Point2I(iconRect.extent.x, 2));
+		RectI lineV = RectI(localToGlobalCoord(Point2I(iconRect.point.x + 4, iconRect.point.y)), Point2I(2, iconRect.extent.y));
+		dglDrawRectFill(lineH, triColor);
+		dglDrawRectFill(lineV, triColor);
+	}
 }
 }
 
 
 void GuiFrameSetCtrl::handleDropButtons(GuiWindowCtrl* window)
 void GuiFrameSetCtrl::handleDropButtons(GuiWindowCtrl* window)
@@ -756,6 +805,48 @@ void GuiFrameSetCtrl::handleDropButtons(GuiWindowCtrl* window)
 			frame->child2->extent = Point2I(frame->extent.x, height);
 			frame->child2->extent = Point2I(frame->extent.x, height);
 			hitButton = true;
 			hitButton = true;
 		}
 		}
+		else if (frame->mCenterButtonRect.pointInRect(cursorPt))
+		{
+			if (!frame->control)
+			{
+				frame->control = window;
+				hitButton = true;
+			}
+			else
+			{
+				GuiTabBookCtrl* book = dynamic_cast<GuiTabBookCtrl*>(frame->control);
+				GuiTabPageCtrl* page = nullptr;
+				if (!book)
+				{
+					book = new GuiTabBookCtrl();
+					book->setControlProfile(mTabBookProfile);
+					book->setControlTabProfile(mTabProfile);
+					book->mBounds.set(frame->localPosition, frame->extent);
+					book->mIsFrameSetGenerated = true;
+					book->registerObject();
+					book->addNewPage();	
+					page = dynamic_cast<GuiTabPageCtrl*>((*book)[0]);
+					page->setControlProfile(mTabPageProfile);
+					GuiWindowCtrl* windowChild = dynamic_cast<GuiWindowCtrl*>(frame->control);
+					GuiControl* child = dynamic_cast<GuiControl*>(frame->control);
+					if (windowChild)
+					{
+						windowChild->dockToPage();
+					}
+					page->setText(child->getText());
+					frame->control = book;
+					page->addObject(child);
+					addObject(book);
+				}
+				window->dockToPage();
+				book->addNewPage();
+				page = dynamic_cast<GuiTabPageCtrl*>((*book)[book->size() - 1]);
+				page->setControlProfile(mTabPageProfile);
+				page->setText(window->getText());
+				page->addObject(window);
+				book->selectPage(window->getText());
+			}
+		}
 
 
 		if (hitButton)
 		if (hitButton)
 		{
 		{
@@ -776,6 +867,81 @@ void GuiFrameSetCtrl::setDropButtonProfile(GuiControlProfile* prof)
 		mDropButtonProfile->incRefCount();
 		mDropButtonProfile->incRefCount();
 }
 }
 
 
+void GuiFrameSetCtrl::setTabBookProfile(GuiControlProfile* prof)
+{
+	AssertFatal(prof, "GuiFrameSetCtrl::setTabBookProfile: invalid content profile");
+	if (prof == mTabBookProfile)
+		return;
+	if (mAwake)
+		mTabBookProfile->decRefCount();
+	mTabBookProfile = prof;
+	if (mAwake)
+		mTabBookProfile->incRefCount();
+
+	//Cycle through all children and replace the profiles of frameSetGenerated books.
+	SimSet::iterator i;
+	for (i = begin(); i != end(); i++)
+	{
+		GuiTabBookCtrl* book = static_cast<GuiTabBookCtrl*>(*i);
+		if (book && book->mIsFrameSetGenerated)
+		{
+			book->setControlProfile(prof);
+		}
+	}
+}
+
+void GuiFrameSetCtrl::setTabProfile(GuiControlProfile* prof)
+{
+	AssertFatal(prof, "GuiFrameSetCtrl::setTabProfile: invalid content profile");
+	if (prof == mTabProfile)
+		return;
+	if (mAwake)
+		mTabProfile->decRefCount();
+	mTabProfile = prof;
+	if (mAwake)
+		mTabProfile->incRefCount();
+
+	SimSet::iterator i;
+	for (i = begin(); i != end(); i++)
+	{
+		GuiTabBookCtrl* book = static_cast<GuiTabBookCtrl*>(*i);
+		if (book && book->mIsFrameSetGenerated)
+		{
+			book->setControlTabProfile(prof);
+		}
+	}
+}
+
+void GuiFrameSetCtrl::setTabPageProfile(GuiControlProfile* prof)
+{
+	AssertFatal(prof, "GuiFrameSetCtrl::setTabPageProfile: invalid content profile");
+	if (prof == mTabPageProfile)
+		return;
+	if (mAwake)
+		mTabPageProfile->decRefCount();
+	mTabPageProfile = prof;
+	if (mAwake)
+		mTabPageProfile->incRefCount();
+
+	SimSet::iterator i;
+	for (i = begin(); i != end(); i++)
+	{
+		GuiTabBookCtrl* book = static_cast<GuiTabBookCtrl*>(*i);
+		if (book && book->mIsFrameSetGenerated)
+		{
+			SimSet::iterator j;
+			for (j = begin(); j != end(); j++)
+			{
+				GuiTabPageCtrl* page = static_cast<GuiTabPageCtrl*>(*i);
+				if (page)
+				{
+					page->setControlProfile(prof);
+				}
+			}
+		}
+	}
+}
+
 void GuiFrameSetCtrl::setControlLeftRightCursor(GuiCursor* cursor)
 void GuiFrameSetCtrl::setControlLeftRightCursor(GuiCursor* cursor)
 {
 {
 	AssertFatal(cursor, "GuiFrameSetCtrl::setControlLeftRightCursor: invalid cursor");
 	AssertFatal(cursor, "GuiFrameSetCtrl::setControlLeftRightCursor: invalid cursor");

+ 13 - 1
engine/source/gui/containers/guiFrameSetCtrl.h

@@ -36,7 +36,7 @@ public:
 		Frame() : Frame(nullptr, nullptr) { }
 		Frame() : Frame(nullptr, nullptr) { }
 		Frame(GuiFrameSetCtrl* theOwner, Frame* theParent) : owner(theOwner), parent(theParent), child1(nullptr), child2(nullptr), 
 		Frame(GuiFrameSetCtrl* theOwner, Frame* theParent) : owner(theOwner), parent(theParent), child1(nullptr), child2(nullptr), 
 			control(nullptr), isVertical(true), id(1), extent(Point2I(100, 100)), dividerRect(RectI()),
 			control(nullptr), isVertical(true), id(1), extent(Point2I(100, 100)), dividerRect(RectI()),
-			localPosition(Point2I(0, 0)), mLeftButtonRect(RectI()), mRightButtonRect(RectI()),
+			localPosition(Point2I(0, 0)), mLeftButtonRect(RectI()), mRightButtonRect(RectI()), mCenterButtonRect(RectI()),
 			mTopButtonRect(RectI()), mBottomButtonRect(RectI()), isAnchored(true), hasLeftRightButtons(false), hasTopBottomButtons(false) { }
 			mTopButtonRect(RectI()), mBottomButtonRect(RectI()), isAnchored(true), hasLeftRightButtons(false), hasTopBottomButtons(false) { }
 		virtual ~Frame() { }
 		virtual ~Frame() { }
 		void deleteChildren();
 		void deleteChildren();
@@ -51,6 +51,7 @@ public:
 		RectI mRightButtonRect;
 		RectI mRightButtonRect;
 		RectI mTopButtonRect;
 		RectI mTopButtonRect;
 		RectI mBottomButtonRect;
 		RectI mBottomButtonRect;
+		RectI mCenterButtonRect;
 		bool hasLeftRightButtons;
 		bool hasLeftRightButtons;
 		bool hasTopBottomButtons;
 		bool hasTopBottomButtons;
 
 
@@ -76,6 +77,10 @@ public:
 	U8 mDividerThickness; 
 	U8 mDividerThickness; 
 	const S32 minSize = 20;
 	const S32 minSize = 20;
 
 
+	GuiControlProfile* mTabBookProfile;
+	GuiControlProfile* mTabProfile;
+	GuiControlProfile* mTabPageProfile;
+
 
 
 private:
 private:
 
 
@@ -112,9 +117,16 @@ public:
 	void getCursor(GuiCursor*& cursor, bool& showCursor, const GuiEvent& lastGuiEvent);
 	void getCursor(GuiCursor*& cursor, bool& showCursor, const GuiEvent& lastGuiEvent);
 
 
 	void setDropButtonProfile(GuiControlProfile* prof);
 	void setDropButtonProfile(GuiControlProfile* prof);
+	void setTabBookProfile(GuiControlProfile* prof);
+	void setTabProfile(GuiControlProfile* prof);
+	void setTabPageProfile(GuiControlProfile* prof);
 	void setControlLeftRightCursor(GuiCursor* cursor);
 	void setControlLeftRightCursor(GuiCursor* cursor);
 	void setControlUpDownCursor(GuiCursor* cursor);
 	void setControlUpDownCursor(GuiCursor* cursor);
 
 
+	static bool setBookProfileFn(void* obj, const char* data) { GuiControlProfile* profile; Sim::findObject(data, profile); static_cast<GuiFrameSetCtrl*>(obj)->setTabBookProfile(profile); return true; }
+	static bool setTabProfileFn(void* obj, const char* data) { GuiControlProfile* profile; Sim::findObject(data, profile); static_cast<GuiFrameSetCtrl*>(obj)->setTabProfile(profile); return true; }
+	static bool setPageProfileFn(void* obj, const char* data) { GuiControlProfile* profile; Sim::findObject(data, profile); static_cast<GuiFrameSetCtrl*>(obj)->setTabPageProfile(profile); return true; }
+
 	DECLARE_CONOBJECT(GuiFrameSetCtrl);
 	DECLARE_CONOBJECT(GuiFrameSetCtrl);
 };
 };
 
 

+ 4 - 1
engine/source/gui/containers/guiTabBookCtrl.cc

@@ -64,9 +64,11 @@ GuiTabBookCtrl::GuiTabBookCtrl()
    mMinTabWidth = 64;
    mMinTabWidth = 64;
    mTabWidth = 64;
    mTabWidth = 64;
    mIsContainer = true;
    mIsContainer = true;
+   mIsFrameSetGenerated = false;
 
 
    mTabProfile = NULL;
    mTabProfile = NULL;
 
 
+   setField("profile", "GuiDefaultProfile");
    setField("TabProfile", "GuiTabProfile");
    setField("TabProfile", "GuiTabProfile");
 }
 }
 
 
@@ -171,7 +173,8 @@ bool GuiTabBookCtrl::onWake()
       mBitmapBounds = mProfile->mBitmapArrayRects.address();
       mBitmapBounds = mProfile->mBitmapArrayRects.address();
 
 
    //increment the tab profile
    //increment the tab profile
-   mTabProfile->incRefCount();
+   if (mTabProfile != NULL)
+		mTabProfile->incRefCount();
 
 
    return true;
    return true;
 }
 }

+ 2 - 0
engine/source/gui/containers/guiTabBookCtrl.h

@@ -115,6 +115,8 @@ private:
 
 
    static void initPersistFields();
    static void initPersistFields();
 
 
+   bool mIsFrameSetGenerated;
+
     /// @name Control Events
     /// @name Control Events
     /// @{
     /// @{
    bool onAdd();
    bool onAdd();

+ 47 - 18
engine/source/gui/containers/guiWindowCtrl.cc

@@ -27,6 +27,7 @@
 #include "gui/containers/guiWindowCtrl.h"
 #include "gui/containers/guiWindowCtrl.h"
 #include "gui/guiDefaultControlRender.h"
 #include "gui/guiDefaultControlRender.h"
 #include "gui/containers/guiFrameSetCtrl.h"
 #include "gui/containers/guiFrameSetCtrl.h"
+#include "gui/containers/guiTabPageCtrl.h"
 
 
 #include "guiWindowCtrl_ScriptBinding.h"
 #include "guiWindowCtrl_ScriptBinding.h"
 
 
@@ -78,6 +79,8 @@ GuiWindowCtrl::GuiWindowCtrl(void)
    mLeftRightCursor = NULL;
    mLeftRightCursor = NULL;
    mUpDownCursor = NULL;
    mUpDownCursor = NULL;
    mNWSECursor = NULL;
    mNWSECursor = NULL;
+
+   mPageDocked = false;
 }
 }
 
 
 void GuiWindowCtrl::initPersistFields()
 void GuiWindowCtrl::initPersistFields()
@@ -173,6 +176,20 @@ GuiControl* GuiWindowCtrl::findHitControl(const Point2I &pt, S32 initialLayer)
       return this;
       return this;
 }
 }
 
 
+void GuiWindowCtrl::dockToPage()
+{
+	mPageDocked = true;
+	setUpdate();
+	Point2I newExtent = mBounds.extent;
+	Point2I oldExtent = Point2I(newExtent.x, newExtent.y - mTitleHeight);
+	iterator i;
+	for (i = begin(); i != end(); i++)
+	{
+		GuiControl* ctrl = static_cast<GuiControl*>(*i);
+		ctrl->parentResized(oldExtent - (ctrl->mRenderInsetLT + ctrl->mRenderInsetRB), newExtent - (ctrl->mRenderInsetLT + ctrl->mRenderInsetRB));
+	}
+}
+
 void GuiWindowCtrl::resize(const Point2I &newPosition, const Point2I &newExtent)
 void GuiWindowCtrl::resize(const Point2I &newPosition, const Point2I &newExtent)
 {
 {
 	GuiFrameSetCtrl* frameSet = dynamic_cast<GuiFrameSetCtrl*>(getParent());
 	GuiFrameSetCtrl* frameSet = dynamic_cast<GuiFrameSetCtrl*>(getParent());
@@ -181,6 +198,14 @@ void GuiWindowCtrl::resize(const Point2I &newPosition, const Point2I &newExtent)
 		mStandardBounds = mBounds;
 		mStandardBounds = mBounds;
 		mMaximized = true;
 		mMaximized = true;
 	}
 	}
+
+	GuiTabPageCtrl* page = dynamic_cast<GuiTabPageCtrl*>(getParent());
+	if (page && mPageDocked)
+	{
+		Parent::resize(Point2I::Zero, page->getExtent());
+		return;
+	}
+
    Parent::resize(newPosition, newExtent);
    Parent::resize(newPosition, newExtent);
 }
 }
 
 
@@ -693,33 +718,37 @@ void GuiWindowCtrl::onRender(Point2I offset, const RectI &updateRect)
 	}
 	}
 
 
 	//Render the title bar
 	//Render the title bar
-   Point2I extent = Point2I(mBounds.extent.x, mTitleHeight);
-	RectI ctrlRectTitle = applyMargins(offset, extent, currentState, mProfile);
-	if (!ctrlRectTitle.isValidRect())
+	if(!mPageDocked)
 	{
 	{
-		return;
-	}
-	mTitleBar.set(Point2I(ctrlRectTitle.point.x - offset.x, ctrlRectTitle.point.y - offset.y), ctrlRectTitle.extent);
-	renderUniversalRect(ctrlRectTitle, mProfile, currentState);
+		Point2I extent = Point2I(mBounds.extent.x, mTitleHeight);
+		RectI ctrlRectTitle = applyMargins(offset, extent, currentState, mProfile);
+		if (!ctrlRectTitle.isValidRect())
+		{
+			return;
+		}
+		mTitleBar.set(Point2I(ctrlRectTitle.point.x - offset.x, ctrlRectTitle.point.y - offset.y), ctrlRectTitle.extent);
+		renderUniversalRect(ctrlRectTitle, mProfile, currentState);
 
 
-	//Render Text and buttons
-	dglSetBitmapModulation(getFontColor(mProfile, currentState));
-	RectI fillRectTitle = applyBorders(ctrlRectTitle.point, ctrlRectTitle.extent, currentState, mProfile);
-	RectI contentRectTitle = applyPadding(fillRectTitle.point, fillRectTitle.extent, currentState, mProfile);
+		//Render Text and buttons
+		dglSetBitmapModulation(getFontColor(mProfile, currentState));
+		RectI fillRectTitle = applyBorders(ctrlRectTitle.point, ctrlRectTitle.extent, currentState, mProfile);
+		RectI contentRectTitle = applyPadding(fillRectTitle.point, fillRectTitle.extent, currentState, mProfile);
 
 
-	if (contentRectTitle.isValidRect())
-	{
-		RectI textRect = renderButtons(offset, contentRectTitle);
-		renderText(textRect.point, textRect.extent, mText, mProfile);
+		if (contentRectTitle.isValidRect())
+		{
+			RectI textRect = renderButtons(offset, contentRectTitle);
+			renderText(textRect.point, textRect.extent, mText, mProfile);
+		}
 	}
 	}
 
 
 	//Render window contents
 	//Render window contents
 	if (!mMinimized)
 	if (!mMinimized)
 	{
 	{
 		currentState = currentState != SelectedState ? NormalState : SelectedState;
 		currentState = currentState != SelectedState ? NormalState : SelectedState;
-      Point2I offsetWithTileHeight = Point2I(offset.x, offset.y + mTitleHeight);
-      Point2I boundsExtentMinusTileHeight = Point2I(mBounds.extent.x, mBounds.extent.y - mTitleHeight);
-		RectI ctrlRectWindow = applyMargins(offsetWithTileHeight, boundsExtentMinusTileHeight, currentState, mContentProfile);
+		S32 titleHeight = mPageDocked ? 0 : mTitleHeight;
+		Point2I offsetWithTitleHeight = Point2I(offset.x, offset.y + titleHeight);
+		Point2I boundsExtentMinusTitleHeight = Point2I(mBounds.extent.x, mBounds.extent.y - titleHeight);
+		RectI ctrlRectWindow = applyMargins(offsetWithTitleHeight, boundsExtentMinusTitleHeight, currentState, mContentProfile);
 		if (!ctrlRectWindow.isValidRect())
 		if (!ctrlRectWindow.isValidRect())
 		{
 		{
 			return;
 			return;

+ 2 - 0
engine/source/gui/containers/guiWindowCtrl.h

@@ -103,6 +103,8 @@ class GuiWindowCtrl : public GuiControl
 
 
 	   bool mDepressed;
 	   bool mDepressed;
 	   Region curHitRegion;
 	   Region curHitRegion;
+	   bool mPageDocked; //True when docked in a GuiTabPageCtrl. 
+	   void dockToPage();
 
 
 	   Region findHitRegion(const Point2I &);
 	   Region findHitRegion(const Point2I &);
 	   GuiControlState getRegionCurrentState(GuiWindowCtrl::Region region);
 	   GuiControlState getRegionCurrentState(GuiWindowCtrl::Region region);

+ 2 - 1
engine/source/gui/guiTypes.h

@@ -98,7 +98,8 @@ enum class GuiDirection
 	Up,				
 	Up,				
 	Down,				
 	Down,				
 	Left,				
 	Left,				
-	Right			
+	Right,
+	Center
 };
 };
 
 
 enum AlignmentType
 enum AlignmentType