1 /** 2 * Copyright: Copyright (C) 2018 Gabriel Gheorghe, All Rights Reserved 3 * Authors: $(Gabriel Gheorghe) 4 * License: $(LINK2 https://www.gnu.org/licenses/gpl-3.0.txt, GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007) 5 * Source 6 * Documentation: 7 * Coverage: 8 */ 9 module liberty.ui.button; 10 import liberty.core.engine; 11 import liberty.core.scenegraph; 12 import liberty.core.input : Input, MouseButton; 13 import liberty.math; 14 import liberty.graphics; 15 import liberty.ui.widget : Widget; 16 import std.string : splitLines; 17 import liberty.core.geometry.shapes; 18 /// 19 final class Button : Widget { 20 /// 21 mixin(NodeServices); 22 /// 23 this(string id, Node parent, int x, int y, int width, int height) { 24 this(id, parent); 25 setPosition(x, y, width, height); 26 } 27 /// 28 this(string id, int x, int y, int width, int height) { 29 this(id); 30 setPosition(x, y, width, height); 31 } 32 ~this() { 33 //shader.cleanUp(); 34 } 35 /// 36 int x = 0; 37 /// 38 int y = 0; 39 /// 40 int width = 0; 41 /// 42 int height = 0; 43 private { 44 void delegate() _onLeftClick = null; 45 //void delegate() _onDoubleClick = null; 46 void delegate() _onMiddleClick = null; 47 void delegate() _onRightClick = null; 48 //void delegate() _onMousePress = null; 49 //void delegate() _onMouseRelease = null 50 //void delegate() _onMouseEnter = null; 51 //void delegate() _onMouseLeave = null; 52 void delegate() _onMouseMove = null; 53 void delegate() _onMouseInside = null; 54 void delegate() _onUpdate = null; 55 void delegate() _onRender = null; 56 bool _isOnLeftClick = false; 57 bool _isOnMiddleClick = false; 58 bool _isOnRightClick = false; 59 bool _isOnMouseMove = false; 60 bool _isOnMouseInside = false; 61 Vector2I _mousePos; 62 Vector2I _oldMousePos; 63 } 64 /// 65 void setPosition(int x, int y, int width, int height) { 66 this.x = x; 67 this.y = y; 68 this.width = width; 69 this.height = height; 70 } 71 /// 72 void position(Vector4I position) pure nothrow @safe @nogc @property { 73 this.x = position.x; 74 this.y = position.y; 75 this.width = position.z; 76 this.height = position.w; 77 } 78 /// 79 override void update(in float deltaTime) { 80 if (_canListen) { 81 clearAllIsOnEvents(); 82 if (mouseIntersectsThis()) { 83 //if (hasOnMouseEnter()) {} 84 if (hasOnMouseMove() && _oldMousePos != _mousePos) { 85 _onMouseMove(); 86 _isOnMouseMove = true; 87 } 88 if (hasOnMouseInside()) { 89 _onMouseInside(); 90 _isOnMouseInside = true; 91 } 92 if (hasOnLeftClick()) { 93 if (Input.get.isMouseButtonPressed(MouseButton.Left)) { 94 _onLeftClick(); 95 _isOnLeftClick = true; 96 } 97 } 98 if (hasOnMiddleClick()) { 99 if (Input.get.isMouseButtonPressed(MouseButton.Middle)) { 100 _onMiddleClick(); 101 _isOnMiddleClick = true; 102 } 103 } 104 if (hasOnRightClick()) { 105 if (Input.get.isMouseButtonPressed(MouseButton.Right)) { 106 _onRightClick(); 107 _isOnRightClick = true; 108 } 109 } 110 } else { 111 //if (hasOnMouseLeave() && oldMouseIntersectsThis()) { 112 113 //} 114 } 115 _oldMousePos = _mousePos; 116 } 117 if (_onUpdate !is null) { 118 _onUpdate(); 119 } 120 } 121 /// 122 void onLeftClick(void delegate() event) pure nothrow @property { 123 _onLeftClick = event; 124 } 125 /// 126 void onMiddleClick(void delegate() event) pure nothrow @property { 127 _onMiddleClick = event; 128 } 129 /// 130 void onRightClick(void delegate() event) pure nothrow @property { 131 _onRightClick = event; 132 } 133 /// 134 void onMouseMove(void delegate() event) pure nothrow @property { 135 _onMouseMove = event; 136 } 137 /// 138 void onMouseInside(void delegate() event) pure nothrow @property { 139 _onMouseInside = event; 140 } 141 /// 142 void onUpdate(void delegate() event) pure nothrow @property { 143 _onUpdate = event; 144 } 145 /// 146 void onRender(void delegate() event) pure nothrow @property { 147 _onRender = event; 148 } 149 /// 150 bool hasOnLeftClick() pure nothrow const { 151 if (_onLeftClick !is null) { 152 return true; 153 } 154 return false; 155 } 156 /// 157 bool hasOnMiddleClick() pure nothrow const { 158 if (_onMiddleClick !is null) { 159 return true; 160 } 161 return false; 162 } 163 /// 164 bool hasOnRightClick() pure nothrow const { 165 if (_onRightClick !is null) { 166 return true; 167 } 168 return false; 169 } 170 /// 171 bool hasOnMouseMove() pure nothrow const { 172 if (_onMouseMove !is null) { 173 return true; 174 } 175 return false; 176 } 177 /// 178 bool hasOnMouseInside() pure nothrow const { 179 if (_onMouseInside !is null) { 180 return true; 181 } 182 return false; 183 } 184 /// 185 bool isOnLeftClick() pure nothrow const { 186 return _isOnLeftClick; 187 } 188 /// 189 bool isOnMiddleClick() pure nothrow const { 190 return _isOnMiddleClick; 191 } 192 /// 193 bool isOnRightClick() pure nothrow const { 194 return _isOnRightClick; 195 } 196 /// 197 bool isOnMouseMove() pure nothrow const { 198 return _isOnMouseMove; 199 } 200 /// 201 bool isOnMouseInside() pure nothrow const { 202 return _isOnMouseInside; 203 } 204 /// 205 int getNumberOfEvents() pure nothrow { 206 int events = 0; 207 if (hasOnLeftClick()) events++; 208 if (hasOnMiddleClick()) events++; 209 if (hasOnRightClick()) events++; 210 if (hasOnMouseMove()) events++; 211 if (hasOnMouseInside()) events++; 212 return events; 213 } 214 private void clearAllIsOnEvents() { 215 _isOnLeftClick = false; 216 _isOnMiddleClick = false; 217 _isOnRightClick = false; 218 _isOnMouseMove = false; 219 _isOnMouseInside = false; 220 } 221 private void clearAllEvents() { 222 _onLeftClick = null; 223 _onMiddleClick = null; 224 _onRightClick = null; 225 _onMouseMove = null; 226 _onMouseInside = null; 227 } 228 private bool mouseIntersectsThis() { 229 _mousePos = Input.get.mousePosition; 230 return _mousePos.x > x && _mousePos.x < x + width && _mousePos.y > y && _mousePos.y < y + height; 231 } 232 private bool oldMouseIntersectsThis() { 233 return _oldMousePos.x > x && _oldMousePos.x < x + width && _oldMousePos.y > y && _oldMousePos.y < y + height; 234 } 235 /// 236 override void stopListening() { 237 __canListen = false; 238 clearAllIsOnEvents(); 239 clearAllEvents(); 240 } 241 }