BsGUIScrollArea.cpp 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557
  1. #include "BsGUIScrollArea.h"
  2. #include "BsGUIElementStyle.h"
  3. #include "BsGUISkin.h"
  4. #include "BsCGUIWidget.h"
  5. #include "BsGUIDimensions.h"
  6. #include "BsGUILayoutY.h"
  7. #include "BsGUISkin.h"
  8. #include "BsGUIScrollBarVert.h"
  9. #include "BsGUIScrollBarHorz.h"
  10. #include "BsGUIMouseEvent.h"
  11. #include "BsGUILayoutUtility.h"
  12. #include "BsGUISpace.h"
  13. #include "BsException.h"
  14. #include "BsProfilerCPU.h"
  15. using namespace std::placeholders;
  16. namespace BansheeEngine
  17. {
  18. const UINT32 GUIScrollArea::ScrollBarWidth = 16;
  19. const UINT32 GUIScrollArea::MinHandleSize = 4;
  20. const UINT32 GUIScrollArea::WheelScrollAmount = 50;
  21. GUIScrollArea::GUIScrollArea(ScrollBarType vertBarType, ScrollBarType horzBarType,
  22. const String& scrollBarStyle, const String& scrollAreaStyle, const GUIDimensions& dimensions)
  23. :GUIElementContainer(dimensions), mVertScroll(nullptr), mHorzScroll(nullptr), mVertOffset(0), mHorzOffset(0),
  24. mVertBarType(vertBarType), mHorzBarType(horzBarType), mScrollBarStyle(scrollBarStyle), mRecalculateVertOffset(false),
  25. mRecalculateHorzOffset(false)
  26. {
  27. mContentLayout = GUILayoutY::create();
  28. _registerChildElement(mContentLayout);
  29. mHorzScroll = GUIScrollBarHorz::create(mScrollBarStyle);
  30. mVertScroll = GUIScrollBarVert::create(mScrollBarStyle);
  31. _registerChildElement(mHorzScroll);
  32. _registerChildElement(mVertScroll);
  33. mHorzScroll->onScrollPositionChanged.connect(std::bind(&GUIScrollArea::horzScrollUpdate, this, _1));
  34. mVertScroll->onScrollPositionChanged.connect(std::bind(&GUIScrollArea::vertScrollUpdate, this, _1));
  35. }
  36. GUIScrollArea::~GUIScrollArea()
  37. {
  38. }
  39. void GUIScrollArea::updateClippedBounds()
  40. {
  41. mClippedBounds = mLayoutData.area;
  42. mClippedBounds.clip(mLayoutData.clipRect);
  43. }
  44. Vector2I GUIScrollArea::_getOptimalSize() const
  45. {
  46. Vector2I optimalSize = mContentLayout->_getOptimalSize();
  47. // Provide 10x10 in case underlying layout is empty because
  48. // 0 doesn't work well with the layout system
  49. optimalSize.x = std::max(10, optimalSize.x);
  50. optimalSize.y = std::max(10, optimalSize.y);
  51. return optimalSize;
  52. }
  53. LayoutSizeRange GUIScrollArea::_calculateLayoutSizeRange() const
  54. {
  55. // I'm ignoring scroll bars here since if the content layout fits
  56. // then they're not needed and the range is valid. And if it doesn't
  57. // fit the area will get clipped anyway and including the scroll bars
  58. // won't change the size much, but it would complicate this method significantly.
  59. if (mContentLayout->_isActive())
  60. return mDimensions.calculateSizeRange(_getOptimalSize());
  61. return mDimensions.calculateSizeRange(Vector2I());
  62. }
  63. LayoutSizeRange GUIScrollArea::_getLayoutSizeRange() const
  64. {
  65. return mSizeRange;
  66. }
  67. void GUIScrollArea::_updateOptimalLayoutSizes()
  68. {
  69. // Update all children first, otherwise we can't determine our own optimal size
  70. GUIElementBase::_updateOptimalLayoutSizes();
  71. if (mChildren.size() != mChildSizeRanges.size())
  72. mChildSizeRanges.resize(mChildren.size());
  73. UINT32 childIdx = 0;
  74. for (auto& child : mChildren)
  75. {
  76. if (child->_isActive())
  77. mChildSizeRanges[childIdx] = child->_getLayoutSizeRange();
  78. else
  79. mChildSizeRanges[childIdx] = LayoutSizeRange();
  80. childIdx++;
  81. }
  82. mSizeRange = mDimensions.calculateSizeRange(_getOptimalSize());
  83. }
  84. void GUIScrollArea::_getElementAreas(const Rect2I& layoutArea, Rect2I* elementAreas, UINT32 numElements,
  85. const Vector<LayoutSizeRange>& sizeRanges, const LayoutSizeRange& mySizeRange) const
  86. {
  87. Vector2I visibleSize, contentSize;
  88. _getElementAreas(layoutArea, elementAreas, numElements, sizeRanges, visibleSize, contentSize);
  89. }
  90. void GUIScrollArea::_getElementAreas(const Rect2I& layoutArea, Rect2I* elementAreas, UINT32 numElements,
  91. const Vector<LayoutSizeRange>& sizeRanges, Vector2I& visibleSize, Vector2I& contentSize) const
  92. {
  93. assert(mChildren.size() == numElements && numElements == 3);
  94. UINT32 layoutIdx = 0;
  95. UINT32 horzScrollIdx = 0;
  96. UINT32 vertScrollIdx = 0;
  97. UINT32 idx = 0;
  98. for (auto& child : mChildren)
  99. {
  100. if (child == mContentLayout)
  101. layoutIdx = idx;
  102. if (child == mHorzScroll)
  103. horzScrollIdx = idx;
  104. if (child == mVertScroll)
  105. vertScrollIdx = idx;
  106. idx++;
  107. }
  108. // Calculate content layout bounds
  109. //// We want elements to use their optimal height, since scroll area
  110. //// technically provides "infinite" space
  111. UINT32 optimalContentWidth = layoutArea.width;
  112. if (mHorzBarType != ScrollBarType::NeverShow)
  113. optimalContentWidth = sizeRanges[layoutIdx].optimal.x;
  114. UINT32 optimalContentHeight = layoutArea.height;
  115. if (mVertBarType != ScrollBarType::NeverShow)
  116. optimalContentHeight = sizeRanges[layoutIdx].optimal.y;
  117. UINT32 layoutWidth = std::max(optimalContentWidth, (UINT32)layoutArea.width);
  118. UINT32 layoutHeight = std::max(optimalContentHeight, (UINT32)layoutArea.height);
  119. contentSize = GUILayoutUtility::calcActualSize(layoutWidth, layoutHeight, mContentLayout, false);
  120. visibleSize = Vector2I(layoutArea.width, layoutArea.height);
  121. bool addHorzScrollbar = (mHorzBarType == ScrollBarType::ShowIfDoesntFit && contentSize.x > visibleSize.x) ||
  122. mHorzBarType == ScrollBarType::AlwaysShow && mHorzBarType != ScrollBarType::NeverShow;
  123. bool hasHorzScrollbar = false;
  124. bool hasVertScrollbar = false;
  125. if (addHorzScrollbar)
  126. {
  127. // Make room for scrollbar
  128. visibleSize.y = (UINT32)std::max(0, (INT32)layoutArea.height - (INT32)ScrollBarWidth);
  129. optimalContentHeight = (UINT32)std::max(0, (INT32)optimalContentHeight - (INT32)ScrollBarWidth);
  130. if (sizeRanges[layoutIdx].min.y > 0)
  131. optimalContentHeight = std::max((UINT32)sizeRanges[layoutIdx].min.y, optimalContentHeight);
  132. layoutHeight = std::max(optimalContentHeight, (UINT32)visibleSize.y); // Never go below optimal size
  133. contentSize = GUILayoutUtility::calcActualSize(layoutWidth, layoutHeight, mContentLayout, true);
  134. hasHorzScrollbar = true;
  135. }
  136. bool addVertScrollbar = (mVertBarType == ScrollBarType::ShowIfDoesntFit && contentSize.y > visibleSize.y) ||
  137. mVertBarType == ScrollBarType::AlwaysShow && mVertBarType != ScrollBarType::NeverShow;
  138. if (addVertScrollbar)
  139. {
  140. // Make room for scrollbar
  141. visibleSize.x = (UINT32)std::max(0, (INT32)layoutArea.width - (INT32)ScrollBarWidth);
  142. optimalContentWidth = (UINT32)std::max(0, (INT32)optimalContentWidth - (INT32)ScrollBarWidth);
  143. if (sizeRanges[layoutIdx].min.x > 0)
  144. optimalContentWidth = std::max((UINT32)sizeRanges[layoutIdx].min.x, optimalContentWidth);
  145. layoutWidth = std::max(optimalContentWidth, (UINT32)visibleSize.x); // Never go below optimal size
  146. contentSize = GUILayoutUtility::calcActualSize(layoutWidth, layoutHeight, mContentLayout, true);
  147. hasVertScrollbar = true;
  148. if (!hasHorzScrollbar) // Since width has been reduced, we need to check if we require the horizontal scrollbar
  149. {
  150. addHorzScrollbar = (mHorzBarType == ScrollBarType::ShowIfDoesntFit && contentSize.x > visibleSize.x) && mHorzBarType != ScrollBarType::NeverShow;
  151. if (addHorzScrollbar)
  152. {
  153. // Make room for scrollbar
  154. visibleSize.y = (UINT32)std::max(0, (INT32)layoutArea.height - (INT32)ScrollBarWidth);
  155. optimalContentHeight = (UINT32)std::max(0, (INT32)optimalContentHeight - (INT32)ScrollBarWidth);
  156. if (sizeRanges[layoutIdx].min.y > 0)
  157. optimalContentHeight = std::max((UINT32)sizeRanges[layoutIdx].min.y, optimalContentHeight);
  158. layoutHeight = std::max(optimalContentHeight, (UINT32)visibleSize.y); // Never go below optimal size
  159. contentSize = GUILayoutUtility::calcActualSize(layoutWidth, layoutHeight, mContentLayout, true);
  160. hasHorzScrollbar = true;
  161. }
  162. }
  163. }
  164. elementAreas[layoutIdx] = Rect2I(layoutArea.x, layoutArea.y, layoutWidth, layoutHeight);
  165. // Calculate vertical scrollbar bounds
  166. if (hasVertScrollbar)
  167. {
  168. INT32 scrollBarOffset = (UINT32)std::max(0, (INT32)layoutArea.width - (INT32)ScrollBarWidth);
  169. UINT32 scrollBarHeight = layoutArea.height;
  170. if (hasHorzScrollbar)
  171. scrollBarHeight = (UINT32)std::max(0, (INT32)scrollBarHeight - (INT32)ScrollBarWidth);
  172. elementAreas[vertScrollIdx] = Rect2I(layoutArea.x + scrollBarOffset, layoutArea.y, ScrollBarWidth, scrollBarHeight);
  173. }
  174. else
  175. {
  176. elementAreas[vertScrollIdx] = Rect2I(layoutArea.x + layoutWidth, layoutArea.y, 0, 0);
  177. }
  178. // Calculate horizontal scrollbar bounds
  179. if (hasHorzScrollbar)
  180. {
  181. INT32 scrollBarOffset = (UINT32)std::max(0, (INT32)layoutArea.height - (INT32)ScrollBarWidth);
  182. UINT32 scrollBarWidth = layoutArea.width;
  183. if (hasVertScrollbar)
  184. scrollBarWidth = (UINT32)std::max(0, (INT32)scrollBarWidth - (INT32)ScrollBarWidth);
  185. elementAreas[horzScrollIdx] = Rect2I(layoutArea.x, layoutArea.y + scrollBarOffset, scrollBarWidth, ScrollBarWidth);
  186. }
  187. else
  188. {
  189. elementAreas[horzScrollIdx] = Rect2I(layoutArea.x, layoutArea.y + layoutHeight, 0, 0);
  190. }
  191. }
  192. void GUIScrollArea::_updateLayoutInternal(const GUILayoutData& data)
  193. {
  194. UINT32 numElements = (UINT32)mChildren.size();
  195. Rect2I* elementAreas = nullptr;
  196. if (numElements > 0)
  197. elementAreas = bs_stack_new<Rect2I>(numElements);
  198. UINT32 layoutIdx = 0;
  199. UINT32 horzScrollIdx = 0;
  200. UINT32 vertScrollIdx = 0;
  201. for (UINT32 i = 0; i < numElements; i++)
  202. {
  203. GUIElementBase* child = _getChild(i);
  204. if (child == mContentLayout)
  205. layoutIdx = i;
  206. if (child == mHorzScroll)
  207. horzScrollIdx = i;
  208. if (child == mVertScroll)
  209. vertScrollIdx = i;
  210. }
  211. _getElementAreas(data.area, elementAreas, numElements, mChildSizeRanges, mVisibleSize, mContentSize);
  212. Rect2I& layoutBounds = elementAreas[layoutIdx];
  213. Rect2I& horzScrollBounds = elementAreas[horzScrollIdx];
  214. Rect2I& vertScrollBounds = elementAreas[vertScrollIdx];
  215. // Recalculate offsets in case scroll percent got updated externally (this needs to be delayed to this point because
  216. // at the time of the update content and visible sizes might be out of date).
  217. if (mRecalculateVertOffset)
  218. {
  219. UINT32 scrollableHeight = (UINT32)std::max(0, INT32(mContentSize.y) - INT32(vertScrollBounds.height));
  220. mVertOffset = scrollableHeight * Math::clamp01(mVertScroll->getScrollPos());
  221. mRecalculateVertOffset = false;
  222. }
  223. if (mRecalculateHorzOffset)
  224. {
  225. UINT32 scrollableWidth = (UINT32)std::max(0, INT32(mContentSize.x) - INT32(horzScrollBounds.width));
  226. mHorzOffset = scrollableWidth * Math::clamp01(mHorzScroll->getScrollPos());
  227. mRecalculateHorzOffset = false;
  228. }
  229. // Layout
  230. if (mContentLayout->_isActive())
  231. {
  232. layoutBounds.x -= Math::floorToInt(mHorzOffset);
  233. layoutBounds.y -= Math::floorToInt(mVertOffset);
  234. Rect2I layoutClipRect = data.clipRect;
  235. layoutClipRect.width = (UINT32)mVisibleSize.x;
  236. layoutClipRect.height = (UINT32)mVisibleSize.y;
  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. }