mirror of
				https://github.com/ArthurSonzogni/FTXUI.git
				synced 2025-11-01 02:58:12 +08:00 
			
		
		
		
	Add focusable Renderer. (#173)
This commit is contained in:
		| @@ -12,12 +12,13 @@ example(menu2) | ||||
| example(menu_multiple) | ||||
| example(menu_style) | ||||
| example(modal_dialog) | ||||
| example(print_key_press) | ||||
| example(radiobox) | ||||
| example(radiobox_in_frame) | ||||
| example(renderer) | ||||
| example(resizable_split) | ||||
| example(slider) | ||||
| example(slider_rgb) | ||||
| example(tab_horizontal) | ||||
| example(tab_vertical) | ||||
| example(toggle) | ||||
| example(resizable_split) | ||||
| example(print_key_press) | ||||
|   | ||||
| @@ -1,11 +1,12 @@ | ||||
| #include <memory>  // for allocator, __shared_ptr_access | ||||
| #include <string>  // for operator+, char_traits, wstring | ||||
| #include <string>  // for char_traits, operator+, wstring, basic_string | ||||
|  | ||||
| #include "ftxui/component/captured_mouse.hpp"  // for ftxui | ||||
| #include "ftxui/component/component.hpp"       // for Input, Renderer, Vertical | ||||
| #include "ftxui/component/component_base.hpp"  // for ComponentBase | ||||
| #include "ftxui/component/component_options.hpp"  // for InputOption | ||||
| #include "ftxui/component/screen_interactive.hpp"  // for Component, ScreenInteractive | ||||
| #include "ftxui/dom/elements.hpp"  // for text, hbox, Element, separator, operator|, vbox, border | ||||
| #include "ftxui/dom/elements.hpp"  // for text, hbox, separator, Element, operator|, vbox, border | ||||
|  | ||||
| int main(int argc, const char* argv[]) { | ||||
|   using namespace ftxui; | ||||
| @@ -14,7 +15,6 @@ int main(int argc, const char* argv[]) { | ||||
|   std::wstring last_name; | ||||
|   std::wstring password; | ||||
|  | ||||
|  | ||||
|   Component input_first_name = Input(&first_name, "first name"); | ||||
|   Component input_last_name = Input(&last_name, "last name"); | ||||
|  | ||||
|   | ||||
							
								
								
									
										49
									
								
								examples/component/renderer.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								examples/component/renderer.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,49 @@ | ||||
| #include <memory>  // for shared_ptr, allocator, __shared_ptr_access | ||||
|  | ||||
| #include "ftxui/component/captured_mouse.hpp"  // for ftxui | ||||
| #include "ftxui/component/component.hpp"       // for Renderer, Button, Vertical | ||||
| #include "ftxui/component/component_base.hpp"  // for ComponentBase | ||||
| #include "ftxui/component/screen_interactive.hpp"  // for ScreenInteractive | ||||
| #include "ftxui/dom/elements.hpp"  // for operator|, Element, text, bold, border, center, color | ||||
| #include "ftxui/screen/color.hpp"  // for Color, Color::Red | ||||
|  | ||||
| int main(int argc, const char* argv[]) { | ||||
|   using namespace ftxui; | ||||
|   auto screen = ScreenInteractive::FitComponent(); | ||||
|  | ||||
|   // A Renderer() is a component using a lambda function as a parameter to | ||||
|   // render itself. | ||||
|  | ||||
|   // 1. Example of focusable renderer: | ||||
|   auto renderer_focusable = Renderer([](bool focused) { | ||||
|     if (focused) | ||||
|       return text(L"FOCUSABLE RENDERER()") | center | bold | border; | ||||
|     else | ||||
|       return text(L" Focusable renderer() ") | center | border; | ||||
|   }); | ||||
|  | ||||
|   // 2. Examples of a non focusable renderer. | ||||
|   auto renderer_non_focusable = Renderer([&] { | ||||
|     return text(L"~~~~~ Non Focusable renderer() ~~~~~");  // | ||||
|   }); | ||||
|  | ||||
|   // 3. Renderer can wrap other components to redefine their Render() function. | ||||
|   auto button = Button(L"Wrapped quit button", screen.ExitLoopClosure()); | ||||
|   auto renderer_wrap = Renderer(button, [&] { | ||||
|     if (button->Focused()) | ||||
|       return button->Render() | bold | color(Color::Red); | ||||
|     else | ||||
|       return button->Render(); | ||||
|   }); | ||||
|  | ||||
|   // Let's renderer everyone: | ||||
|   screen.Loop(Container::Vertical({ | ||||
|       renderer_focusable, | ||||
|       renderer_non_focusable, | ||||
|       renderer_wrap, | ||||
|   })); | ||||
| } | ||||
|  | ||||
| // Copyright 2020 Arthur Sonzogni. All rights reserved. | ||||
| // Use of this source code is governed by the MIT license that can be found in | ||||
| // the LICENSE file. | ||||
| @@ -51,6 +51,7 @@ Component ResizableSplitTop(Component main, Component back, int* main_size); | ||||
| Component ResizableSplitBottom(Component main, Component back, int* main_size); | ||||
| Component Renderer(Component child, std::function<Element()>); | ||||
| Component Renderer(std::function<Element()>); | ||||
| Component Renderer(std::function<Element(bool /* focused */)>); | ||||
| Component CatchEvent(Component child, std::function<bool(Event)>); | ||||
|  | ||||
| namespace Container { | ||||
|   | ||||
| @@ -2,12 +2,12 @@ | ||||
| #define FTXUI_SCREEN_SCREEN | ||||
|  | ||||
| #include <memory> | ||||
| #include <string> | ||||
| #include <vector> | ||||
| #include <string>  // for allocator, wstring, string, basic_string | ||||
| #include <vector>  // for vector | ||||
|  | ||||
| #include "ftxui/screen/box.hpp" | ||||
| #include "ftxui/screen/color.hpp" | ||||
| #include "ftxui/screen/terminal.hpp" | ||||
| #include "ftxui/screen/box.hpp"       // for Box | ||||
| #include "ftxui/screen/color.hpp"     // for Color, Color::Default | ||||
| #include "ftxui/screen/terminal.hpp"  // for Dimensions | ||||
|  | ||||
| namespace ftxui { | ||||
|  | ||||
|   | ||||
| @@ -53,9 +53,7 @@ class ButtonBase : public ComponentBase { | ||||
|     return false; | ||||
|   } | ||||
|  | ||||
|   bool Focusable() const final { | ||||
|     return true; | ||||
|   } | ||||
|   bool Focusable() const final { return true; } | ||||
|  | ||||
|  private: | ||||
|   ConstStringRef label_; | ||||
|   | ||||
| @@ -71,9 +71,7 @@ class CheckboxBase : public ComponentBase { | ||||
|     return false; | ||||
|   } | ||||
|  | ||||
|   bool Focusable() const final { | ||||
|     return true; | ||||
|   } | ||||
|   bool Focusable() const final { return true; } | ||||
|  | ||||
|   ConstStringRef label_; | ||||
|   bool* const state_; | ||||
|   | ||||
| @@ -56,8 +56,7 @@ class InputBase : public ComponentBase { | ||||
|     std::wstring part_at_cursor = cursor_position() < (int)content.size() | ||||
|                                       ? content.substr(cursor_position(), 1) | ||||
|                                       : L" "; | ||||
|     std::wstring part_after_cursor = | ||||
|         cursor_position() < (int)content.size() - 1 | ||||
|     std::wstring part_after_cursor = cursor_position() < (int)content.size() - 1 | ||||
|                                          ? content.substr(cursor_position() + 1) | ||||
|                                          : L""; | ||||
|     auto focused = is_focused ? focus : select; | ||||
| @@ -164,9 +163,7 @@ class InputBase : public ComponentBase { | ||||
|     return true; | ||||
|   } | ||||
|  | ||||
|   bool Focusable() const final { | ||||
|     return true; | ||||
|   } | ||||
|   bool Focusable() const final { return true; } | ||||
|  | ||||
|   StringRef content_; | ||||
|   ConstStringRef placeholder_; | ||||
|   | ||||
| @@ -4,10 +4,13 @@ | ||||
| #include <string>  // for wstring | ||||
|  | ||||
| #include "ftxui/component/captured_mouse.hpp"  // for ftxui | ||||
| #include "ftxui/component/component.hpp"          // for Input, Component | ||||
| #include "ftxui/component/component_base.hpp"     // for ComponentBase | ||||
| #include "ftxui/component/component.hpp"       // for Input | ||||
| #include "ftxui/component/component_base.hpp"  // for ComponentBase, Component | ||||
| #include "ftxui/component/component_options.hpp"  // for InputOption | ||||
| #include "ftxui/component/event.hpp"  // for Event, Event::ArrowLeft, Event::ArrowRight, Event::Backspace, Event::Delete, Event::End, Event::Home | ||||
| #include "ftxui/dom/elements.hpp"     // for Fit | ||||
| #include "ftxui/dom/node.hpp"         // for Render | ||||
| #include "ftxui/screen/screen.hpp"    // for Screen, Pixel | ||||
| #include "ftxui/util/ref.hpp"         // for Ref | ||||
| #include "gtest/gtest_pred_impl.h"    // for Test, EXPECT_EQ, TEST | ||||
|  | ||||
|   | ||||
| @@ -106,9 +106,7 @@ class MenuBase : public ComponentBase { | ||||
|     return false; | ||||
|   } | ||||
|  | ||||
|   bool Focusable() const final { | ||||
|     return entries_->size(); | ||||
|   } | ||||
|   bool Focusable() const final { return entries_->size(); } | ||||
|  | ||||
|   int& focused_entry() { return option_->focused_entry(); } | ||||
|  | ||||
|   | ||||
| @@ -119,9 +119,7 @@ class RadioboxBase : public ComponentBase { | ||||
|     return false; | ||||
|   } | ||||
|  | ||||
|   bool Focusable() const final { | ||||
|     return entries_->size(); | ||||
|   } | ||||
|   bool Focusable() const final { return entries_->size(); } | ||||
|  | ||||
|   int& focused_entry() { return option_->focused_entry(); } | ||||
|  | ||||
|   | ||||
| @@ -1,31 +1,17 @@ | ||||
| #include <functional>  // for function | ||||
| #include <memory>      // for __shared_ptr_access | ||||
| #include <memory>      // for __shared_ptr_access, shared_ptr | ||||
| #include <utility>     // for move | ||||
|  | ||||
| #include "ftxui/component/component.hpp"       // for Component, Make, Renderer | ||||
| #include "ftxui/component/component_base.hpp"  // for ComponentBase | ||||
| #include "ftxui/dom/elements.hpp"              // for Element | ||||
| #include "ftxui/component/captured_mouse.hpp"  // for CapturedMouse | ||||
| #include "ftxui/component/component.hpp"       // for Make, Renderer | ||||
| #include "ftxui/component/component_base.hpp"  // for Component, ComponentBase | ||||
| #include "ftxui/component/event.hpp"           // for Event | ||||
| #include "ftxui/component/mouse.hpp"           // for Mouse | ||||
| #include "ftxui/dom/elements.hpp"  // for Element, operator|, reflect | ||||
| #include "ftxui/screen/box.hpp"    // for Box | ||||
|  | ||||
| namespace ftxui { | ||||
|  | ||||
| // @brief A component rendering Element from a function. | ||||
| class RendererBase : public ComponentBase { | ||||
|  public: | ||||
|   // Access this interface from a Component | ||||
|   static RendererBase* From(Component component) { | ||||
|     return static_cast<RendererBase*>(component.get()); | ||||
|   } | ||||
|  | ||||
|   // Constructor. | ||||
|   RendererBase(std::function<Element()> render) : render_(std::move(render)) {} | ||||
|  | ||||
|   // Component implementation. | ||||
|   Element Render() override { return render_(); } | ||||
|  | ||||
|  protected: | ||||
|   std::function<Element()> render_; | ||||
| }; | ||||
|  | ||||
| /// @brief Return a component, using |render| to render its interface. | ||||
| /// @param render The function drawing the interface. | ||||
| /// @ingroup component | ||||
| @@ -40,7 +26,14 @@ class RendererBase : public ComponentBase { | ||||
| /// screen.Loop(renderer); | ||||
| /// ``` | ||||
| Component Renderer(std::function<Element()> render) { | ||||
|   return Make<RendererBase>(std::move(render)); | ||||
|   class Impl : public ComponentBase { | ||||
|    public: | ||||
|     Impl(std::function<Element()> render) : render_(std::move(render)) {} | ||||
|     Element Render() override { return render_(); } | ||||
|     std::function<Element()> render_; | ||||
|   }; | ||||
|  | ||||
|   return Make<Impl>(std::move(render)); | ||||
| } | ||||
|  | ||||
| /// @brief Return a new Component, similar to |child|, but using |render| as the | ||||
| @@ -69,6 +62,48 @@ Component Renderer(Component child, std::function<Element()> render) { | ||||
|   return renderer; | ||||
| } | ||||
|  | ||||
| /// @brief Return a focusable component, using |render| to render its interface. | ||||
| /// @param render The function drawing the interface, taking a boolean telling | ||||
| /// whether the component is focused or not. | ||||
| /// @ingroup component | ||||
| /// | ||||
| /// ### Example | ||||
| /// | ||||
| /// ```cpp | ||||
| /// auto screen = ScreenInteractive::TerminalOutput(); | ||||
| /// auto renderer = Renderer([] (bool focused) { | ||||
| ///   if (focused) | ||||
| ///     return text("My interface") | inverted; | ||||
| ///   else | ||||
| ///     return text("My interface") | inverted; | ||||
| /// }); | ||||
| /// screen.Loop(renderer); | ||||
| /// ``` | ||||
| Component Renderer(std::function<Element(bool)> render) { | ||||
|   class Impl : public ComponentBase { | ||||
|    public: | ||||
|     Impl(std::function<Element(bool)> render) : render_(std::move(render)) {} | ||||
|  | ||||
|    private: | ||||
|     Element Render() override { return render_(Focused()) | reflect(box_); } | ||||
|     bool Focusable() const override { return true; } | ||||
|     bool OnEvent(Event event) override { | ||||
|       if (event.is_mouse() && box_.Contain(event.mouse().x, event.mouse().y)) { | ||||
|         if (!CaptureMouse(event)) | ||||
|           return false; | ||||
|  | ||||
|         TakeFocus(); | ||||
|       } | ||||
|  | ||||
|       return false; | ||||
|     } | ||||
|     Box box_; | ||||
|  | ||||
|     std::function<Element(bool)> render_; | ||||
|   }; | ||||
|   return Make<Impl>(std::move(render)); | ||||
| } | ||||
|  | ||||
| }  // namespace ftxui | ||||
|  | ||||
| // Copyright 2021 Arthur Sonzogni. All rights reserved. | ||||
|   | ||||
| @@ -84,9 +84,7 @@ class SliderBase : public ComponentBase { | ||||
|     return false; | ||||
|   } | ||||
|  | ||||
|   bool Focusable() const final { | ||||
|     return true; | ||||
|   } | ||||
|   bool Focusable() const final { return true; } | ||||
|  | ||||
|  private: | ||||
|   StringRef label_; | ||||
|   | ||||
| @@ -1,8 +1,14 @@ | ||||
| #include <algorithm>   // for min | ||||
| #include <functional>  // for function | ||||
| #include <memory>      // for __shared_ptr_access | ||||
| #include <utility>     // for move | ||||
| #include <vector>      // for vector | ||||
|  | ||||
| #include "ftxui/dom/elements.hpp"  // for Decorator, Element, Elements, operator|, nothing | ||||
| #include "ftxui/dom/elements.hpp"  // for Element, Decorator, Elements, operator|, Fit, nothing | ||||
| #include "ftxui/dom/node.hpp"         // for Node | ||||
| #include "ftxui/dom/requirement.hpp"  // for Requirement | ||||
| #include "ftxui/screen/screen.hpp"    // for Full | ||||
| #include "ftxui/screen/terminal.hpp"  // for Dimensions | ||||
|  | ||||
| namespace ftxui { | ||||
|  | ||||
|   | ||||
| @@ -1,10 +1,11 @@ | ||||
| #include <algorithm>  // for min | ||||
| #include <algorithm>  // for max | ||||
| #include <iostream>  // for operator<<, basic_ostream, wstringstream, stringstream, flush, cout, ostream | ||||
| #include <memory>    // for allocator | ||||
| #include <sstream>   // IWYU pragma: keep | ||||
|  | ||||
| #include "ftxui/screen/screen.hpp" | ||||
| #include "ftxui/screen/string.hpp"    // for to_string, wchar_width | ||||
| #include "ftxui/screen/terminal.hpp"  // for Terminal::Dimensions, Terminal | ||||
| #include "ftxui/screen/terminal.hpp"  // for Dimensions, Size | ||||
|  | ||||
| #if defined(_WIN32) | ||||
| #define WIN32_LEAN_AND_MEAN | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Arthur Sonzogni
					Arthur Sonzogni