BsGUIScrollArea.cpp 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. #include "BsGUIScrollArea.h"
  2. #include "BsGUIElementStyle.h"
  3. #include "BsGUISkin.h"
  4. #include "BsGUIWidget.h"
  5. #include "BsGUILayoutOptions.h"
  6. #include "BsGUILayout.h"
  7. #include "BsGUISkin.h"
  8. #include "BsGUIScrollBarVert.h"
  9. #include "BsGUIScrollBarHorz.h"
  10. #include "CmException.h"
  11. using namespace CamelotFramework;
  12. namespace BansheeEngine
  13. {
  14. const UINT32 GUIScrollArea::ScrollBarWidth = 8;
  15. const UINT32 GUIScrollArea::MinHandleSize = 4;
  16. GUIScrollArea::GUIScrollArea(GUIWidget& parent, const GUIElementStyle* style, const GUILayoutOptions& layoutOptions)
  17. :GUIElement(parent, style, layoutOptions), mVertScroll(nullptr), mHorzScroll(nullptr), mVertOffset(0), mHorzOffset(0),
  18. mContentWidth(0), mContentHeight(0)
  19. {
  20. mContentLayout = &addLayoutYInternal();
  21. }
  22. GUIScrollArea::~GUIScrollArea()
  23. {
  24. }
  25. UINT32 GUIScrollArea::getNumRenderElements() const
  26. {
  27. return 0;
  28. }
  29. const HMaterial& GUIScrollArea::getMaterial(UINT32 renderElementIdx) const
  30. {
  31. CM_EXCEPT(InternalErrorException, "Trying to retrieve a material from an element with no render elements.");
  32. }
  33. UINT32 GUIScrollArea::getNumQuads(UINT32 renderElementIdx) const
  34. {
  35. return 0;
  36. }
  37. void GUIScrollArea::updateRenderElementsInternal()
  38. { }
  39. UINT32 GUIScrollArea::_getOptimalWidth() const
  40. {
  41. return mContentLayout->_getOptimalWidth();
  42. }
  43. UINT32 GUIScrollArea::_getOptimalHeight() const
  44. {
  45. return mContentLayout->_getOptimalHeight();
  46. }
  47. void GUIScrollArea::fillBuffer(UINT8* vertices, UINT8* uv, UINT32* indices, UINT32 startingQuad, UINT32 maxNumQuads,
  48. UINT32 vertexStride, UINT32 indexStride, UINT32 renderElementIdx) const
  49. { }
  50. void GUIScrollArea::_updateLayoutInternal(UINT32 x, UINT32 y, UINT32 width, UINT32 height,
  51. Rect clipRect, UINT8 widgetDepth, UINT16 areaDepth)
  52. {
  53. mContentLayout->_updateLayoutInternal(x, y, width, height, clipRect, widgetDepth, areaDepth);
  54. UINT32 contentWidth = mContentLayout->_getActualWidth();
  55. UINT32 contentHeight = mContentLayout->_getActualHeight();
  56. if(contentHeight > mHeight)
  57. {
  58. // Make room for scrollbar
  59. UINT32 contentWidth = (UINT32)std::max(0, (INT32)width - (INT32)ScrollBarWidth);
  60. Rect layoutClipRect(clipRect.x, clipRect.y, contentWidth, clipRect.height);
  61. mContentLayout->_updateLayoutInternal(x, y - mVertOffset, contentWidth, height, layoutClipRect, widgetDepth, areaDepth);
  62. contentWidth = mContentLayout->_getActualWidth();
  63. contentHeight = mContentLayout->_getActualHeight();
  64. if(mVertScroll == nullptr)
  65. {
  66. mVertScroll = GUIScrollBarVert::create(_getParentWidget());
  67. mVertScroll->scrollPositionChanged.connect(boost::bind(&GUIScrollArea::vertScrollUpdate, this, _1));
  68. }
  69. Int2 offset(x + contentWidth, y);
  70. mVertScroll->_setOffset(offset);
  71. mVertScroll->_setWidth(ScrollBarWidth);
  72. mVertScroll->_setHeight(height);
  73. mVertScroll->_setAreaDepth(areaDepth);
  74. mVertScroll->_setWidgetDepth(widgetDepth);
  75. UINT32 clippedScrollbarWidth = std::min(width, ScrollBarWidth);
  76. Rect elemClipRect(0, 0, clippedScrollbarWidth, clipRect.height);
  77. mVertScroll->_setClipRect(elemClipRect);
  78. // This element is not a child of any layout so we treat it as a root element
  79. Rect scrollBarLayoutClipRect(clipRect.x + contentWidth, clipRect.y, clippedScrollbarWidth, clipRect.height);
  80. mVertScroll->_updateLayout(offset.x, offset.y, ScrollBarWidth, height, scrollBarLayoutClipRect, widgetDepth, areaDepth);
  81. // Set new handle size and update position to match the new size
  82. UINT32 newHandleSize = (UINT32)Math::FloorToInt(mVertScroll->getMaxHandleSize() * (mHeight / (float)contentHeight));
  83. newHandleSize = std::max(newHandleSize, MinHandleSize);
  84. UINT32 scrollableHeight = (UINT32)std::max(0, INT32(contentHeight) - INT32(mHeight));
  85. float newScrollPct = mVertOffset / (float)scrollableHeight;
  86. mVertScroll->setHandleSize(newHandleSize);
  87. mVertScroll->setScrollPos(newScrollPct);
  88. }
  89. else
  90. {
  91. if(mVertScroll != nullptr)
  92. {
  93. GUIElement::destroy(mVertScroll);
  94. mVertScroll = nullptr;
  95. }
  96. }
  97. // TODO - Add horizontal scroll bar
  98. mContentWidth = contentWidth;
  99. mContentHeight = contentHeight;
  100. }
  101. void GUIScrollArea::vertScrollUpdate(float scrollPos)
  102. {
  103. UINT32 scrollableHeight = (UINT32)std::max(0, INT32(mContentHeight) - INT32(mHeight));
  104. mVertOffset = Math::FloorToInt(scrollableHeight * scrollPos);
  105. markContentAsDirty();
  106. }
  107. void GUIScrollArea::horzScrollUpdate(float scrollPos)
  108. {
  109. UINT32 scrollableWidth = (UINT32)std::max(0, INT32(mContentWidth) - INT32(mWidth));
  110. mHorzOffset = Math::FloorToInt(scrollableWidth * scrollPos);
  111. markContentAsDirty();
  112. }
  113. GUIScrollArea* GUIScrollArea::create(GUIWidget& parent, const GUIElementStyle* style)
  114. {
  115. if(style == nullptr)
  116. {
  117. const GUISkin* skin = parent.getSkin();
  118. style = skin->getStyle(getGUITypeName());
  119. }
  120. return new (cm_alloc<GUIScrollArea, PoolAlloc>()) GUIScrollArea(parent, style, getDefaultLayoutOptions(style));
  121. }
  122. GUIScrollArea* GUIScrollArea::create(GUIWidget& parent, const GUILayoutOptions& layoutOptions, const GUIElementStyle* style)
  123. {
  124. if(style == nullptr)
  125. {
  126. const GUISkin* skin = parent.getSkin();
  127. style = skin->getStyle(getGUITypeName());
  128. }
  129. return new (cm_alloc<GUIScrollArea, PoolAlloc>()) GUIScrollArea(parent, style, layoutOptions);
  130. }
  131. const String& GUIScrollArea::getGUITypeName()
  132. {
  133. static String typeName = "ScrollArea";
  134. return typeName;
  135. }
  136. }