Selaa lähdekoodia

Partial Update to GuiWindow

This brings the GuiWindow partially up-to-date with the rest of the Gui components. The next update should complete the changes.
Peter Robinson 4 vuotta sitten
vanhempi
commit
7507260435

+ 1 - 0
engine/source/graphics/dgl.cc

@@ -904,6 +904,7 @@ void dglDrawRectFill(const RectI &rect, const ColorI &color)
    dglDrawRectFill(rect.point, lowerR, color);
 }
 
+//Start in the top left and move counter-clockwise around the quad.
 void dglDrawQuadFill(const Point2I &point1, const Point2I &point2, const Point2I &point3, const Point2I &point4, const ColorI &color)
 {
 	glEnable(GL_BLEND);

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

@@ -565,6 +565,14 @@ void GuiScrollCtrl::onTouchMove(const GuiEvent& event)
 	curHitRegion = findHitRegion(globalToLocalCoord(event.mousePoint));
 }
 
+void GuiScrollCtrl::onTouchLeave(const GuiEvent &event)
+{
+	if (!mDepressed)
+	{
+		curHitRegion = None;
+	}
+}
+
 bool GuiScrollCtrl::onKeyDown(const GuiEvent &event)
 {
       switch (event.keyCode)

+ 1 - 0
engine/source/gui/containers/guiScrollCtrl.h

@@ -151,6 +151,7 @@ public:
    void onTouchDown(const GuiEvent &event);
    void onTouchUp(const GuiEvent &event);
    void onTouchDragged(const GuiEvent &event);
+   void onTouchLeave(const GuiEvent &event);
    bool onMouseWheelUp(const GuiEvent &event);
    bool onMouseWheelDown(const GuiEvent &event);
 

+ 281 - 203
engine/source/gui/containers/guiWindowCtrl.cc

@@ -37,12 +37,14 @@ GuiWindowCtrl::GuiWindowCtrl(void)
    mCanClose = true;
    mCanMinimize = true;
    mCanMaximize = true;
+
    mTitleHeight = 20;
    mResizeRightWidth = 10;
    mResizeBottomHeight = 10;
    mIsContainer = true;
-
-   mCloseCommand = StringTable->EmptyString;
+   mDepressed = false;
+   curHitRegion = None;
+   mActive = true;
 
    mMinimized = false;
    mMaximized = false;
@@ -50,23 +52,25 @@ GuiWindowCtrl::GuiWindowCtrl(void)
    mMouseResizeWidth = false;
    mMouseResizeHeight = false;
    mBounds.extent.set(100, 200);
-   mMinSize.set(50, 50);
    mMinimizeIndex = -1;
    mTabIndex = -1;
 
-   RectI closeRect(80, 2, 16, 16);
-   mCloseButton = closeRect;
-   closeRect.point.x -= 18;
-   mMaximizeButton = closeRect;
-   closeRect.point.x -= 18;
-   mMinimizeButton = closeRect;
-
    //other defaults
    mActive = true;
    mPressClose = false;
    mPressMaximize = false;
    mPressMinimize = false;
 
+   mContentProfile = NULL;
+   mCloseButtonProfile = NULL;
+   mMinButtonProfile = NULL;
+   mMaxButtonProfile = NULL;
+
+   setField("contentProfile", "GuiWindowContentProfile");
+   setField("closeButtonProfile", "GuiWindowCloseButtonProfile");
+   setField("minButtonProfile", "GuiWindowMinButtonProfile");
+   setField("maxButtonProfile", "GuiWindowMaxButtonProfile");
+   setField("profile", "GuiWindowProfile");
 }
 
 void GuiWindowCtrl::initPersistFields()
@@ -79,8 +83,11 @@ void GuiWindowCtrl::initPersistFields()
    addField("canClose",          TypeBool,         Offset(mCanClose, GuiWindowCtrl));
    addField("canMinimize",       TypeBool,         Offset(mCanMinimize, GuiWindowCtrl));
    addField("canMaximize",       TypeBool,         Offset(mCanMaximize, GuiWindowCtrl));
-   addField("minSize",           TypePoint2I,      Offset(mMinSize, GuiWindowCtrl));
-   addField("closeCommand",      TypeString,       Offset(mCloseCommand, GuiWindowCtrl));
+   addField("titleHeight",		TypeS32,           Offset(mTitleHeight, GuiWindowCtrl));
+   addField("contentProfile", TypeGuiProfile, Offset(mContentProfile, GuiWindowCtrl));
+   addField("closeButtonProfile", TypeGuiProfile, Offset(mCloseButtonProfile, GuiWindowCtrl));
+   addField("minButtonProfile", TypeGuiProfile, Offset(mMinButtonProfile, GuiWindowCtrl));
+   addField("maxButtonProfile", TypeGuiProfile, Offset(mMaxButtonProfile, GuiWindowCtrl));
 }
 
 bool GuiWindowCtrl::isMinimized(S32 &index)
@@ -89,54 +96,22 @@ bool GuiWindowCtrl::isMinimized(S32 &index)
    return mMinimized && mVisible;
 }
 
