1 ///
2 module glui.button;
3 
4 import raylib;
5 
6 import glui.node;
7 import glui.frame;
8 import glui.input;
9 import glui.label;
10 import glui.utils;
11 import glui.style;
12 
13 alias button = simpleConstructor!(GluiButton!GluiLabel);
14 alias frameButton = simpleConstructor!(GluiButton!GluiFrame);
15 
16 @safe:
17 
18 /// A button can be pressed by the user to trigger an action.
19 ///
20 /// Styles: $(UL
21 ///   $(LI `styleKey` = Default style for the button.)
22 ///   $(LI `hoverStyleKey` = Style to apply when the button is hovered.)
23 ///   $(LI `pressStyleKey` = Style to apply when the button is pressed.)
24 ///   $(LI `focusStyleKey` = Style to apply when the button is focused.)
25 /// )
26 class GluiButton(T : GluiNode = GluiLabel) : GluiInput!T {
27 
28     mixin DefineStyles!(
29         "pressStyle", q{ hoverStyle },
30     );
31 
32     /// Mouse button to trigger the button.
33     private static immutable triggerButton = MouseButton.MOUSE_LEFT_BUTTON;
34 
35     /// Callback to run when the button is pressed.
36     alias pressed = submitted;
37 
38     // Button status
39     struct {
40 
41         // If true, this button is currenly down.
42         bool isPressed;
43 
44     }
45 
46     /// Create a new button.
47     /// Params:
48     ///     pressed = Action to perform when the button is pressed.
49     this(T...)(T sup, void delegate() @trusted pressed) {
50 
51         super(sup);
52         this.pressed = pressed;
53 
54     }
55 
56     protected override void drawImpl(Rectangle outer, Rectangle inner) {
57 
58         // Draw the button
59         super.drawImpl(outer, inner);
60 
61         // Reset pressed status
62         isPressed = false;
63 
64     }
65 
66     /// Handle mouse input. By default, this will call the `pressed` delegate if the button is pressed.
67     protected override void mouseImpl() @trusted {
68 
69         // Just released
70         if (IsMouseButtonReleased(triggerButton)) {
71 
72             isPressed = true;
73             pressed();
74 
75         }
76 
77     }
78 
79     /// Handle keyboard input.
80     protected override bool keyboardImpl() @trusted {
81 
82         // Pressed enter
83         if (IsKeyReleased(KeyboardKey.KEY_ENTER)) {
84 
85             isPressed = true;
86             pressed();
87             return true;
88 
89         }
90 
91         return IsKeyDown(KeyboardKey.KEY_ENTER);
92 
93     }
94 
95     /// Pick the style.
96     protected override const(Style) pickStyle() const {
97 
98         alias pressing = () @trusted => IsMouseButtonDown(triggerButton);
99 
100         // If pressed
101         if (isHovered && pressing()) return pressStyle;
102 
103         // If focused
104         if (isFocused) return focusStyle;
105 
106         // If hovered
107         if (isHovered) return hoverStyle;
108 
109         // No decision — normal state
110         return super.pickStyle();
111 
112     }
113 
114 }