2012-09-19 15:15:01 +00:00
//-----------------------------------------------------------------------------
// Copyright (c) 2012 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 "platform/platform.h"
# include "platform/typetraits.h"
# include "gui/containers/guiScrollCtrl.h"
# include "console/engineAPI.h"
# include "console/console.h"
# include "gfx/bitmap/gBitmap.h"
# include "gui/core/guiDefaultControlRender.h"
# include "gfx/gfxDevice.h"
# include "gfx/gfxDrawUtil.h"
# include "gui/core/guiCanvas.h"
IMPLEMENT_CONOBJECT ( GuiScrollCtrl ) ;
ConsoleDocClass ( GuiScrollCtrl ,
" @brief A container that allows to view one or more possibly larger controls inside its area by "
" providing horizontal and/or vertical scroll bars. \n \n "
" @ingroup GuiContainers "
) ;
ImplementEnumType ( GuiScrollBarBehavior ,
" Display behavior of a scroll bar. Determines when a scrollbar will be visible. \n \n "
" @ingroup GuiContainers " )
{ GuiScrollCtrl : : ScrollBarAlwaysOn , " alwaysOn " , " Always visible. " } ,
{ GuiScrollCtrl : : ScrollBarAlwaysOff , " alwaysOff " , " Never visible. " } ,
{ GuiScrollCtrl : : ScrollBarDynamic , " dynamic " , " Only visible when actually needed, i.e. when the child control(s) exceed the visible space on the given axis. " } ,
EndImplementEnumType ;
IMPLEMENT_CALLBACK ( GuiScrollCtrl , onScroll , void , ( ) , ( ) ,
" Called each time the child controls are scrolled by some amount. " ) ;
//-----------------------------------------------------------------------------
GuiScrollCtrl : : GuiScrollCtrl ( )
2017-04-11 04:45:02 +00:00
: mBorderThickness ( 1 ) ,
mChildMargin ( 0 , 0 ) ,
2012-09-19 15:15:01 +00:00
mScrollBarThickness ( 16 ) ,
mScrollBarArrowBtnLength ( 16 ) ,
mScrollBarDragTolerance ( 130 ) ,
mStateDepressed ( false ) ,
mHitRegion ( None ) ,
mForceVScrollBar ( ScrollBarAlwaysOn ) ,
2017-04-11 04:45:02 +00:00
mUseConstantHeightThumb ( false ) ,
mWillFirstRespond ( true ) ,
2012-09-19 15:15:01 +00:00
mForceHScrollBar ( ScrollBarAlwaysOn ) ,
mLockHorizScroll ( false ) ,
mLockVertScroll ( false ) ,
mIgnoreChildResized ( false ) ,
mAnimating ( false ) ,
mScrollAnimSpeed ( - 1 ) ,
2014-11-07 15:25:10 +00:00
mChildPos ( 0 , 0 ) ,
2017-04-11 04:45:02 +00:00
mChildExt ( 0 , 0 ) ,
mScrollTargetPos ( - 1 , - 1 ) ,
2020-05-11 20:03:27 +00:00
mBaseThumbSize ( 0 ) ,
mHBarEnabled ( false ) ,
mVBarEnabled ( false ) ,
mHasHScrollBar ( false ) ,
mHasVScrollBar ( false ) ,
mHThumbSize ( 1 ) ,
mHThumbPos ( 0 ) ,
mVThumbSize ( 1 ) ,
mVThumbPos ( 0 ) ,
mThumbMouseDelta ( 0 )
2012-09-19 15:15:01 +00:00
{
2020-05-11 20:03:27 +00:00
mBitmapBounds = NULL ;
2012-09-19 15:15:01 +00:00
mIsContainer = true ;
setExtent ( 200 , 200 ) ;
2020-05-11 20:03:27 +00:00
mLastPreRender = Platform : : getVirtualMilliseconds ( ) ;
mLastUpdated = Platform : : getVirtualMilliseconds ( ) ;
2012-09-19 15:15:01 +00:00
}
//-----------------------------------------------------------------------------
void GuiScrollCtrl : : initPersistFields ( )
{
addGroup ( " Scolling " ) ;
addField ( " willFirstRespond " , TypeBool , Offset ( mWillFirstRespond , GuiScrollCtrl ) ) ;
addField ( " hScrollBar " , TYPEID < ScrollBarBehavior > ( ) , Offset ( mForceHScrollBar , GuiScrollCtrl ) ,
" When to display the horizontal scrollbar. " ) ;
addField ( " vScrollBar " , TYPEID < ScrollBarBehavior > ( ) , Offset ( mForceVScrollBar , GuiScrollCtrl ) ,
" When to display the vertical scrollbar. " ) ;
addField ( " lockHorizScroll " , TypeBool , Offset ( mLockHorizScroll , GuiScrollCtrl ) ,
" Horizontal scrolling not allowed if set. " ) ;
addField ( " lockVertScroll " , TypeBool , Offset ( mLockVertScroll , GuiScrollCtrl ) ,
" Vertical scrolling not allowed if set. " ) ;
addField ( " constantThumbHeight " , TypeBool , Offset ( mUseConstantHeightThumb , GuiScrollCtrl ) ) ;
addField ( " childMargin " , TypePoint2I , Offset ( mChildMargin , GuiScrollCtrl ) ,
" Padding region to put around child contents. " ) ;
addField ( " mouseWheelScrollSpeed " , TypeS32 , Offset ( mScrollAnimSpeed , GuiScrollCtrl ) ,
" Pixels/Tick - if not positive then mousewheel scrolling occurs instantly (like other scrolling). " ) ;
endGroup ( " Scrolling " ) ;
Parent : : initPersistFields ( ) ;
}
//-----------------------------------------------------------------------------
bool GuiScrollCtrl : : resize ( const Point2I & newPos , const Point2I & newExt )
{
if ( ! Parent : : resize ( newPos , newExt ) )
return false ;
computeSizes ( ) ;
return true ;
}
//-----------------------------------------------------------------------------
void GuiScrollCtrl : : childResized ( GuiControl * child )
{
if ( mIgnoreChildResized )
return ;
Parent : : childResized ( child ) ;
computeSizes ( ) ;
}
//-----------------------------------------------------------------------------
bool GuiScrollCtrl : : onWake ( )
{
if ( ! Parent : : onWake ( ) )
return false ;
2021-07-19 06:07:08 +00:00
mTextureObject = mProfile - > getBitmapResource ( ) ;
2012-09-19 15:15:01 +00:00
if ( mTextureObject & & ( mProfile - > constructBitmapArray ( ) > = BmpStates * BmpCount ) )
{
mBitmapBounds = mProfile - > mBitmapArrayRects . address ( ) ;
//init
mBaseThumbSize = mBitmapBounds [ BmpStates * BmpVThumbTopCap ] . extent . y +
mBitmapBounds [ BmpStates * BmpVThumbBottomCap ] . extent . y ;
mScrollBarThickness = mBitmapBounds [ BmpStates * BmpVPage ] . extent . x ;
mScrollBarArrowBtnLength = mBitmapBounds [ BmpStates * BmpUp ] . extent . y ;
computeSizes ( ) ;
}
else
{
Con : : warnf ( " No texture loaded for scroll control named %s with profile %s " , getName ( ) , mProfile - > getName ( ) ) ;
}
return true ;
}
//-----------------------------------------------------------------------------
void GuiScrollCtrl : : onSleep ( )
{
// Reset the mouse tracking state of this control
// when it is put to sleep
mStateDepressed = false ;
mHitRegion = None ;
Parent : : onSleep ( ) ;
mTextureObject = NULL ;
}
//-----------------------------------------------------------------------------
bool GuiScrollCtrl : : calcChildExtents ( )
{
// scroll control should deal well with multiple gui controls
if ( ! size ( ) )
return false ;
// Find size and relative position of the client rectangle.
Point2I maxPos ( TypeTraits < S32 > : : MIN , TypeTraits < S32 > : : MIN ) ;
Point2I minPos ( TypeTraits < S32 > : : MAX , TypeTraits < S32 > : : MAX ) ;
bool haveVisibleChild = false ;
for ( U32 i = 0 ; i < size ( ) ; i + + )
{
GuiControl * ctrl = ( GuiControl * ) at ( i ) ;
if ( ctrl - > isVisible ( ) )
{
haveVisibleChild = true ;
minPos . x = getMin ( ctrl - > getPosition ( ) . x , minPos . x ) ;
minPos . y = getMin ( ctrl - > getPosition ( ) . y , minPos . y ) ;
// This is +1 but the remaining code here all works with extents +1.
Point2I ctrlMax = ctrl - > getPosition ( ) + ctrl - > getExtent ( ) ;
maxPos . x = getMax ( ctrlMax . x , maxPos . x ) ;
maxPos . y = getMax ( ctrlMax . y , maxPos . y ) ;
}
}
if ( ! haveVisibleChild )
return false ;
mChildPos = minPos ;
mChildExt = maxPos - minPos ;
return true ;
}
//-----------------------------------------------------------------------------
void GuiScrollCtrl : : scrollRectVisible ( RectI rect )
{
// rect is passed in virtual client space
if ( rect . extent . x > mContentExt . x )
rect . extent . x = mContentExt . x ;
if ( rect . extent . y > mContentExt . y )
rect . extent . y = mContentExt . y ;
// Determine the points bounding the requested rectangle
Point2I rectUpperLeft = rect . point ;
Point2I rectLowerRight = rect . point + rect . extent ;
// Determine the points bounding the actual visible area...
Point2I visUpperLeft = mChildRelPos ;
Point2I visLowerRight = mChildRelPos + mContentExt ;
Point2I delta ( 0 , 0 ) ;
// We basically try to make sure that first the top left of the given
// rect is visible, and if it is, then that the bottom right is visible.
// Make sure the rectangle is visible along the X axis...
if ( rectUpperLeft . x < visUpperLeft . x )
delta . x = rectUpperLeft . x - visUpperLeft . x ;
else if ( rectLowerRight . x > visLowerRight . x )
delta . x = rectLowerRight . x - visLowerRight . x ;
// Make sure the rectangle is visible along the Y axis...
if ( rectUpperLeft . y < visUpperLeft . y )
delta . y = rectUpperLeft . y - visUpperLeft . y ;
else if ( rectLowerRight . y > visLowerRight . y )
delta . y = rectLowerRight . y - visLowerRight . y ;
// If we had any changes, scroll, otherwise don't.
if ( delta . x | | delta . y )
scrollDelta ( delta . x , delta . y ) ;
}
//-----------------------------------------------------------------------------
bool GuiScrollCtrl : : isPointVisible ( const Point2I & point )
{
return ( point . x > = mChildRelPos . x & & point . x < = ( mChildRelPos . x + mContentExt . x ) )
& & ( point . y > = mChildRelPos . y & & point . y < = ( mChildRelPos . y + mContentExt . y ) ) ;
}
//-----------------------------------------------------------------------------
bool GuiScrollCtrl : : isRectCompletelyVisible ( const RectI & rect )
{
// rect is passed in virtual client space
// Determine the points bounding the requested rectangle
Point2I rectUpperLeft = rect . point ;
Point2I rectLowerRight = rect . point + rect . extent ;
// Determine the points bounding the actual visible area...
Point2I visUpperLeft = mChildRelPos ;
Point2I visLowerRight = mChildRelPos + mContentExt ;
// Make sure the rectangle is visible along the X axis...
if ( rectUpperLeft . x < visUpperLeft . x )
return false ;
else if ( rectLowerRight . x > visLowerRight . x )
return false ;
// Make sure the rectangle is visible along the Y axis...
if ( rectUpperLeft . y < visUpperLeft . y )
return false ;
else if ( rectLowerRight . y > visLowerRight . y )
return false ;
return true ;
}
//-----------------------------------------------------------------------------
void GuiScrollCtrl : : addObject ( SimObject * object )
{
Parent : : addObject ( object ) ;
computeSizes ( ) ;
}
//-----------------------------------------------------------------------------
GuiControl * GuiScrollCtrl : : findHitControl ( const Point2I & pt , S32 initialLayer )
{
if ( pt . x < mProfile - > mBorderThickness | | pt . y < mProfile - > mBorderThickness )
return this ;
if ( pt . x > = getWidth ( ) - mProfile - > mBorderThickness - ( mHasVScrollBar ? mScrollBarThickness : 0 ) | |
pt . y > = getHeight ( ) - mProfile - > mBorderThickness - ( mHasHScrollBar ? mScrollBarThickness : 0 ) )
return this ;
return Parent : : findHitControl ( pt , initialLayer ) ;
}
//-----------------------------------------------------------------------------
void GuiScrollCtrl : : computeSizes ( )
{
S32 thickness = ( mProfile ? mProfile - > mBorderThickness : 1 ) ;
Point2I borderExtent ( thickness , thickness ) ;
mContentPos = borderExtent + mChildMargin ;
mContentExt = getExtent ( ) - ( mChildMargin * 2 )
- ( borderExtent * 2 ) ;
Point2I childLowerRight ;
mHBarEnabled = false ;
mVBarEnabled = false ;
mHasVScrollBar = ( mForceVScrollBar = = ScrollBarAlwaysOn ) ;
mHasHScrollBar = ( mForceHScrollBar = = ScrollBarAlwaysOn ) ;
setUpdate ( ) ;
if ( calcChildExtents ( ) )
{
childLowerRight = mChildPos + mChildExt ;
if ( mHasVScrollBar )
mContentExt . x - = mScrollBarThickness ;
if ( mHasHScrollBar )
mContentExt . y - = mScrollBarThickness ;
if ( mChildExt . x > mContentExt . x & & ( mForceHScrollBar = = ScrollBarDynamic ) )
{
mHasHScrollBar = true ;
mContentExt . y - = mScrollBarThickness ;
}
if ( mChildExt . y > mContentExt . y & & ( mForceVScrollBar = = ScrollBarDynamic ) )
{
mHasVScrollBar = true ;
mContentExt . x - = mScrollBarThickness ;
// If Extent X Changed, check Horiz Scrollbar.
if ( mChildExt . x > mContentExt . x & & ! mHasHScrollBar & & ( mForceHScrollBar = = ScrollBarDynamic ) )
{
mHasHScrollBar = true ;
mContentExt . y - = mScrollBarThickness ;
}
}
Point2I contentLowerRight = mContentPos + mContentExt ;
// see if the child controls need to be repositioned (null space in control)
Point2I delta ( 0 , 0 ) ;
if ( mChildPos . x > mContentPos . x )
delta . x = mContentPos . x - mChildPos . x ;
else if ( contentLowerRight . x > childLowerRight . x )
{
S32 diff = contentLowerRight . x - childLowerRight . x ;
delta . x = getMin ( mContentPos . x - mChildPos . x , diff ) ;
}
//reposition the children if the child extent > the scroll content extent
if ( mChildPos . y > mContentPos . y )
delta . y = mContentPos . y - mChildPos . y ;
else if ( contentLowerRight . y > childLowerRight . y )
{
S32 diff = contentLowerRight . y - childLowerRight . y ;
delta . y = getMin ( mContentPos . y - mChildPos . y , diff ) ;
}
// apply the deltas to the children...
if ( delta . x | | delta . y )
{
SimGroup : : iterator i ;
for ( i = begin ( ) ; i ! = end ( ) ; i + + )
{
GuiControl * ctrl = ( GuiControl * ) ( * i ) ;
ctrl - > setPosition ( ctrl - > getPosition ( ) + delta ) ;
}
mChildPos + = delta ;
childLowerRight + = delta ;
}
// enable needed scroll bars
if ( mChildExt . x > mContentExt . x )
mHBarEnabled = true ;
if ( mChildExt . y > mContentExt . y )
mVBarEnabled = true ;
mChildRelPos = mContentPos - mChildPos ;
}
// Prevent resizing our children from recalling this function!
mIgnoreChildResized = true ;
if ( mLockVertScroll )
{
// If vertical scroll is locked we size our child's height to our own
SimGroup : : iterator i ;
for ( i = begin ( ) ; i ! = end ( ) ; i + + )
{
GuiControl * ctrl = ( GuiControl * ) ( * i ) ;
ctrl - > setHeight ( mContentExt . y ) ;
}
}
if ( mLockHorizScroll )
{
// If horizontal scroll is locked we size our child's width to our own
SimGroup : : iterator i ;
for ( i = begin ( ) ; i ! = end ( ) ; i + + )
{
GuiControl * ctrl = ( GuiControl * ) ( * i ) ;
ctrl - > setWidth ( mContentExt . x ) ;
}
}
mIgnoreChildResized = false ;
// build all the rectangles and such...
calcScrollRects ( ) ;
calcThumbs ( ) ;
}
//-----------------------------------------------------------------------------
void GuiScrollCtrl : : calcScrollRects ( void )
{
S32 thickness = ( mProfile ? mProfile - > mBorderThickness : 1 ) ;
if ( mHasHScrollBar )
{
mLeftArrowRect . set ( thickness ,
getHeight ( ) - thickness - mScrollBarThickness ,
mScrollBarArrowBtnLength ,
mScrollBarThickness ) ;
mRightArrowRect . set ( getWidth ( ) - thickness - ( mHasVScrollBar ? mScrollBarThickness - 1 : 0 ) - mScrollBarArrowBtnLength ,
getHeight ( ) - thickness - mScrollBarThickness ,
mScrollBarArrowBtnLength ,
mScrollBarThickness ) ;
mHTrackRect . set ( mLeftArrowRect . point . x + mLeftArrowRect . extent . x ,
mLeftArrowRect . point . y ,
mRightArrowRect . point . x - ( mLeftArrowRect . point . x + mLeftArrowRect . extent . x ) ,
mScrollBarThickness ) ;
}
if ( mHasVScrollBar )
{
mUpArrowRect . set ( getWidth ( ) - thickness - mScrollBarThickness ,
thickness ,
mScrollBarThickness ,
mScrollBarArrowBtnLength ) ;
mDownArrowRect . set ( getWidth ( ) - thickness - mScrollBarThickness ,
getHeight ( ) - thickness - ( mHasHScrollBar ? mScrollBarThickness - 1 : 0 ) - mScrollBarArrowBtnLength ,
mScrollBarThickness ,
mScrollBarArrowBtnLength ) ;
mVTrackRect . set ( mUpArrowRect . point . x ,
mUpArrowRect . point . y + mUpArrowRect . extent . y ,
mScrollBarThickness ,
mDownArrowRect . point . y - ( mUpArrowRect . point . y + mUpArrowRect . extent . y ) ) ;
}
}
//-----------------------------------------------------------------------------
void GuiScrollCtrl : : calcThumbs ( )
{
if ( mHBarEnabled & & mChildExt . x > 0 )
{
U32 trackSize = mHTrackRect . len_x ( ) ;
if ( mUseConstantHeightThumb )
mHThumbSize = mBaseThumbSize ;
else
mHThumbSize = getMax ( mBaseThumbSize , ( S32 ) mCeil ( ( F32 ) ( mContentExt . x * trackSize ) / ( F32 ) mChildExt . x ) ) ;
mHThumbPos = mHTrackRect . point . x + ( mChildRelPos . x * ( trackSize - mHThumbSize ) ) / ( mChildExt . x - mContentExt . x ) ;
}
if ( mVBarEnabled & & mChildExt . y > 0 )
{
U32 trackSize = mVTrackRect . len_y ( ) ;
if ( mUseConstantHeightThumb )
mVThumbSize = mBaseThumbSize ;
else
mVThumbSize = getMax ( mBaseThumbSize , ( S32 ) mCeil ( ( F32 ) ( mContentExt . y * trackSize ) / ( F32 ) mChildExt . y ) ) ;
mVThumbPos = mVTrackRect . point . y + ( mChildRelPos . y * ( trackSize - mVThumbSize ) ) / ( mChildExt . y - mContentExt . y ) ;
}
}
//-----------------------------------------------------------------------------
void GuiScrollCtrl : : scrollDelta ( S32 deltaX , S32 deltaY )
{
scrollTo ( mChildRelPos . x + deltaX , mChildRelPos . y + deltaY ) ;
2015-01-29 23:52:10 +00:00
onScroll_callback ( ) ;
2012-09-19 15:15:01 +00:00
}
//-----------------------------------------------------------------------------
void GuiScrollCtrl : : scrollDeltaAnimate ( S32 x , S32 y )
{
if ( ! size ( ) )
return ;
if ( mAnimating )
mScrollTargetPos + = Point2I ( x , y ) ;
else
mScrollTargetPos = mChildRelPos + Point2I ( x , y ) ;
setUpdate ( ) ;
mScrollTargetPos . setMin ( mChildExt - mContentExt ) ;
mScrollTargetPos . setMax ( Point2I : : Zero ) ;
mAnimating = true ;
}
//-----------------------------------------------------------------------------
void GuiScrollCtrl : : scrollTo ( S32 x , S32 y )
{
if ( ! size ( ) )
return ;
if ( x = = mChildRelPos . x & & y = = mChildRelPos . y )
return ;
setUpdate ( ) ;
if ( x > mChildExt . x - mContentExt . x )
x = mChildExt . x - mContentExt . x ;
if ( x < 0 )
x = 0 ;
if ( y > mChildExt . y - mContentExt . y )
y = mChildExt . y - mContentExt . y ;
if ( y < 0 )
y = 0 ;
Point2I delta ( x - mChildRelPos . x , y - mChildRelPos . y ) ;
mChildRelPos + = delta ;
mChildPos - = delta ;
for ( SimSet : : iterator i = begin ( ) ; i ! = end ( ) ; i + + )
{
GuiControl * ctrl = ( GuiControl * ) ( * i ) ;
ctrl - > setPosition ( ctrl - > getPosition ( ) - delta ) ;
}
calcThumbs ( ) ;
onScroll_callback ( ) ;
}
//-----------------------------------------------------------------------------
void GuiScrollCtrl : : scrollToObject ( GuiControl * targetControl )
{
bool isValidChild = false ;
Point2I relativePosition = targetControl - > getPosition ( ) ;
GuiControl * parentControl = targetControl - > getParent ( ) ;
while ( parentControl )
{
GuiScrollCtrl * scrollControl = dynamic_cast < GuiScrollCtrl * > ( parentControl ) ;
if ( scrollControl = = this )
{
relativePosition + = scrollControl - > getChildRelPos ( ) ;
isValidChild = true ;
break ;
}
relativePosition + = parentControl - > getPosition ( ) ;
parentControl = parentControl - > getParent ( ) ;
}
if ( isValidChild )
{
scrollRectVisible ( RectI ( relativePosition , targetControl - > getExtent ( ) ) ) ;
}
else
{
Con : : errorf ( " GuiScrollCtrl::scrollToObject() - Specified object is not a child of this scroll control (%d)! " , targetControl - > getId ( ) ) ;
}
}
//-----------------------------------------------------------------------------
GuiScrollCtrl : : Region GuiScrollCtrl : : findHitRegion ( const Point2I & pt )
{
if ( mVBarEnabled & & mHasVScrollBar )
{
if ( mUpArrowRect . pointInRect ( pt ) )
return UpArrow ;
else if ( mDownArrowRect . pointInRect ( pt ) )
return DownArrow ;
else if ( mVTrackRect . pointInRect ( pt ) )
{
if ( pt . y < mVThumbPos )
return UpPage ;
else if ( pt . y < mVThumbPos + mVThumbSize )
return VertThumb ;
else
return DownPage ;
}
}
if ( mHBarEnabled & & mHasHScrollBar )
{
if ( mLeftArrowRect . pointInRect ( pt ) )
return LeftArrow ;
else if ( mRightArrowRect . pointInRect ( pt ) )
return RightArrow ;
else if ( mHTrackRect . pointInRect ( pt ) )
{
if ( pt . x < mHThumbPos )
return LeftPage ;
else if ( pt . x < mHThumbPos + mHThumbSize )
return HorizThumb ;
else
return RightPage ;
}
}
return None ;
}
//-----------------------------------------------------------------------------
bool GuiScrollCtrl : : wantsTabListMembership ( )
{
return true ;
}
//-----------------------------------------------------------------------------
bool GuiScrollCtrl : : loseFirstResponder ( )
{
setUpdate ( ) ;
return true ;
}
//-----------------------------------------------------------------------------
bool GuiScrollCtrl : : becomeFirstResponder ( )
{
setUpdate ( ) ;
return mWillFirstRespond ;
}
//-----------------------------------------------------------------------------
bool GuiScrollCtrl : : onKeyDown ( const GuiEvent & event )
{
if ( mWillFirstRespond )
{
switch ( event . keyCode )
{
case KEY_RIGHT :
scrollByRegion ( RightArrow ) ;
return true ;
case KEY_LEFT :
scrollByRegion ( LeftArrow ) ;
return true ;
case KEY_DOWN :
scrollByRegion ( DownArrow ) ;
return true ;
case KEY_UP :
scrollByRegion ( UpArrow ) ;
return true ;
case KEY_PAGE_UP :
scrollByRegion ( UpPage ) ;
return true ;
case KEY_PAGE_DOWN :
scrollByRegion ( DownPage ) ;
return true ;
default :
break ;
}
}
return Parent : : onKeyDown ( event ) ;
}
//-----------------------------------------------------------------------------
void GuiScrollCtrl : : _onMouseDown ( const GuiEvent & event , bool lockMouse )
{
if ( lockMouse )
{
mouseLock ( ) ;
mStateDepressed = true ;
}
setUpdate ( ) ;
Point2I curMousePos = globalToLocalCoord ( event . mousePoint ) ;
mHitRegion = findHitRegion ( curMousePos ) ;
// Set a 0.5 second delay before we start scrolling
mLastUpdated = Platform : : getVirtualMilliseconds ( ) + 500 ;
scrollByRegion ( mHitRegion ) ;
if ( mHitRegion = = VertThumb )
{
mChildRelPosAnchor = mChildRelPos ;
mThumbMouseDelta = curMousePos . y - mVThumbPos ;
}
else if ( mHitRegion = = HorizThumb )
{
mChildRelPosAnchor = mChildRelPos ;
mThumbMouseDelta = curMousePos . x - mHThumbPos ;
}
}
//-----------------------------------------------------------------------------
void GuiScrollCtrl : : onMouseDown ( const GuiEvent & event )
{
_onMouseDown ( event , true ) ;
}
//-----------------------------------------------------------------------------
bool GuiScrollCtrl : : onMouseDownEditor ( const GuiEvent & event , Point2I offset )
{
// If ALT is pressed while clicking on a horizontal or vertical scrollbar,
// do a scroll.
if ( event . modifier & SI_PRIMARY_ALT )
{
Region hitRegion = findHitRegion ( globalToLocalCoord ( event . mousePoint ) ) ;
if ( hitRegion ! = None )
{
_onMouseDown ( event , false ) ;
return true ;
}
}
return false ;
}
//-----------------------------------------------------------------------------
void GuiScrollCtrl : : onMouseUp ( const GuiEvent & )
{
mouseUnlock ( ) ;
setUpdate ( ) ;
mHitRegion = None ;
mStateDepressed = false ;
}
//-----------------------------------------------------------------------------
void GuiScrollCtrl : : onMouseDragged ( const GuiEvent & event )
{
Point2I curMousePos = globalToLocalCoord ( event . mousePoint ) ;
setUpdate ( ) ;
if ( ( mHitRegion ! = VertThumb ) & & ( mHitRegion ! = HorizThumb ) )
{
Region hit = findHitRegion ( curMousePos ) ;
if ( hit ! = mHitRegion )
mStateDepressed = false ;
else
mStateDepressed = true ;
return ;
}
// ok... if the mouse is 'near' the scroll bar, scroll with it
// otherwise, snap back to the previous position.
if ( mHitRegion = = VertThumb )
{
if ( curMousePos . x > = mVTrackRect . point . x - mScrollBarDragTolerance & &
curMousePos . x < = mVTrackRect . point . x + mVTrackRect . extent . x - 1 + mScrollBarDragTolerance & &
curMousePos . y > = mVTrackRect . point . y - mScrollBarDragTolerance & &
curMousePos . y < = mVTrackRect . point . y + mVTrackRect . extent . y - 1 + mScrollBarDragTolerance )
{
S32 newVThumbPos = curMousePos . y - mThumbMouseDelta ;
if ( newVThumbPos ! = mVThumbPos )
{
S32 newVPos = ( newVThumbPos - mVTrackRect . point . y ) *
( mChildExt . y - mContentExt . y ) /
( mVTrackRect . extent . y - mVThumbSize ) ;
scrollTo ( mChildRelPosAnchor . x , newVPos ) ;
}
}
else
scrollTo ( mChildRelPosAnchor . x , mChildRelPosAnchor . y ) ;
}
else if ( mHitRegion = = HorizThumb )
{
if ( curMousePos . x > = mHTrackRect . point . x - mScrollBarDragTolerance & &
curMousePos . x < = mHTrackRect . point . x + mHTrackRect . extent . x - 1 + mScrollBarDragTolerance & &
curMousePos . y > = mHTrackRect . point . y - mScrollBarDragTolerance & &
curMousePos . y < = mHTrackRect . point . y + mHTrackRect . extent . y - 1 + mScrollBarDragTolerance )
{
S32 newHThumbPos = curMousePos . x - mThumbMouseDelta ;
if ( newHThumbPos ! = mHThumbPos )
{
S32 newHPos = ( newHThumbPos - mHTrackRect . point . x ) *
( mChildExt . x - mContentExt . x ) /
( mHTrackRect . extent . x - mHThumbSize ) ;
scrollTo ( newHPos , mChildRelPosAnchor . y ) ;
}
}
else
scrollTo ( mChildRelPosAnchor . x , mChildRelPosAnchor . y ) ;
}
}
//-----------------------------------------------------------------------------
bool GuiScrollCtrl : : onMouseWheelUp ( const GuiEvent & event )
{
if ( ! mAwake | | ! mVisible )
return false ;
scrollByMouseWheel ( event ) ;
return true ;
}
//-----------------------------------------------------------------------------
bool GuiScrollCtrl : : onMouseWheelDown ( const GuiEvent & event )
{
if ( ! mAwake | | ! mVisible )
return false ;
scrollByMouseWheel ( event ) ;
return true ;
}
//-----------------------------------------------------------------------------
void GuiScrollCtrl : : updateChildMousePos ( )
{
// We pass a fake GuiEvent to child controls onMouseMove
// since although the mouse has not moved 'they' have.
//
// Its possible this could cause problems if a GuiControl
// responds to more than just the mouse position in the onMouseMove
// event, like for example doing something different depending on
// a modifier key, which we aren't filling in to the structure!
GuiEvent event ;
event . mousePoint = getRoot ( ) - > getCursorPos ( ) ;
iterator itr ;
for ( itr = begin ( ) ; itr ! = end ( ) ; itr + + )
{
GuiControl * child = static_cast < GuiControl * > ( * itr ) ;
child - > onMouseMove ( event ) ;
}
}
//-----------------------------------------------------------------------------
void GuiScrollCtrl : : onPreRender ( )
{
Parent : : onPreRender ( ) ;
S32 currentTime = Platform : : getVirtualMilliseconds ( ) ;
S32 deltaMs = currentTime - mLastPreRender ;
mLastPreRender = currentTime ;
// Update mouse-wheel scroll animation if we are currently doing one...
if ( mAnimating )
{
//U32 frames = Con::getIntVariable( "$frames", 0 );
//frames++;
//Con::setIntVariable( "$frames", frames );
F32 deltaTicks = deltaMs / 32.0f ;
if ( mScrollAnimSpeed < = 0 )
{
scrollTo ( mScrollTargetPos . x , mScrollTargetPos . y ) ;
}
else
{
S32 maxPixels = deltaTicks * mScrollAnimSpeed ;
Point2I toTarget = mScrollTargetPos - mChildRelPos ;
S32 signx = toTarget . x > 0 ? 1 : - 1 ;
S32 signy = toTarget . y > 0 ? 1 : - 1 ;
S32 deltaX = getMin ( mAbs ( toTarget . x ) , maxPixels ) * signx ;
S32 deltaY = getMin ( mAbs ( toTarget . y ) , maxPixels ) * signy ;
scrollDelta ( deltaX , deltaY ) ;
}
if ( mChildRelPos = = mScrollTargetPos )
{
//Con::printf( "Animated Frames : %d", frames );
//Con::setIntVariable( "$frames", 0 );
mAnimating = false ;
}
updateChildMousePos ( ) ;
}
// Now scroll in response to a 'depressed state' if appropriate...
// Short circuit if not depressed to save cycles
if ( mStateDepressed ! = true )
return ;
//default to one second, though it shouldn't be necessary
U32 timeThreshold = 1000 ;
// We don't want to scroll by pages at an interval the same as when we're scrolling
// using the arrow buttons, so adjust accordingly.
switch ( mHitRegion )
{
case UpPage :
case DownPage :
case LeftPage :
case RightPage :
timeThreshold = 200 ;
break ;
case UpArrow :
case DownArrow :
case LeftArrow :
case RightArrow :
timeThreshold = 20 ;
break ;
default :
// Neither a button or a page, don't scroll (shouldn't get here)
return ;
break ;
} ;
S32 timeElapsed = Platform : : getVirtualMilliseconds ( ) - mLastUpdated ;
if ( ( timeElapsed > 0 ) & & ( timeElapsed > timeThreshold ) )
{
mLastUpdated = Platform : : getVirtualMilliseconds ( ) ;
scrollByRegion ( mHitRegion ) ;
}
}
//-----------------------------------------------------------------------------
void GuiScrollCtrl : : scrollByRegion ( Region reg )
{
setUpdate ( ) ;
if ( ! size ( ) )
return ;
GuiControl * content = ( GuiControl * ) front ( ) ;
U32 rowHeight , columnWidth ;
U32 pageHeight , pageWidth ;
content - > getScrollLineSizes ( & rowHeight , & columnWidth ) ;
if ( rowHeight > = mContentExt . y )
pageHeight = 1 ;
else
pageHeight = mContentExt . y - rowHeight ;
if ( columnWidth > = mContentExt . x )
pageWidth = 1 ;
else
pageWidth = mContentExt . x - columnWidth ;
if ( mVBarEnabled )
{
switch ( reg )
{
case UpPage :
scrollDelta ( 0 , - ( S32 ) pageHeight ) ;
break ;
case DownPage :
scrollDelta ( 0 , pageHeight ) ;
break ;
case UpArrow :
scrollDelta ( 0 , - ( S32 ) rowHeight ) ;
break ;
case DownArrow :
scrollDelta ( 0 , rowHeight ) ;
break ;
default :
break ;
}
}
if ( mHBarEnabled )
{
switch ( reg )
{
case LeftPage :
scrollDelta ( - ( S32 ) pageWidth , 0 ) ;
break ;
case RightPage :
scrollDelta ( pageWidth , 0 ) ;
break ;
case LeftArrow :
scrollDelta ( - ( S32 ) columnWidth , 0 ) ;
break ;
case RightArrow :
scrollDelta ( columnWidth , 0 ) ;
break ;
default :
break ;
}
}
}
//-----------------------------------------------------------------------------
void GuiScrollCtrl : : scrollByMouseWheel ( const GuiEvent & event )
{
setUpdate ( ) ;
if ( ! size ( ) )
return ;
if ( event . mouseAxis = = 1 )
scrollDeltaAnimate ( 0 , - event . fval ) ;
else
scrollDeltaAnimate ( - event . fval , 0 ) ;
}
//-----------------------------------------------------------------------------
void GuiScrollCtrl : : onRender ( Point2I offset , const RectI & updateRect )
{
// draw content controls
// create a rect to intersect with the updateRect
RectI contentRect ( mContentPos . x + offset . x , mContentPos . y + offset . y , mContentExt . x , mContentExt . y ) ;
contentRect . intersect ( updateRect ) ;
// Always call parent
Parent : : onRender ( offset , contentRect ) ;
if ( mTextureObject )
{
// Reset the ClipRect as the parent call can modify it when rendering
// the child controls
GFX - > setClipRect ( updateRect ) ;
//draw the scroll corner
if ( mHasVScrollBar & & mHasHScrollBar )
drawScrollCorner ( offset ) ;
// draw scroll bars
if ( mHasVScrollBar )
drawVScrollBar ( offset ) ;
if ( mHasHScrollBar )
drawHScrollBar ( offset ) ;
}
}
//-----------------------------------------------------------------------------
void GuiScrollCtrl : : drawBorder ( const Point2I & offset , bool /*isFirstResponder*/ )
{
}
//-----------------------------------------------------------------------------
void GuiScrollCtrl : : drawVScrollBar ( const Point2I & offset )
{
if ( mTextureObject . isNull ( ) )
{
return ;
}
// Start Point.
Point2I pos = ( offset + mUpArrowRect . point ) ;
// Up Arrow.
S32 upArrowBitmap = ( BmpStates * BmpUp ) ;
if ( ! mVBarEnabled )
{
upArrowBitmap + = BmpDisabled ;
}
else if ( mHitRegion = = UpArrow & & mStateDepressed )
{
upArrowBitmap + = BmpHilite ;
}
// Render Up Arrow.
2015-07-14 03:51:17 +00:00
GFXDrawUtil * drawUtil = GFX - > getDrawUtil ( ) ;
drawUtil - > clearBitmapModulation ( ) ;
drawUtil - > drawBitmapSR ( mTextureObject , pos , mBitmapBounds [ upArrowBitmap ] ) ;
2012-09-19 15:15:01 +00:00
// Update Pos.
pos . y + = mBitmapBounds [ upArrowBitmap ] . extent . y ;
// Track.
S32 trackBitmap = ( BmpStates * BmpVPage ) ;
if ( ! mVBarEnabled )
{
trackBitmap + = BmpDisabled ;
}
else if ( mHitRegion = = DownPage & & mStateDepressed )
{
trackBitmap + = BmpHilite ;
}
// Determine the Track Rect.
RectI trackRect ;
trackRect . point = pos ;
trackRect . extent . x = mBitmapBounds [ trackBitmap ] . extent . x ;
trackRect . extent . y = ( offset . y + mDownArrowRect . point . y ) - pos . y ;
// Render Track?
if ( trackRect . extent . y > 0 )
{
// Render Track.
2015-07-14 03:51:17 +00:00
drawUtil - > clearBitmapModulation ( ) ;
drawUtil - > drawBitmapStretchSR ( mTextureObject , trackRect , mBitmapBounds [ trackBitmap ] ) ;
2012-09-19 15:15:01 +00:00
}
// Update Pos.
pos . y + = trackRect . extent . y ;
// Down Arrow.
S32 downArrowBitmap = ( BmpStates * BmpDown ) ;
if ( ! mVBarEnabled )
{
downArrowBitmap + = BmpDisabled ;
}
else if ( mHitRegion = = DownArrow & & mStateDepressed )
{
downArrowBitmap + = BmpHilite ;
}
// Render Down Arrow.
2015-07-14 03:51:17 +00:00
drawUtil - > clearBitmapModulation ( ) ;
drawUtil - > drawBitmapSR ( mTextureObject , pos , mBitmapBounds [ downArrowBitmap ] ) ;
2012-09-19 15:15:01 +00:00
// Render the Thumb?
if ( ! mVBarEnabled )
{
// Nope.
return ;
}
// Reset the Pos.
pos . y = ( offset . y + mVThumbPos ) ;
// Determine the Bitmaps.
S32 thumbBitmapTop = ( BmpStates * BmpVThumbTopCap ) ;
S32 thumbBitmapMiddle = ( BmpStates * BmpVThumb ) ;
S32 thumbBitmapBottom = ( BmpStates * BmpVThumbBottomCap ) ;
if ( mHitRegion = = VertThumb & & mStateDepressed )
{
thumbBitmapTop + = BmpHilite ;
thumbBitmapMiddle + = BmpHilite ;
thumbBitmapBottom + = BmpHilite ;
}
// Render Thumb Top.
2015-07-14 03:51:17 +00:00
drawUtil - > clearBitmapModulation ( ) ;
drawUtil - > drawBitmapSR ( mTextureObject , pos , mBitmapBounds [ thumbBitmapTop ] ) ;
2012-09-19 15:15:01 +00:00
// Update Pos.
pos . y + = mBitmapBounds [ thumbBitmapTop ] . extent . y ;
// Determine the Thumb Rect.
RectI thumbRect ;
thumbRect . point = pos ;
thumbRect . extent . x = mBitmapBounds [ thumbBitmapMiddle ] . extent . x ;
thumbRect . extent . y = mVThumbSize - ( mBitmapBounds [ thumbBitmapTop ] . extent . y + mBitmapBounds [ thumbBitmapBottom ] . extent . y ) ;
// Render Thumb?
if ( thumbRect . extent . y > 0 )
{
// Render Track.
2015-07-14 03:51:17 +00:00
drawUtil - > clearBitmapModulation ( ) ;
drawUtil - > drawBitmapStretchSR ( mTextureObject , thumbRect , mBitmapBounds [ thumbBitmapMiddle ] ) ;
2012-09-19 15:15:01 +00:00
}
// Update Pos.
pos . y + = thumbRect . extent . y ;
// Render the Thumb Bottom.
2015-07-14 03:51:17 +00:00
drawUtil - > clearBitmapModulation ( ) ;
drawUtil - > drawBitmapSR ( mTextureObject , pos , mBitmapBounds [ thumbBitmapBottom ] ) ;
2012-09-19 15:15:01 +00:00
}
//-----------------------------------------------------------------------------
void GuiScrollCtrl : : drawHScrollBar ( const Point2I & offset )
{
if ( mTextureObject . isNull ( ) )
{
return ;
}
// Start Point.
Point2I pos = ( offset + mLeftArrowRect . point ) ;
// Left Arrow.
S32 leftArrowBitmap = ( BmpStates * BmpLeft ) ;
if ( ! mHBarEnabled )
{
leftArrowBitmap + = BmpDisabled ;
}
else if ( mHitRegion = = LeftArrow & & mStateDepressed )
{
leftArrowBitmap + = BmpHilite ;
}
// Render Up Arrow.
2015-07-14 03:51:17 +00:00
GFXDrawUtil * drawUtil = GFX - > getDrawUtil ( ) ;
drawUtil - > clearBitmapModulation ( ) ;
drawUtil - > drawBitmapSR ( mTextureObject , pos , mBitmapBounds [ leftArrowBitmap ] ) ;
2012-09-19 15:15:01 +00:00
// Update Pos.
pos . x + = mBitmapBounds [ leftArrowBitmap ] . extent . x ;
// Track.
S32 trackBitmap = ( BmpStates * BmpHPage ) ;
if ( ! mHBarEnabled )
{
trackBitmap + = BmpDisabled ;
}
else if ( mHitRegion = = LeftPage & & mStateDepressed )
{
trackBitmap + = BmpHilite ;
}
// Determine the Track Rect.
RectI trackRect ;
trackRect . point = pos ;
trackRect . extent . x = ( offset . x + mRightArrowRect . point . x ) - pos . x ;
trackRect . extent . y = mBitmapBounds [ trackBitmap ] . extent . y ;
// Render Track?
if ( trackRect . extent . x > 0 )
{
// Render Track.
2015-07-14 03:51:17 +00:00
drawUtil - > clearBitmapModulation ( ) ;
drawUtil - > drawBitmapStretchSR ( mTextureObject , trackRect , mBitmapBounds [ trackBitmap ] ) ;
2012-09-19 15:15:01 +00:00
}
// Update Pos.
pos . x + = trackRect . extent . x ;
// Right Arrow.
S32 rightArrowBitmap = ( BmpStates * BmpRight ) ;
if ( ! mHBarEnabled )
{
rightArrowBitmap + = BmpDisabled ;
}
else if ( mHitRegion = = RightArrow & & mStateDepressed )
{
rightArrowBitmap + = BmpHilite ;
}
// Render Right Arrow.
2015-07-14 03:51:17 +00:00
drawUtil - > clearBitmapModulation ( ) ;
drawUtil - > drawBitmapSR ( mTextureObject , pos , mBitmapBounds [ rightArrowBitmap ] ) ;
2012-09-19 15:15:01 +00:00
// Render the Thumb?
if ( ! mHBarEnabled )
{
// Nope.
return ;
}
// Reset the Pos.
pos . x = ( offset . x + mHThumbPos ) ;
// Determine the Bitmaps.
S32 thumbBitmapLeft = ( BmpStates * BmpHThumbLeftCap ) ;
S32 thumbBitmapMiddle = ( BmpStates * BmpHThumb ) ;
S32 thumbBitmapRight = ( BmpStates * BmpHThumbRightCap ) ;
if ( mHitRegion = = HorizThumb & & mStateDepressed )
{
thumbBitmapLeft + = BmpHilite ;
thumbBitmapMiddle + = BmpHilite ;
thumbBitmapRight + = BmpHilite ;
}
// Render Thumb Left.
2015-07-14 03:51:17 +00:00
drawUtil - > clearBitmapModulation ( ) ;
drawUtil - > drawBitmapSR ( mTextureObject , pos , mBitmapBounds [ thumbBitmapLeft ] ) ;
2012-09-19 15:15:01 +00:00
// Update Pos.
pos . x + = mBitmapBounds [ thumbBitmapLeft ] . extent . x ;
// Determine the Thumb Rect.
RectI thumbRect ;
thumbRect . point = pos ;
thumbRect . extent . x = mHThumbSize - ( mBitmapBounds [ thumbBitmapLeft ] . extent . x + mBitmapBounds [ thumbBitmapRight ] . extent . x ) ;
thumbRect . extent . y = mBitmapBounds [ thumbBitmapMiddle ] . extent . y ;
// Render Thumb?
if ( thumbRect . extent . x > 0 )
{
// Render Track.
2015-07-14 03:51:17 +00:00
drawUtil - > clearBitmapModulation ( ) ;
drawUtil - > drawBitmapStretchSR ( mTextureObject , thumbRect , mBitmapBounds [ thumbBitmapMiddle ] ) ;
2012-09-19 15:15:01 +00:00
}
// Update Pos.
pos . x + = thumbRect . extent . x ;
// Render the Thumb Bottom.
2015-07-14 03:51:17 +00:00
drawUtil - > clearBitmapModulation ( ) ;
drawUtil - > drawBitmapSR ( mTextureObject , pos , mBitmapBounds [ thumbBitmapRight ] ) ;
2012-09-19 15:15:01 +00:00
}
//-----------------------------------------------------------------------------
void GuiScrollCtrl : : drawScrollCorner ( const Point2I & offset )
{
Point2I pos = offset ;
pos . x + = mRightArrowRect . point . x + mRightArrowRect . extent . x - 1 ;
pos . y + = mRightArrowRect . point . y ;
GFX - > getDrawUtil ( ) - > clearBitmapModulation ( ) ;
GFX - > getDrawUtil ( ) - > drawBitmapSR ( mTextureObject , pos , mBitmapBounds [ BmpStates * BmpResize ] ) ;
}
//-----------------------------------------------------------------------------
void GuiScrollCtrl : : autoScroll ( Region reg )
{
scrollByRegion ( reg ) ;
}
//=============================================================================
// API.
//=============================================================================
// MARK: ---- API ----
//-----------------------------------------------------------------------------
DefineEngineMethod ( GuiScrollCtrl , scrollToTop , void , ( ) , ,
" Scroll all the way to the top of the vertical and left of the horizontal scrollbar. " )
{
object - > scrollTo ( 0 , 0 ) ;
}
//-----------------------------------------------------------------------------
DefineEngineMethod ( GuiScrollCtrl , scrollToBottom , void , ( ) , ,
" Scroll all the way to the bottom of the vertical scrollbar and the left of the horizontal bar. " )
{
object - > scrollTo ( 0 , 0x7FFFFFFF ) ;
}
//-----------------------------------------------------------------------------
DefineEngineMethod ( GuiScrollCtrl , setScrollPosition , void , ( S32 x , S32 y ) , ,
" Set the position of the scrolled content. \n \n "
" @param x Position on X axis. \n "
" @param y Position on y axis. \n " )
{
object - > scrollTo ( x , y ) ;
}
//-----------------------------------------------------------------------------
DefineEngineMethod ( GuiScrollCtrl , scrollToObject , void , ( GuiControl * control ) , ,
" Scroll the control so that the given child @a control is visible. \n \n "
" @param control A child control. " )
{
if ( control )
object - > scrollToObject ( control ) ;
}
//-----------------------------------------------------------------------------
DefineEngineMethod ( GuiScrollCtrl , getScrollPosition , Point2I , ( ) , ,
" Get the current coordinates of the scrolled content. \n \n "
" @return The current position of the scrolled content. " )
{
return object - > getChildRelPos ( ) ;
}
//-----------------------------------------------------------------------------
DefineEngineMethod ( GuiScrollCtrl , getScrollPositionX , S32 , ( ) , ,
" Get the current X coordinate of the scrolled content. \n \n "
" @return The current X coordinate of the scrolled content. " )
{
return object - > getChildRelPos ( ) . x ;
}
//-----------------------------------------------------------------------------
DefineEngineMethod ( GuiScrollCtrl , getScrollPositionY , S32 , ( ) , ,
" Get the current Y coordinate of the scrolled content. "
" @return The current Y coordinate of the scrolled content. " )
{
return object - > getChildRelPos ( ) . y ;
}
//-----------------------------------------------------------------------------
DefineEngineMethod ( GuiScrollCtrl , computeSizes , void , ( ) , ,
" Refresh sizing and positioning of child controls. " )
{
object - > computeSizes ( ) ;
}