FTXUI  4.1.1
C++ functional terminal UI.
Loading...
Searching...
No Matches
hoverable.cpp
Go to the documentation of this file.
1#include <ftxui/component/captured_mouse.hpp> // for CapturedMouse
2#include <functional> // for function
3#include <utility> // for move
4
5#include "ftxui/component/component.hpp" // for ComponentDecorator, Hoverable, Make
6#include "ftxui/component/component_base.hpp" // for ComponentBase
7#include "ftxui/component/event.hpp" // for Event
8#include "ftxui/component/mouse.hpp" // for Mouse
9#include "ftxui/component/screen_interactive.hpp" // for Component, ScreenInteractive
10#include "ftxui/dom/elements.hpp" // for operator|, reflect, Element
11#include "ftxui/screen/box.hpp" // for Box
12
13namespace ftxui {
14
15namespace {
16
17void Post(std::function<void()> f) {
18 if (auto* screen = ScreenInteractive::Active()) {
19 screen->Post(std::move(f));
20 return;
21 }
22 f();
23}
24
25} // namespace
26
27/// @brief Wrap a component. Gives the ability to know if it is hovered by the
28/// mouse.
29/// @param component: The wrapped component.
30/// @param hover: The value to reflect whether the component is hovered or not.
31/// @ingroup component
32///
33/// ### Example
34///
35/// ```cpp
36/// auto button = Button("exit", screen.ExitLoopClosure());
37/// bool hover = false;
38/// auto button_hover = Hoverable(button, &hover);
39/// ```
40// NOLINTNEXTLINE
41Component Hoverable(Component component, bool* hover) {
42 class Impl : public ComponentBase {
43 public:
44 Impl(Component component, bool* hover)
45 : component_(std::move(component)), hover_(hover) {
46 Add(component_);
47 }
48
49 private:
50 Element Render() override {
51 return ComponentBase::Render() | reflect(box_);
52 }
53
54 bool OnEvent(Event event) override {
55 if (event.is_mouse()) {
56 *hover_ = box_.Contain(event.mouse().x, event.mouse().y) &&
57 CaptureMouse(event);
58 }
59
60 return ComponentBase::OnEvent(event);
61 }
62
63 Component component_;
64 bool* hover_;
65 Box box_;
66 };
67
68 return Make<Impl>(component, hover);
69}
70
71/// @brief Wrap a component. Gives the ability to know if it is hovered by the
72/// mouse.
73/// @param component: The wrapped component.
74/// @param hover: The value to reflect whether the component is hovered or not.
75/// @ingroup component
76///
77/// ### Example
78///
79/// ```cpp
80/// auto button = Button("exit", screen.ExitLoopClosure());
81/// bool hover = false;
82/// auto button_hover = Hoverable(button, &hover);
83/// ```
85 std::function<void()> on_enter,
86 std::function<void()> on_leave) {
87 class Impl : public ComponentBase {
88 public:
89 Impl(Component component,
90 std::function<void()> on_enter,
91 std::function<void()> on_leave)
92 : component_(std::move(component)),
93 on_enter_(std::move(on_enter)),
94 on_leave_(std::move(on_leave)) {
95 Add(component_);
96 }
97
98 private:
99 Element Render() override {
100 return ComponentBase::Render() | reflect(box_);
101 }
102
103 bool OnEvent(Event event) override {
104 if (event.is_mouse()) {
105 const bool hover = box_.Contain(event.mouse().x, event.mouse().y) &&
106 CaptureMouse(event);
107 if (hover != hover_) {
108 Post(hover ? on_enter_ : on_leave_);
109 }
110 hover_ = hover;
111 }
112
113 return ComponentBase::OnEvent(event);
114 }
115
116 Component component_;
117 Box box_;
118 bool hover_ = false;
119 std::function<void()> on_enter_;
120 std::function<void()> on_leave_;
121 };
122
123 return Make<Impl>(std::move(component), std::move(on_enter),
124 std::move(on_leave));
125}
126
127/// @brief Wrap a component. Gives the ability to know if it is hovered by the
128/// mouse.
129/// @param hover: The value to reflect whether the component is hovered or not.
130/// @ingroup component
131///
132/// ### Example
133///
134/// ```cpp
135/// bool hover = false;
136/// auto button = Button("exit", screen.ExitLoopClosure());
137/// button |= Hoverable(&hover);
138/// ```
140 return [hover](Component component) {
141 return Hoverable(std::move(component), hover);
142 };
143}
144
145/// @brief Wrap a component. Gives the ability to know if it is hovered by the
146/// mouse.
147/// @param on_enter is called when the mouse hover the component.
148/// @param on_leave is called when the mouse leave the component.
149/// @ingroup component
150///
151/// ### Example
152///
153/// ```cpp
154/// auto button = Button("exit", screen.ExitLoopClosure());
155/// int on_enter_cnt = 0;
156/// int on_leave_cnt = 0;
157/// button |= Hoverable(
158/// [&]{ on_enter_cnt++; },
159/// [&]{ on_leave_cnt++; }
160// );
161/// ```
162// NOLINTNEXTLINE
163ComponentDecorator Hoverable(std::function<void()> on_enter,
164 // NOLINTNEXTLINE
165 std::function<void()> on_leave) {
166 return [on_enter, on_leave](Component component) {
167 return Hoverable(std::move(component), on_enter, on_leave);
168 };
169}
170
171/// @brief Wrap a component. Gives the ability to know if it is hovered by the
172/// mouse.
173/// @param component the wrapped component.
174/// @param on_change is called when the mouse enter or leave the component.
175/// @ingroup component
176///
177/// ### Example
178///
179/// ```cpp
180/// auto button = Button("exit", screen.ExitLoopClosure());
181/// bool hovered = false;
182/// auto button_hoverable = Hoverable(button,
183// [&](bool hover) { hovered = hover;});
184/// ```
185// NOLINTNEXTLINE
186Component Hoverable(Component component, std::function<void(bool)> on_change) {
187 return Hoverable(
188 std::move(component), //
189 [on_change] { on_change(true); }, //
190 [on_change] { on_change(false); } //
191 );
192}
193
194/// @brief Wrap a component. Gives the ability to know if it is hovered by the
195/// mouse.
196/// @param on_change is called when the mouse enter or leave the component.
197/// @ingroup component
198///
199/// ### Example
200///
201/// ```cpp
202/// auto button = Button("exit", screen.ExitLoopClosure());
203/// bool hovered = false;
204/// button |= Hoverable([&](bool hover) { hovered = hover;});
205/// ```
206// NOLINTNEXTLINE
207ComponentDecorator Hoverable(std::function<void(bool)> on_change) {
208 return [on_change](Component component) {
209 return Hoverable(std::move(component), on_change);
210 };
211}
212
213} // namespace ftxui
214
215// Copyright 2022 Arthur Sonzogni. All rights reserved.
216// Use of this source code is governed by the MIT license that can be found in
217// the LICENSE file.
It implement rendering itself as ftxui::Element. It implement keyboard navigation by responding to ft...
static ScreenInteractive * Active()
std::shared_ptr< T > Make(Args &&... args)
Definition component.hpp:25
std::shared_ptr< Node > Element
Definition elements.hpp:19
Component Hoverable(Component component, bool *hover)
Wrap a component. Gives the ability to know if it is hovered by the mouse.
Definition hoverable.cpp:41
Decorator reflect(Box &box)
Definition reflect.cpp:39
void Render(Screen &screen, const Element &element)
Display an element on a ftxui::Screen.
Definition node.cpp:44
std::function< Component(Component)> ComponentDecorator
Definition component.hpp:30
std::shared_ptr< ComponentBase > Component
Represent an event. It can be key press event, a terminal resize, or more ...
Definition event.hpp:26
bool is_mouse() const
Definition event.hpp:68
struct Mouse & mouse()
Definition event.hpp:69