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 }