1 module rpui.widgets.panel.scroll_button;
2 
3 import rpui.scroll;
4 import rpui.math;
5 import rpui.widgets.panel.widget;
6 import rpui.primitives;
7 import rpui.render.components : State;
8 
9 struct ScrollButton {
10     Orientation orientation;
11     ScrollController scrollController;
12     float regionWidth;
13     bool isEnter = false;
14     bool isClick = false;
15     bool visible = false;
16     vec2 buttonOffset;
17     float buttonSize;
18     Panel panel;
19     float width;
20 
21     @property inout(State) state() inout {
22         if (isClick) {
23             return State.click;
24         } else if (isEnter) {
25             return State.enter;
26         } else {
27             return State.leave;
28         }
29     }
30 
31     this(in Orientation orientation) {
32         this.orientation = orientation;
33         this.scrollController = ScrollController(orientation);
34     }
35 
36     void updateController() {
37         float widgetRegionSizes(in Orientation orientation) {
38             if (orientation == Orientation.horizontal) {
39                 return panel.extraInnerOffset.left + panel.extraInnerOffset.right;
40             } else {
41                 return panel.extraInnerOffset.top + panel.extraInnerOffset.bottom;
42             }
43         }
44 
45         float getVectorComponent(in vec2 vector) {
46             return orientation == Orientation.horizontal ? vector.x : vector.y;
47         }
48 
49         const widgetSize = getVectorComponent(panel.size);
50         const widgetRegionSize = widgetRegionSizes(orientation);
51         const innerBoundarySize = getVectorComponent(panel.innerBoundarySize);
52         const innerBoundarySizeClamped = getVectorComponent(panel.innerBoundarySizeClamped);
53 
54         with (scrollController) {
55             buttonMaxOffset = widgetSize - widgetRegionSize;
56             buttonMaxSize = widgetSize - widgetRegionSize;
57             buttonClick = isClick;
58 
59             visibleSize = widgetSize;
60             contentSize = innerBoundarySize;
61             contentMaxOffset = innerBoundarySizeClamped - widgetSize;
62         }
63     }
64 
65     void attach(Panel panel) {
66         this.panel = panel;
67         this.scrollController.buttonMinSize = panel.measure.scrollButtonMinSize;
68 
69         if (orientation == Orientation.horizontal) {
70             this.width = panel.measure.horizontalScrollRegionWidth;
71         }
72         else if (orientation == Orientation.vertical) {
73             this.width = panel.measure.verticalScrollRegionWidth;
74         }
75     }
76 
77     void updateSize() {
78         updateController();
79         visible = scrollController.contentSize > scrollController.visibleSize;
80 
81         if (orientation == Orientation.horizontal) {
82             buttonSize = scrollController.buttonSize;
83             buttonOffset = vec2(
84                 scrollController.buttonOffset,
85                 panel.size.y - width
86             );
87         }
88         else if (orientation == Orientation.vertical) {
89             buttonSize = scrollController.buttonSize;
90             buttonOffset = vec2(
91                 panel.size.x - width,
92                 scrollController.buttonOffset + panel.extraInnerOffset.top
93             );
94         }
95 
96         if (!visible) {
97             scrollController.setOffsetInPercent(0);
98             return;
99         }
100 
101         scrollController.pollButton(panel.view.mousePos, panel.view.mouseClickPos);
102     }
103 
104     void onProgress() {
105         Rect rect;
106 
107         if (orientation == Orientation.horizontal) {
108             rect = Rect(
109                 panel.absolutePosition + buttonOffset,
110                 vec2(buttonSize, panel.extraInnerOffset.bottom)
111             );
112         }
113         else if (orientation == Orientation.vertical) {
114             rect = Rect(
115                 panel.absolutePosition + buttonOffset,
116                 vec2(panel.extraInnerOffset.right, buttonSize)
117             );
118         }
119 
120         isEnter = pointInRect(panel.view.mousePos, rect);
121     }
122 }