Add menu styles.

This commit is contained in:
Arthur Sonzogni 2019-01-03 00:35:59 +01:00
parent 13e04176a4
commit 178feaa6a9
20 changed files with 241 additions and 46 deletions

View File

@ -1,4 +1,5 @@
cmake_minimum_required(VERSION 3.0) cmake_minimum_required(VERSION 3.0)
enable_testing() enable_testing()
add_subdirectory(ftxui) add_subdirectory(ftxui)

View File

@ -1,3 +1,5 @@
cmake_minimum_required(VERSION 3.0)
function(example name) function(example name)
add_executable(${name} ${name}.cpp) add_executable(${name} ${name}.cpp)
target_link_libraries(${name} PUBLIC ftxui) target_link_libraries(${name} PUBLIC ftxui)

View File

@ -1,6 +1,5 @@
example(color)
example(gauge)
example(input) example(input)
example(menu) example(menu)
example(menu2) example(menu2)
example(menu_style)
example(toggle) example(toggle)

View File

@ -70,7 +70,7 @@ class MyComponent : ComponentHorizontal {
int main(int argc, const char *argv[]) int main(int argc, const char *argv[])
{ {
ftxui::ScreenInteractive screen(60,17); ftxui::ScreenInteractive screen(60,18);
MyComponent component(screen.delegate()); MyComponent component(screen.delegate());
component.on_enter = screen.ExitLoopClosure(); component.on_enter = screen.ExitLoopClosure();
screen.Loop(); screen.Loop();

View File

@ -0,0 +1,87 @@
#include <iostream>
#include <thread>
#include "ftxui/component/component_horizontal.hpp"
#include "ftxui/component/menu.hpp"
#include "ftxui/screen_interactive.hpp"
#include "ftxui/util/string.hpp"
using namespace ftxui;
using namespace ftxui::component;
using namespace ftxui::dom;
class MyComponent : ComponentHorizontal {
public:
MyComponent(ftxui::component::Delegate* delegate)
: ComponentHorizontal(delegate),
menu_1(delegate->NewChild()),
menu_2(delegate->NewChild()),
menu_3(delegate->NewChild()),
menu_4(delegate->NewChild()),
menu_5(delegate->NewChild()),
menu_6(delegate->NewChild()) {
for(Menu* menu : {&menu_1, &menu_2, &menu_3, &menu_4, &menu_5, &menu_6}) {
menu->entries = {
L"Monkey",
L"Dog",
L"Cat",
L"Bird",
L"Elephant",
};
menu->on_enter = [this]() { on_enter(); };
}
menu_2.selected_style = color(Color::Blue);
menu_2.active_style = compose(bold, color(Color::Blue));
menu_3.selected_style = color(Color::Blue);
menu_3.active_style = bgcolor(Color::Blue);
menu_4.selected_style = bgcolor(Color::Blue);
menu_4.active_style = bgcolor(Color::BlueLight);
menu_5.normal_style = bgcolor(Color::Blue);
menu_5.selected_style = bgcolor(Color::Yellow);
menu_5.active_style = bgcolor(Color::Red);
menu_6.normal_style = compose(dim, color(Color::Blue));
menu_6.selected_style = compose(nothing, color(Color::Blue));
menu_6.active_style = compose(bold, color(Color::Blue));
Focus(&menu_1);
}
std::function<void()> on_enter = [](){};
private:
Menu menu_1;
Menu menu_2;
Menu menu_3;
Menu menu_4;
Menu menu_5;
Menu menu_6;
Element Render() override {
return
vbox(
hbox(
flex(frame(center(text(L" menu_1 ")), menu_1.Render())),
flex(frame(center(text(L" menu_2 ")), menu_2.Render())),
flex(frame(center(text(L" menu_3 ")), menu_3.Render()))
),
hbox(
flex(frame(center(text(L" menu_4 ")), menu_4.Render())),
flex(frame(center(text(L" menu_5 ")), menu_5.Render())),
flex(frame(center(text(L" menu_6 ")), menu_6.Render()))
)
);
}
};
int main(int argc, const char *argv[])
{
ftxui::ScreenInteractive screen(90,14);
MyComponent component(screen.delegate());
component.on_enter = screen.ExitLoopClosure();
screen.Loop();
}

View File

@ -18,15 +18,12 @@ class MyComponent : ComponentVertical {
: ComponentVertical(delegate), : ComponentVertical(delegate),
toggle_1(delegate->NewChild()), toggle_1(delegate->NewChild()),
toggle_2(delegate->NewChild()), toggle_2(delegate->NewChild()),
toggle_3(delegate->NewChild()) { toggle_3(delegate->NewChild()),
toggle_1.on = L"On"; toggle_4(delegate->NewChild()) {
toggle_1.off = L"Off"; toggle_1.options = {L"On", L"Off"};
toggle_2.options = {L"Enabled", L"Disabled"};
toggle_2.on = L"Enabled"; toggle_3.options = {L"10€", L"0€"};
toggle_2.off = L"Disabled"; toggle_4.options = {L"Nothing", L"One element", L"Several elements"};
toggle_3.on = L"10€";
toggle_3.off = L"0€";
Focus(&toggle_1); Focus(&toggle_1);
} }
@ -37,6 +34,7 @@ class MyComponent : ComponentVertical {
Toggle toggle_1; Toggle toggle_1;
Toggle toggle_2; Toggle toggle_2;
Toggle toggle_3; Toggle toggle_3;
Toggle toggle_4;
Element Render() override { Element Render() override {
return return
@ -45,7 +43,8 @@ class MyComponent : ComponentVertical {
text(L""), text(L""),
hbox(text(L" * Poweroff on startup : "), toggle_1.Render()), hbox(text(L" * Poweroff on startup : "), toggle_1.Render()),
hbox(text(L" * Out of process : "), toggle_2.Render()), hbox(text(L" * Out of process : "), toggle_2.Render()),
hbox(text(L" * Price of the information : "), toggle_3.Render()) hbox(text(L" * Price of the information : "), toggle_3.Render()),
hbox(text(L" * Number of elements : "), toggle_4.Render())
); );
} }
@ -63,7 +62,7 @@ class MyComponent : ComponentVertical {
}; };
int main(int argc, const char* argv[]) { int main(int argc, const char* argv[]) {
ftxui::ScreenInteractive screen(50,5); ftxui::ScreenInteractive screen(70,7);
MyComponent component(screen.delegate()); MyComponent component(screen.delegate());
component.on_enter = screen.ExitLoopClosure(); component.on_enter = screen.ExitLoopClosure();
screen.Loop(); screen.Loop();

View File

@ -1,3 +1,6 @@
example(color)
example(dbox)
example(frame) example(frame)
example(gauge)
example(separator) example(separator)
example(vbox_hbox) example(vbox_hbox)

31
examples/dom/dbox.cpp Normal file
View File

@ -0,0 +1,31 @@
#include "ftxui/screen.hpp"
#include "ftxui/dom/elements.hpp"
#include <iostream>
int main(int argc, const char *argv[])
{
using namespace ftxui::dom;
auto document =
dbox(
frame(
vbox(
text(L"line_1"),
text(L"line_2"),
text(L"line_3"),
text(L"line_4"),
text(L"line_5")
)
),
center(
frame(
text(L"overlay")
)
)
);
auto screen = ftxui::Screen::TerminalOutput(document);
Render(screen, document.get());
std::cout << screen.ToString();
return 0;
}

View File

@ -7,9 +7,9 @@
int main(int argc, const char *argv[]) int main(int argc, const char *argv[])
{ {
for(float percentage = 0; percentage <= 1.0; percentage+=0.001) { for(float percentage = 0; percentage <= 1.0; percentage+=0.002) {
std::wstring data_downloaded = std::wstring data_downloaded =
std::to_wstring(int(percentage * 44100)) + L"/44100"; std::to_wstring(int(percentage * 5000)) + L"/5000";
using namespace ftxui::dom; using namespace ftxui::dom;
auto document = auto document =
hbox( hbox(

View File

@ -1,5 +1,4 @@
cmake_minimum_required(VERSION 3.0) cmake_minimum_required(VERSION 3.0)
project(ftxui)
add_library(ftxui add_library(ftxui
src/ftxui/component/component.cpp src/ftxui/component/component.cpp
@ -13,6 +12,7 @@ add_library(ftxui
src/ftxui/dom/bold.cpp src/ftxui/dom/bold.cpp
src/ftxui/dom/color.cpp src/ftxui/dom/color.cpp
src/ftxui/dom/composite_decorator.cpp src/ftxui/dom/composite_decorator.cpp
src/ftxui/dom/dbox.cpp
src/ftxui/dom/dim.cpp src/ftxui/dom/dim.cpp
src/ftxui/dom/flex.cpp src/ftxui/dom/flex.cpp
src/ftxui/dom/frame.cpp src/ftxui/dom/frame.cpp

View File

@ -2,6 +2,7 @@
#define FTXUI_COMPONENT_MENU #define FTXUI_COMPONENT_MENU
#include "ftxui/component/component.hpp" #include "ftxui/component/component.hpp"
#include "ftxui/dom/elements.hpp"
#include <functional> #include <functional>
namespace ftxui { namespace ftxui {
@ -16,6 +17,10 @@ class Menu : public Component {
std::vector<std::wstring> entries = {}; std::vector<std::wstring> entries = {};
int selected = 0; int selected = 0;
dom::Decorator active_style = dom::inverted;
dom::Decorator selected_style = dom::bold;
dom::Decorator normal_style = dom::nothing;
// State update callback. // State update callback.
std::function<void()> on_change = [](){}; std::function<void()> on_change = [](){};
std::function<void()> on_enter = [](){}; std::function<void()> on_enter = [](){};

View File

@ -3,6 +3,7 @@
#include "ftxui/component/component.hpp" #include "ftxui/component/component.hpp"
#include <functional> #include <functional>
#include <string>
namespace ftxui { namespace ftxui {
namespace component { namespace component {
@ -13,9 +14,8 @@ class Toggle : public Component {
Toggle(Delegate*); Toggle(Delegate*);
// State. // State.
bool activated = true; size_t activated = 0;
std::wstring on = L"On"; std::vector<std::wstring> options = {L"On", L"Off"};
std::wstring off = L"Off";
// Callback. // Callback.
std::function<void()> on_change = [](){}; std::function<void()> on_change = [](){};

View File

@ -1,6 +1,8 @@
#ifndef FTXUI_DOM_ELEMENTS_HPP #ifndef FTXUI_DOM_ELEMENTS_HPP
#define FTXUI_DOM_ELEMENTS_HPP #define FTXUI_DOM_ELEMENTS_HPP
#include <functional>
#include "ftxui/color.hpp" #include "ftxui/color.hpp"
#include "ftxui/dom/node.hpp" #include "ftxui/dom/node.hpp"
@ -8,12 +10,14 @@ namespace ftxui {
namespace dom { namespace dom {
using Element = std::unique_ptr<Node>; using Element = std::unique_ptr<Node>;
using Decorator = std::function<Element(Element)>;
using Child = std::unique_ptr<Node>; using Child = std::unique_ptr<Node>;
using Children = std::vector<Child>; using Children = std::vector<Child>;
// --- Layout ---- // --- Layout ----
Element vbox(Children); Element vbox(Children);
Element hbox(Children); Element hbox(Children);
Element dbox(Children);
Element flex(); Element flex();
Element flex(Element); Element flex(Element);
@ -32,6 +36,8 @@ Element underlined(Element);
Element blink(Element); Element blink(Element);
Element color(Color, Element); Element color(Color, Element);
Element bgcolor(Color, Element); Element bgcolor(Color, Element);
Decorator color(Color);
Decorator bgcolor(Color);
// --- Util --- // --- Util ---
Element hcenter(Element); Element hcenter(Element);
@ -40,6 +46,7 @@ Element center(Element);
// --- Util --- // --- Util ---
Element nothing(Element element); Element nothing(Element element);
Decorator compose(Decorator, Decorator);
template <class... Args> template <class... Args>
Children unpack(Args... args) { Children unpack(Args... args) {
@ -58,6 +65,11 @@ Element hbox(Args... children) {
return hbox(unpack(std::forward<Args>(children)...)); return hbox(unpack(std::forward<Args>(children)...));
} }
template <class... Args>
Element dbox(Args... children) {
return dbox(unpack(std::forward<Args>(children)...));
}
}; // namespace dom }; // namespace dom
}; // namespace ftxui }; // namespace ftxui

View File

@ -24,9 +24,6 @@ dom::Element Input::Render() {
if (!is_focused) if (!is_focused)
return flex(text(content)); return flex(text(content));
std::wstring sub_content = content;
size_t sub_cursor_position = cursor_position;
std::wstring part_before_cursor = content.substr(0,cursor_position); std::wstring part_before_cursor = content.substr(0,cursor_position);
std::wstring part_at_cursor = cursor_position < (int)content.size() std::wstring part_at_cursor = cursor_position < (int)content.size()
? content.substr(cursor_position, 1) ? content.substr(cursor_position, 1)

View File

@ -14,12 +14,12 @@ dom::Element Menu::Render() {
for (size_t i = 0; i < entries.size(); ++i) { for (size_t i = 0; i < entries.size(); ++i) {
if (size_t(selected) == i) { if (size_t(selected) == i) {
if (focused) if (focused)
elements.push_back(inverted(text(L"> " + entries[i]))); elements.push_back(active_style(text(L"> " + entries[i])));
else else
elements.push_back(bold(text(L"> " + entries[i]))); elements.push_back(selected_style(text(L"> " + entries[i])));
} }
else { else {
elements.push_back(text(L" " + entries[i])); elements.push_back(normal_style(text(L" " + entries[i])));
} }
} }
return vbox(std::move(elements)); return vbox(std::move(elements));

View File

@ -11,33 +11,34 @@ dom::Element Toggle::Render() {
Children children; Children children;
children.push_back(text(L"[")); children.push_back(text(L"["));
if (activated) {
children.push_back(highlight(text(on))); for(size_t i = 0; i<options.size(); ++i) {
// Separator.
if (i != 0)
children.push_back(text(L"|")); children.push_back(text(L"|"));
children.push_back(dim(text(off)));
} else { // Entry.
children.push_back(dim(text(on))); auto style = i == activated ? highlight : dim;
children.push_back(text(L"|")); children.push_back(style(text(options[i])));
children.push_back(highlight(text(off)));
} }
children.push_back(text(L"]")); children.push_back(text(L"]"));
return hbox(std::move(children)); return hbox(std::move(children));
} }
bool Toggle::OnEvent(Event event) { bool Toggle::OnEvent(Event event) {
if (activated) { if (activated > 0 &&
if (event == Event::ArrowRight || event == Event::Character('l')) { (event == Event::ArrowLeft || event == Event::Character('h'))) {
activated = false; activated--;
on_change(); on_change();
return true; return true;
} }
} else {
if (event == Event::ArrowLeft || event == Event::Character('h')) { if (activated < options.size() - 1 &&
activated = true; (event == Event::ArrowRight || event == Event::Character('l'))) {
activated++;
on_change(); on_change();
return true; return true;
} }
}
return false; return false;
} }

View File

@ -47,5 +47,17 @@ std::unique_ptr<Node> bgcolor(Color c, Child child) {
return std::make_unique<BgColor>(unpack(std::move(child)), c); return std::make_unique<BgColor>(unpack(std::move(child)), c);
} }
Decorator color(Color c) {
return [c](Child child) {
return color(c, std::move(child));
};
}
Decorator bgcolor(Color c) {
return [c](Child child) {
return bgcolor(c, std::move(child));
};
}
}; // namespace dom }; // namespace dom
}; // namespace ftxui }; // namespace ftxui

View File

@ -0,0 +1,37 @@
#include "ftxui/dom/node.hpp"
#include "ftxui/dom/elements.hpp"
namespace ftxui {
namespace dom {
class DBox : public Node {
public:
DBox(Children children) : Node(std::move(children)) {}
~DBox() {}
void ComputeRequirement() override {
requirement_.min.x = 0;
requirement_.min.y = 0;
requirement_.flex.x = 1;
requirement_.flex.y = 0;
for (auto& child : children) {
child->ComputeRequirement();
requirement_.min.x = std::max(requirement_.min.x, child->requirement().min.x);
requirement_.min.y = std::max(requirement_.min.y, child->requirement().min.y);
}
}
void SetBox(Box box) override {
Node::SetBox(box);
for (auto& child : children)
child->SetBox(box);
}
};
std::unique_ptr<Node> dbox(Children children) {
return std::make_unique<DBox>(std::move(children));
}
}; // namespace dom
}; // namespace ftxui

View File

@ -7,5 +7,14 @@ Element nothing(Element element) {
return std::move(element); return std::move(element);
} }
Decorator compose(Decorator a, Decorator b) {
return [
a = std::move(a),
b = std::move(b)
](Element element) {
return a(b(std::move(element)));
};
}
}; // namespace dom }; // namespace dom
}; // namespace ftxui }; // namespace ftxui