瀏覽代碼

Complete changes to GuiWindow

The GuiWindow class now fully updated. It uses call back, multiple profiles, and gui cursors for resizing.
Peter Robinson 4 年之前
父節點
當前提交
4ed76dceb6

+ 0 - 0
engine/Link/Debug/libogg/libogg.vcxproj.FileListAbsolute.txt


+ 0 - 0
engine/Link/Debug/libvorbis/libvorbis.vcxproj.FileListAbsolute.txt


+ 0 - 0
engine/Link/Debug/ljpeg/ljpeg.vcxproj.FileListAbsolute.txt


+ 0 - 0
engine/Link/Debug/lpng/lpng.vcxproj.FileListAbsolute.txt


+ 0 - 0
engine/Link/Debug/zlib/zlib.vcxproj.FileListAbsolute.txt


+ 1 - 0
engine/compilers/VisualStudio 2017/Torque 2D.vcxproj

@@ -1152,6 +1152,7 @@
     <ClInclude Include="..\..\source\gui\containers\guiScrollCtrl_ScriptBinding.h" />
     <ClInclude Include="..\..\source\gui\containers\guiTabBookCtrl_ScriptBinding.h" />
     <ClInclude Include="..\..\source\gui\containers\guiTabPageCtrl.h" />
+    <ClInclude Include="..\..\source\gui\containers\guiWindowCtrl_ScriptBinding.h" />
     <ClInclude Include="..\..\source\gui\guiArrayCtrl.h" />
     <ClInclude Include="..\..\source\gui\guiBitmapCtrl.h" />
     <ClInclude Include="..\..\source\gui\guiBubbleTextCtrl.h" />

+ 3 - 0
engine/compilers/VisualStudio 2017/Torque 2D.vcxproj.filters

@@ -3319,6 +3319,9 @@
     <ClInclude Include="..\..\source\gui\containers\guiChainCtrl_ScriptBinding.h">
       <Filter>gui\containers</Filter>
     </ClInclude>
+    <ClInclude Include="..\..\source\gui\containers\guiWindowCtrl_ScriptBinding.h">
+      <Filter>gui\containers</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <ResourceCompile Include="Torque 2D.rc" />

+ 0 - 3
engine/source/gui/containers/guiScrollCtrl.cc

@@ -150,7 +150,6 @@ void GuiScrollCtrl::setControlThumbProfile(GuiControlProfile* prof)
 	mThumbProfile = prof;
 	if (mAwake)
 		mThumbProfile->incRefCount();
-
 }
 
 void GuiScrollCtrl::setControlTrackProfile(GuiControlProfile* prof)
@@ -163,7 +162,6 @@ void GuiScrollCtrl::setControlTrackProfile(GuiControlProfile* prof)
 	mTrackProfile = prof;
 	if (mAwake)
 		mTrackProfile->incRefCount();
-
 }
 
 void GuiScrollCtrl::setControlArrowProfile(GuiControlProfile* prof)
@@ -176,7 +174,6 @@ void GuiScrollCtrl::setControlArrowProfile(GuiControlProfile* prof)
 	mArrowProfile = prof;
 	if (mAwake)
 		mArrowProfile->incRefCount();
-
 }
 
 GuiControl* GuiScrollCtrl::findHitControl(const Point2I& pt, S32 initialLayer)

+ 226 - 78
engine/source/gui/containers/guiWindowCtrl.cc

@@ -27,6 +27,8 @@
 #include "gui/containers/guiWindowCtrl.h"
 #include "gui/guiDefaultControlRender.h"
 
+#include "guiWindowCtrl_ScriptBinding.h"
+
 IMPLEMENT_CONOBJECT(GuiWindowCtrl);
 
 GuiWindowCtrl::GuiWindowCtrl(void)
@@ -71,6 +73,10 @@ GuiWindowCtrl::GuiWindowCtrl(void)
    setField("minButtonProfile", "GuiWindowMinButtonProfile");
    setField("maxButtonProfile", "GuiWindowMaxButtonProfile");
    setField("profile", "GuiWindowProfile");
+
+   mLeftRightCursor = NULL;
+   mUpDownCursor = NULL;
+   mNWSECursor = NULL;
 }
 
 void GuiWindowCtrl::initPersistFields()
@@ -88,6 +94,9 @@ void GuiWindowCtrl::initPersistFields()
    addField("closeButtonProfile", TypeGuiProfile, Offset(mCloseButtonProfile, GuiWindowCtrl));
    addField("minButtonProfile", TypeGuiProfile, Offset(mMinButtonProfile, GuiWindowCtrl));
    addField("maxButtonProfile", TypeGuiProfile, Offset(mMaxButtonProfile, GuiWindowCtrl));
+   addField("leftRightCursor", TypeGuiCursor, Offset(mLeftRightCursor, GuiWindowCtrl));
+   addField("upDownCursor", TypeGuiCursor, Offset(mUpDownCursor, GuiWindowCtrl));
+   addField("nWSECursor", TypeGuiCursor, Offset(mNWSECursor, GuiWindowCtrl));
 }
 
 bool GuiWindowCtrl::isMinimized(S32 &index)
