1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
|
#include "scroller.hpp"
#include "../debug/log.hpp"
#include "../misc/memory.hpp" // for shared_ptr, allocator, __shared_ptr_access
#include <algorithm> // for max, min
#include <ftxui/component/component_base.hpp> // for Component, ComponentBase
#include <ftxui/component/event.hpp> // for Event, Event::ArrowDown, Event::ArrowUp, Event::End, Event::Home, Event::PageDown, Event::PageUp
#include <utility> // for move
#include "ftxui/component/component.hpp" // for Make
#include "ftxui/component/mouse.hpp" // for Mouse, Mouse::WheelDown, Mouse::WheelUp
#include "ftxui/dom/deprecated.hpp" // for text
#include "ftxui/dom/elements.hpp" // for operator|, Element, size, vbox, EQUAL, HEIGHT, dbox, reflect, focus, inverted, nothing, select, vscroll_indicator, yflex, yframe
#include "ftxui/dom/node.hpp" // for Node
#include "ftxui/dom/requirement.hpp" // for Requirement
#include "ftxui/screen/box.hpp" // for Box
namespace ftxui { // NOLINT
class CScrollerBase : public ComponentBase {
public:
CScrollerBase(Component child) { Add(child); }
private:
Element OnRender() final { // NOLINT
auto focused = Focused() ? focus : ftxui::select;
auto style = Focused() ? inverted : nothing;
Element background = ComponentBase::Render();
background->ComputeRequirement();
size_ = background->requirement().min_y;
return dbox({
std::move(background),
vbox({
text(L"") | size(HEIGHT, EQUAL, selected_),
text(L"") | style | focused,
}),
}) |
vscroll_indicator | yframe | yflex | reflect(box_);
}
bool OnEvent(Event event) final { // NOLINT
if (event.is_mouse() && box_.Contain(event.mouse().x, event.mouse().y))
TakeFocus();
int selected_old = selected_;
if (event == Event::ArrowUp || event == Event::Character('k') ||
(event.is_mouse() && event.mouse().button == Mouse::WheelUp))
selected_--;
if ((event == Event::ArrowDown || event == Event::Character('j') ||
(event.is_mouse() && event.mouse().button == Mouse::WheelDown)))
selected_++;
if (event == Event::PageDown)
selected_ += box_.y_max - box_.y_min;
if (event == Event::PageUp)
selected_ -= box_.y_max - box_.y_min;
if (event == Event::Home)
selected_ = 0;
if (event == Event::End)
selected_ = size_;
if (event == Event::Custom && sticky_select)
selected_ = size_;
selected_ = std::max(0, std::min(size_, selected_));
sticky_select = selected_ >= size_ - 15;
return selected_old != selected_;
}
bool Focusable() const final { return true; } // NOLINT
bool sticky_select = true;
int selected_ = 0;
int size_ = 0;
Box box_;
};
Component Scroller(Component child) { // NOLINT
return Make<CScrollerBase>(std::move(child));
}
} // namespace ftxui
// Copyright 2021 Arthur Sonzogni. All rights reserved.
// Use of this source code is governed by the MIT license that can be found in
// the LICENSE file.
|