FTXUI 7.1.0
C++ functional terminal UI.
Loading...
Searching...
No Matches
scroll_indicator.cpp
Go to the documentation of this file.
1// Copyright 2021 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 <algorithm> // for max
5#include <memory> // for make_shared, __shared_ptr_access
6#include <string> // for string
7#include <utility> // for move
8#include <vector> // for vector
9
10#include "ftxui/dom/elements.hpp" // for Element, vscroll_indicator, hscroll_indicator
11#include "ftxui/dom/node.hpp" // for Node, Elements
12#include "ftxui/dom/node_decorator.hpp" // for NodeDecorator
13#include "ftxui/dom/requirement.hpp" // for Requirement
14#include "ftxui/screen/box.hpp" // for Box
15#include "ftxui/screen/screen.hpp" // for Screen, Cell
16
17namespace ftxui {
18
19/// @brief Display a vertical scrollbar on the right.
20/// The background follows the content, the rest follows the parent.
21/// @ingroup dom
23 class Impl : public NodeDecorator {
24 using NodeDecorator::NodeDecorator;
25
26 void ComputeRequirement() override {
27 NodeDecorator::ComputeRequirement();
28 requirement_ = children_[0]->requirement();
29 requirement_.min_x++;
30 }
31
32 void SetBox(Box box) override {
33 box_ = box;
34 box.x_max--;
35 children_[0]->SetBox(box);
36 }
37
38 void Render(Screen& screen) final {
39 // Save the style from the parents, before the content draws over it.
40 const Box stencil = screen.stencil;
41 std::vector<Cell> saved;
42 for (int y = stencil.y_min; y <= stencil.y_max; ++y) {
43 saved.push_back(screen.CellAt(stencil.x_max, y));
44 }
45
46 NodeDecorator::Render(screen);
47
48 const int size_inner = box_.y_max - box_.y_min;
49 if (size_inner <= 0) {
50 return;
51 }
52 const int size_outter = stencil.y_max - stencil.y_min + 1;
53 if (size_outter >= size_inner) {
54 return;
55 }
56
57 int size = 2 * size_outter * size_outter / size_inner;
58 size = std::max(size, 1);
59
60 const int start_y =
61 2 * stencil.y_min + //
62 2 * (stencil.y_min - box_.y_min) * size_outter / size_inner;
63
64 const int x = stencil.x_max;
65 for (int y = stencil.y_min; y <= stencil.y_max; ++y) {
66 const int y_up = 2 * y + 0;
67 const int y_down = 2 * y + 1;
68 const bool up = (start_y <= y_up) && (y_up <= start_y + size);
69 const bool down = (start_y <= y_down) && (y_down <= start_y + size);
70
71 const char* c = up ? (down ? "┃" : "╹") : (down ? "╻" : " "); // NOLINT
72 Cell& cell = screen.CellAt(x, y);
73 const Color background = cell.background_color;
74 cell = saved[y - stencil.y_min];
75 cell.background_color = background;
76 cell.character = c;
77 }
78 }
79 };
80 return std::make_shared<Impl>(std::move(child));
81}
82
83/// @brief Display a horizontal scrollbar at the bottom.
84/// The background follows the content, the rest follows the parent.
85/// @ingroup dom
87 class Impl : public NodeDecorator {
88 using NodeDecorator::NodeDecorator;
89
90 void ComputeRequirement() override {
91 NodeDecorator::ComputeRequirement();
92 requirement_ = children_[0]->requirement();
93 requirement_.min_y++;
94 }
95
96 void SetBox(Box box) override {
97 box_ = box;
98 box.y_max--;
99 children_[0]->SetBox(box);
100 }
101
102 void Render(Screen& screen) final {
103 // Save the style from the parents, before the content draws over it.
104 const Box stencil = screen.stencil;
105 std::vector<Cell> saved;
106 for (int x = stencil.x_min; x <= stencil.x_max; ++x) {
107 saved.push_back(screen.CellAt(x, stencil.y_max));
108 }
109
110 NodeDecorator::Render(screen);
111
112 const int size_inner = box_.x_max - box_.x_min;
113 if (size_inner <= 0) {
114 return;
115 }
116 const int size_outter = stencil.x_max - stencil.x_min + 1;
117 if (size_outter >= size_inner) {
118 return;
119 }
120
121 int size = 2 * size_outter * size_outter / size_inner;
122 size = std::max(size, 1);
123
124 const int start_x =
125 2 * stencil.x_min + //
126 2 * (stencil.x_min - box_.x_min) * size_outter / size_inner;
127
128 const int y = stencil.y_max;
129 for (int x = stencil.x_min; x <= stencil.x_max; ++x) {
130 const int x_left = 2 * x + 0;
131 const int x_right = 2 * x + 1;
132 const bool left = (start_x <= x_left) && (x_left <= start_x + size);
133 const bool right = (start_x <= x_right) && (x_right <= start_x + size);
134
135 const char* c =
136 left ? (right ? "─" : "╴") : (right ? "╶" : " "); // NOLINT
137 Cell& cell = screen.CellAt(x, y);
138 const Color background = cell.background_color;
139 cell = saved[x - stencil.x_min];
140 cell.background_color = background;
141 cell.character = c;
142 }
143 }
144 };
145 return std::make_shared<Impl>(std::move(child));
146}
147
148} // namespace ftxui
Element vscroll_indicator(Element child)
Display a vertical scrollbar on the right. The background follows the content, the rest follows the p...
Element hscroll_indicator(Element child)
Display a horizontal scrollbar at the bottom. The background follows the content, the rest follows th...
The FTXUI ftxui:: namespace.
Definition animation.hpp:11
std::shared_ptr< Node > Element
Definition app.hpp:25
int y
Definition elements.hpp:134
std::uint8_t left
Definition screen.cpp:178
std::uint8_t down
Definition screen.cpp:181
std::uint8_t right
Definition screen.cpp:180