guiRolloutCtrl.cpp 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657
  1. //-----------------------------------------------------------------------------
  2. // Copyright (c) 2012 GarageGames, LLC
  3. //
  4. // Permission is hereby granted, free of charge, to any person obtaining a copy
  5. // of this software and associated documentation files (the "Software"), to
  6. // deal in the Software without restriction, including without limitation the
  7. // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  8. // sell copies of the Software, and to permit persons to whom the Software is
  9. // furnished to do so, subject to the following conditions:
  10. //
  11. // The above copyright notice and this permission notice shall be included in
  12. // all copies or substantial portions of the Software.
  13. //
  14. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  19. // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  20. // IN THE SOFTWARE.
  21. //-----------------------------------------------------------------------------
  22. #include "gui/containers/guiRolloutCtrl.h"
  23. #include "gui/containers/guiScrollCtrl.h"
  24. #include "gfx/gfxDrawUtil.h"
  25. #include "console/engineAPI.h"
  26. IMPLEMENT_CONOBJECT( GuiRolloutCtrl );
  27. ConsoleDocClass( GuiRolloutCtrl,
  28. "@brief A container that shows a single child with an optional header bar that can be used to collapse and expand the rollout.\n\n"
  29. "A rollout is a container that can be collapsed and expanded using smooth animation. By default, rollouts will display a header "
  30. "with a caption along the top edge of the control which can be clicked by the user to toggle the collapse state of the rollout.\n\n"
  31. "Rollouts will automatically size themselves to exactly fit around their child control. They will also automatically position their child "
  32. "control in their upper left corner below the header (if present).\n\n"
  33. "@note GuiRolloutCtrls will only work correctly with a single child control. To put multiple controls in a rollout, put them "
  34. "in their own group using a new GuiControl which then can be put inside the rollout.\n\n"
  35. "@ingroup GuiContainers"
  36. );
  37. IMPLEMENT_CALLBACK( GuiRolloutCtrl, onHeaderRightClick, void, (), (),
  38. "Called when the user right-clicks on the rollout's header. This is useful for implementing "
  39. "context menus for rollouts." );
  40. IMPLEMENT_CALLBACK( GuiRolloutCtrl, onExpanded, void, (), (),
  41. "Called when the rollout is expanded." );
  42. IMPLEMENT_CALLBACK( GuiRolloutCtrl, onCollapsed, void, (), (),
  43. "Called when the rollout is collapsed." );
  44. //-----------------------------------------------------------------------------
  45. GuiRolloutCtrl::GuiRolloutCtrl()
  46. : mHeader(0,0,0,0),
  47. mExpanded(0,0,0,0),
  48. mChildRect(0,0,0,0),
  49. mMargin(0,0,0,0)
  50. {
  51. mExpanded.set(0,0,200,60);
  52. mCaption = StringTable->EmptyString();
  53. mIsExpanded = true;
  54. mIsAnimating = false;
  55. mCollapsing = false;
  56. mAnimateDestHeight = 40;
  57. mAnimateStep = 1;
  58. mDefaultHeight = 40;
  59. mHideHeader = false;
  60. mMargin.set( 0, 0, 0, 0 );
  61. mIsContainer = true;
  62. mCanCollapse = true;
  63. mAutoCollapseSiblings = false;
  64. mDefaultCursor = NULL;
  65. mVertSizingCursor = NULL;
  66. mHasTexture = false;
  67. mBitmapBounds = NULL;
  68. // Make sure we receive our ticks.
  69. setProcessTicks();
  70. }
  71. //-----------------------------------------------------------------------------
  72. GuiRolloutCtrl::~GuiRolloutCtrl()
  73. {
  74. }
  75. //-----------------------------------------------------------------------------
  76. void GuiRolloutCtrl::initPersistFields()
  77. {
  78. addGroup( "Rollout" );
  79. addField( "caption", TypeRealString, Offset( mCaption, GuiRolloutCtrl ),
  80. "Text label to display on the rollout header." );
  81. addField( "margin", TypeRectI, Offset( mMargin, GuiRolloutCtrl ),
  82. "Margin to put around child control." );
  83. addField( "defaultHeight", TypeS32, Offset( mDefaultHeight, GuiRolloutCtrl ),
  84. "Default height of the client area. This is used when no child control has been added to the rollout." );
  85. addProtectedField( "expanded", TypeBool, Offset( mIsExpanded, GuiRolloutCtrl), &setExpanded, &defaultProtectedGetFn,
  86. "The current rollout expansion state." );
  87. addField( "clickCollapse", TypeBool, Offset( mCanCollapse, GuiRolloutCtrl ),
  88. "Whether the rollout can be collapsed by clicking its header." );
  89. addField( "hideHeader", TypeBool, Offset( mHideHeader, GuiRolloutCtrl ),
  90. "Whether to render the rollout header.\n\n"
  91. "@note If this is false, the user cannot toggle the rollout state with the mouse." );
  92. addField( "autoCollapseSiblings", TypeBool, Offset( mAutoCollapseSiblings, GuiRolloutCtrl ),
  93. "Whether to automatically collapse sibling rollouts.\n\n"
  94. "If this is true, the rollout will automatically collapse all sibling rollout controls when it "
  95. "is expanded. If this is false, the auto-collapse behavior can be triggered by CTRL (CMD on MAC) "
  96. "clicking the rollout header. CTRL/CMD clicking also works if this is false, in which case the "
  97. "auto-collapsing of sibling controls will be temporarily deactivated." );
  98. endGroup( "Rollout" );
  99. Parent::initPersistFields();
  100. }
  101. //=============================================================================
  102. // Events.
  103. //=============================================================================
  104. // MARK: ---- Events ----
  105. //-----------------------------------------------------------------------------
  106. bool GuiRolloutCtrl::onAdd()
  107. {
  108. if ( !Parent::onAdd() )
  109. return false;
  110. mHasTexture = ( mProfile ? mProfile->constructBitmapArray() > 0 : false );
  111. if ( mHasTexture )
  112. mBitmapBounds = mProfile->mBitmapArrayRects.address();
  113. // Calculate Heights for this control
  114. calculateHeights();
  115. return true;
  116. }
  117. //-----------------------------------------------------------------------------
  118. bool GuiRolloutCtrl::onWake()
  119. {
  120. if (! Parent::onWake())
  121. return false;
  122. if( !mIsAnimating && mIsExpanded )
  123. sizeToContents();
  124. return true;
  125. }
  126. //-----------------------------------------------------------------------------
  127. void GuiRolloutCtrl::addObject( SimObject *obj )
  128. {
  129. // Call Parent.
  130. Parent::addObject( obj );
  131. sizeToContents();
  132. }
  133. //-----------------------------------------------------------------------------
  134. void GuiRolloutCtrl::removeObject( SimObject *obj )
  135. {
  136. // Call Parent.
  137. Parent::removeObject( obj );
  138. // Recalculate our rectangles.
  139. calculateHeights();
  140. }
  141. //-----------------------------------------------------------------------------
  142. void GuiRolloutCtrl::onMouseDown( const GuiEvent &event )
  143. {
  144. mouseLock();
  145. }
  146. //-----------------------------------------------------------------------------
  147. bool GuiRolloutCtrl::_onMouseUp( const GuiEvent &event, bool lockedMouse )
  148. {
  149. Point2I localPoint = globalToLocalCoord( event.mousePoint );
  150. if( mCanCollapse && mHeader.pointInRect( localPoint ) && !mIsAnimating && ( !lockedMouse || isMouseLocked() ) )
  151. {
  152. // If Ctrl/Cmd-clicking a header, collapse all sibling GuiRolloutCtrls.
  153. if( (( mAutoCollapseSiblings && !mIsExpanded && !( event.modifier & SI_PRIMARY_CTRL ))
  154. || ( !mAutoCollapseSiblings && event.modifier & SI_PRIMARY_CTRL ) ) )
  155. {
  156. for( SimSet::iterator iter = getParent()->begin(); iter != getParent()->end(); ++ iter )
  157. {
  158. GuiRolloutCtrl* ctrl = dynamic_cast< GuiRolloutCtrl* >( *iter );
  159. if( ctrl && ctrl != this && ctrl->mCanCollapse )
  160. ctrl->instantCollapse();
  161. }
  162. if( !mIsExpanded )
  163. expand();
  164. }
  165. else
  166. {
  167. // Toggle expansion.
  168. toggleExpanded( false );
  169. }
  170. return true;
  171. }
  172. return false;
  173. }
  174. //-----------------------------------------------------------------------------
  175. void GuiRolloutCtrl::onMouseUp( const GuiEvent &event )
  176. {
  177. _onMouseUp( event, true );
  178. if( isMouseLocked() )
  179. mouseUnlock();
  180. }
  181. //-----------------------------------------------------------------------------
  182. void GuiRolloutCtrl::onRightMouseUp( const GuiEvent& event )
  183. {
  184. Parent::onRightMouseUp( event );
  185. Point2I localMouse = globalToLocalCoord( event.mousePoint );
  186. if( mHeader.pointInRect( localMouse ) )
  187. onHeaderRightClick_callback();
  188. }
  189. //-----------------------------------------------------------------------------
  190. bool GuiRolloutCtrl::onMouseUpEditor( const GuiEvent& event, Point2I offset )
  191. {
  192. return ( event.modifier & SI_PRIMARY_ALT && _onMouseUp( event, false ) );
  193. }
  194. //=============================================================================
  195. // Sizing.
  196. //=============================================================================
  197. // MARK: ---- Sizing ----
  198. //-----------------------------------------------------------------------------
  199. void GuiRolloutCtrl::calculateHeights()
  200. {
  201. S32 barHeight = 20;
  202. if ( mHasTexture && mProfile && mProfile->mBitmapArrayRects.size() >= NumBitmaps )
  203. {
  204. // Store Header Rectangle
  205. mHeader.set( 0, 0, getWidth(), mProfile->mBitmapArrayRects[ CollapsedCenter ].extent.y );
  206. // Bottom Bar Max
  207. barHeight = mProfile->mBitmapArrayRects[ TopLeftHeader ].extent.y;
  208. }
  209. else
  210. {
  211. mHeader.set( 0, 0, getWidth(), barHeight );
  212. }
  213. if ( mHideHeader )
  214. {
  215. barHeight = 0;
  216. mHeader.extent.y = 0;
  217. }
  218. GuiControl *content = static_cast<GuiControl*>( at(0) );
  219. if ( content != NULL )
  220. mExpanded.set( 0, 0, getWidth(), barHeight + content->getHeight() + ( mMargin.point.y + mMargin.extent.y ) );
  221. else
  222. mExpanded.set( 0, 0, getWidth(), barHeight + mDefaultHeight );
  223. }
  224. //-----------------------------------------------------------------------------
  225. bool GuiRolloutCtrl::resize( const Point2I &newPosition, const Point2I &newExtent )
  226. {
  227. if ( !Parent::resize( newPosition, newExtent ) )
  228. return false;
  229. // Recalculate Heights and resize ourself appropriately.
  230. calculateHeights();
  231. GuiControl *content = dynamic_cast<GuiControl*>( at(0) );
  232. // Size Content Properly?!
  233. if ( mNotifyChildrenResized && content != NULL )
  234. {
  235. S32 barHeight = ( mHideHeader ) ? 0 : 20;
  236. if( !mHideHeader && mHasTexture && mProfile && mProfile->mBitmapArrayRects.size() >= NumBitmaps )
  237. {
  238. barHeight = mProfile->mBitmapArrayRects[ TopLeftHeader ].extent.y;
  239. }
  240. mChildRect.set( mMargin.point.x,
  241. mHeader.extent.y + mMargin.point.y,
  242. getWidth() - ( mMargin.point.x + mMargin.extent.x ),
  243. getHeight() - ( barHeight + ( mMargin.point.y + mMargin.extent.y ) ) );
  244. if ( content->resize( mChildRect.point, mChildRect.extent ) )
  245. return true;
  246. }
  247. // Nothing sized
  248. return false;
  249. }
  250. //-----------------------------------------------------------------------------
  251. void GuiRolloutCtrl::sizeToContents()
  252. {
  253. calculateHeights();
  254. // Set destination height
  255. if ( size() > 0 )
  256. instantExpand();
  257. else
  258. instantCollapse();
  259. }
  260. //-----------------------------------------------------------------------------
  261. void GuiRolloutCtrl::instantExpand()
  262. {
  263. mAnimateDestHeight = mExpanded.extent.y;
  264. mCollapsing = false;
  265. mIsExpanded = true;
  266. mIsAnimating = false;
  267. resize( getPosition() + mExpanded.point, mExpanded.extent );
  268. onExpanded_callback();
  269. }
  270. //-----------------------------------------------------------------------------
  271. void GuiRolloutCtrl::instantCollapse()
  272. {
  273. mAnimateDestHeight = mHeader.extent.y;
  274. mCollapsing = false;
  275. mIsExpanded = false;
  276. mIsAnimating = false;
  277. resize( getPosition() + mHeader.point, mHeader.extent );
  278. onCollapsed_callback();
  279. }
  280. //-----------------------------------------------------------------------------
  281. void GuiRolloutCtrl::toggleExpanded( bool instant )
  282. {
  283. if ( mIsExpanded )
  284. {
  285. if ( instant )
  286. instantCollapse();
  287. else
  288. collapse();
  289. }
  290. else
  291. {
  292. if ( instant )
  293. instantExpand();
  294. else
  295. expand();
  296. }
  297. }
  298. //-----------------------------------------------------------------------------
  299. void GuiRolloutCtrl::childResized( GuiControl *child )
  300. {
  301. Parent::childResized( child );
  302. calculateHeights();
  303. // While we are animating we are constantly resizing our children
  304. // and therefore need to ignore this call to 'instantExpand' which would
  305. // halt the animation in some crappy intermediate stage.
  306. if ( mIsExpanded && !mIsAnimating )
  307. {
  308. mNotifyChildrenResized = false;
  309. instantExpand();
  310. mNotifyChildrenResized = true;
  311. }
  312. }
  313. //=============================================================================
  314. // Animation.
  315. //=============================================================================
  316. // MARK: ---- Animation ----
  317. //-----------------------------------------------------------------------------
  318. void GuiRolloutCtrl::animateTo( S32 height )
  319. {
  320. // We do nothing if we're already animating
  321. if( mIsAnimating )
  322. return;
  323. bool collapsing = (bool)( getHeight() > height );
  324. // If we're already at the destination height, bail
  325. if ( getHeight() >= height && !collapsing )
  326. {
  327. mIsExpanded = true;
  328. return;
  329. }
  330. // If we're already at the destination height, bail
  331. if ( getHeight() <= height && collapsing )
  332. {
  333. mIsExpanded = false;
  334. return;
  335. }
  336. // Set destination height
  337. mAnimateDestHeight = height;
  338. // Set Animation Mode
  339. mCollapsing = collapsing;
  340. // Set Animation Step (Increment)
  341. if ( collapsing )
  342. mAnimateStep = (S32)mFloor( (F32)( getHeight() - height ) / 3.f );
  343. else
  344. mAnimateStep = (S32)mFloor( (F32)( height - getHeight() ) / 3.f );
  345. // Start our animation
  346. mIsAnimating = true;
  347. }
  348. //-----------------------------------------------------------------------------
  349. void GuiRolloutCtrl::processTick()
  350. {
  351. // We do nothing here if we're NOT animating
  352. if ( !mIsAnimating )
  353. return;
  354. // Sanity check to fix non collapsing panels.
  355. if ( mAnimateStep == 0 )
  356. mAnimateStep = 1;
  357. S32 newHeight = getHeight();
  358. // We're collapsing ourself down (Hiding our contents)
  359. if( mCollapsing )
  360. {
  361. if ( newHeight < mAnimateDestHeight )
  362. newHeight = mAnimateDestHeight;
  363. else if ( ( newHeight - mAnimateStep ) < mAnimateDestHeight )
  364. newHeight = mAnimateDestHeight;
  365. if ( newHeight == mAnimateDestHeight )
  366. mIsAnimating = false;
  367. else
  368. newHeight -= mAnimateStep;
  369. if( !mIsAnimating )
  370. {
  371. mIsExpanded = false;
  372. }
  373. }
  374. else // We're expanding ourself (Showing our contents)
  375. {
  376. if ( newHeight > mAnimateDestHeight )
  377. newHeight = mAnimateDestHeight;
  378. else if ( ( newHeight + mAnimateStep ) > mAnimateDestHeight )
  379. newHeight = mAnimateDestHeight;
  380. if ( newHeight == mAnimateDestHeight )
  381. mIsAnimating = false;
  382. else
  383. newHeight += mAnimateStep;
  384. if ( !mIsAnimating )
  385. mIsExpanded = true;
  386. }
  387. if ( newHeight != getHeight() )
  388. setHeight( newHeight );
  389. if ( !mIsAnimating )
  390. {
  391. if( mCollapsing )
  392. onCollapsed_callback();
  393. else if( !mCollapsing )
  394. onExpanded_callback();
  395. calculateHeights();
  396. }
  397. GuiControl* parent = getParent();
  398. if ( parent )
  399. {
  400. parent->childResized( this );
  401. // if our parent's parent is a scroll control, scrollvisible.
  402. GuiScrollCtrl* scroll = dynamic_cast<GuiScrollCtrl*>( parent->getParent() );
  403. if ( scroll )
  404. {
  405. scroll->scrollRectVisible( getBounds() );
  406. }
  407. }
  408. }
  409. //=============================================================================
  410. // Rendering.
  411. //=============================================================================
  412. // MARK: ---- Rendering ----
  413. //-----------------------------------------------------------------------------
  414. void GuiRolloutCtrl::onRender( Point2I offset, const RectI &updateRect )
  415. {
  416. if( !mProfile || mProfile->mFont == NULL )
  417. return;
  418. // Calculate actual world bounds for rendering
  419. RectI worldBounds( offset, getExtent() );
  420. // if opaque, fill the update rect with the fill color
  421. if ( mProfile->mOpaque )
  422. GFX->getDrawUtil()->drawRectFill( worldBounds, mProfile->mFillColor );
  423. if ( mProfile->mBitmapArrayRects.size() >= NumBitmaps )
  424. {
  425. GFX->getDrawUtil()->clearBitmapModulation();
  426. // Draw Rollout From Skin
  427. if ( !mIsExpanded && !mIsAnimating )
  428. renderFixedBitmapBordersFilled( worldBounds, 1, mProfile );
  429. else if ( mHideHeader )
  430. renderSizableBitmapBordersFilledIndex( worldBounds, MidPageLeft, mProfile );
  431. else
  432. renderSizableBitmapBordersFilledIndex( worldBounds, TopLeftHeader, mProfile );
  433. }
  434. if ( !(mIsExpanded && mHideHeader ) )
  435. {
  436. // Draw Caption ( Vertically Centered )
  437. ColorI currColor;
  438. GFX->getDrawUtil()->getBitmapModulation( &currColor );
  439. Point2I textPosition = mHeader.point + offset + mProfile->mTextOffset;
  440. GFX->getDrawUtil()->setBitmapModulation( mProfile->mFontColor );
  441. renderJustifiedText( textPosition, mHeader.extent, mCaption );
  442. GFX->getDrawUtil()->setBitmapModulation( currColor );
  443. }
  444. // If we're collapsed we contain the first child as our content
  445. // thus we don't render it when collapsed. but to support modified
  446. // rollouts with custom header buttons etc we still render our other
  447. // children. -JDD
  448. GuiControl *pChild = dynamic_cast<GuiControl*>( at(0) );
  449. if ( pChild )
  450. {
  451. if ( !mIsExpanded && !mIsAnimating && pChild->isVisible() )
  452. {
  453. pChild->setVisible( false );
  454. }
  455. else if ( (mIsExpanded || mIsAnimating) && !pChild->isVisible() )
  456. {
  457. pChild->setVisible( true );
  458. }
  459. }
  460. renderChildControls( offset, updateRect );
  461. // Render our border should we have it specified in our profile.
  462. renderBorder(worldBounds, mProfile);
  463. }
  464. //=============================================================================
  465. // Console Methods.
  466. //=============================================================================
  467. // MARK: ---- Console Methods ----
  468. //-----------------------------------------------------------------------------
  469. DefineEngineMethod( GuiRolloutCtrl, isExpanded, bool, (),,
  470. "Determine whether the rollout is currently expanded, i.e. whether the child control is visible.\n\n"
  471. "@return True if the rollout is expanded, false if not." )
  472. {
  473. return object->isExpanded();
  474. }
  475. //-----------------------------------------------------------------------------
  476. DefineEngineMethod( GuiRolloutCtrl, collapse, void, (),,
  477. "Collapse the rollout if it is currently expanded. This will make the rollout's child control invisible.\n\n"
  478. "@note The rollout will animate to collapsed state. To instantly collapse without animation, use instantCollapse()." )
  479. {
  480. object->collapse();
  481. }
  482. //-----------------------------------------------------------------------------
  483. DefineEngineMethod( GuiRolloutCtrl, expand, void, (),,
  484. "Expand the rollout if it is currently collapsed. This will make the rollout's child control visible.\n\n"
  485. "@note The rollout will animate to expanded state. To instantly expand without animation, use instantExpand()." )
  486. {
  487. object->expand();
  488. }
  489. //-----------------------------------------------------------------------------
  490. DefineEngineMethod( GuiRolloutCtrl, toggleCollapse, void, (),,
  491. "Toggle the current collapse state of the rollout. If it is currently expanded, then collapse it. If it "
  492. "is currently collapsed, then expand it." )
  493. {
  494. if( object->isExpanded() )
  495. object->collapse();
  496. else
  497. object->expand();
  498. }
  499. //-----------------------------------------------------------------------------
  500. DefineEngineMethod( GuiRolloutCtrl, toggleExpanded, void, ( bool instantly ), ( false ),
  501. "Toggle the current expansion state of the rollout If it is currently expanded, then collapse it. If it "
  502. "is currently collapsed, then expand it.\n\n"
  503. "@param instant If true, the rollout will toggle its state without animation. Otherwise, the rollout will "
  504. "smoothly slide into the opposite state." )
  505. {
  506. object->toggleExpanded( instantly );
  507. }
  508. //-----------------------------------------------------------------------------
  509. DefineEngineMethod( GuiRolloutCtrl, instantCollapse, void, (),,
  510. "Instantly collapse the rollout without animation. To smoothly slide the rollout to collapsed state, use collapse()." )
  511. {
  512. object->instantCollapse();
  513. }
  514. //-----------------------------------------------------------------------------
  515. DefineEngineMethod( GuiRolloutCtrl, instantExpand, void, (),,
  516. "Instantly expand the rollout without animation. To smoothly slide the rollout to expanded state, use expand()." )
  517. {
  518. object->instantExpand();
  519. }
  520. //-----------------------------------------------------------------------------
  521. DefineEngineMethod( GuiRolloutCtrl, sizeToContents, void, (),,
  522. "Resize the rollout to exactly fit around its child control. This can be used to manually trigger a recomputation of "
  523. "the rollout size." )
  524. {
  525. object->sizeToContents();
  526. }