mirror of
https://github.com/ArthurSonzogni/FTXUI.git
synced 2024-11-22 18:59:59 +08:00
Introduce ResizableSplit
This commit is contained in:
parent
aacb677e84
commit
bba2abbb60
@ -101,6 +101,7 @@ add_library(component STATIC
|
|||||||
src/ftxui/component/radiobox.cpp
|
src/ftxui/component/radiobox.cpp
|
||||||
src/ftxui/component/radiobox.cpp
|
src/ftxui/component/radiobox.cpp
|
||||||
src/ftxui/component/renderer.cpp
|
src/ftxui/component/renderer.cpp
|
||||||
|
src/ftxui/component/resizable_split.cpp
|
||||||
src/ftxui/component/screen_interactive.cpp
|
src/ftxui/component/screen_interactive.cpp
|
||||||
src/ftxui/component/slider.cpp
|
src/ftxui/component/slider.cpp
|
||||||
src/ftxui/component/terminal_input_parser.cpp
|
src/ftxui/component/terminal_input_parser.cpp
|
||||||
|
@ -21,3 +21,4 @@ example(slider_rgb)
|
|||||||
example(tab_horizontal)
|
example(tab_horizontal)
|
||||||
example(tab_vertical)
|
example(tab_vertical)
|
||||||
example(toggle)
|
example(toggle)
|
||||||
|
example(resizable_split)
|
||||||
|
34
examples/component/resizable_split.cpp
Normal file
34
examples/component/resizable_split.cpp
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
#include "ftxui/component/component.hpp" // for Slider
|
||||||
|
#include "ftxui/component/screen_interactive.hpp" // for ScreenInteractive
|
||||||
|
|
||||||
|
using namespace ftxui;
|
||||||
|
|
||||||
|
int main(int argc, const char* argv[]) {
|
||||||
|
auto screen = ScreenInteractive::Fullscreen();
|
||||||
|
|
||||||
|
auto middle = Renderer([] { return text(L"middle") | center; });
|
||||||
|
auto left = Renderer([] { return text(L"Left") | center; });
|
||||||
|
auto right = Renderer([] { return text(L"right") | center; });
|
||||||
|
auto top = Renderer([] { return text(L"top") | center; });
|
||||||
|
auto bottom = Renderer([] { return text(L"bottom") | center; });
|
||||||
|
|
||||||
|
int left_size = 20;
|
||||||
|
int right_size = 20;
|
||||||
|
int top_size = 10;
|
||||||
|
int bottom_size = 10;
|
||||||
|
|
||||||
|
auto container = middle;
|
||||||
|
container = ResizableSplit::Left(left, container, &left_size);
|
||||||
|
container = ResizableSplit::Right(right, container, &right_size);
|
||||||
|
container = ResizableSplit::Top(top, container, &top_size);
|
||||||
|
container = ResizableSplit::Bottom(bottom, container, &bottom_size);
|
||||||
|
|
||||||
|
auto renderer =
|
||||||
|
Renderer(container, [&] { return container->Render() | border; });
|
||||||
|
|
||||||
|
screen.Loop(renderer);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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.
|
@ -41,8 +41,16 @@ namespace Container {
|
|||||||
Component Vertical(Components children);
|
Component Vertical(Components children);
|
||||||
Component Horizontal(Components children);
|
Component Horizontal(Components children);
|
||||||
Component Tab(Components children, int* selector);
|
Component Tab(Components children, int* selector);
|
||||||
|
|
||||||
} // namespace Container
|
} // namespace Container
|
||||||
|
|
||||||
|
namespace ResizableSplit {
|
||||||
|
Component Left(Component main, Component back, int* main_size);
|
||||||
|
Component Right(Component main, Component back, int* main_size);
|
||||||
|
Component Top(Component main, Component back, int* main_size);
|
||||||
|
Component Bottom(Component main, Component back, int* main_size);
|
||||||
|
} // namespace ResizableSplit
|
||||||
|
|
||||||
} // namespace ftxui
|
} // namespace ftxui
|
||||||
|
|
||||||
#endif /* end of include guard: FTXUI_COMPONENT_HPP */
|
#endif /* end of include guard: FTXUI_COMPONENT_HPP */
|
||||||
|
257
src/ftxui/component/resizable_split.cpp
Normal file
257
src/ftxui/component/resizable_split.cpp
Normal file
@ -0,0 +1,257 @@
|
|||||||
|
#include "ftxui/component/captured_mouse.hpp" // for CapturedMouse
|
||||||
|
#include "ftxui/component/component.hpp"
|
||||||
|
#include "ftxui/component/component_base.hpp"
|
||||||
|
#include "ftxui/component/event.hpp"
|
||||||
|
#include "ftxui/dom/elements.hpp"
|
||||||
|
|
||||||
|
namespace ftxui {
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
class ResizableSplitLeft : public ComponentBase {
|
||||||
|
public:
|
||||||
|
ResizableSplitLeft(Component main, Component child, int* main_size)
|
||||||
|
: main_(main), child_(child), main_size_(main_size) {
|
||||||
|
Add(Container::Horizontal({
|
||||||
|
main,
|
||||||
|
child,
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool OnEvent(Event event) final {
|
||||||
|
if (event.is_mouse())
|
||||||
|
return OnMouseEvent(std::move(event));
|
||||||
|
return ComponentBase::OnEvent(std::move(event));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool OnMouseEvent(Event event) {
|
||||||
|
if (captured_mouse_ && event.mouse().motion == Mouse::Released) {
|
||||||
|
captured_mouse_.reset();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (event.mouse().button == Mouse::Left &&
|
||||||
|
event.mouse().motion == Mouse::Pressed &&
|
||||||
|
separator_box_.Contain(event.mouse().x, event.mouse().y) &&
|
||||||
|
!captured_mouse_) {
|
||||||
|
captured_mouse_ = CaptureMouse(event);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (captured_mouse_) {
|
||||||
|
*main_size_ = event.mouse().x - global_box_.x_min;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ComponentBase::OnEvent(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
Element Render() final {
|
||||||
|
return hbox({
|
||||||
|
main_->Render() | size(WIDTH, EQUAL, *main_size_),
|
||||||
|
separator() | reflect(separator_box_),
|
||||||
|
child_->Render() | xflex,
|
||||||
|
}) |
|
||||||
|
reflect(global_box_);
|
||||||
|
};
|
||||||
|
|
||||||
|
private:
|
||||||
|
Component main_;
|
||||||
|
Component child_;
|
||||||
|
int* const main_size_;
|
||||||
|
CapturedMouse captured_mouse_;
|
||||||
|
Box separator_box_;
|
||||||
|
Box global_box_;
|
||||||
|
};
|
||||||
|
|
||||||
|
class ResizableSplitRight: public ComponentBase {
|
||||||
|
public:
|
||||||
|
ResizableSplitRight(Component main, Component child, int* main_size)
|
||||||
|
: main_(main), child_(child), main_size_(main_size) {
|
||||||
|
Add(Container::Horizontal({
|
||||||
|
child,
|
||||||
|
main,
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool OnEvent(Event event) final {
|
||||||
|
if (event.is_mouse())
|
||||||
|
return OnMouseEvent(std::move(event));
|
||||||
|
return ComponentBase::OnEvent(std::move(event));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool OnMouseEvent(Event event) {
|
||||||
|
if (captured_mouse_ && event.mouse().motion == Mouse::Released) {
|
||||||
|
captured_mouse_.reset();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (event.mouse().button == Mouse::Left &&
|
||||||
|
event.mouse().motion == Mouse::Pressed &&
|
||||||
|
separator_box_.Contain(event.mouse().x, event.mouse().y) &&
|
||||||
|
!captured_mouse_) {
|
||||||
|
captured_mouse_ = CaptureMouse(event);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (captured_mouse_) {
|
||||||
|
*main_size_ = global_box_.x_max - event.mouse().x;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ComponentBase::OnEvent(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
Element Render() final {
|
||||||
|
return hbox({
|
||||||
|
child_->Render() | xflex,
|
||||||
|
separator() | reflect(separator_box_),
|
||||||
|
main_->Render() | size(WIDTH, EQUAL, *main_size_),
|
||||||
|
}) |
|
||||||
|
reflect(global_box_);
|
||||||
|
};
|
||||||
|
|
||||||
|
private:
|
||||||
|
Component main_;
|
||||||
|
Component child_;
|
||||||
|
int* const main_size_;
|
||||||
|
CapturedMouse captured_mouse_;
|
||||||
|
Box separator_box_;
|
||||||
|
Box global_box_;
|
||||||
|
};
|
||||||
|
|
||||||
|
class ResizableSplitTop: public ComponentBase {
|
||||||
|
public:
|
||||||
|
ResizableSplitTop(Component main, Component child, int* main_size)
|
||||||
|
: main_(main), child_(child), main_size_(main_size) {
|
||||||
|
Add(Container::Vertical({
|
||||||
|
main,
|
||||||
|
child,
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool OnEvent(Event event) final {
|
||||||
|
if (event.is_mouse())
|
||||||
|
return OnMouseEvent(std::move(event));
|
||||||
|
return ComponentBase::OnEvent(std::move(event));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool OnMouseEvent(Event event) {
|
||||||
|
if (captured_mouse_ && event.mouse().motion == Mouse::Released) {
|
||||||
|
captured_mouse_.reset();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (event.mouse().button == Mouse::Left &&
|
||||||
|
event.mouse().motion == Mouse::Pressed &&
|
||||||
|
separator_box_.Contain(event.mouse().x, event.mouse().y) &&
|
||||||
|
!captured_mouse_) {
|
||||||
|
captured_mouse_ = CaptureMouse(event);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (captured_mouse_) {
|
||||||
|
*main_size_ = event.mouse().y - global_box_.y_min;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ComponentBase::OnEvent(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
Element Render() final {
|
||||||
|
return vbox({
|
||||||
|
main_->Render() | size(HEIGHT, EQUAL, *main_size_),
|
||||||
|
separator() | reflect(separator_box_),
|
||||||
|
child_->Render() | yflex,
|
||||||
|
}) |
|
||||||
|
reflect(global_box_);
|
||||||
|
};
|
||||||
|
|
||||||
|
private:
|
||||||
|
Component main_;
|
||||||
|
Component child_;
|
||||||
|
int* const main_size_;
|
||||||
|
CapturedMouse captured_mouse_;
|
||||||
|
Box separator_box_;
|
||||||
|
Box global_box_;
|
||||||
|
};
|
||||||
|
|
||||||
|
class ResizableSplitBottom: public ComponentBase {
|
||||||
|
public:
|
||||||
|
ResizableSplitBottom(Component main, Component child, int* main_size)
|
||||||
|
: main_(main), child_(child), main_size_(main_size) {
|
||||||
|
Add(Container::Vertical({
|
||||||
|
child,
|
||||||
|
main,
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool OnEvent(Event event) final {
|
||||||
|
if (event.is_mouse())
|
||||||
|
return OnMouseEvent(std::move(event));
|
||||||
|
return ComponentBase::OnEvent(std::move(event));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool OnMouseEvent(Event event) {
|
||||||
|
if (captured_mouse_ && event.mouse().motion == Mouse::Released) {
|
||||||
|
captured_mouse_.reset();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (event.mouse().button == Mouse::Left &&
|
||||||
|
event.mouse().motion == Mouse::Pressed &&
|
||||||
|
separator_box_.Contain(event.mouse().x, event.mouse().y) &&
|
||||||
|
!captured_mouse_) {
|
||||||
|
captured_mouse_ = CaptureMouse(event);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (captured_mouse_) {
|
||||||
|
*main_size_ = global_box_.y_max - event.mouse().y;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ComponentBase::OnEvent(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
Element Render() final {
|
||||||
|
return vbox({
|
||||||
|
child_->Render() | yflex,
|
||||||
|
separator() | reflect(separator_box_),
|
||||||
|
main_->Render() | size(HEIGHT, EQUAL, *main_size_),
|
||||||
|
}) |
|
||||||
|
reflect(global_box_);
|
||||||
|
};
|
||||||
|
|
||||||
|
private:
|
||||||
|
Component main_;
|
||||||
|
Component child_;
|
||||||
|
int* const main_size_;
|
||||||
|
CapturedMouse captured_mouse_;
|
||||||
|
Box separator_box_;
|
||||||
|
Box global_box_;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
namespace ResizableSplit {
|
||||||
|
Component Left(Component main, Component back, int* main_size) {
|
||||||
|
return Make<ResizableSplitLeft>(std::move(main), std::move(back), main_size);
|
||||||
|
}
|
||||||
|
Component Right(Component main, Component back, int* main_size) {
|
||||||
|
return Make<ResizableSplitRight>(std::move(main), std::move(back), main_size);
|
||||||
|
}
|
||||||
|
Component Top(Component main, Component back, int* main_size) {
|
||||||
|
return Make<ResizableSplitTop>(std::move(main), std::move(back), main_size);
|
||||||
|
}
|
||||||
|
Component Bottom(Component main, Component back, int* main_size) {
|
||||||
|
return Make<ResizableSplitBottom>(std::move(main), std::move(back), main_size);
|
||||||
|
}
|
||||||
|
//Component Top(Component main, Component back, int main_size) {
|
||||||
|
//return Make<ResizableSplitTop>(std::move(main), std::move(back), main_size);
|
||||||
|
//}
|
||||||
|
//Component Bottom(Component main, Component back, int main_size) {
|
||||||
|
//return Make<ResizableSplitBottom>(std::move(main), std::move(back),
|
||||||
|
//main_size);
|
||||||
|
//}
|
||||||
|
} // namespace ResizableSplit
|
||||||
|
} // namespace ftxui
|
Loading…
Reference in New Issue
Block a user