guiPaneCtrl.cpp
Engine/source/gui/containers/guiPaneCtrl.cpp
Public Functions
ConsoleDocClass(GuiPaneControl , "@brief A collapsable pane <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">control.\n\n</a>" "This class wraps <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> single child <a href="/coding/file/guieditctrl_8cpp/#guieditctrl_8cpp_1abb04e3738c4c5a96b3ade6fa47013a6c">control</a> and displays <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> header with caption " "above it. If you click the header it will collapse or expand (<a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> <<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1acb559820d9ca11295b4500f179ef6392">i</a>>collapsable</<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1acb559820d9ca11295b4500f179ef6392">i</a>> " "is enabled). The <a href="/coding/file/guieditctrl_8cpp/#guieditctrl_8cpp_1abb04e3738c4c5a96b3ade6fa47013a6c">control</a> resizes itself based on its collapsed/expanded size.<br>" "In the GUI editor, <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> you just want the header you can make< <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1acb559820d9ca11295b4500f179ef6392">i</a> >collapsable</<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1acb559820d9ca11295b4500f179ef6392">i</a> > " "false. The caption field lets you set the caption;it expects <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> bitmap(from " "the <a href="/coding/class/classguicontrolprofile/">GuiControlProfile</a>) that contains two images - the first is displayed when " "the <a href="/coding/file/guieditctrl_8cpp/#guieditctrl_8cpp_1abb04e3738c4c5a96b3ade6fa47013a6c">control</a> is expanded and the second is displayed when it is collapsed. The " "header is sized based on the first <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">image.\n\n</a>" " @<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">tsexample\n</a>" "<a href="/coding/file/tmm__on_8h/#tmm__on_8h_1a1ac41480eb2e4aadd52252ee550b630a">new</a> <a href="/coding/class/classguipanecontrol/">GuiPaneControl</a>()\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "{\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" " caption=\"Example Pane\";\n" " collapsable = \"1\";\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" " barBehindText = \"1\";\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" " //Properties not specific <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> this <a href="/coding/file/guieditctrl_8cpp/#guieditctrl_8cpp_1abb04e3738c4c5a96b3ade6fa47013a6c">control</a> have been omitted from this <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">example.\n</a>" "};\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "@<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">endtsexample\n\n</a>" "@ingroup GuiContainers" )
DefineEngineMethod(GuiPaneControl , setCollapsed , void , (bool collapse) , "Collapse or un-collapse the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">control.\n\n</a>" "@param collapse True <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> collapse the control, false <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> un-collapse <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">it\n</a>" )
Detailed Description
Public Functions
ConsoleDocClass(GuiPaneControl , "@brief A collapsable pane <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">control.\n\n</a>" "This class wraps <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> single child <a href="/coding/file/guieditctrl_8cpp/#guieditctrl_8cpp_1abb04e3738c4c5a96b3ade6fa47013a6c">control</a> and displays <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> header with caption " "above it. If you click the header it will collapse or expand (<a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> <<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1acb559820d9ca11295b4500f179ef6392">i</a>>collapsable</<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1acb559820d9ca11295b4500f179ef6392">i</a>> " "is enabled). The <a href="/coding/file/guieditctrl_8cpp/#guieditctrl_8cpp_1abb04e3738c4c5a96b3ade6fa47013a6c">control</a> resizes itself based on its collapsed/expanded size.<br>" "In the GUI editor, <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> you just want the header you can make< <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1acb559820d9ca11295b4500f179ef6392">i</a> >collapsable</<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1acb559820d9ca11295b4500f179ef6392">i</a> > " "false. The caption field lets you set the caption;it expects <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> bitmap(from " "the <a href="/coding/class/classguicontrolprofile/">GuiControlProfile</a>) that contains two images - the first is displayed when " "the <a href="/coding/file/guieditctrl_8cpp/#guieditctrl_8cpp_1abb04e3738c4c5a96b3ade6fa47013a6c">control</a> is expanded and the second is displayed when it is collapsed. The " "header is sized based on the first <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">image.\n\n</a>" " @<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">tsexample\n</a>" "<a href="/coding/file/tmm__on_8h/#tmm__on_8h_1a1ac41480eb2e4aadd52252ee550b630a">new</a> <a href="/coding/class/classguipanecontrol/">GuiPaneControl</a>()\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "{\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" " caption=\"Example Pane\";\n" " collapsable = \"1\";\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" " barBehindText = \"1\";\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" " //Properties not specific <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> this <a href="/coding/file/guieditctrl_8cpp/#guieditctrl_8cpp_1abb04e3738c4c5a96b3ade6fa47013a6c">control</a> have been omitted from this <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">example.\n</a>" "};\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "@<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">endtsexample\n\n</a>" "@ingroup GuiContainers" )
DefineEngineMethod(GuiPaneControl , setCollapsed , void , (bool collapse) , "Collapse or un-collapse the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">control.\n\n</a>" "@param collapse True <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> collapse the control, false <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> un-collapse <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">it\n</a>" )
IMPLEMENT_CONOBJECT(GuiPaneControl )
1 2//----------------------------------------------------------------------------- 3// Copyright (c) 2012 GarageGames, LLC 4// 5// Permission is hereby granted, free of charge, to any person obtaining a copy 6// of this software and associated documentation files (the "Software"), to 7// deal in the Software without restriction, including without limitation the 8// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 9// sell copies of the Software, and to permit persons to whom the Software is 10// furnished to do so, subject to the following conditions: 11// 12// The above copyright notice and this permission notice shall be included in 13// all copies or substantial portions of the Software. 14// 15// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21// IN THE SOFTWARE. 22//----------------------------------------------------------------------------- 23 24#include "console/engineAPI.h" 25#include "platform/platform.h" 26#include "gui/containers/guiPaneCtrl.h" 27 28#include "gfx/gfxDrawUtil.h" 29 30 31IMPLEMENT_CONOBJECT(GuiPaneControl); 32 33ConsoleDocClass( GuiPaneControl, 34 "@brief A collapsable pane control.\n\n" 35 36 "This class wraps a single child control and displays a header with caption " 37 "above it. If you click the header it will collapse or expand (if <i>collapsable</i> " 38 "is enabled). The control resizes itself based on its collapsed/expanded size.<br>" 39 40 "In the GUI editor, if you just want the header you can make <i>collapsable</i> " 41 "false. The caption field lets you set the caption; it expects a bitmap (from " 42 "the GuiControlProfile) that contains two images - the first is displayed when " 43 "the control is expanded and the second is displayed when it is collapsed. The " 44 "header is sized based on the first image.\n\n" 45 46 "@tsexample\n" 47 "new GuiPaneControl()\n" 48 "{\n" 49 " caption = \"Example Pane\";\n" 50 " collapsable = \"1\";\n" 51 " barBehindText = \"1\";\n" 52 " //Properties not specific to this control have been omitted from this example.\n" 53 "};\n" 54 "@endtsexample\n\n" 55 56 "@ingroup GuiContainers" 57); 58 59//----------------------------------------------------------------------------- 60 61GuiPaneControl::GuiPaneControl() 62{ 63 setMinExtent(Point2I(16,16)); 64 65 mActive = true; 66 mCollapsable = true; 67 mCollapsed = false; 68 mBarBehindText = true; 69 mMouseOver = false; 70 mDepressed = false; 71 mCaption = "A Pane"; 72 mCaptionID = StringTable->EmptyString(); 73 mIsContainer = true; 74 75 mOriginalExtents.set(10,10); 76} 77 78//----------------------------------------------------------------------------- 79 80void GuiPaneControl::initPersistFields() 81{ 82 addGroup( "Pane" ); 83 84 addField("caption", TypeRealString, Offset(mCaption, GuiPaneControl), 85 "Text label to display as the pane header." ); 86 addField("captionID", TypeString, Offset(mCaptionID, GuiPaneControl), 87 "String table text ID to use as caption string (overrides 'caption')." ); 88 addField("collapsable", TypeBool, Offset(mCollapsable, GuiPaneControl), 89 "Whether the pane can be collapsed by clicking its header." ); 90 addField("barBehindText", TypeBool, Offset(mBarBehindText, GuiPaneControl), 91 "Whether to draw the bitmapped pane bar behind the header text, too." ); 92 93 endGroup( "Pane" ); 94 95 Parent::initPersistFields(); 96} 97 98//----------------------------------------------------------------------------- 99 100bool GuiPaneControl::onWake() 101{ 102 if ( !Parent::onWake() ) 103 return false; 104 105 if( !mProfile->mFont ) 106 { 107 Con::errorf( "GuiPaneControl::onWake - profile has no valid font" ); 108 return false; 109 } 110 111 if(mCaptionID && *mCaptionID != 0) 112 setCaptionID(mCaptionID); 113 114 mProfile->constructBitmapArray(); 115 if(mProfile->mUseBitmapArray && mProfile->mBitmapArrayRects.size()) 116 { 117 mThumbSize.set( mProfile->mBitmapArrayRects[0].extent.x, mProfile->mBitmapArrayRects[0].extent.y ); 118 mThumbSize.setMax( mProfile->mBitmapArrayRects[1].extent ); 119 120 if( mProfile->mFont->getHeight() > mThumbSize.y ) 121 mThumbSize.y = mProfile->mFont->getHeight(); 122 } 123 else 124 { 125 mThumbSize.set(20, 20); 126 } 127 128 return true; 129} 130 131//----------------------------------------------------------------------------- 132 133void GuiPaneControl::setCaptionID(const char *id) 134{ 135 S32 n = Con::getIntVariable(id, -1); 136 if(n != -1) 137 { 138 mCaptionID = StringTable->insert(id); 139 setCaptionID(n); 140 } 141} 142 143//----------------------------------------------------------------------------- 144 145void GuiPaneControl::setCaptionID(S32 id) 146{ 147 mCaption = getGUIString(id); 148} 149 150//----------------------------------------------------------------------------- 151 152bool GuiPaneControl::resize(const Point2I &newPosition, const Point2I &newExtent) 153{ 154 // CodeReview WTF is going on here that we need to bypass parent sanity? 155 // Investigate this [7/1/2007 justind] 156 if( !Parent::resize( newPosition, newExtent ) ) 157 return false; 158 159 mOriginalExtents.x = getWidth(); 160 161 /* 162 GuiControl *parent = getParent(); 163 if (parent) 164 parent->childResized(this); 165 setUpdate(); 166 */ 167 168 // Resize the child control if we're not collapsed 169 if(size() && !mCollapsed) 170 { 171 GuiControl *gc = dynamic_cast<GuiControl*>(operator[](0)); 172 173 if(gc) 174 { 175 Point2I offset(0, mThumbSize.y); 176 177 gc->resize(offset, newExtent - offset); 178 } 179 } 180 181 // For now. 182 return true; 183} 184 185//----------------------------------------------------------------------------- 186 187void GuiPaneControl::onRender(Point2I offset, const RectI &updateRect) 188{ 189 // Render our awesome little doogong 190 if(mProfile->mBitmapArrayRects.size() >= 2 && mCollapsable) 191 { 192 S32 idx = mCollapsed ? 0 : 1; 193 194 GFX->getDrawUtil()->clearBitmapModulation(); 195 GFX->getDrawUtil()->drawBitmapStretchSR( 196 mProfile->mTextureObject, 197 RectI(offset, mProfile->mBitmapArrayRects[idx].extent), 198 mProfile->mBitmapArrayRects[idx] 199 ); 200 201 } 202 203 S32 textWidth = 0; 204 205 if(!mBarBehindText) 206 { 207 GFX->getDrawUtil()->setBitmapModulation((mMouseOver ? mProfile->mFontColorHL : mProfile->mFontColor)); 208 textWidth = GFX->getDrawUtil()->drawText( 209 mProfile->mFont, 210 Point2I(mThumbSize.x, 0) + offset, 211 mCaption, 212 mProfile->mFontColors 213 ); 214 } 215 216 217 // Draw our little bar, too 218 if(mProfile->mBitmapArrayRects.size() >= 5) 219 { 220 GFX->getDrawUtil()->clearBitmapModulation(); 221 222 S32 barStart = mThumbSize.x + offset.x + textWidth; 223 S32 barTop = mThumbSize.y/2 + offset.y - mProfile->mBitmapArrayRects[3].extent.y /2; 224 225 Point2I barOffset(barStart, barTop); 226 227 // Draw the start of the bar... 228 GFX->getDrawUtil()->drawBitmapStretchSR( 229 mProfile->mTextureObject, 230 RectI(barOffset, mProfile->mBitmapArrayRects[2].extent), 231 mProfile->mBitmapArrayRects[2] 232 ); 233 234 // Now draw the middle... 235 barOffset.x += mProfile->mBitmapArrayRects[2].extent.x; 236 237 S32 barMiddleSize = (getExtent().x - (barOffset.x - offset.x)) - mProfile->mBitmapArrayRects[4].extent.x; 238 239 if(barMiddleSize>0) 240 { 241 // We have to do this inset to prevent nasty stretching artifacts 242 RectI foo = mProfile->mBitmapArrayRects[3]; 243 foo.inset(1,0); 244 245 GFX->getDrawUtil()->drawBitmapStretchSR( 246 mProfile->mTextureObject, 247 RectI(barOffset, Point2I(barMiddleSize, mProfile->mBitmapArrayRects[3].extent.y)), 248 foo 249 ); 250 } 251 252 // And the end 253 barOffset.x += barMiddleSize; 254 255 GFX->getDrawUtil()->drawBitmapStretchSR( 256 mProfile->mTextureObject, 257 RectI(barOffset, mProfile->mBitmapArrayRects[4].extent), 258 mProfile->mBitmapArrayRects[4] 259 ); 260 } 261 262 if(mBarBehindText) 263 { 264 GFX->getDrawUtil()->setBitmapModulation((mMouseOver ? mProfile->mFontColorHL : mProfile->mFontColor)); 265 GFX->getDrawUtil()->drawText( 266 mProfile->mFont, 267 Point2I(mThumbSize.x, 0) + offset, 268 mCaption, 269 mProfile->mFontColors 270 ); 271 } 272 273 // Draw child controls if appropriate 274 if(!mCollapsed) 275 renderChildControls(offset, updateRect); 276} 277 278//----------------------------------------------------------------------------- 279 280void GuiPaneControl::setCollapsed(bool isCollapsed) 281{ 282 // Get the child 283 if(size() == 0 || !mCollapsable) return; 284 285 GuiControl *gc = dynamic_cast<GuiControl*>(operator[](0)); 286 287 if(mCollapsed && !isCollapsed) 288 { 289 resize(getPosition(), mOriginalExtents); 290 mCollapsed = false; 291 292 if(gc) 293 gc->setVisible(true); 294 } 295 else if(!mCollapsed && isCollapsed) 296 { 297 mCollapsed = true; 298 299 mOriginalExtents = getExtent(); 300 resize(getPosition(), Point2I(getExtent().x, mThumbSize.y)); 301 302 if(gc) 303 gc->setVisible(false); 304 } 305} 306 307//----------------------------------------------------------------------------- 308 309void GuiPaneControl::onMouseMove(const GuiEvent &event) 310{ 311 Point2I localMove = globalToLocalCoord(event.mousePoint); 312 313 // If we're clicking in the header then resize 314 mMouseOver = (localMove.y < mThumbSize.y); 315 if(isMouseLocked()) 316 mDepressed = mMouseOver; 317 318} 319 320//----------------------------------------------------------------------------- 321 322void GuiPaneControl::onMouseEnter(const GuiEvent &event) 323{ 324 setUpdate(); 325 if(isMouseLocked()) 326 { 327 mDepressed = true; 328 mMouseOver = true; 329 } 330 else 331 { 332 mMouseOver = true; 333 } 334 335} 336 337//----------------------------------------------------------------------------- 338 339void GuiPaneControl::onMouseLeave(const GuiEvent &event) 340{ 341 setUpdate(); 342 if(isMouseLocked()) 343 mDepressed = false; 344 mMouseOver = false; 345} 346 347//----------------------------------------------------------------------------- 348 349void GuiPaneControl::onMouseDown(const GuiEvent &event) 350{ 351 if(!mCollapsable) 352 return; 353 354 Point2I localClick = globalToLocalCoord(event.mousePoint); 355 356 // If we're clicking in the header then resize 357 if(localClick.y < mThumbSize.y) 358 { 359 mouseLock(); 360 mDepressed = true; 361 362 //update 363 setUpdate(); 364 } 365} 366 367//----------------------------------------------------------------------------- 368 369void GuiPaneControl::onMouseUp(const GuiEvent &event) 370{ 371 // Make sure we only get events we ought to be getting... 372 if (! mActive) 373 return; 374 375 if(!mCollapsable) 376 return; 377 378 mouseUnlock(); 379 setUpdate(); 380 381 Point2I localClick = globalToLocalCoord(event.mousePoint); 382 383 // If we're clicking in the header then resize 384 if(localClick.y < mThumbSize.y && mDepressed) 385 setCollapsed(!mCollapsed); 386} 387 388//============================================================================= 389// Console Methods. 390//============================================================================= 391 392DefineEngineMethod( GuiPaneControl, setCollapsed, void, ( bool collapse ),, 393 "Collapse or un-collapse the control.\n\n" 394 "@param collapse True to collapse the control, false to un-collapse it\n" ) 395{ 396 object->setCollapsed( collapse ); 397} 398