1 module rpui.widgets.panel.transforms_system; 2 3 import rpui.events; 4 import rpui.theme; 5 import rpui.primitives; 6 import rpui.widgets.panel.widget; 7 import rpui.widgets.panel.render_system; 8 import rpui.render.transforms; 9 import rpui.render.components; 10 11 import gapi.transform; 12 import gapi.vec; 13 14 struct RenderTransforms { 15 QuadTransforms background; 16 QuadTransforms splitInner; 17 QuadTransforms splitOuter; 18 HorizontalChainTransforms horizontalScrollButton; 19 HorizontalChainTransforms verticalScrollButton; 20 QuadTransforms headerBackground; 21 QuadTransforms headerMark; 22 UiTextTransforms headerText; 23 } 24 25 struct SplitTransforms { 26 vec2 size; 27 vec2 innerPosition; 28 vec2 outerPosition; 29 } 30 31 final class PanelTransformsSystem : TransformsSystem { 32 private RenderTransforms* transforms; 33 private Panel widget; 34 private RenderData* renderData; 35 private Theme theme; 36 37 this(Panel widget, RenderData* renderData, RenderTransforms* transforms) { 38 this.renderData = renderData; 39 this.transforms = transforms; 40 this.theme = widget.view.theme; 41 this.widget = widget; 42 } 43 44 override void onProgress(in ProgressEvent event) { 45 updateBackgroundTransforms(); 46 updateHeaderTransforms(); 47 updateSplitTransforms(); 48 updateScrollButtonsTransforms(); 49 } 50 51 private void updateBackgroundTransforms() { 52 transforms.background = updateQuadTransforms( 53 widget.view.cameraView, 54 widget.absolutePosition, 55 widget.size 56 ); 57 } 58 59 private void updateHeaderTransforms() { 60 vec2 textPosition; 61 const headerSize = vec2(widget.size.x, widget.measure.headerHeight); 62 63 if (widget.userCanHide) { 64 transforms.headerBackground = updateQuadTransforms( 65 widget.view.cameraView, 66 widget.absolutePosition, 67 headerSize 68 ); 69 70 transforms.headerMark = updateQuadTransforms( 71 widget.view.cameraView, 72 widget.absolutePosition + renderData.headerMarkPosition, 73 renderData.headerMarkSize 74 ); 75 76 textPosition = widget.absolutePosition + 77 vec2(renderData.headerMarkPosition.x + renderData.headerMarkSize.x, 0); 78 } else { 79 textPosition = widget.absolutePosition + vec2(renderData.headerMarkPosition.x, 0); 80 } 81 82 with (renderData.headerText.attrs[widget.headerState]) { 83 caption = widget.caption; 84 } 85 86 transforms.headerText = updateUiTextTransforms( 87 &renderData.headerText.render, 88 &theme.regularFont, 89 transforms.headerText, 90 renderData.headerText.attrs[widget.headerState], 91 widget.view.cameraView, 92 textPosition, 93 headerSize 94 ); 95 } 96 97 private void updateSplitTransforms() { 98 // if (!widget.userCanResize && !widget.showSplit) 99 // return; 100 101 const splitTransforms = getSplitTransforms(); 102 103 transforms.splitInner = updateQuadTransforms( 104 widget.view.cameraView, 105 splitTransforms.innerPosition, 106 splitTransforms.size 107 ); 108 109 transforms.splitOuter = updateQuadTransforms( 110 widget.view.cameraView, 111 splitTransforms.outerPosition, 112 splitTransforms.size 113 ); 114 115 widget.split.cursorRangeRect = Rect( 116 splitTransforms.outerPosition, 117 splitTransforms.size 118 ); 119 } 120 121 private SplitTransforms getSplitTransforms() { 122 vec2 size; 123 vec2 innerPosition; 124 vec2 outerPosition; 125 126 const thickness = widget.split.thickness; 127 128 switch (widget.splitRegionAlign) { 129 case RegionAlign.top: 130 outerPosition = widget.absolutePosition + vec2(0, widget.size.y - thickness); 131 innerPosition = outerPosition - vec2(0, thickness); 132 size = vec2(widget.size.x, thickness); 133 break; 134 135 case RegionAlign.bottom: 136 outerPosition = widget.absolutePosition; 137 innerPosition = outerPosition + vec2(0, thickness); 138 size = vec2(widget.size.x, thickness); 139 break; 140 141 case RegionAlign.left: 142 outerPosition = widget.absolutePosition + vec2(widget.size.x - thickness, 0); 143 innerPosition = outerPosition - vec2(thickness, 0); 144 size = vec2(thickness, widget.size.y); 145 break; 146 147 case RegionAlign.right: 148 outerPosition = widget.absolutePosition; 149 innerPosition = outerPosition + vec2(thickness, 0); 150 size = vec2(thickness, widget.size.y); 151 break; 152 153 default: 154 return SplitTransforms(); 155 } 156 157 return SplitTransforms(size, innerPosition, outerPosition); 158 } 159 160 private void updateScrollButtonsTransforms() { 161 transforms.horizontalScrollButton = updateHorizontalChainTransforms( 162 renderData.horizontalScrollButton.widths, 163 widget.view.cameraView, 164 widget.absolutePosition + widget.horizontalScrollButton.buttonOffset, 165 vec2( 166 widget.horizontalScrollButton.buttonSize, 167 widget.measure.horizontalScrollRegionWidth 168 ) 169 ); 170 171 transforms.verticalScrollButton = updateVerticalChainTransforms( 172 renderData.verticalScrollButton.widths, 173 widget.view.cameraView, 174 widget.absolutePosition + widget.verticalScrollButton.buttonOffset, 175 vec2( 176 widget.measure.verticalScrollRegionWidth, 177 widget.verticalScrollButton.buttonSize 178 ) 179 ); 180 } 181 }