mirror of
https://github.com/ArthurSonzogni/FTXUI.git
synced 2025-09-19 01:38:08 +08:00
Compare commits
8 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
513ec6c5e1 | ||
![]() |
234b3c8a5d | ||
![]() |
6ce88c25e5 | ||
![]() |
f74c5322bd | ||
![]() |
1e86587b68 | ||
![]() |
41c3d4dd52 | ||
![]() |
2fb0b77f02 | ||
![]() |
e2aff66b98 |
9
.github/workflows/build.yaml
vendored
9
.github/workflows/build.yaml
vendored
@@ -66,7 +66,8 @@ jobs:
|
||||
-DFTXUI_BUILD_EXAMPLES:BOOL=ON
|
||||
-DFTXUI_BUILD_TESTS:BOOL=ON
|
||||
-DFTXUI_BUILD_TESTS_FUZZER:BOOL=OFF
|
||||
-DFTXUI_ENABLE_INSTALL:BOOL=ON ;
|
||||
-DFTXUI_ENABLE_INSTALL:BOOL=ON
|
||||
-DFTXUI_DEV_WARNINGS:BOOL=ON ;
|
||||
|
||||
- name: "Build"
|
||||
run: >
|
||||
@@ -160,7 +161,8 @@ jobs:
|
||||
-DFTXUI_BUILD_EXAMPLES=OFF
|
||||
-DFTXUI_BUILD_TESTS=OFF
|
||||
-DFTXUI_BUILD_TESTS_FUZZER=OFF
|
||||
-DFTXUI_ENABLE_INSTALL=ON;
|
||||
-DFTXUI_ENABLE_INSTALL=ON
|
||||
-DFTXUI_DEV_WARNINGS=ON ;
|
||||
cmake --build . --target package;
|
||||
- uses: shogo82148/actions-upload-release-asset@v1
|
||||
with:
|
||||
@@ -196,7 +198,8 @@ jobs:
|
||||
-DFTXUI_BUILD_EXAMPLES=ON
|
||||
-DFTXUI_BUILD_TESTS=OFF
|
||||
-DFTXUI_BUILD_TESTS_FUZZER=OFF
|
||||
-DFTXUI_ENABLE_INSTALL=OFF;
|
||||
-DFTXUI_ENABLE_INSTALL=OFF
|
||||
-DFTXUI_DEV_WARNINGS=ON ;
|
||||
cmake --build . --target doc;
|
||||
cmake --build . ;
|
||||
rsync -amv
|
||||
|
11
CHANGELOG.md
11
CHANGELOG.md
@@ -1,7 +1,16 @@
|
||||
Changelog
|
||||
=========
|
||||
|
||||
4.1.0
|
||||
4.1.1
|
||||
-----
|
||||
|
||||
### Component
|
||||
- Revert Feature: Support `ResizableSplit` with customizable separator.
|
||||
|
||||
### Build
|
||||
- Check version compatibility when using cmake find_package()
|
||||
|
||||
4.1.0 (abandonned)
|
||||
-----
|
||||
|
||||
### Component
|
||||
|
@@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.11)
|
||||
|
||||
project(ftxui
|
||||
LANGUAGES CXX
|
||||
VERSION 4.1.0
|
||||
VERSION 4.1.1
|
||||
DESCRIPTION "C++ Functional Terminal User Interface."
|
||||
)
|
||||
|
||||
@@ -13,6 +13,7 @@ option(FTXUI_BUILD_TESTS_FUZZER "Set to ON to enable fuzzing" OFF)
|
||||
option(FTXUI_ENABLE_INSTALL "Generate the install target" ON)
|
||||
option(FTXUI_CLANG_TIDY "Execute clang-tidy" OFF)
|
||||
option(FTXUI_ENABLE_COVERAGE "Execute code coverage" OFF)
|
||||
option(FTXUI_DEV_WARNINGS "Enable more compiler warnings and warnings as errors" OFF)
|
||||
|
||||
set(FTXUI_MICROSOFT_TERMINAL_FALLBACK_HELP_TEXT "On windows, assume the \
|
||||
terminal used will be one of Microsoft and use a set of reasonnable fallback \
|
||||
@@ -43,7 +44,6 @@ add_library(screen
|
||||
|
||||
add_library(dom
|
||||
include/ftxui/dom/canvas.hpp
|
||||
include/ftxui/dom/direction.hpp
|
||||
include/ftxui/dom/elements.hpp
|
||||
include/ftxui/dom/flexbox_config.hpp
|
||||
include/ftxui/dom/node.hpp
|
||||
|
@@ -2,3 +2,5 @@
|
||||
|
||||
include(CMakeFindDependencyMacro)
|
||||
find_dependency(Threads)
|
||||
|
||||
include("${CMAKE_CURRENT_LIST_DIR}/ftxui-targets.cmake")
|
@@ -10,18 +10,11 @@ function(fuzz name)
|
||||
add_executable(${name}
|
||||
src/ftxui/component/${name}.cpp
|
||||
)
|
||||
target_include_directories(${name}
|
||||
PRIVATE src
|
||||
)
|
||||
target_link_libraries(${name}
|
||||
PRIVATE component
|
||||
)
|
||||
target_compile_options(${name}
|
||||
PRIVATE -fsanitize=fuzzer,address
|
||||
)
|
||||
target_link_libraries(${name}
|
||||
PRIVATE -fsanitize=fuzzer,address
|
||||
)
|
||||
target_include_directories(${name} PRIVATE src)
|
||||
target_link_libraries(${name} PRIVATE component)
|
||||
target_compile_options(${name} PRIVATE -fsanitize=fuzzer,address)
|
||||
target_link_libraries(${name} PRIVATE -fsanitize=fuzzer,address)
|
||||
target_compile_features(${name} PRIVATE cxx_std_17)
|
||||
endfunction(fuzz)
|
||||
|
||||
fuzz(terminal_input_parser_test_fuzzer)
|
||||
|
@@ -3,41 +3,60 @@ if(NOT FTXUI_ENABLE_INSTALL)
|
||||
endif()
|
||||
|
||||
include(GNUInstallDirs)
|
||||
install(TARGETS screen dom component
|
||||
EXPORT ftxui-export
|
||||
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
)
|
||||
|
||||
install(DIRECTORY include/ftxui DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
|
||||
|
||||
# CMake package configuration for easy use of library in CMake
|
||||
include(CMakePackageConfigHelpers)
|
||||
configure_package_config_file(ftxui-config.cmake.in
|
||||
${CMAKE_CURRENT_BINARY_DIR}/ftxui-config.cmake
|
||||
INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/ftxui/cmake
|
||||
PATH_VARS CMAKE_INSTALL_INCLUDEDIR
|
||||
)
|
||||
write_basic_package_version_file(
|
||||
ftxui-config-version.cmake
|
||||
VERSION ${PACKAGE_VERSION}
|
||||
COMPATIBILITY AnyNewerVersion
|
||||
)
|
||||
|
||||
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/ftxui-config.cmake
|
||||
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/ftxui
|
||||
)
|
||||
install(EXPORT ftxui-export
|
||||
FILE ftxui-config-version.cmake
|
||||
# ------------------------------------------------------------------------------
|
||||
# Install the library and its public headers into the standard subdirectories
|
||||
# ------------------------------------------------------------------------------
|
||||
install(
|
||||
TARGETS screen dom component
|
||||
EXPORT ftxui-targets
|
||||
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
)
|
||||
|
||||
install(
|
||||
DIRECTORY include/ftxui
|
||||
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
|
||||
)
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Install the exported cmake targets for use in other CMake projects.
|
||||
# ------------------------------------------------------------------------------
|
||||
install(
|
||||
EXPORT ftxui-targets
|
||||
NAMESPACE ftxui::
|
||||
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/ftxui
|
||||
)
|
||||
)
|
||||
|
||||
# pkg-config file for easy use of library in build systems other than CMake
|
||||
configure_file(ftxui.pc.in
|
||||
${CMAKE_CURRENT_BINARY_DIR}/ftxui.pc
|
||||
@ONLY)
|
||||
# ------------------------------------------------------------------------------
|
||||
# Create and install the ftuxi-config.cmake and ftuxi-config-version.cmake files
|
||||
# needed to support users of find_package()
|
||||
# ------------------------------------------------------------------------------
|
||||
configure_package_config_file(
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/cmake/ftxui-config.cmake.in
|
||||
${CMAKE_CURRENT_BINARY_DIR}/cmake/ftxui-config.cmake
|
||||
INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/ftxui/cmake
|
||||
PATH_VARS CMAKE_INSTALL_INCLUDEDIR
|
||||
)
|
||||
write_basic_package_version_file(
|
||||
${CMAKE_CURRENT_BINARY_DIR}/cmake/ftxui-config-version.cmake
|
||||
VERSION ${PACKAGE_VERSION}
|
||||
COMPATIBILITY SameMajorVersion
|
||||
)
|
||||
install(
|
||||
FILES
|
||||
${CMAKE_CURRENT_BINARY_DIR}/cmake/ftxui-config.cmake
|
||||
${CMAKE_CURRENT_BINARY_DIR}/cmake/ftxui-config-version.cmake
|
||||
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/ftxui
|
||||
)
|
||||
|
||||
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/ftxui.pc
|
||||
DESTINATION lib/pkgconfig
|
||||
)
|
||||
# ------------------------------------------------------------------------------
|
||||
# Create and install pkg-config file for easy use of library in build systems
|
||||
# other than CMake:
|
||||
# ------------------------------------------------------------------------------
|
||||
configure_file(ftxui.pc.in ${CMAKE_CURRENT_BINARY_DIR}/ftxui.pc @ONLY)
|
||||
install(
|
||||
FILES ${CMAKE_CURRENT_BINARY_DIR}/ftxui.pc
|
||||
DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
)
|
||||
|
@@ -43,19 +43,7 @@ function(ftxui_set_options library)
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
|
||||
)
|
||||
|
||||
# Play nicely if we are being consumed by another project
|
||||
# and use their CMAKE_CXX_STANDARD. Otherwise, fall back to 17
|
||||
# C++17 is used. We require fold expression at least.
|
||||
if (DEFINED CMAKE_CXX_STANDARD)
|
||||
set(CXX_STANDARD ${CMAKE_CXX_STANDARD})
|
||||
else()
|
||||
set(CXX_STANDARD 17)
|
||||
endif()
|
||||
|
||||
set_target_properties(${library} PROPERTIES
|
||||
CXX_STANDARD ${CXX_STANDARD}
|
||||
CXX_EXTENSIONS OFF
|
||||
)
|
||||
target_compile_features(${library} PUBLIC cxx_std_17)
|
||||
|
||||
# Force Microsoft Visual Studio to decode sources files in UTF-8. This applies
|
||||
# to the library and the library users.
|
||||
@@ -66,8 +54,10 @@ function(ftxui_set_options library)
|
||||
# Add as many warning as possible:
|
||||
if (WIN32)
|
||||
if (MSVC)
|
||||
target_compile_options(${library} PRIVATE "/W3")
|
||||
target_compile_options(${library} PRIVATE "/WX")
|
||||
if(FTXUI_DEV_WARNINGS)
|
||||
target_compile_options(${library} PRIVATE "/W3")
|
||||
target_compile_options(${library} PRIVATE "/WX")
|
||||
endif()
|
||||
target_compile_options(${library} PRIVATE "/wd4244")
|
||||
target_compile_options(${library} PRIVATE "/wd4267")
|
||||
target_compile_options(${library} PRIVATE "/D_CRT_SECURE_NO_WARNINGS")
|
||||
@@ -75,13 +65,21 @@ function(ftxui_set_options library)
|
||||
# Force Win32 to UNICODE
|
||||
target_compile_definitions(${library} PRIVATE UNICODE _UNICODE)
|
||||
else()
|
||||
target_compile_options(${library} PRIVATE "-Wall")
|
||||
target_compile_options(${library} PRIVATE "-Wextra")
|
||||
target_compile_options(${library} PRIVATE "-pedantic")
|
||||
target_compile_options(${library} PRIVATE "-Werror")
|
||||
target_compile_options(${library} PRIVATE "-Wmissing-declarations")
|
||||
target_compile_options(${library} PRIVATE "-Wdeprecated")
|
||||
target_compile_options(${library} PRIVATE "-Wshadow")
|
||||
if(FTXUI_DEV_WARNINGS)
|
||||
target_compile_options(${library} PRIVATE "-Wall")
|
||||
target_compile_options(${library} PRIVATE "-Werror")
|
||||
target_compile_options(${library} PRIVATE "-Wextra")
|
||||
|
||||
target_compile_options(${library} PRIVATE "-Wcast-align")
|
||||
target_compile_options(${library} PRIVATE "-Wdeprecated")
|
||||
target_compile_options(${library} PRIVATE "-Wmissing-declarations")
|
||||
target_compile_options(${library} PRIVATE "-Wnon-virtual-dtor")
|
||||
target_compile_options(${library} PRIVATE "-Wnull-dereference")
|
||||
target_compile_options(${library} PRIVATE "-Woverloaded-virtual")
|
||||
target_compile_options(${library} PRIVATE "-Wpedantic")
|
||||
target_compile_options(${library} PRIVATE "-Wshadow")
|
||||
target_compile_options(${library} PRIVATE "-Wunused")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if (FTXUI_MICROSOFT_TERMINAL_FALLBACK)
|
||||
|
@@ -57,8 +57,12 @@ target_link_libraries(ftxui-tests
|
||||
target_include_directories(ftxui-tests
|
||||
PRIVATE src
|
||||
)
|
||||
ftxui_set_options(ftxui-tests)
|
||||
target_compile_features(ftxui-tests PUBLIC cxx_std_20)
|
||||
target_compile_features(ftxui-tests PRIVATE cxx_std_20)
|
||||
|
||||
if (FTXUI_MICROSOFT_TERMINAL_FALLBACK)
|
||||
target_compile_definitions(ftxui-tests
|
||||
PRIVATE "FTXUI_MICROSOFT_TERMINAL_FALLBACK")
|
||||
endif()
|
||||
|
||||
include(GoogleTest)
|
||||
gtest_discover_tests(ftxui-tests
|
||||
|
@@ -8,9 +8,7 @@ function(example name)
|
||||
target_link_libraries(ftxui_example_${name} PUBLIC ${DIRECTORY_LIB})
|
||||
file(RELATIVE_PATH dir ${EXAMPLES_DIR} ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
set_property(GLOBAL APPEND PROPERTY FTXUI::EXAMPLES ${dir}/${name})
|
||||
set_target_properties(ftxui_example_${name} PROPERTIES
|
||||
CXX_STANDARD 20
|
||||
)
|
||||
target_compile_features(ftxui_example_${name} PRIVATE cxx_std_17)
|
||||
endfunction(example)
|
||||
|
||||
add_subdirectory(component)
|
||||
|
@@ -2,10 +2,9 @@
|
||||
#include <cmath> // for sin
|
||||
#include <ftxui/component/component_base.hpp> // for ComponentBase
|
||||
#include <ftxui/component/component_options.hpp> // for SliderOption
|
||||
#include <ftxui/dom/direction.hpp> // for Direction, Direction::Up
|
||||
#include <ftxui/dom/elements.hpp> // for size, GREATER_THAN, HEIGHT
|
||||
#include <ftxui/util/ref.hpp> // for ConstRef, Ref
|
||||
#include <memory> // for shared_ptr, __shared_ptr_access
|
||||
#include <ftxui/dom/elements.hpp> // for size, GREATER_THAN, GaugeDirection, GaugeDirection::Up, HEIGHT
|
||||
#include <ftxui/util/ref.hpp> // for ConstRef, Ref
|
||||
#include <memory> // for shared_ptr, __shared_ptr_access
|
||||
|
||||
#include "ftxui/component/captured_mouse.hpp" // for ftxui
|
||||
#include "ftxui/component/component.hpp" // for Horizontal, Slider, operator|=
|
||||
@@ -27,7 +26,7 @@ int main(int argc, const char* argv[]) {
|
||||
option.value = &values[i];
|
||||
option.max = 100;
|
||||
option.increment = 5;
|
||||
option.direction = Direction::Up;
|
||||
option.direction = GaugeDirection::Up;
|
||||
layout_horizontal->Add(Slider<int>(option));
|
||||
|
||||
/* In C++20:
|
||||
@@ -35,7 +34,7 @@ int main(int argc, const char* argv[]) {
|
||||
.value = &values[i],
|
||||
.max = 100,
|
||||
.increment = 5,
|
||||
.direction = Direction::Up,
|
||||
.direction = GaugeDirection::Up,
|
||||
}));
|
||||
*/
|
||||
}
|
||||
|
@@ -18,7 +18,7 @@ void RequestAnimationFrame();
|
||||
|
||||
using Clock = std::chrono::steady_clock;
|
||||
using TimePoint = std::chrono::time_point<Clock>;
|
||||
using Duration = std::chrono::duration<float>;
|
||||
using Duration = std::chrono::duration<double>;
|
||||
|
||||
// Parameter of Component::OnAnimation(param).
|
||||
class Params {
|
||||
|
@@ -92,7 +92,6 @@ 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 ResizableSplit(ResizableSplitOption options);
|
||||
|
||||
Component Renderer(Component child, std::function<Element()>);
|
||||
Component Renderer(std::function<Element()>);
|
||||
|
@@ -3,14 +3,12 @@
|
||||
|
||||
#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
|
||||
#include <functional> // for function
|
||||
#include <optional> // for optional
|
||||
#include <string> // for string
|
||||
#include <ftxui/dom/elements.hpp> // for Element, GaugeDirection, GaugeDirection::Right
|
||||
#include <ftxui/util/ref.hpp> // for Ref, ConstRef
|
||||
#include <functional> // for function
|
||||
#include <optional> // for optional
|
||||
#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 {
|
||||
@@ -89,7 +87,8 @@ struct MenuOption {
|
||||
// Style:
|
||||
UnderlineOption underline;
|
||||
MenuEntryOption entries;
|
||||
Direction direction = Direction::Down;
|
||||
enum Direction { Up, Down, Left, Right };
|
||||
Direction direction = Down;
|
||||
std::function<Element()> elements_prefix;
|
||||
std::function<Element()> elements_infix;
|
||||
std::function<Element()> elements_postfix;
|
||||
@@ -165,16 +164,6 @@ struct RadioboxOption {
|
||||
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>
|
||||
@@ -183,7 +172,7 @@ struct SliderOption {
|
||||
ConstRef<T> min = T(0);
|
||||
ConstRef<T> max = T(100);
|
||||
ConstRef<T> increment = (max() - min()) / 20;
|
||||
Direction direction = Direction::Right;
|
||||
GaugeDirection direction = GaugeDirection::Right;
|
||||
Color color_active = Color::White;
|
||||
Color color_inactive = Color::GrayDark;
|
||||
};
|
||||
|
@@ -1,17 +0,0 @@
|
||||
#ifndef FTXUI_DOM_DIRECTION_HPP
|
||||
#define FTXUI_DOM_DIRECTION_HPP
|
||||
|
||||
namespace ftxui {
|
||||
enum class Direction {
|
||||
Up = 0,
|
||||
Down = 1,
|
||||
Left = 2,
|
||||
Right = 3,
|
||||
};
|
||||
|
||||
} // namespace ftxui
|
||||
|
||||
#endif // FTXUI_DOM_DIRECTION_HPP
|
||||
// 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.
|
@@ -5,7 +5,6 @@
|
||||
#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"
|
||||
@@ -31,6 +30,8 @@ enum BorderStyle {
|
||||
EMPTY,
|
||||
};
|
||||
|
||||
enum class GaugeDirection { Left, Up, Right, Down };
|
||||
|
||||
// Pipe elements into decorator togethers.
|
||||
// For instance the next lines are equivalents:
|
||||
// -> text("ftxui") | bold | underlined
|
||||
@@ -65,7 +66,7 @@ Element gaugeLeft(float progress);
|
||||
Element gaugeRight(float progress);
|
||||
Element gaugeUp(float progress);
|
||||
Element gaugeDown(float progress);
|
||||
Element gaugeDirection(float progress, Direction direction);
|
||||
Element gaugeDirection(float progress, GaugeDirection);
|
||||
Element border(Element);
|
||||
Element borderLight(Element);
|
||||
Element borderDashed(Element);
|
||||
@@ -140,9 +141,9 @@ Element notflex(Element); // Reset the flex attribute.
|
||||
Element filler(); // A blank expandable element.
|
||||
|
||||
// -- Size override;
|
||||
enum WidthOrHeight { WIDTH, HEIGHT };
|
||||
enum Direction { WIDTH, HEIGHT };
|
||||
enum Constraint { LESS_THAN, EQUAL, GREATER_THAN };
|
||||
Decorator size(WidthOrHeight, Constraint, int value);
|
||||
Decorator size(Direction, Constraint, int value);
|
||||
|
||||
// --- Frame ---
|
||||
// A frame is a scrollable area. The internal area is potentially larger than
|
||||
|
@@ -9,8 +9,8 @@ namespace ftxui::animation {
|
||||
namespace easing {
|
||||
|
||||
namespace {
|
||||
constexpr float kPi = 3.14159265358979323846f;
|
||||
constexpr float kPi2 = kPi / 2.f;
|
||||
constexpr float kPi = 3.14159265358979323846F;
|
||||
constexpr float kPi2 = kPi / 2.F;
|
||||
} // namespace
|
||||
|
||||
// Easing function have been taken out of:
|
||||
@@ -37,16 +37,18 @@ float QuadraticIn(float p) {
|
||||
|
||||
// Modeled after the parabola y = -x^2 + 2x
|
||||
float QuadraticOut(float p) {
|
||||
return -(p * (p - 2.f));
|
||||
return -(p * (p - 2));
|
||||
}
|
||||
|
||||
// Modeled after the piecewise quadratic
|
||||
// y = (1/2)((2x)^2) ; [0, 0.5)
|
||||
// y = -(1/2)((2x-1)*(2x-3) - 1) ; [0.5, 1]
|
||||
float QuadraticInOut(float p) {
|
||||
return p < 0.5f // NOLINT
|
||||
? 2.f * p * p // NOLINT
|
||||
: (-2.f * p * p) + (4.f * p) - 1.f; // NOLINT
|
||||
if (p < 0.5F) { // NOLINT
|
||||
return 2 * p * p;
|
||||
} else {
|
||||
return (-2 * p * p) + (4 * p) - 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Modeled after the cubic y = x^3
|
||||
@@ -56,19 +58,20 @@ float CubicIn(float p) {
|
||||
|
||||
// Modeled after the cubic y = (x - 1)^3 + 1
|
||||
float CubicOut(float p) {
|
||||
const float f = (p - 1.f);
|
||||
return f * f * f + 1.f;
|
||||
const float f = (p - 1);
|
||||
return f * f * f + 1;
|
||||
}
|
||||
|
||||
// Modeled after the piecewise cubic
|
||||
// y = (1/2)((2x)^3) ; [0, 0.5)
|
||||
// y = (1/2)((2x-2)^3 + 2) ; [0.5, 1]
|
||||
float CubicInOut(float p) {
|
||||
if (p < 0.5f) { // NOLINT
|
||||
return 4.f * p * p * p;
|
||||
if (p < 0.5F) { // NOLINT
|
||||
return 4 * p * p * p;
|
||||
} else {
|
||||
const float f = ((2 * p) - 2);
|
||||
return 0.5F * f * f * f + 1; // NOLINT
|
||||
}
|
||||
const float f = ((2.f * p) - 2.f);
|
||||
return 0.5f * f * f * f + 1.f; // NOLINT
|
||||
}
|
||||
|
||||
// Modeled after the quartic x^4
|
||||
@@ -78,19 +81,20 @@ float QuarticIn(float p) {
|
||||
|
||||
// Modeled after the quartic y = 1 - (x - 1)^4
|
||||
float QuarticOut(float p) {
|
||||
const float f = (p - 1.f);
|
||||
return f * f * f * (1.f - p) + 1.f;
|
||||
const float f = (p - 1);
|
||||
return f * f * f * (1 - p) + 1;
|
||||
}
|
||||
|
||||
// Modeled after the piecewise quartic
|
||||
// y = (1/2)((2x)^4) ; [0, 0.5)
|
||||
// y = -(1/2)((2x-2)^4 - 2) ; [0.5, 1]
|
||||
float QuarticInOut(float p) {
|
||||
if (p < 0.5f) { // NOLINT
|
||||
return 8.f * p * p * p * p; // NOLINT
|
||||
if (p < 0.5F) { // NOLINT
|
||||
return 8 * p * p * p * p; // NOLINT
|
||||
} else {
|
||||
const float f = (p - 1);
|
||||
return -8 * f * f * f * f + 1; // NOLINT
|
||||
}
|
||||
const float f = (p - 1.f);
|
||||
return -8.f * f * f * f * f + 1.f; // NOLINT
|
||||
}
|
||||
|
||||
// Modeled after the quintic y = x^5
|
||||
@@ -100,24 +104,25 @@ float QuinticIn(float p) {
|
||||
|
||||
// Modeled after the quintic y = (x - 1)^5 + 1
|
||||
float QuinticOut(float p) {
|
||||
const float f = (p - 1.f);
|
||||
return f * f * f * f * f + 1.f;
|
||||
const float f = (p - 1);
|
||||
return f * f * f * f * f + 1;
|
||||
}
|
||||
|
||||
// Modeled after the piecewise quintic
|
||||
// y = (1/2)((2x)^5) ; [0, 0.5)
|
||||
// y = (1/2)((2x-2)^5 + 2) ; [0.5, 1]
|
||||
float QuinticInOut(float p) {
|
||||
if (p < 0.5f) { // NOLINT
|
||||
return 16.f * p * p * p * p * p; // NOLINT
|
||||
if (p < 0.5F) { // NOLINT
|
||||
return 16 * p * p * p * p * p; // NOLINT
|
||||
} else { // NOLINT
|
||||
float f = ((2 * p) - 2); // NOLINT
|
||||
return 0.5 * f * f * f * f * f + 1; // NOLINT
|
||||
}
|
||||
float f = ((2.f * p) - 2.f); // NOLINT
|
||||
return 0.5f * f * f * f * f * f + 1.f; // NOLINT
|
||||
}
|
||||
|
||||
// Modeled after quarter-cycle of sine wave
|
||||
float SineIn(float p) {
|
||||
return std::sin((p - 1.f) * kPi2) + 1.f;
|
||||
return std::sin((p - 1) * kPi2) + 1;
|
||||
}
|
||||
|
||||
// Modeled after quarter-cycle of sine wave (different phase)
|
||||
@@ -127,77 +132,79 @@ float SineOut(float p) {
|
||||
|
||||
// Modeled after half sine wave
|
||||
float SineInOut(float p) {
|
||||
return 0.5f * (1.f - std::cos(p * kPi)); // NOLINT
|
||||
return 0.5F * (1 - std::cos(p * kPi)); // NOLINT
|
||||
}
|
||||
|
||||
// Modeled after shifted quadrant IV of unit circle
|
||||
float CircularIn(float p) {
|
||||
return 1.f - std::sqrt(1.f - (p * p));
|
||||
return 1 - std::sqrt(1 - (p * p));
|
||||
}
|
||||
|
||||
// Modeled after shifted quadrant II of unit circle
|
||||
float CircularOut(float p) {
|
||||
return std::sqrt((2.f - p) * p);
|
||||
return std::sqrt((2 - p) * p);
|
||||
}
|
||||
|
||||
// Modeled after the piecewise circular function
|
||||
// y = (1/2)(1 - sqrt(1 - 4x^2)) ; [0, 0.5)
|
||||
// y = (1/2)(sqrt(-(2x - 3)*(2x - 1)) + 1) ; [0.5, 1]
|
||||
float CircularInOut(float p) {
|
||||
if (p < 0.5f) { // NOLINT
|
||||
return 0.5f * (1.f - std::sqrt(1.f - 4.f * (p * p))); // NOLINT
|
||||
if (p < 0.5F) { // NOLINT
|
||||
return 0.5F * (1 - std::sqrt(1 - 4 * (p * p))); // NOLINT
|
||||
} else {
|
||||
return 0.5F * (std::sqrt(-((2 * p) - 3) * ((2 * p) - 1)) + 1); // NOLINT
|
||||
}
|
||||
// NOLINTNEXTLINE
|
||||
return 0.5f * (std::sqrt(-((2.f * p) - 3.f) * ((2.f * p) - 1.f)) + 1.f);
|
||||
}
|
||||
|
||||
// Modeled after the exponential function y = 2^(10(x - 1))
|
||||
float ExponentialIn(float p) {
|
||||
return (p == 0.f) ? p : std::pow(2.f, 10.f * (p - 1.f)); // NOLINT
|
||||
return (p == 0.0) ? p : std::pow(2, 10 * (p - 1)); // NOLINT
|
||||
}
|
||||
|
||||
// Modeled after the exponential function y = -2^(-10x) + 1
|
||||
float ExponentialOut(float p) {
|
||||
return (p == 1.f) ? p : 1.f - std::pow(2.f, -10.f * p); // NOLINT
|
||||
return (p == 1.0) ? p : 1 - std::pow(2, -10 * p); // NOLINT
|
||||
}
|
||||
|
||||
// Modeled after the piecewise exponential
|
||||
// y = (1/2)2^(10(2x - 1)) ; [0,0.5)
|
||||
// y = -(1/2)*2^(-10(2x - 1))) + 1 ; [0.5,1]
|
||||
float ExponentialInOut(float p) {
|
||||
if (p == 0.f || p == 1.f) {
|
||||
if (p == 0.0 || p == 1.F) {
|
||||
return p;
|
||||
}
|
||||
|
||||
if (p < 0.5f) { // NOLINT
|
||||
return 0.5f * std::pow(2.f, (20.f * p) - 10.f); // NOLINT
|
||||
if (p < 0.5F) { // NOLINT
|
||||
return 0.5 * std::pow(2, (20 * p) - 10); // NOLINT
|
||||
} else { // NOLINT
|
||||
return -0.5 * std::pow(2, (-20 * p) + 10) + 1; // NOLINT
|
||||
}
|
||||
return -0.5f * std::pow(2.f, (-20.f * p) + 10.f) + 1.f; // NOLINT
|
||||
}
|
||||
|
||||
// Modeled after the damped sine wave y = sin(13pi/2*x)*pow(2, 10 * (x - 1))
|
||||
float ElasticIn(float p) {
|
||||
return std::sin(13.f * kPi2 * p) * std::pow(2.f, 10.f * (p - 1.f)); // NOLINT
|
||||
return std::sin(13.F * kPi2 * p) * std::pow(2.F, 10.F * (p - 1)); // NOLINT
|
||||
}
|
||||
|
||||
// Modeled after the damped sine wave y = sin(-13pi/2*(x + 1))*pow(2, -10x) +
|
||||
// 1
|
||||
float ElasticOut(float p) {
|
||||
// NOLINTNEXTLINE
|
||||
return std::sin(-13.f * kPi2 * (p + 1.f)) * std::pow(2.f, -10.f * p) + 1.f;
|
||||
return std::sin(-13.F * kPi2 * (p + 1)) * std::pow(2.F, -10.F * p) + 1;
|
||||
}
|
||||
|
||||
// Modeled after the piecewise exponentially-damped sine wave:
|
||||
// y = (1/2)*sin(13pi/2*(2*x))*pow(2, 10 * ((2*x) - 1)) ; [0,0.5)
|
||||
// y = (1/2)*(sin(-13pi/2*((2x-1)+1))*pow(2,-10(2*x-1)) + 2) ; [0.5, 1]
|
||||
float ElasticInOut(float p) {
|
||||
if (p < 0.5f) { // NOLINT
|
||||
return 0.5f * std::sin(13.f * kPi2 * (2.f * p)) * // NOLINT
|
||||
std::pow(2.f, 10.f * ((2.f * p) - 1.f)); // NOLINT
|
||||
if (p < 0.5F) { // NOLINT
|
||||
return 0.5 * std::sin(13.F * kPi2 * (2 * p)) * // NOLINT
|
||||
std::pow(2, 10 * ((2 * p) - 1)); // NOLINT
|
||||
} else { // NOLINT
|
||||
return 0.5 * (std::sin(-13.F * kPi2 * ((2 * p - 1) + 1)) * // NOLINT
|
||||
std::pow(2, -10 * (2 * p - 1)) + // NOLINT
|
||||
2); // NOLINT
|
||||
}
|
||||
return 0.5f * (std::sin(-13.f * kPi2 * ((2.f * p - 1.f) + 1.f)) * // NOLINT
|
||||
std::pow(2.f, -10.f * (2.f * p - 1.f)) + // NOLINT
|
||||
2.f); // NOLINT
|
||||
}
|
||||
|
||||
// Modeled after the overshooting cubic y = x^3-x*sin(x*pi)
|
||||
@@ -207,48 +214,46 @@ float BackIn(float p) {
|
||||
|
||||
// Modeled after overshooting cubic y = 1-((1-x)^3-(1-x)*sin((1-x)*pi))
|
||||
float BackOut(float p) {
|
||||
const float f = (1.f - p);
|
||||
return 1.f - (f * f * f - f * std::sin(f * kPi));
|
||||
const float f = (1 - p);
|
||||
return 1 - (f * f * f - f * std::sin(f * kPi));
|
||||
}
|
||||
|
||||
// Modeled after the piecewise overshooting cubic function:
|
||||
// y = (1/2)*((2x)^3-(2x)*sin(2*x*pi)) ; [0, 0.5)
|
||||
// y = (1/2)*(1-((1-x)^3-(1-x)*sin((1-x)*pi))+1) ; [0.5, 1]
|
||||
float BackInOut(float p) {
|
||||
if (p < 0.5f) { // NOLINT
|
||||
const float f = 2.f * p;
|
||||
return 0.5f * (f * f * f - f * std::sin(f * kPi)); // NOLINT
|
||||
if (p < 0.5F) { // NOLINT
|
||||
const float f = 2 * p;
|
||||
return 0.5F * (f * f * f - f * std::sin(f * kPi)); // NOLINT
|
||||
} else {
|
||||
float f = (1 - (2 * p - 1)); // NOLINT
|
||||
return 0.5F * (1 - (f * f * f - f * std::sin(f * kPi))) + 0.5; // NOLINT
|
||||
}
|
||||
const float f = (1.f - (2.f * p - 1.f)); // NOLINT
|
||||
return 0.5f * (1.f - (f * f * f - f * std::sin(f * kPi))) + 0.5f; // NOLINT
|
||||
}
|
||||
|
||||
float BounceIn(float p) {
|
||||
return 1.f - BounceOut(1.f - p);
|
||||
return 1 - BounceOut(1 - p);
|
||||
}
|
||||
|
||||
float BounceOut(float p) {
|
||||
if (p < 4.f / 11.f) { // NOLINT
|
||||
return (121.f * p * p) / 16.f; // NOLINT
|
||||
if (p < 4 / 11.0) { // NOLINT
|
||||
return (121 * p * p) / 16.0; // NOLINT
|
||||
} else if (p < 8 / 11.0) { // NOLINT
|
||||
return (363 / 40.0 * p * p) - (99 / 10.0 * p) + 17 / 5.0; // NOLINT
|
||||
} else if (p < 9 / 10.0) { // NOLINT
|
||||
return (4356 / 361.0 * p * p) - (35442 / 1805.0 * p) + // NOLINT
|
||||
16061 / 1805.0; // NOLINT
|
||||
} else { // NOLINT
|
||||
return (54 / 5.0 * p * p) - (513 / 25.0 * p) + 268 / 25.0; // NOLINT
|
||||
}
|
||||
|
||||
if (p < 8.f / 11.f) { // NOLINT
|
||||
return (363.f / 40.f * p * p) - (99.f / 10.f * p) + 17.f / 5.f; // NOLINT
|
||||
}
|
||||
|
||||
if (p < 9.f / 10.f) { // NOLINT
|
||||
return (4356.f / 361.f * p * p) - (35442.f / 1805.f * p) + // NOLINT
|
||||
16061.f / 1805.f; // NOLINT
|
||||
}
|
||||
|
||||
return (54.f / 5.f * p * p) - (513 / 25.f * p) + 268 / 25.f; // NOLINT
|
||||
}
|
||||
|
||||
float BounceInOut(float p) { // NOLINT
|
||||
if (p < 0.5f) { // NOLINT
|
||||
return 0.5f * BounceIn(p * 2.f); // NOLINT
|
||||
float BounceInOut(float p) { // NOLINT
|
||||
if (p < 0.5F) { // NOLINT
|
||||
return 0.5F * BounceIn(p * 2); // NOLINT
|
||||
} else { // NOLINT
|
||||
return 0.5F * BounceOut(p * 2 - 1) + 0.5F; // NOLINT
|
||||
}
|
||||
return 0.5f * BounceOut(p * 2.f - 1.f) + 0.5f; // NOLINT
|
||||
}
|
||||
|
||||
} // namespace easing
|
||||
|
@@ -96,7 +96,7 @@ MenuOption GeneratorMenuOption(const char* data, size_t size) {
|
||||
MenuOption option;
|
||||
option.underline = GeneratorUnderlineOption(data, size);
|
||||
option.entries = GeneratorMenuEntryOption(data, size);
|
||||
option.direction = static_cast<Direction>(GeneratorInt(data, size) % 4);
|
||||
option.direction = static_cast<MenuOption::Direction>(GeneratorInt(data, size) % 4);
|
||||
return option;
|
||||
}
|
||||
|
||||
|
@@ -1,17 +1,16 @@
|
||||
#include <algorithm> // for max, fill_n, reverse
|
||||
#include <chrono> // for milliseconds
|
||||
#include <ftxui/dom/direction.hpp> // for Direction, Direction::Down, Direction::Left, Direction::Right, Direction::Up
|
||||
#include <functional> // for function
|
||||
#include <memory> // for allocator_traits<>::value_type, swap
|
||||
#include <string> // for operator+, string
|
||||
#include <utility> // for move
|
||||
#include <vector> // for vector, __alloc_traits<>::value_type
|
||||
#include <algorithm> // for max, fill_n, reverse
|
||||
#include <chrono> // for milliseconds
|
||||
#include <functional> // for function
|
||||
#include <memory> // for allocator_traits<>::value_type, swap
|
||||
#include <string> // for operator+, string
|
||||
#include <utility> // for move
|
||||
#include <vector> // for vector, __alloc_traits<>::value_type
|
||||
|
||||
#include "ftxui/component/animation.hpp" // for Animator, Linear
|
||||
#include "ftxui/component/captured_mouse.hpp" // for CapturedMouse
|
||||
#include "ftxui/component/component.hpp" // for Make, Menu, MenuEntry, Toggle
|
||||
#include "ftxui/component/component_base.hpp" // for ComponentBase
|
||||
#include "ftxui/component/component_options.hpp" // for MenuOption, MenuEntryOption, UnderlineOption, AnimatedColorOption, AnimatedColorsOption, EntryState
|
||||
#include "ftxui/component/component_options.hpp" // for MenuOption, MenuEntryOption, MenuOption::Direction, UnderlineOption, AnimatedColorOption, AnimatedColorsOption, EntryState, MenuOption::Down, MenuOption::Left, MenuOption::Right, MenuOption::Up
|
||||
#include "ftxui/component/event.hpp" // for Event, Event::ArrowDown, Event::ArrowLeft, Event::ArrowRight, Event::ArrowUp, Event::End, Event::Home, Event::PageDown, Event::PageUp, Event::Return, Event::Tab, Event::TabReverse
|
||||
#include "ftxui/component/mouse.hpp" // for Mouse, Mouse::Left, Mouse::Released, Mouse::WheelDown, Mouse::WheelUp, Mouse::None
|
||||
#include "ftxui/component/screen_interactive.hpp" // for Component
|
||||
@@ -37,25 +36,25 @@ Element DefaultOptionTransform(const EntryState& state) {
|
||||
return e;
|
||||
}
|
||||
|
||||
bool IsInverted(Direction direction) {
|
||||
bool IsInverted(MenuOption::Direction direction) {
|
||||
switch (direction) {
|
||||
case Direction::Up:
|
||||
case Direction::Left:
|
||||
case MenuOption::Direction::Up:
|
||||
case MenuOption::Direction::Left:
|
||||
return true;
|
||||
case Direction::Down:
|
||||
case Direction::Right:
|
||||
case MenuOption::Direction::Down:
|
||||
case MenuOption::Direction::Right:
|
||||
return false;
|
||||
}
|
||||
return false; // NOT_REACHED()
|
||||
}
|
||||
|
||||
bool IsHorizontal(Direction direction) {
|
||||
bool IsHorizontal(MenuOption::Direction direction) {
|
||||
switch (direction) {
|
||||
case Direction::Left:
|
||||
case Direction::Right:
|
||||
case MenuOption::Direction::Left:
|
||||
case MenuOption::Direction::Right:
|
||||
return true;
|
||||
case Direction::Down:
|
||||
case Direction::Up:
|
||||
case MenuOption::Direction::Down:
|
||||
case MenuOption::Direction::Up:
|
||||
return false;
|
||||
}
|
||||
return false; // NOT_REACHED()
|
||||
@@ -179,56 +178,56 @@ class MenuBase : public ComponentBase {
|
||||
|
||||
void OnUp() {
|
||||
switch (option_->direction) {
|
||||
case Direction::Up:
|
||||
case MenuOption::Direction::Up:
|
||||
(*selected_)++;
|
||||
break;
|
||||
case Direction::Down:
|
||||
case MenuOption::Direction::Down:
|
||||
(*selected_)--;
|
||||
break;
|
||||
case Direction::Left:
|
||||
case Direction::Right:
|
||||
case MenuOption::Direction::Left:
|
||||
case MenuOption::Direction::Right:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void OnDown() {
|
||||
switch (option_->direction) {
|
||||
case Direction::Up:
|
||||
case MenuOption::Direction::Up:
|
||||
(*selected_)--;
|
||||
break;
|
||||
case Direction::Down:
|
||||
case MenuOption::Direction::Down:
|
||||
(*selected_)++;
|
||||
break;
|
||||
case Direction::Left:
|
||||
case Direction::Right:
|
||||
case MenuOption::Direction::Left:
|
||||
case MenuOption::Direction::Right:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void OnLeft() {
|
||||
switch (option_->direction) {
|
||||
case Direction::Left:
|
||||
case MenuOption::Direction::Left:
|
||||
(*selected_)++;
|
||||
break;
|
||||
case Direction::Right:
|
||||
case MenuOption::Direction::Right:
|
||||
(*selected_)--;
|
||||
break;
|
||||
case Direction::Down:
|
||||
case Direction::Up:
|
||||
case MenuOption::Direction::Down:
|
||||
case MenuOption::Direction::Up:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void OnRight() {
|
||||
switch (option_->direction) {
|
||||
case Direction::Left:
|
||||
case MenuOption::Direction::Left:
|
||||
(*selected_)--;
|
||||
break;
|
||||
case Direction::Right:
|
||||
case MenuOption::Direction::Right:
|
||||
(*selected_)++;
|
||||
break;
|
||||
case Direction::Down:
|
||||
case Direction::Up:
|
||||
case MenuOption::Direction::Down:
|
||||
case MenuOption::Direction::Up:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@@ -1,6 +1,5 @@
|
||||
#include <gtest/gtest.h> // for Test, EXPECT_EQ, Message, TestPartResult, TestInfo (ptr only), TEST
|
||||
#include <chrono> // for operator""s, chrono_literals
|
||||
#include <ftxui/dom/direction.hpp> // for Direction, Direction::Down, Direction::Left, Direction::Right, Direction::Up
|
||||
#include <chrono> // for operator""s, chrono_literals
|
||||
#include <memory> // for __shared_ptr_access, shared_ptr, allocator
|
||||
#include <string> // for string, basic_string
|
||||
#include <vector> // for vector
|
||||
@@ -8,7 +7,7 @@
|
||||
#include "ftxui/component/animation.hpp" // for Duration, Params
|
||||
#include "ftxui/component/component.hpp" // for Menu
|
||||
#include "ftxui/component/component_base.hpp" // for ComponentBase
|
||||
#include "ftxui/component/component_options.hpp" // for MenuOption
|
||||
#include "ftxui/component/component_options.hpp" // for MenuOption, MenuOption::Down, MenuOption::Left, MenuOption::Right, MenuOption::Up
|
||||
#include "ftxui/component/event.hpp" // for Event, Event::ArrowDown, Event::ArrowLeft, Event::ArrowRight, Event::ArrowUp, Event::Return
|
||||
#include "ftxui/dom/node.hpp" // for Render
|
||||
#include "ftxui/screen/screen.hpp" // for Screen
|
||||
@@ -54,7 +53,7 @@ TEST(MenuTest, DirectionDown) {
|
||||
auto menu = Menu(&entries, &selected, &option);
|
||||
|
||||
selected = 0;
|
||||
option.direction = Direction::Down;
|
||||
option.direction = MenuOption::Down;
|
||||
Screen screen(4, 3);
|
||||
Render(screen, menu->Render());
|
||||
EXPECT_EQ(screen.ToString(),
|
||||
@@ -81,7 +80,7 @@ TEST(MenuTest, DirectionsUp) {
|
||||
std::vector<std::string> entries = {"1", "2", "3"};
|
||||
MenuOption option;
|
||||
auto menu = Menu(&entries, &selected, &option);
|
||||
option.direction = Direction::Up;
|
||||
option.direction = MenuOption::Up;
|
||||
Screen screen(4, 3);
|
||||
Render(screen, menu->Render());
|
||||
EXPECT_EQ(screen.ToString(),
|
||||
@@ -107,7 +106,7 @@ TEST(MenuTest, DirectionsRight) {
|
||||
std::vector<std::string> entries = {"1", "2", "3"};
|
||||
MenuOption option;
|
||||
auto menu = Menu(&entries, &selected, &option);
|
||||
option.direction = Direction::Right;
|
||||
option.direction = MenuOption::Right;
|
||||
Screen screen(10, 1);
|
||||
Render(screen, menu->Render());
|
||||
EXPECT_EQ(screen.ToString(),
|
||||
@@ -133,7 +132,7 @@ TEST(MenuTest, DirectionsLeft) {
|
||||
std::vector<std::string> entries = {"1", "2", "3"};
|
||||
MenuOption option;
|
||||
auto menu = Menu(&entries, &selected, &option);
|
||||
option.direction = Direction::Left;
|
||||
option.direction = MenuOption::Left;
|
||||
Screen screen(10, 1);
|
||||
Render(screen, menu->Render());
|
||||
EXPECT_EQ(screen.ToString(),
|
||||
|
@@ -1,28 +1,26 @@
|
||||
#include <ftxui/component/component_options.hpp> // for ResizableSplitOption
|
||||
#include <ftxui/dom/direction.hpp> // for Direction, Direction::Down, Direction::Left, Direction::Right, Direction::Up
|
||||
#include <ftxui/util/ref.hpp> // for Ref
|
||||
#include <functional> // for function
|
||||
#include <memory> // for __shared_ptr_access, shared_ptr, allocator
|
||||
#include <memory> // for __shared_ptr_access
|
||||
#include <utility> // for move
|
||||
|
||||
#include "ftxui/component/captured_mouse.hpp" // for CapturedMouse
|
||||
#include "ftxui/component/component.hpp" // for Horizontal, Make, ResizableSplit, ResizableSplitBottom, ResizableSplitLeft, ResizableSplitRight, ResizableSplitTop
|
||||
#include "ftxui/component/component_base.hpp" // for Component, ComponentBase
|
||||
#include "ftxui/component/component.hpp" // for Component, Make, Horizontal, Vertical, ResizableSplitBottom, ResizableSplitLeft, ResizableSplitRight, ResizableSplitTop
|
||||
#include "ftxui/component/component_base.hpp" // for ComponentBase
|
||||
#include "ftxui/component/event.hpp" // for Event
|
||||
#include "ftxui/component/mouse.hpp" // for Mouse, Mouse::Left, Mouse::Pressed, Mouse::Released
|
||||
#include "ftxui/dom/elements.hpp" // for operator|, reflect, Element, size, EQUAL, xflex, yflex, hbox, vbox, HEIGHT, WIDTH, text
|
||||
#include "ftxui/dom/elements.hpp" // for operator|, reflect, Element, separator, size, EQUAL, xflex, yflex, hbox, vbox, HEIGHT, WIDTH
|
||||
#include "ftxui/screen/box.hpp" // for Box
|
||||
|
||||
namespace ftxui {
|
||||
namespace {
|
||||
|
||||
class ResizableSplitBase : public ComponentBase {
|
||||
class ResizableSplitLeftBase : public ComponentBase {
|
||||
public:
|
||||
ResizableSplitBase(ResizableSplitOption options)
|
||||
: options_(std::move(options)) {
|
||||
ResizableSplitLeftBase(Component main, Component child, int* main_size)
|
||||
: main_(std::move(main)),
|
||||
child_(std::move(child)),
|
||||
main_size_(main_size) {
|
||||
Add(Container::Horizontal({
|
||||
options_->main,
|
||||
options_->back,
|
||||
main_,
|
||||
child_,
|
||||
}));
|
||||
}
|
||||
|
||||
@@ -47,86 +45,204 @@ class ResizableSplitBase : public ComponentBase {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!captured_mouse_) {
|
||||
return ComponentBase::OnEvent(event);
|
||||
if (captured_mouse_) {
|
||||
*main_size_ = event.mouse().x - box_.x_min;
|
||||
return true;
|
||||
}
|
||||
|
||||
switch (options_->direction()) {
|
||||
case Direction::Left:
|
||||
options_->main_size() = event.mouse().x - box_.x_min;
|
||||
return true;
|
||||
case Direction::Right:
|
||||
options_->main_size() = box_.x_max - event.mouse().x;
|
||||
return true;
|
||||
case Direction::Up:
|
||||
options_->main_size() = event.mouse().y - box_.y_min;
|
||||
return true;
|
||||
case Direction::Down:
|
||||
options_->main_size() = box_.y_max - event.mouse().y;
|
||||
return true;
|
||||
}
|
||||
|
||||
// NOTREACHED()
|
||||
return false;
|
||||
return ComponentBase::OnEvent(event);
|
||||
}
|
||||
|
||||
Element Render() final {
|
||||
switch (options_->direction()) {
|
||||
case Direction::Left:
|
||||
return RenderLeft();
|
||||
case Direction::Right:
|
||||
return RenderRight();
|
||||
case Direction::Up:
|
||||
return RenderTop();
|
||||
case Direction::Down:
|
||||
return RenderBottom();
|
||||
}
|
||||
// NOTREACHED()
|
||||
return text("unreacheable");
|
||||
}
|
||||
|
||||
Element RenderLeft() {
|
||||
return hbox({
|
||||
options_->main->Render() |
|
||||
size(WIDTH, EQUAL, options_->main_size()),
|
||||
options_->separator_func() | reflect(separator_box_),
|
||||
options_->back->Render() | xflex,
|
||||
}) |
|
||||
reflect(box_);
|
||||
};
|
||||
|
||||
Element RenderRight() {
|
||||
return hbox({
|
||||
options_->back->Render() | xflex,
|
||||
options_->separator_func() | reflect(separator_box_),
|
||||
options_->main->Render() |
|
||||
size(WIDTH, EQUAL, options_->main_size()),
|
||||
}) |
|
||||
reflect(box_);
|
||||
};
|
||||
|
||||
Element RenderTop() {
|
||||
return vbox({
|
||||
options_->main->Render() |
|
||||
size(HEIGHT, EQUAL, options_->main_size()),
|
||||
options_->separator_func() | reflect(separator_box_),
|
||||
options_->back->Render() | yflex,
|
||||
}) |
|
||||
reflect(box_);
|
||||
};
|
||||
|
||||
Element RenderBottom() {
|
||||
return vbox({
|
||||
options_->back->Render() | yflex,
|
||||
options_->separator_func() | reflect(separator_box_),
|
||||
options_->main->Render() |
|
||||
size(HEIGHT, EQUAL, options_->main_size()),
|
||||
main_->Render() | size(WIDTH, EQUAL, *main_size_),
|
||||
separator() | reflect(separator_box_),
|
||||
child_->Render() | xflex,
|
||||
}) |
|
||||
reflect(box_);
|
||||
};
|
||||
|
||||
private:
|
||||
Ref<ResizableSplitOption> options_;
|
||||
Component main_;
|
||||
Component child_;
|
||||
int* const main_size_;
|
||||
CapturedMouse captured_mouse_;
|
||||
Box separator_box_;
|
||||
Box box_;
|
||||
};
|
||||
|
||||
class ResizableSplitRightBase : public ComponentBase {
|
||||
public:
|
||||
ResizableSplitRightBase(Component main, Component child, int* main_size)
|
||||
: main_(std::move(main)),
|
||||
child_(std::move(child)),
|
||||
main_size_(main_size) {
|
||||
Add(Container::Horizontal({
|
||||
child_,
|
||||
main_,
|
||||
}));
|
||||
}
|
||||
|
||||
bool OnEvent(Event event) final {
|
||||
if (event.is_mouse()) {
|
||||
return OnMouseEvent(std::move(event));
|
||||
}
|
||||
return ComponentBase::OnEvent(std::move(event));
|
||||
}
|
||||
|
||||
bool OnMouseEvent(Event event) {
|
||||
if (captured_mouse_ && event.mouse().motion == Mouse::Released) {
|
||||
captured_mouse_.reset();
|
||||
return true;
|
||||
}
|
||||
|
||||
if (event.mouse().button == Mouse::Left &&
|
||||
event.mouse().motion == Mouse::Pressed &&
|
||||
separator_box_.Contain(event.mouse().x, event.mouse().y) &&
|
||||
!captured_mouse_) {
|
||||
captured_mouse_ = CaptureMouse(event);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (captured_mouse_) {
|
||||
*main_size_ = box_.x_max - event.mouse().x;
|
||||
return true;
|
||||
}
|
||||
|
||||
return ComponentBase::OnEvent(event);
|
||||
}
|
||||
|
||||
Element Render() final {
|
||||
return hbox({
|
||||
child_->Render() | xflex,
|
||||
separator() | reflect(separator_box_),
|
||||
main_->Render() | size(WIDTH, EQUAL, *main_size_),
|
||||
}) |
|
||||
reflect(box_);
|
||||
};
|
||||
|
||||
private:
|
||||
Component main_;
|
||||
Component child_;
|
||||
int* const main_size_;
|
||||
CapturedMouse captured_mouse_;
|
||||
Box separator_box_;
|
||||
Box box_;
|
||||
};
|
||||
|
||||
class ResizableSplitTopBase : public ComponentBase {
|
||||
public:
|
||||
ResizableSplitTopBase(Component main, Component child, int* main_size)
|
||||
: main_(std::move(main)),
|
||||
child_(std::move(child)),
|
||||
main_size_(main_size) {
|
||||
Add(Container::Vertical({
|
||||
main_,
|
||||
child_,
|
||||
}));
|
||||
}
|
||||
|
||||
bool OnEvent(Event event) final {
|
||||
if (event.is_mouse()) {
|
||||
return OnMouseEvent(std::move(event));
|
||||
}
|
||||
return ComponentBase::OnEvent(std::move(event));
|
||||
}
|
||||
|
||||
bool OnMouseEvent(Event event) {
|
||||
if (captured_mouse_ && event.mouse().motion == Mouse::Released) {
|
||||
captured_mouse_.reset();
|
||||
return true;
|
||||
}
|
||||
|
||||
if (event.mouse().button == Mouse::Left &&
|
||||
event.mouse().motion == Mouse::Pressed &&
|
||||
separator_box_.Contain(event.mouse().x, event.mouse().y) &&
|
||||
!captured_mouse_) {
|
||||
captured_mouse_ = CaptureMouse(event);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (captured_mouse_) {
|
||||
*main_size_ = event.mouse().y - box_.y_min;
|
||||
return true;
|
||||
}
|
||||
|
||||
return ComponentBase::OnEvent(event);
|
||||
}
|
||||
|
||||
Element Render() final {
|
||||
return vbox({
|
||||
main_->Render() | size(HEIGHT, EQUAL, *main_size_),
|
||||
separator() | reflect(separator_box_),
|
||||
child_->Render() | yflex,
|
||||
}) |
|
||||
reflect(box_);
|
||||
};
|
||||
|
||||
private:
|
||||
Component main_;
|
||||
Component child_;
|
||||
int* const main_size_;
|
||||
CapturedMouse captured_mouse_;
|
||||
Box separator_box_;
|
||||
Box box_;
|
||||
};
|
||||
|
||||
class ResizableSplitBottomBase : public ComponentBase {
|
||||
public:
|
||||
ResizableSplitBottomBase(Component main, Component child, int* main_size)
|
||||
: main_(std::move(main)),
|
||||
child_(std::move(child)),
|
||||
main_size_(main_size) {
|
||||
Add(Container::Vertical({
|
||||
child_,
|
||||
main_,
|
||||
}));
|
||||
}
|
||||
|
||||
bool OnEvent(Event event) final {
|
||||
if (event.is_mouse()) {
|
||||
return OnMouseEvent(std::move(event));
|
||||
}
|
||||
return ComponentBase::OnEvent(std::move(event));
|
||||
}
|
||||
|
||||
bool OnMouseEvent(Event event) {
|
||||
if (captured_mouse_ && event.mouse().motion == Mouse::Released) {
|
||||
captured_mouse_.reset();
|
||||
return true;
|
||||
}
|
||||
|
||||
if (event.mouse().button == Mouse::Left &&
|
||||
event.mouse().motion == Mouse::Pressed &&
|
||||
separator_box_.Contain(event.mouse().x, event.mouse().y) &&
|
||||
!captured_mouse_) {
|
||||
captured_mouse_ = CaptureMouse(event);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (captured_mouse_) {
|
||||
*main_size_ = box_.y_max - event.mouse().y;
|
||||
return true;
|
||||
}
|
||||
|
||||
return ComponentBase::OnEvent(event);
|
||||
}
|
||||
|
||||
Element Render() final {
|
||||
return vbox({
|
||||
child_->Render() | yflex,
|
||||
separator() | reflect(separator_box_),
|
||||
main_->Render() | size(HEIGHT, EQUAL, *main_size_),
|
||||
}) |
|
||||
reflect(box_);
|
||||
};
|
||||
|
||||
private:
|
||||
Component main_;
|
||||
Component child_;
|
||||
int* const main_size_;
|
||||
CapturedMouse captured_mouse_;
|
||||
Box separator_box_;
|
||||
Box box_;
|
||||
@@ -134,35 +250,6 @@ class ResizableSplitBase : public ComponentBase {
|
||||
|
||||
} // namespace
|
||||
|
||||
/// @brief A split in between two components.
|
||||
/// @param options: all the parameters.
|
||||
///
|
||||
/// ### Example
|
||||
///
|
||||
/// ```cpp
|
||||
/// auto left = Renderer([] { return text("Left") | center;});
|
||||
/// auto right = Renderer([] { return text("right") | center;});
|
||||
/// int left_size = 10;
|
||||
/// auto component = ResizableSplit({
|
||||
/// .main = left,
|
||||
/// .back = right,
|
||||
/// .direction = Direction::Left,
|
||||
/// .main_size = &left_size,
|
||||
/// .separator_func = [] { return separatorDouble(); },
|
||||
/// });
|
||||
/// ```
|
||||
///
|
||||
/// ### Output
|
||||
///
|
||||
/// ```bash
|
||||
/// ║
|
||||
/// left ║ right
|
||||
/// ║
|
||||
/// ```
|
||||
Component ResizableSplit(ResizableSplitOption options) {
|
||||
return Make<ResizableSplitBase>(std::move(options));
|
||||
}
|
||||
|
||||
/// @brief An horizontal split in between two components, configurable using the
|
||||
/// mouse.
|
||||
/// @param main The main component of size |main_size|, on the left.
|
||||
@@ -189,12 +276,8 @@ Component ResizableSplit(ResizableSplitOption options) {
|
||||
/// │
|
||||
/// ```
|
||||
Component ResizableSplitLeft(Component main, Component back, int* main_size) {
|
||||
return ResizableSplit({
|
||||
std::move(main),
|
||||
std::move(back),
|
||||
Direction::Left,
|
||||
main_size,
|
||||
});
|
||||
return Make<ResizableSplitLeftBase>(std::move(main), std::move(back),
|
||||
main_size);
|
||||
}
|
||||
|
||||
/// @brief An horizontal split in between two components, configurable using the
|
||||
@@ -211,7 +294,7 @@ Component ResizableSplitLeft(Component main, Component back, int* main_size) {
|
||||
/// int right_size = 10;
|
||||
/// auto left = Renderer([] { return text("Left") | center;});
|
||||
/// auto right = Renderer([] { return text("right") | center;});
|
||||
/// auto split = ResizableSplitRight(right, left, &right_size)
|
||||
/// auto split = ResizableSplitRight(right, left, &right_size);
|
||||
/// screen.Loop(split);
|
||||
/// ```
|
||||
///
|
||||
@@ -223,12 +306,8 @@ Component ResizableSplitLeft(Component main, Component back, int* main_size) {
|
||||
/// │
|
||||
/// ```
|
||||
Component ResizableSplitRight(Component main, Component back, int* main_size) {
|
||||
return ResizableSplit({
|
||||
std::move(main),
|
||||
std::move(back),
|
||||
Direction::Right,
|
||||
main_size,
|
||||
});
|
||||
return Make<ResizableSplitRightBase>(std::move(main), std::move(back),
|
||||
main_size);
|
||||
}
|
||||
|
||||
/// @brief An vertical split in between two components, configurable using the
|
||||
@@ -245,7 +324,7 @@ Component ResizableSplitRight(Component main, Component back, int* main_size) {
|
||||
/// int top_size = 1;
|
||||
/// auto top = Renderer([] { return text("Top") | center;});
|
||||
/// auto bottom = Renderer([] { return text("Bottom") | center;});
|
||||
/// auto split = ResizableSplitTop(top, bottom, &top_size)
|
||||
/// auto split = ResizableSplitTop(top, bottom, &top_size);
|
||||
/// screen.Loop(split);
|
||||
/// ```
|
||||
///
|
||||
@@ -257,12 +336,8 @@ Component ResizableSplitRight(Component main, Component back, int* main_size) {
|
||||
/// bottom
|
||||
/// ```
|
||||
Component ResizableSplitTop(Component main, Component back, int* main_size) {
|
||||
return ResizableSplit({
|
||||
std::move(main),
|
||||
std::move(back),
|
||||
Direction::Up,
|
||||
main_size,
|
||||
});
|
||||
return Make<ResizableSplitTopBase>(std::move(main), std::move(back),
|
||||
main_size);
|
||||
}
|
||||
|
||||
/// @brief An vertical split in between two components, configurable using the
|
||||
@@ -279,7 +354,7 @@ Component ResizableSplitTop(Component main, Component back, int* main_size) {
|
||||
/// int bottom_size = 1;
|
||||
/// auto top = Renderer([] { return text("Top") | center;});
|
||||
/// auto bottom = Renderer([] { return text("Bottom") | center;});
|
||||
/// auto split = ResizableSplit::Bottom(bottom, top, &bottom_size)
|
||||
/// auto split = ResizableSplit::Bottom(bottom, top, &bottom_size);
|
||||
/// screen.Loop(split);
|
||||
/// ```
|
||||
///
|
||||
@@ -291,14 +366,9 @@ Component ResizableSplitTop(Component main, Component back, int* main_size) {
|
||||
/// bottom
|
||||
/// ```
|
||||
Component ResizableSplitBottom(Component main, Component back, int* main_size) {
|
||||
return ResizableSplit({
|
||||
std::move(main),
|
||||
std::move(back),
|
||||
Direction::Down,
|
||||
main_size,
|
||||
});
|
||||
return Make<ResizableSplitBottomBase>(std::move(main), std::move(back),
|
||||
main_size);
|
||||
}
|
||||
|
||||
} // namespace ftxui
|
||||
|
||||
// Copyright 2021 Arthur Sonzogni. All rights reserved.
|
||||
|
@@ -1,12 +1,11 @@
|
||||
#include <gtest/gtest.h> // for AssertionResult, Message, TestPartResult, Test, EXPECT_EQ, EXPECT_TRUE, TestInfo (ptr only), TEST
|
||||
#include <ftxui/dom/direction.hpp> // for Direction, Direction::Down, Direction::Left, Direction::Right, Direction::Up
|
||||
#include <gtest/gtest.h>
|
||||
#include <memory> // for __shared_ptr_access, shared_ptr, allocator
|
||||
|
||||
#include "ftxui/component/component.hpp" // for ResizableSplit, Renderer, ResizableSplitBottom, ResizableSplitLeft, ResizableSplitRight, ResizableSplitTop
|
||||
#include "ftxui/component/component.hpp" // for Renderer, ResizableSplitBottom, ResizableSplitLeft, ResizableSplitRight, ResizableSplitTop
|
||||
#include "ftxui/component/component_base.hpp" // for ComponentBase, Component
|
||||
#include "ftxui/component/event.hpp" // for Event
|
||||
#include "ftxui/component/mouse.hpp" // for Mouse, Mouse::Left, Mouse::Pressed, Mouse::Released
|
||||
#include "ftxui/dom/elements.hpp" // for Element, separatorDouble, text
|
||||
#include "ftxui/dom/elements.hpp" // for text, Element
|
||||
#include "ftxui/dom/node.hpp" // for Render
|
||||
#include "ftxui/screen/screen.hpp" // for Screen
|
||||
|
||||
@@ -57,31 +56,6 @@ TEST(ResizableSplit, BasicLeft) {
|
||||
EXPECT_EQ(position, 10);
|
||||
}
|
||||
|
||||
TEST(ResizableSplit, BasicLeftWithCustomSeparator) {
|
||||
int position = 1;
|
||||
auto component = ResizableSplit({
|
||||
.main = BasicComponent(),
|
||||
.back = BasicComponent(),
|
||||
.direction = Direction::Left,
|
||||
.main_size = &position,
|
||||
.separator_func = [] { return separatorDouble(); },
|
||||
});
|
||||
auto screen = Screen(4, 4);
|
||||
Render(screen, component->Render());
|
||||
EXPECT_EQ(position, 1);
|
||||
EXPECT_EQ(screen.ToString(),
|
||||
" ║ \r\n"
|
||||
" ║ \r\n"
|
||||
" ║ \r\n"
|
||||
" ║ ");
|
||||
EXPECT_TRUE(component->OnEvent(MousePressed(1, 1)));
|
||||
EXPECT_EQ(position, 1);
|
||||
EXPECT_TRUE(component->OnEvent(MousePressed(2, 1)));
|
||||
EXPECT_EQ(position, 2);
|
||||
EXPECT_TRUE(component->OnEvent(MouseReleased(2, 1)));
|
||||
EXPECT_EQ(position, 2);
|
||||
}
|
||||
|
||||
TEST(ResizableSplit, BasicRight) {
|
||||
int position = 3;
|
||||
auto component =
|
||||
@@ -97,31 +71,6 @@ TEST(ResizableSplit, BasicRight) {
|
||||
EXPECT_EQ(position, 9);
|
||||
}
|
||||
|
||||
TEST(ResizableSplit, BasicRightWithCustomSeparator) {
|
||||
int position = 1;
|
||||
auto component = ResizableSplit({
|
||||
.main = BasicComponent(),
|
||||
.back = BasicComponent(),
|
||||
.direction = Direction::Right,
|
||||
.main_size = &position,
|
||||
.separator_func = [] { return separatorDouble(); },
|
||||
});
|
||||
auto screen = Screen(4, 4);
|
||||
Render(screen, component->Render());
|
||||
EXPECT_EQ(position, 1);
|
||||
EXPECT_EQ(screen.ToString(),
|
||||
" ║ \r\n"
|
||||
" ║ \r\n"
|
||||
" ║ \r\n"
|
||||
" ║ ");
|
||||
EXPECT_TRUE(component->OnEvent(MousePressed(2, 1)));
|
||||
EXPECT_EQ(position, 1);
|
||||
EXPECT_TRUE(component->OnEvent(MousePressed(1, 1)));
|
||||
EXPECT_EQ(position, 2);
|
||||
EXPECT_TRUE(component->OnEvent(MouseReleased(1, 1)));
|
||||
EXPECT_EQ(position, 2);
|
||||
}
|
||||
|
||||
TEST(ResizableSplit, BasicTop) {
|
||||
int position = 3;
|
||||
auto component =
|
||||
@@ -137,31 +86,6 @@ TEST(ResizableSplit, BasicTop) {
|
||||
EXPECT_EQ(position, 10);
|
||||
}
|
||||
|
||||
TEST(ResizableSplit, BasicTopWithCustomSeparator) {
|
||||
int position = 1;
|
||||
auto component = ResizableSplit({
|
||||
.main = BasicComponent(),
|
||||
.back = BasicComponent(),
|
||||
.direction = Direction::Up,
|
||||
.main_size = &position,
|
||||
.separator_func = [] { return separatorDouble(); },
|
||||
});
|
||||
auto screen = Screen(4, 4);
|
||||
Render(screen, component->Render());
|
||||
EXPECT_EQ(position, 1);
|
||||
EXPECT_EQ(screen.ToString(),
|
||||
" \r\n"
|
||||
"════\r\n"
|
||||
" \r\n"
|
||||
" ");
|
||||
EXPECT_TRUE(component->OnEvent(MousePressed(1, 1)));
|
||||
EXPECT_EQ(position, 1);
|
||||
EXPECT_TRUE(component->OnEvent(MousePressed(1, 2)));
|
||||
EXPECT_EQ(position, 2);
|
||||
EXPECT_TRUE(component->OnEvent(MouseReleased(1, 2)));
|
||||
EXPECT_EQ(position, 2);
|
||||
}
|
||||
|
||||
TEST(ResizableSplit, BasicBottom) {
|
||||
int position = 3;
|
||||
auto component =
|
||||
@@ -177,31 +101,6 @@ TEST(ResizableSplit, BasicBottom) {
|
||||
EXPECT_EQ(position, 9);
|
||||
}
|
||||
|
||||
TEST(ResizableSplit, BasicBottomWithCustomSeparator) {
|
||||
int position = 1;
|
||||
auto component = ResizableSplit({
|
||||
.main = BasicComponent(),
|
||||
.back = BasicComponent(),
|
||||
.direction = Direction::Down,
|
||||
.main_size = &position,
|
||||
.separator_func = [] { return separatorDouble(); },
|
||||
});
|
||||
auto screen = Screen(4, 4);
|
||||
Render(screen, component->Render());
|
||||
EXPECT_EQ(position, 1);
|
||||
EXPECT_EQ(screen.ToString(),
|
||||
" \r\n"
|
||||
" \r\n"
|
||||
"════\r\n"
|
||||
" ");
|
||||
EXPECT_TRUE(component->OnEvent(MousePressed(1, 2)));
|
||||
EXPECT_EQ(position, 1);
|
||||
EXPECT_TRUE(component->OnEvent(MousePressed(1, 1)));
|
||||
EXPECT_EQ(position, 2);
|
||||
EXPECT_TRUE(component->OnEvent(MouseReleased(1, 1)));
|
||||
EXPECT_EQ(position, 2);
|
||||
}
|
||||
|
||||
} // namespace ftxui
|
||||
|
||||
// Copyright 2022 Arthur Sonzogni. All rights reserved.
|
||||
|
@@ -1,8 +1,7 @@
|
||||
#include <algorithm> // for max, min
|
||||
#include <ftxui/component/component_options.hpp> // for SliderOption
|
||||
#include <ftxui/dom/direction.hpp> // for Direction, Direction::Down, Direction::Left, Direction::Right, Direction::Up
|
||||
#include <string> // for allocator
|
||||
#include <utility> // for move
|
||||
#include <string> // for allocator
|
||||
#include <utility> // for move
|
||||
|
||||
#include "ftxui/component/captured_mouse.hpp" // for CapturedMouse
|
||||
#include "ftxui/component/component.hpp" // for Make, Slider
|
||||
@@ -10,7 +9,7 @@
|
||||
#include "ftxui/component/event.hpp" // for Event, Event::ArrowDown, Event::ArrowLeft, Event::ArrowRight, Event::ArrowUp
|
||||
#include "ftxui/component/mouse.hpp" // for Mouse, Mouse::Left, Mouse::Pressed, Mouse::Released
|
||||
#include "ftxui/component/screen_interactive.hpp" // for Component
|
||||
#include "ftxui/dom/elements.hpp" // for operator|, text, Element, xflex, hbox, color, underlined, reflect, Decorator, dim, vcenter, focus, nothing, select, yflex, gaugeDirection
|
||||
#include "ftxui/dom/elements.hpp" // for operator|, text, GaugeDirection, Element, xflex, hbox, color, underlined, GaugeDirection::Down, GaugeDirection::Left, GaugeDirection::Right, GaugeDirection::Up, reflect, Decorator, dim, vcenter, yflex, gaugeDirection
|
||||
#include "ftxui/screen/box.hpp" // for Box
|
||||
#include "ftxui/screen/color.hpp" // for Color, Color::GrayDark, Color::White
|
||||
#include "ftxui/screen/util.hpp" // for clamp
|
||||
@@ -19,13 +18,13 @@
|
||||
namespace ftxui {
|
||||
|
||||
namespace {
|
||||
Decorator flexDirection(Direction direction) {
|
||||
Decorator flexDirection(GaugeDirection direction) {
|
||||
switch (direction) {
|
||||
case Direction::Up:
|
||||
case Direction::Down:
|
||||
case GaugeDirection::Up:
|
||||
case GaugeDirection::Down:
|
||||
return yflex;
|
||||
case Direction::Left:
|
||||
case Direction::Right:
|
||||
case GaugeDirection::Left:
|
||||
case GaugeDirection::Right:
|
||||
return xflex;
|
||||
}
|
||||
return xflex; // NOT_REACHED()
|
||||
@@ -53,56 +52,56 @@ class SliderBase : public ComponentBase {
|
||||
|
||||
void OnLeft() {
|
||||
switch (options_->direction) {
|
||||
case Direction::Right:
|
||||
case GaugeDirection::Right:
|
||||
value_() -= increment_();
|
||||
break;
|
||||
case Direction::Left:
|
||||
case GaugeDirection::Left:
|
||||
value_() += increment_();
|
||||
break;
|
||||
case Direction::Up:
|
||||
case Direction::Down:
|
||||
case GaugeDirection::Up:
|
||||
case GaugeDirection::Down:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void OnRight() {
|
||||
switch (options_->direction) {
|
||||
case Direction::Right:
|
||||
case GaugeDirection::Right:
|
||||
value_() += increment_();
|
||||
break;
|
||||
case Direction::Left:
|
||||
case GaugeDirection::Left:
|
||||
value_() -= increment_();
|
||||
break;
|
||||
case Direction::Up:
|
||||
case Direction::Down:
|
||||
case GaugeDirection::Up:
|
||||
case GaugeDirection::Down:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void OnUp() {
|
||||
switch (options_->direction) {
|
||||
case Direction::Up:
|
||||
case GaugeDirection::Up:
|
||||
value_() -= increment_();
|
||||
break;
|
||||
case Direction::Down:
|
||||
case GaugeDirection::Down:
|
||||
value_() += increment_();
|
||||
break;
|
||||
case Direction::Left:
|
||||
case Direction::Right:
|
||||
case GaugeDirection::Left:
|
||||
case GaugeDirection::Right:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void OnDown() {
|
||||
switch (options_->direction) {
|
||||
case Direction::Down:
|
||||
case GaugeDirection::Down:
|
||||
value_() -= increment_();
|
||||
break;
|
||||
case Direction::Up:
|
||||
case GaugeDirection::Up:
|
||||
value_() += increment_();
|
||||
break;
|
||||
case Direction::Left:
|
||||
case Direction::Right:
|
||||
case GaugeDirection::Left:
|
||||
case GaugeDirection::Right:
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -154,25 +153,25 @@ class SliderBase : public ComponentBase {
|
||||
|
||||
if (captured_mouse_) {
|
||||
switch (options_->direction) {
|
||||
case Direction::Right: {
|
||||
case GaugeDirection::Right: {
|
||||
value_() = min_() + (event.mouse().x - gauge_box_.x_min) *
|
||||
(max_() - min_()) /
|
||||
(gauge_box_.x_max - gauge_box_.x_min);
|
||||
break;
|
||||
}
|
||||
case Direction::Left: {
|
||||
case GaugeDirection::Left: {
|
||||
value_() = max_() - (event.mouse().x - gauge_box_.x_min) *
|
||||
(max_() - min_()) /
|
||||
(gauge_box_.x_max - gauge_box_.x_min);
|
||||
break;
|
||||
}
|
||||
case Direction::Down: {
|
||||
case GaugeDirection::Down: {
|
||||
value_() = min_() + (event.mouse().y - gauge_box_.y_min) *
|
||||
(max_() - min_()) /
|
||||
(gauge_box_.y_max - gauge_box_.y_min);
|
||||
break;
|
||||
}
|
||||
case Direction::Up: {
|
||||
case GaugeDirection::Up: {
|
||||
value_() = max_() - (event.mouse().y - gauge_box_.y_min) *
|
||||
(max_() - min_()) /
|
||||
(gauge_box_.y_max - gauge_box_.y_min);
|
||||
|
@@ -2,8 +2,7 @@
|
||||
#include <stddef.h> // for size_t
|
||||
#include <array> // for array
|
||||
#include <ftxui/component/mouse.hpp> // for Mouse, Mouse::Left, Mouse::Pressed, Mouse::Released
|
||||
#include <ftxui/dom/direction.hpp> // for Direction, Direction::Down, Direction::Left, Direction::Right, Direction::Up
|
||||
#include <ftxui/dom/elements.hpp> // for frame
|
||||
#include <ftxui/dom/elements.hpp> // for GaugeDirection, GaugeDirection::Down, GaugeDirection::Left, GaugeDirection::Right, GaugeDirection::Up, frame
|
||||
#include <memory> // for shared_ptr, __shared_ptr_access, allocator
|
||||
#include <string> // for to_string
|
||||
|
||||
@@ -48,7 +47,7 @@ TEST(SliderTest, Right) {
|
||||
.min = 0,
|
||||
.max = 100,
|
||||
.increment = 10,
|
||||
.direction = Direction::Right,
|
||||
.direction = GaugeDirection::Right,
|
||||
});
|
||||
Screen screen(11, 1);
|
||||
Render(screen, slider->Render());
|
||||
@@ -71,7 +70,7 @@ TEST(SliderTest, Left) {
|
||||
.min = 0,
|
||||
.max = 100,
|
||||
.increment = 10,
|
||||
.direction = Direction::Left,
|
||||
.direction = GaugeDirection::Left,
|
||||
});
|
||||
Screen screen(11, 1);
|
||||
Render(screen, slider->Render());
|
||||
@@ -94,7 +93,7 @@ TEST(SliderTest, Down) {
|
||||
.min = 0,
|
||||
.max = 100,
|
||||
.increment = 10,
|
||||
.direction = Direction::Down,
|
||||
.direction = GaugeDirection::Down,
|
||||
});
|
||||
Screen screen(1, 11);
|
||||
Render(screen, slider->Render());
|
||||
@@ -117,7 +116,7 @@ TEST(SliderTest, Up) {
|
||||
.min = 0,
|
||||
.max = 100,
|
||||
.increment = 10,
|
||||
.direction = Direction::Up,
|
||||
.direction = GaugeDirection::Up,
|
||||
});
|
||||
Screen screen(1, 11);
|
||||
Render(screen, slider->Render());
|
||||
|
@@ -1,9 +1,8 @@
|
||||
#include <ftxui/dom/direction.hpp> // for Direction, Direction::Down, Direction::Left, Direction::Right, Direction::Up
|
||||
#include <memory> // for allocator, make_shared
|
||||
#include <string> // for string
|
||||
#include <memory> // for allocator, make_shared
|
||||
#include <string> // for string
|
||||
|
||||
#include "ftxui/dom/elements.hpp" // for Element, gauge, gaugeDirection, gaugeDown, gaugeLeft, gaugeRight, gaugeUp
|
||||
#include "ftxui/dom/node.hpp" // for Node
|
||||
#include "ftxui/dom/elements.hpp" // for GaugeDirection, Element, GaugeDirection::Down, GaugeDirection::Left, GaugeDirection::Right, GaugeDirection::Up, gauge, gaugeDirection, gaugeDown, gaugeLeft, gaugeRight, gaugeUp
|
||||
#include "ftxui/dom/node.hpp" // for Node
|
||||
#include "ftxui/dom/requirement.hpp" // for Requirement
|
||||
#include "ftxui/screen/box.hpp" // for Box
|
||||
#include "ftxui/screen/screen.hpp" // for Screen, Pixel
|
||||
@@ -41,7 +40,7 @@ static const std::string charset_vertical[10] = {
|
||||
|
||||
class Gauge : public Node {
|
||||
public:
|
||||
Gauge(float progress, Direction direction)
|
||||
Gauge(float progress, GaugeDirection direction)
|
||||
: progress_(progress), direction_(direction) {
|
||||
// This handle NAN correctly:
|
||||
if (!(progress_ > 0.F)) {
|
||||
@@ -54,15 +53,15 @@ class Gauge : public Node {
|
||||
|
||||
void ComputeRequirement() override {
|
||||
switch (direction_) {
|
||||
case Direction::Right:
|
||||
case Direction::Left:
|
||||
case GaugeDirection::Right:
|
||||
case GaugeDirection::Left:
|
||||
requirement_.flex_grow_x = 1;
|
||||
requirement_.flex_grow_y = 0;
|
||||
requirement_.flex_shrink_x = 1;
|
||||
requirement_.flex_shrink_y = 0;
|
||||
break;
|
||||
case Direction::Up:
|
||||
case Direction::Down:
|
||||
case GaugeDirection::Up:
|
||||
case GaugeDirection::Down:
|
||||
requirement_.flex_grow_x = 0;
|
||||
requirement_.flex_grow_y = 1;
|
||||
requirement_.flex_shrink_x = 0;
|
||||
@@ -75,16 +74,16 @@ class Gauge : public Node {
|
||||
|
||||
void Render(Screen& screen) override {
|
||||
switch (direction_) {
|
||||
case Direction::Right:
|
||||
case GaugeDirection::Right:
|
||||
RenderHorizontal(screen, /*invert=*/false);
|
||||
break;
|
||||
case Direction::Up:
|
||||
case GaugeDirection::Up:
|
||||
RenderVertical(screen, /*invert=*/false);
|
||||
break;
|
||||
case Direction::Left:
|
||||
case GaugeDirection::Left:
|
||||
RenderHorizontal(screen, /*invert=*/true);
|
||||
break;
|
||||
case Direction::Down:
|
||||
case GaugeDirection::Down:
|
||||
RenderVertical(screen, /*invert=*/true);
|
||||
break;
|
||||
}
|
||||
@@ -152,7 +151,7 @@ class Gauge : public Node {
|
||||
|
||||
private:
|
||||
float progress_;
|
||||
Direction direction_;
|
||||
GaugeDirection direction_;
|
||||
};
|
||||
|
||||
/// @brief Draw a high definition progress bar progressing in specified
|
||||
@@ -160,7 +159,7 @@ class Gauge : public Node {
|
||||
/// @param progress The proportion of the area to be filled. Belong to [0,1].
|
||||
// @param direction Direction of progress bars progression.
|
||||
/// @ingroup dom
|
||||
Element gaugeDirection(float progress, Direction direction) {
|
||||
Element gaugeDirection(float progress, GaugeDirection direction) {
|
||||
return std::make_shared<Gauge>(progress, direction);
|
||||
}
|
||||
|
||||
@@ -183,7 +182,7 @@ Element gaugeDirection(float progress, Direction direction) {
|
||||
/// └──────────────────────────────────────────────────────────────────────────┘
|
||||
/// ~~~
|
||||
Element gaugeRight(float progress) {
|
||||
return gaugeDirection(progress, Direction::Right);
|
||||
return gaugeDirection(progress, GaugeDirection::Right);
|
||||
}
|
||||
|
||||
/// @brief Draw a high definition progress bar progressing from right to left.
|
||||
@@ -205,7 +204,7 @@ Element gaugeRight(float progress) {
|
||||
/// └──────────────────────────────────────────────────────────────────────────┘
|
||||
/// ~~~
|
||||
Element gaugeLeft(float progress) {
|
||||
return gaugeDirection(progress, Direction::Left);
|
||||
return gaugeDirection(progress, GaugeDirection::Left);
|
||||
}
|
||||
|
||||
/// @brief Draw a high definition progress bar progressing from bottom to top.
|
||||
@@ -234,7 +233,7 @@ Element gaugeLeft(float progress) {
|
||||
/// └─┘
|
||||
/// ~~~
|
||||
Element gaugeUp(float progress) {
|
||||
return gaugeDirection(progress, Direction::Up);
|
||||
return gaugeDirection(progress, GaugeDirection::Up);
|
||||
}
|
||||
|
||||
/// @brief Draw a high definition progress bar progressing from top to bottom.
|
||||
@@ -263,7 +262,7 @@ Element gaugeUp(float progress) {
|
||||
/// └─┘
|
||||
/// ~~~
|
||||
Element gaugeDown(float progress) {
|
||||
return gaugeDirection(progress, Direction::Down);
|
||||
return gaugeDirection(progress, GaugeDirection::Down);
|
||||
}
|
||||
|
||||
/// @brief Draw a high definition progress bar.
|
||||
|
@@ -32,7 +32,7 @@ LinearGradientNormalized Normalize(LinearGradient gradient) {
|
||||
|
||||
// Fill in the two extent, if not provided.
|
||||
if (!gradient.stops.front().position) {
|
||||
gradient.stops.front().position = 0;
|
||||
gradient.stops.front().position = 0.f;
|
||||
}
|
||||
if (!gradient.stops.back().position) {
|
||||
gradient.stops.back().position = 1.f;
|
||||
|
@@ -3,7 +3,7 @@
|
||||
#include <utility> // for move
|
||||
#include <vector> // for __alloc_traits<>::value_type
|
||||
|
||||
#include "ftxui/dom/elements.hpp" // for Constraint, WidthOrHeight, EQUAL, GREATER_THAN, LESS_THAN, WIDTH, unpack, Decorator, Element, size
|
||||
#include "ftxui/dom/elements.hpp" // for Constraint, Direction, EQUAL, GREATER_THAN, LESS_THAN, WIDTH, unpack, Decorator, Element, size
|
||||
#include "ftxui/dom/node.hpp" // for Node, Elements
|
||||
#include "ftxui/dom/requirement.hpp" // for Requirement
|
||||
#include "ftxui/screen/box.hpp" // for Box
|
||||
@@ -12,7 +12,7 @@ namespace ftxui {
|
||||
|
||||
class Size : public Node {
|
||||
public:
|
||||
Size(Element child, WidthOrHeight direction, Constraint constraint, int value)
|
||||
Size(Element child, Direction direction, Constraint constraint, int value)
|
||||
: Node(unpack(std::move(child))),
|
||||
direction_(direction),
|
||||
constraint_(constraint),
|
||||
@@ -71,7 +71,7 @@ class Size : public Node {
|
||||
}
|
||||
|
||||
private:
|
||||
WidthOrHeight direction_;
|
||||
Direction direction_;
|
||||
Constraint constraint_;
|
||||
int value_;
|
||||
};
|
||||
@@ -82,7 +82,7 @@ class Size : public Node {
|
||||
/// @param constraint The type of constaint.
|
||||
/// @param value The value.
|
||||
/// @ingroup dom
|
||||
Decorator size(WidthOrHeight direction, Constraint constraint, int value) {
|
||||
Decorator size(Direction direction, Constraint constraint, int value) {
|
||||
return [=](Element e) {
|
||||
return std::make_shared<Size>(std::move(e), direction, constraint, value);
|
||||
};
|
||||
|
Reference in New Issue
Block a user