1 module rpui.widgets.button.transforms_system; 2 3 import std.container.array; 4 import std.math; 5 import std.algorithm; 6 7 import rpui.events; 8 import rpui.widgets.button.widget; 9 import rpui.render.components_factory; 10 import rpui.render.components; 11 import rpui.render.transforms; 12 import rpui.theme; 13 import rpui.widgets.button.render_system; 14 import rpui.math; 15 import rpui.primitives; 16 import rpui.widget; 17 18 struct RenderTransforms { 19 HorizontalChainTransforms background; 20 HorizontalChainTransforms focusGlow; 21 UiTextTransforms captionText; 22 Array!QuadTransforms icons; 23 } 24 25 final class ButtonTransformsSystem : TransformsSystem { 26 private RenderTransforms* transforms; 27 private Button widget; 28 private Theme theme; 29 private RenderData* renderData; 30 31 this(Button widget, RenderData* renderData, RenderTransforms* transforms) { 32 this.widget = widget; 33 this.theme = widget.view.theme; 34 this.renderData = renderData; 35 this.transforms = transforms; 36 } 37 38 override void onProgress(in ProgressEvent event) { 39 updateBackground(); 40 updateText(); 41 updateIcons(); 42 } 43 44 private void updateBackground() { 45 const uselseeBorderSize = vec2( 46 widget.measure.uselessBorders.left + widget.measure.uselessBorders.right, 47 0 48 // widget.measure.uselessBorders.top + widget.measure.uselessBorders.bottom 49 ); 50 51 transforms.background = updateHorizontalChainTransforms( 52 renderData.background.widths, 53 widget.view.cameraView, 54 widget.absolutePosition - vec2(widget.measure.uselessBorders.left, -widget.measure.uselessBorders.bottom), 55 widget.size + uselseeBorderSize, 56 widget.partDraws 57 ); 58 59 if (widget.focusable && widget.isFocused) { 60 transforms.focusGlow = updateHorizontalChainTransforms( 61 renderData.background.widths, 62 widget.view.cameraView, 63 widget.absolutePosition + widget.measure.focusOffsets, 64 widget.size + vec2(widget.measure.focusResize), 65 widget.partDraws 66 ); 67 } 68 } 69 70 private void updateText() { 71 if (widget.caption == "") { 72 widget.measure.textWidth = 0; 73 return; 74 } 75 76 const captionTransforms = getCaptonTransforms(widget.textAlign); 77 78 with (renderData.captionText.attrs[widget.state]) { 79 caption = widget.caption; 80 textAlign = widget.textAlign; 81 textVerticalAlign = widget.textVerticalAlign; 82 } 83 84 transforms.captionText = updateUiTextTransforms( 85 &renderData.captionText.render, 86 &theme.regularFont, 87 transforms.captionText, 88 renderData.captionText.attrs[widget.state], 89 widget.view.cameraView, 90 captionTransforms.position, 91 captionTransforms.size 92 ); 93 94 widget.measure.textWidth = transforms.captionText.size.x; 95 } 96 97 struct CaptionTransforms { 98 vec2 position; 99 vec2 size; 100 } 101 102 CaptionTransforms getCaptonTransforms(in Align textAlign) { 103 const textBoxSize = widget.size - vec2(widget.measure.iconsAreaSize, 0); 104 auto textPosition = vec2(widget.measure.iconsAreaSize, 0) + widget.absolutePosition; 105 106 if (textAlign == Align.left) { 107 textPosition.x += widget.measure.textLeftMargin; 108 } 109 else if (textAlign == Align.right) { 110 textPosition.x -= widget.measure.textRightMargin; 111 } 112 113 if (widget.partDraws == Widget.PartDraws.left || widget.partDraws == Widget.PartDraws.right) { 114 textPosition.x -= 1; 115 } 116 117 return CaptionTransforms( 118 textPosition, 119 textBoxSize 120 ); 121 } 122 123 private void updateIcons() { 124 with (widget) { 125 measure.iconsAreaSize = 0; 126 127 const iconSize = view.resources.icons.getIconsConfig(iconsGroup).size; 128 const iconVerticalOffset = round((size.y - iconSize.y) / 2.0f); 129 float iconLastOffset = 0; 130 int counter = 0; 131 132 for (int i = 0; i < widget.icons.length; ++i) { 133 const iconOffset = iconLastOffset; 134 135 iconLastOffset = iconOffset + iconSize.x + measure.iconGaps; 136 counter++; 137 const offset = measure.iconOffsets + vec2(iconOffset, iconVerticalOffset); 138 139 const transform = updateQuadTransforms( 140 view.cameraView, 141 absolutePosition + offset, 142 iconSize 143 ); 144 transforms.icons[i] = transform; 145 } 146 147 if (icons.length > 0) { 148 measure.iconsAreaSize += iconLastOffset - measure.iconGaps * 2; 149 } 150 151 if (widget.uselessIconArea != 0) { 152 const count = max(icons.length, widget.uselessIconArea); 153 measure.iconsAreaSize = (iconSize.x + measure.iconGaps) * count - measure.iconGaps * 2; 154 } 155 } 156 } 157 }