BsGUIScrollArea.cpp 18 KB

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