@@ -209,13 +218,12 @@ void GuiWindowCtrl::onTouchDown(const GuiEvent &event)
       else if (curHitRegion == TitleBar)
       {
          mMouseMovingWin = mCanMove;
-         mMouseResizeWidth = false;
-         mMouseResizeHeight = false;
+         ResizeComplete();
       }
    }
    else
    {
-      mMouseMovingWin = false;
+      MoveComplete();
 
       //see if we clicked on the right edge
       if (mResizeWidth && (localPoint.x > mBounds.extent.x - mResizeRightWidth))
@@ -306,9 +314,8 @@ void GuiWindowCtrl::onTouchUp(const GuiEvent &event)
    mouseUnlock();
    setUpdate();
 
-   mMouseMovingWin = false;
-   mMouseResizeWidth = false;
-   mMouseResizeHeight = false;
+   MoveComplete();
+   ResizeComplete();
 
    GuiControl *parent = getParent();
    if (! parent)
@@ -318,7 +325,10 @@ void GuiWindowCtrl::onTouchUp(const GuiEvent &event)
    Point2I localPoint = globalToLocalCoord(event.mousePoint);
    if (closing && mCloseButton.pointInRect(localPoint))
    {
-      //Con::evaluate(mCloseCommand);
+		if(isMethod("onClose"))
+		{
+			Con::executef(this, 1, "onClose");
+		}
    }
    else if (maximizing && mMaximizeButton.pointInRect(localPoint))
    {
@@ -330,6 +340,11 @@ void GuiWindowCtrl::onTouchUp(const GuiEvent &event)
                         mStandardBounds.extent);
          //set the flag
          mMaximized = false;
+
+		 if (isMethod("onRestore"))
+		 {
+			 Con::executef(this, 1, "onRestore");
+		 }
       }
       else
       {
@@ -348,6 +363,11 @@ void GuiWindowCtrl::onTouchUp(const GuiEvent &event)
 
          //set the flag
          mMaximized = true;
+
+		 if (isMethod("onMaximize"))
+		 {
+			 Con::executef(this, 1, "onMaximize");
+		 }
       }
    }
    else if (minimizing && mMinimizeButton.pointInRect(localPoint))
@@ -360,6 +380,11 @@ void GuiWindowCtrl::onTouchUp(const GuiEvent &event)
                         mStandardBounds.extent);
          //set the flag
          mMinimized = false;
+
+		 if (isMethod("onRestore"))
+		 {
+			 Con::executef(this, 1, "onRestore");
+		 }
       }
       else
       {
@@ -419,6 +444,11 @@ void GuiWindowCtrl::onTouchUp(const GuiEvent &event)
 
          //set the flag
          mMinimized = true;
+
+		 if (isMethod("onMinimize"))
+		 {
+			 Con::executef(this, 1, "onMinimize");
+		 }
       }
    }
 
@@ -552,6 +582,19 @@ bool GuiWindowCtrl::onKeyDown(const GuiEvent &event)
    return Parent::onKeyDown(event);
 }
 
+void GuiWindowCtrl::onFocus()
+{
+	//bubble the focus up
+	GuiControl *parent = getParent();
+	if (parent)
+	{
+		parent->pushObjectToBack(this);
+		parent->onFocus();
+	}
+
+	setFirstResponder(mFirstResponder);
+}
+
 void GuiWindowCtrl::selectWindow(void)
 {
    //first make sure this window is the front most of its siblings
@@ -565,6 +608,27 @@ void GuiWindowCtrl::selectWindow(void)
    setFirstResponder(mFirstResponder);
 }
 
+void GuiWindowCtrl::ResizeComplete()
+{
+	if ((mMouseResizeWidth || mMouseResizeHeight) && isMethod("onResize"))
+	{
+		Con::executef(this, 1, "onResize");
+	}
+
+	mMouseResizeWidth = false;
+	mMouseResizeHeight = false;
+}
+
+void GuiWindowCtrl::MoveComplete()
+{
+	if (mMouseMovingWin && isMethod("onMove"))
+	{
+		Con::executef(this, 1, "onMove");
+	}
+
+	mMouseMovingWin = false;
+}
+
 void GuiWindowCtrl::onRender(Point2I offset, const RectI &updateRect)
 {
 	//Does this window have focus (does it or a child receive key events)?
@@ -608,7 +672,7 @@ void GuiWindowCtrl::onRender(Point2I offset, const RectI &updateRect)
 
 	if (contentRectTitle.isValidRect())
 	{
-		RectI textRect = renderButtons(contentRectTitle);
+		RectI textRect = renderButtons(offset, contentRectTitle);
 		renderText(textRect.point, textRect.extent, mText, mProfile);
 	}
 
@@ -634,7 +698,7 @@ void GuiWindowCtrl::onRender(Point2I offset, const RectI &updateRect)
 	}
 }
 
