1 module rpui.widgets.stack_layout.stack_locator;
2
3 import std.math;
4
5 import rpui.widget;
6 import rpui.primitives;
7 import rpui.math;
8
9 struct StackLocator {
10 Widget holder;
11 Orientation orientation = Orientation.vertical;
12
13 private vec2 maxSize = vec2(0, 0);
14 private vec2 lastWidgetPosition = vec2(0, 0);
15 private Widget lastWidgetInStack = null;
16
17 void attach(Widget widget) {
18 holder = widget;
19 holder.widthType = Widget.SizeType.wrapContent;
20 holder.heightType = Widget.SizeType.wrapContent;
21 setDecorator();
22 }
23
24 private void setDecorator() {
25 holder.children.decorateWidgets(delegate(Widget widget) {
26 Widget cell = new Widget();
27 cell.associatedWidget = widget;
28 cell.skipFocus = true;
29 return cell;
30 });
31 }
32
33 void updateWidgetsPosition() {
34 with (holder) {
35 startWidgetsPositioning();
36
37 foreach (Widget cell; children) {
38 pushWidgetPosition(cell);
39 }
40 }
41 }
42
43 void startWidgetsPositioning() {
44 lastWidgetPosition = vec2(0, 0);
45 lastWidgetInStack = null;
46 }
47
48 void pushWidgetPosition(Widget cell) {
49 if (!cell.associatedWidget.isVisible) {
50 return;
51 }
52
53 with (holder) {
54 lastWidgetInStack = cell.firstWidget;
55
56 if (orientation == Orientation.vertical) {
57 cell.widthType = SizeType.matchParent;
58 cell.size.y = lastWidgetInStack.outerSize.y;
59 cell.position.y = lastWidgetPosition.y;
60 cell.updateSize();
61 } else {
62 cell.size.x = lastWidgetInStack.outerSize.x;
63 cell.heightType = SizeType.matchParent;
64 cell.position.x = lastWidgetPosition.x;
65 cell.updateSize();
66 }
67
68 lastWidgetPosition += lastWidgetInStack.size + lastWidgetInStack.outerOffsetEnd;
69
70 if (lastWidgetInStack.widthType != SizeType.matchParent) {
71 maxSize.x = fmax(maxSize.x, lastWidgetInStack.outerSize.x);
72 }
73
74 if (lastWidgetInStack.heightType != SizeType.matchParent) {
75 maxSize.y = fmax(maxSize.y, lastWidgetInStack.outerSize.y);
76 }
77 }
78 }
79
80 void updateSize() {
81 with (holder) {
82 if (orientation == Orientation.vertical) {
83 if (widthType == SizeType.wrapContent) {
84 size.x = maxSize.x > innerSize.x ? maxSize.x : innerSize.x;
85 }
86
87 if (heightType == SizeType.wrapContent) {
88 if (lastWidgetInStack !is null) {
89 size.y = lastWidgetPosition.y + lastWidgetInStack.outerOffset.bottom + innerOffsetSize.y;
90 } else {
91 // TODO(Andrey): why *2 ?
92 size.y = innerOffsetSize.y * 2;
93 }
94 }
95 }
96
97 if (orientation == Orientation.horizontal) {
98 if (heightType == SizeType.wrapContent) {
99 size.y = maxSize.y > innerSize.y ? maxSize.y : innerSize.y;
100 }
101
102 if (widthType == SizeType.wrapContent) {
103 if (lastWidgetInStack !is null) {
104 size.x = lastWidgetPosition.x + lastWidgetInStack.outerOffset.right + innerOffsetSize.x;
105 }
106 }
107 }
108 }
109 }
110 }