1 ///
2 module fluid.hover_button;
3 
4 import fluid.node;
5 import fluid.frame;
6 import fluid.input;
7 import fluid.label;
8 import fluid.style;
9 import fluid.utils;
10 import fluid.button;
11 
12 alias hoverButton = simpleConstructor!HoverButton;
13 alias frameHoverButton = simpleConstructor!FrameHoverButton;
14 
15 alias HoverButton = HoverButtonImpl!Label;
16 alias FrameHoverButton = HoverButtonImpl!Frame;
17 
18 @safe:
19 
20 /// An button that triggers every frame as long as the button is hovered. Useful for advanced buttons which react to
21 /// more than just left button click.
22 ///
23 /// Note, this is a somewhat low-level node and the hover event, as stated, triggers every frame. There are no hover
24 /// entry nor hover leave events. Make sure you know what you're doing when using this node!
25 class HoverButtonImpl(T : Node = Label) : ButtonImpl!T {
26 
27     mixin enableInputActions;
28 
29     /// Create a new hover button.
30     /// Params:
31     ///     pressed = Action to perform when the button is hovered.
32     this(T...)(T sup) {
33 
34         super(sup);
35 
36     }
37 
38     // Disable action on `press`.
39     protected override void press() {
40 
41     }
42 
43     /// Check events
44     protected override void mouseImpl() {
45 
46         // Simple enough
47         submitted();
48 
49     }
50 
51     protected override bool keyboardImpl() {
52 
53         return false;
54 
55     }
56 
57 }
58 
59 // TODO Needs an example
60 
61 unittest {
62 
63     import fluid.backend;
64 
65     int hoverFrameCount;
66 
67     auto io = new HeadlessBackend;
68     auto root = hoverButton(.nullTheme, "Hello, World!", delegate { hoverFrameCount += 1; });
69 
70     root.io = io;
71 
72     // Move the mouse away from the button
73     io.mousePosition = io.windowSize;
74     root.draw();
75 
76     assert(hoverFrameCount == 0);
77 
78     // Hover the button now
79     io.nextFrame;
80     io.mousePosition = Vector2(0, 0);
81     root.draw();
82 
83     assert(hoverFrameCount == 1);
84 
85     // Press the button
86     io.nextFrame;
87     io.press(MouseButton.left);
88     root.draw();
89 
90     assert(io.isDown(MouseButton.left));
91     assert(hoverFrameCount == 2);
92 
93     // Wait while the button is pressed
94     io.nextFrame;
95     root.draw();
96 
97     assert(io.isDown(MouseButton.left));
98     assert(hoverFrameCount == 3);
99 
100     // Release the button
101     io.nextFrame;
102     io.release(MouseButton.left);
103     root.draw();
104 
105     assert(io.isUp(MouseButton.left));
106     assert(hoverFrameCount == 4);
107 
108     // Move the mouse elsewhere
109     io.nextFrame;
110     io.mousePosition = Vector2(-1, -1);
111     root.draw();
112 
113     assert(hoverFrameCount == 4);
114 
115     // Press the button outside
116     io.nextFrame;
117     io.press(MouseButton.left);
118     root.draw();
119 
120     assert(hoverFrameCount == 4);
121 
122 
123 }