1//************************************ bs::framework - Copyright 2018 Marko Pintera **************************************//
2//*********** Licensed under the MIT license. See LICENSE.md for full terms. This notice is not to be removed. ***********//
3#include "GUI/BsGUILayoutUtility.h"
4#include "GUI/BsGUIElementBase.h"
5#include "GUI/BsGUILayout.h"
6
7namespace bs
8{
9 Vector2I GUILayoutUtility::calcOptimalSize(const GUIElementBase* elem)
10 {
11 return elem->_calculateLayoutSizeRange().optimal;
12 }
13
14 Vector2I GUILayoutUtility::calcActualSize(UINT32 width, UINT32 height, GUILayout* layout, bool updateOptimalSizes)
15 {
16 if (updateOptimalSizes)
17 layout->_updateOptimalLayoutSizes();
18
19 return calcActualSizeInternal(width, height, layout);
20 }
21
22 Vector2I GUILayoutUtility::calcActualSizeInternal(UINT32 width, UINT32 height, GUILayout* layout)
23 {
24 UINT32 numElements = (UINT32)layout->_getNumChildren();
25 Rect2I* elementAreas = nullptr;
26
27 if (numElements > 0)
28 elementAreas = bs_stack_new<Rect2I>(numElements);
29
30 Rect2I parentArea;
31 parentArea.width = width;
32 parentArea.height = height;
33
34 layout->_getElementAreas(parentArea, elementAreas, numElements, layout->_getCachedChildSizeRanges(), layout->_getCachedSizeRange());
35
36 Rect2I* actualAreas = elementAreas; // We re-use the same array
37 for (UINT32 i = 0; i < numElements; i++)
38 {
39 GUIElementBase* child = layout->_getChild(i);
40 Rect2I childArea = elementAreas[i];
41
42 if (child->_getType() == GUIElementBase::Type::Layout || child->_getType() == GUIElementBase::Type::Panel)
43 {
44 Vector2I childActualSize = calcActualSizeInternal(childArea.width, childArea.height, static_cast<GUILayout*>(child));
45 actualAreas[i].width = (UINT32)childActualSize.x;
46 actualAreas[i].height = (UINT32)childActualSize.y;
47 }
48 else if (child->_getType() == GUIElementBase::Type::Element)
49 {
50 RectOffset padding = child->_getPadding();
51
52 actualAreas[i].width = elementAreas[i].width + padding.left + padding.right;
53 actualAreas[i].height = elementAreas[i].height + padding.top + padding.bottom;
54 }
55 else
56 {
57 actualAreas[i].width = elementAreas[i].width;
58 actualAreas[i].height = elementAreas[i].height;
59 }
60 }
61
62 Vector2I min;
63 Vector2I max;
64
65 if (numElements > 0)
66 {
67 Rect2I childArea = actualAreas[0];
68
69 min = Vector2I(childArea.x, childArea.y);
70 max = Vector2I(childArea.x + childArea.width, childArea.y + childArea.height);
71 }
72
73 for (UINT32 i = 1; i < numElements; i++)
74 {
75 Rect2I childArea = actualAreas[i];
76
77 min.x = std::min(min.x, childArea.x);
78 min.y = std::min(min.y, childArea.y);
79
80 max.x = std::max(max.x, childArea.x + (INT32)childArea.width);
81 max.y = std::max(max.y, childArea.y + (INT32)childArea.height);
82 }
83
84 Vector2I actualSize = max - min;
85
86 if (elementAreas != nullptr)
87 bs_stack_free(elementAreas);
88
89 return actualSize;
90 }
91}