Initial commit
This commit is contained in:
743
Torque/SDK/engine/gui/containers/guiWindowCtrl.cc
Normal file
743
Torque/SDK/engine/gui/containers/guiWindowCtrl.cc
Normal file
@@ -0,0 +1,743 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// Torque Game Engine
|
||||
// Copyright (C) GarageGames.com, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "console/consoleTypes.h"
|
||||
#include "console/console.h"
|
||||
#include "dgl/dgl.h"
|
||||
#include "gui/core/guiCanvas.h"
|
||||
#include "gui/containers/guiWindowCtrl.h"
|
||||
#include "gui/core/guiDefaultControlRender.h"
|
||||
|
||||
IMPLEMENT_CONOBJECT(GuiWindowCtrl);
|
||||
|
||||
GuiWindowCtrl::GuiWindowCtrl(void)
|
||||
{
|
||||
mResizeWidth = true;
|
||||
mResizeHeight = true;
|
||||
mCanMove = true;
|
||||
mCanClose = true;
|
||||
mCanMinimize = true;
|
||||
mCanMaximize = true;
|
||||
mTitleHeight = 20;
|
||||
mResizeRightWidth = 10;
|
||||
mResizeBottomHeight = 10;
|
||||
|
||||
mCloseCommand = StringTable->insert("");
|
||||
|
||||
mMinimized = false;
|
||||
mMaximized = false;
|
||||
mMouseMovingWin = false;
|
||||
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;
|
||||
|
||||
mDefaultCursor = NULL;
|
||||
mNWSECursor = NULL;
|
||||
mNESWCursor = NULL;
|
||||
mUpDownCursor = NULL;
|
||||
mLeftRightCursor = NULL;
|
||||
|
||||
}
|
||||
|
||||
void GuiWindowCtrl::initPersistFields()
|
||||
{
|
||||
Parent::initPersistFields();
|
||||
|
||||
addField("resizeWidth", TypeBool, Offset(mResizeWidth, GuiWindowCtrl));
|
||||
addField("resizeHeight", TypeBool, Offset(mResizeHeight, GuiWindowCtrl));
|
||||
addField("canMove", TypeBool, Offset(mCanMove, GuiWindowCtrl));
|
||||
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));
|
||||
}
|
||||
|
||||
bool GuiWindowCtrl::isMinimized(S32 &index)
|
||||
{
|
||||
index = mMinimizeIndex;
|
||||
return mMinimized && mVisible;
|
||||
}
|
||||
|
||||
// helper fn so button positioning shares code...
|
||||
void GuiWindowCtrl::PositionButtons(void)
|
||||
{
|
||||
S32 buttonWidth = mBitmapBounds[BmpStates * BmpClose].extent.x;
|
||||
S32 buttonHeight = mBitmapBounds[BmpStates * BmpClose].extent.y;
|
||||
Point2I mainOff = mProfile->mTextOffset;
|
||||
|
||||
// until a pref, if alignment is LEFT, put buttons RIGHT justified.
|
||||
// ELSE, put buttons LEFT justified.
|
||||
int closeLeft = mainOff.x, closeTop = mainOff.y, closeOff = buttonWidth + 2;
|
||||
if ( mProfile->mAlignment == GuiControlProfile::LeftJustify )
|
||||
{
|
||||
closeOff = -closeOff;
|
||||
closeLeft = mBounds.extent.x - buttonWidth - mainOff.x;
|
||||
}
|
||||
RectI closeRect(closeLeft, closeTop, buttonHeight, buttonWidth);
|
||||
mCloseButton = closeRect;
|
||||
|
||||
// Always put Minimize on left side of Maximize.
|
||||
closeRect.point.x += closeOff;
|
||||
if (closeOff>0)
|
||||
{
|
||||
mMinimizeButton = closeRect;
|
||||
closeRect.point.x += closeOff;
|
||||
mMaximizeButton = closeRect;
|
||||
}
|
||||
else
|
||||
{
|
||||
mMaximizeButton = closeRect;
|
||||
closeRect.point.x += closeOff;
|
||||
mMinimizeButton = closeRect;
|
||||
}
|
||||
}
|
||||
|
||||
bool GuiWindowCtrl::onWake()
|
||||
{
|
||||
if (! Parent::onWake())
|
||||
return false;
|
||||
|
||||
//get the texture for the close, minimize, and maximize buttons
|
||||
mTextureHandle = mProfile->mTextureHandle;
|
||||
bool result = mProfile->constructBitmapArray() >= NumBitmaps;
|
||||
AssertFatal(result, "Failed to create the bitmap array");
|
||||
if(!result)
|
||||
return false;
|
||||
|
||||
mBitmapBounds = mProfile->mBitmapArrayRects.address();
|
||||
S32 buttonWidth = mBitmapBounds[BmpStates * BmpClose].extent.x;
|
||||
S32 buttonHeight = mBitmapBounds[BmpStates * BmpClose].extent.y;
|
||||
|
||||
mTitleHeight = buttonHeight + 4;
|
||||
mResizeRightWidth = mTitleHeight / 2;
|
||||
mResizeBottomHeight = mTitleHeight / 2;
|
||||
|
||||
//set the button coords
|
||||
PositionButtons();
|
||||
|
||||
//set the tab index
|
||||
mTabIndex = -1;
|
||||
GuiControl *parent = getParent();
|
||||
if (parent && mFirstResponder)
|
||||
{
|
||||
mTabIndex = 0;
|
||||
|
||||
//count the number of windows preceeding this one
|
||||
iterator i;
|
||||
for (i = parent->begin(); i != parent->end(); i++)
|
||||
{
|
||||
GuiWindowCtrl *ctrl = dynamic_cast<GuiWindowCtrl *>(*i);
|
||||
if (ctrl)
|
||||
{
|
||||
if (ctrl == this) break;
|
||||
else if (ctrl->mFirstResponder) mTabIndex++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void GuiWindowCtrl::onSleep()
|
||||
{
|
||||
mTextureHandle = NULL;
|
||||
Parent::onSleep();
|
||||
}
|
||||
|
||||
GuiControl* GuiWindowCtrl::findHitControl(const Point2I &pt, S32 initialLayer)
|
||||
{
|
||||
if (! mMinimized)
|
||||
return Parent::findHitControl(pt, initialLayer);
|
||||
else
|
||||
return this;
|
||||
}
|
||||
|
||||
void GuiWindowCtrl::resize(const Point2I &newPosition, const Point2I &newExtent)
|
||||
{
|
||||
Parent::resize(newPosition, newExtent);
|
||||
|
||||
//set the button coords
|
||||
PositionButtons();
|
||||
}
|
||||
|
||||
void GuiWindowCtrl::onMouseDown(const GuiEvent &event)
|
||||
{
|
||||
setUpdate();
|
||||
|
||||
mOrigBounds = mBounds;
|
||||
|
||||
mMouseDownPosition = event.mousePoint;
|
||||
Point2I localPoint = globalToLocalCoord(event.mousePoint);
|
||||
|
||||
//select this window - move it to the front, and set the first responder
|
||||
selectWindow();
|
||||
|
||||
//if we clicked within the title bar
|
||||
if (localPoint.y < mTitleHeight)
|
||||
{
|
||||
//if we clicked on the close button
|
||||
if (mCanClose && mCloseButton.pointInRect(localPoint))
|
||||
{
|
||||
mPressClose = mCanClose;
|
||||
}
|
||||
else if (mCanMaximize && mMaximizeButton.pointInRect(localPoint))
|
||||
{
|
||||
mPressMaximize = mCanMaximize;
|
||||
}
|
||||
else if (mCanMinimize && mMinimizeButton.pointInRect(localPoint))
|
||||
{
|
||||
mPressMinimize = mCanMinimize;
|
||||
}
|
||||
|
||||
//else we clicked within the title
|
||||
else
|
||||
{
|
||||
mMouseMovingWin = mCanMove;
|
||||
mMouseResizeWidth = false;
|
||||
mMouseResizeHeight = false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mMouseMovingWin = false;
|
||||
|
||||
//see if we clicked on the right edge
|
||||
if (mResizeWidth && (localPoint.x > mBounds.extent.x - mResizeRightWidth))
|
||||
{
|
||||
mMouseResizeWidth = true;
|
||||
}
|
||||
|
||||
//see if we clicked on the bottom edge (as well)
|
||||
if (mResizeHeight && (localPoint.y > mBounds.extent.y - mResizeBottomHeight))
|
||||
{
|
||||
mMouseResizeHeight = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (mMouseMovingWin || mMouseResizeWidth || mMouseResizeHeight ||
|
||||
mPressClose || mPressMaximize || mPressMinimize)
|
||||
{
|
||||
mouseLock();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
GuiControl *ctrl = findHitControl(localPoint);
|
||||
if (ctrl && ctrl != this)
|
||||
ctrl->onMouseDown(event);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void GuiWindowCtrl::onMouseDragged(const GuiEvent &event)
|
||||
{
|
||||
GuiControl *parent = getParent();
|
||||
GuiCanvas *root = getRoot();
|
||||
if (! root) return;
|
||||
|
||||
Point2I deltaMousePosition = event.mousePoint - mMouseDownPosition;
|
||||
|
||||
Point2I newPosition = mBounds.point;
|
||||
Point2I newExtent = mBounds.extent;
|
||||
bool update = false;
|
||||
if (mMouseMovingWin && parent)
|
||||
{
|
||||
newPosition.x = getMax(0, getMin(parent->mBounds.extent.x - mBounds.extent.x, mOrigBounds.point.x + deltaMousePosition.x));
|
||||
newPosition.y = getMax(0, getMin(parent->mBounds.extent.y - mBounds.extent.y, mOrigBounds.point.y + deltaMousePosition.y));
|
||||
update = true;
|
||||
}
|
||||
else if(mPressClose || mPressMaximize || mPressMinimize)
|
||||
{
|
||||
setUpdate();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (mMouseResizeWidth && parent)
|
||||
{
|
||||
newExtent.x = getMax(0, getMax(mMinSize.x, getMin(parent->mBounds.extent.x, mOrigBounds.extent.x + deltaMousePosition.x)));
|
||||
update = true;
|
||||
}
|
||||
|
||||
if (mMouseResizeHeight && parent)
|
||||
{
|
||||
newExtent.y = getMax(0, getMax(mMinSize.y, getMin(parent->mBounds.extent.y, mOrigBounds.extent.y + deltaMousePosition.y)));
|
||||
update = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (update)
|
||||
{
|
||||
Point2I pos = parent->localToGlobalCoord(mBounds.point);
|
||||
root->addUpdateRegion(pos, mBounds.extent);
|
||||
resize(newPosition, newExtent);
|
||||
}
|
||||
}
|
||||
|
||||
void GuiWindowCtrl::onMouseUp(const GuiEvent &event)
|
||||
{
|
||||
bool closing = mPressClose;
|
||||
bool maximizing = mPressMaximize;
|
||||
bool minimizing = mPressMinimize;
|
||||
mPressClose = false;
|
||||
mPressMaximize = false;
|
||||
mPressMinimize = false;
|
||||
|
||||
event;
|
||||
mouseUnlock();
|
||||
|
||||
mMouseMovingWin = false;
|
||||
mMouseResizeWidth = false;
|
||||
mMouseResizeHeight = false;
|
||||
|
||||
GuiControl *parent = getParent();
|
||||
if (! parent)
|
||||
return;
|
||||
|
||||
//see if we take an action
|
||||
Point2I localPoint = globalToLocalCoord(event.mousePoint);
|
||||
if (closing && mCloseButton.pointInRect(localPoint))
|
||||
{
|
||||
Con::evaluate(mCloseCommand);
|
||||
}
|
||||
else if (maximizing && mMaximizeButton.pointInRect(localPoint))
|
||||
{
|
||||
if (mMaximized)
|
||||
{
|
||||
//resize to the previous position and extent, bounded by the parent
|
||||
resize(Point2I(getMax(0, getMin(parent->mBounds.extent.x - mStandardBounds.extent.x, mStandardBounds.point.x)),
|
||||
getMax(0, getMin(parent->mBounds.extent.y - mStandardBounds.extent.y, mStandardBounds.point.y))),
|
||||
mStandardBounds.extent);
|
||||
//set the flag
|
||||
mMaximized = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
//only save the position if we're not minimized
|
||||
if (! mMinimized)
|
||||
{
|
||||
mStandardBounds = mBounds;
|
||||
}
|
||||
else
|
||||
{
|
||||
mMinimized = false;
|
||||
}
|
||||
|
||||
//resize to fit the parent
|
||||
resize(Point2I(0, 0), parent->mBounds.extent);
|
||||
|
||||
//set the flag
|
||||
mMaximized = true;
|
||||
}
|
||||
}
|
||||
else if (minimizing && mMinimizeButton.pointInRect(localPoint))
|
||||
{
|
||||
if (mMinimized)
|
||||
{
|
||||
//resize to the previous position and extent, bounded by the parent
|
||||
resize(Point2I(getMax(0, getMin(parent->mBounds.extent.x - mStandardBounds.extent.x, mStandardBounds.point.x)),
|
||||
getMax(0, getMin(parent->mBounds.extent.y - mStandardBounds.extent.y, mStandardBounds.point.y))),
|
||||
mStandardBounds.extent);
|
||||
//set the flag
|
||||
mMinimized = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (parent->mBounds.extent.x < 100 || parent->mBounds.extent.y < mTitleHeight + 3)
|
||||
return;
|
||||
|
||||
//only save the position if we're not maximized
|
||||
if (! mMaximized)
|
||||
{
|
||||
mStandardBounds = mBounds;
|
||||
}
|
||||
else
|
||||
{
|
||||
mMaximized = false;
|
||||
}
|
||||
|
||||
//first find the lowest unused minimized index up to 32 minimized windows
|
||||
U32 indexMask = 0;
|
||||
iterator i;
|
||||
S32 count = 0;
|
||||
for (i = parent->begin(); i != parent->end() && count < 32; i++)
|
||||
{
|
||||
count++;
|
||||
S32 index;
|
||||
GuiWindowCtrl *ctrl = dynamic_cast<GuiWindowCtrl *>(*i);
|
||||
if (ctrl && ctrl->isMinimized(index))
|
||||
{
|
||||
indexMask |= (1 << index);
|
||||
}
|
||||
}
|
||||
|
||||
//now find the first unused bit
|
||||
for (count = 0; count < 32; count++)
|
||||
{
|
||||
if (! (indexMask & (1 << count))) break;
|
||||
}
|
||||
|
||||
//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);
|
||||
|
||||
//first, how many can fit across
|
||||
S32 numAcross = getMax(1, (parent->mBounds.extent.x / newExtent.x + 2));
|
||||
|
||||
//find the new "mini position"
|
||||
Point2I newPosition;
|
||||
newPosition.x = (count % numAcross) * (newExtent.x + 2) + 2;
|
||||
newPosition.y = parent->mBounds.extent.y - (((count / numAcross) + 1) * (newExtent.y + 2)) - 2;
|
||||
|
||||
//find the minimized position and extent
|
||||
resize(newPosition, newExtent);
|
||||
|
||||
//set the index so other windows will not try to minimize to the same location
|
||||
mMinimizeIndex = count;
|
||||
|
||||
//set the flag
|
||||
mMinimized = true;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
GuiControl *GuiWindowCtrl::findNextTabable(GuiControl *curResponder, bool firstCall)
|
||||
{
|
||||
//set the global if this is the first call (directly from the canvas)
|
||||
if (firstCall)
|
||||
{
|
||||
GuiControl::smCurResponder = NULL;
|
||||
}
|
||||
|
||||
//if the window does not already contain the first responder, return false
|
||||
//ie. Can't tab into or out of a window
|
||||
if (! ControlIsChild(curResponder))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//loop through, checking each child to see if it is the one that follows the firstResponder
|
||||
GuiControl *tabCtrl = NULL;
|
||||
iterator i;
|
||||
for (i = begin(); i != end(); i++)
|
||||
{
|
||||
GuiControl *ctrl = static_cast<GuiControl *>(*i);
|
||||
tabCtrl = ctrl->findNextTabable(curResponder, false);
|
||||
if (tabCtrl) break;
|
||||
}
|
||||
|
||||
//to ensure the tab cycles within the current window...
|
||||
if (! tabCtrl)
|
||||
{
|
||||
tabCtrl = findFirstTabable();
|
||||
}
|
||||
|
||||
mFirstResponder = tabCtrl;
|
||||
return tabCtrl;
|
||||
}
|
||||
|
||||
GuiControl *GuiWindowCtrl::findPrevTabable(GuiControl *curResponder, bool firstCall)
|
||||
{
|
||||
if (firstCall)
|
||||
{
|
||||
GuiControl::smPrevResponder = NULL;
|
||||
}
|
||||
|
||||
//if the window does not already contain the first responder, return false
|
||||
//ie. Can't tab into or out of a window
|
||||
if (! ControlIsChild(curResponder))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//loop through, checking each child to see if it is the one that follows the firstResponder
|
||||
GuiControl *tabCtrl = NULL;
|
||||
iterator i;
|
||||
for (i = begin(); i != end(); i++)
|
||||
{
|
||||
GuiControl *ctrl = static_cast<GuiControl *>(*i);
|
||||
tabCtrl = ctrl->findPrevTabable(curResponder, false);
|
||||
if (tabCtrl) break;
|
||||
}
|
||||
|
||||
//to ensure the tab cycles within the current window...
|
||||
if (! tabCtrl)
|
||||
{
|
||||
tabCtrl = findLastTabable();
|
||||
}
|
||||
|
||||
mFirstResponder = tabCtrl;
|
||||
return tabCtrl;
|
||||
}
|
||||
|
||||
bool GuiWindowCtrl::onKeyDown(const GuiEvent &event)
|
||||
{
|
||||
//if this control is a dead end, kill the event
|
||||
if ((! mVisible) || (! mActive) || (! mAwake)) return true;
|
||||
|
||||
if ((event.keyCode == KEY_TAB) && (event.modifier & SI_CTRL))
|
||||
{
|
||||
//find the next sibling window, and select it
|
||||
GuiControl *parent = getParent();
|
||||
if (parent)
|
||||
{
|
||||
GuiWindowCtrl *firstWindow = NULL;
|
||||
iterator i;
|
||||
for (i = parent->begin(); i != parent->end(); i++)
|
||||
{
|
||||
GuiWindowCtrl *ctrl = dynamic_cast<GuiWindowCtrl *>(*i);
|
||||
if (ctrl && ctrl->getTabIndex() == mTabIndex + 1)
|
||||
{
|
||||
ctrl->selectWindow();
|
||||
return true;
|
||||
}
|
||||
else if (ctrl && ctrl->getTabIndex() == 0)
|
||||
{
|
||||
firstWindow = ctrl;
|
||||
}
|
||||
}
|
||||
//recycle from the beginning
|
||||
if (firstWindow != this)
|
||||
{
|
||||
firstWindow->selectWindow();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Parent::onKeyDown(event);
|
||||
}
|
||||
|
||||
void GuiWindowCtrl::selectWindow(void)
|
||||
{
|
||||
//first make sure this window is the front most of its siblings
|
||||
GuiControl *parent = getParent();
|
||||
if (parent)
|
||||
{
|
||||
parent->pushObjectToBack(this);
|
||||
}
|
||||
|
||||
//also set the first responder to be the one within this window
|
||||
setFirstResponder(mFirstResponder);
|
||||
}
|
||||
|
||||
void GuiWindowCtrl::drawWinRect(const RectI &myRect)
|
||||
{
|
||||
Point2I bl = myRect.point;
|
||||
Point2I tr;
|
||||
tr.x = myRect.point.x + myRect.extent.x - 1;
|
||||
tr.y = myRect.point.y + myRect.extent.y - 1;
|
||||
dglDrawRectFill(myRect, mProfile->mFillColor);
|
||||
dglDrawLine(Point2I(bl.x + 1, tr.y), Point2I(bl.x + 1, bl.y), ColorI(255, 255, 255));
|
||||
dglDrawLine(Point2I(bl.x, tr.y + 1), Point2I(tr.x, tr.y + 1), ColorI(255, 255, 255));
|
||||
//dglDrawRect(myRect, ColorI(0, 0, 0)); // Taken out, this is controled via mProfile->mBorder
|
||||
}
|
||||
|
||||
void GuiWindowCtrl::onRender(Point2I offset, const RectI &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 fontHeight = mFont->getHeight();
|
||||
S32 textWidth = mProfile->mFont->getStrWidth((const UTF8 *)mText);
|
||||
Point2I start(0,0);
|
||||
// align the horizontal
|
||||
if ( mProfile->mAlignment == GuiControlProfile::RightJustify )
|
||||
start.set( winRect.extent.x - textWidth, 0 );
|
||||
else if ( mProfile->mAlignment == GuiControlProfile::CenterJustify )
|
||||
start.set( ( winRect.extent.x - textWidth) / 2, 0 );
|
||||
else // GuiControlProfile::LeftJustify 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(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] );
|
||||
}
|
||||
|
||||
if( !mMinimized )
|
||||
{
|
||||
//render the children
|
||||
renderChildControls( offset, updateRect );
|
||||
}
|
||||
}
|
||||
|
||||
bool GuiWindowCtrl::initCursors()
|
||||
{
|
||||
if ( mUpDownCursor == NULL || mLeftRightCursor == NULL || mDefaultCursor == NULL || mNWSECursor == NULL || mNESWCursor == NULL )
|
||||
{
|
||||
SimObject *obj;
|
||||
obj = Sim::findObject("UpDownCursor");
|
||||
mUpDownCursor = dynamic_cast<GuiCursor*>(obj);
|
||||
obj = Sim::findObject("LeftRightCursor");
|
||||
mLeftRightCursor = dynamic_cast<GuiCursor*>(obj);
|
||||
obj = Sim::findObject("DefaultCursor");
|
||||
mDefaultCursor = dynamic_cast<GuiCursor*>(obj);
|
||||
obj = Sim::findObject("NESWCursor");
|
||||
mNESWCursor = dynamic_cast<GuiCursor*>(obj);
|
||||
obj = Sim::findObject("NWSECursor");
|
||||
mNWSECursor = dynamic_cast<GuiCursor*>(obj);
|
||||
|
||||
return( mUpDownCursor != NULL && mLeftRightCursor != NULL && mDefaultCursor != NULL && mNWSECursor != NULL && mNESWCursor != NULL );
|
||||
}
|
||||
else
|
||||
return(true);
|
||||
}
|
||||
|
||||
|
||||
void GuiWindowCtrl::getCursor(GuiCursor *&cursor, bool &showCursor, const GuiEvent &lastGuiEvent)
|
||||
{
|
||||
showCursor = true;
|
||||
|
||||
if( initCursors() )
|
||||
{
|
||||
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 );
|
||||
|
||||
if ( resizeRight && resizeBottom && mResizeHeight && mResizeWidth )
|
||||
cursor = mNWSECursor;
|
||||
else if ( resizeBottom && mResizeHeight )
|
||||
cursor = mUpDownCursor;
|
||||
else if ( resizeRight && mResizeWidth )
|
||||
cursor = mLeftRightCursor;
|
||||
else
|
||||
cursor = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user