⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 guiscrollctrl.cc

📁 五行MMORPG引擎系统V1.0
💻 CC
📖 第 1 页 / 共 2 页
字号:
//-----------------------------------------------------------------------------
// Torque Game Engine
// Copyright (C) GarageGames.com, Inc.
//-----------------------------------------------------------------------------

#include "console/consoleTypes.h"
#include "console/console.h"
#include "dgl/gBitmap.h"
#include "dgl/gTexManager.h"
#include "core/resManager.h"
#include "platform/event.h"
#include "dgl/dgl.h"
#include "gui/core/guiArrayCtrl.h"
#include "gui/containers/guiScrollCtrl.h"
#include "gui/core/guiDefaultControlRender.h"

IMPLEMENT_CONOBJECT(GuiScrollCtrl);

// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- //

GuiScrollCtrl::GuiScrollCtrl()
{
   mBounds.extent.set(200,200);
   mChildMargin.set(0,0);
   mBorderThickness = 1;
   mScrollBarThickness = 16;
   mScrollBarArrowBtnLength = 16;
   stateDepressed = false;
   curHitRegion = None;

   mWillFirstRespond = true;
   mUseConstantHeightThumb = false;

   mForceVScrollBar = ScrollBarAlwaysOn;
   mForceHScrollBar = ScrollBarAlwaysOn;
#ifdef TGE_RPG
	m_bVBarAtLeft	  = false;
#endif

}

static EnumTable::Enums scrollBarEnums[] =
{
   { GuiScrollCtrl::ScrollBarAlwaysOn,     "alwaysOn"     },
   { GuiScrollCtrl::ScrollBarAlwaysOff,    "alwaysOff"    },
   { GuiScrollCtrl::ScrollBarDynamic,      "dynamic"      },
};
static EnumTable gScrollBarTable(3, &scrollBarEnums[0]);

ConsoleMethod(GuiScrollCtrl, scrollToTop, void, 2, 2, "() - scrolls the scroll control to the top of the child content area.")
{
   argc; argv;
   object->scrollTo( 0, 0 );
}

ConsoleMethod(GuiScrollCtrl, scrollToBottom, void, 2, 2, "() - scrolls the scroll control to the bottom of the child content area.")
{
   argc; argv;
   object->scrollTo( 0, 0x7FFFFFFF );
}

void GuiScrollCtrl::initPersistFields()
{
   Parent::initPersistFields();

   addField("willFirstRespond",     TypeBool,    Offset(mWillFirstRespond, GuiScrollCtrl));
   addField("hScrollBar",           TypeEnum,    Offset(mForceHScrollBar, GuiScrollCtrl), 1, &gScrollBarTable);
   addField("vScrollBar",           TypeEnum,    Offset(mForceVScrollBar, GuiScrollCtrl), 1, &gScrollBarTable);
   addField("constantThumbHeight",  TypeBool,    Offset(mUseConstantHeightThumb, GuiScrollCtrl));
   addField("childMargin",          TypePoint2I, Offset(mChildMargin, GuiScrollCtrl));
#ifdef TGE_RPG
   addField("vbarAtLeft",			    TypeBool,    Offset(m_bVBarAtLeft, GuiScrollCtrl));
#endif

}

void GuiScrollCtrl::resize(const Point2I &newPos, const Point2I &newExt)
{
   Parent::resize(newPos, newExt);
   computeSizes();
}

void GuiScrollCtrl::childResized(GuiControl *child)
{
   Parent::childResized(child);
   computeSizes();
}

bool GuiScrollCtrl::onWake()
{
   if (! Parent::onWake())
      return false;
	/// TGE_Theme
   //mTextureHandle = mProfile->mTextureHandle;
   //mTextureHandle.setFilterNearest();

   //bool result = mProfile->constructBitmapArray() >= BmpStates * BmpCount;

   //AssertFatal(result, "Failed to create the bitmap array");

   //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();
   return true;
}

void GuiScrollCtrl::onSleep()
{
   Parent::onSleep();
   mTextureHandle = NULL;
}

bool GuiScrollCtrl::calcChildExtents()
{
   // right now the scroll control really only deals well with a single
   // child control for its content
   if (!size())
      return false;

   GuiControl *ctrl = (GuiControl *) front();
   mChildExt = ctrl->mBounds.extent;
   mChildPos = ctrl->mBounds.point;
   return true;
}

