📄 guiwindowctrl.cc
字号:
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))
{
char buf[16];
dSprintf(buf, sizeof(buf), "%d", getId());
Con::setVariable("$ThisControl", buf);
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;
/// TGE_Theme
mTextureHandle = mProfile->mTextureHandle;
bool isKey = (!firstResponder || ControlIsChild(firstResponder));
U32 topBase = isKey ? BorderTopLeftKey : BorderTopLeftNoKey;
////////////////////////////////////////////////////
//这里需要绘画纹理较复杂的边框,需要进行边框tile
#ifdef TGE_RPG_UI
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -