123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330 |
- //-----------------------------------------------------------------------------
- // 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.
- //-----------------------------------------------------------------------------
- #include "gui/containers/guiPaneCtrl.h"
- IMPLEMENT_CONOBJECT(GuiPaneControl);
- GuiPaneControl::GuiPaneControl()
- {
- mMinExtent.set(10, 10);
- mActive = true;
- mCollapsable = true;
- mCollapsed = false;
- mBarBehindText = true;
- mMouseOver = false;
- mDepressed = false;
- mOriginalExtents.set(10,10);
- mCaption = StringTable->insert("A Pane");
- mCaptionID = StringTable->EmptyString;
- mIsContainer = true;
- }
- void GuiPaneControl::initPersistFields()
- {
- Parent::initPersistFields();
- addField("caption", TypeString, Offset(mCaption, GuiPaneControl));
- addField("captionID", TypeString, Offset(mCaptionID, GuiPaneControl));
- addField("collapsable", TypeBool, Offset(mCollapsable, GuiPaneControl));
- addField("barBehindText", TypeBool, Offset(mBarBehindText, GuiPaneControl));
- }
- bool GuiPaneControl::onWake()
- {
- if ( !Parent::onWake() )
- return false;
- mFont = mProfile->mFont;
- AssertFatal(mFont, "GuiPaneControl::onWake: invalid font in profile" );
- if(mCaptionID && *mCaptionID != 0)
- {
- setCaptionID(mCaptionID);
- }
- mProfile->constructBitmapArray();
- if(mProfile->mBitmapArrayRects.size())
- {
- mThumbSize.set( mProfile->mBitmapArrayRects[0].extent.x, mProfile->mBitmapArrayRects[0].extent.y );
- mThumbSize.setMax( mProfile->mBitmapArrayRects[1].extent );
- if(mFont->getHeight() > (U32)mThumbSize.y)
- mThumbSize.y = mFont->getHeight();
- }
- else
- {
- mThumbSize.set(20, 20);
- }
- return true;
- }
- void GuiPaneControl::onSleep()
- {
- Parent::onSleep();
- mFont = NULL;
- }
- void GuiPaneControl::setCaptionID(const char *id)
- {
- S32 n = Con::getIntVariable(id, -1);
- if(n != -1)
- {
- mCaptionID = StringTable->insert(id);
- setCaptionID(n);
- }
- }
- void GuiPaneControl::setCaptionID(S32 id)
- {
- const UTF8 *str = getGUIString(id);
- if(str)
- mCaption = StringTable->insert((const char*)str);
- }
- void GuiPaneControl::resize(const Point2I &newPosition, const Point2I &newExtent)
- {
- //call set update both before and after
- setUpdate();
- Point2I actualNewExtent = Point2I(getMax(mMinExtent.x, newExtent.x),
- getMax(mMinExtent.y, newExtent.y));
- mBounds.set(newPosition, actualNewExtent);
- mOriginalExtents.x = actualNewExtent.x;
- GuiControl *parent = getParent();
- if (parent)
- parent->childResized(this);
- setUpdate();
- // Resize the child control if we're not collapsed
- if(size() && !mCollapsed)
- {
- GuiControl *gc = dynamic_cast<GuiControl*>(operator[](0));
- if(gc)
- {
- Point2I offset(0, mThumbSize.y);
- gc->resize(offset, newExtent - offset);
- }
- }
- }
- void GuiPaneControl::onRender(Point2I offset, const RectI &updateRect)
- {
- // Render our awesome little doogong
- if(mProfile->mBitmapArrayRects.size() >= 2 && mCollapsable)
- {
- S32 idx = mCollapsed ? 0 : 1;
- dglClearBitmapModulation();
- dglDrawBitmapStretchSR(
- mProfile->mTextureHandle,
- RectI(offset, mProfile->mBitmapArrayRects[idx].extent),
- mProfile->mBitmapArrayRects[idx]
- );
- }
- S32 textWidth = 0;
- if(!mBarBehindText)
- {
- dglSetBitmapModulation((mMouseOver ? mProfile->mFontColorHL : mProfile->mFontColor));
- textWidth = dglDrawText(
- mFont,
- Point2I(mThumbSize.x, 0) + offset,
- mCaption,
- mProfile->mFontColors
- );
- }
- // Draw our little bar, too
- if(mProfile->mBitmapArrayRects.size() >= 5)
- {
- dglClearBitmapModulation();
- S32 barStart = mThumbSize.x + offset.x + textWidth;
- S32 barTop = mThumbSize.y/2 + offset.y - mProfile->mBitmapArrayRects[3].extent.y /2;
- Point2I barOffset(barStart, barTop);
- // Draw the start of the bar...
- dglDrawBitmapStretchSR(
- mProfile->mTextureHandle,
- RectI(barOffset, mProfile->mBitmapArrayRects[2].extent),
- mProfile->mBitmapArrayRects[2]
- );
- // Now draw the middle...
- barOffset.x += mProfile->mBitmapArrayRects[2].extent.x;
- S32 barMiddleSize = (getExtent().x - (barOffset.x - offset.x)) - mProfile->mBitmapArrayRects[4].extent.x;
- if(barMiddleSize>0)
- {
- // We have to do this inset to prevent nasty stretching artifacts
- RectI foo = mProfile->mBitmapArrayRects[3];
- foo.inset(1,0);
- dglDrawBitmapStretchSR(
- mProfile->mTextureHandle,
- RectI(barOffset, Point2I(barMiddleSize, mProfile->mBitmapArrayRects[3].extent.y)),
- foo
- );
- }
- // And the end
- barOffset.x += barMiddleSize;
- dglDrawBitmapStretchSR(
- mProfile->mTextureHandle,
- RectI(barOffset, mProfile->mBitmapArrayRects[4].extent),
- mProfile->mBitmapArrayRects[4]
- );
- }
- if(mBarBehindText)
- {
- dglSetBitmapModulation((mMouseOver ? mProfile->mFontColorHL : mProfile->mFontColor));
- dglDrawText(
- mFont,
- Point2I(mThumbSize.x, 0) + offset,
- mCaption,
- mProfile->mFontColors
- );
- }
- // Draw child controls if appropriate
- if(!mCollapsed)
- renderChildControls(offset, updateRect);
- }
- ConsoleMethod(GuiPaneControl, setCollapsed, void, 3, 3, "(bool collapsed) Sets the controls \"collapsed\" property\n"
- "@param collapsed True if the control is to be collapsed"
- "@return No return value.")
- {
- object->setCollapsed(dAtob(argv[2]));
- }
- void GuiPaneControl::setCollapsed(bool isCollapsed)
- {
- // Get the child
- if(size() == 0 || !mCollapsable) return;
- GuiControl *gc = dynamic_cast<GuiControl*>(operator[](0));
- if(mCollapsed && !isCollapsed)
- {
- mCollapsed = false;
- resize(getPosition(), mOriginalExtents);
- if(gc)
- gc->setVisible(true);
- }
- else if(!mCollapsed && isCollapsed)
- {
- mCollapsed = true;
- mOriginalExtents = getExtent();
- resize(getPosition(), Point2I(getExtent().x, mThumbSize.y));
- if(gc)
- gc->setVisible(false);
- }
- }
- void GuiPaneControl::onMouseMove(const GuiEvent &event)
- {
- Point2I localMove = globalToLocalCoord(event.mousePoint);
- // If we're clicking in the header then resize
- mMouseOver = (localMove.y < mThumbSize.y);
- if(isMouseLocked())
- mDepressed = mMouseOver;
- }
- void GuiPaneControl::onMouseEnter(const GuiEvent &event)
- {
- setUpdate();
- if(isMouseLocked())
- {
- mDepressed = true;
- mMouseOver = true;
- }
- else
- {
- mMouseOver = true;
- }
- }
- void GuiPaneControl::onMouseLeave(const GuiEvent &event)
- {
- setUpdate();
- if(isMouseLocked())
- mDepressed = false;
- mMouseOver = false;
- }
- void GuiPaneControl::onMouseDown(const GuiEvent &event)
- {
- if(!mCollapsable)
- return;
- Point2I localClick = globalToLocalCoord(event.mousePoint);
- // If we're clicking in the header then resize
- if(localClick.y < mThumbSize.y)
- {
- mouseLock();
- mDepressed = true;
- //update
- setUpdate();
- }
- }
- void GuiPaneControl::onMouseUp(const GuiEvent &event)
- {
- // Make sure we only get events we ought to be getting...
- if (! mActive)
- return;
- if(!mCollapsable)
- return;
- mouseUnlock();
- setUpdate();
- Point2I localClick = globalToLocalCoord(event.mousePoint);
- // If we're clicking in the header then resize
- if(localClick.y < mThumbSize.y && mDepressed)
- setCollapsed(!mCollapsed);
- }
|