RectI lastVisRect;

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;

   lastVisRect = rect;

   // 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);
}


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 >= mBounds.extent.x - mProfile->mBorderThickness - (mHasVScrollBar ? mScrollBarThickness : 0) ||
      pt.y >= mBounds.extent.y - 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 = mBounds.extent - (mChildMargin * 2)
                                - (borderExtent * 2);
#ifdef TGE_RPG
	if(m_bVBarAtLeft)
	//if(mProfile->mAlignment == GuiControlProfile::LeftJustify)
		mContentPos.x += mScrollBarThickness;
#endif

   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;
         // doh! ext.x changed, so check hscrollbar again
         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->mBounds.point += 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;
   }
   // build all the rectangles and such...
   calcScrollRects();
   calcThumbs();
}

void GuiScrollCtrl::calcScrollRects(void)
{
   S32 thickness = ( mProfile ? mProfile->mBorderThickness : 1 );
   if (mHasHScrollBar)
   {
      mLeftArrowRect.set(thickness,
                        mBounds.extent.y - thickness - mScrollBarThickness - 1,
                        mScrollBarArrowBtnLength,
                        mScrollBarThickness);

      mRightArrowRect.set(mBounds.extent.x - thickness - (mHasVScrollBar ? mScrollBarThickness : 0) - mScrollBarArrowBtnLength,
                        mBounds.extent.y - thickness - mScrollBarThickness - 1,
                        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)
   {
#ifdef TGE_RPG
		if(m_bVBarAtLeft)
		//if(mProfile->mAlignment == GuiControlProfile::LeftJustify)
		{
			mUpArrowRect.set( thickness ,
									thickness,
									mScrollBarThickness,
									mScrollBarArrowBtnLength);
			mDownArrowRect.set( thickness,
									mBounds.extent.y - thickness - mScrollBarArrowBtnLength - (mHasHScrollBar ? ( mScrollBarThickness + 1 ) : 0),
									mScrollBarThickness,
									mScrollBarArrowBtnLength);
			mVTrackRect.set(mUpArrowRect.point.x,
									mUpArrowRect.point.y + mUpArrowRect.extent.y,
									mScrollBarThickness,
									mDownArrowRect.point.y - (mUpArrowRect.point.y + mUpArrowRect.extent.y) );
		}
		else
		{
#endif
			mUpArrowRect.set(mBounds.extent.x - thickness - mScrollBarThickness,
									thickness,
									mScrollBarThickness,
									mScrollBarArrowBtnLength);
			mDownArrowRect.set(mBounds.extent.x - thickness - mScrollBarThickness,
									mBounds.extent.y - thickness - mScrollBarArrowBtnLength - (mHasHScrollBar ? ( mScrollBarThickness + 1 ) : 0),
									mScrollBarThickness,
									mScrollBarArrowBtnLength);
			mVTrackRect.set(mUpArrowRect.point.x,
									mUpArrowRect.point.y + mUpArrowRect.extent.y,
									mScrollBarThickness,
									mDownArrowRect.point.y - (mUpArrowRect.point.y + mUpArrowRect.extent.y) );
#ifdef TGE_RPG
		}
#endif
   }
}

void GuiScrollCtrl::calcThumbs()
{
   if (mHBarEnabled)
   {
      U32 trackSize = mHTrackRect.len_x();

      if (mUseConstantHeightThumb)
         mHThumbSize = mBaseThumbSize;
      else
         mHThumbSize = getMax(mBaseThumbSize, S32((mContentExt.x * trackSize) / mChildExt.x));

      mHThumbPos = mHTrackRect.point.x + (mChildRelPos.x * (trackSize - mHThumbSize)) / (mChildExt.x - mContentExt.x);
   }
   if (mVBarEnabled)
   {
      U32 trackSize = mVTrackRect.len_y();

      if (mUseConstantHeightThumb)
         mVThumbSize = mBaseThumbSize;
      else
         mVThumbSize = getMax(mBaseThumbSize, S32((mContentExt.y * trackSize) / 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);
}

void GuiScrollCtrl::scrollTo(S32 x, S32 y)
{
   if(!size())
      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->mBounds.point -= delta;
   }
   calcThumbs();
}

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;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -