mirror of
				https://github.com/ArthurSonzogni/FTXUI.git
				synced 2025-10-31 18:48:11 +08:00 
			
		
		
		
	Feature resizable spilt with custom separator (#583)
* Feature: ResizableSplit with custom separator
This resolves:
    https://github.com/ArthurSonzogni/FTXUI/issues/580
Co-authored-by: Pin Loon Lee <pinloon_0428@hotmail.com>
			
			
This commit is contained in:
		| @@ -4,6 +4,14 @@ Changelog | |||||||
| current (development)  | current (development)  | ||||||
| --------------------- | --------------------- | ||||||
|  |  | ||||||
|  | ### Component | ||||||
|  | - Feature: Support `ResizableSplit` with customizable separator. | ||||||
|  | - Breaking: MenuDirection enum is renamed Direction | ||||||
|  |  | ||||||
|  | ### | ||||||
|  | - Breaking: Direction enum is renamed WidthOrHeight | ||||||
|  | - Breaking: GaugeDirection enum is renamed Direction | ||||||
|  |  | ||||||
| 4.0.0 | 4.0.0 | ||||||
| ----- | ----- | ||||||
|  |  | ||||||
|   | |||||||
| @@ -42,6 +42,7 @@ add_library(screen | |||||||
|  |  | ||||||
| add_library(dom | add_library(dom | ||||||
|   include/ftxui/dom/canvas.hpp |   include/ftxui/dom/canvas.hpp | ||||||
|  |   include/ftxui/dom/direction.hpp | ||||||
|   include/ftxui/dom/elements.hpp |   include/ftxui/dom/elements.hpp | ||||||
|   include/ftxui/dom/flexbox_config.hpp |   include/ftxui/dom/flexbox_config.hpp | ||||||
|   include/ftxui/dom/node.hpp |   include/ftxui/dom/node.hpp | ||||||
|   | |||||||
| @@ -2,9 +2,10 @@ | |||||||
| #include <cmath>                                  // for sin | #include <cmath>                                  // for sin | ||||||
| #include <ftxui/component/component_base.hpp>     // for ComponentBase | #include <ftxui/component/component_base.hpp>     // for ComponentBase | ||||||
| #include <ftxui/component/component_options.hpp>  // for SliderOption | #include <ftxui/component/component_options.hpp>  // for SliderOption | ||||||
| #include <ftxui/dom/elements.hpp>  // for size, GREATER_THAN, GaugeDirection, GaugeDirection::Up, HEIGHT | #include <ftxui/dom/direction.hpp>  // for Direction, Direction::Up | ||||||
| #include <ftxui/util/ref.hpp>  // for ConstRef, Ref | #include <ftxui/dom/elements.hpp>   // for size, GREATER_THAN, HEIGHT | ||||||
| #include <memory>              // for shared_ptr, __shared_ptr_access | #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/captured_mouse.hpp"  // for ftxui | ||||||
| #include "ftxui/component/component.hpp"  // for Horizontal, Slider, operator|= | #include "ftxui/component/component.hpp"  // for Horizontal, Slider, operator|= | ||||||
| @@ -26,7 +27,7 @@ int main(int argc, const char* argv[]) { | |||||||
|     option.value = &values[i]; |     option.value = &values[i]; | ||||||
|     option.max = 100; |     option.max = 100; | ||||||
|     option.increment = 5; |     option.increment = 5; | ||||||
|     option.direction = GaugeDirection::Up; |     option.direction = Direction::Up; | ||||||
|     layout_horizontal->Add(Slider<int>(option)); |     layout_horizontal->Add(Slider<int>(option)); | ||||||
|  |  | ||||||
|     /* In C++20: |     /* In C++20: | ||||||
| @@ -34,7 +35,7 @@ int main(int argc, const char* argv[]) { | |||||||
|         .value = &values[i], |         .value = &values[i], | ||||||
|         .max = 100, |         .max = 100, | ||||||
|         .increment = 5, |         .increment = 5, | ||||||
|         .direction = GaugeDirection::Up, |         .direction = Direction::Up, | ||||||
|     })); |     })); | ||||||
|     */ |     */ | ||||||
|   } |   } | ||||||
|   | |||||||
| @@ -92,6 +92,7 @@ Component ResizableSplitLeft(Component main, Component back, int* main_size); | |||||||
| Component ResizableSplitRight(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 ResizableSplitTop(Component main, Component back, int* main_size); | ||||||
| Component ResizableSplitBottom(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(Component child, std::function<Element()>); | ||||||
| Component Renderer(std::function<Element()>); | Component Renderer(std::function<Element()>); | ||||||
|   | |||||||
| @@ -3,12 +3,14 @@ | |||||||
|  |  | ||||||
| #include <chrono>                         // for milliseconds | #include <chrono>                         // for milliseconds | ||||||
| #include <ftxui/component/animation.hpp>  // for Duration, QuadraticInOut, Function | #include <ftxui/component/animation.hpp>  // for Duration, QuadraticInOut, Function | ||||||
| #include <ftxui/dom/elements.hpp>  // for Element, GaugeDirection, GaugeDirection::Right | #include <ftxui/dom/direction.hpp>  // for Direction, Direction::Left, Direction::Right, Direction::Down | ||||||
| #include <ftxui/util/ref.hpp>  // for Ref, ConstRef | #include <ftxui/dom/elements.hpp>  // for Element, separator | ||||||
| #include <functional>          // for function | #include <ftxui/util/ref.hpp>      // for Ref, ConstRef | ||||||
| #include <optional>            // for optional | #include <functional>              // for function | ||||||
| #include <string>              // for string | #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 | #include "ftxui/screen/color.hpp"  // for Color, Color::GrayDark, Color::White | ||||||
|  |  | ||||||
| namespace ftxui { | namespace ftxui { | ||||||
| @@ -87,8 +89,7 @@ struct MenuOption { | |||||||
|   // Style: |   // Style: | ||||||
|   UnderlineOption underline; |   UnderlineOption underline; | ||||||
|   MenuEntryOption entries; |   MenuEntryOption entries; | ||||||
|   enum Direction { Up, Down, Left, Right }; |   Direction direction = Direction::Down; | ||||||
|   Direction direction = Down; |  | ||||||
|   std::function<Element()> elements_prefix; |   std::function<Element()> elements_prefix; | ||||||
|   std::function<Element()> elements_infix; |   std::function<Element()> elements_infix; | ||||||
|   std::function<Element()> elements_postfix; |   std::function<Element()> elements_postfix; | ||||||
| @@ -164,6 +165,16 @@ struct RadioboxOption { | |||||||
|   Ref<int> focused_entry = 0; |   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. | // @brief Option for the `Slider` component. | ||||||
| // @ingroup component | // @ingroup component | ||||||
| template <typename T> | template <typename T> | ||||||
| @@ -172,7 +183,7 @@ struct SliderOption { | |||||||
|   ConstRef<T> min = T(0); |   ConstRef<T> min = T(0); | ||||||
|   ConstRef<T> max = T(100); |   ConstRef<T> max = T(100); | ||||||
|   ConstRef<T> increment = (max() - min()) / 20; |   ConstRef<T> increment = (max() - min()) / 20; | ||||||
|   GaugeDirection direction = GaugeDirection::Right; |   Direction direction = Direction::Right; | ||||||
|   Color color_active = Color::White; |   Color color_active = Color::White; | ||||||
|   Color color_inactive = Color::GrayDark; |   Color color_inactive = Color::GrayDark; | ||||||
| }; | }; | ||||||
|   | |||||||
							
								
								
									
										17
									
								
								include/ftxui/dom/direction.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								include/ftxui/dom/direction.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,17 @@ | |||||||
|  | #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,6 +5,7 @@ | |||||||
| #include <memory> | #include <memory> | ||||||
|  |  | ||||||
| #include "ftxui/dom/canvas.hpp" | #include "ftxui/dom/canvas.hpp" | ||||||
|  | #include "ftxui/dom/direction.hpp" | ||||||
| #include "ftxui/dom/flexbox_config.hpp" | #include "ftxui/dom/flexbox_config.hpp" | ||||||
| #include "ftxui/dom/node.hpp" | #include "ftxui/dom/node.hpp" | ||||||
| #include "ftxui/screen/box.hpp" | #include "ftxui/screen/box.hpp" | ||||||
| @@ -21,7 +22,6 @@ using Decorator = std::function<Element(Element)>; | |||||||
| using GraphFunction = std::function<std::vector<int>(int, int)>; | using GraphFunction = std::function<std::vector<int>(int, int)>; | ||||||
|  |  | ||||||
| enum BorderStyle { LIGHT, HEAVY, DOUBLE, ROUNDED, EMPTY }; | enum BorderStyle { LIGHT, HEAVY, DOUBLE, ROUNDED, EMPTY }; | ||||||
| enum class GaugeDirection { Left, Up, Right, Down }; |  | ||||||
|  |  | ||||||
| // Pipe elements into decorator togethers. | // Pipe elements into decorator togethers. | ||||||
| // For instance the next lines are equivalents: | // For instance the next lines are equivalents: | ||||||
| @@ -56,7 +56,7 @@ Element gaugeLeft(float progress); | |||||||
| Element gaugeRight(float progress); | Element gaugeRight(float progress); | ||||||
| Element gaugeUp(float progress); | Element gaugeUp(float progress); | ||||||
| Element gaugeDown(float progress); | Element gaugeDown(float progress); | ||||||
| Element gaugeDirection(float progress, GaugeDirection); | Element gaugeDirection(float progress, Direction direction); | ||||||
| Element border(Element); | Element border(Element); | ||||||
| Element borderLight(Element); | Element borderLight(Element); | ||||||
| Element borderHeavy(Element); | Element borderHeavy(Element); | ||||||
| @@ -124,9 +124,9 @@ Element notflex(Element);  // Reset the flex attribute. | |||||||
| Element filler();          // A blank expandable element. | Element filler();          // A blank expandable element. | ||||||
|  |  | ||||||
| // -- Size override; | // -- Size override; | ||||||
| enum Direction { WIDTH, HEIGHT }; | enum WidthOrHeight { WIDTH, HEIGHT }; | ||||||
| enum Constraint { LESS_THAN, EQUAL, GREATER_THAN }; | enum Constraint { LESS_THAN, EQUAL, GREATER_THAN }; | ||||||
| Decorator size(Direction, Constraint, int value); | Decorator size(WidthOrHeight, Constraint, int value); | ||||||
|  |  | ||||||
| // --- Frame --- | // --- Frame --- | ||||||
| // A frame is a scrollable area. The internal area is potentially larger than | // A frame is a scrollable area. The internal area is potentially larger than | ||||||
|   | |||||||
| @@ -1,16 +1,17 @@ | |||||||
| #include <algorithm>   // for max, fill_n, reverse | #include <algorithm>                // for max, fill_n, reverse | ||||||
| #include <chrono>      // for milliseconds | #include <chrono>                   // for milliseconds | ||||||
| #include <functional>  // for function | #include <ftxui/dom/direction.hpp>  // for Direction, Direction::Down, Direction::Left, Direction::Right, Direction::Up | ||||||
| #include <memory>      // for allocator_traits<>::value_type, swap | #include <functional>               // for function | ||||||
| #include <string>      // for operator+, string | #include <memory>                   // for allocator_traits<>::value_type, swap | ||||||
| #include <utility>     // for move | #include <string>                   // for operator+, string | ||||||
| #include <vector>      // for vector, __alloc_traits<>::value_type | #include <utility>                  // for move | ||||||
|  | #include <vector>                   // for vector, __alloc_traits<>::value_type | ||||||
|  |  | ||||||
| #include "ftxui/component/animation.hpp"       // for Animator, Linear | #include "ftxui/component/animation.hpp"       // for Animator, Linear | ||||||
| #include "ftxui/component/captured_mouse.hpp"  // for CapturedMouse | #include "ftxui/component/captured_mouse.hpp"  // for CapturedMouse | ||||||
| #include "ftxui/component/component.hpp"  // for Make, Menu, MenuEntry, Toggle | #include "ftxui/component/component.hpp"  // for Make, Menu, MenuEntry, Toggle | ||||||
| #include "ftxui/component/component_base.hpp"     // for ComponentBase | #include "ftxui/component/component_base.hpp"     // for ComponentBase | ||||||
| #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/component_options.hpp"  // for MenuOption, MenuEntryOption, UnderlineOption, AnimatedColorOption, AnimatedColorsOption, EntryState | ||||||
| #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/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/mouse.hpp"  // for Mouse, Mouse::Left, Mouse::Released, Mouse::WheelDown, Mouse::WheelUp, Mouse::None | ||||||
| #include "ftxui/component/screen_interactive.hpp"  // for Component | #include "ftxui/component/screen_interactive.hpp"  // for Component | ||||||
| @@ -36,25 +37,25 @@ Element DefaultOptionTransform(const EntryState& state) { | |||||||
|   return e; |   return e; | ||||||
| } | } | ||||||
|  |  | ||||||
| bool IsInverted(MenuOption::Direction direction) { | bool IsInverted(Direction direction) { | ||||||
|   switch (direction) { |   switch (direction) { | ||||||
|     case MenuOption::Direction::Up: |     case Direction::Up: | ||||||
|     case MenuOption::Direction::Left: |     case Direction::Left: | ||||||
|       return true; |       return true; | ||||||
|     case MenuOption::Direction::Down: |     case Direction::Down: | ||||||
|     case MenuOption::Direction::Right: |     case Direction::Right: | ||||||
|       return false; |       return false; | ||||||
|   } |   } | ||||||
|   return false;  // NOT_REACHED() |   return false;  // NOT_REACHED() | ||||||
| } | } | ||||||
|  |  | ||||||
| bool IsHorizontal(MenuOption::Direction direction) { | bool IsHorizontal(Direction direction) { | ||||||
|   switch (direction) { |   switch (direction) { | ||||||
|     case MenuOption::Direction::Left: |     case Direction::Left: | ||||||
|     case MenuOption::Direction::Right: |     case Direction::Right: | ||||||
|       return true; |       return true; | ||||||
|     case MenuOption::Direction::Down: |     case Direction::Down: | ||||||
|     case MenuOption::Direction::Up: |     case Direction::Up: | ||||||
|       return false; |       return false; | ||||||
|   } |   } | ||||||
|   return false;  // NOT_REACHED() |   return false;  // NOT_REACHED() | ||||||
| @@ -178,56 +179,56 @@ class MenuBase : public ComponentBase { | |||||||
|  |  | ||||||
|   void OnUp() { |   void OnUp() { | ||||||
|     switch (option_->direction) { |     switch (option_->direction) { | ||||||
|       case MenuOption::Direction::Up: |       case Direction::Up: | ||||||
|         (*selected_)++; |         (*selected_)++; | ||||||
|         break; |         break; | ||||||
|       case MenuOption::Direction::Down: |       case Direction::Down: | ||||||
|         (*selected_)--; |         (*selected_)--; | ||||||
|         break; |         break; | ||||||
|       case MenuOption::Direction::Left: |       case Direction::Left: | ||||||
|       case MenuOption::Direction::Right: |       case Direction::Right: | ||||||
|         break; |         break; | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   void OnDown() { |   void OnDown() { | ||||||
|     switch (option_->direction) { |     switch (option_->direction) { | ||||||
|       case MenuOption::Direction::Up: |       case Direction::Up: | ||||||
|         (*selected_)--; |         (*selected_)--; | ||||||
|         break; |         break; | ||||||
|       case MenuOption::Direction::Down: |       case Direction::Down: | ||||||
|         (*selected_)++; |         (*selected_)++; | ||||||
|         break; |         break; | ||||||
|       case MenuOption::Direction::Left: |       case Direction::Left: | ||||||
|       case MenuOption::Direction::Right: |       case Direction::Right: | ||||||
|         break; |         break; | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   void OnLeft() { |   void OnLeft() { | ||||||
|     switch (option_->direction) { |     switch (option_->direction) { | ||||||
|       case MenuOption::Direction::Left: |       case Direction::Left: | ||||||
|         (*selected_)++; |         (*selected_)++; | ||||||
|         break; |         break; | ||||||
|       case MenuOption::Direction::Right: |       case Direction::Right: | ||||||
|         (*selected_)--; |         (*selected_)--; | ||||||
|         break; |         break; | ||||||
|       case MenuOption::Direction::Down: |       case Direction::Down: | ||||||
|       case MenuOption::Direction::Up: |       case Direction::Up: | ||||||
|         break; |         break; | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   void OnRight() { |   void OnRight() { | ||||||
|     switch (option_->direction) { |     switch (option_->direction) { | ||||||
|       case MenuOption::Direction::Left: |       case Direction::Left: | ||||||
|         (*selected_)--; |         (*selected_)--; | ||||||
|         break; |         break; | ||||||
|       case MenuOption::Direction::Right: |       case Direction::Right: | ||||||
|         (*selected_)++; |         (*selected_)++; | ||||||
|         break; |         break; | ||||||
|       case MenuOption::Direction::Down: |       case Direction::Down: | ||||||
|       case MenuOption::Direction::Up: |       case Direction::Up: | ||||||
|         break; |         break; | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|   | |||||||
| @@ -1,5 +1,6 @@ | |||||||
| #include <gtest/gtest.h>  // for Test, EXPECT_EQ, Message, TestPartResult, TestInfo (ptr only), TEST | #include <gtest/gtest.h>  // for Test, EXPECT_EQ, Message, TestPartResult, TestInfo (ptr only), TEST | ||||||
| #include <chrono>  // for operator""s, chrono_literals | #include <chrono>                   // for operator""s, chrono_literals | ||||||
|  | #include <ftxui/dom/direction.hpp>  // for Direction, Direction::Down, Direction::Left, Direction::Right, Direction::Up | ||||||
| #include <memory>  // for __shared_ptr_access, shared_ptr, allocator | #include <memory>  // for __shared_ptr_access, shared_ptr, allocator | ||||||
| #include <string>  // for string, basic_string | #include <string>  // for string, basic_string | ||||||
| #include <vector>  // for vector | #include <vector>  // for vector | ||||||
| @@ -7,7 +8,7 @@ | |||||||
| #include "ftxui/component/animation.hpp"          // for Duration, Params | #include "ftxui/component/animation.hpp"          // for Duration, Params | ||||||
| #include "ftxui/component/component.hpp"          // for Menu | #include "ftxui/component/component.hpp"          // for Menu | ||||||
| #include "ftxui/component/component_base.hpp"     // for ComponentBase | #include "ftxui/component/component_base.hpp"     // for ComponentBase | ||||||
| #include "ftxui/component/component_options.hpp"  // for MenuOption, MenuOption::Down, MenuOption::Left, MenuOption::Right, MenuOption::Up | #include "ftxui/component/component_options.hpp"  // for MenuOption | ||||||
| #include "ftxui/component/event.hpp"  // for Event, Event::ArrowDown, Event::ArrowLeft, Event::ArrowRight, Event::ArrowUp, Event::Return | #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/dom/node.hpp"         // for Render | ||||||
| #include "ftxui/screen/screen.hpp"    // for Screen | #include "ftxui/screen/screen.hpp"    // for Screen | ||||||
| @@ -53,7 +54,7 @@ TEST(MenuTest, DirectionDown) { | |||||||
|   auto menu = Menu(&entries, &selected, &option); |   auto menu = Menu(&entries, &selected, &option); | ||||||
|  |  | ||||||
|   selected = 0; |   selected = 0; | ||||||
|   option.direction = MenuOption::Down; |   option.direction = Direction::Down; | ||||||
|   Screen screen(4, 3); |   Screen screen(4, 3); | ||||||
|   Render(screen, menu->Render()); |   Render(screen, menu->Render()); | ||||||
|   EXPECT_EQ(screen.ToString(), |   EXPECT_EQ(screen.ToString(), | ||||||
| @@ -80,7 +81,7 @@ TEST(MenuTest, DirectionsUp) { | |||||||
|   std::vector<std::string> entries = {"1", "2", "3"}; |   std::vector<std::string> entries = {"1", "2", "3"}; | ||||||
|   MenuOption option; |   MenuOption option; | ||||||
|   auto menu = Menu(&entries, &selected, &option); |   auto menu = Menu(&entries, &selected, &option); | ||||||
|   option.direction = MenuOption::Up; |   option.direction = Direction::Up; | ||||||
|   Screen screen(4, 3); |   Screen screen(4, 3); | ||||||
|   Render(screen, menu->Render()); |   Render(screen, menu->Render()); | ||||||
|   EXPECT_EQ(screen.ToString(), |   EXPECT_EQ(screen.ToString(), | ||||||
| @@ -106,7 +107,7 @@ TEST(MenuTest, DirectionsRight) { | |||||||
|   std::vector<std::string> entries = {"1", "2", "3"}; |   std::vector<std::string> entries = {"1", "2", "3"}; | ||||||
|   MenuOption option; |   MenuOption option; | ||||||
|   auto menu = Menu(&entries, &selected, &option); |   auto menu = Menu(&entries, &selected, &option); | ||||||
|   option.direction = MenuOption::Right; |   option.direction = Direction::Right; | ||||||
|   Screen screen(10, 1); |   Screen screen(10, 1); | ||||||
|   Render(screen, menu->Render()); |   Render(screen, menu->Render()); | ||||||
|   EXPECT_EQ(screen.ToString(), |   EXPECT_EQ(screen.ToString(), | ||||||
| @@ -132,7 +133,7 @@ TEST(MenuTest, DirectionsLeft) { | |||||||
|   std::vector<std::string> entries = {"1", "2", "3"}; |   std::vector<std::string> entries = {"1", "2", "3"}; | ||||||
|   MenuOption option; |   MenuOption option; | ||||||
|   auto menu = Menu(&entries, &selected, &option); |   auto menu = Menu(&entries, &selected, &option); | ||||||
|   option.direction = MenuOption::Left; |   option.direction = Direction::Left; | ||||||
|   Screen screen(10, 1); |   Screen screen(10, 1); | ||||||
|   Render(screen, menu->Render()); |   Render(screen, menu->Render()); | ||||||
|   EXPECT_EQ(screen.ToString(), |   EXPECT_EQ(screen.ToString(), | ||||||
|   | |||||||
| @@ -1,26 +1,28 @@ | |||||||
| #include <memory>   // for __shared_ptr_access | #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 <utility>  // for move | #include <utility>  // for move | ||||||
|  |  | ||||||
| #include "ftxui/component/captured_mouse.hpp"  // for CapturedMouse | #include "ftxui/component/captured_mouse.hpp"  // for CapturedMouse | ||||||
| #include "ftxui/component/component.hpp"  // for Component, Make, Horizontal, Vertical, ResizableSplitBottom, ResizableSplitLeft, ResizableSplitRight, ResizableSplitTop | #include "ftxui/component/component.hpp"  // for Horizontal, Make, ResizableSplit, ResizableSplitBottom, ResizableSplitLeft, ResizableSplitRight, ResizableSplitTop | ||||||
| #include "ftxui/component/component_base.hpp"  // for ComponentBase | #include "ftxui/component/component_base.hpp"  // for Component, ComponentBase | ||||||
| #include "ftxui/component/event.hpp"           // for Event | #include "ftxui/component/event.hpp"           // for Event | ||||||
| #include "ftxui/component/mouse.hpp"  // for Mouse, Mouse::Left, Mouse::Pressed, Mouse::Released | #include "ftxui/component/mouse.hpp"  // for Mouse, Mouse::Left, Mouse::Pressed, Mouse::Released | ||||||
| #include "ftxui/dom/elements.hpp"  // for operator|, reflect, Element, separator, size, EQUAL, xflex, yflex, hbox, vbox, HEIGHT, WIDTH | #include "ftxui/dom/elements.hpp"  // for operator|, reflect, Element, size, EQUAL, xflex, yflex, hbox, vbox, HEIGHT, WIDTH, text | ||||||
| #include "ftxui/screen/box.hpp"    // for Box | #include "ftxui/screen/box.hpp"    // for Box | ||||||
|  |  | ||||||
| namespace ftxui { | namespace ftxui { | ||||||
| namespace { | namespace { | ||||||
|  |  | ||||||
| class ResizableSplitLeftBase : public ComponentBase { | class ResizableSplitBase : public ComponentBase { | ||||||
|  public: |  public: | ||||||
|   ResizableSplitLeftBase(Component main, Component child, int* main_size) |   ResizableSplitBase(ResizableSplitOption options) | ||||||
|       : main_(std::move(main)), |       : options_(std::move(options)) { | ||||||
|         child_(std::move(child)), |  | ||||||
|         main_size_(main_size) { |  | ||||||
|     Add(Container::Horizontal({ |     Add(Container::Horizontal({ | ||||||
|         main_, |         options_->main, | ||||||
|         child_, |         options_->back, | ||||||
|     })); |     })); | ||||||
|   } |   } | ||||||
|  |  | ||||||
| @@ -45,204 +47,86 @@ class ResizableSplitLeftBase : public ComponentBase { | |||||||
|       return true; |       return true; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     if (captured_mouse_) { |     if (!captured_mouse_) { | ||||||
|       *main_size_ = event.mouse().x - box_.x_min; |       return ComponentBase::OnEvent(event); | ||||||
|       return true; |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     return ComponentBase::OnEvent(event); |     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; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   Element Render() final { |   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({ |     return hbox({ | ||||||
|                main_->Render() | size(WIDTH, EQUAL, *main_size_), |                options_->main->Render() | | ||||||
|                separator() | reflect(separator_box_), |                    size(WIDTH, EQUAL, options_->main_size()), | ||||||
|                child_->Render() | xflex, |                options_->separator_func() | reflect(separator_box_), | ||||||
|  |                options_->back->Render() | xflex, | ||||||
|            }) | |            }) | | ||||||
|            reflect(box_); |            reflect(box_); | ||||||
|   }; |   }; | ||||||
|  |  | ||||||
|  private: |   Element RenderRight() { | ||||||
|   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({ |     return hbox({ | ||||||
|                child_->Render() | xflex, |                options_->back->Render() | xflex, | ||||||
|                separator() | reflect(separator_box_), |                options_->separator_func() | reflect(separator_box_), | ||||||
|                main_->Render() | size(WIDTH, EQUAL, *main_size_), |                options_->main->Render() | | ||||||
|  |                    size(WIDTH, EQUAL, options_->main_size()), | ||||||
|            }) | |            }) | | ||||||
|            reflect(box_); |            reflect(box_); | ||||||
|   }; |   }; | ||||||
|  |  | ||||||
|  private: |   Element RenderTop() { | ||||||
|   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({ |     return vbox({ | ||||||
|                main_->Render() | size(HEIGHT, EQUAL, *main_size_), |                options_->main->Render() | | ||||||
|                separator() | reflect(separator_box_), |                    size(HEIGHT, EQUAL, options_->main_size()), | ||||||
|                child_->Render() | yflex, |                options_->separator_func() | reflect(separator_box_), | ||||||
|  |                options_->back->Render() | yflex, | ||||||
|            }) | |            }) | | ||||||
|            reflect(box_); |            reflect(box_); | ||||||
|   }; |   }; | ||||||
|  |  | ||||||
|  private: |   Element RenderBottom() { | ||||||
|   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({ |     return vbox({ | ||||||
|                child_->Render() | yflex, |                options_->back->Render() | yflex, | ||||||
|                separator() | reflect(separator_box_), |                options_->separator_func() | reflect(separator_box_), | ||||||
|                main_->Render() | size(HEIGHT, EQUAL, *main_size_), |                options_->main->Render() | | ||||||
|  |                    size(HEIGHT, EQUAL, options_->main_size()), | ||||||
|            }) | |            }) | | ||||||
|            reflect(box_); |            reflect(box_); | ||||||
|   }; |   }; | ||||||
|  |  | ||||||
|  private: |  private: | ||||||
|   Component main_; |   Ref<ResizableSplitOption> options_; | ||||||
|   Component child_; |  | ||||||
|   int* const main_size_; |  | ||||||
|   CapturedMouse captured_mouse_; |   CapturedMouse captured_mouse_; | ||||||
|   Box separator_box_; |   Box separator_box_; | ||||||
|   Box box_; |   Box box_; | ||||||
| @@ -250,6 +134,35 @@ class ResizableSplitBottomBase : public ComponentBase { | |||||||
|  |  | ||||||
| }  // namespace | }  // 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 | /// @brief An horizontal split in between two components, configurable using the | ||||||
| /// mouse. | /// mouse. | ||||||
| /// @param main The main component of size |main_size|, on the left. | /// @param main The main component of size |main_size|, on the left. | ||||||
| @@ -276,8 +189,12 @@ class ResizableSplitBottomBase : public ComponentBase { | |||||||
| ///           │ | ///           │ | ||||||
| /// ``` | /// ``` | ||||||
| Component ResizableSplitLeft(Component main, Component back, int* main_size) { | Component ResizableSplitLeft(Component main, Component back, int* main_size) { | ||||||
|   return Make<ResizableSplitLeftBase>(std::move(main), std::move(back), |   return ResizableSplit({ | ||||||
|                                       main_size); |       std::move(main), | ||||||
|  |       std::move(back), | ||||||
|  |       Direction::Left, | ||||||
|  |       main_size, | ||||||
|  |   }); | ||||||
| } | } | ||||||
|  |  | ||||||
| /// @brief An horizontal split in between two components, configurable using the | /// @brief An horizontal split in between two components, configurable using the | ||||||
| @@ -294,7 +211,7 @@ Component ResizableSplitLeft(Component main, Component back, int* main_size) { | |||||||
| /// int right_size = 10; | /// int right_size = 10; | ||||||
| /// auto left = Renderer([] { return text("Left") | center;}); | /// auto left = Renderer([] { return text("Left") | center;}); | ||||||
| /// auto right = Renderer([] { return text("right") | 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); | /// screen.Loop(split); | ||||||
| /// ``` | /// ``` | ||||||
| /// | /// | ||||||
| @@ -306,8 +223,12 @@ Component ResizableSplitLeft(Component main, Component back, int* main_size) { | |||||||
| ///           │ | ///           │ | ||||||
| /// ``` | /// ``` | ||||||
| Component ResizableSplitRight(Component main, Component back, int* main_size) { | Component ResizableSplitRight(Component main, Component back, int* main_size) { | ||||||
|   return Make<ResizableSplitRightBase>(std::move(main), std::move(back), |   return ResizableSplit({ | ||||||
|                                        main_size); |       std::move(main), | ||||||
|  |       std::move(back), | ||||||
|  |       Direction::Right, | ||||||
|  |       main_size, | ||||||
|  |   }); | ||||||
| } | } | ||||||
|  |  | ||||||
| /// @brief An vertical split in between two components, configurable using the | /// @brief An vertical split in between two components, configurable using the | ||||||
| @@ -324,7 +245,7 @@ Component ResizableSplitRight(Component main, Component back, int* main_size) { | |||||||
| /// int top_size = 1; | /// int top_size = 1; | ||||||
| /// auto top = Renderer([] { return text("Top") | center;}); | /// auto top = Renderer([] { return text("Top") | center;}); | ||||||
| /// auto bottom = Renderer([] { return text("Bottom") | 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); | /// screen.Loop(split); | ||||||
| /// ``` | /// ``` | ||||||
| /// | /// | ||||||
| @@ -336,8 +257,12 @@ Component ResizableSplitRight(Component main, Component back, int* main_size) { | |||||||
| ///    bottom | ///    bottom | ||||||
| /// ``` | /// ``` | ||||||
| Component ResizableSplitTop(Component main, Component back, int* main_size) { | Component ResizableSplitTop(Component main, Component back, int* main_size) { | ||||||
|   return Make<ResizableSplitTopBase>(std::move(main), std::move(back), |   return ResizableSplit({ | ||||||
|                                      main_size); |       std::move(main), | ||||||
|  |       std::move(back), | ||||||
|  |       Direction::Up, | ||||||
|  |       main_size, | ||||||
|  |   }); | ||||||
| } | } | ||||||
|  |  | ||||||
| /// @brief An vertical split in between two components, configurable using the | /// @brief An vertical split in between two components, configurable using the | ||||||
| @@ -354,7 +279,7 @@ Component ResizableSplitTop(Component main, Component back, int* main_size) { | |||||||
| /// int bottom_size = 1; | /// int bottom_size = 1; | ||||||
| /// auto top = Renderer([] { return text("Top") | center;}); | /// auto top = Renderer([] { return text("Top") | center;}); | ||||||
| /// auto bottom = Renderer([] { return text("Bottom") | 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); | /// screen.Loop(split); | ||||||
| /// ``` | /// ``` | ||||||
| /// | /// | ||||||
| @@ -366,9 +291,14 @@ Component ResizableSplitTop(Component main, Component back, int* main_size) { | |||||||
| ///    bottom | ///    bottom | ||||||
| /// ``` | /// ``` | ||||||
| Component ResizableSplitBottom(Component main, Component back, int* main_size) { | Component ResizableSplitBottom(Component main, Component back, int* main_size) { | ||||||
|   return Make<ResizableSplitBottomBase>(std::move(main), std::move(back), |   return ResizableSplit({ | ||||||
|                                         main_size); |       std::move(main), | ||||||
|  |       std::move(back), | ||||||
|  |       Direction::Down, | ||||||
|  |       main_size, | ||||||
|  |   }); | ||||||
| } | } | ||||||
|  |  | ||||||
| }  // namespace ftxui | }  // namespace ftxui | ||||||
|  |  | ||||||
| // Copyright 2021 Arthur Sonzogni. All rights reserved. | // Copyright 2021 Arthur Sonzogni. All rights reserved. | ||||||
|   | |||||||
| @@ -1,11 +1,12 @@ | |||||||
| #include <gtest/gtest.h> | #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 <memory>  // for __shared_ptr_access, shared_ptr, allocator | #include <memory>  // for __shared_ptr_access, shared_ptr, allocator | ||||||
|  |  | ||||||
| #include "ftxui/component/component.hpp"  // for Renderer, ResizableSplitBottom, ResizableSplitLeft, ResizableSplitRight, ResizableSplitTop | #include "ftxui/component/component.hpp"  // for ResizableSplit, Renderer, ResizableSplitBottom, ResizableSplitLeft, ResizableSplitRight, ResizableSplitTop | ||||||
| #include "ftxui/component/component_base.hpp"  // for ComponentBase, Component | #include "ftxui/component/component_base.hpp"  // for ComponentBase, Component | ||||||
| #include "ftxui/component/event.hpp"           // for Event | #include "ftxui/component/event.hpp"           // for Event | ||||||
| #include "ftxui/component/mouse.hpp"  // for Mouse, Mouse::Left, Mouse::Pressed, Mouse::Released | #include "ftxui/component/mouse.hpp"  // for Mouse, Mouse::Left, Mouse::Pressed, Mouse::Released | ||||||
| #include "ftxui/dom/elements.hpp"   // for text, Element | #include "ftxui/dom/elements.hpp"   // for Element, separatorDouble, text | ||||||
| #include "ftxui/dom/node.hpp"       // for Render | #include "ftxui/dom/node.hpp"       // for Render | ||||||
| #include "ftxui/screen/screen.hpp"  // for Screen | #include "ftxui/screen/screen.hpp"  // for Screen | ||||||
|  |  | ||||||
| @@ -56,6 +57,31 @@ TEST(ResizableSplit, BasicLeft) { | |||||||
|   EXPECT_EQ(position, 10); |   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) { | TEST(ResizableSplit, BasicRight) { | ||||||
|   int position = 3; |   int position = 3; | ||||||
|   auto component = |   auto component = | ||||||
| @@ -71,6 +97,31 @@ TEST(ResizableSplit, BasicRight) { | |||||||
|   EXPECT_EQ(position, 9); |   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) { | TEST(ResizableSplit, BasicTop) { | ||||||
|   int position = 3; |   int position = 3; | ||||||
|   auto component = |   auto component = | ||||||
| @@ -86,6 +137,31 @@ TEST(ResizableSplit, BasicTop) { | |||||||
|   EXPECT_EQ(position, 10); |   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) { | TEST(ResizableSplit, BasicBottom) { | ||||||
|   int position = 3; |   int position = 3; | ||||||
|   auto component = |   auto component = | ||||||
| @@ -101,6 +177,31 @@ TEST(ResizableSplit, BasicBottom) { | |||||||
|   EXPECT_EQ(position, 9); |   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 | }  // namespace ftxui | ||||||
|  |  | ||||||
| // Copyright 2022 Arthur Sonzogni. All rights reserved. | // Copyright 2022 Arthur Sonzogni. All rights reserved. | ||||||
|   | |||||||
| @@ -1,7 +1,8 @@ | |||||||
| #include <algorithm>                              // for max, min | #include <algorithm>                              // for max, min | ||||||
| #include <ftxui/component/component_options.hpp>  // for SliderOption | #include <ftxui/component/component_options.hpp>  // for SliderOption | ||||||
| #include <string>                                 // for allocator | #include <ftxui/dom/direction.hpp>  // for Direction, Direction::Down, Direction::Left, Direction::Right, Direction::Up | ||||||
| #include <utility>                                // for move | #include <string>                   // for allocator | ||||||
|  | #include <utility>                  // for move | ||||||
|  |  | ||||||
| #include "ftxui/component/captured_mouse.hpp"  // for CapturedMouse | #include "ftxui/component/captured_mouse.hpp"  // for CapturedMouse | ||||||
| #include "ftxui/component/component.hpp"       // for Make, Slider | #include "ftxui/component/component.hpp"       // for Make, Slider | ||||||
| @@ -9,7 +10,7 @@ | |||||||
| #include "ftxui/component/event.hpp"  // for Event, Event::ArrowDown, Event::ArrowLeft, Event::ArrowRight, Event::ArrowUp | #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/mouse.hpp"  // for Mouse, Mouse::Left, Mouse::Pressed, Mouse::Released | ||||||
| #include "ftxui/component/screen_interactive.hpp"  // for Component | #include "ftxui/component/screen_interactive.hpp"  // for Component | ||||||
| #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/dom/elements.hpp"  // for operator|, text, Element, xflex, hbox, color, underlined, reflect, Decorator, dim, vcenter, focus, nothing, select, yflex, gaugeDirection | ||||||
| #include "ftxui/screen/box.hpp"    // for Box | #include "ftxui/screen/box.hpp"    // for Box | ||||||
| #include "ftxui/screen/color.hpp"  // for Color, Color::GrayDark, Color::White | #include "ftxui/screen/color.hpp"  // for Color, Color::GrayDark, Color::White | ||||||
| #include "ftxui/screen/util.hpp"   // for clamp | #include "ftxui/screen/util.hpp"   // for clamp | ||||||
| @@ -18,13 +19,13 @@ | |||||||
| namespace ftxui { | namespace ftxui { | ||||||
|  |  | ||||||
| namespace { | namespace { | ||||||
| Decorator flexDirection(GaugeDirection direction) { | Decorator flexDirection(Direction direction) { | ||||||
|   switch (direction) { |   switch (direction) { | ||||||
|     case GaugeDirection::Up: |     case Direction::Up: | ||||||
|     case GaugeDirection::Down: |     case Direction::Down: | ||||||
|       return yflex; |       return yflex; | ||||||
|     case GaugeDirection::Left: |     case Direction::Left: | ||||||
|     case GaugeDirection::Right: |     case Direction::Right: | ||||||
|       return xflex; |       return xflex; | ||||||
|   } |   } | ||||||
|   return xflex;  // NOT_REACHED() |   return xflex;  // NOT_REACHED() | ||||||
| @@ -52,56 +53,56 @@ class SliderBase : public ComponentBase { | |||||||
|  |  | ||||||
|   void OnLeft() { |   void OnLeft() { | ||||||
|     switch (options_->direction) { |     switch (options_->direction) { | ||||||
|       case GaugeDirection::Right: |       case Direction::Right: | ||||||
|         value_() -= increment_(); |         value_() -= increment_(); | ||||||
|         break; |         break; | ||||||
|       case GaugeDirection::Left: |       case Direction::Left: | ||||||
|         value_() += increment_(); |         value_() += increment_(); | ||||||
|         break; |         break; | ||||||
|       case GaugeDirection::Up: |       case Direction::Up: | ||||||
|       case GaugeDirection::Down: |       case Direction::Down: | ||||||
|         break; |         break; | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   void OnRight() { |   void OnRight() { | ||||||
|     switch (options_->direction) { |     switch (options_->direction) { | ||||||
|       case GaugeDirection::Right: |       case Direction::Right: | ||||||
|         value_() += increment_(); |         value_() += increment_(); | ||||||
|         break; |         break; | ||||||
|       case GaugeDirection::Left: |       case Direction::Left: | ||||||
|         value_() -= increment_(); |         value_() -= increment_(); | ||||||
|         break; |         break; | ||||||
|       case GaugeDirection::Up: |       case Direction::Up: | ||||||
|       case GaugeDirection::Down: |       case Direction::Down: | ||||||
|         break; |         break; | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   void OnUp() { |   void OnUp() { | ||||||
|     switch (options_->direction) { |     switch (options_->direction) { | ||||||
|       case GaugeDirection::Up: |       case Direction::Up: | ||||||
|         value_() -= increment_(); |         value_() -= increment_(); | ||||||
|         break; |         break; | ||||||
|       case GaugeDirection::Down: |       case Direction::Down: | ||||||
|         value_() += increment_(); |         value_() += increment_(); | ||||||
|         break; |         break; | ||||||
|       case GaugeDirection::Left: |       case Direction::Left: | ||||||
|       case GaugeDirection::Right: |       case Direction::Right: | ||||||
|         break; |         break; | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   void OnDown() { |   void OnDown() { | ||||||
|     switch (options_->direction) { |     switch (options_->direction) { | ||||||
|       case GaugeDirection::Down: |       case Direction::Down: | ||||||
|         value_() -= increment_(); |         value_() -= increment_(); | ||||||
|         break; |         break; | ||||||
|       case GaugeDirection::Up: |       case Direction::Up: | ||||||
|         value_() += increment_(); |         value_() += increment_(); | ||||||
|         break; |         break; | ||||||
|       case GaugeDirection::Left: |       case Direction::Left: | ||||||
|       case GaugeDirection::Right: |       case Direction::Right: | ||||||
|         break; |         break; | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
| @@ -153,25 +154,25 @@ class SliderBase : public ComponentBase { | |||||||
|  |  | ||||||
|     if (captured_mouse_) { |     if (captured_mouse_) { | ||||||
|       switch (options_->direction) { |       switch (options_->direction) { | ||||||
|         case GaugeDirection::Right: { |         case Direction::Right: { | ||||||
|           value_() = min_() + (event.mouse().x - gauge_box_.x_min) * |           value_() = min_() + (event.mouse().x - gauge_box_.x_min) * | ||||||
|                                   (max_() - min_()) / |                                   (max_() - min_()) / | ||||||
|                                   (gauge_box_.x_max - gauge_box_.x_min); |                                   (gauge_box_.x_max - gauge_box_.x_min); | ||||||
|           break; |           break; | ||||||
|         } |         } | ||||||
|         case GaugeDirection::Left: { |         case Direction::Left: { | ||||||
|           value_() = max_() - (event.mouse().x - gauge_box_.x_min) * |           value_() = max_() - (event.mouse().x - gauge_box_.x_min) * | ||||||
|                                   (max_() - min_()) / |                                   (max_() - min_()) / | ||||||
|                                   (gauge_box_.x_max - gauge_box_.x_min); |                                   (gauge_box_.x_max - gauge_box_.x_min); | ||||||
|           break; |           break; | ||||||
|         } |         } | ||||||
|         case GaugeDirection::Down: { |         case Direction::Down: { | ||||||
|           value_() = min_() + (event.mouse().y - gauge_box_.y_min) * |           value_() = min_() + (event.mouse().y - gauge_box_.y_min) * | ||||||
|                                   (max_() - min_()) / |                                   (max_() - min_()) / | ||||||
|                                   (gauge_box_.y_max - gauge_box_.y_min); |                                   (gauge_box_.y_max - gauge_box_.y_min); | ||||||
|           break; |           break; | ||||||
|         } |         } | ||||||
|         case GaugeDirection::Up: { |         case Direction::Up: { | ||||||
|           value_() = max_() - (event.mouse().y - gauge_box_.y_min) * |           value_() = max_() - (event.mouse().y - gauge_box_.y_min) * | ||||||
|                                   (max_() - min_()) / |                                   (max_() - min_()) / | ||||||
|                                   (gauge_box_.y_max - gauge_box_.y_min); |                                   (gauge_box_.y_max - gauge_box_.y_min); | ||||||
|   | |||||||
| @@ -2,7 +2,8 @@ | |||||||
| #include <stddef.h>       // for size_t | #include <stddef.h>       // for size_t | ||||||
| #include <array>          // for array | #include <array>          // for array | ||||||
| #include <ftxui/component/mouse.hpp>  // for Mouse, Mouse::Left, Mouse::Pressed, Mouse::Released | #include <ftxui/component/mouse.hpp>  // for Mouse, Mouse::Left, Mouse::Pressed, Mouse::Released | ||||||
| #include <ftxui/dom/elements.hpp>  // for GaugeDirection, GaugeDirection::Down, GaugeDirection::Left, GaugeDirection::Right, GaugeDirection::Up, frame | #include <ftxui/dom/direction.hpp>  // for Direction, Direction::Down, Direction::Left, Direction::Right, Direction::Up | ||||||
|  | #include <ftxui/dom/elements.hpp>   // for frame | ||||||
| #include <memory>  // for shared_ptr, __shared_ptr_access, allocator | #include <memory>  // for shared_ptr, __shared_ptr_access, allocator | ||||||
| #include <string>  // for to_string | #include <string>  // for to_string | ||||||
|  |  | ||||||
| @@ -47,7 +48,7 @@ TEST(SliderTest, Right) { | |||||||
|       .min = 0, |       .min = 0, | ||||||
|       .max = 100, |       .max = 100, | ||||||
|       .increment = 10, |       .increment = 10, | ||||||
|       .direction = GaugeDirection::Right, |       .direction = Direction::Right, | ||||||
|   }); |   }); | ||||||
|   Screen screen(11, 1); |   Screen screen(11, 1); | ||||||
|   Render(screen, slider->Render()); |   Render(screen, slider->Render()); | ||||||
| @@ -70,7 +71,7 @@ TEST(SliderTest, Left) { | |||||||
|       .min = 0, |       .min = 0, | ||||||
|       .max = 100, |       .max = 100, | ||||||
|       .increment = 10, |       .increment = 10, | ||||||
|       .direction = GaugeDirection::Left, |       .direction = Direction::Left, | ||||||
|   }); |   }); | ||||||
|   Screen screen(11, 1); |   Screen screen(11, 1); | ||||||
|   Render(screen, slider->Render()); |   Render(screen, slider->Render()); | ||||||
| @@ -93,7 +94,7 @@ TEST(SliderTest, Down) { | |||||||
|       .min = 0, |       .min = 0, | ||||||
|       .max = 100, |       .max = 100, | ||||||
|       .increment = 10, |       .increment = 10, | ||||||
|       .direction = GaugeDirection::Down, |       .direction = Direction::Down, | ||||||
|   }); |   }); | ||||||
|   Screen screen(1, 11); |   Screen screen(1, 11); | ||||||
|   Render(screen, slider->Render()); |   Render(screen, slider->Render()); | ||||||
| @@ -116,7 +117,7 @@ TEST(SliderTest, Up) { | |||||||
|       .min = 0, |       .min = 0, | ||||||
|       .max = 100, |       .max = 100, | ||||||
|       .increment = 10, |       .increment = 10, | ||||||
|       .direction = GaugeDirection::Up, |       .direction = Direction::Up, | ||||||
|   }); |   }); | ||||||
|   Screen screen(1, 11); |   Screen screen(1, 11); | ||||||
|   Render(screen, slider->Render()); |   Render(screen, slider->Render()); | ||||||
|   | |||||||
| @@ -1,8 +1,9 @@ | |||||||
| #include <memory>  // for allocator, make_shared | #include <ftxui/dom/direction.hpp>  // for Direction, Direction::Down, Direction::Left, Direction::Right, Direction::Up | ||||||
| #include <string>  // for string | #include <memory>                   // for allocator, make_shared | ||||||
|  | #include <string>                   // for string | ||||||
|  |  | ||||||
| #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/elements.hpp"  // for Element, gauge, gaugeDirection, gaugeDown, gaugeLeft, gaugeRight, gaugeUp | ||||||
| #include "ftxui/dom/node.hpp"      // for Node | #include "ftxui/dom/node.hpp"         // for Node | ||||||
| #include "ftxui/dom/requirement.hpp"  // for Requirement | #include "ftxui/dom/requirement.hpp"  // for Requirement | ||||||
| #include "ftxui/screen/box.hpp"       // for Box | #include "ftxui/screen/box.hpp"       // for Box | ||||||
| #include "ftxui/screen/screen.hpp"    // for Screen, Pixel | #include "ftxui/screen/screen.hpp"    // for Screen, Pixel | ||||||
| @@ -40,7 +41,7 @@ static const std::string charset_vertical[10] = { | |||||||
|  |  | ||||||
| class Gauge : public Node { | class Gauge : public Node { | ||||||
|  public: |  public: | ||||||
|   Gauge(float progress, GaugeDirection direction) |   Gauge(float progress, Direction direction) | ||||||
|       : progress_(progress), direction_(direction) { |       : progress_(progress), direction_(direction) { | ||||||
|     // This handle NAN correctly: |     // This handle NAN correctly: | ||||||
|     if (!(progress_ > 0.F)) { |     if (!(progress_ > 0.F)) { | ||||||
| @@ -53,15 +54,15 @@ class Gauge : public Node { | |||||||
|  |  | ||||||
|   void ComputeRequirement() override { |   void ComputeRequirement() override { | ||||||
|     switch (direction_) { |     switch (direction_) { | ||||||
|       case GaugeDirection::Right: |       case Direction::Right: | ||||||
|       case GaugeDirection::Left: |       case Direction::Left: | ||||||
|         requirement_.flex_grow_x = 1; |         requirement_.flex_grow_x = 1; | ||||||
|         requirement_.flex_grow_y = 0; |         requirement_.flex_grow_y = 0; | ||||||
|         requirement_.flex_shrink_x = 1; |         requirement_.flex_shrink_x = 1; | ||||||
|         requirement_.flex_shrink_y = 0; |         requirement_.flex_shrink_y = 0; | ||||||
|         break; |         break; | ||||||
|       case GaugeDirection::Up: |       case Direction::Up: | ||||||
|       case GaugeDirection::Down: |       case Direction::Down: | ||||||
|         requirement_.flex_grow_x = 0; |         requirement_.flex_grow_x = 0; | ||||||
|         requirement_.flex_grow_y = 1; |         requirement_.flex_grow_y = 1; | ||||||
|         requirement_.flex_shrink_x = 0; |         requirement_.flex_shrink_x = 0; | ||||||
| @@ -74,16 +75,16 @@ class Gauge : public Node { | |||||||
|  |  | ||||||
|   void Render(Screen& screen) override { |   void Render(Screen& screen) override { | ||||||
|     switch (direction_) { |     switch (direction_) { | ||||||
|       case GaugeDirection::Right: |       case Direction::Right: | ||||||
|         RenderHorizontal(screen, /*invert=*/false); |         RenderHorizontal(screen, /*invert=*/false); | ||||||
|         break; |         break; | ||||||
|       case GaugeDirection::Up: |       case Direction::Up: | ||||||
|         RenderVertical(screen, /*invert=*/false); |         RenderVertical(screen, /*invert=*/false); | ||||||
|         break; |         break; | ||||||
|       case GaugeDirection::Left: |       case Direction::Left: | ||||||
|         RenderHorizontal(screen, /*invert=*/true); |         RenderHorizontal(screen, /*invert=*/true); | ||||||
|         break; |         break; | ||||||
|       case GaugeDirection::Down: |       case Direction::Down: | ||||||
|         RenderVertical(screen, /*invert=*/true); |         RenderVertical(screen, /*invert=*/true); | ||||||
|         break; |         break; | ||||||
|     } |     } | ||||||
| @@ -151,7 +152,7 @@ class Gauge : public Node { | |||||||
|  |  | ||||||
|  private: |  private: | ||||||
|   float progress_; |   float progress_; | ||||||
|   GaugeDirection direction_; |   Direction direction_; | ||||||
| }; | }; | ||||||
|  |  | ||||||
| /// @brief Draw a high definition progress bar progressing in specified | /// @brief Draw a high definition progress bar progressing in specified | ||||||
| @@ -159,7 +160,7 @@ class Gauge : public Node { | |||||||
| /// @param progress The proportion of the area to be filled. Belong to [0,1]. | /// @param progress The proportion of the area to be filled. Belong to [0,1]. | ||||||
| //  @param direction Direction of progress bars progression. | //  @param direction Direction of progress bars progression. | ||||||
| /// @ingroup dom | /// @ingroup dom | ||||||
| Element gaugeDirection(float progress, GaugeDirection direction) { | Element gaugeDirection(float progress, Direction direction) { | ||||||
|   return std::make_shared<Gauge>(progress, direction); |   return std::make_shared<Gauge>(progress, direction); | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -182,7 +183,7 @@ Element gaugeDirection(float progress, GaugeDirection direction) { | |||||||
| /// └──────────────────────────────────────────────────────────────────────────┘ | /// └──────────────────────────────────────────────────────────────────────────┘ | ||||||
| /// ~~~ | /// ~~~ | ||||||
| Element gaugeRight(float progress) { | Element gaugeRight(float progress) { | ||||||
|   return gaugeDirection(progress, GaugeDirection::Right); |   return gaugeDirection(progress, Direction::Right); | ||||||
| } | } | ||||||
|  |  | ||||||
| /// @brief Draw a high definition progress bar progressing from right to left. | /// @brief Draw a high definition progress bar progressing from right to left. | ||||||
| @@ -204,7 +205,7 @@ Element gaugeRight(float progress) { | |||||||
| /// └──────────────────────────────────────────────────────────────────────────┘ | /// └──────────────────────────────────────────────────────────────────────────┘ | ||||||
| /// ~~~ | /// ~~~ | ||||||
| Element gaugeLeft(float progress) { | Element gaugeLeft(float progress) { | ||||||
|   return gaugeDirection(progress, GaugeDirection::Left); |   return gaugeDirection(progress, Direction::Left); | ||||||
| } | } | ||||||
|  |  | ||||||
| /// @brief Draw a high definition progress bar progressing from bottom to top. | /// @brief Draw a high definition progress bar progressing from bottom to top. | ||||||
| @@ -233,7 +234,7 @@ Element gaugeLeft(float progress) { | |||||||
| ///  └─┘ | ///  └─┘ | ||||||
| /// ~~~ | /// ~~~ | ||||||
| Element gaugeUp(float progress) { | Element gaugeUp(float progress) { | ||||||
|   return gaugeDirection(progress, GaugeDirection::Up); |   return gaugeDirection(progress, Direction::Up); | ||||||
| } | } | ||||||
|  |  | ||||||
| /// @brief Draw a high definition progress bar progressing from top to bottom. | /// @brief Draw a high definition progress bar progressing from top to bottom. | ||||||
| @@ -262,7 +263,7 @@ Element gaugeUp(float progress) { | |||||||
| ///  └─┘ | ///  └─┘ | ||||||
| /// ~~~ | /// ~~~ | ||||||
| Element gaugeDown(float progress) { | Element gaugeDown(float progress) { | ||||||
|   return gaugeDirection(progress, GaugeDirection::Down); |   return gaugeDirection(progress, Direction::Down); | ||||||
| } | } | ||||||
|  |  | ||||||
| /// @brief Draw a high definition progress bar. | /// @brief Draw a high definition progress bar. | ||||||
|   | |||||||
| @@ -3,7 +3,7 @@ | |||||||
| #include <utility>    // for move | #include <utility>    // for move | ||||||
| #include <vector>     // for __alloc_traits<>::value_type | #include <vector>     // for __alloc_traits<>::value_type | ||||||
|  |  | ||||||
| #include "ftxui/dom/elements.hpp"  // for Constraint, Direction, EQUAL, GREATER_THAN, LESS_THAN, WIDTH, unpack, Decorator, Element, size | #include "ftxui/dom/elements.hpp"  // for Constraint, WidthOrHeight, EQUAL, GREATER_THAN, LESS_THAN, WIDTH, unpack, Decorator, Element, size | ||||||
| #include "ftxui/dom/node.hpp"      // for Node, Elements | #include "ftxui/dom/node.hpp"      // for Node, Elements | ||||||
| #include "ftxui/dom/requirement.hpp"  // for Requirement | #include "ftxui/dom/requirement.hpp"  // for Requirement | ||||||
| #include "ftxui/screen/box.hpp"       // for Box | #include "ftxui/screen/box.hpp"       // for Box | ||||||
| @@ -12,7 +12,7 @@ namespace ftxui { | |||||||
|  |  | ||||||
| class Size : public Node { | class Size : public Node { | ||||||
|  public: |  public: | ||||||
|   Size(Element child, Direction direction, Constraint constraint, int value) |   Size(Element child, WidthOrHeight direction, Constraint constraint, int value) | ||||||
|       : Node(unpack(std::move(child))), |       : Node(unpack(std::move(child))), | ||||||
|         direction_(direction), |         direction_(direction), | ||||||
|         constraint_(constraint), |         constraint_(constraint), | ||||||
| @@ -71,7 +71,7 @@ class Size : public Node { | |||||||
|   } |   } | ||||||
|  |  | ||||||
|  private: |  private: | ||||||
|   Direction direction_; |   WidthOrHeight direction_; | ||||||
|   Constraint constraint_; |   Constraint constraint_; | ||||||
|   int value_; |   int value_; | ||||||
| }; | }; | ||||||
| @@ -82,7 +82,7 @@ class Size : public Node { | |||||||
| /// @param constraint The type of constaint. | /// @param constraint The type of constaint. | ||||||
| /// @param value The value. | /// @param value The value. | ||||||
| /// @ingroup dom | /// @ingroup dom | ||||||
| Decorator size(Direction direction, Constraint constraint, int value) { | Decorator size(WidthOrHeight direction, Constraint constraint, int value) { | ||||||
|   return [=](Element e) { |   return [=](Element e) { | ||||||
|     return std::make_shared<Size>(std::move(e), direction, constraint, value); |     return std::make_shared<Size>(std::move(e), direction, constraint, value); | ||||||
|   }; |   }; | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Arthur Sonzogni
					Arthur Sonzogni