Make component more functionnal

This commit is contained in:
ArthurSonzogni
2021-05-09 20:32:27 +02:00
parent 9d15d1c275
commit 6d75cb2748
70 changed files with 2182 additions and 1769 deletions

View File

@@ -1,36 +1,35 @@
#ifndef FTXUI_COMPONENT_BUTTON_HPP
#define FTXUI_COMPONENT_BUTTON_HPP
#include <functional>
#include <string>
#include <functional> // for function
#include <string> // for wstring
#include "ftxui/component/component.hpp"
#include "ftxui/dom/elements.hpp"
#include "ftxui/screen/box.hpp"
#include "ftxui/component/component.hpp" // for Component
#include "ftxui/component/component_base.hpp" // for ComponentBase
#include "ftxui/dom/elements.hpp" // for Element
#include "ftxui/screen/box.hpp" // for Box
namespace ftxui {
struct Event;
/// @brief A button. An action is associated to the click event.
/// @ingroup dom
class Button : public Component {
class ButtonBase : public ComponentBase {
public:
// Access this interface from a Component
static ButtonBase* From(Component);
// Constructor.
Button() = default;
Button(std::wstring label) : label(label) {}
~Button() override = default;
/// The Button label.
std::wstring label = L"button";
/// Called when the user press the "enter" button.
std::function<void()> on_click = [] {};
ButtonBase(const std::wstring* label, std::function<void()> on_click);
~ButtonBase() override = default;
// Component implementation.
Element Render() override;
bool OnEvent(Event) override;
private:
const std::wstring* label_;
std::function<void()> on_click_;
Box box_;
};

View File

@@ -1,10 +1,13 @@
#ifndef FTXUI_COMPONENT_CHECKBOX_HPP
#define FTXUI_COMPONENT_CHECKBOX_HPP
#include <string>
#include <functional> // for function
#include <string> // for wstring, allocator
#include "ftxui/component/component.hpp"
#include "ftxui/screen/box.hpp"
#include "ftxui/component/component.hpp" // for Component
#include "ftxui/component/component_base.hpp" // for ComponentBase
#include "ftxui/dom/elements.hpp" // for Element, Decorator, inverted, nothing
#include "ftxui/screen/box.hpp" // for Box
namespace ftxui {
struct Event;
@@ -12,14 +15,14 @@ struct Event;
/// @brief A Checkbox. It can be checked or unchecked.Display an element on a
/// ftxui::Screen.
/// @ingroup dom
class CheckBox : public Component {
class CheckboxBase : public ComponentBase {
public:
// Constructor.
CheckBox() = default;
~CheckBox() override = default;
// Access this interface from a Component
static CheckboxBase* From(Component component);
bool state = false; // The current state. true=checked, false:unchecked.
std::wstring label = L"label"; // The CheckBox label.
// Constructor.
CheckboxBase(const std::wstring* label, bool* state);
~CheckboxBase() override = default;
#if defined(_WIN32)
std::wstring checked = L"[X] "; /// Prefix for a "checked" state.
@@ -32,7 +35,7 @@ class CheckBox : public Component {
Decorator focused_style = inverted; /// Decorator used when focused.
Decorator unfocused_style = nothing; /// Decorator used when unfocused.
/// Called when the user change the state of the CheckBox.
/// Called when the user change the state of the CheckboxBase.
std::function<void()> on_change = []() {};
// Component implementation.
@@ -42,6 +45,8 @@ class CheckBox : public Component {
private:
bool OnMouseEvent(Event event);
const std::wstring* const label_;
bool* const state_;
int cursor_position = 0;
Box box_;
};

View File

@@ -1,77 +1,45 @@
#ifndef FTXUI_COMPONENT_COMPONENT_HPP
#define FTXUI_COMPONENT_COMPONENT_HPP
#ifndef FTXUI_COMPONENT_HPP
#define FTXUI_COMPONENT_HPP
#include <memory> // for unique_ptr
#include <vector> // for vector
#include <functional> // for function
#include <memory> // for shared_ptr, make_shared
#include <string> // for wstring
#include <vector> // for vector
#include "ftxui/component/captured_mouse.hpp" // for CaptureMouse
#include "ftxui/dom/elements.hpp" // for Element
#include "ftxui/component/component_base.hpp"
namespace ftxui {
class Delegate;
class Focus;
struct Event;
class ComponentBase;
/// @brief It implement rendering itself as ftxui::Element. It implement
/// keyboard navigation by responding to ftxui::Event.
/// @ingroup component
class Component {
public:
// Constructor/Destructor.
Component() = default;
virtual ~Component();
using Component = std::shared_ptr<ComponentBase>;
using Components = std::vector<Component>;
// Component hierarchy.
Component* Parent();
void Add(Component* children);
template <class T, class... Args>
std::shared_ptr<T> Make(Args&&... args) {
return std::make_shared<T>(args...);
}
// Renders the component.
virtual Element Render();
Component Button(const std::wstring* label, std::function<void()> on_click);
Component Checkbox(const std::wstring* label, bool* checked);
Component Input(std::wstring* content, const std::wstring* placeholder);
Component Menu(const std::vector<std::wstring>* entries, int* selected_);
Component Radiobox(const std::vector<std::wstring>* entries, int* selected_);
Component Toggle(const std::vector<std::wstring>* entries, int* selected);
// Handles an event.
// By default, reduce on children with a lazy OR.
//
// Returns whether the event was handled or not.
virtual bool OnEvent(Event);
template <class T> // T = {int, float}
Component Slider(std::wstring label, T* value, T min, T max, T increment);
// Focus management ----------------------------------------------------------
//
// If this component contains children, this indicates which one is active,
// nullptr if none is active.
//
// We say an element has the focus if the chain of ActiveChild() from the
// root component contains this object.
virtual Component* ActiveChild();
// namespace Component {
// Component Vertical(Components children);
// Component Horizontal(Components children);
// Component Tab(int* selector, Components children);
//} // namespace Component
// Whether this is the active child of its parent.
bool Active();
// Whether all the ancestors are active.
bool Focused();
}; // namespace ftxui
// Make the |child| to be the "active" one.
virtual void SetActiveChild(Component* child);
#endif /* end of include guard: FTXUI_COMPONENT_HPP */
// Configure all the ancestors to give focus to this component.
void TakeFocus();
protected:
CapturedMouse CaptureMouse(const Event& event);
std::vector<Component*> children_;
private:
Component* parent_ = nullptr;
void Detach();
void Attach(Component* parent);
};
using ComponentPtr = std::unique_ptr<Component>;
} // namespace ftxui
#endif /* end of include guard: FTXUI_COMPONENT_COMPONENT_HPP */
// Copyright 2020 Arthur Sonzogni. All rights reserved.
// Copyright 2021 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

@@ -0,0 +1,81 @@
#ifndef FTXUI_COMPONENT_BASE_HPP
#define FTXUI_COMPONENT_BASE_HPP
#include <memory> // for unique_ptr
#include <vector> // for vector
#include "ftxui/component/captured_mouse.hpp" // for CaptureMouse
#include "ftxui/dom/elements.hpp" // for Element
namespace ftxui {
class Delegate;
class Focus;
struct Event;
class ComponentBase;
using Component = std::shared_ptr<ComponentBase>;
using Components = std::vector<Component>;
/// @brief It implement rendering itself as ftxui::Element. It implement
/// keyboard navigation by responding to ftxui::Event.
/// @ingroup component
class ComponentBase {
public:
// Constructor/Destructor.
ComponentBase() = default;
virtual ~ComponentBase();
// ComponentBase hierarchy.
ComponentBase* Parent();
void Add(Component children);
// Renders the component.
virtual Element Render();
// Handles an event.
// By default, reduce on children with a lazy OR.
//
// Returns whether the event was handled or not.
virtual bool OnEvent(Event);
// Focus management ----------------------------------------------------------
//
// If this component contains children, this indicates which one is active,
// nullptr if none is active.
//
// We say an element has the focus if the chain of ActiveChild() from the
// root component contains this object.
virtual Component ActiveChild();
// Whether this is the active child of its parent.
bool Active();
// Whether all the ancestors are active.
bool Focused();
// Make the |child| to be the "active" one.
virtual void SetActiveChild(ComponentBase* child);
void SetActiveChild(Component child);
// Configure all the ancestors to give focus to this component.
void TakeFocus();
protected:
CapturedMouse CaptureMouse(const Event& event);
std::vector<Component> children_;
private:
ComponentBase* parent_ = nullptr;
void Detach();
};
using Component = std::shared_ptr<ComponentBase>;
} // namespace ftxui
#endif /* end of include guard: FTXUI_COMPONENT_BASE_HPP */
// 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

@@ -1,26 +1,32 @@
#ifndef FTXUI_COMPONENT_CONTAINER_HPP
#define FTXUI_COMPONENT_CONTAINER_HPP
#include "ftxui/component/component.hpp"
#include "ftxui/component/event.hpp"
#include "ftxui/dom/elements.hpp"
#include "ftxui/component/component.hpp" // for Component, Components
#include "ftxui/component/component_base.hpp" // for ComponentBase
#include "ftxui/component/event.hpp" // for Event
#include "ftxui/dom/elements.hpp" // for Element
namespace ftxui {
/// @brief A component where focus and events are automatically handled for you.
class Container : public Component {
class Container : public ComponentBase {
public:
static Container Vertical();
static Container Horizontal();
static Container Tab(int* selector);
static Component Vertical();
static Component Vertical(Components children);
static Component Horizontal();
static Component Horizontal(Components children);
static Component Tab(int* selector);
static Component Tab(int* selector, Components children);
~Container() override = default;
// Component override.
bool OnEvent(Event event) override;
Element Render() override;
Component* ActiveChild() override;
virtual void SetActiveChild(Component*) override;
Component ActiveChild() override;
virtual void SetActiveChild(ComponentBase*) override;
protected:
// Handlers

View File

@@ -8,7 +8,7 @@
namespace ftxui {
class ScreenInteractive;
class Component;
class ComponentBase;
/// @brief Represent an event. It can be key press event, a terminal resize, or
/// more ...
@@ -76,7 +76,7 @@ struct Event {
//--- State section ----------------------------------------------------------
private:
friend Component;
friend ComponentBase;
friend ScreenInteractive;
enum class Type {
Unknown,

View File

@@ -1,27 +1,29 @@
#ifndef FTXUI_COMPONENT_INPUT_H_
#define FTXUI_COMPONENT_INPUT_H_
#include <functional>
#include <string>
#include <functional> // for function
#include <string> // for wstring
#include "ftxui/component/component.hpp"
#include "ftxui/dom/elements.hpp"
#include "ftxui/screen/box.hpp"
#include "ftxui/component/component.hpp" // for Component
#include "ftxui/component/component_base.hpp" // for ComponentBase
#include "ftxui/dom/elements.hpp" // for Element
#include "ftxui/screen/box.hpp" // for Box
namespace ftxui {
struct Event;
/// @brief An input box. The user can type text into it.
/// @ingroup component.
class Input : public Component {
class InputBase : public ComponentBase {
public:
// Access this interface from a Component
static InputBase* From(Component component);
// Constructor.
Input() = default;
~Input() override = default;
InputBase(std::wstring* content, const std::wstring* placeholder);
~InputBase() override = default;
// State.
std::wstring content;
std::wstring placeholder;
int cursor_position = 0;
// State update callback.
@@ -33,6 +35,9 @@ class Input : public Component {
bool OnEvent(Event) override;
private:
std::wstring* const content_;
const std::wstring* const placeholder_;
bool OnMouseEvent(Event);
Box input_box_;
Box cursor_box_;

View File

@@ -1,28 +1,30 @@
#ifndef FTXUI_COMPONENT_MENU
#define FTXUI_COMPONENT_MENU
#include <functional>
#include <string>
#include <vector>
#include <functional> // for function
#include <string> // for wstring
#include <vector> // for vector
#include "ftxui/component/component.hpp"
#include "ftxui/dom/elements.hpp"
#include "ftxui/screen/box.hpp"
#include "ftxui/component/component.hpp" // for Component
#include "ftxui/component/component_base.hpp" // for ComponentBase
#include "ftxui/dom/elements.hpp" // for Element, Decorator, operator|, bold, inverted, nothing
#include "ftxui/screen/box.hpp" // for Box
namespace ftxui {
struct Event;
/// @brief A list of items. The user can navigate through them.
/// @ingroup component
class Menu : public Component {
class MenuBase : public ComponentBase {
public:
// Access this interface from a Component
static MenuBase* From(Component component);
// Constructor.
Menu() = default;
~Menu() override = default;
MenuBase(const std::vector<std::wstring>* entries, int* selected_);
~MenuBase() override = default;
// State.
std::vector<std::wstring> entries = {};
int selected = 0;
int focused = 0;
Decorator normal_style = nothing;
@@ -38,7 +40,10 @@ class Menu : public Component {
Element Render() override;
bool OnEvent(Event) override;
private:
protected:
const std::vector<std::wstring>* const entries_;
int* selected_ = 0;
bool OnMouseEvent(Event);
std::vector<Box> boxes_;

View File

@@ -1,12 +1,14 @@
#ifndef FTXUI_COMPONENT_RADIOBOX_HPP
#define FTXUI_COMPONENT_RADIOBOX_HPP
#include <string>
#include <vector>
#include <functional> // for function
#include <string> // for wstring, allocator
#include <vector> // for vector
#include "ftxui/component/component.hpp"
#include "ftxui/dom/elements.hpp"
#include "ftxui/screen/box.hpp"
#include "ftxui/component/component.hpp" // for Component
#include "ftxui/component/component_base.hpp" // for ComponentBase
#include "ftxui/dom/elements.hpp" // for Element, Decorator, inverted, nothing
#include "ftxui/screen/box.hpp" // for Box
namespace ftxui {
struct Event;
@@ -14,15 +16,16 @@ struct Event;
/// @brief A list of selectable element. One and only one can be selected at
/// the same time.
/// @ingroup component
class RadioBox : public Component {
class RadioboxBase : public ComponentBase {
public:
// Constructor.
RadioBox() = default;
~RadioBox() override = default;
// Access this interface from a Component
static RadioboxBase* From(Component component);
// Constructor.
RadioboxBase(const std::vector<std::wstring>* entries, int* selected);
~RadioboxBase() override = default;
int selected = 0;
int focused = 0;
std::vector<std::wstring> entries;
#if defined(_WIN32)
std::wstring checked = L"(*) ";
@@ -43,6 +46,9 @@ class RadioBox : public Component {
bool OnEvent(Event) override;
private:
const std::vector<std::wstring>* const entries_;
int* const selected_;
bool OnMouseEvent(Event event);
int cursor_position = 0;
std::vector<Box> boxes_;

View File

@@ -3,15 +3,18 @@
#include <atomic> // for atomic
#include <ftxui/component/receiver.hpp>
#include <memory> // for unique_ptr
#include <string> // for string
#include <functional> // for function
#include <memory> // for unique_ptr, shared_ptr
#include <string> // for string
#include "ftxui/component/captured_mouse.hpp" // for CapturedMouse
#include "ftxui/component/event.hpp"
#include "ftxui/screen/screen.hpp" // for Screen
namespace ftxui {
class Component;
class ComponentBase;
using Component = std::shared_ptr<ComponentBase>;
struct Event;
class ScreenInteractive : public Screen {
@@ -22,15 +25,15 @@ class ScreenInteractive : public Screen {
static ScreenInteractive TerminalOutput();
~ScreenInteractive();
void Loop(Component*);
void Loop(Component);
std::function<void()> ExitLoopClosure();
void PostEvent(Event event);
CapturedMouse CaptureMouse();
private:
void Draw(Component* component);
void EventLoop(Component* component);
void Draw(Component component);
void EventLoop(Component component);
enum class Dimension {
FitComponent,

View File

@@ -1,23 +0,0 @@
#ifndef FTXUI_COMPONENT_SLIDER_HPP
#define FTXUI_COMPONENT_SLIDER_HPP
#include <string>
#include "ftxui/component/component.hpp"
namespace ftxui {
// ComponentPtr Slider(std::string label,
// float* value,
// float min = 0.f,
// float max = 100.f,
// float increment = (max - min) * 0.05f);
template <class T> // T = {int, float}
ComponentPtr Slider(std::wstring label, T* value, T min, T max, T increment);
} // namespace ftxui
#endif /* end of include guard: FTXUI_COMPONENT_SLIDER_HPP */
// 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

@@ -1,26 +1,30 @@
#ifndef FTXUI_COMPONENT_TOGGLE_H_
#define FTXUI_COMPONENT_TOGGLE_H_
#include <string>
#include <vector>
#include <functional> // for function
#include <string> // for wstring
#include <vector> // for vector
#include "ftxui/component/component.hpp"
#include "ftxui/dom/elements.hpp"
#include "ftxui/screen/box.hpp"
#include "ftxui/component/component.hpp" // for Component
#include "ftxui/component/component_base.hpp" // for ComponentBase
#include "ftxui/dom/elements.hpp" // for Element, Decorator, operator|, bold, dim, inverted
#include "ftxui/screen/box.hpp" // for Box
namespace ftxui {
struct Event;
/// @brief An horizontal list of elements. The user can navigate through them.
/// @ingroup component
class Toggle : public Component {
class ToggleBase : public ComponentBase {
public:
// Access this interface from a Component
static ToggleBase* From(Component component);
// Constructor.
~Toggle() override = default;
ToggleBase(const std::vector<std::wstring>* entries, int* selected);
~ToggleBase() override = default;
// State.
std::vector<std::wstring> entries = {L"On", L"Off"};
int selected = 0;
int focused = 0;
Decorator normal_style = dim;
@@ -36,7 +40,10 @@ class Toggle : public Component {
Element Render() override;
bool OnEvent(Event) override;
private:
protected:
const std::vector<std::wstring>* const entries_;
int* selected_ = 0;
bool OnMouseEvent(Event event);
std::vector<Box> boxes_;
};