BsGUIScrollArea.cpp 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552
  1. #include "BsGUIScrollArea.h"
  2. #include "BsGUIElementStyle.h"
  3. #include "BsGUIDimensions.h"
  4. #include "BsGUILayoutY.h"
  5. #include "BsGUIScrollBarVert.h"
  6. #include "BsGUIScrollBarHorz.h"
  7. #include "BsGUIMouseEvent.h"
  8. #include "BsGUILayoutUtility.h"
  9. using namespace std::placeholders;
  10. namespace BansheeEngine
  11. {
  12. const UINT32 GUIScrollArea::ScrollBarWidth = 16;
  13. const UINT32 GUIScrollArea::MinHandleSize = 4;
  14. const UINT32 GUIScrollArea::WheelScrollAmount = 50;
  15. GUIScrollArea::GUIScrollArea(ScrollBarType vertBarType, ScrollBarType horzBarType,
  16. const String& scrollBarStyle, const String& scrollAreaStyle, const GUIDimensions& dimensions)
  17. :GUIElementContainer(dimensions), mVertScroll(nullptr), mHorzScroll(nullptr), mVertOffset(0), mHorzOffset(0),
  18. mVertBarType(vertBarType), mHorzBarType(horzBarType), mScrollBarStyle(scrollBarStyle), mRecalculateVertOffset(false),
  19. mRecalculateHorzOffset(false)
  20. {
  21. mContentLayout = GUILayoutY::create();
  22. _registerChildElement(mContentLayout);
  23. mHorzScroll = GUIScrollBarHorz::create(mScrollBarStyle);
  24. mVertScroll = GUIScrollBarVert::create(mScrollBarStyle);
  25. _registerChildElement(mHorzScroll);
  26. _registerChildElement(mVertScroll);
  27. mHorzScroll->onScrollPositionChanged.connect(std::bind(&GUIScrollArea::horzScrollUpdate, this, _1));
  28. mVertScroll->onScrollPositionChanged.connect(std::bind(&GUIScrollArea::vertScrollUpdate, this, _1));
  29. }
  30. GUIScrollArea::~GUIScrollArea()
  31. {
  32. }
  33. void GUIScrollArea::updateClippedBounds()
  34. {
  35. mClippedBounds = mLayoutData.area;
  36. mClippedBounds.clip(mLayoutData.clipRect);
  37. }
  38. Vector2I GUIScrollArea::_getOptimalSize() const
  39. {
  40. Vector2I optimalSize = mContentLayout->_getOptimalSize();
  41. // Provide 10x10 in case underlying layout is empty because
  42. // 0 doesn't work well with the layout system
  43. optimalSize.x = std::max(10, optimalSize.x);
  44. optimalSize.y = std::max(10, optimalSize.y);
  45. return optimalSize;
  46. }
  47. LayoutSizeRange GUIScrollArea::_calculateLayoutSizeRange() const
  48. {
  49. // I'm ignoring scroll bars here since if the content layout fits
  50. // then they're not needed and the range is valid. And if it doesn't
  51. // fit the area will get clipped anyway and including the scroll bars
  52. // won't change the size much, but it would complicate this method significantly.
  53. if (mContentLayout->_isActive())
  54. return mDimensions.calculateSizeRange(_getOptimalSize());
  55. return mDimensions.calculateSizeRange(Vector2I());
  56. }
  57. LayoutSizeRange GUIScrollArea::_getLayoutSizeRange() const
  58. {
  59. return mSizeRange;
  60. }
  61. void GUIScrollArea::_updateOptimalLayoutSizes()
  62. {
  63. // Update all children first, otherwise we can't determine our own optimal size
  64. GUIElementBase::_updateOptimalLayoutSizes();
  65. if (mChildren.size() != mChildSizeRanges.size())
  66. mChildSizeRanges.resize(mChildren.size());
  67. UINT32 childIdx = 0;
  68. for (auto& child : mChildren)
  69. {
  70. if (child->_isActive())
  71. mChildSizeRanges[childIdx] = child->_getLayoutSizeRange();
  72. else
  73. mChildSizeRanges[childIdx] = LayoutSizeRange();
  74. childIdx++;
  75. }
  76. mSizeRange = mDimensions.calculateSizeRange(_getOptimalSize());
  77. }
  78. void GUIScrollArea::_getElementAreas(const Rect2I& layoutArea, Rect2I* elementAreas, UINT32 numElements,
  79. const Vector<LayoutSizeRange>& sizeRanges, const LayoutSizeRange& mySizeRange) const
  80. {
  81. Vector2I visibleSize, contentSize;
  82. _getElementAreas(layoutArea, elementAreas, numElements, sizeRanges, visibleSize, contentSize);
  83. }
  84. void GUIScrollArea::_getElementAreas(const Rect2I& layoutArea, Rect2I* elementAreas, UINT32 numElements,
  85. const Vector<LayoutSizeRange>& sizeRanges, Vector2I& visibleSize, Vector2I& contentSize) const
  86. {
  87. assert(mChildren.size() == numElements && numElements == 3);
  88. UINT32 layoutIdx = 0;
  89. UINT32 horzScrollIdx = 0;
  90. UINT32 vertScrollIdx = 0;
  91. UINT32 idx = 0;
  92. for (auto& child : mChildren)
  93. {
  94. if (child == mContentLayout)
  95. layoutIdx = idx;
  96. if (child == mHorzScroll)
  97. horzScrollIdx = idx;
  98. if (child == mVertScroll)
  99. vertScrollIdx = idx;
  100. idx++;
  101. }
  102. // Calculate content layout bounds
  103. //// We want elements to use their optimal height, since scroll area
  104. //// technically provides "infinite" space
  105. UINT32 optimalContentWidth = layoutArea.width;
  106. if (mHorzBarType != ScrollBarType::NeverShow)
  107. optimalContentWidth = sizeRanges[layoutIdx].optimal.x;
  108. UINT32 optimalContentHeight = layoutArea.height;
  109. if (mVertBarType != ScrollBarType::NeverShow)
  110. optimalContentHeight = sizeRanges[layoutIdx].optimal.y;
  111. UINT32 layoutWidth = std::max(optimalContentWidth, (UINT32)layoutArea.width);
  112. UINT32 layoutHeight = std::max(optimalContentHeight, (UINT32)layoutArea.height);
  113. contentSize = GUILayoutUtility::calcActualSize(layoutWidth, layoutHeight, mContentLayout, false);
  114. visibleSize = Vector2I(layoutArea.width, layoutArea.height);
  115. bool addHorzScrollbar = (mHorzBarType == ScrollBarType::ShowIfDoesntFit && contentSize.x > visibleSize.x) ||
  116. mHorzBarType == ScrollBarType::AlwaysShow && mHorzBarType != ScrollBarType::NeverShow;
  117. bool hasHorzScrollbar = false;
  118. bool hasVertScrollbar = false;
  119. if (addHorzScrollbar)
  120. {
  121. // Make room for scrollbar
  122. visibleSize.y = (UINT32)std::max(0, (INT32)layoutArea.height - (INT32)ScrollBarWidth);
  123. optimalContentHeight = (UINT32)std::max(0, (INT32)optimalContentHeight - (INT32)ScrollBarWidth);
  124. if (sizeRanges[layoutIdx].min.y > 0)
  125. optimalContentHeight = std::max((UINT32)sizeRanges[layoutIdx].min.y, optimalContentHeight);
  126. layoutHeight = std::max(optimalContentHeight, (UINT32)visibleSize.y); // Never go below optimal size
  127. contentSize = GUILayoutUtility::calcActualSize(layoutWidth, layoutHeight, mContentLayout, true);
  128. hasHorzScrollbar = true;
  129. }
  130. bool addVertScrollbar = (mVertBarType == ScrollBarType::ShowIfDoesntFit && contentSize.y > visibleSize.y) ||
  131. mVertBarType == ScrollBarType::AlwaysShow && mVertBarType != ScrollBarType::NeverShow;
  132. if (addVertScrollbar)
  133. {
  134. // Make room for scrollbar
  135. visibleSize.x = (UINT32)std::max(0, (INT32)layoutArea.width - (INT32)ScrollBarWidth);
  136. optimalContentWidth = (UINT32)std::max(0, (INT32)optimalContentWidth - (INT32)ScrollBarWidth);
  137. if (sizeRanges[layoutIdx].min.x > 0)
  138. optimalContentWidth = std::max((UINT32)sizeRanges[layoutIdx].min.x, optimalContentWidth);
  139. layoutWidth = std::max(optimalContentWidth, (UINT32)visibleSize.x); // Never go below optimal size
  140. contentSize = GUILayoutUtility::calcActualSize(layoutWidth, layoutHeight, mContentLayout, true);
  141. hasVertScrollbar = true;
  142. if (!hasHorzScrollbar) // Since width has been reduced, we need to check if we require the horizontal scrollbar
  143. {
  144. addHorzScrollbar = (mHorzBarType == ScrollBarType::ShowIfDoesntFit && contentSize.x > visibleSize.x) && mHorzBarType != ScrollBarType::NeverShow;
  145. if (addHorzScrollbar)
  146. {
  147. // Make room for scrollbar
  148. visibleSize.y = (UINT32)std::max(0, (INT32)layoutArea.height - (INT32)ScrollBarWidth);
  149. optimalContentHeight = (UINT32)std::max(0, (INT32)optimalContentHeight - (INT32)ScrollBarWidth);
  150. if (sizeRanges[layoutIdx].min.y > 0)
  151. optimalContentHeight = std::max((UINT32)sizeRanges[layoutIdx].min.y, optimalContentHeight);
  152. layoutHeight = std::max(optimalContentHeight, (UINT32)visibleSize.y); // Never go below optimal size
  153. contentSize = GUILayoutUtility::calcActualSize(layoutWidth, layoutHeight, mContentLayout, true);
  154. hasHorzScrollbar = true;
  155. }
  156. }
  157. }
  158. elementAreas[layoutIdx] = Rect2I(layoutArea.x, layoutArea.y, layoutWidth, layoutHeight);
  159. // Calculate vertical scrollbar bounds
  160. if (hasVertScrollbar)
  161. {
  162. INT32 scrollBarOffset = (UINT32)std::max(0, (INT32)layoutArea.width - (INT32)ScrollBarWidth);
  163. UINT32 scrollBarHeight = layoutArea.height;
  164. if (hasHorzScrollbar)
  165. scrollBarHeight = (UINT32)std::max(0, (INT32)scrollBarHeight - (INT32)ScrollBarWidth);
  166. elementAreas[vertScrollIdx] = Rect2I(layoutArea.x + scrollBarOffset, layoutArea.y, ScrollBarWidth, scrollBarHeight);
  167. }
  168. else
  169. {
  170. elementAreas[vertScrollIdx] = Rect2I(layoutArea.x + layoutWidth, layoutArea.y, 0, 0);
  171. }
  172. // Calculate horizontal scrollbar bounds
  173. if (hasHorzScrollbar)
  174. {
  175. INT32 scrollBarOffset = (UINT32)std::max(0, (INT32)layoutArea.height - (INT32)ScrollBarWidth);
  176. UINT32 scrollBarWidth = layoutArea.width;
  177. if (hasVertScrollbar)
  178. scrollBarWidth = (UINT32)std::max(0, (INT32)scrollBarWidth - (INT32)ScrollBarWidth);
  179. elementAreas[horzScrollIdx] = Rect2I(layoutArea.x, layoutArea.y + scrollBarOffset, scrollBarWidth, ScrollBarWidth);
  180. }
  181. else
  182. {
  183. elementAreas[horzScrollIdx] = Rect2I(layoutArea.x, layoutArea.y + layoutHeight, 0, 0);
  184. }
  185. }
  186. void GUIScrollArea::_updateLayoutInternal(const GUILayoutData& data)
  187. {
  188. UINT32 numElements = (UINT32)mChildren.size();
  189. Rect2I* elementAreas = nullptr;
  190. if (numElements > 0)
  191. elementAreas = bs_stack_new<Rect2I>(numElements);
  192. UINT32 layoutIdx = 0;
  193. UINT32 horzScrollIdx = 0;
  194. UINT32 vertScrollIdx = 0;
  195. for (UINT32 i = 0; i < numElements; i++)
  196. {
  197. GUIElementBase* child = _getChild(i);
  198. if (child == mContentLayout)
  199. layoutIdx = i;
  200. if (child == mHorzScroll)
  201. horzScrollIdx = i;
  202. if (child == mVertScroll)
  203. vertScrollIdx = i;
  204. }
  205. _getElementAreas(data.area, elementAreas, numElements, mChildSizeRanges, mVisibleSize, mContentSize);
  206. Rect2I& layoutBounds = elementAreas[layoutIdx];
  207. Rect2I& horzScrollBounds = elementAreas[horzScrollIdx];
  208. Rect2I& vertScrollBounds = elementAreas[vertScrollIdx];
  209. // Recalculate offsets in case scroll percent got updated externally (this needs to be delayed to this point because
  210. // at the time of the update content and visible sizes might be out of date).
  211. if (mRecalculateVertOffset)
  212. {
  213. UINT32 scrollableHeight = (UINT32)std::max(0, INT32(mContentSize.y) - INT32(vertScrollBounds.height));
  214. mVertOffset = scrollableHeight * Math::clamp01(mVertScroll->getScrollPos());
  215. mRecalculateVertOffset = false;
  216. }
  217. if (mRecalculateHorzOffset)
  218. {
  219. UINT32 scrollableWidth = (UINT32)std::max(0, INT32(mContentSize.x) - INT32(horzScrollBounds.width));
  220. mHorzOffset = scrollableWidth * Math::clamp01(mHorzScroll->getScrollPos());
  221. mRecalculateHorzOffset = false;
  222. }
  223. // Layout
  224. if (mContentLayout->_isActive())
  225. {
  226. layoutBounds.x -= Math::floorToInt(mHorzOffset);
  227. layoutBounds.y -= Math::floorToInt(mVertOffset);
  228. Rect2I layoutClipRect = data.clipRect;
  229. layoutClipRect.width = (UINT32)mVisibleSize.x;
  230. layoutClipRect.height = (UINT32)mVisibleSize.y;
  231. layoutClipRect.clip(data.clipRect);
  232. GUILayoutData layoutData = data;
  233. layoutData.area = layoutBounds;
  234. layoutData.clipRect = layoutClipRect;
  235. mContentLayout->_setLayoutData(layoutData);
  236. mContentLayout->_updateLayoutInternal(layoutData);
  237. }
  238. // Vertical scrollbar
  239. {
  240. GUILayoutData vertScrollData = data;
  241. vertScrollData.area = vertScrollBounds;
  242. vertScrollData.clipRect = vertScrollBounds;
  243. vertScrollData.clipRect.clip(data.clipRect);
  244. mVertScroll->_setLayoutData(vertScrollData);
  245. mVertScroll->_updateLayoutInternal(vertScrollData);
  246. // Set new handle size and update position to match the new size
  247. UINT32 newHandleSize = (UINT32)Math::floorToInt(mVertScroll->getMaxHandleSize() * (vertScrollBounds.height / (float)mContentSize.y));
  248. newHandleSize = std::max(newHandleSize, MinHandleSize);
  249. UINT32 scrollableHeight = (UINT32)std::max(0, INT32(mContentSize.y) - INT32(vertScrollBounds.height));
  250. float newScrollPct = 0.0f;
  251. if (scrollableHeight > 0)
  252. newScrollPct = mVertOffset / scrollableHeight;
  253. mVertScroll->_setHandleSize(newHandleSize);
  254. mVertScroll->_setScrollPos(newScrollPct);
  255. }
  256. // Horizontal scrollbar
  257. {
  258. GUILayoutData horzScrollData = data;
  259. horzScrollData.area = horzScrollBounds;
  260. horzScrollData.clipRect = horzScrollBounds;
  261. horzScrollData.clipRect.clip(data.clipRect);
  262. mHorzScroll->_setLayoutData(horzScrollData);
  263. mHorzScroll->_updateLayoutInternal(horzScrollData);
  264. // Set new handle size and update position to match the new size
  265. UINT32 newHandleSize = (UINT32)Math::floorToInt(mHorzScroll->getMaxHandleSize() * (horzScrollBounds.width / (float)mContentSize.x));
  266. newHandleSize = std::max(newHandleSize, MinHandleSize);
  267. UINT32 scrollableWidth = (UINT32)std::max(0, INT32(mContentSize.x) - INT32(horzScrollBounds.width));
  268. float newScrollPct = 0.0f;
  269. if (scrollableWidth > 0)
  270. newScrollPct = mHorzOffset / scrollableWidth;
  271. mHorzScroll->_setHandleSize(newHandleSize);
  272. mHorzScroll->_setScrollPos(newScrollPct);
  273. }
  274. if (elementAreas != nullptr)
  275. bs_stack_free(elementAreas);
  276. }
  277. void GUIScrollArea::vertScrollUpdate(float scrollPos)
  278. {
  279. UINT32 scrollableHeight = (UINT32)std::max(0, INT32(mContentSize.y) - INT32(mVisibleSize.y));
  280. mVertOffset = scrollableHeight * Math::clamp01(scrollPos);
  281. _markLayoutAsDirty();
  282. }
  283. void GUIScrollArea::horzScrollUpdate(float scrollPos)
  284. {
  285. UINT32 scrollableWidth = (UINT32)std::max(0, INT32(mContentSize.x) - INT32(mVisibleSize.x));
  286. mHorzOffset = scrollableWidth * Math::clamp01(scrollPos);
  287. _markLayoutAsDirty();
  288. }
  289. void GUIScrollArea::scrollToVertical(float pct)
  290. {
  291. mVertScroll->_setScrollPos(pct);
  292. mRecalculateVertOffset = true;
  293. _markLayoutAsDirty();
  294. }
  295. void GUIScrollArea::scrollToHorizontal(float pct)
  296. {
  297. mHorzScroll->_setScrollPos(pct);
  298. mRecalculateHorzOffset = true;
  299. _markLayoutAsDirty();
  300. }
  301. float GUIScrollArea::getVerticalScroll() const
  302. {
  303. if (mVertScroll != nullptr)
  304. return mVertScroll->getScrollPos();
  305. return 0.0f;
  306. }
  307. float GUIScrollArea::getHorizontalScroll() const
  308. {
  309. if (mHorzScroll != nullptr)
  310. return mHorzScroll->getScrollPos();
  311. return 0.0f;
  312. }
  313. Rect2I GUIScrollArea::getContentBounds()
  314. {
  315. Rect2I bounds = getBounds();
  316. if (mHorzScroll)
  317. bounds.height -= ScrollBarWidth;
  318. if (mVertScroll)
  319. bounds.width -= ScrollBarWidth;
  320. return bounds;
  321. }
  322. void GUIScrollArea::scrollUpPx(UINT32 pixels)
  323. {
  324. if(mVertScroll != nullptr)
  325. {
  326. UINT32 scrollableSize = (UINT32)std::max(0, INT32(mContentSize.y) - INT32(mVisibleSize.y));
  327. float offset = 0.0f;
  328. if(scrollableSize > 0)
  329. offset = pixels / (float)scrollableSize;
  330. mVertScroll->scroll(offset);
  331. }
  332. }
  333. void GUIScrollArea::scrollDownPx(UINT32 pixels)
  334. {
  335. if(mVertScroll != nullptr)
  336. {
  337. UINT32 scrollableSize = (UINT32)std::max(0, INT32(mContentSize.y) - INT32(mVisibleSize.y));
  338. float offset = 0.0f;
  339. if(scrollableSize > 0)
  340. offset = pixels / (float)scrollableSize;
  341. mVertScroll->scroll(-offset);
  342. }
  343. }
  344. void GUIScrollArea::scrollLeftPx(UINT32 pixels)
  345. {
  346. if(mHorzScroll != nullptr)
  347. {
  348. UINT32 scrollableSize = (UINT32)std::max(0, INT32(mContentSize.x) - INT32(mVisibleSize.x));
  349. float offset = 0.0f;
  350. if(scrollableSize > 0)
  351. offset = pixels / (float)scrollableSize;
  352. mHorzScroll->scroll(offset);
  353. }
  354. }
  355. void GUIScrollArea::scrollRightPx(UINT32 pixels)
  356. {
  357. if(mHorzScroll != nullptr)
  358. {
  359. UINT32 scrollableSize = (UINT32)std::max(0, INT32(mContentSize.x) - INT32(mVisibleSize.x));
  360. float offset = 0.0f;
  361. if(scrollableSize > 0)
  362. offset = pixels / (float)scrollableSize;
  363. mHorzScroll->scroll(-offset);
  364. }
  365. }
  366. void GUIScrollArea::scrollUpPct(float percent)
  367. {
  368. if(mVertScroll != nullptr)
  369. mVertScroll->scroll(percent);
  370. }
  371. void GUIScrollArea::scrollDownPct(float percent)
  372. {
  373. if(mVertScroll != nullptr)
  374. mVertScroll->scroll(-percent);
  375. }
  376. void GUIScrollArea::scrollLeftPct(float percent)
  377. {
  378. if(mHorzScroll != nullptr)
  379. mHorzScroll->scroll(percent);
  380. }
  381. void GUIScrollArea::scrollRightPct(float percent)
  382. {
  383. if(mHorzScroll != nullptr)
  384. mHorzScroll->scroll(-percent);
  385. }
  386. bool GUIScrollArea::_mouseEvent(const GUIMouseEvent& ev)
  387. {
  388. if(ev.getType() == GUIMouseEventType::MouseWheelScroll)
  389. {
  390. // Mouse wheel only scrolls on the Y axis
  391. if(mVertScroll != nullptr)
  392. {
  393. UINT32 scrollableHeight = (UINT32)std::max(0, INT32(mContentSize.y) - INT32(mVisibleSize.y));
  394. float additionalScroll = (float)WheelScrollAmount / scrollableHeight;
  395. mVertScroll->scroll(additionalScroll * ev.getWheelScrollAmount());
  396. return true;
  397. }
  398. }
  399. return false;
  400. }
  401. GUIScrollArea* GUIScrollArea::create(ScrollBarType vertBarType, ScrollBarType horzBarType,
  402. const String& scrollBarStyle, const String& scrollAreaStyle)
  403. {
  404. return new (bs_alloc<GUIScrollArea>()) GUIScrollArea(vertBarType, horzBarType, scrollBarStyle,
  405. getStyleName<GUIScrollArea>(scrollAreaStyle), GUIDimensions::create());
  406. }
  407. GUIScrollArea* GUIScrollArea::create(const GUIOptions& options, const String& scrollBarStyle,
  408. const String& scrollAreaStyle)
  409. {
  410. return new (bs_alloc<GUIScrollArea>()) GUIScrollArea(ScrollBarType::ShowIfDoesntFit,
  411. ScrollBarType::ShowIfDoesntFit, scrollBarStyle, getStyleName<GUIScrollArea>(scrollAreaStyle), GUIDimensions::create(options));
  412. }
  413. GUIScrollArea* GUIScrollArea::create(const String& scrollBarStyle, const String& scrollAreaStyle)
  414. {
  415. return new (bs_alloc<GUIScrollArea>()) GUIScrollArea(ScrollBarType::ShowIfDoesntFit, ScrollBarType::ShowIfDoesntFit, scrollBarStyle,
  416. getStyleName<GUIScrollArea>(scrollAreaStyle), GUIDimensions::create());
  417. }
  418. GUIScrollArea* GUIScrollArea::create(ScrollBarType vertBarType,
  419. ScrollBarType horzBarType, const GUIOptions& options, const String& scrollBarStyle,
  420. const String& scrollAreaStyle)
  421. {
  422. return new (bs_alloc<GUIScrollArea>()) GUIScrollArea(vertBarType, horzBarType, scrollBarStyle,
  423. getStyleName<GUIScrollArea>(scrollAreaStyle), GUIDimensions::create(options));
  424. }
  425. const String& GUIScrollArea::getGUITypeName()
  426. {
  427. static String typeName = "ScrollArea";
  428. return typeName;
  429. }
  430. }