1 /** 2 Grimoire 3 Copyright (c) 2017 Enalye 4 5 This software is provided 'as-is', without any express or implied warranty. 6 In no event will the authors be held liable for any damages arising 7 from the use of this software. 8 9 Permission is granted to anyone to use this software for any purpose, 10 including commercial applications, and to alter it and redistribute 11 it freely, subject to the following restrictions: 12 13 1. The origin of this software must not be misrepresented; 14 you must not claim that you wrote the original software. 15 If you use this software in a product, an acknowledgment 16 in the product documentation would be appreciated but 17 is not required. 18 19 2. Altered source versions must be plainly marked as such, 20 and must not be misrepresented as being the original software. 21 22 3. This notice may not be removed or altered from any source distribution. 23 */ 24 25 module ui.button; 26 27 import std.conv: to; 28 29 import core.all; 30 import render.all; 31 import common.all; 32 33 import ui.widget; 34 import ui.label; 35 36 class Button: Widget { 37 void function() onClick; 38 39 override void update(float deltaTime) {} 40 override void onEvent(Event event) {} 41 42 override void onSelect() { 43 if(!_isLocked && !_isSelected && _isHovered) 44 isValidated = true; 45 else 46 isValidated = false; 47 } 48 49 override void onValidate() { 50 if(_isValidated) { 51 if(onClick !is null) 52 onClick(); 53 triggerCallback(); 54 } 55 } 56 } 57 58 class ListButton: Button { 59 protected Sprite _sprite; 60 Label label; 61 62 @property { 63 alias color = label.color; 64 alias text = label.text; 65 66 Sprite sprite() { return _sprite; } 67 Sprite sprite(Sprite newSprite) { 68 _sprite = newSprite; 69 reload(); 70 return _sprite; 71 } 72 } 73 74 this(string text) { 75 label = new Label; 76 label.text = text; 77 _size = label.size; 78 } 79 80 this(Sprite newSprite) { 81 label = new Label; 82 _sprite = newSprite; 83 reload(); 84 } 85 86 this(string text, Sprite newSprite) { 87 label = new Label; 88 label.text = text; 89 _size = label.size; 90 _sprite = newSprite; 91 reload(); 92 } 93 94 override void update(float deltaTime) { 95 super.update(deltaTime); 96 label.position = _position; 97 } 98 99 override void draw() { 100 if(_isValidated) 101 drawFilledRect(_position - _size / 2f, _size, Color.white * 0.8f); 102 else if(_isHovered) 103 drawFilledRect(_position - _size / 2f, _size, Color.white * 0.25f); 104 else 105 drawFilledRect(_position - _size / 2f, _size, Color.white * 0.15f); 106 107 if(sprite.texture) 108 sprite.draw(_position); 109 110 if(label.isLoaded) 111 label.draw(); 112 } 113 114 override void onPosition() { 115 reload(); 116 } 117 118 override void onSize() { 119 reload(); 120 } 121 122 private void reload() { 123 label.position = _position; 124 if(_sprite.texture) { 125 _sprite.fit(_size); 126 } 127 } 128 } 129 130 class TextButton: Button { 131 Label label; 132 133 @property { 134 alias color = label.color; 135 alias text = label.text; 136 } 137 138 this(string text) { 139 label = new Label; 140 label.text = text; 141 _size = label.size; 142 } 143 144 override void update(float deltaTime) { 145 super.update(deltaTime); 146 label.position = _position; 147 } 148 149 override void draw() { 150 if(_isLocked) 151 drawFilledRect(_position - _size / 2f, _size, Color.white * 0.055f); 152 else if(_isSelected) 153 drawFilledRect(_position - _size / 2f + (_isSelected ? 1f : 0f), _size, Color.white * 0.4f); 154 else if(_isHovered) 155 drawFilledRect(_position - _size / 2f + (_isSelected ? 1f : 0f), _size, Color.white * 0.25f); 156 else 157 drawFilledRect(_position - _size / 2f + (_isSelected ? 1f : 0f), _size, Color.white * 0.15f); 158 if(label.isLoaded) 159 label.draw(); 160 } 161 162 override void onPosition() { 163 label.position = _position; 164 } 165 } 166 167 class ImgButton: Button { 168 Label label; 169 170 protected { 171 bool _isFixedSize, _isScaleLocked; 172 Sprite _idleSprite, _hoveredSprite, _clickedSprite, _lockedSprite; 173 } 174 175 @property { 176 alias color = label.color; 177 alias text = label.text; 178 179 bool isScaleLocked() { return _isScaleLocked; } 180 bool isScaleLocked(bool newIsScaleLocked) { 181 _isScaleLocked = newIsScaleLocked; 182 if(_idleSprite.texture) 183 setToSize(_idleSprite); 184 if(_hoveredSprite.texture) 185 setToSize(_hoveredSprite); 186 if(_clickedSprite.texture) 187 setToSize(_clickedSprite); 188 if(_lockedSprite.texture) 189 setToSize(_lockedSprite); 190 return _isScaleLocked; 191 } 192 193 Sprite idleSprite() { return _idleSprite; } 194 Sprite idleSprite(Sprite newSprite) { 195 if(_isFixedSize) 196 setToSize(newSprite); 197 else 198 _size = newSprite.size; 199 return _idleSprite = newSprite; 200 } 201 202 Sprite hoveredSprite() { return _hoveredSprite; } 203 Sprite hoveredSprite(Sprite newSprite) { 204 if(_isFixedSize) 205 setToSize(newSprite); 206 else { 207 if(_idleSprite.texture is null) 208 _size = newSprite.size; 209 } 210 return _hoveredSprite = newSprite; 211 } 212 213 Sprite clickedSprite() { return _clickedSprite; } 214 Sprite clickedSprite(Sprite newSprite) { 215 if(_isFixedSize) 216 setToSize(newSprite); 217 else { 218 if(_idleSprite.texture is null) 219 _size = newSprite.size; 220 } 221 return _clickedSprite = newSprite; 222 } 223 224 Sprite lockedSprite() { return _lockedSprite; } 225 Sprite lockedSprite(Sprite newSprite) { 226 if(_isFixedSize) 227 setToSize(newSprite); 228 else { 229 if(_idleSprite.texture is null) 230 _size = newSprite.size; 231 } 232 return _lockedSprite = newSprite; 233 } 234 } 235 236 this() { 237 label = new Label; 238 } 239 240 this(string text) { 241 label = new Label; 242 label.text = text; 243 _size = label.size; 244 } 245 246 private void setToSize(Sprite sprite) { 247 if(!_isFixedSize) 248 return; 249 250 if(_isScaleLocked) { 251 Vec2f clip = to!Vec2f(sprite.clip.zw); 252 float scale; 253 if(_size.x / _size.y > clip.x / clip.y) 254 scale = _size.y / clip.y; 255 else 256 scale = _size.x / clip.x; 257 sprite.size = clip * scale; 258 } 259 else 260 sprite.size = _size; 261 } 262 263 override void update(float deltaTime) { 264 super.update(deltaTime); 265 label.position = _position; 266 } 267 268 override void draw() { 269 if(_isLocked) { 270 if(_lockedSprite.texture) 271 _lockedSprite.drawUnchecked(_position); 272 else if(_idleSprite.texture) 273 _idleSprite.drawUnchecked(_position); 274 else 275 drawFilledRect(_position - _size / 2f, _size, Color.gray); 276 } 277 else if(_isSelected) { 278 if(_clickedSprite.texture) 279 _clickedSprite.drawUnchecked(_position); 280 else if(_idleSprite.texture) 281 _idleSprite.drawUnchecked(_position + Vec2f.one); 282 else 283 drawFilledRect(_position - _size / 2f + Vec2f.one, _size, Color.blue); 284 } 285 else if(_isHovered) { 286 if(_hoveredSprite.texture) 287 _hoveredSprite.drawUnchecked(_position); 288 else if(_idleSprite.texture) 289 _idleSprite.drawUnchecked(_position); 290 else 291 drawFilledRect(_position - _size / 2f, _size, Color.green); 292 } 293 else { 294 if(_idleSprite.texture) 295 _idleSprite.drawUnchecked(_position); 296 else 297 drawFilledRect(_position - _size / 2f, _size, Color.red); 298 } 299 if(label.isLoaded) 300 label.draw(); 301 } 302 303 override void onSize() { 304 _isFixedSize = true; 305 if(_idleSprite.texture) 306 setToSize(_idleSprite); 307 if(_hoveredSprite.texture) 308 setToSize(_hoveredSprite); 309 if(_clickedSprite.texture) 310 setToSize(_clickedSprite); 311 if(_lockedSprite.texture) 312 setToSize(_lockedSprite); 313 } 314 }