1 module rpui.widgets.text_input.number_input_type_component; 2 3 import std.conv; 4 import std.math; 5 6 import rpui.math; 7 import rpui.primitives; 8 import rpui.events; 9 import rpui.widgets.text_input.widget; 10 import rpui.render.components; 11 12 struct NumberInputTypeComponent { 13 struct Arrow { 14 vec2 absolutePosition; 15 Rect area; 16 bool isEnter = false; 17 18 @property inout(State) state() inout { 19 return isEnter ? State.enter : State.leave; 20 } 21 } 22 23 Arrow leftArrow; 24 Arrow rightArrow; 25 26 TextInput textInput; 27 float delta = 0; 28 bool isClick = false; 29 int startX = 0; 30 int startY = 0; 31 float value = 0; 32 float initialValue = 0; 33 float mouseSensetive = 20.0f; 34 bool avoidFocusing = false; 35 36 void attach(TextInput textInput) { 37 this.textInput = textInput; 38 } 39 40 void onMouseDown(in MouseDownEvent event) { 41 if (leftArrow.isEnter) { 42 textInput.blur(); 43 avoidFocusing = true; 44 addValue(-1); 45 return; 46 } 47 48 if (rightArrow.isEnter) { 49 textInput.blur(); 50 avoidFocusing = true; 51 addValue(1); 52 return; 53 } 54 55 if (!textInput.isEnter || textInput.isFocused) 56 return; 57 58 isClick = true; 59 delta = 0; 60 startX = event.x; 61 startY = event.y; 62 initialValue = value; 63 avoidFocusing = false; 64 textInput.view.hideCursor(); 65 textInput.freezeUI(); 66 } 67 68 void onMouseMove(in MouseMoveEvent event) { 69 if (!isClick) 70 return; 71 72 delta = (event.x - startX) / mouseSensetive; 73 74 if (delta > 0) { 75 addValue(floor(delta).to!int); 76 } else { 77 addValue(ceil(delta).to!int); 78 } 79 80 if (abs(delta) >= 1) { 81 textInput.view.setMousePositon(startX, startY); 82 avoidFocusing = true; 83 delta = 0; 84 } 85 } 86 87 void onMouseUp(in MouseUpEvent event) { 88 textInput.unfreezeUI(); 89 90 if (avoidFocusing) { 91 avoidFocusing = false; 92 textInput.blur(); 93 // TODO: notify on change event 94 } 95 96 delta = 0; 97 startX = 0; 98 isClick = false; 99 textInput.view.showCursor(); 100 } 101 102 void onBlur() { 103 } 104 105 void addValue(in float sign) { 106 if (sign == 0) 107 return; 108 109 value = textInput.text.to!(float) + sign * textInput.numberStep; 110 textInput.text = value.to!(dstring); 111 } 112 113 void updateArrowStates() { 114 const areaSize = vec2(textInput.measure.arrowsAreaWidth, textInput.size.y); 115 116 leftArrow.area = Rect( 117 textInput.absolutePosition, 118 areaSize 119 ); 120 121 rightArrow.area = Rect( 122 textInput.absolutePosition + vec2(textInput.size.x - areaSize.x, 0), 123 areaSize 124 ); 125 126 if (isClick) { 127 leftArrow.isEnter = false; 128 rightArrow.isEnter = false; 129 } else { 130 leftArrow.isEnter = pointInRect(textInput.view.mousePos, leftArrow.area); 131 rightArrow.isEnter = pointInRect(textInput.view.mousePos, rightArrow.area); 132 } 133 } 134 }