mirror of
https://github.com/ArthurSonzogni/FTXUI.git
synced 2025-09-17 16:38:09 +08:00
Introduce ResizableSplit
This commit is contained in:

committed by
Arthur Sonzogni

parent
aacb677e84
commit
bba2abbb60
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
|
Reference in New Issue
Block a user