-RectI GuiWindowCtrl::renderButtons(const RectI &contentRect)
+RectI GuiWindowCtrl::renderButtons(const Point2I &offset, const RectI &contentRect)
 {
 	S32 distanceFromEdge = 0;
 
@@ -642,7 +706,7 @@ RectI GuiWindowCtrl::renderButtons(const RectI &contentRect)
 	{
 		GuiControlState state = getRegionCurrentState(Region::CloseButton);
 		RectI content = renderButton(contentRect,  distanceFromEdge, state, mCloseButtonProfile, Icon::Close);
-		mCloseButton.set(Point2I(content.point.x - contentRect.point.x, content.point.y - contentRect.point.y), content.extent);
+		mCloseButton.set(Point2I(content.point.x - offset.x, content.point.y - offset.y), content.extent);
 		distanceFromEdge += content.extent.x;
 
 		GuiBorderProfile *leftProfile = mCloseButtonProfile->getLeftBorder();
@@ -657,7 +721,7 @@ RectI GuiWindowCtrl::renderButtons(const RectI &contentRect)
 	{
 		GuiControlState state = getRegionCurrentState(Region::MaxButton);
 		RectI content = renderButton(contentRect, distanceFromEdge, state, mMaxButtonProfile, Icon::Max);
-		mMaximizeButton.set(Point2I(content.point.x - contentRect.point.x, content.point.y - contentRect.point.y), content.extent);
+		mMaximizeButton.set(Point2I(content.point.x - offset.x, content.point.y - offset.y), content.extent);
 		distanceFromEdge += content.extent.x;
 
 		GuiBorderProfile *leftProfile = mMaxButtonProfile->getLeftBorder();
@@ -672,7 +736,7 @@ RectI GuiWindowCtrl::renderButtons(const RectI &contentRect)
 	{
 		GuiControlState state = getRegionCurrentState(Region::MinButton);
 		RectI content = renderButton(contentRect, distanceFromEdge, state, mMinButtonProfile, Icon::Min);
-		mMinimizeButton.set(Point2I(content.point.x - contentRect.point.x, content.point.y - contentRect.point.y), content.extent);
+		mMinimizeButton.set(Point2I(content.point.x - offset.x, content.point.y - offset.y), content.extent);
 		distanceFromEdge += content.extent.x;
 
 		GuiBorderProfile *leftProfile = mMinButtonProfile->getLeftBorder();
@@ -704,16 +768,16 @@ RectI GuiWindowCtrl::renderButton(const RectI &contentRect, S32 distanceFromEdge
 		//get the right margin and add it to the distance from the edge
 		GuiBorderProfile *rightProfile = profile->getRightBorder();
 		S32 rightSize = (rightProfile) ? rightProfile->getMargin(buttonState) : 0;
-		distanceFromEdge += rightSize;
 		finalButtonRect.point.x = contentRect.point.x + (contentRect.extent.x - finalButtonRect.extent.x) - distanceFromEdge;
+		distanceFromEdge += rightSize;
 	}
 	else
 	{
 		//get the left margin and add it to the disance from the edge
 		GuiBorderProfile *leftProfile = profile->getLeftBorder();
 		S32 leftSize = (leftProfile) ? leftProfile->getMargin(buttonState) : 0;
+		finalButtonRect.point.x = contentRect.point.x + distanceFromEdge;
 		distanceFromEdge += leftSize;
-		finalButtonRect.point.x = distanceFromEdge;
 	}
 	RectI finalButtonContent = applyMargins(finalButtonRect.point, finalButtonRect.extent, buttonState, profile);
 	renderUniversalRect(finalButtonContent, profile, buttonState);
@@ -728,7 +792,17 @@ RectI GuiWindowCtrl::renderButton(const RectI &contentRect, S32 distanceFromEdge
 		//draw the icon
 		if (defaultIcon == Icon::Close)
 		{
+			Point2I p1 = Point2I(contentRect.point.x + 1, contentRect.point.y);
+			Point2I p2 = Point2I(contentRect.point.x, contentRect.point.y + 1);
+			Point2I p3 = Point2I(contentRect.point.x + contentRect.extent.x - 1, contentRect.point.y + contentRect.extent.y);
+			Point2I p4 = Point2I(contentRect.point.x + contentRect.extent.x, contentRect.point.y + contentRect.extent.y - 1);
+			dglDrawQuadFill(p1, p2, p3, p4, profile->getFontColor(buttonState));
 
+			Point2I p5 = Point2I(contentRect.point.x, contentRect.point.y + contentRect.extent.y - 1);
+			Point2I p6 = Point2I(contentRect.point.x + 1, contentRect.point.y + contentRect.extent.y);
+			Point2I p7 = Point2I(contentRect.point.x + contentRect.extent.x, contentRect.point.y + 1);
+			Point2I p8 = Point2I(contentRect.point.x + contentRect.extent.x - 1, contentRect.point.y);
+			dglDrawQuadFill(p5, p6, p7, p8, profile->getFontColor(buttonState));
 		}
 		else if (defaultIcon == Icon::Min)
 		{
@@ -741,7 +815,34 @@ RectI GuiWindowCtrl::renderButton(const RectI &contentRect, S32 distanceFromEdge
 		}
 		else if (defaultIcon == Icon::Max)
 		{
+			//left side
+			S32 h = (contentRect.len_y() / 2) - 1;
+			Point2I p1 = Point2I(contentRect.point.x, contentRect.point.y);
+			Point2I p2 = Point2I(contentRect.point.x, contentRect.point.y + contentRect.extent.y);
+			Point2I p3 = Point2I(contentRect.point.x + 2, contentRect.point.y + contentRect.extent.y);
+			Point2I p4 = Point2I(contentRect.point.x + 2, contentRect.point.y);
+			dglDrawQuadFill(p1, p2, p3, p4, profile->getFontColor(buttonState));
+
+			//right side
+			p1.set(contentRect.point.x + contentRect.extent.x - 2, contentRect.point.y);
+			p2.set(contentRect.point.x + contentRect.extent.x - 2, contentRect.point.y + contentRect.extent.y);
+			p3.set(contentRect.point.x + contentRect.extent.x, contentRect.point.y + contentRect.extent.y);
+			p4.set(contentRect.point.x + contentRect.extent.x, contentRect.point.y);
+			dglDrawQuadFill(p1, p2, p3, p4, profile->getFontColor(buttonState));
 
+			//top
+			p1.set(contentRect.point.x + 2, contentRect.point.y);
+			p2.set(contentRect.point.x + 2, contentRect.point.y + 2);
+			p3.set(contentRect.point.x + contentRect.extent.x - 2, contentRect.point.y + 2);
+			p4.set(contentRect.point.x + contentRect.extent.x - 2, contentRect.point.y);
+			dglDrawQuadFill(p1, p2, p3, p4, profile->getFontColor(buttonState));
+
+			//bottom
+			p1.set(contentRect.point.x + 2, contentRect.point.y + contentRect.extent.y - 2);
+			p2.set(contentRect.point.x + 2, contentRect.point.y + contentRect.extent.y);
+			p3.set(contentRect.point.x + contentRect.extent.x - 2, contentRect.point.y + contentRect.extent.y);
+			p4.set(contentRect.point.x + contentRect.extent.x - 2, contentRect.point.y + contentRect.extent.y - 2);
+			dglDrawQuadFill(p1, p2, p3, p4, profile->getFontColor(buttonState));
 		}
 	}
 
@@ -768,77 +869,124 @@ GuiControlState GuiWindowCtrl::getRegionCurrentState(GuiWindowCtrl::Region regio
 
 void GuiWindowCtrl::getCursor(GuiCursor *&cursor, bool &showCursor, const GuiEvent &lastGuiEvent)
 {
-   Point2I mousePos  = lastGuiEvent.mousePoint;
-   RectI winRect   = mBounds;
-   RectI rightRect = RectI( ( ( winRect.extent.x + winRect.point.x ) - mResizeRightWidth), winRect.point.y, mResizeRightWidth, winRect.extent.y );
-   RectI bottomRect = RectI( winRect.point.x, ( ( winRect.point.y + winRect.extent.y ) - mResizeBottomHeight), winRect.extent.x , mResizeBottomHeight );
+	Point2I mousePos  = lastGuiEvent.mousePoint;
+	RectI winRect   = mBounds;
+	RectI rightRect = RectI( ( ( winRect.extent.x + winRect.point.x ) - mResizeRightWidth), winRect.point.y, mResizeRightWidth, winRect.extent.y );
+	RectI bottomRect = RectI( winRect.point.x, ( ( winRect.point.y + winRect.extent.y ) - mResizeBottomHeight), winRect.extent.x , mResizeBottomHeight );
 
-   bool resizeRight = rightRect.pointInRect( mousePos );
-   bool resizeBottom = bottomRect.pointInRect( mousePos );
+	bool resizeRight = rightRect.pointInRect( mousePos );
+	bool resizeBottom = bottomRect.pointInRect( mousePos );
 
-   if ( resizeRight && resizeBottom && mResizeHeight && mResizeWidth )
-   {
-      if(GuiControl::smCursorChanged != CursorManager::curResizeNWSE)
-      {
-         // We've already changed the cursor, 
-         // so set it back before we change it again.
-         if(GuiControl::smCursorChanged != -1)
-            Input::popCursor();
-
-         // Now change the cursor shape
-         Input::pushCursor(CursorManager::curResizeNWSE);
-         GuiControl::smCursorChanged = CursorManager::curResizeNWSE;
-      }
-
-      //cursor = mNWSECursor;
-   }
+	if ( resizeRight && resizeBottom && mResizeHeight && mResizeWidth )
+	{
+		if (mNWSECursor == NULL)
+		{
+			SimObject *obj;
+			obj = Sim::findObject("NWSECursor");
+			mNWSECursor = dynamic_cast<GuiCursor*>(obj);
+		}
+		if(mNWSECursor != NULL)
+		{
+			cursor = mNWSECursor;
+		}
+	}
       
-   else if ( resizeBottom && mResizeHeight )
-   {
-      if(GuiControl::smCursorChanged != CursorManager::curResizeHorz)
-      {
-         // We've already changed the cursor, 
-         // so set it back before we change it again.
-         if(GuiControl::smCursorChanged != -1)
-            Input::popCursor();
-
-         // Now change the cursor shape
-         Input::pushCursor(CursorManager::curResizeHorz);
-         GuiControl::smCursorChanged = CursorManager::curResizeHorz;
-      }
+	else if ( resizeBottom && mResizeHeight )
+	{
+		if(mUpDownCursor == NULL)
+		{
+			SimObject *obj;
+			obj = Sim::findObject("UpDownCursor");
+			mUpDownCursor = dynamic_cast<GuiCursor*>(obj);
+		}
+		if (mUpDownCursor != NULL)
+		{
+			cursor = mUpDownCursor;
+		}
+	}
+	else if ( resizeRight && mResizeWidth )
+	{
+		if (mLeftRightCursor == NULL)
+		{
+			SimObject *obj;
+			obj = Sim::findObject("LeftRightCursor");
+			mLeftRightCursor = dynamic_cast<GuiCursor*>(obj);
+		}
+		if (mLeftRightCursor != NULL)
+		{
+			cursor = mLeftRightCursor;
+		}
+	}
+}
 
-      //cursor = mUpDownCursor;
-   }
-   else if ( resizeRight && mResizeWidth )
-   {
-      if(GuiControl::smCursorChanged != CursorManager::curResizeVert)
-      {
-         // We've already changed the cursor, 
-         // so set it back before we change it again.
-         if(GuiControl::smCursorChanged != -1)
-            Input::popCursor();
-
-         // Now change the cursor shape
-         Input::pushCursor(CursorManager::curResizeVert);
-         GuiControl::smCursorChanged = CursorManager::curResizeVert;
-      }
+void GuiWindowCtrl::setControlContentProfile(GuiControlProfile* prof)
+{
+	AssertFatal(prof, "GuiWindowCtrl::setControlContentProfile: invalid content profile");
+	if (prof == mContentProfile)
+		return;
+	if (mAwake)
+		mContentProfile->decRefCount();
+	mContentProfile = prof;
+	if (mAwake)
+		mContentProfile->incRefCount();
+}
 
-      //cursor = mLeftRightCursor;
-   }
-   else
-   {
-      if(GuiControl::smCursorChanged != -1)
-      {
-         // We've already changed the cursor, 
-         // so set it back before we change it again.
-         Input::popCursor();
+void GuiWindowCtrl::setControlCloseButtonProfile(GuiControlProfile* prof)
+{
+	AssertFatal(prof, "GuiWindowCtrl::setControlCloseButtonProfile: invalid close button profile");
+	if (prof == mCloseButtonProfile)
+		return;
+	if (mAwake)
+		mCloseButtonProfile->decRefCount();
+	mCloseButtonProfile = prof;
+	if (mAwake)
+		mCloseButtonProfile->incRefCount();
+}
 
-         // We haven't changed it
-         GuiControl::smCursorChanged = -1;
-      }
+void GuiWindowCtrl::setControlMinButtonProfile(GuiControlProfile* prof)
+{
+	AssertFatal(prof, "GuiWindowCtrl::setControlMinButtonProfile: invalid minimize button profile");
+	if (prof == mMinButtonProfile)
+		return;
+	if (mAwake)
+		mMinButtonProfile->decRefCount();
+	mMinButtonProfile = prof;
+	if (mAwake)
+		mMinButtonProfile->incRefCount();
+}
 
-      return;
-   }
+void GuiWindowCtrl::setControlMaxButtonProfile(GuiControlProfile* prof)
+{
+	AssertFatal(prof, "GuiWindowCtrl::setControlMaxButtonProfile: invalid maximize button profile");
+	if (prof == mMaxButtonProfile)
+		return;
+	if (mAwake)
+		mMaxButtonProfile->decRefCount();
+	mMaxButtonProfile = prof;
+	if (mAwake)
+		mMaxButtonProfile->incRefCount();
+}
+
+void GuiWindowCtrl::setControlLeftRightCursor(GuiCursor* cursor)
+{
+	AssertFatal(cursor, "GuiWindowCtrl::setControlLeftRightCursor: invalid cursor");
+	if (cursor == mLeftRightCursor)
+		return;
+	mLeftRightCursor = cursor;
 }
 
+void GuiWindowCtrl::setControlUpDownCursor(GuiCursor* cursor)
+{
+	AssertFatal(cursor, "GuiWindowCtrl::setControlUpDownCursor: invalid cursor");
+	if (cursor == mUpDownCursor)
+		return;
+	mUpDownCursor = cursor;
+}
 
+void GuiWindowCtrl::setControlNWSECursor(GuiCursor* cursor)
+{
+	AssertFatal(cursor, "GuiWindowCtrl::setControlNWSECursor: invalid cursor");
+	if (cursor == mNWSECursor)
+		return;
+	mNWSECursor = cursor;
+}

+ 20 - 1
engine/source/gui/containers/guiWindowCtrl.h

@@ -80,6 +80,14 @@ class GuiWindowCtrl : public GuiControl
 	  GuiControlProfile *mMinButtonProfile; //Used to render the close button.
 	  GuiControlProfile *mMaxButtonProfile; //Used to render the close button.
 
+	  // Sizing Cursors
+	  GuiCursor*        mLeftRightCursor;
+	  GuiCursor*        mUpDownCursor;
+	  GuiCursor*        mNWSECursor;
+
+	  void ResizeComplete();
+	  void MoveComplete();
+
    public:
 	   enum Region
 	   {
@@ -123,6 +131,8 @@ class GuiWindowCtrl : public GuiControl
       void onTouchUp(const GuiEvent &event);
 	  void onTouchLeave(const GuiEvent &event);
 
+	  virtual void onFocus();
+
       //only cycle tabs through the current window, so overwrite the method
       GuiControl* findNextTabable(GuiControl *curResponder, bool firstCall = true);
       GuiControl* findPrevTabable(GuiControl *curResponder, bool firstCall = true);
@@ -133,8 +143,17 @@ class GuiWindowCtrl : public GuiControl
       void selectWindow(void);
 
       void onRender(Point2I offset, const RectI &updateRect);
-	  RectI renderButtons(const RectI &contentRect);
+	  RectI renderButtons(const Point2I &offset, const RectI &contentRect);
 	  RectI renderButton(const RectI &contentRect, S32 distanceFromEdge, GuiControlState buttonState, GuiControlProfile *profile, Icon defaultIcon);
+
+	  void setControlContentProfile(GuiControlProfile* prof);
+	  void setControlCloseButtonProfile(GuiControlProfile* prof);
+	  void setControlMinButtonProfile(GuiControlProfile* prof);
+	  void setControlMaxButtonProfile(GuiControlProfile* prof);
+
+	  void setControlLeftRightCursor(GuiCursor* cursor);
+	  void setControlUpDownCursor(GuiCursor* cursor);
+	  void setControlNWSECursor(GuiCursor* cursor);
 };
 /// @}
 

+ 109 - 0
engine/source/gui/containers/guiWindowCtrl_ScriptBinding.h

@@ -0,0 +1,109 @@
+//-----------------------------------------------------------------------------
+// Copyright (c) 2013 GarageGames, LLC
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to
+// deal in the Software without restriction, including without limitation the
+// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+// sell copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+// IN THE SOFTWARE.
+//-----------------------------------------------------------------------------
+
+ConsoleMethodGroupBeginWithDocs(GuiWindowCtrl, GuiControl)
+
+/*! Sets the profile that will be used for the content of the window
+	@param p The content profile
+	@return No return value
+*/
+ConsoleMethodWithDocs(GuiWindowCtrl, setContentProfile, ConsoleVoid, 3, 3, (GuiControlProfile p))
+{
+	GuiControlProfile* profile;
+
+	if (Sim::findObject(argv[2], profile))
+		object->setControlContentProfile(profile);
+}
+
+/*! Sets the profile that will be used for the close button
+	@param p The close button profile
+	@return No return value
+*/
+ConsoleMethodWithDocs(GuiWindowCtrl, setCloseButtonProfile, ConsoleVoid, 3, 3, (GuiControlProfile p))
+{
+	GuiControlProfile* profile;
+
+	if (Sim::findObject(argv[2], profile))
+		object->setControlCloseButtonProfile(profile);
+}
+
+/*! Sets the profile that will be used for the minimize button
+	@param p The minimize button profile
+	@return No return value
+*/
+ConsoleMethodWithDocs(GuiWindowCtrl, setMinButtonProfile, ConsoleVoid, 3, 3, (GuiControlProfile p))
+{
+	GuiControlProfile* profile;
+
+	if (Sim::findObject(argv[2], profile))
+		object->setControlMinButtonProfile(profile);
+}
+
+/*! Sets the profile that will be used for the maximize button
+	@param p The maximize button profile
+	@return No return value
+*/
+ConsoleMethodWithDocs(GuiWindowCtrl, setMaxButtonProfile, ConsoleVoid, 3, 3, (GuiControlProfile p))
+{
+	GuiControlProfile* profile;
+
+	if (Sim::findObject(argv[2], profile))
+		object->setControlMaxButtonProfile(profile);
+}
+
+/*! Sets the GuiCursor that will be used when resizing the GuiWindow
+	@param c The GuiCursor that will be used when resizing
+	@return No return value
+*/
+ConsoleMethodWithDocs(GuiWindowCtrl, setLeftRightCursor, ConsoleVoid, 3, 3, (GuiCursor c))
+{
+	GuiCursor* cursor;
+
+	if (Sim::findObject(argv[2], cursor))
+		object->setControlLeftRightCursor(cursor);
+}
+
+/*! Sets the GuiCursor that will be used when resizing the GuiWindow
+	@param c The GuiCursor that will be used when resizing
+	@return No return value
+*/
+ConsoleMethodWithDocs(GuiWindowCtrl, setUpDownCursor, ConsoleVoid, 3, 3, (GuiCursor c))
+{
+	GuiCursor* cursor;
+
+	if (Sim::findObject(argv[2], cursor))
+		object->setControlUpDownCursor(cursor);
+}
+
+/*! Sets the GuiCursor that will be used when resizing the GuiWindow
+	@param c The GuiCursor that will be used when resizing
+	@return No return value
+*/
+ConsoleMethodWithDocs(GuiWindowCtrl, setNWSECursor, ConsoleVoid, 3, 3, (GuiCursor c))
+{
+	GuiCursor* cursor;
+
+	if (Sim::findObject(argv[2], cursor))
+		object->setControlNWSECursor(cursor);
+}
+
+ConsoleMethodGroupEndWithDocs(GuiWindowCtrl)

+ 9 - 9
engine/source/gui/guiCanvas.cc

@@ -611,6 +611,9 @@ void GuiCanvas::rootMouseDown(const GuiEvent &event)
          GuiControl *ctrl = static_cast<GuiControl *>(*i);
          GuiControl *controlHit = ctrl->findHitControl(event.mousePoint);
 
+		 //Regardless of what the control does, it has the user's focus.
+		 controlHit->onFocus();
+
          if (controlHit->mProfile->mUseInput)
          {
             controlHit->onTouchDown(event);
@@ -660,16 +663,13 @@ void GuiCanvas::rootScreenTouchDown(const GuiEvent &event)
               
             //If the control we hit is not the same one that is locked,  
             // then unlock the existing control.  
-            if (bool(mMouseCapturedControl))  
+            if (bool(mMouseCapturedControl) && mMouseCapturedControl->isMouseLocked() && mMouseCapturedControl != controlHit)  
             {  
-                if(mMouseCapturedControl->isMouseLocked())  
-                {  
-                    if(mMouseCapturedControl != controlHit)  
-                    {  
-                        mMouseCapturedControl->onTouchLeave(event);  
-                    }  
-                }  
-            }  
+                mMouseCapturedControl->onTouchLeave(event);   
+            } 
+			
+			//Regardless of what the control does, it has the user's focus.
+			controlHit->onFocus();
               
 			if (controlHit->mProfile->mUseInput)
 			{

+ 8 - 0
engine/source/gui/guiControl.cc

@@ -1407,6 +1407,14 @@ bool GuiControl::ControlIsChild(GuiControl *child)
    return false;
 }
 
+void GuiControl::onFocus()
+{
+	//bubble the focus up
+	GuiControl *parent = getParent();
+	if (parent)
+		parent->onFocus();
+}
+
 bool GuiControl::isFirstResponder()
 {
    GuiCanvas *root = getRoot();

+ 4 - 0
engine/source/gui/guiControl.h

@@ -547,6 +547,10 @@ public:
     virtual void onMiddleMouseDragged(const GuiEvent &event);
 
     /// @}
+
+	//Called just before onTouch down for the hit control. The focus should then bubble up through the 
+	//controls allowing windows to move to the front.
+	virtual void onFocus();
     
     /// @name Editor Mouse Events
     ///

+ 31 - 0
engine/source/gui/guiTypes.cc

@@ -91,6 +91,37 @@ void GuiCursor::render(const Point2I &pos)
    dglDrawBitmap(mTextureHandle, renderPos);
 }
 
+// Setup the type, this will keep Border profiles from being listed with normal profiles.
+ConsoleType(GuiCursor, TypeGuiCursor, sizeof(GuiCursor*), "")
+
+ConsoleSetType(TypeGuiCursor)
+{
+	GuiCursor *profile = NULL;
+	if (argc == 1)
+		Sim::findObject(argv[0], profile);
+
+	AssertWarn(profile != NULL, avar("GuiCursor: requested gui cursor (%s) does not exist.", argv[0]));
+	if (!profile)
+		profile = dynamic_cast<GuiCursor*>(Sim::findObject("DefaultCursor"));
+
+	AssertFatal(profile != NULL, avar("GuiCursor: unable to find specified cursor (%s) and DefaultCursor does not exist!", argv[0]));
+
+	GuiCursor **obj = (GuiCursor **)dptr;
+	if ((*obj) == profile)
+		return;
+
+	*obj = profile;
+}
+
+ConsoleGetType(TypeGuiCursor)
+{
+	static char returnBuffer[256];
+
+	GuiCursor **obj = (GuiCursor**)dptr;
+	dSprintf(returnBuffer, sizeof(returnBuffer), "%s", *obj ? (*obj)->getName() ? (*obj)->getName() : (*obj)->getIdString() : "");
+	return returnBuffer;
+}
+
 //------------------------------------------------------------------------------
 IMPLEMENT_CONOBJECT(GuiBorderProfile);
 

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

@@ -121,6 +121,7 @@ public:
    void onRemove();
    void render(const Point2I &pos);
 };
+DefineConsoleType(TypeGuiCursor)
 
 /// A GuiBorderProfile holds on the information needed for a single border of a GuiControl.
 /// GuiBorderProfiles can be assigned to a GuiControlProfile to cover one or all of the borders.

+ 8 - 10
toybox/GuiEditorToy/1/assets/gui/guiToolbox.gui

@@ -27,19 +27,17 @@
 		VertSizing = "bottom";
 		position = "640 40";
 		Extent = "220 380";
-		MinExtent = "8 2";
+		MinExtent = "100 100";
 		canSave = "1";
 		Visible = "1";
 		hovertime = "1000";
 		text = "GUI Toolbox";
-		maxLength = "1024";
-		resizeWidth = "1";
-		resizeHeight = "1";
+		resizeWidth = "3";
+		resizeHeight = "3";
 		canMove = "1";
 		canClose = "0";
 		canMinimize = "1";
 		canMaximize = "0";
-		minSize = "50 50";
 
 		new GuiScrollCtrl() {
             canSaveDynamicFields = "0";
@@ -51,7 +49,7 @@
             HorizSizing = "width";
             VertSizing = "height";
             position = "0 0";
-            Extent = "220 360";
+            Extent = "214 357";
             MinExtent = "8 2";
             canSave = "1";
             Visible = "1";
@@ -96,7 +94,7 @@
 		VertSizing = "bottom";
 		position = "60 40";
 		Extent = "360 380";
-		MinExtent = "8 2";
+		MinExtent = "100 100";
 		canSave = "1";
 		Visible = "1";
 		hovertime = "1000";
@@ -120,7 +118,7 @@
             HorizSizing = "width";
             VertSizing = "height";
             position = "0 0";
-            Extent = "360 360";
+            Extent = "354 357";
             MinExtent = "8 2";
             canSave = "1";
             Visible = "1";
@@ -155,7 +153,7 @@
 		VertSizing = "bottom";
 		position = "360 40";
 		Extent = "220 380";
-		MinExtent = "8 2";
+		MinExtent = "100 100";
 		canSave = "1";
 		Visible = "1";
 		hovertime = "1000";
@@ -179,7 +177,7 @@
             HorizSizing = "width";
             VertSizing = "height";
             position = "0 0";
-            Extent = "220 360";
+            Extent = "214 357";
             MinExtent = "8 2";
             canSave = "1";
             Visible = "1";

+ 17 - 6
toybox/Sandbox/1/gui/guiProfiles.cs

@@ -204,6 +204,14 @@ if(!isObject(GuiListBoxProfile)) new GuiControlProfile (GuiListBoxProfile : GuiD
 	category = "defaultListBox";
 };
 
+if(!isObject(GuiWindowBorderProfile)) new GuiBorderProfile (GuiWindowBorderProfile : GuiDefaultBorderProfile)
+{
+	padding = 10;
+	paddingHL = 10;
+	paddingSL = 10;
+	paddingNA = 4;
+};
+
 if(!isObject(GuiWindowProfile)) new GuiControlProfile (GuiWindowProfile : GuiDefaultProfile)
 {
    fillColor = AdjustColorValue($color1, 10);
@@ -211,8 +219,11 @@ if(!isObject(GuiWindowProfile)) new GuiControlProfile (GuiWindowProfile : GuiDef
    fillColorSL = $color4;
    fillColorNA = $color1;
    category = "defaultWindow";
+   align = "Left";
 
    fontColorSL = $color5;
+
+   borderLeft = GuiWindowBorderProfile;
 };
 
 if(!isObject(GuiWindowContentBorderProfile)) new GuiBorderProfile (GuiWindowContentBorderProfile : GuiDefaultBorderProfile)
@@ -220,8 +231,8 @@ if(!isObject(GuiWindowContentBorderProfile)) new GuiBorderProfile (GuiWindowCont
 	borderColor = AdjustColorValue($color1, 10);
 	borderColorSL = AdjustColorValue($color4, -10);
 
-	border = 1;
-	borderSL = 1;
+	border = 3;
+	borderSL = 3;
 };
 
 if(!isObject(GuiWindowContentProfile)) new GuiControlProfile (GuiWindowContentProfile : GuiDefaultProfile)
@@ -240,10 +251,10 @@ if(!isObject(GuiWindowButtonBorderProfile)) new GuiBorderProfile (GuiWindowButto
 	marginSL = 1;
 	marginNA = 1;
 
-	padding = 2;
-	paddingHL = 2;
-	paddingSL = 2;
-	paddingNA = 2;
+	padding = 3;
+	paddingHL = 3;
+	paddingSL = 3;
+	paddingNA = 3;
 };
 
 if(!isObject(GuiWindowCloseButtonProfile)) new GuiControlProfile (GuiWindowCloseButtonProfile : GuiDefaultProfile)