Initialize
This commit is contained in:
123
ftxui/include/ftxui/component/animation.hpp
Normal file
123
ftxui/include/ftxui/component/animation.hpp
Normal file
@@ -0,0 +1,123 @@
|
||||
// Copyright 2022 Arthur Sonzogni. All rights reserved.
|
||||
// Use of this source code is governed by the MIT license that can be found in
|
||||
// the LICENSE file.
|
||||
#ifndef FTXUI_ANIMATION_HPP
|
||||
#define FTXUI_ANIMATION_HPP
|
||||
|
||||
#include <chrono> // for milliseconds, duration, steady_clock, time_point
|
||||
#include <functional> // for function
|
||||
|
||||
namespace ftxui::animation {
|
||||
/// @brief RequestAnimationFrame is a function that requests a new frame to be
|
||||
/// drawn in the next animation cycle.
|
||||
///
|
||||
/// @note This function is typically called by components that need to
|
||||
/// update their state or appearance over time, such as animations or
|
||||
/// transitions. This is useful when the change doesn't depend depend on the
|
||||
/// events seen by the terminal, but rather on the passage of time.
|
||||
///
|
||||
/// Components who haven't completed their animation can call this function to
|
||||
/// request a new frame to be drawn later.
|
||||
///
|
||||
/// When there is no new events and no animations to complete, no new frame is
|
||||
/// drawn.
|
||||
///
|
||||
/// @ingroup component
|
||||
void RequestAnimationFrame();
|
||||
|
||||
using Clock = std::chrono::steady_clock;
|
||||
using TimePoint = std::chrono::time_point<Clock>;
|
||||
using Duration = std::chrono::duration<float>;
|
||||
|
||||
// Parameter of Component::OnAnimation(param).
|
||||
class Params {
|
||||
public:
|
||||
explicit Params(Duration duration) : duration_(duration) {}
|
||||
|
||||
/// The duration this animation step represents.
|
||||
Duration duration() const { return duration_; }
|
||||
|
||||
private:
|
||||
Duration duration_;
|
||||
};
|
||||
|
||||
namespace easing {
|
||||
using Function = std::function<float(float)>;
|
||||
// Linear interpolation (no easing)
|
||||
float Linear(float p);
|
||||
|
||||
// Quadratic easing; p^2
|
||||
float QuadraticIn(float p);
|
||||
float QuadraticOut(float p);
|
||||
float QuadraticInOut(float p);
|
||||
|
||||
// Cubic easing; p^3
|
||||
float CubicIn(float p);
|
||||
float CubicOut(float p);
|
||||
float CubicInOut(float p);
|
||||
|
||||
// Quartic easing; p^4
|
||||
float QuarticIn(float p);
|
||||
float QuarticOut(float p);
|
||||
float QuarticInOut(float p);
|
||||
|
||||
// Quintic easing; p^5
|
||||
float QuinticIn(float p);
|
||||
float QuinticOut(float p);
|
||||
float QuinticInOut(float p);
|
||||
|
||||
// Sine wave easing; sin(p * PI/2)
|
||||
float SineIn(float p);
|
||||
float SineOut(float p);
|
||||
float SineInOut(float p);
|
||||
|
||||
// Circular easing; sqrt(1 - p^2)
|
||||
float CircularIn(float p);
|
||||
float CircularOut(float p);
|
||||
float CircularInOut(float p);
|
||||
|
||||
// Exponential easing, base 2
|
||||
float ExponentialIn(float p);
|
||||
float ExponentialOut(float p);
|
||||
float ExponentialInOut(float p);
|
||||
|
||||
// Exponentially-damped sine wave easing
|
||||
float ElasticIn(float p);
|
||||
float ElasticOut(float p);
|
||||
float ElasticInOut(float p);
|
||||
|
||||
// Overshooting cubic easing;
|
||||
float BackIn(float p);
|
||||
float BackOut(float p);
|
||||
float BackInOut(float p);
|
||||
|
||||
// Exponentially-decaying bounce easing
|
||||
float BounceIn(float p);
|
||||
float BounceOut(float p);
|
||||
float BounceInOut(float p);
|
||||
} // namespace easing
|
||||
|
||||
class Animator {
|
||||
public:
|
||||
explicit Animator(float* from,
|
||||
float to = 0.f,
|
||||
Duration duration = std::chrono::milliseconds(250),
|
||||
easing::Function easing_function = easing::Linear,
|
||||
Duration delay = std::chrono::milliseconds(0));
|
||||
|
||||
void OnAnimation(Params&);
|
||||
|
||||
float to() const { return to_; }
|
||||
|
||||
private:
|
||||
float* value_;
|
||||
float from_;
|
||||
float to_;
|
||||
Duration duration_;
|
||||
easing::Function easing_function_;
|
||||
Duration current_;
|
||||
};
|
||||
|
||||
} // namespace ftxui::animation
|
||||
|
||||
#endif /* end of include guard: FTXUI_ANIMATION_HPP */
|
||||
23
ftxui/include/ftxui/component/captured_mouse.hpp
Normal file
23
ftxui/include/ftxui/component/captured_mouse.hpp
Normal file
@@ -0,0 +1,23 @@
|
||||
// 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.
|
||||
#ifndef FTXUI_CAPTURED_MOUSE_HPP
|
||||
#define FTXUI_CAPTURED_MOUSE_HPP
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace ftxui {
|
||||
|
||||
class CapturedMouseInterface {
|
||||
public:
|
||||
CapturedMouseInterface() = default;
|
||||
CapturedMouseInterface(const CapturedMouseInterface&) = default;
|
||||
CapturedMouseInterface(CapturedMouseInterface&&) = delete;
|
||||
CapturedMouseInterface& operator=(const CapturedMouseInterface&) = default;
|
||||
CapturedMouseInterface& operator=(CapturedMouseInterface&&) = delete;
|
||||
virtual ~CapturedMouseInterface() = default;
|
||||
};
|
||||
using CapturedMouse = std::unique_ptr<CapturedMouseInterface>;
|
||||
} // namespace ftxui
|
||||
|
||||
#endif /* end of include guard: FTXUI_CAPTURED_MOUSE_HPP */
|
||||
143
ftxui/include/ftxui/component/component.hpp
Normal file
143
ftxui/include/ftxui/component/component.hpp
Normal file
@@ -0,0 +1,143 @@
|
||||
// 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.
|
||||
#ifndef FTXUI_COMPONENT_HPP
|
||||
#define FTXUI_COMPONENT_HPP
|
||||
|
||||
#include <functional> // for function
|
||||
#include <memory> // for make_shared, shared_ptr
|
||||
#include <utility> // for forward
|
||||
|
||||
#include <ftxui/util/warn_windows_macro.hpp>
|
||||
#include "ftxui/component/component_base.hpp" // for Component, Components
|
||||
#include "ftxui/component/component_options.hpp" // for ButtonOption, CheckboxOption, MenuOption
|
||||
#include "ftxui/dom/elements.hpp" // for Element
|
||||
#include "ftxui/util/ref.hpp" // for ConstRef, Ref, ConstStringRef, ConstStringListRef, StringRef
|
||||
|
||||
namespace ftxui {
|
||||
struct ButtonOption;
|
||||
struct CheckboxOption;
|
||||
struct Event;
|
||||
struct InputOption;
|
||||
struct MenuOption;
|
||||
struct RadioboxOption;
|
||||
struct MenuEntryOption;
|
||||
|
||||
template <class T, class... Args>
|
||||
std::shared_ptr<T> Make(Args&&... args) {
|
||||
return std::make_shared<T>(std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
// Pipe operator to decorate components.
|
||||
using ComponentDecorator = std::function<Component(Component)>;
|
||||
using ElementDecorator = std::function<Element(Element)>;
|
||||
Component operator|(Component component, ComponentDecorator decorator);
|
||||
Component operator|(Component component, ElementDecorator decorator);
|
||||
Component& operator|=(Component& component, ComponentDecorator decorator);
|
||||
Component& operator|=(Component& component, ElementDecorator decorator);
|
||||
|
||||
namespace Container {
|
||||
Component Vertical(Components children);
|
||||
Component Vertical(Components children, int* selector);
|
||||
Component Horizontal(Components children);
|
||||
Component Horizontal(Components children, int* selector);
|
||||
Component Tab(Components children, int* selector);
|
||||
Component Stacked(Components children);
|
||||
} // namespace Container
|
||||
|
||||
Component Button(ButtonOption options);
|
||||
Component Button(ConstStringRef label,
|
||||
std::function<void()> on_click,
|
||||
ButtonOption options = ButtonOption::Simple());
|
||||
|
||||
Component Checkbox(CheckboxOption options);
|
||||
Component Checkbox(ConstStringRef label,
|
||||
bool* checked,
|
||||
CheckboxOption options = CheckboxOption::Simple());
|
||||
|
||||
Component Input(InputOption options = {});
|
||||
Component Input(StringRef content, InputOption options = {});
|
||||
Component Input(StringRef content,
|
||||
StringRef placeholder,
|
||||
InputOption options = {});
|
||||
|
||||
Component Menu(MenuOption options);
|
||||
Component Menu(ConstStringListRef entries,
|
||||
int* selected_,
|
||||
MenuOption options = MenuOption::Vertical());
|
||||
Component MenuEntry(MenuEntryOption options);
|
||||
Component MenuEntry(ConstStringRef label, MenuEntryOption options = {});
|
||||
|
||||
Component Radiobox(RadioboxOption options);
|
||||
Component Radiobox(ConstStringListRef entries,
|
||||
int* selected_,
|
||||
RadioboxOption options = {});
|
||||
|
||||
Component Dropdown(ConstStringListRef entries, int* selected);
|
||||
Component Dropdown(DropdownOption options);
|
||||
|
||||
Component Toggle(ConstStringListRef entries, int* selected);
|
||||
|
||||
// General slider constructor:
|
||||
template <typename T>
|
||||
Component Slider(SliderOption<T> options);
|
||||
|
||||
// Shorthand without the `SliderOption` constructor:
|
||||
Component Slider(ConstStringRef label,
|
||||
Ref<int> value,
|
||||
ConstRef<int> min = 0,
|
||||
ConstRef<int> max = 100,
|
||||
ConstRef<int> increment = 5);
|
||||
Component Slider(ConstStringRef label,
|
||||
Ref<float> value,
|
||||
ConstRef<float> min = 0.f,
|
||||
ConstRef<float> max = 100.f,
|
||||
ConstRef<float> increment = 5.f);
|
||||
Component Slider(ConstStringRef label,
|
||||
Ref<long> value,
|
||||
ConstRef<long> min = 0L,
|
||||
ConstRef<long> max = 100L,
|
||||
ConstRef<long> increment = 5L);
|
||||
|
||||
Component ResizableSplit(ResizableSplitOption options);
|
||||
Component ResizableSplitLeft(Component main, Component back, int* main_size);
|
||||
Component ResizableSplitRight(Component main, Component back, int* main_size);
|
||||
Component ResizableSplitTop(Component main, Component back, int* main_size);
|
||||
Component ResizableSplitBottom(Component main, Component back, int* main_size);
|
||||
|
||||
Component Renderer(Component child, std::function<Element()>);
|
||||
Component Renderer(std::function<Element()>);
|
||||
Component Renderer(std::function<Element(bool /* focused */)>);
|
||||
ComponentDecorator Renderer(ElementDecorator);
|
||||
|
||||
Component CatchEvent(Component child, std::function<bool(Event)>);
|
||||
ComponentDecorator CatchEvent(std::function<bool(Event)> on_event);
|
||||
|
||||
Component Maybe(Component, const bool* show);
|
||||
Component Maybe(Component, std::function<bool()>);
|
||||
ComponentDecorator Maybe(const bool* show);
|
||||
ComponentDecorator Maybe(std::function<bool()>);
|
||||
|
||||
Component Modal(Component main, Component modal, const bool* show_modal);
|
||||
ComponentDecorator Modal(Component modal, const bool* show_modal);
|
||||
|
||||
Component Collapsible(ConstStringRef label,
|
||||
Component child,
|
||||
Ref<bool> show = false);
|
||||
|
||||
Component Hoverable(Component component, bool* hover);
|
||||
Component Hoverable(Component component,
|
||||
std::function<void()> on_enter,
|
||||
std::function<void()> on_leave);
|
||||
Component Hoverable(Component component, //
|
||||
std::function<void(bool)> on_change);
|
||||
ComponentDecorator Hoverable(bool* hover);
|
||||
ComponentDecorator Hoverable(std::function<void()> on_enter,
|
||||
std::function<void()> on_leave);
|
||||
ComponentDecorator Hoverable(std::function<void(bool)> on_change);
|
||||
|
||||
Component Window(WindowOptions option);
|
||||
|
||||
} // namespace ftxui
|
||||
|
||||
#endif /* end of include guard: FTXUI_COMPONENT_HPP */
|
||||
105
ftxui/include/ftxui/component/component_base.hpp
Normal file
105
ftxui/include/ftxui/component/component_base.hpp
Normal file
@@ -0,0 +1,105 @@
|
||||
// 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.
|
||||
#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;
|
||||
|
||||
namespace animation {
|
||||
class Params;
|
||||
} // namespace animation
|
||||
|
||||
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:
|
||||
explicit ComponentBase(Components children)
|
||||
: children_(std::move(children)) {}
|
||||
virtual ~ComponentBase();
|
||||
ComponentBase() = default;
|
||||
|
||||
// A component is not copyable/movable.
|
||||
ComponentBase(const ComponentBase&) = delete;
|
||||
ComponentBase(ComponentBase&&) = delete;
|
||||
ComponentBase& operator=(const ComponentBase&) = delete;
|
||||
ComponentBase& operator=(ComponentBase&&) = delete;
|
||||
|
||||
// Component hierarchy:
|
||||
ComponentBase* Parent() const;
|
||||
Component& ChildAt(size_t i);
|
||||
size_t ChildCount() const;
|
||||
int Index() const;
|
||||
void Add(Component children);
|
||||
void Detach();
|
||||
void DetachAllChildren();
|
||||
|
||||
// Renders the component.
|
||||
Element Render();
|
||||
|
||||
// Override this function modify how `Render` works.
|
||||
virtual Element OnRender();
|
||||
|
||||
// Handles an event.
|
||||
// By default, reduce on children with a lazy OR.
|
||||
//
|
||||
// Returns whether the event was handled or not.
|
||||
virtual bool OnEvent(Event);
|
||||
|
||||
// Handle an animation step.
|
||||
virtual void OnAnimation(animation::Params& params);
|
||||
|
||||
// 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();
|
||||
|
||||
// Return true when the component contains focusable elements.
|
||||
// The non focusable Component will be skipped when navigating using the
|
||||
// keyboard.
|
||||
virtual bool Focusable() const;
|
||||
|
||||
// Whether this is the active child of its parent.
|
||||
bool Active() const;
|
||||
// Whether all the ancestors are active.
|
||||
bool Focused() const;
|
||||
|
||||
// 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);
|
||||
|
||||
Components children_;
|
||||
|
||||
private:
|
||||
ComponentBase* parent_ = nullptr;
|
||||
bool in_render = false;
|
||||
};
|
||||
|
||||
} // namespace ftxui
|
||||
|
||||
#endif /* end of include guard: FTXUI_COMPONENT_BASE_HPP */
|
||||
287
ftxui/include/ftxui/component/component_options.hpp
Normal file
287
ftxui/include/ftxui/component/component_options.hpp
Normal file
@@ -0,0 +1,287 @@
|
||||
// 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.
|
||||
#ifndef FTXUI_COMPONENT_COMPONENT_OPTIONS_HPP
|
||||
#define FTXUI_COMPONENT_COMPONENT_OPTIONS_HPP
|
||||
|
||||
#include <chrono> // for milliseconds
|
||||
#include <ftxui/component/animation.hpp> // for Duration, QuadraticInOut, Function
|
||||
#include <ftxui/dom/direction.hpp> // for Direction, Direction::Left, Direction::Right, Direction::Down
|
||||
#include <ftxui/dom/elements.hpp> // for Element, separator
|
||||
#include <ftxui/util/ref.hpp> // for Ref, ConstRef, StringRef
|
||||
#include <ftxui/util/warn_windows_macro.hpp>
|
||||
#include <functional> // for function
|
||||
#include <string> // for string
|
||||
|
||||
#include "ftxui/component/component_base.hpp" // for Component
|
||||
#include "ftxui/screen/color.hpp" // for Color, Color::GrayDark, Color::White
|
||||
|
||||
namespace ftxui {
|
||||
|
||||
/// @brief arguments for transform from |ButtonOption|, |CheckboxOption|,
|
||||
/// |RadioboxOption|, |MenuEntryOption|, |MenuOption|.
|
||||
struct EntryState {
|
||||
std::string label; ///< The label to display.
|
||||
bool state; ///< The state of the button/checkbox/radiobox
|
||||
bool active; ///< Whether the entry is the active one.
|
||||
bool focused; ///< Whether the entry is one focused by the user.
|
||||
int index; ///< Index of the entry when applicable or -1.
|
||||
};
|
||||
|
||||
/// @brief Option for the underline effect.
|
||||
/// @ingroup component
|
||||
struct UnderlineOption {
|
||||
bool enabled = false;
|
||||
|
||||
Color color_active = Color::White;
|
||||
Color color_inactive = Color::GrayDark;
|
||||
|
||||
animation::easing::Function leader_function =
|
||||
animation::easing::QuadraticInOut;
|
||||
animation::easing::Function follower_function =
|
||||
animation::easing::QuadraticInOut;
|
||||
|
||||
animation::Duration leader_duration = std::chrono::milliseconds(250);
|
||||
animation::Duration leader_delay = std::chrono::milliseconds(0);
|
||||
animation::Duration follower_duration = std::chrono::milliseconds(250);
|
||||
animation::Duration follower_delay = std::chrono::milliseconds(0);
|
||||
|
||||
void SetAnimation(animation::Duration d, animation::easing::Function f);
|
||||
void SetAnimationDuration(animation::Duration d);
|
||||
void SetAnimationFunction(animation::easing::Function f);
|
||||
void SetAnimationFunction(animation::easing::Function f_leader,
|
||||
animation::easing::Function f_follower);
|
||||
};
|
||||
|
||||
/// @brief Option about a potentially animated color.
|
||||
/// @ingroup component
|
||||
struct AnimatedColorOption {
|
||||
void Set(
|
||||
Color inactive,
|
||||
Color active,
|
||||
animation::Duration duration = std::chrono::milliseconds(250),
|
||||
animation::easing::Function function = animation::easing::QuadraticInOut);
|
||||
|
||||
bool enabled = false;
|
||||
Color inactive;
|
||||
Color active;
|
||||
animation::Duration duration = std::chrono::milliseconds(250);
|
||||
animation::easing::Function function = animation::easing::QuadraticInOut;
|
||||
};
|
||||
|
||||
struct AnimatedColorsOption {
|
||||
AnimatedColorOption background;
|
||||
AnimatedColorOption foreground;
|
||||
};
|
||||
|
||||
/// @brief Option for the MenuEntry component.
|
||||
/// @ingroup component
|
||||
struct MenuEntryOption {
|
||||
ConstStringRef label = "MenuEntry";
|
||||
std::function<Element(const EntryState& state)> transform;
|
||||
AnimatedColorsOption animated_colors;
|
||||
};
|
||||
|
||||
/// @brief Option for the Menu component.
|
||||
/// @ingroup component
|
||||
struct MenuOption {
|
||||
// Standard constructors:
|
||||
static MenuOption Horizontal();
|
||||
static MenuOption HorizontalAnimated();
|
||||
static MenuOption Vertical();
|
||||
static MenuOption VerticalAnimated();
|
||||
static MenuOption Toggle();
|
||||
|
||||
ConstStringListRef entries; ///> The list of entries.
|
||||
Ref<int> selected = 0; ///> The index of the selected entry.
|
||||
|
||||
// Style:
|
||||
UnderlineOption underline;
|
||||
MenuEntryOption entries_option;
|
||||
Direction direction = Direction::Down;
|
||||
std::function<Element()> elements_prefix;
|
||||
std::function<Element()> elements_infix;
|
||||
std::function<Element()> elements_postfix;
|
||||
|
||||
// Observers:
|
||||
std::function<void()> on_change; ///> Called when the selected entry changes.
|
||||
std::function<void()> on_enter; ///> Called when the user presses enter.
|
||||
Ref<int> focused_entry = 0;
|
||||
};
|
||||
|
||||
/// @brief Option for the AnimatedButton component.
|
||||
/// @ingroup component
|
||||
struct ButtonOption {
|
||||
// Standard constructors:
|
||||
static ButtonOption Ascii();
|
||||
static ButtonOption Simple();
|
||||
static ButtonOption Border();
|
||||
static ButtonOption Animated();
|
||||
static ButtonOption Animated(Color color);
|
||||
static ButtonOption Animated(Color background, Color foreground);
|
||||
static ButtonOption Animated(Color background,
|
||||
Color foreground,
|
||||
Color background_active,
|
||||
Color foreground_active);
|
||||
|
||||
ConstStringRef label = "Button";
|
||||
std::function<void()> on_click = [] {};
|
||||
|
||||
// Style:
|
||||
std::function<Element(const EntryState&)> transform;
|
||||
AnimatedColorsOption animated_colors;
|
||||
};
|
||||
|
||||
/// @brief Option for the Checkbox component.
|
||||
/// @ingroup component
|
||||
struct CheckboxOption {
|
||||
// Standard constructors:
|
||||
static CheckboxOption Simple();
|
||||
|
||||
ConstStringRef label = "Checkbox";
|
||||
|
||||
Ref<bool> checked = false;
|
||||
|
||||
// Style:
|
||||
std::function<Element(const EntryState&)> transform;
|
||||
|
||||
// Observer:
|
||||
/// Called when the user change the state.
|
||||
std::function<void()> on_change = [] {};
|
||||
};
|
||||
|
||||
/// @brief Used to define style for the Input component.
|
||||
struct InputState {
|
||||
Element element;
|
||||
bool hovered; ///< Whether the input is hovered by the mouse.
|
||||
bool focused; ///< Whether the input is focused by the user.
|
||||
bool is_placeholder; ///< Whether the input is empty and displaying the
|
||||
///< placeholder.
|
||||
};
|
||||
|
||||
/// @brief Option for the Input component.
|
||||
/// @ingroup component
|
||||
struct InputOption {
|
||||
// A set of predefined styles:
|
||||
|
||||
/// @brief Create the default input style:
|
||||
static InputOption Default();
|
||||
/// @brief A white on black style with high margins:
|
||||
static InputOption Spacious();
|
||||
|
||||
/// The content of the input.
|
||||
StringRef content = "";
|
||||
|
||||
/// The content of the input when it's empty.
|
||||
StringRef placeholder = "";
|
||||
|
||||
// Style:
|
||||
std::function<Element(InputState)> transform;
|
||||
Ref<bool> password = false; ///< Obscure the input content using '*'.
|
||||
Ref<bool> multiline = true; ///< Whether the input can be multiline.
|
||||
Ref<bool> insert = true; ///< Insert or overtype character mode.
|
||||
|
||||
/// Called when the content changes.
|
||||
std::function<void()> on_change = [] {};
|
||||
/// Called when the user presses enter.
|
||||
std::function<void()> on_enter = [] {};
|
||||
|
||||
// The char position of the cursor:
|
||||
Ref<int> cursor_position = 0;
|
||||
};
|
||||
|
||||
/// @brief Option for the Radiobox component.
|
||||
/// @ingroup component
|
||||
struct RadioboxOption {
|
||||
// Standard constructors:
|
||||
static RadioboxOption Simple();
|
||||
|
||||
// Content:
|
||||
ConstStringListRef entries;
|
||||
Ref<int> selected = 0;
|
||||
|
||||
// Style:
|
||||
std::function<Element(const EntryState&)> transform;
|
||||
|
||||
// Observers:
|
||||
/// Called when the selected entry changes.
|
||||
std::function<void()> on_change = [] {};
|
||||
Ref<int> focused_entry = 0;
|
||||
};
|
||||
|
||||
struct ResizableSplitOption {
|
||||
Component main;
|
||||
Component back;
|
||||
Ref<Direction> direction = Direction::Left;
|
||||
Ref<int> main_size =
|
||||
(direction() == Direction::Left || direction() == Direction::Right) ? 20
|
||||
: 10;
|
||||
std::function<Element()> separator_func = [] { return ::ftxui::separator(); };
|
||||
};
|
||||
|
||||
// @brief Option for the `Slider` component.
|
||||
// @ingroup component
|
||||
template <typename T>
|
||||
struct SliderOption {
|
||||
Ref<T> value;
|
||||
ConstRef<T> min = T(0);
|
||||
ConstRef<T> max = T(100);
|
||||
ConstRef<T> increment = (max() - min()) / 20;
|
||||
Direction direction = Direction::Right;
|
||||
Color color_active = Color::White;
|
||||
Color color_inactive = Color::GrayDark;
|
||||
std::function<void()> on_change; ///> Called when `value` is updated.
|
||||
};
|
||||
|
||||
/// @brief State passed to the `Window` component's render function.
|
||||
/// @ingroup component
|
||||
struct WindowRenderState {
|
||||
Element inner; ///< The element wrapped inside this window.
|
||||
const std::string& title; ///< The title of the window.
|
||||
bool active = false; ///< Whether the window is the active one.
|
||||
bool drag = false; ///< Whether the window is being dragged.
|
||||
bool resize = false; ///< Whether the window is being resized.
|
||||
bool hover_left = false; ///< Whether the resizeable left side is hovered.
|
||||
bool hover_right = false; ///< Whether the resizeable right side is hovered.
|
||||
bool hover_top = false; ///< Whether the resizeable top side is hovered.
|
||||
bool hover_down = false; ///< Whether the resizeable down side is hovered.
|
||||
};
|
||||
|
||||
// @brief Option for the `Window` component.
|
||||
// @ingroup component
|
||||
struct WindowOptions {
|
||||
Component inner; ///< The component wrapped by this window.
|
||||
ConstStringRef title = ""; ///< The title displayed by this window.
|
||||
|
||||
Ref<int> left = 0; ///< The left side position of the window.
|
||||
Ref<int> top = 0; ///< The top side position of the window.
|
||||
Ref<int> width = 20; ///< The width of the window.
|
||||
Ref<int> height = 10; ///< The height of the window.
|
||||
|
||||
Ref<bool> resize_left = true; ///< Can the left side be resized?
|
||||
Ref<bool> resize_right = true; ///< Can the right side be resized?
|
||||
Ref<bool> resize_top = true; ///< Can the top side be resized?
|
||||
Ref<bool> resize_down = true; ///< Can the down side be resized?
|
||||
|
||||
/// An optional function to customize how the window looks like:
|
||||
std::function<Element(const WindowRenderState&)> render;
|
||||
};
|
||||
|
||||
/// @brief Option for the Dropdown component.
|
||||
/// @ingroup component
|
||||
/// A dropdown menu is a checkbox opening/closing a radiobox.
|
||||
struct DropdownOption {
|
||||
/// Whether the dropdown is open or closed:
|
||||
Ref<bool> open = false;
|
||||
// The options for the checkbox:
|
||||
CheckboxOption checkbox;
|
||||
// The options for the radiobox:
|
||||
RadioboxOption radiobox;
|
||||
// The transformation function:
|
||||
std::function<Element(bool open, Element checkbox, Element radiobox)>
|
||||
transform;
|
||||
};
|
||||
|
||||
} // namespace ftxui
|
||||
|
||||
#endif /* end of include guard: FTXUI_COMPONENT_COMPONENT_OPTIONS_HPP */
|
||||
154
ftxui/include/ftxui/component/event.hpp
Normal file
154
ftxui/include/ftxui/component/event.hpp
Normal file
@@ -0,0 +1,154 @@
|
||||
// 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.
|
||||
#ifndef FTXUI_COMPONENT_EVENT_HPP
|
||||
#define FTXUI_COMPONENT_EVENT_HPP
|
||||
|
||||
#include <ftxui/component/mouse.hpp> // for Mouse
|
||||
#include <string> // for string, operator==
|
||||
|
||||
namespace ftxui {
|
||||
|
||||
class ScreenInteractive;
|
||||
class ComponentBase;
|
||||
|
||||
/// @brief Represent an event. It can be key press event, a terminal resize, or
|
||||
/// more ...
|
||||
///
|
||||
/// For example:
|
||||
/// - Printable character can be created using Event::Character('a').
|
||||
/// - Some special are predefined, like Event::ArrowLeft.
|
||||
/// - One can find arbitrary code for special Events using:
|
||||
/// ./example/util/print_key_press
|
||||
/// For instance, CTLR+A maps to Event::Special({1});
|
||||
///
|
||||
/// Useful documentation about xterm specification:
|
||||
/// https://invisible-island.net/xterm/ctlseqs/ctlseqs.html
|
||||
///
|
||||
/// @ingroup component
|
||||
struct Event {
|
||||
// --- Constructor section ---------------------------------------------------
|
||||
static Event Character(std::string);
|
||||
static Event Character(char);
|
||||
static Event Character(wchar_t);
|
||||
static Event Special(std::string);
|
||||
static Event Mouse(std::string, Mouse mouse);
|
||||
static Event CursorPosition(std::string, int x, int y); // Internal
|
||||
static Event CursorShape(std::string, int shape); // Internal
|
||||
|
||||
// --- Arrow ---
|
||||
static const Event ArrowLeft;
|
||||
static const Event ArrowRight;
|
||||
static const Event ArrowUp;
|
||||
static const Event ArrowDown;
|
||||
|
||||
static const Event ArrowLeftCtrl;
|
||||
static const Event ArrowRightCtrl;
|
||||
static const Event ArrowUpCtrl;
|
||||
static const Event ArrowDownCtrl;
|
||||
|
||||
// --- Other ---
|
||||
static const Event Backspace;
|
||||
static const Event Delete;
|
||||
static const Event Return;
|
||||
static const Event Escape;
|
||||
static const Event Tab;
|
||||
static const Event TabReverse;
|
||||
|
||||
// --- Navigation keys ---
|
||||
static const Event Insert;
|
||||
static const Event Home;
|
||||
static const Event End;
|
||||
static const Event PageUp;
|
||||
static const Event PageDown;
|
||||
|
||||
// --- Function keys ---
|
||||
static const Event F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12;
|
||||
|
||||
// --- Control keys ---
|
||||
static const Event a, A, CtrlA, AltA, CtrlAltA;
|
||||
static const Event b, B, CtrlB, AltB, CtrlAltB;
|
||||
static const Event c, C, CtrlC, AltC, CtrlAltC;
|
||||
static const Event d, D, CtrlD, AltD, CtrlAltD;
|
||||
static const Event e, E, CtrlE, AltE, CtrlAltE;
|
||||
static const Event f, F, CtrlF, AltF, CtrlAltF;
|
||||
static const Event g, G, CtrlG, AltG, CtrlAltG;
|
||||
static const Event h, H, CtrlH, AltH, CtrlAltH;
|
||||
static const Event i, I, CtrlI, AltI, CtrlAltI;
|
||||
static const Event j, J, CtrlJ, AltJ, CtrlAltJ;
|
||||
static const Event k, K, CtrlK, AltK, CtrlAltK;
|
||||
static const Event l, L, CtrlL, AltL, CtrlAltL;
|
||||
static const Event m, M, CtrlM, AltM, CtrlAltM;
|
||||
static const Event n, N, CtrlN, AltN, CtrlAltN;
|
||||
static const Event o, O, CtrlO, AltO, CtrlAltO;
|
||||
static const Event p, P, CtrlP, AltP, CtrlAltP;
|
||||
static const Event q, Q, CtrlQ, AltQ, CtrlAltQ;
|
||||
static const Event r, R, CtrlR, AltR, CtrlAltR;
|
||||
static const Event s, S, CtrlS, AltS, CtrlAltS;
|
||||
static const Event t, T, CtrlT, AltT, CtrlAltT;
|
||||
static const Event u, U, CtrlU, AltU, CtrlAltU;
|
||||
static const Event v, V, CtrlV, AltV, CtrlAltV;
|
||||
static const Event w, W, CtrlW, AltW, CtrlAltW;
|
||||
static const Event x, X, CtrlX, AltX, CtrlAltX;
|
||||
static const Event y, Y, CtrlY, AltY, CtrlAltY;
|
||||
static const Event z, Z, CtrlZ, AltZ, CtrlAltZ;
|
||||
|
||||
// --- Custom ---
|
||||
static const Event Custom;
|
||||
|
||||
//--- Method section ---------------------------------------------------------
|
||||
bool operator==(const Event& other) const { return input_ == other.input_; }
|
||||
bool operator!=(const Event& other) const { return !operator==(other); }
|
||||
bool operator<(const Event& other) const { return input_ < other.input_; }
|
||||
|
||||
const std::string& input() const { return input_; }
|
||||
|
||||
bool is_character() const { return type_ == Type::Character; }
|
||||
std::string character() const { return input_; }
|
||||
|
||||
bool is_mouse() const { return type_ == Type::Mouse; }
|
||||
struct Mouse& mouse() { return data_.mouse; }
|
||||
|
||||
// --- Internal Method section -----------------------------------------------
|
||||
bool is_cursor_position() const { return type_ == Type::CursorPosition; }
|
||||
int cursor_x() const { return data_.cursor.x; }
|
||||
int cursor_y() const { return data_.cursor.y; }
|
||||
|
||||
bool is_cursor_shape() const { return type_ == Type::CursorShape; }
|
||||
int cursor_shape() const { return data_.cursor_shape; }
|
||||
|
||||
// Debug
|
||||
std::string DebugString() const;
|
||||
|
||||
//--- State section ----------------------------------------------------------
|
||||
ScreenInteractive* screen_ = nullptr;
|
||||
|
||||
private:
|
||||
friend ComponentBase;
|
||||
friend ScreenInteractive;
|
||||
enum class Type {
|
||||
Unknown,
|
||||
Character,
|
||||
Mouse,
|
||||
CursorPosition,
|
||||
CursorShape,
|
||||
};
|
||||
Type type_ = Type::Unknown;
|
||||
|
||||
struct Cursor {
|
||||
int x = 0;
|
||||
int y = 0;
|
||||
};
|
||||
|
||||
union {
|
||||
struct Mouse mouse;
|
||||
struct Cursor cursor;
|
||||
int cursor_shape;
|
||||
} data_ = {};
|
||||
|
||||
std::string input_;
|
||||
};
|
||||
|
||||
} // namespace ftxui
|
||||
|
||||
#endif /* end of include guard: FTXUI_COMPONENT_EVENT_HPP */
|
||||
80
ftxui/include/ftxui/component/loop.hpp
Normal file
80
ftxui/include/ftxui/component/loop.hpp
Normal file
@@ -0,0 +1,80 @@
|
||||
// Copyright 2022 Arthur Sonzogni. All rights reserved.
|
||||
// Use of this source code is governed by the MIT license that can be found in
|
||||
// the LICENSE file.
|
||||
#ifndef FTXUI_COMPONENT_LOOP_HPP
|
||||
#define FTXUI_COMPONENT_LOOP_HPP
|
||||
|
||||
#include <memory> // for shared_ptr
|
||||
|
||||
#include "ftxui/component/component_base.hpp" // for ComponentBase
|
||||
|
||||
namespace ftxui {
|
||||
class ComponentBase;
|
||||
|
||||
using Component = std::shared_ptr<ComponentBase>;
|
||||
class ScreenInteractive;
|
||||
|
||||
/// @brief Loop is a class that manages the event loop for a component.
|
||||
///
|
||||
/// It is responsible for running the component, handling events, and
|
||||
/// updating the screen.
|
||||
///
|
||||
/// The Loop class is designed to be used with a ScreenInteractive object,
|
||||
/// which represents the terminal screen.
|
||||
///
|
||||
/// **Example**
|
||||
/// ```cpp
|
||||
/// #include <ftxui/component/component.hpp>
|
||||
/// #include <ftxui/component/screen_interactive.hpp>
|
||||
/// #include <ftxui/component/loop.hpp>
|
||||
///
|
||||
/// int main() {
|
||||
/// auto screen = ftxui::ScreenInteractive::TerminalOutput();
|
||||
/// auto component = ftxui::Button("Click me", [] { ... });
|
||||
///
|
||||
/// ftxui::Loop loop(screen.get(), component);
|
||||
///
|
||||
/// // Either
|
||||
/// loop.Run(); // Blocking until the component quits.
|
||||
///
|
||||
/// // Or
|
||||
/// loop.RunOnce(); // Non-blocking, returns immediately.
|
||||
///
|
||||
/// // Or
|
||||
/// loop.RunOnceBlocking(); // Blocking until handling one event.
|
||||
///
|
||||
/// // Or in a loop:
|
||||
/// while (!loop.HasQuitted()) {
|
||||
/// loop.RunOnce();
|
||||
///
|
||||
/// // Do something else like running a different library loop function.
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// @ingroup component
|
||||
class Loop {
|
||||
public:
|
||||
Loop(ScreenInteractive* screen, Component component);
|
||||
~Loop();
|
||||
|
||||
bool HasQuitted();
|
||||
void RunOnce();
|
||||
void RunOnceBlocking();
|
||||
void Run();
|
||||
|
||||
// This class is non copyable/movable.
|
||||
Loop(const Loop&) = default;
|
||||
Loop(Loop&&) = delete;
|
||||
Loop& operator=(Loop&&) = delete;
|
||||
Loop(const ScreenInteractive&) = delete;
|
||||
Loop& operator=(const Loop&) = delete;
|
||||
|
||||
private:
|
||||
ScreenInteractive* screen_;
|
||||
Component component_;
|
||||
};
|
||||
|
||||
} // namespace ftxui
|
||||
|
||||
#endif // FTXUI_COMPONENT_LOOP_HPP
|
||||
47
ftxui/include/ftxui/component/mouse.hpp
Normal file
47
ftxui/include/ftxui/component/mouse.hpp
Normal file
@@ -0,0 +1,47 @@
|
||||
// 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.
|
||||
#ifndef FTXUI_COMPONENT_MOUSE_HPP
|
||||
#define FTXUI_COMPONENT_MOUSE_HPP
|
||||
namespace ftxui {
|
||||
|
||||
/// @brief A mouse event. It contains the coordinate of the mouse, the button
|
||||
/// pressed and the modifier (shift, ctrl, meta).
|
||||
/// @ingroup component
|
||||
struct Mouse {
|
||||
enum Button {
|
||||
Left = 0,
|
||||
Middle = 1,
|
||||
Right = 2,
|
||||
None = 3,
|
||||
WheelUp = 4,
|
||||
WheelDown = 5,
|
||||
WheelLeft = 6, /// Supported terminal only.
|
||||
WheelRight = 7, /// Supported terminal only.
|
||||
};
|
||||
|
||||
enum Motion {
|
||||
Released = 0,
|
||||
Pressed = 1,
|
||||
Moved = 2,
|
||||
};
|
||||
|
||||
// Button
|
||||
Button button = Button::None;
|
||||
|
||||
// Motion
|
||||
Motion motion = Motion::Pressed;
|
||||
|
||||
// Modifiers:
|
||||
bool shift = false;
|
||||
bool meta = false;
|
||||
bool control = false;
|
||||
|
||||
// Coordinates:
|
||||
int x = 0;
|
||||
int y = 0;
|
||||
};
|
||||
|
||||
} // namespace ftxui
|
||||
|
||||
#endif /* end of include guard: FTXUI_COMPONENT_MOUSE_HPP */
|
||||
155
ftxui/include/ftxui/component/receiver.hpp
Normal file
155
ftxui/include/ftxui/component/receiver.hpp
Normal file
@@ -0,0 +1,155 @@
|
||||
// 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.
|
||||
#ifndef FTXUI_COMPONENT_RECEIVER_HPP_
|
||||
#define FTXUI_COMPONENT_RECEIVER_HPP_
|
||||
|
||||
#include <algorithm> // for copy, max
|
||||
#include <atomic> // for atomic, __atomic_base
|
||||
#include <condition_variable> // for condition_variable
|
||||
#include <ftxui/util/warn_windows_macro.hpp>
|
||||
#include <memory> // for unique_ptr, make_unique
|
||||
#include <mutex> // for mutex, unique_lock
|
||||
#include <queue> // for queue
|
||||
#include <utility> // for move
|
||||
|
||||
namespace ftxui {
|
||||
|
||||
// Deprecated
|
||||
//
|
||||
// Usage:
|
||||
//
|
||||
// Initialization:
|
||||
// ---------------
|
||||
//
|
||||
// auto receiver = MakeReceiver<std:string>();
|
||||
// auto sender_1= receiver->MakeSender();
|
||||
// auto sender_2 = receiver->MakeSender();
|
||||
//
|
||||
// Then move the senders elsewhere, potentially in a different thread.
|
||||
//
|
||||
// On the producer side:
|
||||
// ----------------------
|
||||
// [thread 1] sender_1->Send("hello");
|
||||
// [thread 2] sender_2->Send("world");
|
||||
//
|
||||
// On the consumer side:
|
||||
// ---------------------
|
||||
// char c;
|
||||
// while(receiver->Receive(&c)) // Return true as long as there is a producer.
|
||||
// print(c)
|
||||
//
|
||||
// Receiver::Receive() returns true when there are no more senders.
|
||||
|
||||
// clang-format off
|
||||
// Deprecated:
|
||||
template<class T> class SenderImpl;
|
||||
// Deprecated:
|
||||
template<class T> class ReceiverImpl;
|
||||
// Deprecated:
|
||||
|
||||
// Deprecated:
|
||||
template<class T> using Sender = std::unique_ptr<SenderImpl<T>>;
|
||||
// Deprecated:
|
||||
template<class T> using Receiver = std::unique_ptr<ReceiverImpl<T>>;
|
||||
// Deprecated:
|
||||
template<class T> Receiver<T> MakeReceiver();
|
||||
// clang-format on
|
||||
|
||||
// ---- Implementation part ----
|
||||
|
||||
template <class T>
|
||||
// Deprecated:
|
||||
class SenderImpl {
|
||||
public:
|
||||
SenderImpl(const SenderImpl&) = delete;
|
||||
SenderImpl(SenderImpl&&) = delete;
|
||||
SenderImpl& operator=(const SenderImpl&) = delete;
|
||||
SenderImpl& operator=(SenderImpl&&) = delete;
|
||||
void Send(T t) { receiver_->Receive(std::move(t)); }
|
||||
~SenderImpl() { receiver_->ReleaseSender(); }
|
||||
|
||||
Sender<T> Clone() { return receiver_->MakeSender(); }
|
||||
|
||||
private:
|
||||
friend class ReceiverImpl<T>;
|
||||
explicit SenderImpl(ReceiverImpl<T>* consumer) : receiver_(consumer) {}
|
||||
ReceiverImpl<T>* receiver_;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
class ReceiverImpl {
|
||||
public:
|
||||
Sender<T> MakeSender() {
|
||||
std::unique_lock<std::mutex> lock(mutex_);
|
||||
senders_++;
|
||||
return std::unique_ptr<SenderImpl<T>>(new SenderImpl<T>(this));
|
||||
}
|
||||
ReceiverImpl() = default;
|
||||
|
||||
bool Receive(T* t) {
|
||||
while (senders_ || !queue_.empty()) {
|
||||
std::unique_lock<std::mutex> lock(mutex_);
|
||||
if (queue_.empty()) {
|
||||
notifier_.wait(lock);
|
||||
}
|
||||
if (queue_.empty()) {
|
||||
continue;
|
||||
}
|
||||
*t = std::move(queue_.front());
|
||||
queue_.pop();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ReceiveNonBlocking(T* t) {
|
||||
std::unique_lock<std::mutex> lock(mutex_);
|
||||
if (queue_.empty()) {
|
||||
return false;
|
||||
}
|
||||
*t = queue_.front();
|
||||
queue_.pop();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool HasPending() {
|
||||
std::unique_lock<std::mutex> lock(mutex_);
|
||||
return !queue_.empty();
|
||||
}
|
||||
|
||||
bool HasQuitted() {
|
||||
std::unique_lock<std::mutex> lock(mutex_);
|
||||
return queue_.empty() && !senders_;
|
||||
}
|
||||
|
||||
private:
|
||||
friend class SenderImpl<T>;
|
||||
|
||||
void Receive(T t) {
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(mutex_);
|
||||
queue_.push(std::move(t));
|
||||
}
|
||||
notifier_.notify_one();
|
||||
}
|
||||
|
||||
void ReleaseSender() {
|
||||
senders_--;
|
||||
notifier_.notify_one();
|
||||
}
|
||||
|
||||
std::mutex mutex_;
|
||||
std::queue<T> queue_;
|
||||
std::condition_variable notifier_;
|
||||
std::atomic<int> senders_{0};
|
||||
};
|
||||
|
||||
template <class T>
|
||||
Receiver<T> MakeReceiver() {
|
||||
return std::make_unique<ReceiverImpl<T>>();
|
||||
}
|
||||
|
||||
} // namespace ftxui
|
||||
|
||||
#endif // FTXUI_COMPONENT_RECEIVER_HPP_
|
||||
181
ftxui/include/ftxui/component/screen_interactive.hpp
Normal file
181
ftxui/include/ftxui/component/screen_interactive.hpp
Normal file
@@ -0,0 +1,181 @@
|
||||
// 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.
|
||||
#ifndef FTXUI_COMPONENT_SCREEN_INTERACTIVE_HPP
|
||||
#define FTXUI_COMPONENT_SCREEN_INTERACTIVE_HPP
|
||||
|
||||
#include <atomic> // for atomic
|
||||
#include <functional> // for function
|
||||
#include <memory> // for shared_ptr
|
||||
#include <string> // for string
|
||||
|
||||
#include "ftxui/component/animation.hpp" // for TimePoint
|
||||
#include "ftxui/component/captured_mouse.hpp" // for CapturedMouse
|
||||
#include "ftxui/component/event.hpp" // for Event
|
||||
#include "ftxui/component/task.hpp" // for Task, Closure
|
||||
#include "ftxui/dom/selection.hpp" // for SelectionOption
|
||||
#include "ftxui/screen/screen.hpp" // for Screen
|
||||
|
||||
namespace ftxui {
|
||||
class ComponentBase;
|
||||
class Loop;
|
||||
struct Event;
|
||||
|
||||
using Component = std::shared_ptr<ComponentBase>;
|
||||
class ScreenInteractivePrivate;
|
||||
|
||||
namespace task {
|
||||
class TaskRunner;
|
||||
}
|
||||
|
||||
/// @brief ScreenInteractive is a `Screen` that can handle events, run a main
|
||||
/// loop, and manage components.
|
||||
///
|
||||
/// @ingroup component
|
||||
class ScreenInteractive : public Screen {
|
||||
public:
|
||||
// Constructors:
|
||||
static ScreenInteractive FixedSize(int dimx, int dimy);
|
||||
static ScreenInteractive Fullscreen();
|
||||
static ScreenInteractive FullscreenPrimaryScreen();
|
||||
static ScreenInteractive FullscreenAlternateScreen();
|
||||
static ScreenInteractive FitComponent();
|
||||
static ScreenInteractive TerminalOutput();
|
||||
|
||||
// Destructor.
|
||||
~ScreenInteractive();
|
||||
|
||||
// Options. Must be called before Loop().
|
||||
void TrackMouse(bool enable = true);
|
||||
|
||||
// Return the currently active screen, nullptr if none.
|
||||
static ScreenInteractive* Active();
|
||||
|
||||
// Start/Stop the main loop.
|
||||
void Loop(Component);
|
||||
void Exit();
|
||||
Closure ExitLoopClosure();
|
||||
|
||||
// Post tasks to be executed by the loop.
|
||||
void Post(Task task);
|
||||
void PostEvent(Event event);
|
||||
void RequestAnimationFrame();
|
||||
|
||||
CapturedMouse CaptureMouse();
|
||||
|
||||
// Decorate a function. The outputted one will execute similarly to the
|
||||
// inputted one, but with the currently active screen terminal hooks
|
||||
// temporarily uninstalled.
|
||||
Closure WithRestoredIO(Closure);
|
||||
|
||||
// FTXUI implements handlers for Ctrl-C and Ctrl-Z. By default, these handlers
|
||||
// are executed, even if the component catches the event. This avoid users
|
||||
// handling every event to be trapped in the application. However, in some
|
||||
// cases, the application may want to handle these events itself. In this
|
||||
// case, the application can force FTXUI to not handle these events by calling
|
||||
// the following functions with force=true.
|
||||
void ForceHandleCtrlC(bool force);
|
||||
void ForceHandleCtrlZ(bool force);
|
||||
|
||||
// Selection API.
|
||||
std::string GetSelection();
|
||||
void SelectionChange(std::function<void()> callback);
|
||||
|
||||
private:
|
||||
void ExitNow();
|
||||
|
||||
void Install();
|
||||
void Uninstall();
|
||||
|
||||
void PreMain();
|
||||
void PostMain();
|
||||
|
||||
bool HasQuitted();
|
||||
void RunOnce(Component component);
|
||||
void RunOnceBlocking(Component component);
|
||||
|
||||
void HandleTask(Component component, Task& task);
|
||||
bool HandleSelection(bool handled, Event event);
|
||||
void RefreshSelection();
|
||||
void Draw(Component component);
|
||||
void ResetCursorPosition();
|
||||
|
||||
void Signal(int signal);
|
||||
|
||||
void FetchTerminalEvents();
|
||||
|
||||
void PostAnimationTask();
|
||||
|
||||
ScreenInteractive* suspended_screen_ = nullptr;
|
||||
enum class Dimension {
|
||||
FitComponent,
|
||||
Fixed,
|
||||
Fullscreen,
|
||||
TerminalOutput,
|
||||
};
|
||||
ScreenInteractive(Dimension dimension,
|
||||
int dimx,
|
||||
int dimy,
|
||||
bool use_alternative_screen);
|
||||
const Dimension dimension_;
|
||||
const bool use_alternative_screen_;
|
||||
|
||||
bool track_mouse_ = true;
|
||||
|
||||
std::string set_cursor_position;
|
||||
std::string reset_cursor_position;
|
||||
|
||||
std::atomic<bool> quit_{false};
|
||||
bool animation_requested_ = false;
|
||||
animation::TimePoint previous_animation_time_;
|
||||
|
||||
int cursor_x_ = 1;
|
||||
int cursor_y_ = 1;
|
||||
|
||||
std::uint64_t frame_count_ = 0;
|
||||
bool mouse_captured = false;
|
||||
bool previous_frame_resized_ = false;
|
||||
|
||||
bool frame_valid_ = false;
|
||||
|
||||
bool force_handle_ctrl_c_ = true;
|
||||
bool force_handle_ctrl_z_ = true;
|
||||
|
||||
// The style of the cursor to restore on exit.
|
||||
int cursor_reset_shape_ = 1;
|
||||
|
||||
// Selection API:
|
||||
CapturedMouse selection_pending_;
|
||||
struct SelectionData {
|
||||
int start_x = -1;
|
||||
int start_y = -1;
|
||||
int end_x = -2;
|
||||
int end_y = -2;
|
||||
bool empty = true;
|
||||
bool operator==(const SelectionData& other) const;
|
||||
bool operator!=(const SelectionData& other) const;
|
||||
};
|
||||
SelectionData selection_data_;
|
||||
SelectionData selection_data_previous_;
|
||||
std::unique_ptr<Selection> selection_;
|
||||
std::function<void()> selection_on_change_;
|
||||
|
||||
// PIMPL private implementation idiom (Pimpl).
|
||||
struct Internal;
|
||||
std::unique_ptr<Internal> internal_;
|
||||
|
||||
friend class Loop;
|
||||
|
||||
Component component_;
|
||||
|
||||
public:
|
||||
class Private {
|
||||
public:
|
||||
static void Signal(ScreenInteractive& s, int signal) { s.Signal(signal); }
|
||||
};
|
||||
friend Private;
|
||||
};
|
||||
|
||||
} // namespace ftxui
|
||||
|
||||
#endif /* end of include guard: FTXUI_COMPONENT_SCREEN_INTERACTIVE_HPP */
|
||||
17
ftxui/include/ftxui/component/task.hpp
Normal file
17
ftxui/include/ftxui/component/task.hpp
Normal file
@@ -0,0 +1,17 @@
|
||||
// Copyright 2022 Arthur Sonzogni. All rights reserved.
|
||||
// Use of this source code is governed by the MIT license that can be found in
|
||||
// the LICENSE file.
|
||||
#ifndef FTXUI_COMPONENT_ANIMATION_HPP
|
||||
#define FTXUI_COMPONENT_ANIMATION_HPP
|
||||
|
||||
#include <functional>
|
||||
#include <variant>
|
||||
#include "ftxui/component/event.hpp"
|
||||
|
||||
namespace ftxui {
|
||||
class AnimationTask {};
|
||||
using Closure = std::function<void()>;
|
||||
using Task = std::variant<Event, Closure, AnimationTask>;
|
||||
} // namespace ftxui
|
||||
|
||||
#endif // FTXUI_COMPONENT_ANIMATION_HPP
|
||||
162
ftxui/include/ftxui/dom/canvas.hpp
Normal file
162
ftxui/include/ftxui/dom/canvas.hpp
Normal file
@@ -0,0 +1,162 @@
|
||||
// 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.
|
||||
#ifndef FTXUI_DOM_CANVAS_HPP
|
||||
#define FTXUI_DOM_CANVAS_HPP
|
||||
|
||||
#include <cstddef> // for size_t
|
||||
#include <functional> // for function
|
||||
#include <string> // for string
|
||||
#include <unordered_map> // for unordered_map
|
||||
|
||||
#include "ftxui/screen/color.hpp" // for Color
|
||||
#include "ftxui/screen/image.hpp" // for Pixel, Image
|
||||
|
||||
#ifdef DrawText
|
||||
// Workaround for WinUsr.h (via Windows.h) defining macros that break things.
|
||||
// https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-drawtext
|
||||
#undef DrawText
|
||||
#endif
|
||||
|
||||
namespace ftxui {
|
||||
|
||||
/// @brief Canvas is a drawable buffer associated with drawing operations.
|
||||
///
|
||||
/// Canvas is a drawable area that can be used to create complex graphics. It
|
||||
/// supports drawing points, lines, circles, ellipses, text, and images using
|
||||
/// braille, block, or normal characters.
|
||||
///
|
||||
/// Note: A terminal contains cells. A cells is a unit of:
|
||||
/// - 2x4 braille characters (1x1 pixel)
|
||||
/// - 2x2 block characters (2x2 pixels)
|
||||
/// - 2x4 normal characters (2x4 pixels)
|
||||
///
|
||||
/// You need to multiply the x coordinate by 2 and the y coordinate by 4 to
|
||||
/// get the correct position in the terminal.
|
||||
///
|
||||
/// @ingroup dom
|
||||
struct Canvas {
|
||||
public:
|
||||
Canvas() = default;
|
||||
Canvas(int width, int height);
|
||||
|
||||
// Getters:
|
||||
int width() const { return width_; }
|
||||
int height() const { return height_; }
|
||||
Pixel GetPixel(int x, int y) const;
|
||||
|
||||
using Stylizer = std::function<void(Pixel&)>;
|
||||
|
||||
// Draws using braille characters --------------------------------------------
|
||||
void DrawPointOn(int x, int y);
|
||||
void DrawPointOff(int x, int y);
|
||||
void DrawPointToggle(int x, int y);
|
||||
void DrawPoint(int x, int y, bool value);
|
||||
void DrawPoint(int x, int y, bool value, const Stylizer& s);
|
||||
void DrawPoint(int x, int y, bool value, const Color& color);
|
||||
void DrawPointLine(int x1, int y1, int x2, int y2);
|
||||
void DrawPointLine(int x1, int y1, int x2, int y2, const Stylizer& s);
|
||||
void DrawPointLine(int x1, int y1, int x2, int y2, const Color& color);
|
||||
void DrawPointCircle(int x, int y, int radius);
|
||||
void DrawPointCircle(int x, int y, int radius, const Stylizer& s);
|
||||
void DrawPointCircle(int x, int y, int radius, const Color& color);
|
||||
void DrawPointCircleFilled(int x, int y, int radius);
|
||||
void DrawPointCircleFilled(int x, int y, int radius, const Stylizer& s);
|
||||
void DrawPointCircleFilled(int x, int y, int radius, const Color& color);
|
||||
void DrawPointEllipse(int x, int y, int r1, int r2);
|
||||
void DrawPointEllipse(int x, int y, int r1, int r2, const Color& color);
|
||||
void DrawPointEllipse(int x, int y, int r1, int r2, const Stylizer& s);
|
||||
void DrawPointEllipseFilled(int x, int y, int r1, int r2);
|
||||
void DrawPointEllipseFilled(int x, int y, int r1, int r2, const Color& color);
|
||||
void DrawPointEllipseFilled(int x, int y, int r1, int r2, const Stylizer& s);
|
||||
|
||||
// Draw using box characters -------------------------------------------------
|
||||
// Block are of size 1x2. y is considered to be a multiple of 2.
|
||||
void DrawBlockOn(int x, int y);
|
||||
void DrawBlockOff(int x, int y);
|
||||
void DrawBlockToggle(int x, int y);
|
||||
void DrawBlock(int x, int y, bool value);
|
||||
void DrawBlock(int x, int y, bool value, const Stylizer& s);
|
||||
void DrawBlock(int x, int y, bool value, const Color& color);
|
||||
void DrawBlockLine(int x1, int y1, int x2, int y2);
|
||||
void DrawBlockLine(int x1, int y1, int x2, int y2, const Stylizer& s);
|
||||
void DrawBlockLine(int x1, int y1, int x2, int y2, const Color& color);
|
||||
void DrawBlockCircle(int x1, int y1, int radius);
|
||||
void DrawBlockCircle(int x1, int y1, int radius, const Stylizer& s);
|
||||
void DrawBlockCircle(int x1, int y1, int radius, const Color& color);
|
||||
void DrawBlockCircleFilled(int x1, int y1, int radius);
|
||||
void DrawBlockCircleFilled(int x1, int y1, int radius, const Stylizer& s);
|
||||
void DrawBlockCircleFilled(int x1, int y1, int radius, const Color& color);
|
||||
void DrawBlockEllipse(int x1, int y1, int r1, int r2);
|
||||
void DrawBlockEllipse(int x1, int y1, int r1, int r2, const Stylizer& s);
|
||||
void DrawBlockEllipse(int x1, int y1, int r1, int r2, const Color& color);
|
||||
void DrawBlockEllipseFilled(int x1, int y1, int r1, int r2);
|
||||
void DrawBlockEllipseFilled(int x1,
|
||||
int y1,
|
||||
int r1,
|
||||
int r2,
|
||||
const Stylizer& s);
|
||||
void DrawBlockEllipseFilled(int x1,
|
||||
int y1,
|
||||
int r1,
|
||||
int r2,
|
||||
const Color& color);
|
||||
|
||||
// Draw using normal characters ----------------------------------------------
|
||||
// Draw using character of size 2x4 at position (x,y)
|
||||
// x is considered to be a multiple of 2.
|
||||
// y is considered to be a multiple of 4.
|
||||
void DrawText(int x, int y, const std::string& value);
|
||||
void DrawText(int x, int y, const std::string& value, const Color& color);
|
||||
void DrawText(int x, int y, const std::string& value, const Stylizer& style);
|
||||
|
||||
// Draw using directly pixels or images --------------------------------------
|
||||
// x is considered to be a multiple of 2.
|
||||
// y is considered to be a multiple of 4.
|
||||
void DrawPixel(int x, int y, const Pixel&);
|
||||
void DrawImage(int x, int y, const Image&);
|
||||
|
||||
// Decorator:
|
||||
// x is considered to be a multiple of 2.
|
||||
// y is considered to be a multiple of 4.
|
||||
void Style(int x, int y, const Stylizer& style);
|
||||
|
||||
private:
|
||||
bool IsIn(int x, int y) const {
|
||||
return x >= 0 && x < width_ && y >= 0 && y < height_;
|
||||
}
|
||||
|
||||
enum CellType {
|
||||
kCell, // Units of size 2x4
|
||||
kBlock, // Units of size 2x2
|
||||
kBraille, // Units of size 1x1
|
||||
};
|
||||
|
||||
struct Cell {
|
||||
CellType type = kCell;
|
||||
Pixel content;
|
||||
};
|
||||
|
||||
struct XY {
|
||||
int x;
|
||||
int y;
|
||||
bool operator==(const XY& other) const {
|
||||
return x == other.x && y == other.y;
|
||||
}
|
||||
};
|
||||
|
||||
struct XYHash {
|
||||
size_t operator()(const XY& xy) const {
|
||||
constexpr size_t shift = 1024;
|
||||
return size_t(xy.x) * shift + size_t(xy.y);
|
||||
}
|
||||
};
|
||||
|
||||
int width_ = 0;
|
||||
int height_ = 0;
|
||||
std::unordered_map<XY, Cell, XYHash> storage_;
|
||||
};
|
||||
|
||||
} // namespace ftxui
|
||||
|
||||
#endif // FTXUI_DOM_CANVAS_HPP
|
||||
16
ftxui/include/ftxui/dom/deprecated.hpp
Normal file
16
ftxui/include/ftxui/dom/deprecated.hpp
Normal file
@@ -0,0 +1,16 @@
|
||||
// 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.
|
||||
#ifndef FTXUI_DOM_DEPRECATED_HPP
|
||||
#define FTXUI_DOM_DEPRECATED_HPP
|
||||
|
||||
#include <ftxui/dom/node.hpp>
|
||||
#include <string>
|
||||
|
||||
namespace ftxui {
|
||||
Element text(std::wstring text);
|
||||
Element vtext(std::wstring text);
|
||||
Elements paragraph(std::wstring text);
|
||||
} // namespace ftxui
|
||||
|
||||
#endif // FTXUI_DOM_DEPRECATED_HPP
|
||||
22
ftxui/include/ftxui/dom/direction.hpp
Normal file
22
ftxui/include/ftxui/dom/direction.hpp
Normal file
@@ -0,0 +1,22 @@
|
||||
// Copyright 2023 Arthur Sonzogni. All rights reserved.
|
||||
// Use of this source code is governed by the MIT license that can be found in
|
||||
// the LICENSE file.
|
||||
#ifndef FTXUI_DOM_DIRECTION_HPP
|
||||
#define FTXUI_DOM_DIRECTION_HPP
|
||||
|
||||
namespace ftxui {
|
||||
|
||||
/// @brief Direction is an enumeration that represents the four cardinal
|
||||
/// directions.
|
||||
///
|
||||
/// @ingroup dom
|
||||
enum class Direction {
|
||||
Up = 0,
|
||||
Down = 1,
|
||||
Left = 2,
|
||||
Right = 3,
|
||||
};
|
||||
|
||||
} // namespace ftxui
|
||||
|
||||
#endif /* end of include guard: FTXUI_DOM_DIRECTION_HPP */
|
||||
210
ftxui/include/ftxui/dom/elements.hpp
Normal file
210
ftxui/include/ftxui/dom/elements.hpp
Normal file
@@ -0,0 +1,210 @@
|
||||
// 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.
|
||||
#ifndef FTXUI_DOM_ELEMENTS_HPP
|
||||
#define FTXUI_DOM_ELEMENTS_HPP
|
||||
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
|
||||
#include "ftxui/dom/canvas.hpp"
|
||||
#include "ftxui/dom/direction.hpp"
|
||||
#include "ftxui/dom/flexbox_config.hpp"
|
||||
#include "ftxui/dom/linear_gradient.hpp"
|
||||
#include "ftxui/dom/node.hpp"
|
||||
#include "ftxui/screen/box.hpp"
|
||||
#include "ftxui/screen/color.hpp"
|
||||
#include "ftxui/screen/terminal.hpp"
|
||||
#include "ftxui/util/ref.hpp"
|
||||
|
||||
namespace ftxui {
|
||||
class Node;
|
||||
using Element = std::shared_ptr<Node>;
|
||||
using Elements = std::vector<Element>;
|
||||
using Decorator = std::function<Element(Element)>;
|
||||
using GraphFunction = std::function<std::vector<int>(int, int)>;
|
||||
|
||||
/// @brief BorderStyle is an enumeration that represents the different styles
|
||||
/// of borders that can be applied to elements in the terminal UI.
|
||||
///
|
||||
/// BorderStyle is an enumeration that represents the different styles of
|
||||
/// borders that can be applied to elements in the terminal UI.
|
||||
/// It is used to define the visual appearance of borders around elements,
|
||||
/// such as windows, frames, or separators.
|
||||
/// @ingroup dom
|
||||
enum BorderStyle {
|
||||
LIGHT,
|
||||
DASHED,
|
||||
HEAVY,
|
||||
DOUBLE,
|
||||
ROUNDED,
|
||||
EMPTY,
|
||||
};
|
||||
|
||||
// Pipe elements into decorator togethers.
|
||||
// For instance the next lines are equivalents:
|
||||
// -> text("ftxui") | bold | underlined
|
||||
// -> underlined(bold(text("FTXUI")))
|
||||
Element operator|(Element, Decorator);
|
||||
Element& operator|=(Element&, Decorator);
|
||||
Elements operator|(Elements, Decorator);
|
||||
Decorator operator|(Decorator, Decorator);
|
||||
|
||||
// --- Widget ---
|
||||
Element text(std::string text);
|
||||
Element vtext(std::string text);
|
||||
Element separator();
|
||||
Element separatorLight();
|
||||
Element separatorDashed();
|
||||
Element separatorHeavy();
|
||||
Element separatorDouble();
|
||||
Element separatorEmpty();
|
||||
Element separatorStyled(BorderStyle);
|
||||
Element separator(Pixel);
|
||||
Element separatorCharacter(std::string);
|
||||
Element separatorHSelector(float left,
|
||||
float right,
|
||||
Color unselected_color,
|
||||
Color selected_color);
|
||||
Element separatorVSelector(float up,
|
||||
float down,
|
||||
Color unselected_color,
|
||||
Color selected_color);
|
||||
Element gauge(float progress);
|
||||
Element gaugeLeft(float progress);
|
||||
Element gaugeRight(float progress);
|
||||
Element gaugeUp(float progress);
|
||||
Element gaugeDown(float progress);
|
||||
Element gaugeDirection(float progress, Direction direction);
|
||||
Element border(Element);
|
||||
Element borderLight(Element);
|
||||
Element borderDashed(Element);
|
||||
Element borderHeavy(Element);
|
||||
Element borderDouble(Element);
|
||||
Element borderRounded(Element);
|
||||
Element borderEmpty(Element);
|
||||
Decorator borderStyled(BorderStyle);
|
||||
Decorator borderStyled(BorderStyle, Color);
|
||||
Decorator borderStyled(Color);
|
||||
Decorator borderWith(const Pixel&);
|
||||
Element window(Element title, Element content, BorderStyle border = ROUNDED);
|
||||
Element spinner(int charset_index, size_t image_index);
|
||||
Element paragraph(const std::string& text);
|
||||
Element paragraphAlignLeft(const std::string& text);
|
||||
Element paragraphAlignRight(const std::string& text);
|
||||
Element paragraphAlignCenter(const std::string& text);
|
||||
Element paragraphAlignJustify(const std::string& text);
|
||||
Element graph(GraphFunction);
|
||||
Element emptyElement();
|
||||
Element canvas(ConstRef<Canvas>);
|
||||
Element canvas(int width, int height, std::function<void(Canvas&)>);
|
||||
Element canvas(std::function<void(Canvas&)>);
|
||||
|
||||
// -- Decorator ---
|
||||
Element bold(Element);
|
||||
Element dim(Element);
|
||||
Element italic(Element);
|
||||
Element inverted(Element);
|
||||
Element underlined(Element);
|
||||
Element underlinedDouble(Element);
|
||||
Element blink(Element);
|
||||
Element strikethrough(Element);
|
||||
Decorator color(Color);
|
||||
Decorator bgcolor(Color);
|
||||
Decorator color(const LinearGradient&);
|
||||
Decorator bgcolor(const LinearGradient&);
|
||||
Element color(Color, Element);
|
||||
Element bgcolor(Color, Element);
|
||||
Element color(const LinearGradient&, Element);
|
||||
Element bgcolor(const LinearGradient&, Element);
|
||||
Decorator focusPosition(int x, int y);
|
||||
Decorator focusPositionRelative(float x, float y);
|
||||
Element automerge(Element child);
|
||||
Decorator hyperlink(std::string link);
|
||||
Element hyperlink(std::string link, Element child);
|
||||
Element selectionStyleReset(Element);
|
||||
Decorator selectionColor(Color foreground);
|
||||
Decorator selectionBackgroundColor(Color foreground);
|
||||
Decorator selectionForegroundColor(Color foreground);
|
||||
Decorator selectionStyle(std::function<void(Pixel&)> style);
|
||||
|
||||
// --- Layout is
|
||||
// Horizontal, Vertical or stacked set of elements.
|
||||
Element hbox(Elements);
|
||||
Element vbox(Elements);
|
||||
Element dbox(Elements);
|
||||
Element flexbox(Elements, FlexboxConfig config = FlexboxConfig());
|
||||
Element gridbox(std::vector<Elements> lines);
|
||||
|
||||
Element hflow(Elements); // Helper: default flexbox with row direction.
|
||||
Element vflow(Elements); // Helper: default flexbox with column direction.
|
||||
|
||||
// -- Flexibility ---
|
||||
// Define how to share the remaining space when not all of it is used inside a
|
||||
// container.
|
||||
Element flex(Element); // Expand/Minimize if possible/needed.
|
||||
Element flex_grow(Element); // Expand element if possible.
|
||||
Element flex_shrink(Element); // Minimize element if needed.
|
||||
|
||||
Element xflex(Element); // Expand/Minimize if possible/needed on X axis.
|
||||
Element xflex_grow(Element); // Expand element if possible on X axis.
|
||||
Element xflex_shrink(Element); // Minimize element if needed on X axis.
|
||||
|
||||
Element yflex(Element); // Expand/Minimize if possible/needed on Y axis.
|
||||
Element yflex_grow(Element); // Expand element if possible on Y axis.
|
||||
Element yflex_shrink(Element); // Minimize element if needed on Y axis.
|
||||
|
||||
Element notflex(Element); // Reset the flex attribute.
|
||||
Element filler(); // A blank expandable element.
|
||||
|
||||
// -- Size override;
|
||||
enum WidthOrHeight { WIDTH, HEIGHT };
|
||||
enum Constraint { LESS_THAN, EQUAL, GREATER_THAN };
|
||||
Decorator size(WidthOrHeight, Constraint, int value);
|
||||
|
||||
// --- Frame ---
|
||||
// A frame is a scrollable area. The internal area is potentially larger than
|
||||
// the external one. The internal area is scrolled in order to make visible the
|
||||
// focused element.
|
||||
Element frame(Element);
|
||||
Element xframe(Element);
|
||||
Element yframe(Element);
|
||||
Element focus(Element);
|
||||
Element select(Element e); // Deprecated - Alias for focus.
|
||||
|
||||
// --- Cursor ---
|
||||
// Those are similar to `focus`, but also change the shape of the cursor.
|
||||
Element focusCursorBlock(Element);
|
||||
Element focusCursorBlockBlinking(Element);
|
||||
Element focusCursorBar(Element);
|
||||
Element focusCursorBarBlinking(Element);
|
||||
Element focusCursorUnderline(Element);
|
||||
Element focusCursorUnderlineBlinking(Element);
|
||||
|
||||
// --- Misc ---
|
||||
Element vscroll_indicator(Element);
|
||||
Element hscroll_indicator(Element);
|
||||
Decorator reflect(Box& box);
|
||||
// Before drawing the |element| clear the pixel below. This is useful in
|
||||
// combinaison with dbox.
|
||||
Element clear_under(Element element);
|
||||
|
||||
// --- Util --------------------------------------------------------------------
|
||||
Element hcenter(Element);
|
||||
Element vcenter(Element);
|
||||
Element center(Element);
|
||||
Element align_right(Element);
|
||||
Element nothing(Element element);
|
||||
|
||||
namespace Dimension {
|
||||
Dimensions Fit(Element&, bool extend_beyond_screen = false);
|
||||
} // namespace Dimension
|
||||
|
||||
} // namespace ftxui
|
||||
|
||||
// Make container able to take any number of children as input.
|
||||
#include "ftxui/dom/take_any_args.hpp"
|
||||
|
||||
// Include old definitions using wstring.
|
||||
#include "ftxui/dom/deprecated.hpp"
|
||||
#endif // FTXUI_DOM_ELEMENTS_HPP
|
||||
126
ftxui/include/ftxui/dom/flexbox_config.hpp
Normal file
126
ftxui/include/ftxui/dom/flexbox_config.hpp
Normal file
@@ -0,0 +1,126 @@
|
||||
// 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.
|
||||
#ifndef FTXUI_DOM_FLEXBOX_CONFIG_HPP
|
||||
#define FTXUI_DOM_FLEXBOX_CONFIG_HPP
|
||||
|
||||
/*
|
||||
This replicate the CSS flexbox model.
|
||||
See guide for documentation:
|
||||
https://css-tricks.com/snippets/css/a-guide-to-flexbox/
|
||||
*/
|
||||
|
||||
namespace ftxui {
|
||||
|
||||
/// @brief FlexboxConfig is a configuration structure that defines the layout
|
||||
/// properties for a flexbox container.
|
||||
//
|
||||
/// It allows you to specify the direction of the flex items, whether they
|
||||
/// should wrap, how they should be justified along the main axis, and how
|
||||
/// they should be aligned along the cross axis.
|
||||
/// It also includes properties for gaps between flex items in both the
|
||||
/// main and cross axes.
|
||||
/// This structure is used to configure the layout behavior of flexbox
|
||||
/// containers in a terminal user interface.
|
||||
///
|
||||
/// @ingroup dom
|
||||
struct FlexboxConfig {
|
||||
/// This establishes the main-axis, thus defining the direction flex items are
|
||||
/// placed in the flex container. Flexbox is (aside wrapping) single-direction
|
||||
/// layout concept. Think of flex items as primarily laying out either in
|
||||
/// horizontal rows or vertical columns.
|
||||
enum class Direction {
|
||||
Row, ///< Flex items are laid out in a row.
|
||||
RowInversed, ///< Flex items are laid out in a row, but in reverse order.
|
||||
Column, ///< Flex items are laid out in a column.
|
||||
ColumnInversed ///< Flex items are laid out in a column, but in reverse
|
||||
///< order.
|
||||
};
|
||||
Direction direction = Direction::Row;
|
||||
|
||||
/// By default, flex items will all try to fit onto one line. You can change
|
||||
/// that and allow the items to wrap as needed with this property.
|
||||
enum class Wrap {
|
||||
NoWrap, ///< Flex items will all try to fit onto one line.
|
||||
Wrap, ///< Flex items will wrap onto multiple lines.
|
||||
WrapInversed, ///< Flex items will wrap onto multiple lines, but in reverse
|
||||
///< order.
|
||||
};
|
||||
Wrap wrap = Wrap::Wrap;
|
||||
|
||||
/// This defines the alignment along the main axis. It helps distribute extra
|
||||
/// free space leftover when either all the flex items on a line are
|
||||
/// inflexible, or are flexible but have reached their maximum size. It also
|
||||
/// exerts some control over the alignment of items when they overflow the
|
||||
/// line.
|
||||
enum class JustifyContent {
|
||||
/// Items are aligned to the start of flexbox's direction.
|
||||
FlexStart,
|
||||
/// Items are aligned to the end of flexbox's direction.
|
||||
FlexEnd,
|
||||
/// Items are centered along the line.
|
||||
Center,
|
||||
/// Items are stretched to fill the line.
|
||||
Stretch,
|
||||
/// Items are evenly distributed in the line; first item is on the start
|
||||
// line, last item on the end line
|
||||
SpaceBetween,
|
||||
/// Items are evenly distributed in the line with equal space around them.
|
||||
/// Note that visually the spaces aren’t equal, since all the items have
|
||||
/// equal space on both sides. The first item will have one unit of space
|
||||
/// against the container edge, but two units of space between the next item
|
||||
/// because that next item has its own spacing that applies.
|
||||
SpaceAround,
|
||||
/// Items are distributed so that the spacing between any two items (and the
|
||||
/// space to the edges) is equal.
|
||||
SpaceEvenly,
|
||||
};
|
||||
JustifyContent justify_content = JustifyContent::FlexStart;
|
||||
|
||||
/// This defines the default behavior for how flex items are laid out along
|
||||
/// the cross axis on the current line. Think of it as the justify-content
|
||||
/// version for the cross-axis (perpendicular to the main-axis).
|
||||
enum class AlignItems {
|
||||
FlexStart, ///< items are placed at the start of the cross axis.
|
||||
FlexEnd, ///< items are placed at the end of the cross axis.
|
||||
Center, ///< items are centered along the cross axis.
|
||||
Stretch, ///< items are stretched to fill the cross axis.
|
||||
};
|
||||
AlignItems align_items = AlignItems::FlexStart;
|
||||
|
||||
// This aligns a flex container’s lines within when there is extra space in
|
||||
// the cross-axis, similar to how justify-content aligns individual items
|
||||
// within the main-axis.
|
||||
enum class AlignContent {
|
||||
FlexStart, ///< items are placed at the start of the cross axis.
|
||||
FlexEnd, ///< items are placed at the end of the cross axis.
|
||||
Center, ///< items are centered along the cross axis.
|
||||
Stretch, ///< items are stretched to fill the cross axis.
|
||||
SpaceBetween, ///< items are evenly distributed in the cross axis.
|
||||
SpaceAround, ///< tems evenly distributed with equal space around each
|
||||
///< line.
|
||||
SpaceEvenly, ///< items are evenly distributed in the cross axis with equal
|
||||
///< space around them.
|
||||
};
|
||||
AlignContent align_content = AlignContent::FlexStart;
|
||||
|
||||
int gap_x = 0;
|
||||
int gap_y = 0;
|
||||
|
||||
// Constructor pattern. For chained use like:
|
||||
// ```
|
||||
// FlexboxConfig()
|
||||
// .Set(FlexboxConfig::Direction::Row)
|
||||
// .Set(FlexboxConfig::Wrap::Wrap);
|
||||
// ```
|
||||
FlexboxConfig& Set(FlexboxConfig::Direction);
|
||||
FlexboxConfig& Set(FlexboxConfig::Wrap);
|
||||
FlexboxConfig& Set(FlexboxConfig::JustifyContent);
|
||||
FlexboxConfig& Set(FlexboxConfig::AlignItems);
|
||||
FlexboxConfig& Set(FlexboxConfig::AlignContent);
|
||||
FlexboxConfig& SetGap(int gap_x, int gap_y);
|
||||
};
|
||||
|
||||
} // namespace ftxui
|
||||
|
||||
#endif // FTXUI_DOM_FLEXBOX_CONFIG_HPP
|
||||
58
ftxui/include/ftxui/dom/linear_gradient.hpp
Normal file
58
ftxui/include/ftxui/dom/linear_gradient.hpp
Normal file
@@ -0,0 +1,58 @@
|
||||
// Copyright 2023 Arthur Sonzogni. All rights reserved.
|
||||
// Use of this source code is governed by the MIT license that can be found in
|
||||
// the LICENSE file.
|
||||
#ifndef FTXUI_DOM_LINEAR_GRADIENT_HPP
|
||||
#define FTXUI_DOM_LINEAR_GRADIENT_HPP
|
||||
|
||||
#include <optional>
|
||||
#include <vector>
|
||||
|
||||
#include "ftxui/screen/color.hpp" // for Colors
|
||||
|
||||
namespace ftxui {
|
||||
|
||||
/// @brief A class representing the settings for linear-gradient color effect.
|
||||
///
|
||||
/// Example:
|
||||
/// ```cpp
|
||||
/// LinearGradient()
|
||||
/// .Angle(45)
|
||||
/// .Stop(Color::Red, 0.0)
|
||||
/// .Stop(Color::Green, 0.5)
|
||||
/// .Stop(Color::Blue, 1.0);
|
||||
/// ```
|
||||
///
|
||||
/// There are also shorthand constructors:
|
||||
/// ```cpp
|
||||
/// LinearGradient(Color::Red, Color::Blue);
|
||||
/// LinearGradient(45, Color::Red, Color::Blue);
|
||||
/// ```
|
||||
///
|
||||
/// @ingroup dom
|
||||
struct LinearGradient {
|
||||
float angle = 0.f;
|
||||
|
||||
/// A stop is a color at a specific position in the gradient.
|
||||
/// The position is a value between 0.0 and 1.0,
|
||||
/// where 0.0 is the start of the gradient
|
||||
/// and 1.0 is the end of the gradient.
|
||||
struct Stop {
|
||||
Color color = Color::Default;
|
||||
std::optional<float> position;
|
||||
};
|
||||
std::vector<Stop> stops;
|
||||
|
||||
// Simple constructor
|
||||
LinearGradient();
|
||||
LinearGradient(Color begin, Color end);
|
||||
LinearGradient(float angle, Color begin, Color end);
|
||||
|
||||
// Modifier using the builder pattern.
|
||||
LinearGradient& Angle(float angle);
|
||||
LinearGradient& Stop(Color color, float position);
|
||||
LinearGradient& Stop(Color color);
|
||||
};
|
||||
|
||||
} // namespace ftxui
|
||||
|
||||
#endif // FTXUI_DOM_LINEAR_GRADIENT_HPP
|
||||
93
ftxui/include/ftxui/dom/node.hpp
Normal file
93
ftxui/include/ftxui/dom/node.hpp
Normal file
@@ -0,0 +1,93 @@
|
||||
// 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.
|
||||
#ifndef FTXUI_DOM_NODE_HPP
|
||||
#define FTXUI_DOM_NODE_HPP
|
||||
|
||||
#include <memory> // for shared_ptr
|
||||
#include <vector> // for vector
|
||||
|
||||
#include "ftxui/dom/requirement.hpp" // for Requirement
|
||||
#include "ftxui/dom/selection.hpp" // for Selection
|
||||
#include "ftxui/screen/box.hpp" // for Box
|
||||
#include "ftxui/screen/screen.hpp"
|
||||
|
||||
namespace ftxui {
|
||||
|
||||
class Node;
|
||||
class Screen;
|
||||
|
||||
using Element = std::shared_ptr<Node>;
|
||||
using Elements = std::vector<Element>;
|
||||
|
||||
/// @brief Node is the base class for all elements in the DOM tree.
|
||||
///
|
||||
/// It represents a single node in the document object model (DOM) and provides
|
||||
/// the basic structure for layout and rendering.
|
||||
/// It contains methods for computing layout requirements, setting the box
|
||||
/// dimensions, selecting content, rendering to the screen, and checking the
|
||||
/// layout status.
|
||||
/// It typically contains child elements, which are also instances of Node.
|
||||
///
|
||||
/// Users are expected to derive from this class to create custom elements.
|
||||
///
|
||||
/// A list of builtin elements can be found in the `elements.hpp` file.
|
||||
///
|
||||
/// @ingroup dom
|
||||
class Node {
|
||||
public:
|
||||
Node();
|
||||
explicit Node(Elements children);
|
||||
Node(const Node&) = delete;
|
||||
Node(const Node&&) = delete;
|
||||
Node& operator=(const Node&) = delete;
|
||||
Node& operator=(const Node&&) = delete;
|
||||
|
||||
virtual ~Node();
|
||||
|
||||
// Step 1: Compute layout requirement. Tell parent what dimensions this
|
||||
// element wants to be.
|
||||
// Propagated from Children to Parents.
|
||||
virtual void ComputeRequirement();
|
||||
Requirement requirement() { return requirement_; }
|
||||
|
||||
// Step 2: Assign this element its final dimensions.
|
||||
// Propagated from Parents to Children.
|
||||
virtual void SetBox(Box box);
|
||||
|
||||
// Step 3: (optional) Selection
|
||||
// Propagated from Parents to Children.
|
||||
virtual void Select(Selection& selection);
|
||||
|
||||
// Step 4: Draw this element.
|
||||
virtual void Render(Screen& screen);
|
||||
|
||||
virtual std::string GetSelectedContent(Selection& selection);
|
||||
|
||||
// Layout may not resolve within a single iteration for some elements. This
|
||||
// allows them to request additionnal iterations. This signal must be
|
||||
// forwarded to children at least once.
|
||||
struct Status {
|
||||
int iteration = 0;
|
||||
bool need_iteration = false;
|
||||
};
|
||||
virtual void Check(Status* status);
|
||||
|
||||
friend void Render(Screen& screen, Node* node, Selection& selection);
|
||||
|
||||
protected:
|
||||
Elements children_;
|
||||
Requirement requirement_;
|
||||
Box box_;
|
||||
};
|
||||
|
||||
void Render(Screen& screen, const Element& element);
|
||||
void Render(Screen& screen, Node* node);
|
||||
void Render(Screen& screen, Node* node, Selection& selection);
|
||||
std::string GetNodeSelectedContent(Screen& screen,
|
||||
Node* node,
|
||||
Selection& selection);
|
||||
|
||||
} // namespace ftxui
|
||||
|
||||
#endif // FTXUI_DOM_NODE_HPP
|
||||
56
ftxui/include/ftxui/dom/requirement.hpp
Normal file
56
ftxui/include/ftxui/dom/requirement.hpp
Normal file
@@ -0,0 +1,56 @@
|
||||
// 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.
|
||||
#ifndef FTXUI_DOM_REQUIREMENT_HPP
|
||||
#define FTXUI_DOM_REQUIREMENT_HPP
|
||||
|
||||
#include "ftxui/screen/box.hpp"
|
||||
#include "ftxui/screen/screen.hpp"
|
||||
|
||||
namespace ftxui {
|
||||
class Node;
|
||||
|
||||
/// @brief Requirement is a structure that defines the layout requirements for a
|
||||
/// Node in the terminal user interface.
|
||||
///
|
||||
/// It specifies the minimum size required to fully draw the element,
|
||||
/// @ingroup dom
|
||||
struct Requirement {
|
||||
// The required size to fully draw the element.
|
||||
int min_x = 0;
|
||||
int min_y = 0;
|
||||
|
||||
// How much flexibility is given to the component.
|
||||
int flex_grow_x = 0;
|
||||
int flex_grow_y = 0;
|
||||
int flex_shrink_x = 0;
|
||||
int flex_shrink_y = 0;
|
||||
|
||||
// Focus management to support the frame/focus/select element.
|
||||
struct Focused {
|
||||
bool enabled = false;
|
||||
Box box;
|
||||
Node* node = nullptr;
|
||||
Screen::Cursor::Shape cursor_shape = Screen::Cursor::Shape::Hidden;
|
||||
|
||||
// Internal for interactions with components.
|
||||
bool component_active = false;
|
||||
|
||||
// Return whether this requirement should be preferred over the other.
|
||||
bool Prefer(const Focused& other) const {
|
||||
if (!other.enabled) {
|
||||
return false;
|
||||
}
|
||||
if (!enabled) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return other.component_active && !component_active;
|
||||
}
|
||||
};
|
||||
Focused focused;
|
||||
};
|
||||
|
||||
} // namespace ftxui
|
||||
|
||||
#endif // FTXUI_DOM_REQUIREMENT_HPP
|
||||
55
ftxui/include/ftxui/dom/selection.hpp
Normal file
55
ftxui/include/ftxui/dom/selection.hpp
Normal file
@@ -0,0 +1,55 @@
|
||||
// Copyright 2024 Arthur Sonzogni. All rights reserved.
|
||||
// Use of this source code is governed by the MIT license that can be found in
|
||||
// the LICENSE file.
|
||||
|
||||
#ifndef FTXUI_DOM_SELECTION_HPP
|
||||
#define FTXUI_DOM_SELECTION_HPP
|
||||
|
||||
#include <functional>
|
||||
|
||||
#include <sstream>
|
||||
#include "ftxui/screen/box.hpp" // for Box
|
||||
#include "ftxui/screen/pixel.hpp" // for Pixel
|
||||
|
||||
namespace ftxui {
|
||||
|
||||
/// @brief Represents a selection in a terminal user interface.
|
||||
///
|
||||
/// Selection is a class that represents the two endpoints of a selection in a
|
||||
/// terminal user interface.
|
||||
///
|
||||
/// @ingroup dom
|
||||
class Selection {
|
||||
public:
|
||||
Selection(); // Empty selection.
|
||||
Selection(int start_x, int start_y, int end_x, int end_y);
|
||||
|
||||
const Box& GetBox() const;
|
||||
|
||||
Selection SaturateHorizontal(Box box);
|
||||
Selection SaturateVertical(Box box);
|
||||
bool IsEmpty() const { return empty_; }
|
||||
|
||||
void AddPart(const std::string& part, int y, int left, int right);
|
||||
std::string GetParts() { return parts_.str(); }
|
||||
|
||||
private:
|
||||
Selection(int start_x, int start_y, int end_x, int end_y, Selection* parent);
|
||||
|
||||
const int start_x_ = 0;
|
||||
const int start_y_ = 0;
|
||||
const int end_x_ = 0;
|
||||
const int end_y_ = 0;
|
||||
const Box box_ = {};
|
||||
Selection* const parent_ = this;
|
||||
const bool empty_ = true;
|
||||
std::stringstream parts_;
|
||||
|
||||
// The position of the last inserted part.
|
||||
int x_ = 0;
|
||||
int y_ = 0;
|
||||
};
|
||||
|
||||
} // namespace ftxui
|
||||
|
||||
#endif /* end of include guard: FTXUI_DOM_SELECTION_HPP */
|
||||
95
ftxui/include/ftxui/dom/table.hpp
Normal file
95
ftxui/include/ftxui/dom/table.hpp
Normal file
@@ -0,0 +1,95 @@
|
||||
// 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.
|
||||
#ifndef FTXUI_DOM_TABLE
|
||||
#define FTXUI_DOM_TABLE
|
||||
|
||||
#include <string> // for string
|
||||
#include <vector> // for vector
|
||||
|
||||
#include "ftxui/dom/elements.hpp" // for Element, BorderStyle, LIGHT, Decorator
|
||||
|
||||
namespace ftxui {
|
||||
|
||||
class Table;
|
||||
class TableSelection;
|
||||
|
||||
/// @brief Table is a utility to draw tables.
|
||||
///
|
||||
/// **example**
|
||||
/// ```cpp
|
||||
/// auto table = Table({
|
||||
/// {"X", "Y"},
|
||||
/// {"-1", "1"},
|
||||
/// {"+0", "0"},
|
||||
/// {"+1", "1"},
|
||||
/// });
|
||||
///
|
||||
/// table.SelectAll().Border(LIGHT);
|
||||
/// table.SelectRow(1).Border(DOUBLE);
|
||||
/// table.SelectRow(1).SeparatorInternal(LIGHT);
|
||||
///
|
||||
/// std::move(table).Render();
|
||||
/// ```
|
||||
///
|
||||
/// @ingroup dom
|
||||
class Table {
|
||||
public:
|
||||
Table();
|
||||
explicit Table(std::vector<std::vector<std::string>>);
|
||||
explicit Table(std::vector<std::vector<Element>>);
|
||||
Table(std::initializer_list<std::vector<std::string>> init);
|
||||
TableSelection SelectAll();
|
||||
TableSelection SelectCell(int column, int row);
|
||||
TableSelection SelectRow(int row_index);
|
||||
TableSelection SelectRows(int row_min, int row_max);
|
||||
TableSelection SelectColumn(int column_index);
|
||||
TableSelection SelectColumns(int column_min, int column_max);
|
||||
TableSelection SelectRectangle(int column_min,
|
||||
int column_max,
|
||||
int row_min,
|
||||
int row_max);
|
||||
Element Render();
|
||||
|
||||
private:
|
||||
void Initialize(std::vector<std::vector<Element>>);
|
||||
friend TableSelection;
|
||||
std::vector<std::vector<Element>> elements_;
|
||||
int input_dim_x_ = 0;
|
||||
int input_dim_y_ = 0;
|
||||
int dim_x_ = 0;
|
||||
int dim_y_ = 0;
|
||||
};
|
||||
|
||||
class TableSelection {
|
||||
public:
|
||||
void Decorate(Decorator);
|
||||
void DecorateAlternateRow(Decorator, int modulo = 2, int shift = 0);
|
||||
void DecorateAlternateColumn(Decorator, int modulo = 2, int shift = 0);
|
||||
|
||||
void DecorateCells(Decorator);
|
||||
void DecorateCellsAlternateColumn(Decorator, int modulo = 2, int shift = 0);
|
||||
void DecorateCellsAlternateRow(Decorator, int modulo = 2, int shift = 0);
|
||||
|
||||
void Border(BorderStyle border = LIGHT);
|
||||
void BorderLeft(BorderStyle border = LIGHT);
|
||||
void BorderRight(BorderStyle border = LIGHT);
|
||||
void BorderTop(BorderStyle border = LIGHT);
|
||||
void BorderBottom(BorderStyle border = LIGHT);
|
||||
|
||||
void Separator(BorderStyle border = LIGHT);
|
||||
void SeparatorVertical(BorderStyle border = LIGHT);
|
||||
void SeparatorHorizontal(BorderStyle border = LIGHT);
|
||||
|
||||
private:
|
||||
friend Table;
|
||||
Table* table_;
|
||||
int x_min_;
|
||||
int x_max_;
|
||||
int y_min_;
|
||||
int y_max_;
|
||||
};
|
||||
|
||||
} // namespace ftxui
|
||||
|
||||
#endif /* end of include guard: FTXUI_DOM_TABLE */
|
||||
48
ftxui/include/ftxui/dom/take_any_args.hpp
Normal file
48
ftxui/include/ftxui/dom/take_any_args.hpp
Normal file
@@ -0,0 +1,48 @@
|
||||
// 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.
|
||||
#ifndef FTXUI_DOM_TAKE_ANY_ARGS_HPP
|
||||
#define FTXUI_DOM_TAKE_ANY_ARGS_HPP
|
||||
|
||||
// IWYU pragma: private, include "ftxui/dom/elements.hpp"
|
||||
#include <ftxui/dom/node.hpp>
|
||||
|
||||
namespace ftxui {
|
||||
|
||||
template <class T>
|
||||
void Merge(Elements& /*container*/, T /*element*/) {}
|
||||
|
||||
template <>
|
||||
inline void Merge(Elements& container, Element element) {
|
||||
container.push_back(std::move(element));
|
||||
}
|
||||
|
||||
template <>
|
||||
inline void Merge(Elements& container, Elements elements) {
|
||||
for (auto& element : elements) {
|
||||
container.push_back(std::move(element));
|
||||
}
|
||||
}
|
||||
|
||||
// Turn a set of arguments into a vector.
|
||||
template <class... Args>
|
||||
Elements unpack(Args... args) {
|
||||
std::vector<Element> vec;
|
||||
(Merge(vec, std::move(args)), ...);
|
||||
return vec;
|
||||
}
|
||||
|
||||
// Make |container| able to take any number of argments.
|
||||
#define TAKE_ANY_ARGS(container) \
|
||||
template <class... Args> \
|
||||
Element container(Args... children) { \
|
||||
return container(unpack(std::forward<Args>(children)...)); \
|
||||
}
|
||||
|
||||
TAKE_ANY_ARGS(vbox)
|
||||
TAKE_ANY_ARGS(hbox)
|
||||
TAKE_ANY_ARGS(dbox)
|
||||
TAKE_ANY_ARGS(hflow)
|
||||
} // namespace ftxui
|
||||
|
||||
#endif // FTXUI_DOM_TAKE_ANY_ARGS_HPP
|
||||
33
ftxui/include/ftxui/screen/box.hpp
Normal file
33
ftxui/include/ftxui/screen/box.hpp
Normal file
@@ -0,0 +1,33 @@
|
||||
// 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.
|
||||
#ifndef FTXUI_SCREEN_BOX_HPP
|
||||
#define FTXUI_SCREEN_BOX_HPP
|
||||
|
||||
namespace ftxui {
|
||||
|
||||
/// @brief Box is a structure that represents a rectangular area in a 2D space.
|
||||
///
|
||||
/// It is defined by its minimum and maximum coordinates along the x and y axes.
|
||||
/// Note that the coordinates are inclusive, meaning that the box includes both
|
||||
/// the minimum and maximum values.
|
||||
///
|
||||
/// @ingroup screen
|
||||
struct Box {
|
||||
int x_min = 0;
|
||||
int x_max = 0;
|
||||
int y_min = 0;
|
||||
int y_max = 0;
|
||||
|
||||
static auto Intersection(Box a, Box b) -> Box;
|
||||
static auto Union(Box a, Box b) -> Box;
|
||||
void Shift(int x, int y);
|
||||
bool Contain(int x, int y) const;
|
||||
bool IsEmpty() const;
|
||||
bool operator==(const Box& other) const;
|
||||
bool operator!=(const Box& other) const;
|
||||
};
|
||||
|
||||
} // namespace ftxui
|
||||
|
||||
#endif // FTXUI_SCREEN_BOX_HPP
|
||||
347
ftxui/include/ftxui/screen/color.hpp
Normal file
347
ftxui/include/ftxui/screen/color.hpp
Normal file
@@ -0,0 +1,347 @@
|
||||
// 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.
|
||||
#ifndef FTXUI_SCREEN_COLOR_HPP
|
||||
#define FTXUI_SCREEN_COLOR_HPP
|
||||
|
||||
#include <cstdint> // for uint8_t
|
||||
#include <string> // for string
|
||||
|
||||
#ifdef RGB
|
||||
// Workaround for wingdi.h (via Windows.h) defining macros that break things.
|
||||
// https://docs.microsoft.com/en-us/windows/win32/api/wingdi/nf-wingdi-rgb
|
||||
#undef RGB
|
||||
#endif
|
||||
|
||||
namespace ftxui {
|
||||
|
||||
/// @brief Color is a class that represents a color in the terminal user
|
||||
/// interface.
|
||||
///
|
||||
/// @ingroup screen
|
||||
class Color {
|
||||
public:
|
||||
enum Palette1 : uint8_t;
|
||||
enum Palette16 : uint8_t;
|
||||
enum Palette256 : uint8_t;
|
||||
|
||||
// NOLINTBEGIN
|
||||
Color(); // Transparent.
|
||||
Color(Palette1 index); // Transparent.
|
||||
Color(Palette16 index); // Implicit conversion from index to Color.
|
||||
Color(Palette256 index); // Implicit conversion from index to Color.
|
||||
// NOLINTEND
|
||||
Color(uint8_t red, uint8_t green, uint8_t blue, uint8_t alpha = 255);
|
||||
static Color RGB(uint8_t red, uint8_t green, uint8_t blue);
|
||||
static Color HSV(uint8_t hue, uint8_t saturation, uint8_t value);
|
||||
static Color RGBA(uint8_t red, uint8_t green, uint8_t blue, uint8_t alpha);
|
||||
static Color HSVA(uint8_t hue,
|
||||
uint8_t saturation,
|
||||
uint8_t value,
|
||||
uint8_t alpha);
|
||||
static Color Interpolate(float t, const Color& a, const Color& b);
|
||||
static Color Blend(const Color& lhs, const Color& rhs);
|
||||
|
||||
//---------------------------
|
||||
// List of colors:
|
||||
//---------------------------
|
||||
// clang-format off
|
||||
enum Palette1 : uint8_t{
|
||||
Default, // Transparent
|
||||
};
|
||||
|
||||
enum Palette16 : uint8_t {
|
||||
Black = 0,
|
||||
Red = 1,
|
||||
Green = 2,
|
||||
Yellow = 3,
|
||||
Blue = 4,
|
||||
Magenta = 5,
|
||||
Cyan = 6,
|
||||
GrayLight = 7,
|
||||
GrayDark = 8,
|
||||
RedLight = 9,
|
||||
GreenLight = 10,
|
||||
YellowLight = 11,
|
||||
BlueLight = 12,
|
||||
MagentaLight = 13,
|
||||
CyanLight = 14,
|
||||
White = 15,
|
||||
};
|
||||
|
||||
enum Palette256 : uint8_t {
|
||||
Aquamarine1 = 122,
|
||||
Aquamarine1Bis = 86,
|
||||
Aquamarine3 = 79,
|
||||
Blue1 = 21,
|
||||
Blue3 = 19,
|
||||
Blue3Bis = 20,
|
||||
BlueViolet = 57,
|
||||
CadetBlue = 72,
|
||||
CadetBlueBis = 73,
|
||||
Chartreuse1 = 118,
|
||||
Chartreuse2 = 112,
|
||||
Chartreuse2Bis = 82,
|
||||
Chartreuse3 = 70,
|
||||
Chartreuse3Bis = 76,
|
||||
Chartreuse4 = 64,
|
||||
CornflowerBlue = 69,
|
||||
Cornsilk1 = 230,
|
||||
Cyan1 = 51,
|
||||
Cyan2 = 50,
|
||||
Cyan3 = 43,
|
||||
DarkBlue = 18,
|
||||
DarkCyan = 36,
|
||||
DarkGoldenrod = 136,
|
||||
DarkGreen = 22,
|
||||
DarkKhaki = 143,
|
||||
DarkMagenta = 90,
|
||||
DarkMagentaBis = 91,
|
||||
DarkOliveGreen1 = 191,
|
||||
DarkOliveGreen1Bis = 192,
|
||||
DarkOliveGreen2 = 155,
|
||||
DarkOliveGreen3 = 107,
|
||||
DarkOliveGreen3Bis = 113,
|
||||
DarkOliveGreen3Ter = 149,
|
||||
DarkOrange = 208,
|
||||
DarkOrange3 = 130,
|
||||
DarkOrange3Bis = 166,
|
||||
DarkRed = 52,
|
||||
DarkRedBis = 88,
|
||||
DarkSeaGreen = 108,
|
||||
DarkSeaGreen1 = 158,
|
||||
DarkSeaGreen1Bis = 193,
|
||||
DarkSeaGreen2 = 151,
|
||||
DarkSeaGreen2Bis = 157,
|
||||
DarkSeaGreen3 = 115,
|
||||
DarkSeaGreen3Bis = 150,
|
||||
DarkSeaGreen4 = 65,
|
||||
DarkSeaGreen4Bis = 71,
|
||||
DarkSlateGray1 = 123,
|
||||
DarkSlateGray2 = 87,
|
||||
DarkSlateGray3 = 116,
|
||||
DarkTurquoise = 44,
|
||||
DarkViolet = 128,
|
||||
DarkVioletBis = 92,
|
||||
DeepPink1 = 198,
|
||||
DeepPink1Bis = 199,
|
||||
DeepPink2 = 197,
|
||||
DeepPink3 = 161,
|
||||
DeepPink3Bis = 162,
|
||||
DeepPink4 = 125,
|
||||
DeepPink4Bis = 89,
|
||||
DeepPink4Ter = 53,
|
||||
DeepSkyBlue1 = 39,
|
||||
DeepSkyBlue2 = 38,
|
||||
DeepSkyBlue3 = 31,
|
||||
DeepSkyBlue3Bis = 32,
|
||||
DeepSkyBlue4 = 23,
|
||||
DeepSkyBlue4Bis = 24,
|
||||
DeepSkyBlue4Ter = 25,
|
||||
DodgerBlue1 = 33,
|
||||
DodgerBlue2 = 27,
|
||||
DodgerBlue3 = 26,
|
||||
Gold1 = 220,
|
||||
Gold3 = 142,
|
||||
Gold3Bis = 178,
|
||||
Green1 = 46,
|
||||
Green3 = 34,
|
||||
Green3Bis = 40,
|
||||
Green4 = 28,
|
||||
GreenYellow = 154,
|
||||
Grey0 = 16,
|
||||
Grey100 = 231,
|
||||
Grey11 = 234,
|
||||
Grey15 = 235,
|
||||
Grey19 = 236,
|
||||
Grey23 = 237,
|
||||
Grey27 = 238,
|
||||
Grey3 = 232,
|
||||
Grey30 = 239,
|
||||
Grey35 = 240,
|
||||
Grey37 = 59,
|
||||
Grey39 = 241,
|
||||
Grey42 = 242,
|
||||
Grey46 = 243,
|
||||
Grey50 = 244,
|
||||
Grey53 = 102,
|
||||
Grey54 = 245,
|
||||
Grey58 = 246,
|
||||
Grey62 = 247,
|
||||
Grey63 = 139,
|
||||
Grey66 = 248,
|
||||
Grey69 = 145,
|
||||
Grey7 = 233,
|
||||
Grey70 = 249,
|
||||
Grey74 = 250,
|
||||
Grey78 = 251,
|
||||
Grey82 = 252,
|
||||
Grey84 = 188,
|
||||
Grey85 = 253,
|
||||
Grey89 = 254,
|
||||
Grey93 = 255,
|
||||
Honeydew2 = 194,
|
||||
HotPink = 205,
|
||||
HotPink2 = 169,
|
||||
HotPink3 = 132,
|
||||
HotPink3Bis = 168,
|
||||
HotPinkBis = 206,
|
||||
IndianRed = 131,
|
||||
IndianRed1 = 203,
|
||||
IndianRed1Bis = 204,
|
||||
IndianRedBis = 167,
|
||||
Khaki1 = 228,
|
||||
Khaki3 = 185,
|
||||
LightCoral = 210,
|
||||
LightCyan1Bis = 195,
|
||||
LightCyan3 = 152,
|
||||
LightGoldenrod1 = 227,
|
||||
LightGoldenrod2 = 186,
|
||||
LightGoldenrod2Bis = 221,
|
||||
LightGoldenrod2Ter = 222,
|
||||
LightGoldenrod3 = 179,
|
||||
LightGreen = 119,
|
||||
LightGreenBis = 120,
|
||||
LightPink1 = 217,
|
||||
LightPink3 = 174,
|
||||
LightPink4 = 95,
|
||||
LightSalmon1 = 216,
|
||||
LightSalmon3 = 137,
|
||||
LightSalmon3Bis = 173,
|
||||
LightSeaGreen = 37,
|
||||
LightSkyBlue1 = 153,
|
||||
LightSkyBlue3 = 109,
|
||||
LightSkyBlue3Bis = 110,
|
||||
LightSlateBlue = 105,
|
||||
LightSlateGrey = 103,
|
||||
LightSteelBlue = 147,
|
||||
LightSteelBlue1 = 189,
|
||||
LightSteelBlue3 = 146,
|
||||
LightYellow3 = 187,
|
||||
Magenta1 = 201,
|
||||
Magenta2 = 165,
|
||||
Magenta2Bis = 200,
|
||||
Magenta3 = 127,
|
||||
Magenta3Bis = 163,
|
||||
Magenta3Ter = 164,
|
||||
MediumOrchid = 134,
|
||||
MediumOrchid1 = 171,
|
||||
MediumOrchid1Bis = 207,
|
||||
MediumOrchid3 = 133,
|
||||
MediumPurple = 104,
|
||||
MediumPurple1 = 141,
|
||||
MediumPurple2 = 135,
|
||||
MediumPurple2Bis = 140,
|
||||
MediumPurple3 = 97,
|
||||
MediumPurple3Bis = 98,
|
||||
MediumPurple4 = 60,
|
||||
MediumSpringGreen = 49,
|
||||
MediumTurquoise = 80,
|
||||
MediumVioletRed = 126,
|
||||
MistyRose1 = 224,
|
||||
MistyRose3 = 181,
|
||||
NavajoWhite1 = 223,
|
||||
NavajoWhite3 = 144,
|
||||
NavyBlue = 17,
|
||||
Orange1 = 214,
|
||||
Orange3 = 172,
|
||||
Orange4 = 58,
|
||||
Orange4Bis = 94,
|
||||
OrangeRed1 = 202,
|
||||
Orchid = 170,
|
||||
Orchid1 = 213,
|
||||
Orchid2 = 212,
|
||||
PaleGreen1 = 121,
|
||||
PaleGreen1Bis = 156,
|
||||
PaleGreen3 = 114,
|
||||
PaleGreen3Bis = 77,
|
||||
PaleTurquoise1 = 159,
|
||||
PaleTurquoise4 = 66,
|
||||
PaleVioletRed1 = 211,
|
||||
Pink1 = 218,
|
||||
Pink3 = 175,
|
||||
Plum1 = 219,
|
||||
Plum2 = 183,
|
||||
Plum3 = 176,
|
||||
Plum4 = 96,
|
||||
Purple = 129,
|
||||
Purple3 = 56,
|
||||
Purple4 = 54,
|
||||
Purple4Bis = 55,
|
||||
PurpleBis = 93,
|
||||
Red1 = 196,
|
||||
Red3 = 124,
|
||||
Red3Bis = 160,
|
||||
RosyBrown = 138,
|
||||
RoyalBlue1 = 63,
|
||||
Salmon1 = 209,
|
||||
SandyBrown = 215,
|
||||
SeaGreen1 = 84,
|
||||
SeaGreen1Bis = 85,
|
||||
SeaGreen2 = 83,
|
||||
SeaGreen3 = 78,
|
||||
SkyBlue1 = 117,
|
||||
SkyBlue2 = 111,
|
||||
SkyBlue3 = 74,
|
||||
SlateBlue1 = 99,
|
||||
SlateBlue3 = 61,
|
||||
SlateBlue3Bis = 62,
|
||||
SpringGreen1 = 48,
|
||||
SpringGreen2 = 42,
|
||||
SpringGreen2Bis = 47,
|
||||
SpringGreen3 = 35,
|
||||
SpringGreen3Bis = 41,
|
||||
SpringGreen4 = 29,
|
||||
SteelBlue = 67,
|
||||
SteelBlue1 = 75,
|
||||
SteelBlue1Bis = 81,
|
||||
SteelBlue3 = 68,
|
||||
Tan = 180,
|
||||
Thistle1 = 225,
|
||||
Thistle3 = 182,
|
||||
Turquoise2 = 45,
|
||||
Turquoise4 = 30,
|
||||
Violet = 177,
|
||||
Wheat1 = 229,
|
||||
Wheat4 = 101,
|
||||
Yellow1 = 226,
|
||||
Yellow2 = 190,
|
||||
Yellow3 = 148,
|
||||
Yellow3Bis = 184,
|
||||
Yellow4 = 100,
|
||||
Yellow4Bis = 106,
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
// --- Operators ------
|
||||
bool operator==(const Color& rhs) const;
|
||||
bool operator!=(const Color& rhs) const;
|
||||
|
||||
std::string Print(bool is_background_color) const;
|
||||
bool IsOpaque() const { return alpha_ == 255; }
|
||||
|
||||
private:
|
||||
enum class ColorType : uint8_t {
|
||||
Palette1,
|
||||
Palette16,
|
||||
Palette256,
|
||||
TrueColor,
|
||||
};
|
||||
ColorType type_ = ColorType::Palette1;
|
||||
uint8_t red_ = 0;
|
||||
uint8_t green_ = 0;
|
||||
uint8_t blue_ = 0;
|
||||
uint8_t alpha_ = 0;
|
||||
};
|
||||
|
||||
inline namespace literals {
|
||||
|
||||
/// @brief Creates a color from a combined hex RGB representation,
|
||||
/// e.g. 0x808000_rgb
|
||||
Color operator""_rgb(unsigned long long int combined);
|
||||
|
||||
} // namespace literals
|
||||
|
||||
} // namespace ftxui
|
||||
|
||||
#endif // FTXUI_SCREEN_COLOR_HPP
|
||||
33
ftxui/include/ftxui/screen/color_info.hpp
Normal file
33
ftxui/include/ftxui/screen/color_info.hpp
Normal file
@@ -0,0 +1,33 @@
|
||||
// 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.
|
||||
#ifndef FTXUI_SCREEN_COLOR_INFO_HPP
|
||||
#define FTXUI_SCREEN_COLOR_INFO_HPP
|
||||
|
||||
#include <cstdint>
|
||||
#include <ftxui/screen/color.hpp>
|
||||
|
||||
namespace ftxui {
|
||||
|
||||
/// @brief ColorInfo is a structure that contains information about the terminal
|
||||
/// color palette.
|
||||
///
|
||||
/// @ingroup screen
|
||||
struct ColorInfo {
|
||||
const char* name;
|
||||
uint8_t index_256;
|
||||
uint8_t index_16;
|
||||
uint8_t red;
|
||||
uint8_t green;
|
||||
uint8_t blue;
|
||||
uint8_t hue;
|
||||
uint8_t saturation;
|
||||
uint8_t value;
|
||||
};
|
||||
|
||||
ColorInfo GetColorInfo(Color::Palette256 index);
|
||||
ColorInfo GetColorInfo(Color::Palette16 index);
|
||||
|
||||
} // namespace ftxui
|
||||
|
||||
#endif // FTXUI_SCREEN_COLOR_INFO_HPP
|
||||
14
ftxui/include/ftxui/screen/deprecated.hpp
Normal file
14
ftxui/include/ftxui/screen/deprecated.hpp
Normal file
@@ -0,0 +1,14 @@
|
||||
// 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.
|
||||
#ifndef FTXUI_SCREEN_DEPRECATED_HPP
|
||||
#define FTXUI_SCREEN_DEPRECATED_HPP
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace ftxui {
|
||||
int wchar_width(wchar_t);
|
||||
int wstring_width(const std::wstring&);
|
||||
} // namespace ftxui
|
||||
|
||||
#endif // FTXUI_SCREEN_DEPRECATED_HPP
|
||||
51
ftxui/include/ftxui/screen/image.hpp
Normal file
51
ftxui/include/ftxui/screen/image.hpp
Normal file
@@ -0,0 +1,51 @@
|
||||
// Copyright 2024 Arthur Sonzogni. All rights reserved.
|
||||
// Use of this source code is governed by the MIT license that can be found in
|
||||
// the LICENSE file.
|
||||
#ifndef FTXUI_SCREEN_IMAGE_HPP
|
||||
#define FTXUI_SCREEN_IMAGE_HPP
|
||||
|
||||
#include <string> // for string, basic_string, allocator
|
||||
#include <vector> // for vector
|
||||
|
||||
#include "ftxui/screen/box.hpp" // for Box
|
||||
#include "ftxui/screen/pixel.hpp" // for Pixel
|
||||
|
||||
namespace ftxui {
|
||||
|
||||
/// @brief A rectangular grid of Pixel.
|
||||
/// @ingroup screen
|
||||
class Image {
|
||||
public:
|
||||
// Constructors:
|
||||
Image() = delete;
|
||||
Image(int dimx, int dimy);
|
||||
|
||||
// Destructor:
|
||||
virtual ~Image() = default;
|
||||
|
||||
// Access a character in the grid at a given position.
|
||||
std::string& at(int x, int y);
|
||||
const std::string& at(int x, int y) const;
|
||||
|
||||
// Access a cell (Pixel) in the grid at a given position.
|
||||
Pixel& PixelAt(int x, int y);
|
||||
const Pixel& PixelAt(int x, int y) const;
|
||||
|
||||
// Get screen dimensions.
|
||||
int dimx() const { return dimx_; }
|
||||
int dimy() const { return dimy_; }
|
||||
|
||||
// Fill the image with space and default style
|
||||
void Clear();
|
||||
|
||||
Box stencil;
|
||||
|
||||
protected:
|
||||
int dimx_;
|
||||
int dimy_;
|
||||
std::vector<std::vector<Pixel>> pixels_;
|
||||
};
|
||||
|
||||
} // namespace ftxui
|
||||
|
||||
#endif // FTXUI_SCREEN_IMAGE_HPP
|
||||
54
ftxui/include/ftxui/screen/pixel.hpp
Normal file
54
ftxui/include/ftxui/screen/pixel.hpp
Normal file
@@ -0,0 +1,54 @@
|
||||
// Copyright 2024 Arthur Sonzogni. All rights reserved.
|
||||
// Use of this source code is governed by the MIT license that can be found in
|
||||
// the LICENSE file.
|
||||
#ifndef FTXUI_SCREEN_PIXEL_HPP
|
||||
#define FTXUI_SCREEN_PIXEL_HPP
|
||||
|
||||
#include <cstdint> // for uint8_t
|
||||
#include <string> // for string, basic_string, allocator
|
||||
#include "ftxui/screen/color.hpp" // for Color, Color::Default
|
||||
|
||||
namespace ftxui {
|
||||
|
||||
/// @brief A Unicode character and its associated style.
|
||||
/// @ingroup screen
|
||||
struct Pixel {
|
||||
Pixel()
|
||||
: blink(false),
|
||||
bold(false),
|
||||
dim(false),
|
||||
italic(false),
|
||||
inverted(false),
|
||||
underlined(false),
|
||||
underlined_double(false),
|
||||
strikethrough(false),
|
||||
automerge(false) {}
|
||||
|
||||
// A bit field representing the style:
|
||||
bool blink : 1;
|
||||
bool bold : 1;
|
||||
bool dim : 1;
|
||||
bool italic : 1;
|
||||
bool inverted : 1;
|
||||
bool underlined : 1;
|
||||
bool underlined_double : 1;
|
||||
bool strikethrough : 1;
|
||||
bool automerge : 1;
|
||||
|
||||
// The hyperlink associated with the pixel.
|
||||
// 0 is the default value, meaning no hyperlink.
|
||||
// It's an index for accessing Screen meta data
|
||||
uint8_t hyperlink = 0;
|
||||
|
||||
// The graphemes stored into the pixel. To support combining characters,
|
||||
// like: a?, this can potentially contain multiple codepoints.
|
||||
std::string character = "";
|
||||
|
||||
// Colors:
|
||||
Color background_color = Color::Default;
|
||||
Color foreground_color = Color::Default;
|
||||
};
|
||||
|
||||
} // namespace ftxui
|
||||
|
||||
#endif // FTXUI_SCREEN_PIXEL_HPP
|
||||
90
ftxui/include/ftxui/screen/screen.hpp
Normal file
90
ftxui/include/ftxui/screen/screen.hpp
Normal file
@@ -0,0 +1,90 @@
|
||||
// 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.
|
||||
#ifndef FTXUI_SCREEN_SCREEN_HPP
|
||||
#define FTXUI_SCREEN_SCREEN_HPP
|
||||
|
||||
#include <cstdint> // for uint8_t
|
||||
#include <functional> // for function
|
||||
#include <string> // for string, basic_string, allocator
|
||||
#include <vector> // for vector
|
||||
|
||||
#include "ftxui/screen/image.hpp" // for Pixel, Image
|
||||
#include "ftxui/screen/terminal.hpp" // for Dimensions
|
||||
|
||||
namespace ftxui {
|
||||
|
||||
/// @brief Define how the Screen's dimensions should look like.
|
||||
/// @ingroup screen
|
||||
namespace Dimension {
|
||||
Dimensions Fixed(int);
|
||||
Dimensions Full();
|
||||
} // namespace Dimension
|
||||
|
||||
/// @brief A rectangular grid of Pixel.
|
||||
/// @ingroup screen
|
||||
class Screen : public Image {
|
||||
public:
|
||||
// Constructors:
|
||||
Screen(int dimx, int dimy);
|
||||
static Screen Create(Dimensions dimension);
|
||||
static Screen Create(Dimensions width, Dimensions height);
|
||||
|
||||
// Destructor:
|
||||
~Screen() override = default;
|
||||
|
||||
std::string ToString() const;
|
||||
|
||||
// Print the Screen on to the terminal.
|
||||
void Print() const;
|
||||
|
||||
// Fill the screen with space and reset any screen state, like hyperlinks, and
|
||||
// cursor
|
||||
void Clear();
|
||||
|
||||
// Move the terminal cursor n-lines up with n = dimy().
|
||||
std::string ResetPosition(bool clear = false) const;
|
||||
|
||||
void ApplyShader();
|
||||
|
||||
struct Cursor {
|
||||
int x = 0;
|
||||
int y = 0;
|
||||
|
||||
enum Shape {
|
||||
Hidden = 0,
|
||||
BlockBlinking = 1,
|
||||
Block = 2,
|
||||
UnderlineBlinking = 3,
|
||||
Underline = 4,
|
||||
BarBlinking = 5,
|
||||
Bar = 6,
|
||||
};
|
||||
Shape shape = Hidden;
|
||||
};
|
||||
|
||||
Cursor cursor() const { return cursor_; }
|
||||
void SetCursor(Cursor cursor) { cursor_ = cursor; }
|
||||
|
||||
// Store an hyperlink in the screen. Return the id of the hyperlink. The id is
|
||||
// used to identify the hyperlink when the user click on it.
|
||||
uint8_t RegisterHyperlink(const std::string& link);
|
||||
const std::string& Hyperlink(uint8_t id) const;
|
||||
|
||||
using SelectionStyle = std::function<void(Pixel&)>;
|
||||
const SelectionStyle& GetSelectionStyle() const;
|
||||
void SetSelectionStyle(SelectionStyle decorator);
|
||||
|
||||
protected:
|
||||
Cursor cursor_;
|
||||
std::vector<std::string> hyperlinks_ = {""};
|
||||
|
||||
// The current selection style. This is overridden by various dom elements.
|
||||
SelectionStyle selection_style_ = [](Pixel& pixel) {
|
||||
pixel.inverted ^= true;
|
||||
};
|
||||
};
|
||||
|
||||
} // namespace ftxui
|
||||
|
||||
#endif // FTXUI_SCREEN_SCREEN_HPP
|
||||
31
ftxui/include/ftxui/screen/string.hpp
Normal file
31
ftxui/include/ftxui/screen/string.hpp
Normal file
@@ -0,0 +1,31 @@
|
||||
// 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.
|
||||
#ifndef FTXUI_SCREEN_STRING_HPP
|
||||
#define FTXUI_SCREEN_STRING_HPP
|
||||
|
||||
#include <string> // for string, wstring, to_string
|
||||
#include <vector> // for vector
|
||||
|
||||
namespace ftxui {
|
||||
std::string to_string(const std::wstring& s);
|
||||
std::wstring to_wstring(const std::string& s);
|
||||
|
||||
template <typename T>
|
||||
std::wstring to_wstring(T s) {
|
||||
return to_wstring(std::to_string(s));
|
||||
}
|
||||
|
||||
int string_width(const std::string&);
|
||||
|
||||
// Split the string into a its glyphs. An empty one is inserted ater fullwidth
|
||||
// ones.
|
||||
std::vector<std::string> Utf8ToGlyphs(const std::string& input);
|
||||
|
||||
// Map every cells drawn by |input| to their corresponding Glyphs. Half-size
|
||||
// Glyphs takes one cell, full-size Glyphs take two cells.
|
||||
std::vector<int> CellToGlyphIndex(const std::string& input);
|
||||
|
||||
} // namespace ftxui
|
||||
|
||||
#endif /* end of include guard: FTXUI_SCREEN_STRING_HPP */
|
||||
36
ftxui/include/ftxui/screen/terminal.hpp
Normal file
36
ftxui/include/ftxui/screen/terminal.hpp
Normal file
@@ -0,0 +1,36 @@
|
||||
// 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.
|
||||
#ifndef FTXUI_SCREEN_TERMINAL_HPP
|
||||
#define FTXUI_SCREEN_TERMINAL_HPP
|
||||
|
||||
namespace ftxui {
|
||||
|
||||
/// @brief Dimensions is a structure that represents the size of the terminal
|
||||
/// @ingroup screen
|
||||
struct Dimensions {
|
||||
int dimx;
|
||||
int dimy;
|
||||
};
|
||||
|
||||
namespace Terminal {
|
||||
Dimensions Size();
|
||||
void SetFallbackSize(const Dimensions& fallbackSize);
|
||||
|
||||
/// @brief Color is an enumeration that represents the color support of the
|
||||
/// terminal.
|
||||
/// @ingroup screen
|
||||
enum Color {
|
||||
Palette1,
|
||||
Palette16,
|
||||
Palette256,
|
||||
TrueColor,
|
||||
};
|
||||
Color ColorSupport();
|
||||
void SetColorSupport(Color color);
|
||||
|
||||
} // namespace Terminal
|
||||
|
||||
} // namespace ftxui
|
||||
|
||||
#endif // FTXUI_SCREEN_TERMINAL_HPP
|
||||
32
ftxui/include/ftxui/util/autoreset.hpp
Normal file
32
ftxui/include/ftxui/util/autoreset.hpp
Normal file
@@ -0,0 +1,32 @@
|
||||
// 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.
|
||||
#ifndef FTXUI_UTIL_AUTORESET_HPP
|
||||
#define FTXUI_UTIL_AUTORESET_HPP
|
||||
|
||||
#include <utility>
|
||||
|
||||
namespace ftxui {
|
||||
|
||||
/// Assign a value to a variable, reset its old value when going out of scope.
|
||||
template <typename T>
|
||||
class AutoReset {
|
||||
public:
|
||||
AutoReset(T* variable, T new_value)
|
||||
: variable_(variable), previous_value_(std::move(*variable)) {
|
||||
*variable_ = std::move(new_value);
|
||||
}
|
||||
AutoReset(const AutoReset&) = delete;
|
||||
AutoReset(AutoReset&&) = delete;
|
||||
AutoReset& operator=(const AutoReset&) = delete;
|
||||
AutoReset& operator=(AutoReset&&) = delete;
|
||||
~AutoReset() { *variable_ = std::move(previous_value_); }
|
||||
|
||||
private:
|
||||
T* variable_;
|
||||
T previous_value_;
|
||||
};
|
||||
|
||||
} // namespace ftxui
|
||||
|
||||
#endif /* end of include guard: FTXUI_UTIL_AUTORESET_HPP */
|
||||
216
ftxui/include/ftxui/util/ref.hpp
Normal file
216
ftxui/include/ftxui/util/ref.hpp
Normal file
@@ -0,0 +1,216 @@
|
||||
// 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.
|
||||
#ifndef FTXUI_UTIL_REF_HPP
|
||||
#define FTXUI_UTIL_REF_HPP
|
||||
|
||||
#include <ftxui/screen/string.hpp>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <variant>
|
||||
#include <vector>
|
||||
|
||||
namespace ftxui {
|
||||
|
||||
/// @brief An adapter. Own or reference an immutable object.
|
||||
template <typename T>
|
||||
class ConstRef {
|
||||
public:
|
||||
ConstRef() = default;
|
||||
ConstRef(T t) : variant_(std::move(t)) {} // NOLINT
|
||||
ConstRef(const T* t) : variant_(t) {} // NOLINT
|
||||
ConstRef& operator=(ConstRef&&) noexcept = default;
|
||||
ConstRef(const ConstRef<T>&) = default;
|
||||
ConstRef(ConstRef<T>&&) noexcept = default;
|
||||
~ConstRef() = default;
|
||||
|
||||
// Make a "reseatable" reference
|
||||
ConstRef<T>& operator=(const ConstRef<T>&) = default;
|
||||
|
||||
// Accessors:
|
||||
const T& operator()() const { return *Address(); }
|
||||
const T& operator*() const { return *Address(); }
|
||||
const T* operator->() const { return Address(); }
|
||||
|
||||
private:
|
||||
std::variant<T, const T*> variant_ = T{};
|
||||
|
||||
const T* Address() const {
|
||||
return std::holds_alternative<T>(variant_) ? &std::get<T>(variant_)
|
||||
: std::get<const T*>(variant_);
|
||||
}
|
||||
};
|
||||
|
||||
/// @brief An adapter. Own or reference an mutable object.
|
||||
template <typename T>
|
||||
class Ref {
|
||||
public:
|
||||
Ref() = default;
|
||||
Ref(T t) : variant_(std::move(t)) {} // NOLINT
|
||||
Ref(T* t) : variant_(t) {} // NOLINT
|
||||
~Ref() = default;
|
||||
Ref& operator=(Ref&&) noexcept = default;
|
||||
Ref(const Ref<T>&) = default;
|
||||
Ref(Ref<T>&&) noexcept = default;
|
||||
|
||||
// Make a "reseatable" reference.
|
||||
Ref<T>& operator=(const Ref<T>&) = default;
|
||||
|
||||
// Accessors:
|
||||
T& operator()() { return *Address(); }
|
||||
T& operator*() { return *Address(); }
|
||||
T* operator->() { return Address(); }
|
||||
const T& operator()() const { return *Address(); }
|
||||
const T& operator*() const { return *Address(); }
|
||||
const T* operator->() const { return Address(); }
|
||||
|
||||
private:
|
||||
std::variant<T, T*> variant_ = T{};
|
||||
|
||||
const T* Address() const {
|
||||
return std::holds_alternative<T>(variant_) ? &std::get<T>(variant_)
|
||||
: std::get<T*>(variant_);
|
||||
}
|
||||
T* Address() {
|
||||
return std::holds_alternative<T>(variant_) ? &std::get<T>(variant_)
|
||||
: std::get<T*>(variant_);
|
||||
}
|
||||
};
|
||||
|
||||
/// @brief An adapter. Own or reference a constant string. For convenience, this
|
||||
/// class convert multiple mutable string toward a shared representation.
|
||||
class StringRef : public Ref<std::string> {
|
||||
public:
|
||||
using Ref<std::string>::Ref;
|
||||
|
||||
StringRef(const wchar_t* ref) // NOLINT
|
||||
: StringRef(to_string(std::wstring(ref))) {}
|
||||
StringRef(const char* ref) // NOLINT
|
||||
: StringRef(std::string(ref)) {}
|
||||
};
|
||||
|
||||
/// @brief An adapter. Own or reference a constant string. For convenience, this
|
||||
/// class convert multiple immutable string toward a shared representation.
|
||||
class ConstStringRef : public ConstRef<std::string> {
|
||||
public:
|
||||
using ConstRef<std::string>::ConstRef;
|
||||
|
||||
ConstStringRef(const std::wstring* ref) // NOLINT
|
||||
: ConstStringRef(to_string(*ref)) {}
|
||||
ConstStringRef(const std::wstring ref) // NOLINT
|
||||
: ConstStringRef(to_string(ref)) {}
|
||||
ConstStringRef(const wchar_t* ref) // NOLINT
|
||||
: ConstStringRef(to_string(std::wstring(ref))) {}
|
||||
ConstStringRef(const char* ref) // NOLINT
|
||||
: ConstStringRef(std::string(ref)) {}
|
||||
};
|
||||
|
||||
/// @brief An adapter. Reference a list of strings.
|
||||
///
|
||||
/// Supported input:
|
||||
/// - `std::vector<std::string>`
|
||||
/// - `std::vector<std::string>*`
|
||||
/// - `std::vector<std::wstring>*`
|
||||
/// - `Adapter*`
|
||||
/// - `std::unique_ptr<Adapter>`
|
||||
class ConstStringListRef {
|
||||
public:
|
||||
// Bring your own adapter:
|
||||
class Adapter {
|
||||
public:
|
||||
Adapter() = default;
|
||||
Adapter(const Adapter&) = default;
|
||||
Adapter& operator=(const Adapter&) = default;
|
||||
Adapter(Adapter&&) = default;
|
||||
Adapter& operator=(Adapter&&) = default;
|
||||
virtual ~Adapter() = default;
|
||||
virtual size_t size() const = 0;
|
||||
virtual std::string operator[](size_t i) const = 0;
|
||||
};
|
||||
using Variant = std::variant<const std::vector<std::string>, //
|
||||
const std::vector<std::string>*, //
|
||||
const std::vector<std::wstring>*, //
|
||||
Adapter*, //
|
||||
std::unique_ptr<Adapter> //
|
||||
>;
|
||||
|
||||
ConstStringListRef() = default;
|
||||
~ConstStringListRef() = default;
|
||||
ConstStringListRef& operator=(const ConstStringListRef&) = default;
|
||||
ConstStringListRef& operator=(ConstStringListRef&&) = default;
|
||||
ConstStringListRef(ConstStringListRef&&) = default;
|
||||
ConstStringListRef(const ConstStringListRef&) = default;
|
||||
|
||||
ConstStringListRef(std::vector<std::string> value) // NOLINT
|
||||
{
|
||||
variant_ = std::make_shared<Variant>(value);
|
||||
}
|
||||
ConstStringListRef(const std::vector<std::string>* value) // NOLINT
|
||||
{
|
||||
variant_ = std::make_shared<Variant>(value);
|
||||
}
|
||||
ConstStringListRef(const std::vector<std::wstring>* value) // NOLINT
|
||||
{
|
||||
variant_ = std::make_shared<Variant>(value);
|
||||
}
|
||||
ConstStringListRef(Adapter* adapter) // NOLINT
|
||||
{
|
||||
variant_ = std::make_shared<Variant>(adapter);
|
||||
}
|
||||
template <typename AdapterType>
|
||||
ConstStringListRef(std::unique_ptr<AdapterType> adapter) // NOLINT
|
||||
{
|
||||
variant_ = std::make_shared<Variant>(
|
||||
static_cast<std::unique_ptr<Adapter>>(std::move(adapter)));
|
||||
}
|
||||
|
||||
size_t size() const {
|
||||
return variant_ ? std::visit(SizeVisitor(), *variant_) : 0;
|
||||
}
|
||||
|
||||
std::string operator[](size_t i) const {
|
||||
return variant_ ? std::visit(IndexedGetter(i), *variant_) : "";
|
||||
}
|
||||
|
||||
private:
|
||||
struct SizeVisitor {
|
||||
size_t operator()(const std::vector<std::string>& v) const {
|
||||
return v.size();
|
||||
}
|
||||
size_t operator()(const std::vector<std::string>* v) const {
|
||||
return v->size();
|
||||
}
|
||||
size_t operator()(const std::vector<std::wstring>* v) const {
|
||||
return v->size();
|
||||
}
|
||||
size_t operator()(const Adapter* v) const { return v->size(); }
|
||||
size_t operator()(const std::unique_ptr<Adapter>& v) const {
|
||||
return v->size();
|
||||
}
|
||||
};
|
||||
|
||||
struct IndexedGetter {
|
||||
IndexedGetter(size_t index) // NOLINT
|
||||
: index_(index) {}
|
||||
size_t index_;
|
||||
std::string operator()(const std::vector<std::string>& v) const {
|
||||
return v[index_];
|
||||
}
|
||||
std::string operator()(const std::vector<std::string>* v) const {
|
||||
return (*v)[index_];
|
||||
}
|
||||
std::string operator()(const std::vector<std::wstring>* v) const {
|
||||
return to_string((*v)[index_]);
|
||||
}
|
||||
std::string operator()(const Adapter* v) const { return (*v)[index_]; }
|
||||
std::string operator()(const std::unique_ptr<Adapter>& v) const {
|
||||
return (*v)[index_];
|
||||
}
|
||||
};
|
||||
|
||||
std::shared_ptr<Variant> variant_;
|
||||
};
|
||||
|
||||
} // namespace ftxui
|
||||
|
||||
#endif /* end of include guard: FTXUI_UTIL_REF_HPP */
|
||||
18
ftxui/include/ftxui/util/warn_windows_macro.hpp
Normal file
18
ftxui/include/ftxui/util/warn_windows_macro.hpp
Normal file
@@ -0,0 +1,18 @@
|
||||
// Copyright 2025 Arthur Sonzogni. All rights reserved.
|
||||
// Use of this source code is governed by the MIT license that can be found in
|
||||
// the LICENSE file.
|
||||
|
||||
#ifndef FTXUI_UTIL_WARN_WINDOWS_MACRO_H_
|
||||
#define FTXUI_UTIL_WARN_WINDOWS_MACRO_H_
|
||||
|
||||
#ifdef min
|
||||
#error \
|
||||
"The macro 'min' is defined, which conflicts with the standard C++ library and FTXUI. This is often caused by including <windows.h>. To fix this, add '#define NOMINMAX' before including <windows.h>, or pass '/DNOMINMAX' as a compiler flag."
|
||||
#endif
|
||||
|
||||
#ifdef max
|
||||
#error \
|
||||
"The macro 'max' is defined, which conflicts with the standard C++ library and FTXUI. This is often caused by including <windows.h>. To fix this, add '#define NOMINMAX' before including <windows.h>, or pass '/DNOMINMAX' as a compiler flag."
|
||||
#endif
|
||||
|
||||
#endif // FTXUI_UTIL_WARN_WINDOWS_MACRO_H_
|
||||
Reference in New Issue
Block a user