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 }