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