-// helper fn so button positioning shares code...
-void GuiWindowCtrl::PositionButtons(void)
-{
-   if( !mBitmapBounds || !mAwake )
-      return;
-
-   S32 buttonWidth = mBitmapBounds[BmpStates * BmpClose].extent.x;
-   S32 buttonHeight = mBitmapBounds[BmpStates * BmpClose].extent.y;
-   Point2I mainOff = mProfile->mTextOffset;
-
-   int minLeft = mBounds.extent.x - buttonWidth * 3 - mainOff.x;
-   int minTop = mainOff.y;
-   int minOff = buttonWidth + 2;
-   
-   RectI minRect(minLeft, minTop, buttonHeight, buttonWidth);
-   mMinimizeButton = minRect;
-
-   mMaximizeButton = minRect;
-   minRect.point.x += minOff;
-   mMaximizeButton = minRect;
-
-   mCloseButton = minRect;
-   minRect.point.x += minOff;
-   mCloseButton = minRect;
-}
-
 bool GuiWindowCtrl::onWake()
 {
-   if (! Parent::onWake())
-      return false;
+	if (!Parent::onWake())
+		return false;
 
-   //get the texture for the close, minimize, and maximize buttons
-   
-   bool result = mProfile->constructBitmapArray() >= NumBitmaps;
-   mTextureHandle = mProfile->mTextureHandle;
-   AssertFatal(result, "Failed to create the bitmap array");
-   if(!result)
-      return false;
+	if (mContentProfile != NULL)
+		mContentProfile->incRefCount();
 
-   mBitmapBounds = mProfile->mBitmapArrayRects.address();
-   S32 buttonHeight = mBitmapBounds[BmpStates * BmpClose].extent.y;
+	if (mCloseButtonProfile != NULL)
+		mCloseButtonProfile->incRefCount();
 
-   mTitleHeight = buttonHeight + 4;
-   mResizeRightWidth = mTitleHeight / 2;
-   mResizeBottomHeight = mTitleHeight / 2;
+	if (mMinButtonProfile != NULL)
+		mMinButtonProfile->incRefCount();
 
-   //set the button coords
-   PositionButtons();
+	if (mMaxButtonProfile != NULL)
+		mMaxButtonProfile->incRefCount();
 
    //set the tab index
    mTabIndex = -1;
@@ -163,8 +138,19 @@ bool GuiWindowCtrl::onWake()
 
 void GuiWindowCtrl::onSleep()
 {
-   mTextureHandle = NULL;
    Parent::onSleep();
+
+   if (mContentProfile != NULL)
+	   mContentProfile->decRefCount();
+
+   if (mCloseButtonProfile != NULL)
+	   mCloseButtonProfile->decRefCount();
+
+   if (mMinButtonProfile != NULL)
+	   mMinButtonProfile->decRefCount();
+
+   if (mMaxButtonProfile != NULL)
+	   mMaxButtonProfile->decRefCount();
 }
 
 GuiControl* GuiWindowCtrl::findHitControl(const Point2I &pt, S32 initialLayer)
@@ -178,9 +164,16 @@ GuiControl* GuiWindowCtrl::findHitControl(const Point2I &pt, S32 initialLayer)
 void GuiWindowCtrl::resize(const Point2I &newPosition, const Point2I &newExtent)
 {
    Parent::resize(newPosition, newExtent);
+}
+
+void GuiWindowCtrl::onTouchMove(const GuiEvent &event)
+{
+	curHitRegion = findHitRegion(globalToLocalCoord(event.mousePoint));
+}
 
-   //set the button coords
-   PositionButtons();
+void GuiWindowCtrl::onTouchLeave(const GuiEvent &event)
+{
+	curHitRegion = None;
 }
 
 void GuiWindowCtrl::onTouchDown(const GuiEvent &event)
@@ -191,6 +184,8 @@ void GuiWindowCtrl::onTouchDown(const GuiEvent &event)
 
    mMouseDownPosition = event.mousePoint;
    Point2I localPoint = globalToLocalCoord(event.mousePoint);
+   curHitRegion = findHitRegion(localPoint);
+   mDepressed = true;
 
    //select this window - move it to the front, and set the first responder
    selectWindow();
@@ -199,21 +194,19 @@ void GuiWindowCtrl::onTouchDown(const GuiEvent &event)
    if (localPoint.y < mTitleHeight)
    {
       //if we clicked on the close button
-      if (mCanClose && mCloseButton.pointInRect(localPoint))
+      if (curHitRegion == CloseButton)
       {
-         mPressClose = mCanClose;
+         mPressClose = true;
       }
-      else if (mCanMaximize && mMaximizeButton.pointInRect(localPoint))
+      else if (curHitRegion == MaxButton)
       {
-         mPressMaximize = mCanMaximize;
+         mPressMaximize = true;
       }
-      else if (mCanMinimize && mMinimizeButton.pointInRect(localPoint))
+      else if (curHitRegion == MinButton)
       {
-         mPressMinimize = mCanMinimize;
+         mPressMinimize = true;
       }
-
-      //else we clicked within the title
-      else
+      else if (curHitRegion == TitleBar)
       {
          mMouseMovingWin = mCanMove;
          mMouseResizeWidth = false;
@@ -259,6 +252,8 @@ void GuiWindowCtrl::onTouchDragged(const GuiEvent &event)
    GuiCanvas *root = getRoot();
    if (! root) return;
 
+   curHitRegion = findHitRegion(globalToLocalCoord(event.mousePoint));
+
    Point2I deltaMousePosition = event.mousePoint - mMouseDownPosition;
 
    Point2I newPosition = mBounds.point;
@@ -306,8 +301,10 @@ void GuiWindowCtrl::onTouchUp(const GuiEvent &event)
    mPressClose = false;
    mPressMaximize = false;
    mPressMinimize = false;
+   mDepressed = false;
 
    mouseUnlock();
+   setUpdate();
 
    mMouseMovingWin = false;
    mMouseResizeWidth = false;
@@ -321,7 +318,7 @@ void GuiWindowCtrl::onTouchUp(const GuiEvent &event)
    Point2I localPoint = globalToLocalCoord(event.mousePoint);
    if (closing && mCloseButton.pointInRect(localPoint))
    {
-      Con::evaluate(mCloseCommand);
+      //Con::evaluate(mCloseCommand);
    }
    else if (maximizing && mMaximizeButton.pointInRect(localPoint))
    {
@@ -403,8 +400,8 @@ void GuiWindowCtrl::onTouchUp(const GuiEvent &event)
          //if we have more than 32 minimized windows, use the first position
          count = getMax(0, count);
 
-         //this algorithm assumes all window have the same title height, and will minimize to 98 pix
-         Point2I newExtent(98, mTitleHeight);
+         //this algorithm assumes all window have the same title height, and will minimize to 148 pix
+         Point2I newExtent(148, mTitleHeight);
 
          //first, how many can fit across
          S32 numAcross = getMax(1, (parent->mBounds.extent.x / newExtent.x + 2));
@@ -496,6 +493,27 @@ GuiControl *GuiWindowCtrl::findPrevTabable(GuiControl *curResponder, bool firstC
    return tabCtrl;
 }
 
+GuiWindowCtrl::Region GuiWindowCtrl::findHitRegion(const Point2I& pt)
+{
+	if (mCanClose && mCloseButton.pointInRect(pt)) 
+	{
+		return CloseButton;
+	}
+	else if (mCanMaximize && mMaximizeButton.pointInRect(pt))
+	{
+		return MaxButton;
+	}
+	else if (mCanMinimize && mMinimizeButton.pointInRect(pt))
+	{
+		return MinButton;
+	}
+	else if (mTitleBar.pointInRect(pt))
+	{
+		return TitleBar;
+	}
+	return None;
+}
+
 bool GuiWindowCtrl::onKeyDown(const GuiEvent &event)
 {
    //if this control is a dead end, kill the event
@@ -549,144 +567,204 @@ void GuiWindowCtrl::selectWindow(void)
 
 void GuiWindowCtrl::onRender(Point2I offset, const RectI &updateRect)
 {
-   if( !mProfile || mProfile->mFont.isNull() || mProfile->mBitmapArrayRects.size() < NumBitmaps )
-      return Parent::onRender( offset, updateRect );
-
-   //draw the outline
-   RectI winRect;
-   winRect.point = offset;
-   winRect.extent = mBounds.extent;
-   GuiCanvas *root = getRoot();
-   GuiControl *firstResponder = root ? root->getFirstResponder() : NULL;
-
-   bool isKey = (!firstResponder || ControlIsChild(firstResponder));
-
-   U32 topBase = isKey ? BorderTopLeftKey : BorderTopLeftNoKey;
-   winRect.point.x += mBitmapBounds[BorderLeft].extent.x;
-   winRect.point.y += mBitmapBounds[topBase + 2].extent.y;
-
-   winRect.extent.x -= mBitmapBounds[BorderLeft].extent.x + mBitmapBounds[BorderRight].extent.x;
-   winRect.extent.y -= mBitmapBounds[topBase + 2].extent.y + mBitmapBounds[BorderBottom].extent.y;
-
-   dglDrawRectFill(winRect, mProfile->mFillColor);
-
-   dglClearBitmapModulation();
-   dglDrawBitmapSR(mTextureHandle, offset, mBitmapBounds[topBase]);
-   dglDrawBitmapSR(mTextureHandle, Point2I(offset.x + mBounds.extent.x - mBitmapBounds[topBase+1].extent.x, offset.y),
-                   mBitmapBounds[topBase + 1]);
-
-   RectI destRect;
-   destRect.point.x = offset.x + mBitmapBounds[topBase].extent.x;
-   destRect.point.y = offset.y;
-   destRect.extent.x = mBounds.extent.x - mBitmapBounds[topBase].extent.x - mBitmapBounds[topBase + 1].extent.x;
-   destRect.extent.y = mBitmapBounds[topBase + 2].extent.y;
-   RectI stretchRect = mBitmapBounds[topBase + 2];
-   stretchRect.inset(1,0);
-   dglDrawBitmapStretchSR(mTextureHandle, destRect, stretchRect);
-
-   destRect.point.x = offset.x;
-   destRect.point.y = offset.y + mBitmapBounds[topBase].extent.y;
-   destRect.extent.x = mBitmapBounds[BorderLeft].extent.x;
-   destRect.extent.y = mBounds.extent.y - mBitmapBounds[topBase].extent.y - mBitmapBounds[BorderBottomLeft].extent.y;
-   stretchRect = mBitmapBounds[BorderLeft];
-   stretchRect.inset(0,1);
-   dglDrawBitmapStretchSR(mTextureHandle, destRect, stretchRect);
-
-   destRect.point.x = offset.x + mBounds.extent.x - mBitmapBounds[BorderRight].extent.x;
-   destRect.extent.x = mBitmapBounds[BorderRight].extent.x;
-   destRect.point.y = offset.y + mBitmapBounds[topBase + 1].extent.y;
-   destRect.extent.y = mBounds.extent.y - mBitmapBounds[topBase + 1].extent.y - mBitmapBounds[BorderBottomRight].extent.y;
-
-   stretchRect = mBitmapBounds[BorderRight];
-   stretchRect.inset(0,1);
-   dglDrawBitmapStretchSR(mTextureHandle, destRect, stretchRect);
-
-   dglDrawBitmapSR(mTextureHandle, offset + Point2I(0, mBounds.extent.y - mBitmapBounds[BorderBottomLeft].extent.y), mBitmapBounds[BorderBottomLeft]);
-   dglDrawBitmapSR(mTextureHandle, offset + mBounds.extent - mBitmapBounds[BorderBottomRight].extent, mBitmapBounds[BorderBottomRight]);
-
-   destRect.point.x = offset.x + mBitmapBounds[BorderBottomLeft].extent.x;
-   destRect.extent.x = mBounds.extent.x - mBitmapBounds[BorderBottomLeft].extent.x - mBitmapBounds[BorderBottomRight].extent.x;
-
-   destRect.point.y = offset.y + mBounds.extent.y - mBitmapBounds[BorderBottom].extent.y;
-   destRect.extent.y = mBitmapBounds[BorderBottom].extent.y;
-   stretchRect = mBitmapBounds[BorderBottom];
-   stretchRect.inset(1,0);
-
-   dglDrawBitmapStretchSR(mTextureHandle, destRect, stretchRect);
-
-   //draw the title
-   // dhc addition: copied/modded from renderJustifiedText, since we enforce a
-   // different color usage here. NOTE: it currently CAN overdraw the controls
-   // if mis-positioned or 'scrunched' in a small width.
-   dglSetBitmapModulation(mProfile->mFontColor);
-   S32 textWidth = mProfile->mFont->getStrWidth((const UTF8 *)mText);
-   Point2I start(0,0);
-   // align the horizontal
-   if ( mProfile->mAlignment == GuiControlProfile::RightAlign )
-      start.set( winRect.extent.x - textWidth, 0 );
-   else if ( mProfile->mAlignment == GuiControlProfile::CenterAlign )
-      start.set( ( winRect.extent.x - textWidth) / 2, 0 );
-   else // GuiControlProfile::LeftAlign or garbage... ;)
-      start.set( 0, 0 );
-   // If the text is longer then the box size, (it'll get clipped) so force Left Justify
-   if( textWidth > winRect.extent.x ) start.set( 0, 0 );
-   // center the vertical
-//   start.y = ( winRect.extent.y - ( font->getHeight() - 2 ) ) / 2;
-   dglDrawText(mProfile->mFont, start + offset + mProfile->mTextOffset, mText);
-
-   // deal with rendering the titlebar controls
-   AssertFatal(root, "Unable to get the root Canvas.");
-   Point2I localPoint = globalToLocalCoord(root->getCursorPos());
-
-   //draw the close button
-   Point2I tempUL;
-   Point2I tempLR;
-   S32 bmp = BmpStates * BmpClose;
-
-   if( mCanClose ) {
-      if( mCloseButton.pointInRect( localPoint ) && mPressClose )
-         bmp += BmpHilite;
-
-      dglClearBitmapModulation();
-      dglDrawBitmapSR(mTextureHandle, offset + mCloseButton.point, mBitmapBounds[bmp]);
-   }
-
-   //draw the maximize button
-   if( mMaximized )
-      bmp = BmpStates * BmpNormal;
-   else
-      bmp = BmpStates * BmpMaximize;
-
-   if( mCanMaximize ) {
-      if( mMaximizeButton.pointInRect( localPoint ) && mPressMaximize )
-         bmp += BmpHilite;
-
-      dglClearBitmapModulation();
-      dglDrawBitmapSR( mTextureHandle, offset + mMaximizeButton.point, mBitmapBounds[bmp] );
-   }
-
-   //draw the minimize button
-   if( mMinimized )
-      bmp = BmpStates * BmpNormal;
-   else
-      bmp = BmpStates * BmpMinimize;
-
-   if( mCanMinimize ) {
-      if( mMinimizeButton.pointInRect( localPoint ) && mPressMinimize )
-         bmp += BmpHilite;
-
-      dglClearBitmapModulation();
-      dglDrawBitmapSR( mTextureHandle, offset + mMinimizeButton.point, mBitmapBounds[bmp] );
-   }
+	//Does this window have focus (does it or a child receive key events)?
+	GuiCanvas *root = getRoot();
+	GuiControl *firstResponder = root ? root->getFirstResponder() : NULL;
+	bool hasFocus = (!firstResponder || ControlIsChild(firstResponder));
+
+	GuiControlState currentState = NormalState;
+	if (mMinimized)
+	{
+		currentState = DisabledState;
+	}
+	else if (hasFocus)
+	{
+		currentState = SelectedState;
+
+		GuiControl *parent = getParent();
+		if (parent)
+		{
+			parent->pushObjectToBack(this);
+		}
+	}
+	else if (curHitRegion == TitleBar)
+	{
+		currentState = HighlightState;
+	}
+
+	//Render the title bar
+	RectI ctrlRectTitle = applyMargins(offset, Point2I(mBounds.extent.x, mTitleHeight), 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(mProfile->mFontColor);
+	RectI fillRectTitle = applyBorders(ctrlRectTitle.point, ctrlRectTitle.extent, currentState, mProfile);
+	RectI contentRectTitle = applyPadding(fillRectTitle.point, fillRectTitle.extent, currentState, mProfile);
+
+	if (contentRectTitle.isValidRect())
+	{
+		RectI textRect = renderButtons(contentRectTitle);
+		renderText(textRect.point, textRect.extent, mText, mProfile);
+	}
+
+	//Render window contents
+	if (!mMinimized)
+	{
+		currentState = currentState != SelectedState ? NormalState : SelectedState;
+		RectI ctrlRectWindow = applyMargins(Point2I(offset.x, offset.y + mTitleHeight), Point2I(mBounds.extent.x, mBounds.extent.y - mTitleHeight), currentState, mContentProfile);
+		if (!ctrlRectWindow.isValidRect())
+		{
+			return;
+		}
+		renderUniversalRect(ctrlRectWindow, mContentProfile, currentState);
+
+		RectI fillRectWindow = applyBorders(ctrlRectWindow.point, ctrlRectWindow.extent, currentState, mContentProfile);
+		RectI contentRectWindow = applyPadding(fillRectWindow.point, fillRectWindow.extent, currentState, mContentProfile);
+
+		if (contentRectWindow.isValidRect())
+		{
+			//render the children
+			renderChildControls(offset, contentRectWindow, updateRect);
+		}
+	}
+}
 
-   if( !mMinimized )
-   {
-      //render the children
-      renderChildControls( offset, mBounds, updateRect );
-   }
+RectI GuiWindowCtrl::renderButtons(const RectI &contentRect)
+{
+	S32 distanceFromEdge = 0;
+
+	if (mCanClose)
+	{
+		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);
+		distanceFromEdge += content.extent.x;
+
+		GuiBorderProfile *leftProfile = mCloseButtonProfile->getLeftBorder();
+		S32 leftSize = (leftProfile) ? leftProfile->getMargin(state) : 0;
+		distanceFromEdge += leftSize;
+
+		GuiBorderProfile *rightProfile = mCloseButtonProfile->getRightBorder();
+		S32 rightSize = (rightProfile) ? rightProfile->getMargin(state) : 0;
+		distanceFromEdge += rightSize;
+	}
+	if (mCanMaximize)
+	{
+		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);
+		distanceFromEdge += content.extent.x;
+
+		GuiBorderProfile *leftProfile = mMaxButtonProfile->getLeftBorder();
+		S32 leftSize = (leftProfile) ? leftProfile->getMargin(state) : 0;
+		distanceFromEdge += leftSize;
+
+		GuiBorderProfile *rightProfile = mMaxButtonProfile->getRightBorder();
+		S32 rightSize = (rightProfile) ? rightProfile->getMargin(state) : 0;
+		distanceFromEdge += rightSize;
+	}
+	if (mCanMinimize)
+	{
+		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);
+		distanceFromEdge += content.extent.x;
+
+		GuiBorderProfile *leftProfile = mMinButtonProfile->getLeftBorder();
+		S32 leftSize = (leftProfile) ? leftProfile->getMargin(state) : 0;
+		distanceFromEdge += leftSize;
+
+		GuiBorderProfile *rightProfile = mMinButtonProfile->getRightBorder();
+		S32 rightSize = (rightProfile) ? rightProfile->getMargin(state) : 0;
+		distanceFromEdge += rightSize;
+	}
+
+	if (mProfile->mAlignment != GuiControlProfile::AlignmentType::RightAlign)
+	{
+		return RectI(contentRect.point.x, contentRect.point.y, contentRect.extent.x - distanceFromEdge, contentRect.extent.y);
+	}
+	else
+	{
+		return RectI(contentRect.point.x + distanceFromEdge, contentRect.point.y, contentRect.extent.x - distanceFromEdge, contentRect.extent.y);
+	}
 }
 
+RectI GuiWindowCtrl::renderButton(const RectI &contentRect, S32 distanceFromEdge, GuiControlState buttonState, GuiControlProfile *profile, Icon defaultIcon)
+{
+	RectI buttonContent = applyMargins(contentRect.point, contentRect.extent, buttonState, profile);
+	S32 horizMarginSize = contentRect.extent.x - buttonContent.extent.x;
+	RectI finalButtonRect = RectI(contentRect.point, Point2I(buttonContent.extent.y + horizMarginSize, contentRect.extent.y));
+	if (mProfile->mAlignment != GuiControlProfile::AlignmentType::RightAlign)
+	{
+		//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;
+	}
+	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;
+		distanceFromEdge += leftSize;
+		finalButtonRect.point.x = distanceFromEdge;
+	}
+	RectI finalButtonContent = applyMargins(finalButtonRect.point, finalButtonRect.extent, buttonState, profile);
+	renderUniversalRect(finalButtonContent, profile, buttonState);
+
+	//now draw an icon if default rendering was used.
+	if ((profile->mImageAsset == NULL || !mCloseButtonProfile->mImageAsset->isAssetValid()) &&
+		profile->mBitmapName == NULL)
+	{
+		RectI fillRect = applyBorders(finalButtonContent.point, finalButtonContent.extent, buttonState, profile);
+		RectI contentRect = applyPadding(fillRect.point, fillRect.extent, buttonState, profile);
+
+		//draw the icon
+		if (defaultIcon == Icon::Close)
+		{
+
+		}
+		else if (defaultIcon == Icon::Min)
+		{
+			S32 h = (contentRect.len_y() / 2) - 1;
+			Point2I p1 = Point2I(contentRect.point.x, contentRect.point.y + h);
+			Point2I p2 = Point2I(contentRect.point.x, contentRect.point.y + h + 2);
+			Point2I p3 = Point2I(contentRect.point.x + contentRect.extent.x, contentRect.point.y + h + 2);
+			Point2I p4 = Point2I(contentRect.point.x + contentRect.extent.x, contentRect.point.y + h);
+			dglDrawQuadFill(p1, p2, p3, p4, profile->getFontColor(buttonState));
+		}
+		else if (defaultIcon == Icon::Max)
+		{
+
+		}
+	}
+
+	return finalButtonContent;
+}
 
+GuiControlState GuiWindowCtrl::getRegionCurrentState(GuiWindowCtrl::Region region)
+{
+	GuiControlState currentState = GuiControlState::NormalState;
+	if (!mActive)
+	{
+		currentState = GuiControlState::DisabledState;
+	}
+	else if (curHitRegion == region && mDepressed)
+	{
+		currentState = GuiControlState::SelectedState;
+	}
+	else if (curHitRegion == region)
+	{
+		currentState = GuiControlState::HighlightState;
+	}
+	return currentState;
+}
 
 void GuiWindowCtrl::getCursor(GuiCursor *&cursor, bool &showCursor, const GuiEvent &lastGuiEvent)
 {

+ 42 - 45
engine/source/gui/containers/guiWindowCtrl.h

@@ -36,23 +36,25 @@ class GuiWindowCtrl : public GuiControl
    private:
       typedef GuiControl Parent;
 
+	  //Allow these behaviors.
       bool mResizeWidth;
       bool mResizeHeight;
       bool mCanMove;
       bool mCanClose;
       bool mCanMinimize;
       bool mCanMaximize;
+
+	  //Did the touch down happen inside these buttons?
       bool mPressClose;
       bool mPressMinimize;
       bool mPressMaximize;
-      Point2I mMinSize;
-
-      StringTableEntry mCloseCommand;
 
-      S32 mTitleHeight;
-      S32 mResizeRightWidth;
-      S32 mResizeBottomHeight;
+	  //Window settings.
+      S32 mTitleHeight;					//The height of the title bar before appling margin/border/padding.
+      S32 mResizeRightWidth;			//The size of the area inset from the right edge that can be clicked to resize horizontally.
+      S32 mResizeBottomHeight;			//The size of the area inset from the bottom edge that can be clicked to resize vertically.
 
+	  //Current State
       bool mMouseMovingWin;
       bool mMouseResizeWidth;
       bool mMouseResizeHeight;
@@ -63,51 +65,44 @@ class GuiWindowCtrl : public GuiControl
       RectI mOrigBounds;
       RectI mStandardBounds;
 
+	  //The location of the window parts.
       RectI mCloseButton;
       RectI mMinimizeButton;
       RectI mMaximizeButton;
+	  RectI mTitleBar;
+
       S32 mMinimizeIndex;
       S32 mTabIndex;
 
-      void PositionButtons(void);
-
-   protected:
-      enum BitmapIndices
-      {
-         BmpClose,
-         BmpMaximize,
-         BmpNormal,
-         BmpMinimize,
-
-         BmpCount
-      };
-      enum {
-         BorderTopLeftKey = 12,
-         BorderTopRightKey,
-         BorderTopKey,
-         BorderTopLeftNoKey,
-         BorderTopRightNoKey,
-         BorderTopNoKey,
-         BorderLeft,
-         BorderRight,
-         BorderBottomLeft,
-         BorderBottom,
-         BorderBottomRight,
-         NumBitmaps
-      };
-
-      enum BitmapStates
-      {
-         BmpDefault = 0,
-         BmpHilite,
-         BmpDisabled,
-
-         BmpStates
-      };
-      RectI *mBitmapBounds;  //bmp is [3*n], bmpHL is [3*n + 1], bmpNA is [3*n + 2]
-      TextureHandle mTextureHandle;
+	  //Additional profiles used by the window.
+	  GuiControlProfile *mContentProfile; //Used to render the content section of the window.
+	  GuiControlProfile *mCloseButtonProfile; //Used to render the close button.
+	  GuiControlProfile *mMinButtonProfile; //Used to render the close button.
+	  GuiControlProfile *mMaxButtonProfile; //Used to render the close button.
 
    public:
+	   enum Region
+	   {
+		   TitleBar,
+		   CloseButton,
+		   MinButton,
+		   MaxButton,
+		   None
+	   };
+
+	   enum Icon
+	   {
+		   Close,
+		   Min,
+		   Max
+	   };
+
+	   bool mDepressed;
+	   Region curHitRegion;
+
+	   Region findHitRegion(const Point2I &);
+	   GuiControlState getRegionCurrentState(GuiWindowCtrl::Region region);
+
       GuiWindowCtrl();
       DECLARE_CONOBJECT(GuiWindowCtrl);
       static void initPersistFields();
@@ -119,14 +114,14 @@ class GuiWindowCtrl : public GuiControl
 
       virtual void getCursor(GuiCursor *&cursor, bool &showCursor, const GuiEvent &lastGuiEvent);
 
-      void setFont(S32 fntTag);
-
       GuiControl* findHitControl(const Point2I &pt, S32 initialLayer = -1);
       void resize(const Point2I &newPosition, const Point2I &newExtent);
 
+	  void onTouchMove(const GuiEvent &event);
       void onTouchDown(const GuiEvent &event);
       void onTouchDragged(const GuiEvent &event);
       void onTouchUp(const GuiEvent &event);
+	  void onTouchLeave(const GuiEvent &event);
 
       //only cycle tabs through the current window, so overwrite the method
       GuiControl* findNextTabable(GuiControl *curResponder, bool firstCall = true);
@@ -138,6 +133,8 @@ class GuiWindowCtrl : public GuiControl
       void selectWindow(void);
 
       void onRender(Point2I offset, const RectI &updateRect);
+	  RectI renderButtons(const RectI &contentRect);
+	  RectI renderButton(const RectI &contentRect, S32 distanceFromEdge, GuiControlState buttonState, GuiControlProfile *profile, Icon defaultIcon);
 };
 /// @}
 

+ 9 - 6
engine/source/gui/guiTypes.cc

@@ -563,12 +563,15 @@ void GuiControlProfile::decRefCount()
 
    --mRefCount;
 
-   if(!mRefCount)
-   {
-	  mFont = NULL;
-	  mTextureHandle = NULL;
-	  mImageAsset.clear();
-   }
+	if(!mRefCount)
+	{
+		mFont = NULL;
+		mTextureHandle = NULL;
+		if(mImageAsset != NULL)
+		{
+			mImageAsset.clear();
+		}
+	}
 }
 
 void GuiControlProfile::setImageAsset(const char* pImageAssetID)

+ 34 - 19
toybox/GuiEditorToy/1/assets/gui/guiToolbox.gui

@@ -12,12 +12,17 @@
     isContainer = "1";
     canSave = "1";
     canSaveDynamicFields = "1";
-   
+
 	new GuiWindowCtrl(GuiToolbox) {
 		canSaveDynamicFields = "0";
 		internalName = "toolbox";
 		isContainer = "1";
 		Profile = "GuiWindowProfile";
+		ContentProfile = "GuiWindowContentProfile";
+		CloseButtonProfile = "GuiWindowCloseButtonProfile";
+		MinButtonProfile = "GuiWindowMinButtonProfile";
+		MaxButtonProfile = "GuiWindowMaxButtonProfile";
+		titleHeight = "20";
 		HorizSizing = "left";
 		VertSizing = "bottom";
 		position = "640 40";
@@ -35,7 +40,7 @@
 		canMinimize = "1";
 		canMaximize = "0";
 		minSize = "50 50";
-		
+
 		new GuiScrollCtrl() {
             canSaveDynamicFields = "0";
             isContainer = "1";
@@ -45,8 +50,8 @@
 			ArrowProfile = "GuiScrollArrowProfile";
             HorizSizing = "width";
             VertSizing = "height";
-            position = "0 20";
-            Extent = "220 340";
+            position = "0 0";
+            Extent = "220 360";
             MinExtent = "8 2";
             canSave = "1";
             Visible = "1";
@@ -57,7 +62,7 @@
 			constantThumbHeight="0";
 			showArrowButtons="0";
 			scrollBarThickness="14";
-		
+
 			new GuiListBoxCtrl() {
 				canSaveDynamicFields = "0";
 				internalName = "toolboxList";
@@ -66,7 +71,7 @@
 				Profile = "GuiListBoxProfile";
 				HorizSizing = "width";
 				VertSizing = "height";
-				position = "2 20";
+				position = "2 2";
 				Extent = "218 1260";
 				MinExtent = "8 2";
 				canSave = "1";
@@ -77,11 +82,16 @@
 			};
 		};
 	};
-	
+
 	new GuiWindowCtrl(GuiInspectorWindow) {
 		canSaveDynamicFields = "0";
 		isContainer = "1";
 		Profile = "GuiWindowProfile";
+		ContentProfile = "GuiWindowContentProfile";
+		CloseButtonProfile = "GuiWindowCloseButtonProfile";
+		MinButtonProfile = "GuiWindowMinButtonProfile";
+		MaxButtonProfile = "GuiWindowMaxButtonProfile";
+		titleHeight = "20";
 		HorizSizing = "left";
 		VertSizing = "bottom";
 		position = "60 40";
@@ -99,7 +109,7 @@
 		canMinimize = "1";
 		canMaximize = "0";
 		minSize = "50 50";
-		
+
 		new GuiScrollCtrl() {
             canSaveDynamicFields = "0";
             isContainer = "1";
@@ -109,8 +119,8 @@
 			ArrowProfile = "GuiScrollArrowProfile";
             HorizSizing = "width";
             VertSizing = "height";
-            position = "0 20";
-            Extent = "360 340";
+            position = "0 0";
+            Extent = "360 360";
             MinExtent = "8 2";
             canSave = "1";
             Visible = "1";
@@ -121,21 +131,26 @@
 			constantThumbHeight="0";
 			showArrowButtons="0";
 			scrollBarThickness="14";
-		
+
 			new GuiChainCtrl(GuiEditorCtrlProperties) {
                 isContainer = "1";
-                Position = "0 20";
+                Position = "0 0";
                 Extent = "340 40";
 				HorizSizing = "width";
 				VertSizing = "height";
             };
 		};
 	};
-	
+
 	new GuiWindowCtrl(GuiTreeViewWindow) {
 		canSaveDynamicFields = "0";
 		isContainer = "1";
 		Profile = "GuiWindowProfile";
+		ContentProfile = "GuiWindowContentProfile";
+		CloseButtonProfile = "GuiWindowCloseButtonProfile";
+		MinButtonProfile = "GuiWindowMinButtonProfile";
+		MaxButtonProfile = "GuiWindowMaxButtonProfile";
+		titleHeight = "20";
 		HorizSizing = "left";
 		VertSizing = "bottom";
 		position = "360 40";
@@ -153,7 +168,7 @@
 		canMinimize = "1";
 		canMaximize = "0";
 		minSize = "50 50";
-		
+
 		new GuiScrollCtrl() {
             canSaveDynamicFields = "0";
             isContainer = "1";
@@ -163,8 +178,8 @@
 			ArrowProfile = "GuiScrollArrowProfile";
             HorizSizing = "width";
             VertSizing = "height";
-            position = "0 20";
-            Extent = "220 340";
+            position = "0 0";
+            Extent = "220 360";
             MinExtent = "8 2";
             canSave = "1";
             Visible = "1";
@@ -175,7 +190,7 @@
 			constantThumbHeight="0";
 			showArrowButtons="0";
 			scrollBarThickness="14";
-		
+
 			new GuiTreeViewCtrl(GuiEditorTreeView) {
                canSaveDynamicFields = "0";
                isContainer = "1";
@@ -200,5 +215,5 @@
             };
 		};
 	};
-	
-};
+
+};

