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: $(LINK2 https://github.com/GabyForceQ/LibertyEngine/blob/master/source/liberty/framework/gui/meta.d) 6 * Documentation: 7 * Coverage: 8 **/ 9 module liberty.framework.gui.meta; 10 11 import liberty.framework.gui.widget; 12 13 /** 14 * 15 **/ 16 mixin template WidgetEventProps(alias event, string options = "default") { 17 static string[] getEventArrayString() { 18 return event; 19 } 20 21 static if (options == "default") { 22 import std.algorithm : canFind; 23 import std.traits : EnumMembers; 24 25 private { 26 static foreach (name; EnumMembers!Event) 27 mixin("enum bool _" ~ name ~ " = getEventArrayString.canFind(Event." ~ name ~ ");"); 28 29 enum bool _MouseEnterLeave = _MouseEnter && _MouseLeave; 30 enum bool _CheckUncheck = _Check && _Uncheck && _Checked && _Unchecked && _StateChange; 31 32 static if (_MouseEnterLeave) 33 bool mouseEntered; 34 35 static if (_CheckUncheck) { 36 bool checked; 37 38 public bool isChecked() const { 39 return checked; 40 } 41 } 42 43 static if (_StateChange) 44 bool state; 45 46 static foreach (member; event) { 47 mixin("void delegate(Widget, Event) on" ~ member ~ " = null;"); 48 49 static if (member != "Update") 50 mixin("bool isOn" ~ member ~ ";"); 51 } 52 } 53 54 static if (_MouseEnter || _MouseLeave) 55 static assert(_MouseEnterLeave, 56 "In default mode MouseEnter and MouseLeave events should be declared together."); 57 58 static if (_Check || _Uncheck || _Checked || _Unchecked) 59 static assert(_CheckUncheck, 60 "In default mode Check, Uncheck, Checked and Unchecked events should be declared together."); 61 62 static foreach (member; event) { 63 /** 64 * 65 **/ 66 mixin("typeof(this) setOn" ~ member ~ "(void delegate(Widget, Event) on" ~ member ~ ") {" ~ 67 "this.on" ~ member ~ " = on" ~ member ~ "; return this; }"); 68 69 static if (member != "Update") 70 /** 71 * 72 **/ 73 mixin("bool hasOn" ~ member ~ "() const {" ~ 74 "return on" ~ member ~ " !is null; }"); 75 } 76 77 private void clearAllBooleans() { 78 static foreach (member; event) 79 static if (member != "Update") 80 mixin("isOn" ~ member ~ " = false;"); 81 } 82 83 private void clearAllEvents() { 84 static foreach (member; event) 85 static if (member != "Update") 86 mixin("on" ~ member ~ " = null;"); 87 } 88 } else static if (options == "custom") { 89 90 } else 91 static assert(0, "Invalid options."); 92 } 93 94 /** 95 * 96 **/ 97 mixin template WidgetConstructor(string code = "") { 98 import liberty.framework.gui.impl; 99 100 /** 101 * 102 **/ 103 this(string id, Gui gui) { 104 super(id, gui); 105 mixin(code); 106 } 107 } 108 109 /** 110 * 111 **/ 112 mixin template WidgetUpdate() { 113 import liberty.input.impl; 114 import liberty.input.mouse.constants; 115 116 /** 117 * 118 **/ 119 override void update() { 120 clearAllBooleans(); 121 122 static if (_StateChange) 123 state = false; 124 125 if (Input.getMouse.getCursorType != CursorType.DISABLED) { 126 if (isMouseColliding) { 127 static if (_MouseOver) 128 if (hasOnMouseOver) { 129 onMouseOver(this, Event.MouseOver); 130 isOnMouseOver = true; 131 } 132 133 static if (_MouseMove) 134 if (hasOnMouseMove) 135 if (Input.getMouse.isMoving) { 136 onMouseMove(this, Event.MouseMove); 137 isOnMouseMove = true; 138 } 139 140 static if (_MouseEnterLeave) { 141 if (hasOnMouseLeave && !hasOnMouseEnter) { 142 if (!mouseEntered) 143 mouseEntered = true; 144 } else if (hasOnMouseEnter && !mouseEntered) { 145 onMouseEnter(this, Event.MouseEnter); 146 mouseEntered = true; 147 isOnMouseEnter = true; 148 } 149 } 150 151 static if (_MouseLeftClick) 152 if (hasOnMouseLeftClick) 153 if (Input.getMouse.isButtonDown(MouseButton.LEFT)) { 154 onMouseLeftClick(this, Event.MouseLeftClick); 155 isOnMouseLeftClick = true; 156 } 157 158 static if (_MouseMiddleClick) 159 if (hasOnMouseMiddleClick) 160 if (Input.getMouse.isButtonDown(MouseButton.MIDDLE)) { 161 onMouseMiddleClick(this, Event.MouseMiddleClick); 162 isOnMouseMiddleClick = true; 163 } 164 165 static if (_MouseRightClick) 166 if (hasOnMouseRightClick) 167 if (Input.getMouse.isButtonDown(MouseButton.RIGHT)) { 168 onMouseRightClick(this, Event.MouseRightClick); 169 isOnMouseRightClick = true; 170 } 171 172 static if (_CheckUncheck) { 173 if (hasOnCheck && !checked) { 174 if (Input.getMouse.isButtonDown(MouseButton.LEFT)) { 175 onCheck(this, Event.Check); 176 checked = true; 177 isOnCheck = true; 178 static if (_StateChange) 179 state = true; 180 } 181 } else if (hasOnUncheck && checked) 182 if (Input.getMouse.isButtonDown(MouseButton.LEFT)) { 183 onUncheck(this, Event.Uncheck); 184 checked = false; 185 isOnUncheck = true; 186 static if (_StateChange) 187 state = true; 188 } 189 190 static if (_StateChange) 191 if (hasOnStateChange && state) { 192 onStateChange(this, Event.StateChange); 193 isOnStateChange = true; 194 } 195 } 196 } else { 197 static if (_MouseLeave) { 198 if (hasOnMouseLeave && mouseEntered) { 199 onMouseLeave(this, Event.MouseLeave); 200 isOnMouseLeave = true; 201 } 202 203 if (mouseEntered) 204 mouseEntered = false; 205 } 206 } 207 } 208 209 static if (_CheckUncheck) { 210 if (hasOnChecked && checked) { 211 onChecked(this, Event.Checked); 212 isOnChecked = true; 213 } else if (hasOnUnchecked && !checked) { 214 onUnchecked(this, Event.Unchecked); 215 isOnUnchecked = true; 216 } 217 } 218 219 static if (_Update) 220 if (onUpdate !is null) 221 onUpdate(this, Event.Update); 222 } 223 }