1 ///
2 module glui.input;
3 
4 import raylib;
5 
6 import std.meta;
7 
8 import glui.node;
9 import glui.structs;
10 import glui.style;
11 
12 @safe:
13 
14 // TODO This could probably be just a plain interface, replacing GluiFocusable
15 
16 /// Represents a general input node.
17 ///
18 /// Styles: $(UL
19 ///     $(LI `styleKey` = Default style for the input.)
20 ///     $(LI `focusStyleKey` = Style for when the input is focused.)
21 ///     $(LI `disabledStyleKey` = Style for when the input is disabled.)
22 /// )
23 abstract class GluiInput(Parent : GluiNode) : Parent, GluiFocusable {
24 
25     mixin DefineStyles!(
26         "focusStyle", q{ style },
27         "hoverStyle", q{ style },
28         "disabledStyle", q{ style },
29     );
30 
31     /// Callback to run when the input value is altered.
32     void delegate() changed;
33 
34     /// Callback to run when the input is submitted.
35     void delegate() submitted;
36 
37     this(T...)(T sup) {
38 
39         super(sup);
40 
41     }
42 
43     override ref inout(bool) isDisabled() inout { return super.isDisabled; }
44 
45     override const(Style) pickStyle() const {
46 
47         // Disabled
48         if (isDisabledInherited) return disabledStyle;
49 
50         // Focused
51         else if (isFocused) return focusStyle;
52 
53         // Hovered
54         else if (isHovered) return hoverStyle;
55 
56         // Other
57         else return style;
58 
59     }
60 
61     /// Handle mouse input.
62     ///
63     /// Only one node can run its `inputImpl` callback per frame, specifically, the last one to register its input.
64     /// This is to prevent parents or overlapping children to take input when another node is drawn on them.
65     protected abstract void mouseImpl();
66 
67     /// Handle keyboard input.
68     ///
69     /// This will be called each frame as long as this node has focus.
70     ///
71     /// Returns: True if the input was handled, false if not.
72     protected abstract bool keyboardImpl();
73 
74     /// Change the focus to this node.
75     void focus() {
76 
77         // Ignore if disabled
78         if (isDisabled) return;
79 
80         tree.focus = this;
81 
82     }
83 
84     // TODO naming consistence??
85     @property {
86 
87         /// Check if the node has focus.
88         bool isFocused() const {
89 
90             return tree.focus is this;
91 
92         }
93 
94         /// Set or remove focus from this node.
95         bool isFocused(bool enable) {
96 
97             if (enable) focus();
98             else if (isFocused) tree.focus = null;
99 
100             return enable;
101 
102         }
103 
104     }
105 
106 }