diff --git a/CMakeLists.txt b/CMakeLists.txt index 27ff319..2708ac0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,15 @@ cmake_minimum_required(VERSION 3.0) + +execute_process( + COMMAND git rev-list --count HEAD + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} + OUTPUT_VARIABLE git_version + OUTPUT_STRIP_TRAILING_WHITESPACE +) + project(ftxui LANGUAGES CXX - VERSION 0.1 + VERSION 0.1.${git_version} ) option(FTXUI_BUILD_EXAMPLES "Set to ON to build examples" ON) diff --git a/doc/Doxyfile.in b/doc/Doxyfile.in index 162317d..9b334e0 100644 --- a/doc/Doxyfile.in +++ b/doc/Doxyfile.in @@ -38,7 +38,7 @@ PROJECT_NAME = "FTXUI" # could be handy for archiving the generated documentation or if some version # control system is used. -PROJECT_NUMBER = 1.0 +PROJECT_NUMBER = @CMAKE_PROJECT_VERSION@ # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a @@ -51,7 +51,7 @@ PROJECT_BRIEF = "C++ functionnal terminal UI." # pixels and the maximum width should not exceed 200 pixels. Doxygen will copy # the logo to the output directory. -PROJECT_LOGO = +#PROJECT_LOGO = ./logo.png # The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path # into which the generated documentation will be written. If a relative path is @@ -440,19 +440,19 @@ EXTRACT_ALL = YES # be included in the documentation. # The default value is: NO. -EXTRACT_PRIVATE = YES +EXTRACT_PRIVATE = NO # If the EXTRACT_PACKAGE tag is set to YES, all members with package or internal # scope will be included in the documentation. # The default value is: NO. -EXTRACT_PACKAGE = YES +EXTRACT_PACKAGE = NO # If the EXTRACT_STATIC tag is set to YES, all static members of a file will be # included in the documentation. # The default value is: NO. -EXTRACT_STATIC = YES +EXTRACT_STATIC = NO # If the EXTRACT_LOCAL_CLASSES tag is set to YES, classes (and structs) defined # locally in source files will be included in the documentation. If set to NO, @@ -460,7 +460,7 @@ EXTRACT_STATIC = YES # for Java sources. # The default value is: YES. -EXTRACT_LOCAL_CLASSES = YES +EXTRACT_LOCAL_CLASSES = NO # This flag is only useful for Objective-C code. If set to YES, local methods, # which are defined in the implementation section but not in the interface are @@ -468,7 +468,7 @@ EXTRACT_LOCAL_CLASSES = YES # included. # The default value is: NO. -EXTRACT_LOCAL_METHODS = YES +EXTRACT_LOCAL_METHODS = NO # If this flag is set to YES, the members of anonymous namespaces will be # extracted and appear in the documentation as a namespace called @@ -477,7 +477,7 @@ EXTRACT_LOCAL_METHODS = YES # are hidden. # The default value is: NO. -EXTRACT_ANON_NSPACES = YES +EXTRACT_ANON_NSPACES = NO # If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all # undocumented members inside documented classes or files. If set to NO these @@ -702,7 +702,7 @@ FILE_VERSION_FILTER = # DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE # tag is left empty. -#LAYOUT_FILE = @CMAKE_CURRENT_SOURCE_DIR@/DoxygenLayout.xml +LAYOUT_FILE = @CMAKE_CURRENT_SOURCE_DIR@/doxygen_layout.xml # The CITE_BIB_FILES tag can be used to specify one or more bib files containing # the reference definitions. This must be a list of .bib files. The .bib @@ -891,7 +891,8 @@ EXCLUDE_SYMLINKS = NO # Note that the wildcards are matched against the file with absolute path, so to # exclude all test directories for example use the pattern */test/* -EXCLUDE_PATTERNS = +EXCLUDE_PATTERNS += *test.cpp +EXCLUDE_PATTERNS += *take_any_args.hpp # The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names # (namespaces, classes, functions, etc.) that should be excluded from the @@ -1164,7 +1165,7 @@ HTML_FILE_EXTENSION = .html # of the possible markers and block names see the documentation. # This tag requires that the tag GENERATE_HTML is set to YES. -#HTML_HEADER = @CMAKE_CURRENT_SOURCE_DIR@/header.html +HTML_HEADER = @CMAKE_CURRENT_SOURCE_DIR@/doxygen_header.html # The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each # generated HTML page. If the tag is left blank doxygen will generate a standard @@ -1174,7 +1175,7 @@ HTML_FILE_EXTENSION = .html # that doxygen normally uses. # This tag requires that the tag GENERATE_HTML is set to YES. -#HTML_FOOTER = @CMAKE_CURRENT_SOURCE_DIR@/footer.html +HTML_FOOTER = @CMAKE_CURRENT_SOURCE_DIR@/doxygen_footer.html # The HTML_STYLESHEET tag can be used to specify a user-defined cascading style # sheet that is used by each HTML page. It can be used to fine-tune the look of @@ -1199,7 +1200,7 @@ HTML_STYLESHEET = # list). For an example see the documentation. # This tag requires that the tag GENERATE_HTML is set to YES. -#HTML_EXTRA_STYLESHEET = @CMAKE_CURRENT_SOURCE_DIR@/doxygen_style.css +HTML_EXTRA_STYLESHEET = @CMAKE_CURRENT_SOURCE_DIR@/doxygen_extra.css # The HTML_EXTRA_FILES tag can be used to specify one or more extra images or # other source files which should be copied to the HTML output directory. Note @@ -2339,7 +2340,7 @@ INCLUDED_BY_GRAPH = YES # The default value is: NO. # This tag requires that the tag HAVE_DOT is set to YES. -CALL_GRAPH = YES +CALL_GRAPH = NO # If the CALLER_GRAPH tag is set to YES then doxygen will generate a caller # dependency graph for every global function or class method. @@ -2351,7 +2352,7 @@ CALL_GRAPH = YES # The default value is: NO. # This tag requires that the tag HAVE_DOT is set to YES. -CALLER_GRAPH = YES +CALLER_GRAPH = NO # If the GRAPHICAL_HIERARCHY tag is set to YES then doxygen will graphical # hierarchy of all classes instead of a textual one. diff --git a/doc/build-with-cmake.md b/doc/build-with-cmake.md deleted file mode 100644 index 5c83fa7..0000000 --- a/doc/build-with-cmake.md +++ /dev/null @@ -1,52 +0,0 @@ -# Build ftxui and install - -~~~bash -mkdir build && cd build -cmake .. -make -sudo make install -~~~ - -# Example project - -main.cpp -~~~cpp -#include "ftxui/screen/screen.hpp" -#include "ftxui/dom/elements.hpp" -#include - -int main(int argc, const char *argv[]) { - using namespace ftxui; - auto document = - hbox({ - text(L"left") | bold | border, - text(L"middle") | flex | border, - text(L"right") | border, - }); - auto screen = Screen::Create(Dimension::Full(), Dimension::Fit(document)); - Render(screen, document); - - std::cout << screen.ToString(); - - return 0; -} -~~~ - -# Add dependency - -CMakeLists.txt -~~~cmake -cmake_minimum_required(VERSION 3.0) - -find_package(ftxui REQUIRED) -add_executable(main main.cpp) -target_link_libraries(main PUBLIC ftxui::dom) -~~~ - -# Build -~~~ -mkdir build && cd build -cmake .. -make -./main -~~~ diff --git a/doc/build-with-nxxm.md b/doc/build-with-nxxm.md deleted file mode 100644 index b3f8644..0000000 --- a/doc/build-with-nxxm.md +++ /dev/null @@ -1,39 +0,0 @@ -# Add dependency - -.nxxm/deps -~~~json -{ - "ArthurSonzogni/FTXUI": {} -} -~~~ - -# Example project - -main.cpp -~~~cpp -#include "ftxui/screen/screen.hpp" -#include "ftxui/dom/elements.hpp" -#include - -int main(int argc, const char *argv[]) { - using namespace ftxui; - auto document = - hbox({ - text(L"left") | bold | border, - text(L"middle") | flex | border, - text(L"right") | border, - }); - auto screen = Screen::Create(Dimension::Full(), Dimension::Fit(document)); - Render(screen, document); - - std::cout << screen.ToString(); - - return 0; -} -~~~ - -# Build - -~~~ -nxxm . -t clang-cxx17 -~~~ diff --git a/doc/doxygen_extra.css b/doc/doxygen_extra.css new file mode 100755 index 0000000..e990cfa --- /dev/null +++ b/doc/doxygen_extra.css @@ -0,0 +1,335 @@ +/* + * GitHub Markdown style CSS for doxygen 1.8.14 + * Source: https://github.com/sindresorhus/github-markdown-css + * License: MIT � Sindre Sorhus + */ + +* { + box-sizing: border-box; +} + +body, table, div, p, dl { + -ms-text-size-adjust: 100%; + -webkit-text-size-adjust: 100%; + line-height: 1.5; + color: #24292e; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif; + font-size: 16px; + word-wrap: break-word; +} + +b { + font-weight: 600; +} + +/* @group Heading Levels */ + +h1, h2, h3, h4, h5, h6 { + font-weight: 600; + line-height: 1.25; + margin-top: 24px; + margin-bottom: 16px; +} + +h1 { + font-size: 2em; + padding-bottom: 0.3em; + border-bottom: 1px solid #eaecef; +} + +h2 { + padding-bottom: 0.3em; + font-size: 1.5em; + border-bottom: 1px solid #eaecef; +} + +h3 { + font-size: 1.25em; +} + +h4 { + font-size: 1em; +} + +h5 { + font-size: 0.875em; +} + +h6 { + font-size: 0.85em; + color: #6a737d; +} + +a { + background-color: transparent; + color: #0366d6; + text-decoration: none; + font-weight: normal; +} + +.contents a:visited { + color: #0366d6; +} + +a:active, a:hover { + outline-width: 0; +} + +a:hover { + text-decoration: underline; +} + +a:not([href]) { + color: inherit; + text-decoration: none; +} + +a.el { + font-weight: normal; +} + +.image { + text-align: left; +} + +.tip { + background-image: url(tip.png); + background-position: left center; + background-repeat: no-repeat; + padding-left: 30px; + margin-top: 1em; + margin-bottom: 1em; + min-height: 31px; + display: block; + font-style:italic; +} + +.warn { + background-image: url(warn.png); + background-position: left center; + background-repeat: no-repeat; + padding-left: 48px; + margin-top: 1em; + margin-bottom: 1em; + min-height: 31px; + display: block; + font-style:italic; +} + +#projectname +{ + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif; + font-size: 2em; + font-weight: bold; +} + +#projectbrief +{ + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif; + font-size: 0.8em; +} + +#projectnumber +{ + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif; + font-size: 1em; +} + +div.contents { + width: 980px; + padding: 40px; + margin-top: -1px; + margin-left: auto; + margin-right: auto; + margin-bottom: 10px; + border: 1px solid #d1d5da; + border-radius: 2px; +} + +div.toc { + border: 0 none; + border-radius: 7px; +} + +div.header +{ + width: 980px; + padding: 10px; + margin-top: 10px; + margin-left: auto; + margin-right: auto; + background-image: none; + background-repeat: none; + background-color: #f6f8fa; + border: 1px solid #d1d5da; +} + +div.headertitle +{ + padding: 0; +} + +.title ol { + margin: 0; +} + +.title ol li { + list-style-type: none; +} + +.ui-resizable-e { + background: none; + background-color: #E6E6E6; +} + +div.fragment { + padding: 16px; + background-color: #f3f3f3; + border: 0 solid; + transition: all 0.5s ease-in-out; + border-radius:5px; +} + +div.fragment:hover { + background-color: #e9e9e9; + box-shadow: 0 5px 10px -5px rgb(0,0,0,0.5) inset; +} + +div.line { + font-family: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, Courier, monospace; + font-size: 85%; + line-height: 1.45; + -webkit-transition-duration: 0; + -moz-transition-duration: 0; + -ms-transition-duration: 0; + -o-transition-duration: 0; + transition-duration: 0; +} + +div.line.glow { + background-color: auto; + box-shadow: none; +} + +pre.fragment { + border: 0 solid #C4CFE5; + padding: 16px; + background-color: #f3f3f3; + font-size: 85%; + line-height: 1.45; + font-family: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, Courier, monospace; +} + +/* @group Code Colorization */ +span.keyword { + color: #808000 +} + +span.keywordtype { + color: #808000 +} + +span.keywordflow { + color: #808000 +} + +span.comment { + color: #008000 +} + +span.preprocessor { + color: #800000 +} + +span.stringliteral { + color: #000080 +} + +span.charliteral { + color: #000080 +} + +blockquote { + background-color: #EEEEEE; + border-left: 2px solid #606060; + margin: 0 24px 0 4px; + padding: 0 12px 0 16px; +} + +/* @end */ + +.arrow { + box-sizing: content-box; +} + +img { + max-width: 100%; + max-height: 100%; +} + +#nav-tree { + background-image: none; + background-color: white; +} + +#nav-tree .label { + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif; + font-size: 14px; +} + +#side-nav { + width: 25%; + max-width: 50%; +} + +.memtitle { + background-image: none; +} + +.memproto { + text-shadow: none; + /* opera specific markup */ + box-shadow: none; + /* firefox specific markup */ + -moz-box-shadow: none; + -moz-border-radius-topright: 4px; + /* webkit specific markup */ + -webkit-box-shadow: none; + -webkit-border-top-right-radius: 4px; +} + +.memdoc { + background-image:none; + background-repeat:repeat-x; + background-color: #FFFFFF; + /* opera specific markup */ + box-shadow: none; + /* firefox specific markup */ + -moz-box-shadow: none; + /* webkit specific markup */ + -webkit-box-shadow: none; +} + +#main-menu { + background: none; + border-bottom: 1px solid black; +} + +#main-menu li { + border: none !important; + transition: all 0.1s ease-in-out; +} + +#main-menu li:hover { + color:black; + background-color:black; +} + +.sm-dox a, .sm-dox a:focus, .sm-dox a:active, .sm-dox a:hover, .sm-dox a.highlighted { + background-image:none; +} + +#titlearea { + margin: 8px; + border: none; +} diff --git a/doc/doxygen_footer.html b/doc/doxygen_footer.html new file mode 100644 index 0000000..0bc90f7 --- /dev/null +++ b/doc/doxygen_footer.html @@ -0,0 +1,10 @@ + + + + + + + + + diff --git a/doc/doxygen_header.html b/doc/doxygen_header.html new file mode 100644 index 0000000..48a2e36 --- /dev/null +++ b/doc/doxygen_header.html @@ -0,0 +1,59 @@ + + + + + + + + + +$projectname: $title +$title + + + +$treeview +$search +$mathjax + +$extrastylesheet + + +
+ + +
+ + + + + + + + + + + + + + + + + + + + + +
+
$projectname +  $projectnumber +
+
$projectbrief
+
+
$projectbrief
+
$searchbox
+
+ + + + diff --git a/doc/doxygen_layout.xml b/doc/doxygen_layout.xml new file mode 100644 index 0000000..dcae4cf --- /dev/null +++ b/doc/doxygen_layout.xml @@ -0,0 +1,194 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/doc/example_list.h b/doc/example_list.h new file mode 100644 index 0000000..834ea10 --- /dev/null +++ b/doc/example_list.h @@ -0,0 +1,34 @@ +/// @example ./examples/util/print_key_press.cpp +/// @example ./examples/dom/dbox.cpp +/// @example ./examples/dom/separator.cpp +/// @example ./examples/dom/style_color.cpp +/// @example ./examples/dom/paragraph.cpp +/// @example ./examples/dom/style_blink.cpp +/// @example ./examples/dom/style_dim.cpp +/// @example ./examples/dom/style_inverted.cpp +/// @example ./examples/dom/graph.cpp +/// @example ./examples/dom/package_manager.cpp +/// @example ./examples/dom/window.cpp +/// @example ./examples/dom/html_like.cpp +/// @example ./examples/dom/border.cpp +/// @example ./examples/dom/style_underlined.cpp +/// @example ./examples/dom/gauge.cpp +/// @example ./examples/dom/style_bold.cpp +/// @example ./examples/dom/spinner.cpp +/// @example ./examples/dom/style_gallery.cpp +/// @example ./examples/dom/vbox_hbox.cpp +/// @example ./examples/dom/size.cpp +/// @example ./examples/dom/hflow.cpp +/// @example ./examples/component/tab_vertical.cpp +/// @example ./examples/component/gallery.cpp +/// @example ./examples/component/checkbox.cpp +/// @example ./examples/component/checkbox_in_frame.cpp +/// @example ./examples/component/menu2.cpp +/// @example ./examples/component/tab_horizontal.cpp +/// @example ./examples/component/input.cpp +/// @example ./examples/component/homescreen.cpp +/// @example ./examples/component/radiobox.cpp +/// @example ./examples/component/menu.cpp +/// @example ./examples/component/menu_style.cpp +/// @example ./examples/component/radiobox_in_frame.cpp +/// @example ./examples/component/toggle.cpp diff --git a/doc/example_list.md b/doc/example_list.md deleted file mode 100644 index 483fa6b..0000000 --- a/doc/example_list.md +++ /dev/null @@ -1,35 +0,0 @@ -# Examples -@example ./examples/util/print_key_press.cpp -@example ./examples/dom/dbox.cpp -@example ./examples/dom/separator.cpp -@example ./examples/dom/style_color.cpp -@example ./examples/dom/paragraph.cpp -@example ./examples/dom/style_blink.cpp -@example ./examples/dom/style_dim.cpp -@example ./examples/dom/style_inverted.cpp -@example ./examples/dom/graph.cpp -@example ./examples/dom/package_manager.cpp -@example ./examples/dom/window.cpp -@example ./examples/dom/html_like.cpp -@example ./examples/dom/border.cpp -@example ./examples/dom/style_underlined.cpp -@example ./examples/dom/gauge.cpp -@example ./examples/dom/style_bold.cpp -@example ./examples/dom/spinner.cpp -@example ./examples/dom/style_gallery.cpp -@example ./examples/dom/vbox_hbox.cpp -@example ./examples/dom/size.cpp -@example ./examples/dom/hflow.cpp -@example ./examples/component/tab_vertical.cpp -@example ./examples/component/gallery.cpp -@example ./examples/component/checkbox.cpp -@example ./examples/component/checkbox_in_frame.cpp -@example ./examples/component/menu2.cpp -@example ./examples/component/tab_horizontal.cpp -@example ./examples/component/input.cpp -@example ./examples/component/homescreen.cpp -@example ./examples/component/radiobox.cpp -@example ./examples/component/menu.cpp -@example ./examples/component/menu_style.cpp -@example ./examples/component/radiobox_in_frame.cpp -@example ./examples/component/toggle.cpp diff --git a/doc/logo.png b/doc/logo.png deleted file mode 100644 index f3fd8b3..0000000 Binary files a/doc/logo.png and /dev/null differ diff --git a/doc/mainpage.md b/doc/mainpage.md index 77d91cf..74cba30 100644 --- a/doc/mainpage.md +++ b/doc/mainpage.md @@ -26,7 +26,10 @@ int main(void) { text(L"right") | border, }); - auto screen = Screen::Create(Dimension::Full(), Dimension::Fit(document)); + auto screen = Screen::Create( + Dimension::Full(), // Width + Dimension::Fit(document) // Height + ); Render(screen, document); std::cout << screen.ToString() << std::endl; @@ -42,7 +45,7 @@ int main(void) { ``` **cmake** -```cpp +``` cmake_minimum_required (VERSION 3.11) include(FetchContent) @@ -64,20 +67,17 @@ target_link_libraries(main set_target_properties(main PROPERTIES CXX_STANDARD 17) ``` -# Modules +# List of modules. The project is split into 3 modules: -1. ftxui/screen -2. ftxui/dom -3. ftxui/component -ftxui/screen defines a ftxui::Screen, this is a grid of ftxui::Pixel. +1. **ftxui/screen** defines a ftxui::Screen, this is a grid of ftxui::Pixel. -ftxui/dom is the main module. It defines a hierarchical set of ftxui::Element. +2. **ftxui/dom** is the main module. It defines a hierarchical set of ftxui::Element. An element draws something on the ftxui::Screen. It is responsive to the size of its container. -ftxui/component. The part is only needed if you need to respond to the User +3. **ftxui/component** The part is only needed if you need to respond to the User input. It defines a set of ftxui::Component. The use can navigates using the arrow keys and interact with widgets like checkbox/inputbox/... You can make you own components. @@ -85,19 +85,20 @@ own components. ## screen It defines a ftxui::Screen. This is a grid of ftxui::Pixel. A Pixel represent a -unicode character and its style. The screen can be printed as a string using ftxui::Screen::ToString(). +unicode character and its associated style (bold, colors, etc...). +The screen can be printed as a string using ftxui::Screen::ToString(). -Example: ~~~cpp #include int main(void) { using namespace ftxui; - auto screen = ftxui::Screen(Dimension::Fixed(32), Dimension::Fixed(10)); + auto screen = Screen(Dimension::Fixed(32), Dimension::Fixed(10)); auto& pixel = screen.PixelAt(10,10); pixel.character = U'A'; pixel.bold = true; + pixel.foreground_color = Color::Blue; std::cout << screen.ToString(); return EXIT_SUCCESS; @@ -108,11 +109,45 @@ Example: This module defines a hierachical set of Element. An element manages layout and can be responsive to the terminal dimensions. -They are declared in ftxui/dom/elements.hpp> + +**Example:** +```cpp +// Define the document +Element document = vbox({ + text(L"The window") | bold | color(Color::Blue), + gauge(0.5) + text(L"The footer") + }); + +// Add a border. +document = border(document); +``` + +**List of elements** + +You only need one header: ftxui/dom/elements.hpp \include ftxui/dom/elements.hpp -### text +## component + +Finally, the ftxui/component directory defines the logic to get interactivity. + +Please take a look at ./examples/component + +This provides: +1. A main loop. +2. Get events and respond to them. +3. A predefined implementation of "keyboard navigation". +4. A set of predefined widget: CheckBox, RadioBox, Input, Menu, Toggle. + +# ftxui/dom + +Every elements of the dom are declared from: + +\include ftxui/dom/elements.hpp + +## text The most simple widget. It displays a text. ~~~cpp @@ -124,7 +159,7 @@ text(L"I am a piece of text"); I am a piece of text. ~~~ -### border +## border Add a border around an element ~~~cpp @@ -139,7 +174,23 @@ border(text(L"The element")) └───────────┘ ~~~ -### separator +## window + +A ftxui::window is a ftxui::border, but with some text on top of the border. +Add a border around an element +~~~cpp +using namespace ftxui; + +window(L"The window", text(L"The element")) +~~~ + +~~~bash +┌The window─┐ +│The element│ +└───────────┘ +~~~ + +## separator Display a vertical or horizontal line to visually split the content of a container in two. @@ -160,7 +211,7 @@ border( └────┴─────┘ ~~~ -### gauge +## gauge A gauge. It can be used to represent a progress bar. ~~~cpp @@ -173,11 +224,54 @@ border(gauge(0.5)) └────────────────────────────────────────────────────────────────────────────┘ ~~~ -### graph -[![asciicast](https://asciinema.org/a/223726.svg)](https://asciinema.org/a/223726) +## graph +@htmlonly + +@endhtmlonly +## Colors +A terminal console can usually display colored text and colored background. -### Style +~~~cpp +Decorator color(Color); +Decorator bgcolor(Color); +~~~ + +The following colors are available: +- Default + +- Black +- GrayDark +- GrayLight + +- White + +- Blue +- BlueLight + +- Cyan +- CyanLight + +- Green +- GreenLight + +- Magenta +- MagentaLight + +- Red +- RedLight + +- Yellow +- YellowLight + +Example: +```cpp +text(L"Blue foreground") | color(Color::Blue); +text(L"Blue backgrond") | bgcolor(Color::Blue); +text(L"Black on white") | color(Color::Black) | bgcolor(Color::White); +``` + +## Style A terminal console can usually display colored text and colored background. The text can also have different effects: bold, dim, underlined, inverted, blink. @@ -202,7 +296,7 @@ Tips: The pipe operator can be used to chain Decorator: text(L"This text is bold")) | bold | underlined ~~~ -### Layout +## Layout These layout are similar to the HTML flexbox: * vbox (Vertical-box) @@ -246,23 +340,125 @@ An horizontal flow layout is implemented by: └────┘└───────────────────────────────────┘└───────────────────────────────────┘ ~~~ -## Components. +# ftxui/component Element are stateless object. On the other side, components are used when an internal state is needed. Components are used to interact with the user with its keyboard. They handle keyboard navigation, including component focus. -### Input -[![asciicast](https://asciinema.org/a/223719.svg)](https://asciinema.org/a/223719) +## Input -### Menu -[![asciicast](https://asciinema.org/a/223720.svg)](https://asciinema.org/a/223720) +@htmlonly + +@endhtmlonly -### Toggle. -[![asciicast](https://asciinema.org/a/223722.svg)](https://asciinema.org/a/223722) +## Menu +@htmlonly + +@endhtmlonly -### CheckBox -[![asciicast](https://asciinema.org/a/223724.svg)](https://asciinema.org/a/223724) +## Toggle. +@htmlonly + +@endhtmlonly -### RadioBox -[![asciicast](https://asciinema.org/a/223725.svg)](https://asciinema.org/a/223725) +## CheckBox +@htmlonly + +@endhtmlonly + +## RadioBox +@htmlonly + +@endhtmlonly + +# Build + +Assuming this example example.cpp file. + +**main.cpp** +~~~cpp +#include "ftxui/screen/screen.hpp" +#include "ftxui/dom/elements.hpp" +#include + +int main(int argc, const char *argv[]) { + using namespace ftxui; + auto document = + hbox({ + text(L"left") | bold | border, + text(L"middle") | flex | border, + text(L"right") | border, + }); + auto screen = Screen::Create(Dimension::Full(), Dimension::Fit(document)); + Render(screen, document); + + std::cout << screen.ToString(); + + return 0; +} +~~~ + +## Using CMake + +CMakeLists.txt +~~~cmake +cmake_minimum_required (VERSION 3.11) + +# --- Fetch FTXUI -------------------------------------------------------------- +include(FetchContent) + +set(FETCHCONTENT_UPDATES_DISCONNECTED TRUE) +FetchContent_Declare(ftxui + GIT_REPOSITORY https://github.com/ArthurSonzogni/ftxui + # Specify a GIT TAG here. +) + +FetchContent_GetProperties(ftxui) +if(NOT ftxui_POPULATED) + FetchContent_Populate(ftxui) + add_subdirectory(${ftxui_SOURCE_DIR} ${ftxui_BINARY_DIR} EXCLUDE_FROM_ALL) +endif() + +# ------------------------------------------------------------------------------ + +project(ftxui-starter + LANGUAGES CXX + VERSION 1.0.0 +) + +add_executable(ftxui-starter src/main.cpp) +target_include_directories(ftxui-starter PRIVATE src) + +target_link_libraries(ftxui-starter + PRIVATE ftxui::screen + PRIVATE ftxui::dom + PRIVATE ftxui::component # Not needed for this example. +) + +# C++17 is used. We requires fold expressions at least. +set_target_properties(ftxui-starter PROPERTIES CXX_STANDARD 17) + +~~~ + +Build +~~~ +mkdir build && cd build +cmake .. +make +./main +~~~ + +## Using NXXM + +**.nxxm/deps** +~~~json +{ + "ArthurSonzogni/FTXUI": {} +} +~~~ + +Build: +~~~ +nxxm . -t clang-cxx17 +~~~ diff --git a/doc/tutorial.md b/doc/tutorial.md deleted file mode 100644 index 12dfe63..0000000 --- a/doc/tutorial.md +++ /dev/null @@ -1,289 +0,0 @@ -## Introduction - -The library is split in 3 parts: - -1. ftxui/screen/ -2. ftxui/dom/ -3. ftxui/component/ - -# ftxui/screen/ - -It defines a ftxui::Screen. This is a grid of ftxui::Pixel. A Pixel represent a -unicode character and its style. The screen can be printed as a string using ftxui::Screen::ToString(). - -Example: -~~~cpp - #include - - int main(void) { - using namespace ftxui; - auto screen = ftxui::Screen(Dimension::Fixed(32), Dimension::Fixed(10)); - - auto& pixel = screen.PixelAt(10,10); - pixel.character = U'A'; - pixel.bold = true; - - std::cout << screen.ToString(); - return EXIT_SUCCESS; - } -~~~ - - -2. [ftuix/dom/](../include/ftxui/dom/) - These are a set of hierachical ftxui::Element declared in - [ftxui/dom/elements.hpp](../ftxui/dom/elements.hpp). An element can render - itself on the the Screen. It manage layout and is responsive to the Screen - dimensions. - -3. [ftuix/component/](../include/ftxui/component) - The part is only needed if you need to respond to the User input. It defines a - set of ftxui::Component. The use can navigates using the arrow keys and - interact with widgets like checkbox/inputbox/... You can make you own - components. - -~~~cpp - using namespace ftxui; - - auto document = text(L"Hello world"); - - auto screen = Screen::Create(Dimension::Fit(document)); - Render(screen, document); - - std::cout << screen.ToString(); -~~~ - - -I recommand not to take too much time reading the tutorial. Instead, -you should try to read the examples (in [../examples/](../examples)). - -## DOM -All the dom element are declared in one header: - -\include ./ftxui/dom/elements.hpp - -It declares the following set of elements: - -~~~cpp -// --- Widget --- -Element text(std::wstring text); -Element separator(); -Element separator(Pixel); -Element gauge(float ratio); -Element border(Element); -Decorator borderWith(Pixel); -Element window(Element title, Element content); -Element spinner(int charset_index, size_t image_index); -Elements paragraph(std::wstring text); // Use inside hflow(). Split by space. -Element graph(GraphFunction); - -// -- Decorator --- -Element bold(Element); -Element dim(Element); -Element inverted(Element); -Element underlined(Element); -Element blink(Element); -Decorator color(Color); -Decorator bgcolor(Color); -Element color(Color, Element); -Element bgcolor(Color, Element); - -// --- Layout --- -// Horizontal, Vertical or stacked set of elements. -Element hbox(Elements); -Element vbox(Elements); -Element dbox(Elements); -Element hflow(Elements); - -// -- Flexibility --- -// Define how to share the remaining space when not all of it is used inside a -// container. -Element filler(); -Element flex(Element); -Element notflex(Element); - -// -- Size override; -enum Direction { WIDTH, HEIGHT }; -enum Constraint { LESS_THAN, EQUAL, GREATER_THAN }; -Decorator size(Direction, Constraint, int value); - -// --- Frame --- -// A frame is a scrollable area. The internal area is potentially larger than -// the external one. The internal area is scrolled in order to make visible the -// focused element. -Element frame(Element); -Element focus(Element); -Element select(Element); - -// --- Util -------------------------------------------------------------------- -Element hcenter(Element); -Element vcenter(Element); -Element center(Element); -Element align_right(Element); -Element nothing(Element element); -~~~ - -### Widget. - -#### text - -The most simple widget. It displays a text. -~~~cpp -using namespace ftxui; - -text(L"I am a piece of text"); -~~~ -~~~bash -I am a piece of text. -~~~ - -#### border -Add a border around an element -~~~cpp -using namespace ftxui; - -border(text(L"The element")) -~~~ - -~~~bash -┌───────────┐ -│The element│ -└───────────┘ -~~~ - -#### separator - -Display a vertical or horizontal line to visually split the content of a -container in two. - -~~~cpp -border( - hbox({ - vbox({ - text(L"left top"), - text(L"left bottom"), - }), - separator(), - vbox({ - text(L"right top"), - text(L"right bottom"), - }), - }) -); -~~~ - -~~~bash -┌───────────┬────────────┐ -│left top │right top │ -│left bottom│right bottom│ -└───────────┴────────────┘ -~~~ - -#### gauge - -A gauge. It can be used to represent a progress bar. -~~~cpp -border(gauge(0.5)) -~~~ - -~~~bash -┌────────────────────────────────────────────────────────────────────────────┐ -│██████████████████████████████████████ │ -└────────────────────────────────────────────────────────────────────────────┘ -~~~ - -#### graph -[![asciicast](https://asciinema.org/a/223726.svg)](https://asciinema.org/a/223726) - - -### Style -A terminal console can usually display colored text and colored background. -The text can also have different effects: bold, dim, underlined, inverted, -blink. - -~~~cpp -Element bold(Element); -Element dim(Element); -Element inverted(Element); -Element underlined(Element); -Element blink(Element); -Decorator color(Color); -Decorator bgcolor(Color); -~~~ - -Example: -~~~cpp -underlined(bold(text(L"This text is bold and underlined"))) -~~~ - -Tips: The pipe operator can be used to chain Decorator: -~~~cpp -text(L"This text is bold")) | bold | underlined -~~~ - -### Layout - -These layout are similar to the HTML flexbox: -* vbox (Vertical-box) -* hbox (Horizontal-box) -* dbox (Z-axis-box) -They are used to compose all the elements together. Each -children are put side by side. If the container is flexible, the extra space -available will be shared among the remaining flexible children. - -flex(element) can be used to make a non-flexible element flexible. filler() is a -flexible empty element. You can use it align children on one side of the -container. - -An horizontal flow layout is implemented by: -* hflow (Horizontal flow) - -#### Examples -~~~cpp - hbox({ - text(L"left") | border , - text(L"middle") | border | flex, - text(L"right") | border, - }); -~~~ -~~~bash -┌────┐┌─────────────────────────────────────────────────────────────────┐┌─────┐ -│left││middle ││right│ -└────┘└─────────────────────────────────────────────────────────────────┘└─────┘ -~~~ - -~~~cpp - hbox({ - text(L"left") | border , - text(L"middle") | border | flex, - text(L"right") | border | flex, - }); -~~~ -~~~bash -┌────┐┌───────────────────────────────────┐┌───────────────────────────────────┐ -│left││middle ││right │ -└────┘└───────────────────────────────────┘└───────────────────────────────────┘ -~~~ - - - -## Components. - -Element are stateless object. On the other side, components are used when an -internal state is needed. Components are used to interact with the user with -its keyboard. They handle keyboard navigation, including component focus. - -### Input -[![asciicast](https://asciinema.org/a/223719.svg)](https://asciinema.org/a/223719) -![asciicast](https://asciinema.org/a/223719.svg) - -### Menu -[![asciicast](https://asciinema.org/a/223720.svg)](https://asciinema.org/a/223720) - -### Toggle. -[![asciicast](https://asciinema.org/a/223722.svg)](https://asciinema.org/a/223722) - -### CheckBox -[![asciicast](https://asciinema.org/a/223724.svg)](https://asciinema.org/a/223724) - -### RadioBox -[![asciicast](https://asciinema.org/a/223725.svg)](https://asciinema.org/a/223725) diff --git a/include/ftxui/README.md b/include/ftxui/README.md deleted file mode 100644 index aa57409..0000000 --- a/include/ftxui/README.md +++ /dev/null @@ -1,30 +0,0 @@ -# Level of abstractions: -* Level 0: terminal output. -* Level 1: ftxui::Screen -* Level 2: ftxui::Node -* Level 3: ftxui::Component - -## Level 0: terminal output. - This is std::cout. You can send text to it. - -## Level 1: ftxui::Screen - A rectangular grid of characters. - Use Terminal::ToString() to append its content to the console (level 0). - -## Level 2: ftxui::Node - A hierarchial set of element. - They handle layout and render themself on the screen (level 1) - See [elements.hpp](./dom/elements.hpp) - - You can make implement your own. - -## Level 3: ftxui::Component - A hierarchical set of components. - Components store some state and react to events: - * keyboard - * mouse - * terminal event - - Components renders themself by producing ftxui::Node (Level 2) - - Implement your own! diff --git a/include/ftxui/screen/string.hpp b/include/ftxui/screen/string.hpp index b904f41..e6e5da9 100644 --- a/include/ftxui/screen/string.hpp +++ b/include/ftxui/screen/string.hpp @@ -7,6 +7,7 @@ #include +namespace ftxui { std::string to_string(const std::wstring& s); std::wstring to_wstring(const std::string& s); @@ -19,5 +20,6 @@ int wchar_width(wchar_t); int wchar_width_cjk(wchar_t); int wstring_width(const std::wstring&); int wstring_width_cjk(const std::wstring&); +} // namespace ftxui #endif /* end of include guard: FTXUI_SCREEN_STRING_HPP */ diff --git a/src/ftxui/component/event.cpp b/src/ftxui/component/event.cpp index 04d1a5e..cff815e 100644 --- a/src/ftxui/component/event.cpp +++ b/src/ftxui/component/event.cpp @@ -10,35 +10,7 @@ namespace ftxui { -// static -Event Event::Character(const std::string& input) { - Event event; - event.input_ = input; - event.is_character_ = true; - event.character_ = to_wstring(input)[0]; - return event; -} - -// static -Event Event::Character(char c) { - return Character(wchar_t(c)); -} - -// static -Event Event::Character(wchar_t c) { - Event event; - event.input_ = {(char)c}; - event.is_character_ = true; - event.character_ = c; - return event; -} - -// static -Event Event::Special(const std::string& input) { - Event event; - event.input_ = std::move(input); - return event; -} +namespace { void ParseUTF8(Receiver& in, Sender& out, std::string& input) { char c; @@ -131,6 +103,38 @@ void ParseESC(Receiver& in, Sender& out, std::string& input) { } } +} // namespace + +// static +Event Event::Character(const std::string& input) { + Event event; + event.input_ = input; + event.is_character_ = true; + event.character_ = to_wstring(input)[0]; + return event; +} + +// static +Event Event::Character(char c) { + return Character(wchar_t(c)); +} + +// static +Event Event::Character(wchar_t c) { + Event event; + event.input_ = {(char)c}; + event.is_character_ = true; + event.character_ = c; + return event; +} + +// static +Event Event::Special(const std::string& input) { + Event event; + event.input_ = std::move(input); + return event; +} + // static void Event::Convert(Receiver& in, Sender& out, char c) { std::string input; diff --git a/src/ftxui/component/screen_interactive.cpp b/src/ftxui/component/screen_interactive.cpp index 3b800a7..125a82c 100644 --- a/src/ftxui/component/screen_interactive.cpp +++ b/src/ftxui/component/screen_interactive.cpp @@ -4,8 +4,6 @@ #include "ftxui/component/screen_interactive.hpp" -#define DEFINE_CONSOLEV2_PROPERTIES - #include #include @@ -20,6 +18,7 @@ #include "ftxui/screen/terminal.hpp" #if defined(_WIN32) + #define DEFINE_CONSOLEV2_PROPERTIES #define WIN32_LEAN_AND_MEAN #ifndef NOMINMAX #define NOMINMAX @@ -40,6 +39,7 @@ namespace ftxui { +namespace { // Produce a stream of Event from a stream of char. void CharToEventStream(Receiver receiver, Sender sender) { char c; @@ -154,6 +154,8 @@ void OnResize(int /* signal */) { on_resize(); } +} // namespace + ScreenInteractive::ScreenInteractive(int dimx, int dimy, Dimension dimension, diff --git a/src/ftxui/dom/flex.cpp b/src/ftxui/dom/flex.cpp index 721fc93..b6042dd 100644 --- a/src/ftxui/dom/flex.cpp +++ b/src/ftxui/dom/flex.cpp @@ -7,6 +7,8 @@ namespace ftxui { +namespace { + using FlexFunction = void (*)(Requirement&); void function_flex_grow(Requirement& r) { @@ -59,6 +61,8 @@ void function_not_flex(Requirement& r) { r.flex_shrink_y = 0; } +} // namespace + class Flex : public Node { public: Flex(FlexFunction f) { f_ = f; } diff --git a/src/ftxui/screen/string.cpp b/src/ftxui/screen/string.cpp index 8cf4c91..e3afd56 100644 --- a/src/ftxui/screen/string.cpp +++ b/src/ftxui/screen/string.cpp @@ -7,6 +7,7 @@ #include #include +namespace ftxui { #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4996) // codecvt_utf8_utf16 is deprecated @@ -24,4 +25,6 @@ std::wstring to_wstring(const std::string& s) { #ifdef _MSC_VER #pragma warning(pop) -#endif \ No newline at end of file +#endif + +} // namespace ftxui diff --git a/src/ftxui/screen/wcwidth.cpp b/src/ftxui/screen/wcwidth.cpp index 0e69959..92e3697 100644 --- a/src/ftxui/screen/wcwidth.cpp +++ b/src/ftxui/screen/wcwidth.cpp @@ -67,6 +67,8 @@ #include "ftxui/screen/string.hpp" +namespace ftxui { + namespace { struct interval { int first; @@ -303,3 +305,5 @@ int wstring_width_cjk(const std::wstring& text) { } return width; } + +} // namespace ftxui