+ 33 - 22
toybox/Sandbox/1/gui/guiProfiles.cs

@@ -187,9 +187,7 @@ if(!isObject(GuiPanelProfile)) new GuiControlProfile (GuiPanelProfile : GuiDefau
     fillColorHL = AdjustColorValue($color1, 10);
     fillColorSL = AdjustColorValue($color1, 15);
     fillColorNA = SetColorAlpha($color1, 100);
-	borderDefault = GuiDarkBorderProfile;
-	borderTop = GuiBrightBorderProfile;
-	borderLeft = GuiBrightBorderProfile;
+	borderDefault = GuiBrightBorderProfile;
 	category = "defaultPanel";
 };
 
@@ -208,8 +206,8 @@ if(!isObject(GuiListBoxProfile)) new GuiControlProfile (GuiListBoxProfile : GuiD
 
 if(!isObject(GuiWindowProfile)) new GuiControlProfile (GuiWindowProfile : GuiDefaultProfile)
 {
-   fillColor = $color1;
-   fillColorHL = AdjustColorValue($color1, 10);
+   fillColor = AdjustColorValue($color1, 10);
+   fillColorHL = AdjustColorValue($color1, 12);
    fillColorSL = $color4;
    fillColorNA = $color1;
    category = "defaultWindow";
@@ -219,39 +217,54 @@ if(!isObject(GuiWindowProfile)) new GuiControlProfile (GuiWindowProfile : GuiDef
 
 if(!isObject(GuiWindowContentBorderProfile)) new GuiBorderProfile (GuiWindowContentBorderProfile : GuiDefaultBorderProfile)
 {
-	borderColor = AdjustColorValue($color1, -10);
-	borderColorHL = AdjustColorValue($color1, -10);
+	borderColor = AdjustColorValue($color1, 10);
 	borderColorSL = AdjustColorValue($color4, -10);
-	borderColorNA = $color5;
 
 	border = 1;
-	borderHL = 1;
 	borderSL = 1;
-	borderNA = 1;
 };
 
 if(!isObject(GuiWindowContentProfile)) new GuiControlProfile (GuiWindowContentProfile : GuiDefaultProfile)
 {
-	fillColor = $color2;
-	fillColorHL = $color2;
-	fillColorSL = $color2;
-	fillColorNA = $color2;
+	fillColor = AdjustColorValue($color1, -10);
+	fillColorSL = AdjustColorValue($color1, -10);
 
 	borderDefault = GuiWindowContentBorderProfile;
+	borderTop = GuiDefaultBorderProfile;
+};
+
+if(!isObject(GuiWindowButtonBorderProfile)) new GuiBorderProfile (GuiWindowButtonBorderProfile : GuiDefaultBorderProfile)
+{
+	margin = 1;
+	marginHL = 1;
+	marginSL = 1;
+	marginNA = 1;
+
+	padding = 2;
+	paddingHL = 2;
+	paddingSL = 2;
+	paddingNA = 2;
 };
 
 if(!isObject(GuiWindowCloseButtonProfile)) new GuiControlProfile (GuiWindowCloseButtonProfile : GuiDefaultProfile)
 {
-   fillColor = $color1;
-   fillColorHL = $color6;
-   fillColorHL = AdjustColorValue($color6, 10);
+   fillColor = SetColorAlpha($color1, 150);
+   fillColorHL = SetColorAlpha($color6, 150);
+   fillColorSL = AdjustColorValue($color6, 10);
    fillColorNA = $color1;
+
+   fontColor = SetColorAlpha($color3, 150);
+   fontColorHL = SetColorAlpha($color3, 170);
+   fontColorSL = $color5;
+   fontColorNA = SetColorAlpha($color3, 150);
+
+   borderDefault = GuiWindowButtonBorderProfile;
 };
 
 if(!isObject(GuiWindowMinButtonProfile)) new GuiControlProfile (GuiWindowMinButtonProfile : GuiWindowCloseButtonProfile)
 {
-   fillColorHL = $color4;
-   fillColorHL = AdjustColorValue($color4, 10);
+   fillColorHL = SetColorAlpha($color4, 150);
+   fillColorSL = AdjustColorValue($color4, 10);
 };
 
 if(!isObject(GuiWindowMaxButtonProfile)) new GuiControlProfile (GuiWindowMaxButtonProfile : GuiWindowMinButtonProfile);
@@ -273,9 +286,7 @@ if(!isObject(GuiTabProfile)) new GuiControlProfile (GuiTabProfile : GuiDefaultPr
 	fillColorHL = AdjustColorValue($color1, 10);
 	fillColorSL = AdjustColorValue($color1, 15);
 	fillColorNA = SetColorAlpha($color1, 100);
-	borderDefault = GuiDarkBorderProfile;
-	borderTop = GuiBrightBorderProfile;
-	borderLeft = GuiBrightBorderProfile;
+	borderDefault = GuiBrightBorderProfile;
 	align = Center;
 	//bitmap = "./images/tab";
 	category = "defaultTab";