guiRolloutCtrl.cpp
Engine/source/gui/containers/guiRolloutCtrl.cpp
Public Functions
ConsoleDocClass(GuiRolloutCtrl , "@brief A container that shows <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> single child with an optional header bar that can be used <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> collapse and expand the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">rollout.\n\n</a>" "A rollout is <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> container that can be collapsed and expanded using smooth animation. By default, rollouts will display <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> header " "with <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> caption along the top edge of the <a href="/coding/file/guieditctrl_8cpp/#guieditctrl_8cpp_1abb04e3738c4c5a96b3ade6fa47013a6c">control</a> which can be clicked by the user <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> toggle the collapse state of the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">rollout.\n\n</a>" "Rollouts will automatically <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1ab7d671599a7b25ca99a487fa341bc33a">size</a> themselves <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> exactly fit around their child control. They will also automatically position their child " "<a href="/coding/file/guieditctrl_8cpp/#guieditctrl_8cpp_1abb04e3738c4c5a96b3ade6fa47013a6c">control</a> in their upper left corner below the header(<a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> present).\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n\n</a>" " @note GuiRolloutCtrls will only work correctly with <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> single child control. To put multiple controls in <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> rollout, put them " "in their own group using <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> <a href="/coding/file/tmm__on_8h/#tmm__on_8h_1a1ac41480eb2e4aadd52252ee550b630a">new</a> <a href="/coding/class/classguicontrol/">GuiControl</a> which then can be put inside the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">rollout.\n\n</a>" " @ingroup GuiContainers" )
DefineEngineMethod(GuiRolloutCtrl , collapse , void , () , "Collapse the rollout <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> it is currently expanded. This will make the rollout's child <a href="/coding/file/guieditctrl_8cpp/#guieditctrl_8cpp_1abb04e3738c4c5a96b3ade6fa47013a6c">control</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">invisible.\n\n</a>" "@note The rollout will animate <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> collapsed state. To instantly collapse without animation, use instantCollapse()." )
DefineEngineMethod(GuiRolloutCtrl , expand , void , () , "Expand the rollout <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> it is currently collapsed. This will make the rollout's child <a href="/coding/file/guieditctrl_8cpp/#guieditctrl_8cpp_1abb04e3738c4c5a96b3ade6fa47013a6c">control</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">visible.\n\n</a>" "@note The rollout will animate <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> expanded state. To instantly expand without animation, use instantExpand()." )
DefineEngineMethod(GuiRolloutCtrl , instantCollapse , void , () , "Instantly collapse the rollout without animation. To smoothly slide the rollout <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> collapsed state, use collapse()." )
DefineEngineMethod(GuiRolloutCtrl , instantExpand , void , () , "Instantly expand the rollout without animation. To smoothly slide the rollout <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> expanded state, use expand()." )
DefineEngineMethod(GuiRolloutCtrl , isExpanded , bool , () , "Determine whether the rollout is currently expanded, i.e. whether the child <a href="/coding/file/guieditctrl_8cpp/#guieditctrl_8cpp_1abb04e3738c4c5a96b3ade6fa47013a6c">control</a> is <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">visible.\n\n</a>" " @return True <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> the rollout is expanded, false <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> not." )
DefineEngineMethod(GuiRolloutCtrl , sizeToContents , void , () , "Resize the rollout <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> exactly fit around its child control. This can be used <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> manually trigger <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> recomputation of " "the rollout size." )
DefineEngineMethod(GuiRolloutCtrl , toggleCollapse , void , () , "Toggle the current collapse state of the rollout. If it is currently expanded, then collapse it. If it " "is currently collapsed, then expand it." )
DefineEngineMethod(GuiRolloutCtrl , toggleExpanded , void , (bool instantly) , (false) , "Toggle the current expansion state of the rollout If it is currently expanded, then collapse it. If it " "is currently collapsed, then expand <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">it.\n\n</a>" " @param instant If true, the rollout will toggle its state without animation. Otherwise, the rollout will " "smoothly slide into the opposite state." )
IMPLEMENT_CALLBACK(GuiRolloutCtrl , onCollapsed , void , () , () , "Called when the rollout is collapsed." )
IMPLEMENT_CALLBACK(GuiRolloutCtrl , onExpanded , void , () , () , "Called when the rollout is expanded." )
IMPLEMENT_CALLBACK(GuiRolloutCtrl , onHeaderRightClick , void , () , () , "Called when the user right-clicks on the rollout's header. This is useful <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> implementing " "context menus <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> rollouts." )
Detailed Description
Public Functions
ConsoleDocClass(GuiRolloutCtrl , "@brief A container that shows <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> single child with an optional header bar that can be used <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> collapse and expand the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">rollout.\n\n</a>" "A rollout is <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> container that can be collapsed and expanded using smooth animation. By default, rollouts will display <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> header " "with <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> caption along the top edge of the <a href="/coding/file/guieditctrl_8cpp/#guieditctrl_8cpp_1abb04e3738c4c5a96b3ade6fa47013a6c">control</a> which can be clicked by the user <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> toggle the collapse state of the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">rollout.\n\n</a>" "Rollouts will automatically <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1ab7d671599a7b25ca99a487fa341bc33a">size</a> themselves <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> exactly fit around their child control. They will also automatically position their child " "<a href="/coding/file/guieditctrl_8cpp/#guieditctrl_8cpp_1abb04e3738c4c5a96b3ade6fa47013a6c">control</a> in their upper left corner below the header(<a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> present).\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n\n</a>" " @note GuiRolloutCtrls will only work correctly with <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> single child control. To put multiple controls in <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> rollout, put them " "in their own group using <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> <a href="/coding/file/tmm__on_8h/#tmm__on_8h_1a1ac41480eb2e4aadd52252ee550b630a">new</a> <a href="/coding/class/classguicontrol/">GuiControl</a> which then can be put inside the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">rollout.\n\n</a>" " @ingroup GuiContainers" )
DefineEngineMethod(GuiRolloutCtrl , collapse , void , () , "Collapse the rollout <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> it is currently expanded. This will make the rollout's child <a href="/coding/file/guieditctrl_8cpp/#guieditctrl_8cpp_1abb04e3738c4c5a96b3ade6fa47013a6c">control</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">invisible.\n\n</a>" "@note The rollout will animate <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> collapsed state. To instantly collapse without animation, use instantCollapse()." )
DefineEngineMethod(GuiRolloutCtrl , expand , void , () , "Expand the rollout <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> it is currently collapsed. This will make the rollout's child <a href="/coding/file/guieditctrl_8cpp/#guieditctrl_8cpp_1abb04e3738c4c5a96b3ade6fa47013a6c">control</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">visible.\n\n</a>" "@note The rollout will animate <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> expanded state. To instantly expand without animation, use instantExpand()." )
DefineEngineMethod(GuiRolloutCtrl , instantCollapse , void , () , "Instantly collapse the rollout without animation. To smoothly slide the rollout <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> collapsed state, use collapse()." )
DefineEngineMethod(GuiRolloutCtrl , instantExpand , void , () , "Instantly expand the rollout without animation. To smoothly slide the rollout <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> expanded state, use expand()." )
DefineEngineMethod(GuiRolloutCtrl , isExpanded , bool , () , "Determine whether the rollout is currently expanded, i.e. whether the child <a href="/coding/file/guieditctrl_8cpp/#guieditctrl_8cpp_1abb04e3738c4c5a96b3ade6fa47013a6c">control</a> is <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">visible.\n\n</a>" " @return True <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> the rollout is expanded, false <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> not." )
DefineEngineMethod(GuiRolloutCtrl , sizeToContents , void , () , "Resize the rollout <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> exactly fit around its child control. This can be used <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> manually trigger <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> recomputation of " "the rollout size." )
DefineEngineMethod(GuiRolloutCtrl , toggleCollapse , void , () , "Toggle the current collapse state of the rollout. If it is currently expanded, then collapse it. If it " "is currently collapsed, then expand it." )
DefineEngineMethod(GuiRolloutCtrl , toggleExpanded , void , (bool instantly) , (false) , "Toggle the current expansion state of the rollout If it is currently expanded, then collapse it. If it " "is currently collapsed, then expand <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">it.\n\n</a>" " @param instant If true, the rollout will toggle its state without animation. Otherwise, the rollout will " "smoothly slide into the opposite state." )
IMPLEMENT_CALLBACK(GuiRolloutCtrl , onCollapsed , void , () , () , "Called when the rollout is collapsed." )
IMPLEMENT_CALLBACK(GuiRolloutCtrl , onExpanded , void , () , () , "Called when the rollout is expanded." )
IMPLEMENT_CALLBACK(GuiRolloutCtrl , onHeaderRightClick , void , () , () , "Called when the user right-clicks on the rollout's header. This is useful <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> implementing " "context menus <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> rollouts." )
IMPLEMENT_CONOBJECT(GuiRolloutCtrl )
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 "gui/containers/guiRolloutCtrl.h" 25#include "gui/containers/guiScrollCtrl.h" 26#include "gfx/gfxDrawUtil.h" 27#include "console/engineAPI.h" 28 29 30IMPLEMENT_CONOBJECT( GuiRolloutCtrl ); 31 32ConsoleDocClass( GuiRolloutCtrl, 33 "@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" 34 35 "A rollout is a container that can be collapsed and expanded using smooth animation. By default, rollouts will display a header " 36 "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" 37 38 "Rollouts will automatically size themselves to exactly fit around their child control. They will also automatically position their child " 39 "control in their upper left corner below the header (if present).\n\n" 40 41 "@note GuiRolloutCtrls will only work correctly with a single child control. To put multiple controls in a rollout, put them " 42 "in their own group using a new GuiControl which then can be put inside the rollout.\n\n" 43 44 "@ingroup GuiContainers" 45); 46 47IMPLEMENT_CALLBACK( GuiRolloutCtrl, onHeaderRightClick, void, (), (), 48 "Called when the user right-clicks on the rollout's header. This is useful for implementing " 49 "context menus for rollouts." ); 50 51IMPLEMENT_CALLBACK( GuiRolloutCtrl, onExpanded, void, (), (), 52 "Called when the rollout is expanded." ); 53 54IMPLEMENT_CALLBACK( GuiRolloutCtrl, onCollapsed, void, (), (), 55 "Called when the rollout is collapsed." ); 56 57//----------------------------------------------------------------------------- 58 59GuiRolloutCtrl::GuiRolloutCtrl() 60 : mHeader(0,0,0,0), 61 mExpanded(0,0,0,0), 62 mChildRect(0,0,0,0), 63 mMargin(0,0,0,0) 64{ 65 mExpanded.set(0,0,200,60); 66 mCaption = StringTable->EmptyString(); 67 mIsExpanded = true; 68 mIsAnimating = false; 69 mCollapsing = false; 70 mAnimateDestHeight = 40; 71 mAnimateStep = 1; 72 mDefaultHeight = 40; 73 mHideHeader = false; 74 mMargin.set( 0, 0, 0, 0 ); 75 mIsContainer = true; 76 mCanCollapse = true; 77 mAutoCollapseSiblings = false; 78 mDefaultCursor = NULL; 79 mVertSizingCursor = NULL; 80 mHasTexture = false; 81 mBitmapBounds = NULL; 82 // Make sure we receive our ticks. 83 setProcessTicks(); 84} 85 86//----------------------------------------------------------------------------- 87 88GuiRolloutCtrl::~GuiRolloutCtrl() 89{ 90} 91 92//----------------------------------------------------------------------------- 93 94void GuiRolloutCtrl::initPersistFields() 95{ 96 addGroup( "Rollout" ); 97 98 addField( "caption", TypeRealString, Offset( mCaption, GuiRolloutCtrl ), 99 "Text label to display on the rollout header." ); 100 addField( "margin", TypeRectI, Offset( mMargin, GuiRolloutCtrl ), 101 "Margin to put around child control." ); 102 addField( "defaultHeight", TypeS32, Offset( mDefaultHeight, GuiRolloutCtrl ), 103 "Default height of the client area. This is used when no child control has been added to the rollout." ); 104 addProtectedField( "expanded", TypeBool, Offset( mIsExpanded, GuiRolloutCtrl), &setExpanded, &defaultProtectedGetFn, 105 "The current rollout expansion state." ); 106 addField( "clickCollapse", TypeBool, Offset( mCanCollapse, GuiRolloutCtrl ), 107 "Whether the rollout can be collapsed by clicking its header." ); 108 addField( "hideHeader", TypeBool, Offset( mHideHeader, GuiRolloutCtrl ), 109 "Whether to render the rollout header.\n\n" 110 "@note If this is false, the user cannot toggle the rollout state with the mouse." ); 111 addField( "autoCollapseSiblings", TypeBool, Offset( mAutoCollapseSiblings, GuiRolloutCtrl ), 112 "Whether to automatically collapse sibling rollouts.\n\n" 113 "If this is true, the rollout will automatically collapse all sibling rollout controls when it " 114 "is expanded. If this is false, the auto-collapse behavior can be triggered by CTRL (CMD on MAC) " 115 "clicking the rollout header. CTRL/CMD clicking also works if this is false, in which case the " 116 "auto-collapsing of sibling controls will be temporarily deactivated." ); 117 118 endGroup( "Rollout" ); 119 120 Parent::initPersistFields(); 121} 122 123//============================================================================= 124// Events. 125//============================================================================= 126// MARK: ---- Events ---- 127 128//----------------------------------------------------------------------------- 129 130bool GuiRolloutCtrl::onAdd() 131{ 132 if ( !Parent::onAdd() ) 133 return false; 134 135 mHasTexture = ( mProfile ? mProfile->constructBitmapArray() > 0 : false ); 136 if ( mHasTexture ) 137 mBitmapBounds = mProfile->mBitmapArrayRects.address(); 138 139 // Calculate Heights for this control 140 calculateHeights(); 141 142 return true; 143} 144 145//----------------------------------------------------------------------------- 146 147bool GuiRolloutCtrl::onWake() 148{ 149 if (! Parent::onWake()) 150 return false; 151 152 if( !mIsAnimating && mIsExpanded ) 153 sizeToContents(); 154 155 return true; 156} 157 158//----------------------------------------------------------------------------- 159 160void GuiRolloutCtrl::addObject( SimObject *obj ) 161{ 162 // Call Parent. 163 Parent::addObject( obj ); 164 165 sizeToContents(); 166} 167 168//----------------------------------------------------------------------------- 169 170void GuiRolloutCtrl::removeObject( SimObject *obj ) 171{ 172 // Call Parent. 173 Parent::removeObject( obj ); 174 175 // Recalculate our rectangles. 176 calculateHeights(); 177} 178 179//----------------------------------------------------------------------------- 180 181void GuiRolloutCtrl::onMouseDown( const GuiEvent &event ) 182{ 183 mouseLock(); 184} 185 186//----------------------------------------------------------------------------- 187 188bool GuiRolloutCtrl::_onMouseUp( const GuiEvent &event, bool lockedMouse ) 189{ 190 Point2I localPoint = globalToLocalCoord( event.mousePoint ); 191 if( mCanCollapse && mHeader.pointInRect( localPoint ) && !mIsAnimating && ( !lockedMouse || isMouseLocked() ) ) 192 { 193 // If Ctrl/Cmd-clicking a header, collapse all sibling GuiRolloutCtrls. 194 195 if( (( mAutoCollapseSiblings && !mIsExpanded && !( event.modifier & SI_PRIMARY_CTRL )) 196 || ( !mAutoCollapseSiblings && event.modifier & SI_PRIMARY_CTRL ) ) ) 197 { 198 for( SimSet::iterator iter = getParent()->begin(); iter != getParent()->end(); ++ iter ) 199 { 200 GuiRolloutCtrl* ctrl = dynamic_cast< GuiRolloutCtrl* >( *iter ); 201 if( ctrl && ctrl != this && ctrl->mCanCollapse ) 202 ctrl->instantCollapse(); 203 } 204 205 if( !mIsExpanded ) 206 expand(); 207 } 208 else 209 { 210 // Toggle expansion. 211 212 toggleExpanded( false ); 213 } 214 215 return true; 216 } 217 218 return false; 219} 220 221//----------------------------------------------------------------------------- 222 223void GuiRolloutCtrl::onMouseUp( const GuiEvent &event ) 224{ 225 _onMouseUp( event, true ); 226 if( isMouseLocked() ) 227 mouseUnlock(); 228} 229 230//----------------------------------------------------------------------------- 231 232void GuiRolloutCtrl::onRightMouseUp( const GuiEvent& event ) 233{ 234 Parent::onRightMouseUp( event ); 235 236 Point2I localMouse = globalToLocalCoord( event.mousePoint ); 237 if( mHeader.pointInRect( localMouse ) ) 238 onHeaderRightClick_callback(); 239} 240 241//----------------------------------------------------------------------------- 242 243bool GuiRolloutCtrl::onMouseUpEditor( const GuiEvent& event, Point2I offset ) 244{ 245 return ( event.modifier & SI_PRIMARY_ALT && _onMouseUp( event, false ) ); 246} 247 248//============================================================================= 249// Sizing. 250//============================================================================= 251// MARK: ---- Sizing ---- 252 253//----------------------------------------------------------------------------- 254 255void GuiRolloutCtrl::calculateHeights() 256{ 257 S32 barHeight = 20; 258 259 if ( mHasTexture && mProfile && mProfile->mBitmapArrayRects.size() >= NumBitmaps ) 260 { 261 // Store Header Rectangle 262 mHeader.set( 0, 0, getWidth(), mProfile->mBitmapArrayRects[ CollapsedCenter ].extent.y ); 263 264 // Bottom Bar Max 265 barHeight = mProfile->mBitmapArrayRects[ TopLeftHeader ].extent.y; 266 } 267 else 268 { 269 mHeader.set( 0, 0, getWidth(), barHeight ); 270 } 271 272 if ( mHideHeader ) 273 { 274 barHeight = 0; 275 mHeader.extent.y = 0; 276 } 277 278 GuiControl *content = static_cast<GuiControl*>( at(0) ); 279 if ( content != NULL ) 280 mExpanded.set( 0, 0, getWidth(), barHeight + content->getHeight() + ( mMargin.point.y + mMargin.extent.y ) ); 281 else 282 mExpanded.set( 0, 0, getWidth(), barHeight + mDefaultHeight ); 283} 284 285//----------------------------------------------------------------------------- 286 287bool GuiRolloutCtrl::resize( const Point2I &newPosition, const Point2I &newExtent ) 288{ 289 if ( !Parent::resize( newPosition, newExtent ) ) 290 return false; 291 292 // Recalculate Heights and resize ourself appropriately. 293 calculateHeights(); 294 295 GuiControl *content = dynamic_cast<GuiControl*>( at(0) ); 296 297 // Size Content Properly?! 298 if ( mNotifyChildrenResized && content != NULL ) 299 { 300 S32 barHeight = ( mHideHeader ) ? 0 : 20; 301 if( !mHideHeader && mHasTexture && mProfile && mProfile->mBitmapArrayRects.size() >= NumBitmaps ) 302 { 303 barHeight = mProfile->mBitmapArrayRects[ TopLeftHeader ].extent.y; 304 } 305 306 mChildRect.set( mMargin.point.x, 307 mHeader.extent.y + mMargin.point.y, 308 getWidth() - ( mMargin.point.x + mMargin.extent.x ), 309 getHeight() - ( barHeight + ( mMargin.point.y + mMargin.extent.y ) ) ); 310 311 if ( content->resize( mChildRect.point, mChildRect.extent ) ) 312 return true; 313 } 314 315 // Nothing sized 316 return false; 317} 318 319//----------------------------------------------------------------------------- 320 321void GuiRolloutCtrl::sizeToContents() 322{ 323 calculateHeights(); 324 325 // Set destination height 326 if ( size() > 0 ) 327 instantExpand(); 328 else 329 instantCollapse(); 330} 331 332//----------------------------------------------------------------------------- 333 334void GuiRolloutCtrl::instantExpand() 335{ 336 mAnimateDestHeight = mExpanded.extent.y; 337 mCollapsing = false; 338 mIsExpanded = true; 339 mIsAnimating = false; 340 resize( getPosition() + mExpanded.point, mExpanded.extent ); 341 342 onExpanded_callback(); 343} 344 345//----------------------------------------------------------------------------- 346 347void GuiRolloutCtrl::instantCollapse() 348{ 349 mAnimateDestHeight = mHeader.extent.y; 350 mCollapsing = false; 351 mIsExpanded = false; 352 mIsAnimating = false; 353 resize( getPosition() + mHeader.point, mHeader.extent ); 354 355 onCollapsed_callback(); 356} 357 358//----------------------------------------------------------------------------- 359 360void GuiRolloutCtrl::toggleExpanded( bool instant ) 361{ 362 if ( mIsExpanded ) 363 { 364 if ( instant ) 365 instantCollapse(); 366 else 367 collapse(); 368 } 369 else 370 { 371 if ( instant ) 372 instantExpand(); 373 else 374 expand(); 375 } 376} 377 378//----------------------------------------------------------------------------- 379 380void GuiRolloutCtrl::childResized( GuiControl *child ) 381{ 382 Parent::childResized( child ); 383 384 calculateHeights(); 385 386 // While we are animating we are constantly resizing our children 387 // and therefore need to ignore this call to 'instantExpand' which would 388 // halt the animation in some crappy intermediate stage. 389 if ( mIsExpanded && !mIsAnimating ) 390 { 391 mNotifyChildrenResized = false; 392 instantExpand(); 393 mNotifyChildrenResized = true; 394 } 395} 396 397//============================================================================= 398// Animation. 399//============================================================================= 400// MARK: ---- Animation ---- 401 402//----------------------------------------------------------------------------- 403 404void GuiRolloutCtrl::animateTo( S32 height ) 405{ 406 // We do nothing if we're already animating 407 if( mIsAnimating ) 408 return; 409 410 bool collapsing = (bool)( getHeight() > height ); 411 412 // If we're already at the destination height, bail 413 if ( getHeight() >= height && !collapsing ) 414 { 415 mIsExpanded = true; 416 return; 417 } 418 419 // If we're already at the destination height, bail 420 if ( getHeight() <= height && collapsing ) 421 { 422 mIsExpanded = false; 423 return; 424 } 425 426 // Set destination height 427 mAnimateDestHeight = height; 428 429 // Set Animation Mode 430 mCollapsing = collapsing; 431 432 // Set Animation Step (Increment) 433 if ( collapsing ) 434 mAnimateStep = (S32)mFloor( (F32)( getHeight() - height ) / 3.f ); 435 else 436 mAnimateStep = (S32)mFloor( (F32)( height - getHeight() ) / 3.f ); 437 438 // Start our animation 439 mIsAnimating = true; 440} 441 442//----------------------------------------------------------------------------- 443 444void GuiRolloutCtrl::processTick() 445{ 446 // We do nothing here if we're NOT animating 447 if ( !mIsAnimating ) 448 return; 449 450 // Sanity check to fix non collapsing panels. 451 if ( mAnimateStep == 0 ) 452 mAnimateStep = 1; 453 454 S32 newHeight = getHeight(); 455 // We're collapsing ourself down (Hiding our contents) 456 if( mCollapsing ) 457 { 458 if ( newHeight < mAnimateDestHeight ) 459 newHeight = mAnimateDestHeight; 460 else if ( ( newHeight - mAnimateStep ) < mAnimateDestHeight ) 461 newHeight = mAnimateDestHeight; 462 463 if ( newHeight == mAnimateDestHeight ) 464 mIsAnimating = false; 465 else 466 newHeight -= mAnimateStep; 467 468 if( !mIsAnimating ) 469 { 470 mIsExpanded = false; 471 } 472 } 473 else // We're expanding ourself (Showing our contents) 474 { 475 if ( newHeight > mAnimateDestHeight ) 476 newHeight = mAnimateDestHeight; 477 else if ( ( newHeight + mAnimateStep ) > mAnimateDestHeight ) 478 newHeight = mAnimateDestHeight; 479 480 if ( newHeight == mAnimateDestHeight ) 481 mIsAnimating = false; 482 else 483 newHeight += mAnimateStep; 484 485 if ( !mIsAnimating ) 486 mIsExpanded = true; 487 } 488 489 if ( newHeight != getHeight() ) 490 setHeight( newHeight ); 491 492 if ( !mIsAnimating ) 493 { 494 if( mCollapsing ) 495 onCollapsed_callback(); 496 else if( !mCollapsing ) 497 onExpanded_callback(); 498 499 calculateHeights(); 500 } 501 502 GuiControl* parent = getParent(); 503 if ( parent ) 504 { 505 parent->childResized( this ); 506 // if our parent's parent is a scroll control, scrollvisible. 507 GuiScrollCtrl* scroll = dynamic_cast<GuiScrollCtrl*>( parent->getParent() ); 508 if ( scroll ) 509 { 510 scroll->scrollRectVisible( getBounds() ); 511 } 512 } 513} 514 515//============================================================================= 516// Rendering. 517//============================================================================= 518// MARK: ---- Rendering ---- 519 520//----------------------------------------------------------------------------- 521 522void GuiRolloutCtrl::onRender( Point2I offset, const RectI &updateRect ) 523{ 524 if( !mProfile || mProfile->mFont == NULL ) 525 return; 526 527 // Calculate actual world bounds for rendering 528 RectI worldBounds( offset, getExtent() ); 529 530 // if opaque, fill the update rect with the fill color 531 if ( mProfile->mOpaque ) 532 GFX->getDrawUtil()->drawRectFill( worldBounds, mProfile->mFillColor ); 533 534 if ( mProfile->mBitmapArrayRects.size() >= NumBitmaps ) 535 { 536 GFX->getDrawUtil()->clearBitmapModulation(); 537 538 // Draw Rollout From Skin 539 if ( !mIsExpanded && !mIsAnimating ) 540 renderFixedBitmapBordersFilled( worldBounds, 1, mProfile ); 541 else if ( mHideHeader ) 542 renderSizableBitmapBordersFilledIndex( worldBounds, MidPageLeft, mProfile ); 543 else 544 renderSizableBitmapBordersFilledIndex( worldBounds, TopLeftHeader, mProfile ); 545 } 546 547 if ( !(mIsExpanded && mHideHeader ) ) 548 { 549 // Draw Caption ( Vertically Centered ) 550 ColorI currColor; 551 GFX->getDrawUtil()->getBitmapModulation( &currColor ); 552 Point2I textPosition = mHeader.point + offset + mProfile->mTextOffset; 553 GFX->getDrawUtil()->setBitmapModulation( mProfile->mFontColor ); 554 renderJustifiedText( textPosition, mHeader.extent, mCaption ); 555 GFX->getDrawUtil()->setBitmapModulation( currColor ); 556 } 557 558 // If we're collapsed we contain the first child as our content 559 // thus we don't render it when collapsed. but to support modified 560 // rollouts with custom header buttons etc we still render our other 561 // children. -JDD 562 GuiControl *pChild = dynamic_cast<GuiControl*>( at(0) ); 563 if ( pChild ) 564 { 565 if ( !mIsExpanded && !mIsAnimating && pChild->isVisible() ) 566 { 567 pChild->setVisible( false ); 568 } 569 else if ( (mIsExpanded || mIsAnimating) && !pChild->isVisible() ) 570 { 571 pChild->setVisible( true ); 572 } 573 } 574 renderChildControls( offset, updateRect ); 575 576 // Render our border should we have it specified in our profile. 577 renderBorder(worldBounds, mProfile); 578} 579 580//============================================================================= 581// Console Methods. 582//============================================================================= 583// MARK: ---- Console Methods ---- 584 585//----------------------------------------------------------------------------- 586 587DefineEngineMethod( GuiRolloutCtrl, isExpanded, bool, (),, 588 "Determine whether the rollout is currently expanded, i.e. whether the child control is visible.\n\n" 589 "@return True if the rollout is expanded, false if not." ) 590{ 591 return object->isExpanded(); 592} 593 594//----------------------------------------------------------------------------- 595 596DefineEngineMethod( GuiRolloutCtrl, collapse, void, (),, 597 "Collapse the rollout if it is currently expanded. This will make the rollout's child control invisible.\n\n" 598 "@note The rollout will animate to collapsed state. To instantly collapse without animation, use instantCollapse()." ) 599{ 600 object->collapse(); 601} 602 603//----------------------------------------------------------------------------- 604 605DefineEngineMethod( GuiRolloutCtrl, expand, void, (),, 606 "Expand the rollout if it is currently collapsed. This will make the rollout's child control visible.\n\n" 607 "@note The rollout will animate to expanded state. To instantly expand without animation, use instantExpand()." ) 608{ 609 object->expand(); 610} 611 612//----------------------------------------------------------------------------- 613 614DefineEngineMethod( GuiRolloutCtrl, toggleCollapse, void, (),, 615 "Toggle the current collapse state of the rollout. If it is currently expanded, then collapse it. If it " 616 "is currently collapsed, then expand it." ) 617{ 618 if( object->isExpanded() ) 619 object->collapse(); 620 else 621 object->expand(); 622} 623 624//----------------------------------------------------------------------------- 625 626DefineEngineMethod( GuiRolloutCtrl, toggleExpanded, void, ( bool instantly ), ( false ), 627 "Toggle the current expansion state of the rollout If it is currently expanded, then collapse it. If it " 628 "is currently collapsed, then expand it.\n\n" 629 "@param instant If true, the rollout will toggle its state without animation. Otherwise, the rollout will " 630 "smoothly slide into the opposite state." ) 631{ 632 object->toggleExpanded( instantly ); 633} 634 635//----------------------------------------------------------------------------- 636 637DefineEngineMethod( GuiRolloutCtrl, instantCollapse, void, (),, 638 "Instantly collapse the rollout without animation. To smoothly slide the rollout to collapsed state, use collapse()." ) 639{ 640 object->instantCollapse(); 641} 642 643//----------------------------------------------------------------------------- 644 645DefineEngineMethod( GuiRolloutCtrl, instantExpand, void, (),, 646 "Instantly expand the rollout without animation. To smoothly slide the rollout to expanded state, use expand()." ) 647{ 648 object->instantExpand(); 649} 650 651//----------------------------------------------------------------------------- 652 653DefineEngineMethod( GuiRolloutCtrl, sizeToContents, void, (),, 654 "Resize the rollout to exactly fit around its child control. This can be used to manually trigger a recomputation of " 655 "the rollout size." ) 656{ 657 object->sizeToContents(); 658} 659