Add focusPosition[relative](x,y) (#280)

It allows when using inside a frame, to scroll the view toward a
particular position.

This resolves:
https://github.com/ArthurSonzogni/FTXUI/issues/125
This commit is contained in:
Arthur Sonzogni 2021-12-13 11:38:31 +01:00 committed by GitHub
parent 52276c8a2b
commit 7e5cd23b4c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 186 additions and 0 deletions

View File

@ -17,6 +17,13 @@ unreleased (development)
- `paragraphAlignRight` - `paragraphAlignRight`
- `paragraphAlignJustify` - `paragraphAlignJustify`
- Add the helper elements based on `flexbox`: `hflow()`, `vflow()`. - Add the helper elements based on `flexbox`: `hflow()`, `vflow()`.
- Add: `focusPositionRelative` and `focusPosition`
### Bug
#### Component
- `Input` shouldn't take focus when hovered by the mouse.
- Modifying `Input`'s during on_enter/on_change event is now working correctly.
### Bug ### Bug

View File

@ -57,6 +57,7 @@ add_library(dom
src/ftxui/dom/flexbox_config.cpp src/ftxui/dom/flexbox_config.cpp
src/ftxui/dom/flexbox_helper.cpp src/ftxui/dom/flexbox_helper.cpp
src/ftxui/dom/flexbox_helper.hpp src/ftxui/dom/flexbox_helper.hpp
src/ftxui/dom/focus.cpp
src/ftxui/dom/frame.cpp src/ftxui/dom/frame.cpp
src/ftxui/dom/gauge.cpp src/ftxui/dom/gauge.cpp
src/ftxui/dom/graph.cpp src/ftxui/dom/graph.cpp

View File

@ -10,6 +10,7 @@ example(gallery)
example(homescreen) example(homescreen)
example(input) example(input)
example(maybe) example(maybe)
example(focus)
example(menu) example(menu)
example(menu2) example(menu2)
example(menu_entries) example(menu_entries)

View File

@ -0,0 +1,72 @@
#include <stddef.h> // for size_t
#include <memory> // for shared_ptr, __shared_ptr_access, allocator
#include <string> // for string, basic_string, to_string, operator+, char_traits
#include <vector> // for vector
#include "ftxui/component/captured_mouse.hpp" // for ftxui
#include "ftxui/component/component.hpp" // for Radiobox, Vertical, Checkbox, Horizontal, Renderer, ResizableSplitBottom, ResizableSplitRight
#include "ftxui/component/component_base.hpp" // for ComponentBase
#include "ftxui/component/screen_interactive.hpp" // for ScreenInteractive
#include "ftxui/dom/elements.hpp" // for text, window, operator|, vbox, hbox, Element, flexbox, bgcolor, filler, flex, size, border, hcenter, color, EQUAL, bold, dim, notflex, xflex_grow, yflex_grow, HEIGHT, WIDTH
#include "ftxui/dom/flexbox_config.hpp" // for FlexboxConfig, FlexboxConfig::AlignContent, FlexboxConfig::JustifyContent, FlexboxConfig::AlignContent::Center, FlexboxConfig::AlignItems, FlexboxConfig::Direction, FlexboxConfig::JustifyContent::Center, FlexboxConfig::Wrap
#include "ftxui/screen/color.hpp" // for Color, Color::Black
using namespace ftxui;
Element make_box(int x, int y) {
std::string title = "(" + std::to_string(x) + ", " + std::to_string(y) + ")";
return text(title) | center | size(WIDTH, EQUAL, 18) |
size(HEIGHT, EQUAL, 9) | border |
bgcolor(Color::HSV(x * 255 / 15, 255, y * 255 / 15));
};
Element make_grid() {
std::vector<Elements> rows;
for (int i = 0; i < 15; i++) {
std::vector<Element> cols;
for (int j = 0; j < 15; j++) {
cols.push_back(make_box(i, j));
}
rows.push_back(cols);
}
return gridbox(rows);
};
int main(int argc, const char* argv[]) {
float focus_x = 0.0f;
float focus_y = 0.0f;
auto slider_x = Slider("x", &focus_x, 0.f, 1.f, 0.05f);
auto slider_y = Slider("y", &focus_y, 0.f, 1.f, 0.05f);
auto renderer = Renderer(
Container::Vertical({
slider_x,
slider_y,
}),
[&] {
auto title = "focusPositionRelative(" + //
std::to_string(focus_x) + ", " + //
std::to_string(focus_y) + ")"; //
return vbox({
text(title),
separator(),
slider_x->Render(),
slider_y->Render(),
separator(),
make_grid() | focusPositionRelative(focus_x, focus_y) |
frame | flex,
}) |
border;
});
auto screen = ScreenInteractive::Fullscreen();
screen.Loop(renderer);
return 0;
}
// Copyright 2020 Arthur Sonzogni. All rights reserved.
// Use of this source code is governed by the MIT license that can be found in
// the LICENSE file.

View File

@ -68,6 +68,8 @@ Decorator color(Color);
Decorator bgcolor(Color); Decorator bgcolor(Color);
Element color(Color, Element); Element color(Color, Element);
Element bgcolor(Color, Element); Element bgcolor(Color, Element);
Decorator focusPosition(int x, int y);
Decorator focusPositionRelative(float x, float y);
// --- Layout is // --- Layout is
// Horizontal, Vertical or stacked set of elements. // Horizontal, Vertical or stacked set of elements.

103
src/ftxui/dom/focus.cpp Normal file
View File

@ -0,0 +1,103 @@
#include <memory> // for make_shared
#include <utility> // for move
#include "ftxui/dom/elements.hpp" // for Element, bold
#include "ftxui/dom/node.hpp" // for Node
#include "ftxui/dom/node_decorator.hpp" // for NodeDecorator
#include "ftxui/screen/box.hpp" // for Box
#include "ftxui/screen/screen.hpp" // for Pixel, Screen
namespace ftxui {
namespace {
} // namespace
/// @brief Used inside a `frame`, this force the view to be scrolled toward a
/// a given position. The position is expressed in proportion of the requested
/// size.
///
/// For instance:
/// - (0, 0) means that the view is scrolled toward the upper left.
/// - (1, 0) means that the view is scrolled toward the upper right.
/// - (0, 1) means that the view is scrolled toward the bottom left.
/// @ingroup dom
///
/// ### Example
///
/// ```cpp
/// Element document = huge_document()
/// | focusPositionRelative(0.f, 1.f)
/// | frame;
/// ```
Decorator focusPositionRelative(float x, float y) {
class Impl : public NodeDecorator {
public:
Impl(Element child, float x, float y)
: NodeDecorator(child), x_(x), y_(y) {}
void ComputeRequirement() override {
NodeDecorator::ComputeRequirement();
requirement_.selection = Requirement::Selection::NORMAL;
Box& box = requirement_.selected_box;
box.x_min = requirement_.min_x * x_;
box.y_min = requirement_.min_y * y_;
box.x_max = requirement_.min_x * x_;
box.y_max = requirement_.min_y * y_;
}
private:
const float x_;
const float y_;
};
return [x, y](Element child) {
return std::make_shared<Impl>(std::move(child), x, y);
};
}
/// @brief Used inside a `frame`, this force the view to be scrolled toward a
/// a given position. The position is expressed in the numbers of cells.
///
/// @ingroup dom
///
/// ### Example
///
/// ```cpp
/// Element document = huge_document()
/// | focusPosition(10, 10)
/// | frame;
/// ```
Decorator focusPosition(int x, int y) {
class Impl : public NodeDecorator {
public:
Impl(Element child, float x, float y)
: NodeDecorator(child), x_(x), y_(y) {}
void ComputeRequirement() override {
NodeDecorator::ComputeRequirement();
requirement_.selection = Requirement::Selection::NORMAL;
Box& box = requirement_.selected_box;
box.x_min = x_;
box.y_min = y_;
box.x_max = x_;
box.y_max = y_;
}
private:
const int x_;
const int y_;
};
return [x, y](Element child) {
return std::make_shared<Impl>(std::move(child), x, y);
};
}
} // namespace ftxui
// Copyright 2020 Arthur Sonzogni. All rights reserved.
// Use of this source code is governed by the MIT license that can be found in
// the LICENSE file.