121 Commits

Author SHA1 Message Date
ArthurSonzogni
d301fab1f4 Release v4.0.0 2023-02-12 18:02:40 +01:00
Arthur Sonzogni
3e35f45830 Execute clang-tidy and IWYU. (#576) 2023-02-12 14:07:28 +01:00
Arthur Sonzogni
a4e70dfb93 Fix vscroll hidding the last character. (#575)
This resolve:
https://github.com/ArthurSonzogni/FTXUI/issues/574
2023-02-12 13:51:51 +01:00
Arthur Sonzogni
b2853c8f14 Fix: cursor position offset. (#562)
This resolves:
https://github.com/ArthurSonzogni/FTXUI/issues/559
2023-01-22 11:51:37 +01:00
Arthur Sonzogni
6fe8310321 Feature: strikethrough and underlinedDouble decorator. (#561)
This resolves:
https://github.com/ArthurSonzogni/FTXUI/issues/560
2023-01-22 11:02:27 +01:00
Arthur Sonzogni
350dcac032 Fix build about fuzzer. (#557)
Previous patch introduced a regression. The condition needs to be
inverted.

Fixed:https://github.com/ArthurSonzogni/FTXUI/issues/556
2023-01-17 17:36:59 +01:00
Arthur Sonzogni
65848d1e5f cmake: support gtest from the package manager (#552)
Some developers would be happier with the gtest version provided from
their package manager. Use it if it is installed the package provide
cmake support.

Fixed: https://github.com/ArthurSonzogni/FTXUI/issues/551
2023-01-14 20:37:42 +01:00
Alex
1561293140 change vcpk.info to vcpkgx.com (#553)
The vcpkg.info site is now defunct.
[vcpkgx.com](https://vcpkgx.com/) provides a similar if not identical service to what vcpkg.info used to provide.
2023-01-12 10:16:00 +01:00
Arthur Sonzogni
90dfceefcb Fix slider focus. (#549)
This resolves:
https://github.com/ArthurSonzogni/FTXUI/issues/547

From discussion:
https://github.com/ArthurSonzogni/FTXUI/discussions/546
2023-01-07 18:13:59 +01:00
Arthur Sonzogni
5410329ac6 Adding heartbeat to spinner (#548)
Co-authored-by: cyrus <cyruswang2017@gmail.com>
2023-01-06 11:05:56 +01:00
Matthias Vallentin
9f9571190a Fix crash on empty tab container. (#540) 2022-12-30 16:31:47 +01:00
Arthur Sonzogni
b56afce48c Fix blinking cursor shape. (#539) 2022-12-28 13:17:56 +01:00
Arthur Sonzogni
abd5b2a503 Fix Windows UTF16 char. (#538)
Windows output UTF16 unicode char, but FTXUI works using UTF8. Do the
conversion.

This resolves:
https://github.com/ArthurSonzogni/FTXUI/issues/495
2022-12-28 11:47:11 +01:00
Arthur Sonzogni
60b9e491db Add all the Slider implementations. (#532)
This resolves:
https://github.com/ArthurSonzogni/FTXUI/issues/524
2022-12-22 21:15:54 +01:00
重装小杰
6cea410eaa Remove punctuation that affects compilation (#531) 2022-12-22 18:00:27 +01:00
Arthur Sonzogni
a52b959f66 Fix compile with gcc. (#529)
This resolves:
- https://github.com/ArthurSonzogni/FTXUI/issues/526
- https://github.com/ArthurSonzogni/FTXUI/issues/520
2022-12-19 20:00:03 +01:00
Arthur Sonzogni
0542227ba7 Execute clang tidy and IWYU (#528) 2022-12-19 19:44:43 +01:00
Arthur Sonzogni
4dc1a9fff9 Fix mouse on support over PuTTY (#525)
This resolves:
https://github.com/ArthurSonzogni/FTXUI/issues/523
2022-12-14 22:09:25 +01:00
ArthurSonzogni
b9f51844c3 Add documentation about the hoverable component. 2022-12-04 11:59:56 +01:00
Arthur Sonzogni (slow/sick)
0d54285e19 Add the Hoverable wrapper. (#522)
This will make it easier for developers. For instance:
https://github.com/ArthurSonzogni/FTXUI/issues/521
2022-12-04 11:54:49 +01:00
mr-mocap
f21ca3aa14 Improve UNIX signal handling (#518)
There was a dead lock caused by the reentrancy of the post method.

Co-authored-by: ArthurSonzogni <sonzogniarthur@gmail.com>
2022-12-01 22:56:35 +01:00
Arthur Sonzogni (slow/sick)
05f29ff3b3 Remove codecvt dependency. (#516)
This resolves:
https://github.com/ArthurSonzogni/FTXUI/issues/514
2022-11-26 20:43:09 +01:00
Fredrik Hallenberg
55b9706cfd Fix automerge at border (#515) 2022-11-25 00:39:17 +01:00
wflohry
121bd0d046 Ignoring wstring_convert deprecation warnings (#498) 2022-11-19 14:22:44 +01:00
Arthur Sonzogni (slow/sick)
2c5681ee20 Interpret 8 as 127 (#510)
This resolves:
https://github.com/ArthurSonzogni/FTXUI/issues/508

Apparently, this is a common issue:
https://www.cs.colostate.edu/~mcrob/toolbox/unix/keyboard.html
2022-11-17 22:16:25 +01:00
Arthur Sonzogni (slow/sick)
1689802349 Support multiple kind of cursor shapes. (#505)
https://github.com/ArthurSonzogni/FTXUI/issues/424
2022-11-11 14:09:53 +01:00
Arthur Sonzogni (slow/sick)
9babfea36b Fix example demo. (#506) 2022-11-11 14:07:27 +01:00
Tim Ebbeke
dfdbe1eecf Fix std::ignore is in <tuple>. (#502) 2022-10-25 15:26:12 -04:00
Arthur Sonzogni
aeaf39b8ea Fix F1-F4 keymapping. (#501)
It was just wrong, even on Linux.

Bug:https://github.com/ArthurSonzogni/FTXUI/issues/492
2022-10-18 22:58:22 +02:00
Arthur Sonzogni
0acfd8f255 Introduce Loop. (#476)
It can be used to give developers a better control on the loop. Users
can use it not to take full control of the thread, and poll FTXUI from
time to time as part of an external loop.

This resolves: https://github.com/ArthurSonzogni/FTXUI/issues/474
2022-10-18 21:29:27 +02:00
Arthur Sonzogni
26d63bc56f Fix pedantic compile issue. (#500) 2022-10-16 10:45:11 +02:00
Aleksandar Brakmić
f692a50195 Added eCAL monitor to the list of projects that are using FTXUI (#497) 2022-10-10 00:10:38 +02:00
Rosen Penev
e04ea27dcd fix cross compiling with MinGW (#499)
MinGW on Linux is case sensitive. Windows is case insensitive.

Signed-off-by: Rosen Penev <rosenp@gmail.com>

Signed-off-by: Rosen Penev <rosenp@gmail.com>
2022-10-10 00:08:28 +02:00
Arthur Sonzogni
f4b47333be Featre: Support ctrl+arrow in input. (#494)
CTRL+LEFT: Move the cursor to the beginning of the word.
CTRL+RIGHT: Move the cursor to the beginning of the word.

This was requested by:
https://github.com/ArthurSonzogni/FTXUI/issues/490
2022-10-06 21:16:55 +02:00
Arthur Sonzogni
ccfe22bc24 Test Page{Up,Down} for Radiobox. (#493)
See: https://github.com/ArthurSonzogni/FTXUI/pull/491#issuecomment-1264335576
2022-10-01 20:24:16 +02:00
jdfa
5ba29a9539 #487 Handled Space and Enter events for Radiobox (#491)
Return true when an event a RadioBox is state change due to pressing Return or space.

Co-authored-by: ArthurSonzogni <sonzogniarthur@gmail.com>
2022-10-01 13:34:15 +02:00
Arthur Sonzogni
c61fadd8ec Update to unicode 13 standard. (#484)
It contains additional full width character and combining characters.

This resolves:
https://github.com/ArthurSonzogni/FTXUI/issues/483
2022-09-29 10:50:27 +02:00
Lobanova Valeriia
b3aad183da FIX: minor mistake (#482) 2022-09-25 22:00:12 +02:00
Arthur Sonzogni
fab74f745d Execute clang tidy. (#477) 2022-09-05 20:56:41 +02:00
Arthur Sonzogni
c8ec151154 Bring back C++17 minimal requirement. (#475) 2022-09-03 13:03:04 +02:00
Arthur Sonzogni
1d76a2321c Update codecov.yml (#473)
This avoids being spammed by codecov.
2022-08-30 21:19:32 +02:00
Arthur Sonzogni
1661a5e83d Implement ButtonOption::Border() (#472)
It was missing. See:
https://github.com/ArthurSonzogni/FTXUI/issues/471
2022-08-30 19:03:14 +02:00
Arthur Sonzogni
b3ba747d82 Feature: Slider in any directions. (#468)
Add the `SliderOption` option supporting:
```cpp
{
  Ref<T> value;
  ConstRef<T> min = T(0);
  ConstRef<T> max = T(100);
  ConstRef<T> increment = (max() - min()) / 20;
  GaugeDirection direction = GaugeDirection::Right;
  Color color_active = Color::White;
  Color color_inactive = Color::GrayDark;
};
```

In particular, this supports multiple direction. This resolves:
https://github.com/ArthurSonzogni/FTXUI/issues/467

This one do not support adding a label. The old constructors can still
be used to have a label.
2022-08-30 18:52:33 +02:00
Arthur Sonzogni
8226c5aea7 Fix clang-tidy. (#469) 2022-08-28 21:30:01 +02:00
Arthur Sonzogni
1e381fcad6 Add codecov.yml (#470) 2022-08-28 21:29:48 +02:00
Jan Sende
d04e04adc6 Fixed typo (#465) 2022-08-24 12:00:54 +02:00
Arthur Sonzogni
ec994a4e65 Add support for emscripten screen resize. (#463)
This resolves:
https://github.com/ArthurSonzogni/FTXUI/issues/432
2022-08-21 23:04:32 +02:00
Arthur Sonzogni
3ec765e1f0 Menu: keep the previously focused element with mouse. (#462)
This resolves:
https://github.com/ArthurSonzogni/FTXUI/issues/453
2022-08-21 17:23:13 +02:00
Ian J
251306a4bb Fixed divide by zero segault (#461)
Check if inner_size is less than 1 to prevent divide by 0 segfault.

Co-authored-by: Arthur Sonzogni <sonzogniarthur@gmail.com>
2022-08-19 19:43:55 +02:00
Jan Sende
7cc68cfbd0 Fixed dim and bold not mixing well (#460)
One single reset code controls both the dim and bold properties. Mixing both led to one of the properties being wrongly reset.

Co-authored-by: Arthur Sonzogni <sonzogniarthur@gmail.com>
2022-08-19 19:03:56 +02:00
Arthur Sonzogni
36460fea2a Switch to codecov v3 (#458) 2022-08-15 15:00:28 +02:00
Arthur Sonzogni
d755356481 Add ref for sliders. (#457)
This resolves:
https://github.com/ArthurSonzogni/FTXUI/issues/456
2022-08-13 16:26:53 +02:00
Arthur Sonzogni
f461050759 Run IWYU (#450) 2022-08-07 14:44:33 +02:00
Julien Marrec
e42ab7b2e6 Typo in iwyu.cmake (#447) 2022-08-07 12:15:52 +02:00
Arthur Sonzogni
d9241435ce Fix link to TermBreaker. 2022-07-15 17:59:13 +02:00
badlydrawnrod
d5044bdaaf Fix #441 Canvas::DrawText() (#442)
Fix for Canvas::DrawText() draws nothing if the start coordinate is out
of bounds.
2022-07-10 22:14:32 +02:00
ArthurSonzogni
f91677e79f Update links toward examples. 2022-07-09 20:47:18 +02:00
ArthurSonzogni
d6da30a518 Add COOP/COEP for worker.js file. 2022-07-09 19:58:11 +02:00
ArthurSonzogni
d5b1899290 Fix workflow for documentation. 2022-07-09 19:15:17 +02:00
Hunter Zolomon
d545fb6f19 Fix README link reference. (#440) 2022-07-09 18:57:30 +02:00
ArthurSonzogni
f80e20c4aa Build documents and examples on master. 2022-07-09 18:51:35 +02:00
Hunter Zolomon
d805eb0648 Improved Introductory Tutorial Page (#433)
This PR solves #434 by improving on the existing introductory tutorial through adjustment of the grammar and vocabulary of the sentences, rewriting of sentences, writing new descriptions for sub-headings, and adding new link references for the corresponding discussion elements.

I have not replaced the inline script ascii calls yet, and there might be a few other things that might require some adjustment. However, this version looks much cleaner, consistent, and descriptive that the previous iteration.

Co-authored-by: ArthurSonzogni <sonzogniarthur@gmail.com>
2022-07-09 17:53:36 +02:00
倔强的贝吉塔
940f805b8f Add StartUp into the project list (#439) 2022-07-09 16:16:05 +02:00
Arthur Sonzogni
57da24dfdb Fix homescreen example thread safety. (#431)
This addresses and fix:
https://github.com/ArthurSonzogni/FTXUI/issues/430

This patchs makes |shift| to be read and written on the same thread. We
request the update to be made via a task posted on the main thread.

This patch has no real consequence, the previous behavior was fine.
I hope it will help users not to have thread safety issue and better
understand they can post tasks this way.
2022-07-04 23:34:37 +02:00
Jason Turner
0abaab6268 Update tag from v2.0.0 to v3.0.0 for cmake fetch (#429) 2022-07-01 09:15:58 +02:00
Levon
ef0f1da147 README: game_jam DisarmSelfDestruct link fixed (#425) 2022-06-26 22:52:32 +02:00
DanArmor
137f1fbf67 Add turing_cmd into the project list (#422) 2022-06-14 21:47:39 +02:00
AMS21
094d8d9d0a Fix border charset array being to large (#421)
This for some reason caused the clang compiler to crash, while also
being incorrect as the tables are actually only 5x6.

See the LLVM issue here:
https://github.com/llvm/llvm-project/issues/56016
2022-06-14 21:03:03 +02:00
Arthur Sonzogni
81e086788d Avoid making new allocation to clear the screen. (#420)
Previously, a new 2D vector was allocated for every new frame. This
caused a lot of temporary allocation to be made.

This patch modify "Screen::Clear" so that it do make a new allocation,
but clear the existing one instead.

Bug:https://github.com/ArthurSonzogni/FTXUI/issues/290#issuecomment-1153327251
2022-06-13 21:49:36 +02:00
Arthur Sonzogni
925a7578d4 Feature: the Modal component. (#418) 2022-06-12 17:08:22 +02:00
Vebjørn Johansen Rognli
bb3231695f Set includes as system interface to suppress warnings for other users (#415)
Set includes as system interface to suppress warnings for other users

Co-authored-by: ArthurSonzogni <sonzogniarthur@gmail.com>
2022-06-11 18:39:07 +02:00
Jian De
0a522488a7 Add beagle-config into the project list (#412) 2022-06-05 18:07:20 +02:00
Jhon Adams
b63aa9e375 Swap incorrect width/height mapping (#409)
width and height were being set using the incorrect axes resulting in incorrect canvas dimensions

Co-authored-by: ArthurSonzogni <sonzogniarthur@gmail.com>
2022-06-01 21:13:39 +02:00
Arthur Sonzogni
ed5b4cec49 Fix: Forward gridbox selected box. (#408)
This was discovered in:
https://github.com/ArthurSonzogni/FTXUI/issues/407
2022-05-28 22:35:52 +02:00
Amin Yahyaabadi
219daf46ff ci: use gcovr 5.0 temporarily (#406) 2022-05-23 17:34:07 +02:00
Arthur Sonzogni
11519ef1c6 Fix focus vs flexbox interaction. (#405)
- Fix focus in flexbox. This required resetting the focus state at the
  beginning of the ComputeRequirement(), because it can now run several
  times.

  This resolves:https://github.com/ArthurSonzogni/FTXUI/issues/399

- Add Box::Union.

- Add a preliminary implementation of forwarding selected_box from
  within the flexbox.
2022-05-22 21:41:29 +02:00
Conner
f9256fa132 Fix PostEvent() segfault (#403)
Fix segfault when PostEvent() called on inactive screen.

Co-authored-by: ArthurSonzogni <sonzogniarthur@gmail.com>
2022-05-22 15:37:27 +02:00
Arthur Sonzogni
c033ca61ae Remove NXXM. Execute IWYU. (#397) 2022-05-08 08:44:38 +02:00
Arthur Sonzogni
a6e04b4346 Table: reset dimensions. (#396)
The table is not meant to be used to render more than once. Reset the
dimensions so that, even if it is used wrongly, this is not memory
unsafe.

This was raised by:
https://github.com/ArthurSonzogni/FTXUI/issues/381
2022-05-08 08:34:51 +02:00
SColibri
09a2c077eb windows.h defines DrawText and shadows the function Canvas.DrawText, fix based on the solution #70 (#394)
Co-authored-by: Sebastian Carrion Ständer <sebastian.carrion@tum.de>
2022-05-04 23:39:03 +02:00
ArthurSonzogni
bc206f85da Fix compilation error on Windows for Color::Print 2022-05-02 20:50:15 +02:00
ArthurSonzogni
e9772a0116 Update gcov options. 2022-04-28 11:32:30 +02:00
ArthurSonzogni
e4c5c7b43b Fix ButtonTest.Animate 2022-04-28 11:03:39 +02:00
ArthurSonzogni
c2e1920449 Execute IWYU. 2022-04-28 10:43:31 +02:00
ArthurSonzogni
3d56146447 Add test coverage for button, collapsible and menu. 2022-04-28 10:08:33 +02:00
ArthurSonzogni
c33e805a76 Add coverage for menu and resizable_split. 2022-04-27 23:00:29 +02:00
ArthurSonzogni
d0890f94d1 execute IWYU and add some coverage tests. 2022-04-27 18:57:48 +02:00
ArthurSonzogni
84d6e6b3dd Add additional coverage tests. 2022-04-27 14:00:46 +02:00
ArthurSonzogni
001dd0a8c3 Exclude tests from coverage. 2022-04-27 13:25:43 +02:00
ArthurSonzogni
114cbfcffd Add coverage and remove deprecated WideInput. 2022-04-27 11:33:42 +02:00
ArthurSonzogni
5ba301d316 Add coverage for terminal_input_parser. 2022-04-27 11:11:32 +02:00
Arthur Sonzogni
06ed8567b8 Add coverage for colors (extended) (#385) 2022-04-27 09:28:48 +02:00
Arthur Sonzogni
04b36df567 Coverage decorator (#384)
Add code coverage for colors and decorators.
2022-04-26 17:04:34 +02:00
Arthur Sonzogni
764c24ef40 Add code coverage support. (#378) 2022-04-17 15:47:20 +02:00
Arthur Sonzogni
b2896aba49 Add games from the gamejam 2022-04-12 23:52:35 +02:00
Arthur Sonzogni
9f610a0110 Make the focused button to take the focus inside frame. (#371)
This resolves:
https://github.com/ArthurSonzogni/FTXUI/issues/370
2022-04-03 15:04:33 +02:00
Arthur Sonzogni
aebde94352 Add clang-tidy. (#368) 2022-03-31 02:17:43 +02:00
Arthur Sonzogni
62fb6298be Bug fixes. (#367)
- Do not draw more frames than what is needed.
- Fix MenuEntry transform state.
- Fix Canvas animated example.
2022-03-26 07:55:52 +01:00
Arthur Sonzogni
548fa51b71 Upgrade version (#363) 2022-03-20 21:14:17 +01:00
Arthur Sonzogni
1a3fcc1bd8 Improvement documentation. (#361) 2022-03-20 18:13:11 +01:00
Kefu Chai
0137d2a9ac component/collapsible: drop unused member variable (#360)
Signed-off-by: Kefu Chai <tchaikov@gmail.com>
2022-03-20 16:04:42 +01:00
Arthur Sonzogni
c76612a3c8 Fix error with invalid float in the gauge component. (#356) 2022-03-13 22:30:05 +01:00
Arthur Sonzogni
4da63b9260 Animation (#355) 2022-03-13 18:51:46 +01:00
Kefu Chai
95c766e9e4 Component decorators (#354)
Add decorator variants for decorator components

Add the "pipe" operator for components, similar to what was done for Elements.
We are able to put something like:
```
Button(...) | Maybe(&show_button)
```

Add decorators for:
- `Maybe`
- `CatchEvent`
- `Renderer`

Signed-off-by: Kefu Chai <tchaikov@gmail.com>
Co-authored-by: ArthurSonzogni <sonzogniarthur@gmail.com>
2022-03-12 15:18:36 +01:00
Arthur Sonzogni
3e28fd6520 Convert \r into \n (#350)
This resolves:
https://github.com/ArthurSonzogni/FTXUI/issues/337
2022-03-04 13:23:45 +01:00
Kefu Chai
a254e36632 component/catch_event: improve the example for CatchEvent() (#351)
before this change, the example in the doxygen document for CatchEvent()
does not use the documented function. hence the example is not that
useful for developers interested in a typical usage of this function.

after this change, the example is improved to added the call to
CatchEvent(), which allows the application to the Loop() function at
user input.

Signed-off-by: Kefu Chai <tchaikov@gmail.com>
2022-03-04 13:23:31 +01:00
IsakTheHacker
9dbc23a7d4 Fix typos in README (#349) 2022-03-01 19:07:50 +01:00
Vladislav Nepogodin
3fe12b8a2f Add cachyos-cli-installer in README (#347) 2022-02-24 14:38:28 +01:00
Arthur Sonzogni
43dd70979d Update README.md 2022-02-21 10:27:53 +01:00
Elazar Leibovich
779c2d5b1a Add conan as a possible packaging system. (#342) 2022-02-21 10:25:05 +01:00
Arthur Sonzogni
20f16b3984 Improve ComponentBase and Container::Tab Focusable implementations (#341)
- Provide better defaults for ComponentBase `Focusable()` and
  `ActiveChild()` methods. This resolves:
  https://github.com/ArthurSonzogni/FTXUI/issues/335

- Implement `Container::Tab` 's  `Focusable()` methods. This prevents
  the users to navigate into a tab with no interactivity.
2022-02-19 11:49:12 +01:00
ericLemanissier
f95ed885bb Don't override PREFIX target property (#340)
PREFIX is by default "lib", which most of the libraries use.
this changes makes the library files libftxui-foo.a
as ArthurSonzogni/FTXUI#140 intended originally
2022-02-19 10:48:07 +01:00
Kefu Chai
63e8dadad9 allow passing move-only parameter to Make() (#338)
ftxui::Ref<> is used for passing Options, for instance, MenuOption,
to the corresponding component which is supposed to hold a strong
reference of it. and we can observe the events sent to the component
by setting callback(s) in the option instance passed to the owner
component.

but the callback function is not always copyable, despite that it
might be moveable.

in this change,

* Make<>() is updated to use the perfect forwarding to avoid
  enforcing its parameters to be copyable.
* Ref<> is also updated to take a rvalue reference, so we can
  move away from the contructor parameter when creating an
  instance of Ref<>() from it.

Signed-off-by: Kefu Chai <tchaikov@gmail.com>
2022-02-16 14:09:08 +01:00
Arthur Sonzogni
9b83205b3e Fix vscroll-indicator size and offset. (#334) 2022-02-14 02:44:57 +01:00
Arthur Sonzogni
5da7b8a59a Fix automerge in tables. (#333) 2022-02-13 11:41:31 +01:00
Arthur Sonzogni
9c4218c2a8 Support SIGTSTP and task posting. (#331)
- Add support for SIGTSTP:
https://github.com/ArthurSonzogni/FTXUI/issues/330
This

- Add support for task posting.
This allows folks to defer function execution, and execute it directly
below the main loop. The task are executed in a FIFO order.
2022-02-13 11:11:34 +01:00
Arthur Sonzogni
62747a49b6 Fix windows warning. (#332) 2022-02-13 10:51:47 +01:00
Arthur Sonzogni
8ba3698437 Gauge direction (#326)
Add `gauge` with all the different directions.

Co-authored-by: Aleksandar Brakmic <13668697+brakmic-aleksandar@users.noreply.github.com>
2022-02-06 19:17:21 +01:00
Arthur Sonzogni
7c3ca1beb5 Update README.md 2022-02-05 15:06:23 +01:00
Nikola Dućak
689d5dd299 Replace std::clamp with util::clamp and reformat the code (#321)
* Replace std::clamp with util::clamp
* Apply clang-format
* Execute ./tools/iwyu.sh

Co-authored-by: ArthurSonzogni <sonzogniarthur@gmail.com>
2022-02-05 15:03:45 +01:00
Tushar Maheshwari
372d0ace4a Add tusharpm/tiles in README (#324) 2022-02-04 13:18:34 +01:00
191 changed files with 12373 additions and 3044 deletions

24
.clang-tidy Normal file
View File

@@ -0,0 +1,24 @@
---
Checks: "*,
-abseil-*,
-altera-*,
-android-*,
-fuchsia-*,
-google-*,
-llvm*,
-modernize-use-trailing-return-type,
-zircon-*,
-bugprone-easily-swappable-parameters,
-cppcoreguidelines-non-private-member-variables-in-classes,
-misc-no-recursion,
-misc-non-private-member-variables-in-classes,
-modernize-use-nodiscard,
-readability-avoid-const-params-in-decls,
-readability-else-after-return,
-readability-identifier-length,
-readability-implicit-bool-conversion,
-readability-static-accessed-through-instance,
"
WarningsAsErrors: ''
HeaderFilterRegex: ''
FormatStyle: none

View File

@@ -15,58 +15,102 @@ jobs:
test:
name: "Tests"
strategy:
fail-fast: false
matrix:
include:
- name: Linux GCC
os: ubuntu-latest
compiler: g++-9
test: true
compiler: gcc
gcov_executable: gcov
- name: Linux Clang
os: ubuntu-latest
compiler: clang++
test: true
compiler: llvm
gcov_executable: "llvm-cov gcov"
- name: MacOS clang
os: macos-latest
compiler: clang++
test: true
compiler: llvm
gcov_executable: "llvm-cov gcov"
- name: Windows MSVC
os: windows-latest
compiler: cl
test: false
runs-on: ${{ matrix.os }}
steps:
- name: "Checkout repository"
uses: actions/checkout@v2
- name: "Enable MSVC command prompt"
if: matrix.os == 'windows-latest'
uses: ilammy/msvc-dev-cmd@v1
- name: "Setup Cpp"
uses: aminya/setup-cpp@v1
with:
compiler: ${{ matrix.compiler }}
vcvarsall: ${{ contains(matrix.os, 'windows' )}}
cmake: true
ninja: true
clangtidy: true
cppcheck: false
gcovr: "5.0"
opencppcoverage: true
- name: "Install cmake"
uses: lukka/get-cmake@latest
- name: "Build debug mode"
# make sure coverage is only enabled for Debug builds, since it sets -O0
# to make sure coverage has meaningful results
- name: "Configure CMake"
run: >
mkdir build;
cd build;
cmake ..
-DCMAKE_CXX_COMPILER=${{ matrix.compiler }}
-DFTXUI_BUILD_DOCS=OFF
-DFTXUI_BUILD_EXAMPLES=ON
-DFTXUI_BUILD_TESTS=ON
-DFTXUI_BUILD_TESTS_FUZZER=OFF
-DFTXUI_ENABLE_INSTALL=ON ;
cmake --build . --config Debug;
cmake -S .
-B ./build
-DCMAKE_BUILD_TYPE:STRING=Debug
-DFTXUI_ENABLE_COVERAGE:BOOL=ON
-DFTXUI_BUILD_DOCS:BOOL=OFF
-DFTXUI_BUILD_EXAMPLES:BOOL=ON
-DFTXUI_BUILD_TESTS:BOOL=ON
-DFTXUI_BUILD_TESTS_FUZZER:BOOL=OFF
-DFTXUI_ENABLE_INSTALL:BOOL=ON ;
- name: "Run tests"
if: matrix.test
- name: "Build"
run: >
cd build;
./tests
cmake
--build ./build
- name: Unix - Test and coverage
if: runner.os != 'Windows'
working-directory: ./build
run: >
ctest -C Debug --rerun-failed --output-on-failure;
gcovr
-j ${{env.nproc}}
--delete
--root ../
--exclude "../examples"
--exclude ".*google.*"
--exclude ".*test.*"
--exclude-unreachable-branches
--exclude-throw-branches
--sort-uncovered
--print-summary
--xml-pretty
--xml
coverage.xml
.
--gcov-executable '${{ matrix.gcov_executable }}';
- name: Windows - Test and coverage
if: runner.os == 'Windows'
working-directory: ./build
run: >
OpenCppCoverage.exe
--export_type cobertura:coverage.xml
--cover_children
--
ctest -C Debug --rerun-failed --output-on-failure;
- name: Publish to codecov
uses: codecov/codecov-action@v3
with:
flags: ${{ runner.os }}
name: ${{ runner.os }}-coverage
files: ./build/coverage.xml
# Create a release on new v* tags
release:
@@ -117,7 +161,7 @@ jobs:
-DFTXUI_BUILD_TESTS=OFF
-DFTXUI_BUILD_TESTS_FUZZER=OFF
-DFTXUI_ENABLE_INSTALL=ON;
cmake --build . --config Release --target package;
cmake --build . --target package;
- uses: shogo82148/actions-upload-release-asset@v1
with:
upload_url: ${{ needs.release.outputs.upload_url }}
@@ -125,7 +169,7 @@ jobs:
overwrite: true
documentation:
needs: package
if: github.ref == 'refs/heads/master'
runs-on: ubuntu-latest
steps:
- name: "Checkout repository"
@@ -146,9 +190,23 @@ jobs:
run: >
mkdir build;
cd build;
emcmake cmake ..;
emcmake cmake ..
-DCMAKE_BUILD_TYPE=Release
-DFTXUI_BUILD_DOCS=ON
-DFTXUI_BUILD_EXAMPLES=ON
-DFTXUI_BUILD_TESTS=OFF
-DFTXUI_BUILD_TESTS_FUZZER=OFF
-DFTXUI_ENABLE_INSTALL=OFF;
cmake --build . --target doc;
rsync -amv --include='*/' --include='*.html' --include='*.js' --include='*.wasm' --exclude='*' examples doc/doxygen/html;
cmake --build . ;
rsync -amv
--include='*/'
--include='*.html'
--include='*.js'
--include='*.wasm'
--exclude='*'
examples
doc/doxygen/html;
- name: "Deploy"
uses: peaceiris/actions-gh-pages@v3

View File

@@ -1,5 +0,0 @@
{
"platform": [
"GTest::+gtest"
]
}

View File

@@ -4,6 +4,118 @@ Changelog
current (development)
---------------------
4.0.0
-----
### DOM
- Feature: more styles:
- `strikethrough`
- `underlinedDouble`
- Feature: Customize the cursor. Add the following decorators:
- `focusCursorBlock`
- `focusCursorBlockBlinking`
- `focusCursorBar`
- `focusCursorBarBlinking`
- `focusCursorUnderline`
- `focusCursorUnderlineBlinking`
- Bugfix: Fix `focus`/`select` when the `vbox`/`hbox`/`dbox` contains a
`flexbox`
- Bugfix: Fix the selected/focused area. It used to be 1 cell larger/longer than
requested
- Bugfix: Forward the selected/focused area from the child in gridbox.
- Bugfix: Fix incorrect Canvas computed dimensions.
- Bugfix: Support `vscroll_indicator` with a zero inner size.
- Bugfix: Fix `vscroll_indicator` hidding the last column.
### Component:
- Feature: Add the `Modal` component.
- Feature: `Slider` supports taking references for all its arguments.
- Feature: `Slider` supports `SliderOption`. It supports:
- multiple directions.
- multiple colors.
- various values (value, min, max, increment).
- Feature: Define `ScreenInteractive::Exit()`.
- Feature: Add `Loop` to give developers a better control on the main loop. This
can be used to integrate FTXUI into another main loop, without taking the full
control.
- Feature: `Input` supports CTRL+Left and CTRL+Right
- Feature: Use a blinking bar in the `Input` component.
- Improvement: The `Menu` keeps the focus when an entry is selected with the
mouse.
- Bugfix: Add implementation of `ButtonOption::Border()`. It was missing.
- Bugfix: Provide the correct key for F1-F4 and F11.
- Feature: Add the `Hoverable` component decorators.
### Screen
- Feature: add `Box::Union(a,b) -> Box`
- Bugfix: Fix resetting `dim` clashing with resetting of `bold`.
- Feature: Add emscripten screen resize support.
- Bugfix: Add unicode 13 support for full width characters.
- Bugfix: Fix MSVC treating codecvt C++17 deprecated function as an error.
### Build
- Support using the google test version provided by the package manager.
3.0.0
-----
### Build
- **breaking**: The library prefix is now back to "lib" (the default). This
means non-cmake users should not link against "libftxui-dom" for instance.
### Component
- **Animations** module! Components can implement the `OnAnimation` method and
the animation::Animator to define some animated properties.
- `Menu` now support animations.
- `Button` now supports animations.
- Support SIGTSTP. (ctrl+z).
- Support task posting. `ScreenInteractive::Post(Task)`.
- `Menu` can now be used in the 4 directions, using `MenuOption.direction`.
- `Menu` can display an animated underline, using
`MenuOption.underline.enabled`.
- `Button` is now taking the focus in frame.
- **breaking** All the options are now using a transform function.
- **breaking** The `Toggle` component is now implemented using `Menu`.
- **bugfix** Container::Tab implements `Focusable()`.
- **bugfix** Improved default implementations of ComponentBase `Focusable()` and
`ActiveChild()` methods.
- **bugfix** Automatically convert '\r' keys into '\n' for Linux programs that
do not send the correct code for the return key, like the 'bind'.
https://github.com/ArthurSonzogni/FTXUI/issues/337
- Add decorator for components:
- `operator|(Component, ComponentDecorator)`
- `operator|(Component, ElementDecorator)`
- `operator|=(Component, ComponentDecorator)`
- `operator|=(Component, ElementDecorator)`
- Add the `Maybe` decorator.
- Add the `CatchEvent` decorator.
- Add the `Renderer` decorator.
- **breaking** remove the "deprectated.hpp" header and Input support for wide
string.
### DOM:
- **breaking**: The `inverted` decorator now toggle in the inverted attribute.
- Add `gauge` for the 4 directions. Expose the following API:
```cpp
Element gauge(float ratio);
Element gaugeLeft(float ratio);
Element gaugeRight(float ratio);
Element gaugeUp(float ratio);
Element gaugeDown(float ratio);
Element gaugeDirection(float ratio, GaugeDirection);
```
- Add `separatorHSelector` and `separatorVSelector` elements. This can be used
to highlight an area.
- Add the `automerge` decorator. This makes separator characters to be merged
with others nearby.
- Fix the `Table` rendering function, to allow automerging characters.
- **Bugfix**: The `vscroll_indicator` now computes its offset and size
correctly.
- Add the `operator|=(Element, Decorator)`
### Screen:
- Add: `Color::Interpolate(lambda, color_a, color_b)`.
2.0.0
-----

View File

@@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.11)
project(ftxui
LANGUAGES CXX
VERSION 2.0.0
VERSION 4.0.0
)
option(FTXUI_BUILD_DOCS "Set to ON to build docs" ON)
@@ -10,6 +10,8 @@ option(FTXUI_BUILD_EXAMPLES "Set to ON to build examples" ON)
option(FTXUI_BUILD_TESTS "Set to ON to build tests" OFF)
option(FTXUI_BUILD_TESTS_FUZZER "Set to ON to enable fuzzing" OFF)
option(FTXUI_ENABLE_INSTALL "Generate the install target" ON)
option(FTXUI_CLANG_TIDY "Execute clang-tidy" OFF)
option(FTXUI_ENABLE_COVERAGE "Execute code coverage" OFF)
set(FTXUI_MICROSOFT_TERMINAL_FALLBACK_HELP_TEXT "On windows, assume the \
terminal used will be one of Microsoft and use a set of reasonnable fallback \
@@ -22,6 +24,7 @@ else()
${FTXUI_MICROSOFT_TERMINAL_FALLBACK_HELP_TEXT} OFF)
endif()
add_library(screen
include/ftxui/screen/box.hpp
include/ftxui/screen/color.hpp
@@ -44,6 +47,7 @@ add_library(dom
include/ftxui/dom/node.hpp
include/ftxui/dom/requirement.hpp
include/ftxui/dom/take_any_args.hpp
src/ftxui/dom/automerge.cpp
src/ftxui/dom/blink.cpp
src/ftxui/dom/bold.cpp
src/ftxui/dom/border.cpp
@@ -75,32 +79,43 @@ add_library(dom
src/ftxui/dom/separator.cpp
src/ftxui/dom/size.cpp
src/ftxui/dom/spinner.cpp
src/ftxui/dom/strikethrough.cpp
src/ftxui/dom/table.cpp
src/ftxui/dom/text.cpp
src/ftxui/dom/underlined.cpp
src/ftxui/dom/underlined_double.cpp
src/ftxui/dom/util.cpp
src/ftxui/dom/vbox.cpp
)
add_library(component
include/ftxui/component/animation.hpp
include/ftxui/component/captured_mouse.hpp
include/ftxui/component/component.hpp
include/ftxui/component/component_base.hpp
include/ftxui/component/component_options.hpp
include/ftxui/component/event.hpp
include/ftxui/component/loop.hpp
include/ftxui/component/mouse.hpp
include/ftxui/component/receiver.hpp
include/ftxui/component/screen_interactive.hpp
include/ftxui/component/task.hpp
src/ftxui/component/animation.cpp
src/ftxui/component/button.cpp
src/ftxui/component/catch_event.cpp
src/ftxui/component/checkbox.cpp
src/ftxui/component/collapsible.cpp
src/ftxui/component/component.cpp
src/ftxui/component/component_options.cpp
src/ftxui/component/container.cpp
src/ftxui/component/dropdown.cpp
src/ftxui/component/event.cpp
src/ftxui/component/hoverable.cpp
src/ftxui/component/input.cpp
src/ftxui/component/loop.cpp
src/ftxui/component/maybe.cpp
src/ftxui/component/menu.cpp
src/ftxui/component/modal.cpp
src/ftxui/component/radiobox.cpp
src/ftxui/component/radiobox.cpp
src/ftxui/component/renderer.cpp
@@ -109,44 +124,41 @@ add_library(component
src/ftxui/component/slider.cpp
src/ftxui/component/terminal_input_parser.cpp
src/ftxui/component/terminal_input_parser.hpp
src/ftxui/component/toggle.cpp
src/ftxui/component/util.cpp
)
target_link_libraries(dom
PUBLIC screen
)
find_package(Threads)
target_link_libraries(component
PUBLIC dom
PUBLIC Threads::Threads
)
set_target_properties(screen PROPERTIES VERSION ${PROJECT_VERSION})
set_target_properties(dom PROPERTIES VERSION ${PROJECT_VERSION})
set_target_properties(component PROPERTIES VERSION ${PROJECT_VERSION})
if (NOT EMSCRIPTEN)
find_package(Threads)
target_link_libraries(component
PUBLIC Threads::Threads
)
endif()
include(cmake/ftxui_set_options.cmake)
ftxui_set_options(screen)
ftxui_set_options(dom)
ftxui_set_options(component)
if (FTXUI_BUILD_TESTS AND ${CMAKE_VERSION} VERSION_GREATER "3.11.4")
include(cmake/ftxui_test.cmake)
endif()
if(FTXUI_BUILD_EXAMPLES)
add_subdirectory(examples)
endif()
if(FTXUI_BUILD_DOCS)
add_subdirectory(doc)
endif()
include(cmake/ftxui_coverage.cmake)
ftxui_check_coverage(screen)
ftxui_check_coverage(dom)
ftxui_check_coverage(component)
include(cmake/ftxui_test.cmake)
include(cmake/ftxui_benchmark.cmake)
include(cmake/ftxui_fuzzer.cmake)
include(cmake/iwyu.cmake)
include(cmake/ftxui_export.cmake)
include(cmake/ftxui_install.cmake)
include(cmake/ftxui_package.cmake)
if(FTXUI_ENABLE_INSTALL)
include(cmake/ftxui_install.cmake)
include(cmake/ftxui_package.cmake)
endif()
add_subdirectory(examples)
add_subdirectory(doc)

102
README.md
View File

@@ -8,10 +8,14 @@
<a href="#"><img src="https://img.shields.io/github/repo-size/ArthurSonzogni/FTXUI"></img></a>
<a href="https://github.com/ArthurSonzogni/FTXUI/issues"><img src="https://img.shields.io/github/issues/ArthurSonzogni/FTXUI"></img></a>
<a href="https://github.com/ArthurSonzogni/FTXUI/graphs/contributors"><img src="https://img.shields.io/github/contributors/arthursonzogni/FTXUI?color=blue"></img></a>
<a href="https://codecov.io/gh/ArthurSonzogni/FTXUI">
<img src="https://codecov.io/gh/ArthurSonzogni/FTXUI/branch/master/graph/badge.svg?token=C41FdRpNVA"/>
</a>
<br/>
<a href="https://arthursonzogni.github.io/FTXUI/">Documentation</a> ·
<a href="https://github.com/ArthurSonzogni/FTXUI/issues">Report Bug</a> ·
<a href="https://github.com/ArthurSonzogni/FTXUI/issues">Report a Bug</a> ·
<a href="https://arthursonzogni.github.io/FTXUI/examples.html">Examples</a> .
<a href="https://github.com/ArthurSonzogni/FTXUI/issues">Request Feature</a> ·
<a href="https://github.com/ArthurSonzogni/FTXUI/pulls">Send a Pull Request</a>
@@ -22,21 +26,34 @@
<i>Functional Terminal (X) User interface</i>
A simple C++ library for terminal based user interface.
A simple C++ library for terminal based user interfaces!
## Feature
* Functional style. Inspired by
[[1]](https://hackernoon.com/building-reactive-terminal-interfaces-in-c-d392ce34e649?gi=d9fb9ce35901)
and [React](https://reactjs.org/)
* Simple and elegant syntax (in my opinion).
* Support for [UTF8](https://en.wikipedia.org/wiki/UTF-8) and [fullwidth chars](https://en.wikipedia.org/wiki/Halfwidth_and_fullwidth_forms) (→ 测试).
* No dependencies.
* Cross platform. Linux/mac (main target), Windows (experimental thanks to contributors), WebAssembly.
* Simple and elegant syntax (in my opinion)
* Keyboard & mouse navigation.
* Support for [UTF8](https://en.wikipedia.org/wiki/UTF-8) and [fullwidth chars](https://en.wikipedia.org/wiki/Halfwidth_and_fullwidth_forms) (→ 测试)
* Support for animations. [Demo 1](https://arthursonzogni.github.io/FTXUI/examples/?file=component/menu_underline_animated_gallery), [Demo 2](https://arthursonzogni.github.io/FTXUI/examples/?file=component/button_style)
* Support for drawing. [Demo](https://arthursonzogni.github.io/FTXUI/examples/?file=component/canvas_animated)
* No dependencies
* Cross platform: Linux/MacOS (main target), WebAssembly, Windows (Thanks to contributors!).
* Learn by [examples](#documentation), and [tutorials](#documentation)
* Multiple packages: CMake [FetchContent](https://bewagner.net/programming/2020/05/02/cmake-fetchcontent/) (preferred), vcpkg, pkgbuild, conan.
* Good practises: documentation, tests, fuzzers, performance tests, automated CI, automated packaging, etc...
## Documentation
- [Starter example project](https://github.com/ArthurSonzogni/ftxui-starter)
- [Documentation](https://arthursonzogni.github.io/FTXUI/)
- [Examples (WebAssembly)](https://arthursonzogni.github.io/FTXUI/examples/)
- [Build using CMake](https://arthursonzogni.github.io/FTXUI/#build-cmake)
## Operating systems
- Webassembly
This is expected to be cross platform. This supports / tests:
- WebAssembly
- Linux
- MacOS
- Windows
@@ -62,13 +79,6 @@ A simple C++ library for terminal based user interface.
└────────────────────────────────────────────────────────────────────────────┘
~~~
## Documentation
- [Starter example project](https://github.com/ArthurSonzogni/ftxui-starter)
- [Documentation](https://arthursonzogni.github.io/FTXUI/)
- [Examples (WebAssembly)](https://arthursonzogni.com/FTXUI/examples/)
- [Build using CMake](https://github.com/ArthurSonzogni/FTXUI/blob/master/doc/mainpage.md#using-cmake)
## Short gallery
#### DOM
@@ -101,7 +111,7 @@ Element can become flexible using the the `flex` decorator.
![image](https://user-images.githubusercontent.com/4759106/147243064-780ac7cc-605b-475f-94b8-cf7c4aed03a5.png)
[See](https://arthursonzogni.github.io/FTXUI/examples_2dom_2hflow_8cpp-example.html) also this [demo](https://arthursonzogni.com/FTXUI/examples/?file=component/flexbox).
[See](https://arthursonzogni.github.io/FTXUI/examples_2dom_2hflow_8cpp-example.html) also this [demo](https://arthursonzogni.github.io/FTXUI/examples/?file=component/flexbox).
</details>
@@ -112,7 +122,9 @@ An element can be decorated using the functions:
- `dim`
- `inverted`
- `underlined`
- `underlinedDouble`
- `blink`
- `strikethrough`
- `color`
- `bgcolor`
@@ -120,13 +132,13 @@ An element can be decorated using the functions:
![image](https://user-images.githubusercontent.com/4759106/147244118-380bf834-9e33-40df-9ff0-07c10f2598ef.png)
FTXUI support the pipe operator. It means: `decorator1(decorator2(element))` and `element | decorator1 | decorator2` can be used.
FTXUI supports the pipe operator. It means: `decorator1(decorator2(element))` and `element | decorator1 | decorator2` can be used.
</details>
<details><summary>Colors</summary>
FTXUI support every color palettes:
FTXUI support every color palette:
Color [gallery](https://arthursonzogni.github.io/FTXUI/examples_2dom_2color_gallery_8cpp-example.html):
![image](https://user-images.githubusercontent.com/4759106/147248595-04c7245a-5b85-4544-809d-a5984fc6f9e7.png)
@@ -156,7 +168,7 @@ auto document = vbox({
A simple piece of text is represented using `text("content")`.
To support text wrapping following spaces the following function are provided:
To support text wrapping following spaces the following functions are provided:
```cpp
Element paragraph(std::string text);
Element paragraphAlignLeft(std::string text);
@@ -165,7 +177,7 @@ Element paragraphAlignCenter(std::string text);
Element paragraphAlignJustify(std::string text);
```
[Paragraph example](https://arthursonzogni.github.io/FTXUI/examples_2dom_2table_8cpp-example.html):
[Paragraph example](https://arthursonzogni.github.io/FTXUI/examples_2dom_2paragraph_8cpp-example.html)
![ezgif com-gif-maker (4)](https://user-images.githubusercontent.com/4759106/147251370-983a06e7-6f41-4113-92b8-942f43d34d06.gif)
@@ -202,7 +214,7 @@ Prebuilt components are declared in [<ftxui/component/component.hpp>](https://ar
<details><summary>Gallery</summary>
[Gallery](https://arthursonzogni.github.io/FTXUI/examples_2component_2gallery_8cpp-example.html) of multiple components. ([demo](https://arthursonzogni.com/FTXUI/examples/?file=component/gallery))
[Gallery](https://arthursonzogni.github.io/FTXUI/examples_2component_2gallery_8cpp-example.html) of multiple components. ([demo](https://arthursonzogni.github.io/FTXUI/examples/?file=component/gallery))
![image](https://user-images.githubusercontent.com/4759106/147247330-b60beb9f-e665-48b4-81c0-4b01ee95bc66.png)
@@ -312,16 +324,54 @@ Feel free to add your projects here:
- [TimeAccumulator](https://github.com/asari555/TimeAccumulator)
- [vantage](https://github.com/gokulmaxi/vantage)
- [tabdeeli](https://github.com/typon/tabdeeli)
- [tiles](https://github.com/tusharpm/tiles)
- [cachyos-cli-installer](https://github.com/cachyos/new-cli-installer)
- [beagle-config](https://github.com/SAtacker/beagle-config)
- [turing_cmd](https://github.com/DanArmor/turing_cmd)
- [StartUp](https://github.com/StubbornVegeta/StartUp)
- [eCAL monitor](https://github.com/eclipse-ecal/ecal)
## Hosted on
* [github](https://github.com/ArthurSonzogni/ftxui)
* [gitlab](https://gitlab.com/ArthurSonzogni/ftxui)
## [cpp-best-practices/game_jam](https://github.com/cpp-best-practices/game_jam)
Several games using the FTXUI have been made during the Game Jam:
- [TermBreaker](https://github.com/ArthurSonzogni/termBreaker) [**[Play web version]**](https://arthursonzogni.com/TermBreaker/)
- [Minesweeper Marathon](https://github.com/cpp-best-practices/game_jam/blob/main/Jam1_April_2022/minesweeper_marathon.md) [**[Play web version]**](https://barlasgarden.com/minesweeper/index.html)
- [Grand Rounds](https://github.com/cpp-best-practices/game_jam/blob/main/Jam1_April_2022/grandrounds.md)
- [LightsRound](https://github.com/cpp-best-practices/game_jam/blob/main/Jam1_April_2022/LightsRound.v.0.1.0.md)
- [DanteO](https://github.com/cpp-best-practices/game_jam/blob/main/Jam1_April_2022/danteo.md)
- [Sumo](https://github.com/cpp-best-practices/game_jam/blob/main/Jam1_April_2022/sumo.md)
- [Drag Me aROUND](https://github.com/cpp-best-practices/game_jam/blob/main/Jam1_April_2022/drag_me_around.md)
- [DisarmSelfDestruct](https://github.com/cpp-best-practices/game_jam/blob/main/Jam1_April_2022/DisarmSelfDestruct.md)
- [TheWorld](https://github.com/cpp-best-practices/game_jam/blob/main/Jam1_April_2022/TheWorld.md)
- [smoothlife](https://github.com/cpp-best-practices/game_jam/blob/main/Jam1_April_2022/smoothlife.md)
- [Consu](https://github.com/cpp-best-practices/game_jam/blob/main/Jam1_April_2022/consu.md)
## External package
It is **highly** recommanded to use cmake FetchContent to depends on FTXUI. This
way you can specify which commit you would like to depends on.
It is **highly** recommended to use CMake FetchContent to depend on FTXUI. This
way you can specify which commit you would like to depend on.
```cmake
include(FetchContent)
FetchContent_Declare(ftxui
GIT_REPOSITORY https://github.com/ArthurSonzogni/ftxui
GIT_TAG v3.0.0
)
FetchContent_GetProperties(ftxui)
if(NOT ftxui_POPULATED)
FetchContent_Populate(ftxui)
add_subdirectory(${ftxui_SOURCE_DIR} ${ftxui_BINARY_DIR} EXCLUDE_FROM_ALL)
endif()
```
If you don't, the following packages have been created:
- vcpkg ([soon](https://github.com/ArthurSonzogni/FTXUI/issues/112))
- [vcpkg](https://vcpkgx.com/details.html?package=ftxui)
- [Arch Linux PKGBUILD](https://aur.archlinux.org/packages/ftxui-git/).
- [conan.io](https://conan.io/center/ftxui)
## Contributors
<a href="https://github.com/ArthurSonzogni/FTXUI/graphs/contributors">
<img src="https://contrib.rocks/image?repo=ArthurSonzogni/FTXUI" />
</a>

View File

@@ -1,24 +1,21 @@
if (NOT WIN32)
FetchContent_Declare(googlebenchmark
GIT_REPOSITORY "https://github.com/google/benchmark"
GIT_TAG 62937f91b5c763a8e119d0c20c67b87bde8eff1c
)
FetchContent_GetProperties(googlebenchmark)
if(NOT googlebenchmark_POPULATED)
FetchContent_Populate(googlebenchmark)
add_subdirectory(${googlebenchmark_SOURCE_DIR} ${googlebenchmark_BINARY_DIR} EXCLUDE_FROM_ALL)
endif()
add_executable(ftxui_benchmark
src/ftxui/dom/benchmark_test.cpp
)
target_link_libraries(ftxui_benchmark
PRIVATE dom
PRIVATE benchmark::benchmark
PRIVATE benchmark::benchmark_main
)
target_include_directories(ftxui_benchmark
PRIVATE src
)
if (NOT FTXUI_BUILD_TESTS OR
NOT ${CMAKE_VERSION} VERSION_GREATER "3.11.4" OR
WIN32
)
return()
endif()
include(cmake/ftxui_find_google_benchmark.cmake)
add_executable(ftxui-benchmark
src/ftxui/dom/benchmark_test.cpp
)
ftxui_set_options(ftxui-benchmark)
target_link_libraries(ftxui-benchmark
PRIVATE dom
PRIVATE benchmark::benchmark
PRIVATE benchmark::benchmark_main
)
target_include_directories(ftxui-benchmark
PRIVATE src
)

View File

@@ -0,0 +1,8 @@
function(ftxui_check_coverage library)
if (FTXUI_ENABLE_COVERAGE)
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" OR CMAKE_CXX_COMPILER_ID MATCHES ".*Clang")
target_compile_options(${library} INTERFACE --coverage -O0 -g)
target_link_libraries(${library} INTERFACE --coverage)
endif()
endif()
endfunction()

View File

@@ -0,0 +1,32 @@
# Some developers would be happier with the google benchmark version provided
# from their package manager. Use it if it is installed the package provide
# cmake support.
# https://github.com/ArthurSonzogni/FTXUI/issues/551
find_package(benchmark QUIET)
if (benchmark_FOUND)
return()
endif()
option(FETCHCONTENT_UPDATES_DISCONNECTED TRUE)
option(FETCHCONTENT_QUIET FALSE)
include(FetchContent)
FetchContent_Declare(googlebenchmark
GIT_REPOSITORY "https://github.com/google/benchmark"
GIT_TAG 62937f91b5c763a8e119d0c20c67b87bde8eff1c
GIT_PROGRESS TRUE
)
FetchContent_GetProperties(googlebenchmark)
set (BENCHMARK_ENABLE_GTEST_TESTS OFF CACHE INTERNAL "")
set (BENCHMARK_ENABLE_TESTING OFF CACHE INTERNAL "")
if(googlebenchmark_POPULATED)
return()
endif()
FetchContent_Populate(googlebenchmark)
add_subdirectory(
${googlebenchmark_SOURCE_DIR}
${googlebenchmark_BINARY_DIR}
EXCLUDE_FROM_ALL
)

View File

@@ -0,0 +1,33 @@
# Some developers would be happier with the gtest version provided from their
# package manager. Use it if it is installed the package provide cmake support.
# https://github.com/ArthurSonzogni/FTXUI/issues/551
find_package(GTest QUIET)
if (GTest_FOUND)
return()
endif()
option(FETCHCONTENT_UPDATES_DISCONNECTED TRUE)
option(FETCHCONTENT_QUIET FALSE)
include(FetchContent)
FetchContent_Declare(googletest
GIT_REPOSITORY "https://github.com/google/googletest"
GIT_TAG 23ef29555ef4789f555f1ba8c51b4c52975f0907
GIT_PROGRESS TRUE
)
FetchContent_GetProperties(googletest)
if(googletest_POPULATED)
return()
endif()
FetchContent_Populate(googletest)
set(BUILD_GMOCK OFF CACHE INTERNAL "")
set(INSTALL_GTEST OFF CACHE INTERNAL "")
set(gtest_force_shared_crt ON CACHE INTERNAL "")
add_subdirectory(
${googletest_SOURCE_DIR}
${googletest_BINARY_DIR}
EXCLUDE_FROM_ALL
)

View File

@@ -1,3 +1,7 @@
if (NOT FTXUI_BUILD_TESTS_FUZZER)
return()
endif()
set(CMAKE_C_COMPILER clang)
set(CMAKE_CXX_COMPILER clang++)

View File

@@ -1,3 +1,7 @@
if(NOT FTXUI_ENABLE_INSTALL)
return()
endif()
include(GNUInstallDirs)
install(TARGETS screen dom component
EXPORT ftxui-export

View File

@@ -1,3 +1,7 @@
if(NOT FTXUI_ENABLE_INSTALL)
return()
endif()
if (UNIX AND NOT APPLE)
set(CPACK_GENERATOR "DEB;External;RPM;STGZ;TBZ2;TGZ;TXZ;TZ;TZST;ZIP")
elseif (UNIX AND APPLE)

View File

@@ -1,17 +1,53 @@
function(ftxui_set_options library)
set_target_properties(${library} PROPERTIES PREFIX "ftxui-")
find_program(CLANG_TIDY_EXE NAMES "clang-tidy" DOC "Path to clang-tidy executable" )
if(NOT CLANG_TIDY_EXE)
message(STATUS "clang-tidy not found.")
else()
message(STATUS "clang-tidy found: ${CLANG_TIDY_EXE}")
endif()
function(ftxui_set_options library)
message(STATUS "ftxui_set_options " ${library})
set_target_properties(${library} PROPERTIES VERSION ${PROJECT_VERSION})
if (NOT ${library} MATCHES "ftxui-*")
set_target_properties(${library} PROPERTIES OUTPUT_NAME "ftxui-${library}")
endif()
if(CLANG_TIDY_EXE AND FTXUI_CLANG_TIDY)
set_target_properties(${library}
PROPERTIES CXX_CLANG_TIDY "${CLANG_TIDY_EXE};-warnings-as-errors=*"
)
# By using "PUBLIC" as opposed to "SYSTEM INTERFACE", the compiler warning
# are enforced on the headers. This is behind "FTXUI_CLANG_TIDY", so that it
# applies only when developing FTXUI and on the CI. User's of the library
# get only the SYSTEM INTERFACE instead.
target_include_directories(${library}
PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
)
else()
target_include_directories(${library} SYSTEM
INTERFACE
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
)
endif()
target_include_directories(${library} SYSTEM
INTERFACE
$<INSTALL_INTERFACE:include>
)
target_include_directories(${library}
PUBLIC
$<INSTALL_INTERFACE:include>
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
PRIVATE
src
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/src>
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
)
# C++17 is used. We require fold expression at least.
target_compile_features(${library} PUBLIC cxx_std_17)
set_target_properties(${library} PROPERTIES
CXX_STANDARD 17
CXX_EXTENSIONS OFF
)
# Force Microsoft Visual Studio to decode sources files in UTF-8. This applies
# to the library and the library users.
@@ -47,9 +83,7 @@ function(ftxui_set_options library)
endfunction()
if (EMSCRIPTEN)
#string(APPEND CMAKE_CXX_FLAGS " -s ASSERTIONS=1")
string(APPEND CMAKE_CXX_FLAGS " -s USE_PTHREADS")
string(APPEND CMAKE_EXE_LINKER_FLAGS " -s ASYNCIFY")
string(APPEND CMAKE_EXE_LINKER_FLAGS " -s PROXY_TO_PTHREAD")
endif()

View File

@@ -1,56 +1,65 @@
enable_testing()
set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
set(FETCHCONTENT_UPDATES_DISCONNECTED TRUE)
include(FetchContent)
FetchContent_Declare(googletest
GIT_REPOSITORY "https://github.com/google/googletest"
GIT_TAG 23ef29555ef4789f555f1ba8c51b4c52975f0907
)
FetchContent_GetProperties(googletest)
if(NOT googletest_POPULATED)
FetchContent_Populate(googletest)
add_subdirectory(${googletest_SOURCE_DIR} ${googletest_BINARY_DIR} EXCLUDE_FROM_ALL)
if (NOT FTXUI_BUILD_TESTS OR
NOT ${CMAKE_VERSION} VERSION_GREATER "3.11.4")
return()
endif()
add_executable(tests
enable_testing()
include(cmake/ftxui_find_google_test.cmake)
add_executable(ftxui-tests
src/ftxui/component/animation_test.cpp
src/ftxui/component/button_test.cpp
src/ftxui/component/collapsible_test.cpp
src/ftxui/component/component_test.cpp
src/ftxui/component/component_test.cpp
src/ftxui/component/container_test.cpp
src/ftxui/component/hoverable_test.cpp
src/ftxui/component/input_test.cpp
src/ftxui/component/menu_test.cpp
src/ftxui/component/modal_test.cpp
src/ftxui/component/radiobox_test.cpp
src/ftxui/component/receiver_test.cpp
src/ftxui/component/resizable_split_test.cpp
src/ftxui/component/screen_interactive_test.cpp
src/ftxui/component/slider_test.cpp
src/ftxui/component/terminal_input_parser_test.cpp
src/ftxui/component/toggle_test.cpp
src/ftxui/dom/blink_test.cpp
src/ftxui/dom/bold_test.cpp
src/ftxui/dom/border_test.cpp
src/ftxui/dom/canvas_test.cpp
src/ftxui/dom/color_test.cpp
src/ftxui/dom/dbox_test.cpp
src/ftxui/dom/dim_test.cpp
src/ftxui/dom/flexbox_helper_test.cpp
src/ftxui/dom/flexbox_test.cpp
src/ftxui/dom/gauge_test.cpp
src/ftxui/dom/gridbox_test.cpp
src/ftxui/dom/hbox_test.cpp
src/ftxui/dom/scroll_indicator_test.cpp
src/ftxui/dom/separator_test.cpp
src/ftxui/dom/spinner_test.cpp
src/ftxui/dom/table_test.cpp
src/ftxui/dom/text_test.cpp
src/ftxui/dom/underlined_test.cpp
src/ftxui/dom/vbox_test.cpp
src/ftxui/screen/color_test.cpp
src/ftxui/screen/string_test.cpp
)
target_link_libraries(tests
target_link_libraries(ftxui-tests
PRIVATE component
PRIVATE gtest
PRIVATE gmock
PRIVATE gtest_main
PRIVATE GTest::gtest
PRIVATE GTest::gtest_main
)
target_include_directories(tests
target_include_directories(ftxui-tests
PRIVATE src
)
target_compile_options(tests PRIVATE -fsanitize=address)
target_link_libraries(tests PRIVATE -fsanitize=address)
ftxui_set_options(ftxui-tests)
target_compile_features(ftxui-tests PUBLIC cxx_std_20)
if (NOT MSVC)
include(cmake/ftxui_benchmark.cmake)
endif()
if (FTXUI_BUILD_TESTS_FUZZER)
include(cmake/ftxui_fuzzer.cmake)
endif()
include(GoogleTest)
gtest_discover_tests(ftxui-tests
DISCOVERY_TIMEOUT 600
)

View File

@@ -2,6 +2,6 @@ find_program(iwyu_path NAMES include-what-you-use iwyu)
if(iwyu_path)
set_property(TARGET ${lib}
PROPERTY ${iwyu_path} -Xiwyu
--mapping_file ${CMAKE_CURRENT_SOURCE_DIR}/iwyu.impl
--mapping_file ${CMAKE_CURRENT_SOURCE_DIR}/iwyu.imp
)
endif()

12
codecov.yml Normal file
View File

@@ -0,0 +1,12 @@
codecov:
require_ci_to_pass: no
notify:
after_n_builds: 4
wait_for_ci: yes
coverage:
precision: 2
round: down
range: "50...100"
comment: false

View File

@@ -1,22 +1,27 @@
if(NOT FTXUI_BUILD_DOCS)
return()
endif()
find_package(Doxygen)
if (DOXYGEN_FOUND)
# Generate example list for documentation
set(EXAMPLE_LIST "${CMAKE_CURRENT_BINARY_DIR}/example_list.md")
file(WRITE ${EXAMPLE_LIST} "# Examples")
get_property(EXAMPLES GLOBAL PROPERTY FTXUI::EXAMPLES)
foreach(EXAMPLE IN LISTS EXAMPLES)
file(APPEND ${EXAMPLE_LIST} "\n@example examples/${EXAMPLE}.cpp")
endforeach(EXAMPLE IN LISTS EXAMPLES)
configure_file(Doxyfile.in Doxyfile @ONLY)
# note the option ALL which allows to build the docs together with the application
add_custom_target(doc
COMMAND ${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
COMMENT "Generating API documentation with Doxygen"
VERBATIM
)
else (DOXYGEN_FOUND)
if (NOT DOXYGEN_FOUND)
message("Doxygen need to be installed to generate the doxygen documentation")
endif (DOXYGEN_FOUND)
return()
endif()
# Generate example list for documentation
set(EXAMPLE_LIST "${CMAKE_CURRENT_BINARY_DIR}/example_list.md")
file(WRITE ${EXAMPLE_LIST} "# Examples")
get_property(EXAMPLES GLOBAL PROPERTY FTXUI::EXAMPLES)
foreach(EXAMPLE IN LISTS EXAMPLES)
file(APPEND ${EXAMPLE_LIST} "\n@example examples/${EXAMPLE}.cpp")
endforeach(EXAMPLE IN LISTS EXAMPLES)
configure_file(Doxyfile.in Doxyfile @ONLY)
# note the option ALL which allows to build the docs together with the application
add_custom_target(doc
COMMAND ${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
COMMENT "Generating API documentation with Doxygen"
VERBATIM
)

View File

@@ -178,11 +178,12 @@ div.headertitle {
}
div.fragment {
padding: 16px;
background-color: #f3f3f3;
border: 0 solid;
transition: all 0.5s ease-in-out;
border-radius:5px;
border: 0 solid;
border: none;
padding:16px;
transition: all 0.5s ease-in-out;
}
div.fragment:hover {
@@ -192,8 +193,9 @@ div.fragment:hover {
div.line {
font-family: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, Courier, monospace;
font-size: 85%;
line-height: 1.45;
font-size: 90%;
font-variant-numeric: tabular-nums lining-nums;
font-kerning: none;
-webkit-transition-duration: 0;
-moz-transition-duration: 0;
-ms-transition-duration: 0;
@@ -206,15 +208,6 @@ div.line.glow {
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

View File

@@ -1,14 +1,19 @@
\mainpage
# Introduction
# Introduction {#introduction}
Welcome to the FTXUI documentation. Here, you will find the detail of every
functions and classes.
Welcome to the FTXUI documentation!
This is a brief tutorial. You are also encouraged to self-learn by reading the
[examples](./examples.html).
@tableofcontents
**Short example**
To build a single frame, you need create an `ftxui::Element`, and display it on
a `ftxui::Screen`.
**main.cpp**
```cpp
#include <ftxui/dom/elements.hpp>
@@ -37,19 +42,22 @@ int main(void) {
}
```
**output**
```bash
┌────┐┌─────────────────────────────────────────────────────────────────┐┌─────┐
│left││middle ││right│
└────┘└─────────────────────────────────────────────────────────────────┘└─────┘
┌────┐┌────────────────────────────────────┐┌─────┐
│left││middle ││right│
└────┘└────────────────────────────────────┘└─────┘
```
# Build
# Build {#build}
## Using CMake
## Using CMake {#build-cmake}
This is an example configuration for your **CMakeLists.txt**
CMakeLists.txt
~~~cmake
```cmake
cmake_minimum_required (VERSION 3.11)
# --- Fetch FTXUI --------------------------------------------------------------
@@ -58,7 +66,7 @@ include(FetchContent)
set(FETCHCONTENT_UPDATES_DISCONNECTED TRUE)
FetchContent_Declare(ftxui
GIT_REPOSITORY https://github.com/ArthurSonzogni/ftxui
# Specify a GIT_TAG here.
# Important: Specify a GIT_TAG XXXXX here.
)
FetchContent_GetProperties(ftxui)
@@ -83,38 +91,43 @@ target_link_libraries(ftxui-starter
PRIVATE ftxui::component # Not needed for this example.
)
~~~
```
Build
~~~
Subsequently, you build the project in the standard fashion as follows:
```bash
mkdir build && cd build
cmake ..
make
./main
~~~
```
# List of modules.
# List of modules. {#modules}
The project is split into 3 modules:
The project is comprised of 3 modules:
1. **ftxui/screen** defines a `ftxui::Screen`, this is a grid of `ftxui::Pixel`.
1. **ftxui/screen** defines a `ftxui::Screen`, a grid of `ftxui::Pixel`.
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.
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
3. **ftxui/component** The module is required if your program needs to respond
to user input. It defines a set of `ftxui::Component`. These components can
be utilized to navigate the program by using the arrow keys and interacting
with widgets such as the checkbox. You can also make you own components.
The use can navigates
using the arrow keys and interact with widgets like checkbox/inputbox/... You
can make you own components.
# screen
# screen {#module-screen}
It defines a `ftxui::Screen`. This is a grid of `ftxui::Pixel`. A Pixel
represent a Unicode character and its associated style (bold, colors, etc...).
The screen can be printed as a string using `ftxui::Screen::ToString()`.
This is the visual element of the program. It defines a `ftxui::Screen`, which
is a grid of `ftxui::Pixel`. A Pixel represents a Unicode character and its
associated style (bold, colors, etc.). The screen can be printed as a string
using `ftxui::Screen::ToString()`. The following example highlights this
process:
~~~cpp
```cpp
#include <ftxui/screen/screen.hpp>
#include <iostream>
@@ -130,75 +143,154 @@ The screen can be printed as a string using `ftxui::Screen::ToString()`.
std::cout << screen.ToString();
return EXIT_SUCCESS;
}
~~~
```
# dom
# dom {#module-dom}
This module defines a hierarchical set of Element. An element manages layout and
can be responsive to the terminal dimensions.
This module defines a hierarchical set of `ftxui::Element`. An element manages
the layout and can be responsive to the terminal dimension changes. Note the
following example where this module is used to create a simple layout with a
number of operators:
**Example:**
```cpp
// Define the document
Element document = vbox({
text("The window") | bold | color(Color::Blue),
gauge(0.5)
text("The footer")
});
text("The window") | bold | color(Color::Blue),
gauge(0.5)
text("The footer")
});
// Add a border.
// Add a border, by calling the `ftxui::border` decorator function.
document = border(document);
// Add another border, using the pipe operator.
document = document | border.
// Add another border, using the |= operator.
document |= border
```
**List of elements**
You only need one header: ftxui/dom/elements.hpp
The list of all elements are included and can be accessed by including the
corresponding header file:
```cpp
#include <ftxui/dom/elements.hpp>
```
\include ftxui/dom/elements.hpp
## text
## text ## {#dom-text}
The most simple widget. It displays a text.
~~~cpp
```cpp
text("I am a piece of text");
~~~
~~~bash
```
```bash
I am a piece of text.
~~~
```
## border
## vtext {#dom-vtext}
Add a border around an element
~~~cpp
Identical to `ftxui::text`, but displayed vertically.
Code:
```cpp
vtext("HELLO");
```
Terminal output:
```bash
H
E
L
L
O
```
## paragraph {#dom-paragraph}
Similar to `ftxui::text`, but the individual word are wrapped along multiple
lines, depending on the width of its container.
Sample Code:
```cpp
paragraph("A very long text")
```
![ezgif com-gif-maker (4)](https://user-images.githubusercontent.com/4759106/147251370-983a06e7-6f41-4113-92b8-942f43d34d06.gif)
For a more detailed example refer to [detailed example](https://arthursonzogni.github.io/FTXUI/examples_2dom_2paragraph_8cpp-example.html). Paragraph also includes a number of other variants as shown below:
```cpp
Element paragraph(std::string text);
Element paragraphAlignLeft(std::string text);
Element paragraphAlignRight(std::string text);
Element paragraphAlignCenter(std::string text);
Element paragraphAlignJustify(std::string text);
```
## border {#dom-border}
Adds a border around an element.
Code:
```cpp
border(text("The element"))
~~~
```
~~~bash
Terminal output:
```bash
┌───────────┐
│The element│
└───────────┘
~~~
```
## window
You can achieve the same behavior by using the pipe operator.
A `ftxui::window` is a `ftxui::border`, but with some text on top of the border.
Add a border around an element
~~~cpp
Code:
```cpp
text("The element") | border
```
Border also comes in a variety of styles as shown below:
```cpp
Element border(Element);
Element borderLight(Element);
Element borderHeavy(Element);
Element borderDouble(Element);
Element borderRounded(Element);
Element borderEmpty(Element);
Decorator borderStyled(BorderStyle);
Decorator borderWith(Pixel);
```
## window ## {#dom-window}
A `ftxui::window` is a `ftxui::border`, but with an additional header. To add a
window around an element, wrap it and specify a string as the header.
Code:
```cpp
window("The window", text("The element"))
~~~
```
~~~bash
Terminal output:
```bash
┌The window─┐
│The element│
└───────────┘
~~~
```
## separator
## separator {#dom-separator}
Display a vertical or horizontal line to visually split the content of a
Displays a vertical/horizontal line to visually split the content of a
container in two.
~~~cpp
Code:
```cpp
border(
hbox({
text("Left"),
@@ -206,44 +298,89 @@ border(
text("Right")
})
)
~~~
```
~~~bash
Terminal output:
```bash
┌────┬─────┐
│left│right│
└────┴─────┘
~~~
```
## gauge
A gauge. It can be used to represent a progress bar.
~~~cpp
Separators come in a variety of flavors as shown below:
```cpp
Element separator(void);
Element separatorLight();
Element separatorHeavy();
Element separatorDouble();
Element separatorEmpty();
Element separatorStyled(BorderStyle);
Element separator(Pixel);
Element separatorCharacter(std::string);
Element separatorHSelector(float left,
float right,
Color background,
Color foreground);
Element separatorVSelector(float up,
float down,
Color background,
Color foreground);
```
## gauge {#dom-gauge}
It constitutes a gauge. It can be used to represent a progress bar.
Code:
```cpp
border(gauge(0.5))
~~~
```
~~~bash
Teminal output:
```bash
┌────────────────────────────────────────────────────────────────────────────┐
│██████████████████████████████████████ │
└────────────────────────────────────────────────────────────────────────────┘
~~~
```
## graph
Gauges can be displayed in many orientations as shown below:
```cpp
Element gauge(float ratio);
Element gaugeLeft(float ratio);
Element gaugeRight(float ratio);
Element gaugeUp(float ratio);
Element gaugeDown(float ratio);
Element gaugeDirection(float ratio, GaugeDirection);
```
## graph {#dom-graph}
@htmlonly
<script id="asciicast-223726" src="https://asciinema.org/a/223726.js" async></script>
@endhtmlonly
## Colors
A terminal console can usually display colored text and colored background.
See:
```cpp
Element graph(GraphFunction);
```
~~~cpp
## Colors {#dom-colors}
Most terminal consoles can display colored text and colored backgrounds. FTXUI
supports every color palette:
```cpp
Decorator color(Color);
Decorator bgcolor(Color);
~~~
```
### Palette16
On most terminal the following colors are supported:
Color [gallery](https://arthursonzogni.github.io/FTXUI/examples_2dom_2color_gallery_8cpp-example.html):
![image](https://user-images.githubusercontent.com/4759106/147248595-04c7245a-5b85-4544-809d-a5984fc6f9e7.png)
### Palette16 #{#dom-colors-palette-16}
On most terminals the following colors are supported:
- Default
- Black
@@ -270,14 +407,14 @@ On most terminal the following colors are supported:
- Yellow
- YellowLight
Example:
Example use of the above colors using the pipe operator:
```cpp
text("Blue foreground") | color(Color::Blue);
text("Blue background") | bgcolor(Color::Blue);
text("Black on white") | color(Color::Black) | bgcolor(Color::White);
```
### Palette256
### Palette256 #{#dom-colors-palette-256}
On terminal supporting 256 colors.
@htmlonly
@@ -288,9 +425,13 @@ On terminal supporting 256 colors.
text("HotPink") | color(Color::HotPink);
```
### TrueColor
### TrueColor #{#dom-colors-true-color}
On terminal supporting trueColor, you can directly chose the 24bit RGB color:
On terminal supporting trueColor, you can directly use the 24bit RGB color
space:
Use the constructors below to specify the **RGB** or **HSV** values for your
color:
There are two constructors:
```cpp
@@ -303,100 +444,159 @@ ftxui::Color::HSV(uint8_t hue, uint8_t saturation, uint8_t value);
<script id="asciicast-xwzzghmqcqzIuyLwCpQFEqbEu" src="https://asciinema.org/a/xwzzghmqcqzIuyLwCpQFEqbEu.js" async></script>
@endhtmlonly
## Style
A terminal console can usually display colored text and colored background.
The text can also have different effects: bold, dim, underlined, inverted,
blink.
## Style {#dom-style}
In addition to colored text and colored backgrounds. Many terminals support text
effects such as: `bold`, `dim`, `underlined`, `inverted`, `blink`.
~~~cpp
```cpp
Element bold(Element);
Element dim(Element);
Element inverted(Element);
Element underlined(Element);
Element underlinedDouble(Element);
Element strikethrough(Element);
Element blink(Element);
Decorator color(Color);
Decorator bgcolor(Color);
~~~
```
Example:
~~~cpp
[Example](https://arthursonzogni.github.io/FTXUI/examples_2dom_2style_gallery_8cpp-example.html)
![image](https://user-images.githubusercontent.com/4759106/147244118-380bf834-9e33-40df-9ff0-07c10f2598ef.png)
To use these effects, simply wrap your elements with your desired effect:
```cpp
underlined(bold(text("This text is bold and underlined")))
~~~
```
Tips: The pipe operator can be used to chain Decorator:
~~~cpp
text("This text is bold")) | bold | underlined
~~~
Alternatively, use the pipe operator to chain it on your element:
```cpp
text("This text is bold") | bold | underlined
```
## Layout
## Layout {#dom-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.
Enables elements to be arranged in the following ways:
- **Horizontally** with `ftxui::hbox`
- **Vertically** with `ftxui::vbox`
- **Inside a grid** with `ftxui::gridbox`
- **Wrapped along one direction** using the `ftxui::flexbox`.
[Example](https://arthursonzogni.github.io/FTXUI/examples_2dom_2vbox_hbox_8cpp-example.html) using `ftxui::hbox`, `ftxui::vbox` and `ftxui::filler`.
`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.
![image](https://user-images.githubusercontent.com/4759106/147242524-7103b5d9-1a92-4e2d-ac70-b3d6740061e3.png)
[Example](https://arthursonzogni.github.io/FTXUI/examples_2dom_2gridbox_8cpp-example.htmlp)
using `ftxui::gridbox`:
An horizontal flow layout is implemented by:
* hflow (Horizontal flow)
![image](https://user-images.githubusercontent.com/4759106/147242972-0db1f2e9-0790-496f-86e6-ed2c604f7a73.png)
**Examples**
~~~cpp
[Example](https://github.com/ArthurSonzogni/FTXUI/blob/master/examples/dom/hflow.cpp)
using flexbox:
![image](https://user-images.githubusercontent.com/4759106/147243064-780ac7cc-605b-475f-94b8-cf7c4aed03a5.png)
Checkout this
[example](https://arthursonzogni.github.io/FTXUI/examples_2dom_2hflow_8cpp-example.html)
and the associated
[demo](https://arthursonzogni.github.io/FTXUI/examples/?file=component/flexbox).
Element can also become flexible using the the `ftxui::flex` decorator.
Code:
```cpp
hbox({
text("left") | border ,
text("middle") | border | flex,
text("right") | border,
});
~~~
~~~bash
┌────┐┌─────────────────────────────────────────────────────────────────┐┌─────┐
│left││middle ││right│
└────┘└─────────────────────────────────────────────────────────────────┘└─────┘
~~~
```
Terminal output:
```bash
┌────┐┌─────────────────────────────────────────────────────┐┌─────┐
│left││middle ││right│
└────┘└─────────────────────────────────────────────────────┘└─────┘
```
~~~cpp
Code:
```cpp
hbox({
text("left") | border ,
text("middle") | border | flex,
text("right") | border | flex,
});
~~~
~~~bash
┌────┐┌───────────────────────────────────┐┌───────────────────────────────────┐
│left││middle ││right │
└────┘└───────────────────────────────────┘└───────────────────────────────────┘
~~~
```
Terminal output:
```bash
┌────┐┌───────────────────────────────┐┌───────────────────────────────┐
│left││middle ││right │
└────┘└───────────────────────────────┘└───────────────────────────────┘
```
# component
## Table {#dom-table}
The `ftxui/component` directory defines the logic to get produce
interactive component responding to user's events (keyboard, mouse, etc...)
Enables easy formatting of data into a neat table like visual form.
A `ftxui::ScreenInteractive` defines a main loop to render a component.
[Code example](https://arthursonzogni.github.io/FTXUI/examples_2dom_2table_8cpp-example.html):
![image](https://user-images.githubusercontent.com/4759106/147250766-77d8ec9e-cf2b-486d-9866-1fd9f1bd2e6b.png)
A `ftxui::Component` is a shared pointer to a `ftxui::ComponentBase`. The later
defines
## Canvas {#dom-canvas}
See the API [<ftxui/dom/canvas.hpp>](./canvas_8hpp_source.html)
```cpp
auto c = Canvas(100, 100);
c.DrawPointLine(10, 10, 80, 10, Color::Red);
auto element = canvas(c);
```
Drawing can be performed on a `ftxui::Canvas`, using braille, block, or simple
characters:
Simple [example](https://github.com/ArthurSonzogni/FTXUI/blob/master/examples/dom/canvas.cpp):
![image](https://user-images.githubusercontent.com/4759106/147245843-76cc62fb-ccb4-421b-aacf-939f9afb42fe.png)
Complex [example](https://github.com/ArthurSonzogni/FTXUI/blob/master/examples/component/canvas_animated.cpp):
![ezgif com-gif-maker (3)](https://user-images.githubusercontent.com/4759106/147250538-783a8246-98e0-4a25-b032-3bd3710549d1.gif)
# component {#module-component}
The `ftxui::component` module defines the logic that produces interactive
components that respond to user events (keyboard, mouse, etc.).
A `ftxui::ScreenInteractive` defines a main loop that renders a component.
A `ftxui::Component` is a shared pointer to a `ftxui::ComponentBase`. The latter defines:
- `ftxui::ComponentBase::Render()`: How to render the interface.
- `ftxui::ComponentBase::OnEvent()`: How to react to events.
- `ftxui::ComponentBase::Add()`: Give a parent/child relation ship in between
two component. This defines a tree a components, which help properly define
how keyboard navigation works.
- `ftxui::ComponentBase::Add()`: Construct a parent/child relationship
between two components. The tree of component is used to define how to
navigate using the keyboard.
Predefined components are available in `ftxui/dom/component.hpp`:
`ftxui::Element` are used to render a single frame.
`ftxui::Component` are used to render dynamic user interface, producing multiple
frame, and updating its state on events.
[Gallery](https://arthursonzogni.github.io/FTXUI/examples_2component_2gallery_8cpp-example.html) of multiple components. ([demo](https://arthursonzogni.github.io/FTXUI/examples/?file=component/gallery))
![image](https://user-images.githubusercontent.com/4759106/147247330-b60beb9f-e665-48b4-81c0-4b01ee95bc66.png)
All predefined components are available in
["ftxui/dom/component.hpp"](./component_8hpp.html)
\include ftxui/component/component.hpp
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 {#component-input}
## Input
[Example](https://arthursonzogni.github.io/FTXUI/examples_2component_2input_8cpp-example.html):
![image](https://user-images.githubusercontent.com/4759106/147247671-f1d6f606-1845-4e94-a4a0-d4273e9ae6bd.png)
Produced by: `ftxui::Input()` from "ftxui/component/component.hpp"
@@ -404,7 +604,14 @@ Produced by: `ftxui::Input()` from "ftxui/component/component.hpp"
<script id="asciicast-223719" src="https://asciinema.org/a/223719.js" async></script>
@endhtmlonly
## Menu
## Menu {#component-menu}
Defines a menu object. It contains a list of entries, one of them is selected.
[Example](https://arthursonzogni.github.io/FTXUI/examples_2component_2menu_8cpp-example.html):
![image](https://user-images.githubusercontent.com/4759106/147247822-0035fd6f-bb13-4b3a-b057-77eb9291582f.png)
Produced by: `ftxui::Menu()` from "ftxui/component/component.hpp"
@@ -412,7 +619,13 @@ Produced by: `ftxui::Menu()` from "ftxui/component/component.hpp"
<script id="asciicast-223720" src="https://asciinema.org/a/223720.js" async></script>
@endhtmlonly
## Toggle.
## Toggle {#component-toggle}
A special kind of menu. The entries are displayed horizontally.
[Example](https://arthursonzogni.github.io/FTXUI/examples_2component_2toggle_8cpp-example.html):
![image](https://user-images.githubusercontent.com/4759106/147249383-e2201cf1-b7b8-4a5a-916f-d761e3e7ae40.png)
Produced by: `ftxui::Toggle()` from "ftxui/component/component.hpp"
@@ -420,7 +633,14 @@ Produced by: `ftxui::Toggle()` from "ftxui/component/component.hpp"
<script id="asciicast-223722" src="https://asciinema.org/a/223722.js" async></script>
@endhtmlonly
## CheckBox
## CheckBox {#component-checkbox}
This component defines a checkbox. It is a single entry that can be turned
on/off.
[Example](https://arthursonzogni.github.io/FTXUI/examples_2component_2checkbox_8cpp-example.html):
![image](https://user-images.githubusercontent.com/4759106/147246646-b86926a9-1ef9-4efb-af98-48a9b62acd81.png)
Produced by: `ftxui::Checkbox()` from "ftxui/component/component.hpp"
@@ -428,7 +648,13 @@ Produced by: `ftxui::Checkbox()` from "ftxui/component/component.hpp"
<script id="asciicast-223724" src="https://asciinema.org/a/223724.js" async></script>
@endhtmlonly
## RadioBox
## RadioBox {#component-radiobox}
A radiobutton component. This is a list of entries, where one can be turned on.
[Example](https://arthursonzogni.github.io/FTXUI/examples_2component_2radiobox_8cpp-example.html):
![image](https://user-images.githubusercontent.com/4759106/147246401-809d14a5-6621-4e36-8dd9-a2d75ef2a94e.png)
Produced by: `ftxui::Radiobox()` from "ftxui/component/component.hpp"
@@ -436,65 +662,182 @@ Produced by: `ftxui::Radiobox()` from "ftxui/component/component.hpp"
<script id="asciicast-223725" src="https://asciinema.org/a/223725.js" async></script>
@endhtmlonly
## Renderer
## Dropdown {#component-dropdown}
Produced by: `ftxui::Renderer()` from \ref "ftxui/component/component.hpp". This
A drop down menu is a component that when checked display a list of element for
the user to select one.
[Example](https://arthursonzogni.github.io/FTXUI/examples_2component_2dropdown_8cpp-example.html):
![youtube-video-gif (3)](https://user-images.githubusercontent.com/4759106/147246982-1e821751-531c-4e1f-bc37-2fa290e143cd.gif)
Produced by: `ftxui::Dropdown()` from "ftxui/component/component.hpp"
## Slider {#component-slider}
Represents a slider object that consists of a range with binned intermediate
intervals. It can be created by `ftxui::Slider()`.
[Example](https://arthursonzogni.github.io/FTXUI/examples_2component_2slider_8cpp-example.html):
![image](https://user-images.githubusercontent.com/4759106/147249265-7e2cad75-082c-436e-affe-44a550c480ab.png)
Produced by: `ftxui::Slider()` from "ftxui/component/component.hpp"
## Renderer {#component-renderer}
Produced by: `ftxui::Renderer()` from \ref ftxui/component/component.hpp. This
component decorate another one by using a different function to render an
interface.
## CatchEvent
Example:
```cpp
auto inner = [...]
Produced by: `ftxui::CatchEvent()` from \ref "ftxui/component/component.hpp".
This component decorate another one and catch the events before the underlying
component.
auto renderer = Renderer(inner, [&] {
return inner->Render() | border
});
```
## Container::Horizontal
`ftxui::Renderer` also supports the component decorator pattern:
```cpp
auto component = [...]
component = component
| Renderer([](Element e) { return e | border))
| Renderer(bold)
```
As a short hand, you can also compose a component with an element decorator:
```cpp
auto component = [...]
component = component | border | bold;
```
## CatchEvent {#component-catchevent}
Produced by: `ftxui::CatchEvent()` from \ref ftxui/component/component.hpp.
This component decorate others, catching events before the underlying component.
Examples:
```cpp
auto screen = ScreenInteractive::TerminalOutput();
auto renderer = Renderer([] {
return text("My interface");
});
auto component = CatchEvent(renderer, [&](Event event) {
if (event == Event::Character('q')) {
screen.ExitLoopClosure()();
return true;
}
return false;
});
screen.Loop(component);
```
The `ftxui::CatchEvent` can also be used as a decorator:
```cpp
component = component
| CatchEvent(handler_1)
| CatchEvent(handler_2)
| CatchEvent(handler_3)
;
```
## Collapsible {#component-collapsible}
Useful for visual elements whose visibility can be toggle on/off by the user.
Essentially, this the combination of the `ftxui::Checkbox()` and
`ftxui::Maybe()` components.
```cpp
auto collabsible = Collapsible("Show more", inner_element);
```
## Maybe {#component-maybe}
Produced by: `ftxui::Maybe()` from \ref ftxui/component/component.hpp.
This component can be utilized to show/hide any other component via a boolean or
a predicate.
Example with a boolean:
```cpp
bool show = true;
auto component = Renderer([]{ return "Hello World!"; });
auto maybe_component = Maybe(component, &show)
```
Example with a predicate:
```cpp
auto component = Renderer([]{ return "Hello World!"; });
auto maybe_component = Maybe(component, [&] { return time > 10; })
```
As usual, `ftxui::Maybe` can also be used as a decorator:
```cpp
component = component
| Maybe(&a_boolean)
| Maybe([&] { return time > 10; })
;
```
## Container {#component-container}
### Horizontal {#component-horizontal}
Produced by: `ftxui::Container::Horizontal()` from
"ftxui/component/component.hpp". It displays a list of components horizontally
and handle keyboard/mouse navigation.
## Container::Vertial
### Vertical {#component-vertical}
Produced by: `ftxui::Container::Vertical()` from
"ftxui/component/component.hpp". It displays a list of components vertically
and handles keyboard/mouse navigation.
## Container::Tab
### Tab {#component-tab}
Produced by: `ftxui::Container::Tab()` from
"ftxui/component/component.hpp". It take a list of component and display only
one of them. This is useful for implementing a tab bar.
## ResizableSplit::{Left, Right, Top, Bottom}
[Vertical](https://arthursonzogni.github.io/FTXUI/examples_2component_2tab_vertical_8cpp-example.html):
![ezgif com-gif-maker (1)](https://user-images.githubusercontent.com/4759106/147250144-22ff044a-4773-4ff7-a49c-12ba4034acb4.gif)
Produced by:
[Horizontal](https://arthursonzogni.github.io/FTXUI/examples_2component_2tab_horizontal_8cpp-example.html):
![ezgif com-gif-maker (2)](https://user-images.githubusercontent.com/4759106/147250217-fe447e0f-7a99-4e08-948a-995087d9b40e.gif)
## ResizableSplit {#component-resizable-split}
It defines a horizontal or vertical separation between two children components.
The position of the split is variable and controllable using the mouse.
There are four possible splits:
- `ftxui::ResizableSplitLeft()`
- `ftxui::ResizableSplitRight()`
- `ftxui::ResizableSplitTop()`
- `ftxui::ResizableSplitBottom()`
from "ftxui/component/component.hpp"
It defines an horizontal or vertical separation in between two children
component. The position of the split is variable and controllable using the
mouse.
[Example](https://arthursonzogni.github.io/FTXUI/examples_2component_2resizable_split_8cpp-example.html):
![ezgif com-gif-maker](https://user-images.githubusercontent.com/4759106/147248372-c55512fe-9b96-4b08-a1df-d05cf2cae431.gif)
@htmlonly
<script id="asciicast-tprMH2EdkUoMb7D2YxgMGgpzx" src="https://asciinema.org/a/tprMH2EdkUoMb7D2YxgMGgpzx.js" async></script>
@endhtmlonly
## Force a frame redraw.
## Force a frame redraw. {#component-force-redraw}
Whenever a new group of events have been processed: keyboard, mouse, window
resize, etc..., the `ftxui::ScreenInteractive::Loop()` is responsible for
drawing a new frame.
You might want to react to arbitrary events that are unknown to FTXUI. This can
be achieve by posting events via `ftxui::ScreenInteractive::PostEvent`, via a
thread. You can post the event`ftxui::Event::Custom`.
Typically, `ftxui::ScreenInteractive::Loop()` is responsible for drawing a new
frame whenever a new group of events (e.g keyboard, mouse, window resize, etc.)
has been processed. However, you might want to react to arbitrary events that
are unknown to FTXUI. To accomplish this, you must post events using
`ftxui::ScreenInteractive::PostEvent` (**this is thread safe**) via a thread.
You will have to post the event `ftxui::Event::Custom`.
Example:
```cpp
screen->PostEvent(Event::Custom);
```
`ftxui::ScreenInteractive::PostEvent` is thread safe.

View File

@@ -1,18 +1,32 @@
if(NOT FTXUI_BUILD_EXAMPLES)
return()
endif()
set(EXAMPLES_DIR ${CMAKE_CURRENT_SOURCE_DIR})
function(example name)
add_executable(ftxui_example_${name} ${name}.cpp)
target_link_libraries(ftxui_example_${name} PUBLIC ${DIRECTORY_LIB})
file(RELATIVE_PATH dir ${EXAMPLES_DIR} ${CMAKE_CURRENT_SOURCE_DIR})
set_property(GLOBAL APPEND PROPERTY FTXUI::EXAMPLES ${dir}/${name})
set_target_properties(ftxui_example_${name} PROPERTIES
CXX_STANDARD 20
)
endfunction(example)
add_subdirectory(component)
add_subdirectory(dom)
if (EMSCRIPTEN)
# 32MB should be enough to run all the examples, in debug mode.
target_link_options(component PUBLIC "SHELL: -s TOTAL_MEMORY=33554432")
target_link_options(component PUBLIC "SHELL: -s ASSERTIONS=1")
#string(APPEND CMAKE_EXE_LINKER_FLAGS " -s ALLOW_MEMORY_GROWTH=1")
#target_link_options(component PUBLIC "SHELL: -s ALLOW_MEMORY_GROWTH=1")
get_property(EXAMPLES GLOBAL PROPERTY FTXUI::EXAMPLES)
foreach(file
"index.html"
"sw.js"
"run_webassembly.py")
configure_file(${file} ${file})
endforeach(file)

View File

@@ -1,14 +1,19 @@
set(DIRECTORY_LIB component)
example(button)
example(button_animated)
example(button_in_frame)
example(button_style)
example(canvas_animated)
example(checkbox)
example(checkbox_in_frame)
example(collapsible)
example(composition)
example(custom_loop)
example(dropdown)
example(flexbox_gallery)
example(focus)
example(focus_cursor)
example(gallery)
example(homescreen)
example(input)
@@ -16,10 +21,13 @@ example(maybe)
example(menu)
example(menu2)
example(menu_entries)
example(menu_entries_animated)
example(menu_in_frame)
example(menu_multiple)
example(menu_style)
example(menu_underline_animated_gallery)
example(modal_dialog)
example(modal_dialog_custom)
example(nested_screen)
example(print_key_press)
example(radiobox)
@@ -27,6 +35,7 @@ example(radiobox_in_frame)
example(renderer)
example(resizable_split)
example(slider)
example(slider_direction)
example(slider_rgb)
example(tab_horizontal)
example(tab_vertical)

View File

@@ -1,12 +1,11 @@
#include <memory> // for shared_ptr, __shared_ptr_access
#include <string> // for operator+, to_wstring
#include <string> // for operator+, to_string
#include "ftxui/component/captured_mouse.hpp" // for ftxui
#include "ftxui/component/component.hpp" // for Button, Horizontal, Renderer
#include "ftxui/component/component_base.hpp" // for ComponentBase
#include "ftxui/component/component_options.hpp" // for ButtonOption
#include "ftxui/component/screen_interactive.hpp" // for ScreenInteractive
#include "ftxui/dom/elements.hpp" // for separator, gauge, Element, operator|, vbox, border
#include "ftxui/dom/elements.hpp" // for separator, gauge, text, Element, operator|, vbox, border
using namespace ftxui;
@@ -14,13 +13,9 @@ int main(int argc, const char* argv[]) {
int value = 50;
// The tree of components. This defines how to navigate using the keyboard.
auto button_option = ButtonOption();
button_option.border = false;
auto buttons = Container::Horizontal({
Button(
"[Decrease]", [&] { value--; }, &button_option),
Button(
"[Increase]", [&] { value++; }, &button_option),
Button("Decrease", [&] { value--; }),
Button("Increase", [&] { value++; }),
});
// Modify the way to render them on screen:

View File

@@ -0,0 +1,46 @@
#include <memory> // for shared_ptr, __shared_ptr_access
#include <string> // for operator+, to_string
#include "ftxui/component/captured_mouse.hpp" // for ftxui
#include "ftxui/component/component.hpp" // for Button, Horizontal, Renderer
#include "ftxui/component/component_base.hpp" // for ComponentBase
#include "ftxui/component/component_options.hpp" // for ButtonOption
#include "ftxui/component/screen_interactive.hpp" // for ScreenInteractive
#include "ftxui/dom/elements.hpp" // for gauge, separator, text, vbox, operator|, Element, border
#include "ftxui/screen/color.hpp" // for Color, Color::Blue, Color::Green, Color::Red
using namespace ftxui;
int main(int argc, const char* argv[]) {
int value = 50;
// The tree of components. This defines how to navigate using the keyboard.
auto buttons = Container::Horizontal({
Button(
"Decrease", [&] { value--; }, ButtonOption::Animated(Color::Red)),
Button(
"Reset", [&] { value = 50; }, ButtonOption::Animated(Color::Green)),
Button(
"Increase", [&] { value++; }, ButtonOption::Animated(Color::Blue)),
});
// Modify the way to render them on screen:
auto component = Renderer(buttons, [&] {
return vbox({
vbox({
text("value = " + std::to_string(value)),
separator(),
gauge(value * 0.01f),
}) | border,
buttons->Render(),
});
});
auto screen = ScreenInteractive::FitComponent();
screen.Loop(component);
return 0;
}
// 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.

View File

@@ -0,0 +1,49 @@
#include <memory> // for allocator, __shared_ptr_access, shared_ptr
#include <string> // for to_string, operator+
#include "ftxui/component/captured_mouse.hpp" // for ftxui
#include "ftxui/component/component.hpp" // for Button, Renderer, Vertical
#include "ftxui/component/component_base.hpp" // for ComponentBase
#include "ftxui/component/component_options.hpp" // for ButtonOption
#include "ftxui/component/screen_interactive.hpp" // for ScreenInteractive
#include "ftxui/dom/elements.hpp" // for operator|, text, Element, hbox, separator, size, vbox, border, frame, vscroll_indicator, HEIGHT, LESS_THAN
#include "ftxui/screen/color.hpp" // for Color, Color::Default, Color::GrayDark, Color::White
using namespace ftxui;
int main(int argc, const char* argv[]) {
int counter = 0;
auto on_click = [&] { counter++; };
auto button_style = ButtonOption::Animated(Color::Default, Color::GrayDark,
Color::Default, Color::White);
auto container = Container::Vertical({});
for (int i = 0; i < 30; ++i) {
auto button =
Button("Button " + std::to_string(i), on_click, &button_style);
container->Add(button);
}
auto renderer = Renderer(container, [&] {
return vbox({
hbox({
text("Counter:"),
text(std::to_string(counter)),
}),
separator(),
container->Render() | vscroll_indicator | frame |
size(HEIGHT, LESS_THAN, 20),
}) |
border;
});
auto screen = ScreenInteractive::FitComponent();
screen.Loop(renderer);
return 0;
}
// Copyright 2022 Arthur Sonzogni. All rights reserved.
// Use of this source code is governed by the MIT license that can be found in
// the LICENSE file.

View File

@@ -0,0 +1,61 @@
#include <string> // for operator+, to_string
#include "ftxui/component/captured_mouse.hpp" // for ftxui
#include "ftxui/component/component.hpp" // for Button, Vertical, Renderer, Horizontal, operator|
#include "ftxui/component/component_base.hpp" // for Component
#include "ftxui/component/component_options.hpp" // for ButtonOption
#include "ftxui/component/screen_interactive.hpp" // for ScreenInteractive
#include "ftxui/dom/elements.hpp" // for Element, separator, text, border
#include "ftxui/screen/color.hpp" // for Color, Color::Blue, Color::Green, Color::Red
using namespace ftxui;
int main(int argc, const char* argv[]) {
int value = 0;
auto action = [&] { value++; };
auto action_renderer =
Renderer([&] { return text("count = " + std::to_string(value)); });
auto buttons =
Container::Vertical({
action_renderer,
Renderer([] { return separator(); }),
Container::Horizontal({
Container::Vertical({
Button("Ascii 1", action, ButtonOption::Ascii()),
Button("Ascii 2", action, ButtonOption::Ascii()),
Button("Ascii 3", action, ButtonOption::Ascii()),
}),
Renderer([] { return separator(); }),
Container::Vertical({
Button("Simple 1", action, ButtonOption::Simple()),
Button("Simple 2", action, ButtonOption::Simple()),
Button("Simple 3", action, ButtonOption::Simple()),
}),
Renderer([] { return separator(); }),
Container::Vertical({
Button("Animated 1", action, ButtonOption::Animated()),
Button("Animated 2", action, ButtonOption::Animated()),
Button("Animated 3", action, ButtonOption::Animated()),
}),
Renderer([] { return separator(); }),
Container::Vertical({
Button("Animated 4", action,
ButtonOption::Animated(Color::Red)),
Button("Animated 5", action,
ButtonOption::Animated(Color::Green)),
Button("Animated 6", action,
ButtonOption::Animated(Color::Blue)),
}),
}),
}) |
border;
auto screen = ScreenInteractive::FitComponent();
screen.Loop(buttons);
return 0;
}
// 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.

View File

@@ -126,9 +126,9 @@ int main(int argc, const char* argv[]) {
std::vector<int> ys(100);
for (int x = 0; x < 100; x++) {
float dx = x - mouse_x;
float dy = 50;
ys[x] = dy + 20 * cos(dx * 0.14) + 10 * sin(dx * 0.42);
float dx = float(x - mouse_x);
float dy = 50.f;
ys[x] = int(dy + 20 * cos(dx * 0.14) + 10 * sin(dx * 0.42));
}
for (int x = 1; x < 99; x++)
c.DrawPointLine(x, ys[x], x + 1, ys[x + 1]);
@@ -141,10 +141,10 @@ int main(int argc, const char* argv[]) {
c.DrawText(0, 0, "A symmetrical graph filled");
std::vector<int> ys(100);
for (int x = 0; x < 100; x++) {
ys[x] = 30 + //
10 * cos(x * 0.2 - mouse_x * 0.05) + //
5 * sin(x * 0.4) + //
5 * sin(x * 0.3 - mouse_y * 0.05); //
ys[x] = int(30 + //
10 * cos(x * 0.2 - mouse_x * 0.05) + //
5 * sin(x * 0.4) + //
5 * sin(x * 0.3 - mouse_y * 0.05)); //
}
for (int x = 0; x < 100; x++) {
c.DrawPointLine(x, 50 + ys[x], x, 50 - ys[x], Color::Red);

View File

@@ -1,26 +1,22 @@
#include <memory> // for shared_ptr, __shared_ptr_access, allocator_traits<>::value_type
#include <array> // for array
#include <memory> // for shared_ptr, __shared_ptr_access
#include <string> // for operator+, to_string
#include <vector> // for vector
#include "ftxui/component/captured_mouse.hpp" // for ftxui
#include "ftxui/component/component.hpp" // for Checkbox, Renderer, 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, size, border, frame, HEIGHT, LESS_THAN
#include "ftxui/dom/elements.hpp" // for operator|, Element, size, border, frame, vscroll_indicator, HEIGHT, LESS_THAN
using namespace ftxui;
struct CheckboxState {
bool checked;
};
int main(int argc, const char* argv[]) {
std::vector<CheckboxState> states(30);
std::array<bool, 30> states;
auto container = Container::Vertical({});
for (int i = 0; i < 30; ++i) {
states[i].checked = false;
container->Add(
Checkbox("Checkbox" + std::to_string(i), &states[i].checked));
states[i] = false;
container->Add(Checkbox("Checkbox" + std::to_string(i), &states[i]));
}
auto renderer = Renderer(container, [&] {

View File

@@ -4,7 +4,6 @@
#include "ftxui/component/captured_mouse.hpp" // for ftxui
#include "ftxui/component/component.hpp" // for Button, Horizontal, Renderer
#include "ftxui/component/component_base.hpp" // for ComponentBase
#include "ftxui/component/component_options.hpp" // for ButtonOption
#include "ftxui/component/screen_interactive.hpp" // for ScreenInteractive
#include "ftxui/dom/elements.hpp" // for text, separator, Element, operator|, vbox, border
@@ -13,24 +12,17 @@ using namespace ftxui;
// An example of how to compose multiple components into one and maintain their
// interactiveness.
int main(int argc, const char* argv[]) {
auto button_option = ButtonOption();
button_option.border = false;
auto left_count = 0;
auto right_count = 0;
auto left_buttons = Container::Horizontal({
Button(
"[Decrease]", [&] { left_count--; }, &button_option),
Button(
"[Increase]", [&] { left_count++; }, &button_option),
Button("Decrease", [&] { left_count--; }),
Button("Increase", [&] { left_count++; }),
});
auto right_buttons = Container::Horizontal({
Button(
"[Decrease]", [&] { right_count--; }, &button_option),
Button(
"[Increase]", [&] { right_count++; }, &button_option),
Button("Decrease", [&] { right_count--; }),
Button("Increase", [&] { right_count++; }),
});
// Renderer decorates its child with a new rendering function. The way the

View File

@@ -0,0 +1,55 @@
#include <stdlib.h> // for EXIT_SUCCESS
#include <chrono> // for milliseconds
#include <ftxui/component/event.hpp> // for Event
#include <ftxui/component/mouse.hpp> // for ftxui
#include <ftxui/dom/elements.hpp> // for text, separator, Element, operator|, vbox, border
#include <memory> // for allocator, shared_ptr
#include <string> // for operator+, to_string
#include <thread> // for sleep_for
#include "ftxui/component/component.hpp" // for CatchEvent, Renderer, operator|=
#include "ftxui/component/loop.hpp" // for Loop
#include "ftxui/component/screen_interactive.hpp" // for ScreenInteractive
int main(int argc, const char* argv[]) {
using namespace ftxui;
auto screen = ScreenInteractive::FitComponent();
// Create a component counting the number of frames drawn and event handled.
int custom_loop_count = 0;
int frame_count = 0;
int event_count = 0;
auto component = Renderer([&] {
frame_count++;
return vbox({
text("This demonstrates using a custom ftxui::Loop. It "),
text("runs at 100 iterations per seconds. The FTXUI events "),
text("are all processed once per iteration and a new frame "),
text("is rendered as needed"),
separator(),
text("ftxui event count: " + std::to_string(event_count)),
text("ftxui frame count: " + std::to_string(frame_count)),
text("Custom loop count: " + std::to_string(custom_loop_count)),
}) |
border;
});
component |= CatchEvent([&](Event) -> bool {
event_count++;
return false;
});
Loop loop(&screen, component);
while (!loop.HasQuitted()) {
custom_loop_count++;
loop.RunOnce();
std::this_thread::sleep_for(std::chrono::milliseconds(10));
}
return EXIT_SUCCESS;
}
// 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.

View File

@@ -32,8 +32,8 @@ Element make_grid() {
};
int main(int argc, const char* argv[]) {
float focus_x = 0.0f;
float focus_y = 0.0f;
float focus_x = 0.5f;
float focus_y = 0.5f;
auto slider_x = Slider("x", &focus_x, 0.f, 1.f, 0.01f);
auto slider_y = Slider("y", &focus_y, 0.f, 1.f, 0.01f);

View File

@@ -0,0 +1,38 @@
#include <ftxui/component/captured_mouse.hpp> // for ftxui
#include <string> // for allocator, operator+, char_traits, string
#include "ftxui/component/component.hpp" // for Renderer, Vertical
#include "ftxui/component/screen_interactive.hpp" // for ScreenInteractive, Component
#include "ftxui/dom/elements.hpp" // for text, Decorator, focus, focusCursorBar, focusCursorBarBlinking, focusCursorBlock, focusCursorBlockBlinking, focusCursorUnderline, focusCursorUnderlineBlinking, hbox, Element
using namespace ftxui;
Component Instance(std::string label, Decorator focusCursor) {
return Renderer([=](bool focused) {
if (focused) {
return hbox({
text("> " + label + " "),
focusCursor(text(" ")),
});
}
return text(" " + label + " ");
});
};
int main(int argc, const char* argv[]) {
auto screen = ScreenInteractive::Fullscreen();
screen.Loop(Container::Vertical({
Instance("focus", focus),
Instance("focusCursorBlock", focusCursorBlock),
Instance("focusCursorBlockBlinking", focusCursorBlockBlinking),
Instance("focusCursorBar", focusCursorBar),
Instance("focusCursorBarBlinking", focusCursorBarBlinking),
Instance("focusCursorUnderline", focusCursorUnderline),
Instance("focusCursorUnderlineBlinking", focusCursorUnderlineBlinking),
}));
return 0;
}
// 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.

View File

@@ -1,23 +1,26 @@
#include <stddef.h> // for size_t
#include <array> // for array
#include <atomic> // for atomic
#include <chrono> // for operator""s, chrono_literals
#include <cmath> // for sin
#include <functional> // for ref, reference_wrapper, function
#include <memory> // for allocator, shared_ptr, __shared_ptr_access
#include <string> // for string, basic_string, operator+, to_string, char_traits
#include <string> // for string, basic_string, char_traits, operator+, to_string
#include <thread> // for sleep_for, thread
#include <utility> // for move
#include <vector> // for vector
#include "ftxui/component/captured_mouse.hpp" // for ftxui
#include "ftxui/component/component.hpp" // for Checkbox, Renderer, Horizontal, Vertical, Input, Menu, Radiobox, ResizableSplitLeft, Tab, Toggle
#include "ftxui/component/component_base.hpp" // for ComponentBase
#include "ftxui/component/component_options.hpp" // for InputOption
#include "../dom/color_info_sorted_2d.ipp" // for ColorInfoSorted2D
#include "ftxui/component/component.hpp" // for Checkbox, Renderer, Horizontal, Vertical, Input, Menu, Radiobox, ResizableSplitLeft, Tab
#include "ftxui/component/component_base.hpp" // for ComponentBase, Component
#include "ftxui/component/component_options.hpp" // for MenuOption, InputOption
#include "ftxui/component/event.hpp" // for Event, Event::Custom
#include "ftxui/component/screen_interactive.hpp" // for Component, ScreenInteractive
#include "ftxui/dom/elements.hpp" // for text, operator|, color, bgcolor, filler, Element, size, vbox, flex, hbox, separator, graph, EQUAL, paragraph, hcenter, WIDTH, bold, window, border, vscroll_indicator, Elements, HEIGHT, hflow, frame, flex_grow, flexbox, gauge, paragraphAlignCenter, paragraphAlignJustify, paragraphAlignLeft, paragraphAlignRight, dim, spinner, Decorator, LESS_THAN, center, yflex, GREATER_THAN
#include "ftxui/screen/color.hpp" // for Color, Color::Blue, Color::BlueLight, Color::RedLight, Color::Black, Color::Cyan, Color::CyanLight, Color::GrayDark, Color::GrayLight, Color::Green, Color::GreenLight, Color::Magenta, Color::MagentaLight, Color::Red, Color::White, Color::Yellow, Color::YellowLight, Color::Default
#include "ftxui/screen/terminal.hpp" // for Size, Dimensions
#include "ftxui/dom/elements.hpp" // for text, color, operator|, bgcolor, filler, Element, vbox, size, hbox, separator, flex, window, graph, EQUAL, paragraph, WIDTH, hcenter, Elements, bold, vscroll_indicator, HEIGHT, flexbox, hflow, border, frame, flex_grow, gauge, paragraphAlignCenter, paragraphAlignJustify, paragraphAlignLeft, paragraphAlignRight, dim, spinner, LESS_THAN, center, yframe, GREATER_THAN
#include "ftxui/dom/flexbox_config.hpp" // for FlexboxConfig
#include "ftxui/screen/color.hpp" // for Color, Color::BlueLight, Color::RedLight, Color::Black, Color::Blue, Color::Cyan, Color::CyanLight, Color::GrayDark, Color::GrayLight, Color::Green, Color::GreenLight, Color::Magenta, Color::MagentaLight, Color::Red, Color::White, Color::Yellow, Color::YellowLight, Color::Default, Color::Palette256, ftxui
#include "ftxui/screen/color_info.hpp" // for ColorInfo
#include "ftxui/screen/terminal.hpp" // for Size, Dimensions
using namespace ftxui;
@@ -27,7 +30,6 @@ int main(int argc, const char* argv[]) {
// ---------------------------------------------------------------------------
// HTOP
// ---------------------------------------------------------------------------
int shift = 0;
auto my_graph = [&shift](int width, int height) {
@@ -95,7 +97,7 @@ int main(int argc, const char* argv[]) {
separator(),
ram | flex,
}) |
flex | border;
flex;
});
// ---------------------------------------------------------------------------
@@ -255,7 +257,7 @@ int main(int argc, const char* argv[]) {
}) | size(HEIGHT, LESS_THAN, 8),
hflow(render_command()) | flex_grow,
}) |
flex_grow | border;
flex_grow;
});
// ---------------------------------------------------------------------------
@@ -267,61 +269,116 @@ int main(int argc, const char* argv[]) {
entries.push_back(spinner(i, shift / 2) | bold |
size(WIDTH, GREATER_THAN, 2) | border);
}
return hflow(std::move(entries)) | border;
return hflow(std::move(entries));
});
// ---------------------------------------------------------------------------
// Colors
// ---------------------------------------------------------------------------
auto color_tab_renderer = Renderer([] {
return hbox({
vbox({
color(Color::Default, text("Default")),
color(Color::Black, text("Black")),
color(Color::GrayDark, text("GrayDark")),
color(Color::GrayLight, text("GrayLight")),
color(Color::White, text("White")),
color(Color::Blue, text("Blue")),
color(Color::BlueLight, text("BlueLight")),
color(Color::Cyan, text("Cyan")),
color(Color::CyanLight, text("CyanLight")),
color(Color::Green, text("Green")),
color(Color::GreenLight, text("GreenLight")),
color(Color::Magenta, text("Magenta")),
color(Color::MagentaLight, text("MagentaLight")),
color(Color::Red, text("Red")),
color(Color::RedLight, text("RedLight")),
color(Color::Yellow, text("Yellow")),
color(Color::YellowLight, text("YellowLight")),
}),
vbox({
bgcolor(Color::Default, text("Default")),
bgcolor(Color::Black, text("Black")),
bgcolor(Color::GrayDark, text("GrayDark")),
bgcolor(Color::GrayLight, text("GrayLight")),
bgcolor(Color::White, text("White")),
bgcolor(Color::Blue, text("Blue")),
bgcolor(Color::BlueLight, text("BlueLight")),
bgcolor(Color::Cyan, text("Cyan")),
bgcolor(Color::CyanLight, text("CyanLight")),
bgcolor(Color::Green, text("Green")),
bgcolor(Color::GreenLight, text("GreenLight")),
bgcolor(Color::Magenta, text("Magenta")),
bgcolor(Color::MagentaLight, text("MagentaLight")),
bgcolor(Color::Red, text("Red")),
bgcolor(Color::RedLight, text("RedLight")),
bgcolor(Color::Yellow, text("Yellow")),
bgcolor(Color::YellowLight, text("YellowLight")),
}),
}) |
hcenter | border;
auto basic_color_display =
vbox({
text("16 color palette:"),
separator(),
hbox({
vbox({
color(Color::Default, text("Default")),
color(Color::Black, text("Black")),
color(Color::GrayDark, text("GrayDark")),
color(Color::GrayLight, text("GrayLight")),
color(Color::White, text("White")),
color(Color::Blue, text("Blue")),
color(Color::BlueLight, text("BlueLight")),
color(Color::Cyan, text("Cyan")),
color(Color::CyanLight, text("CyanLight")),
color(Color::Green, text("Green")),
color(Color::GreenLight, text("GreenLight")),
color(Color::Magenta, text("Magenta")),
color(Color::MagentaLight, text("MagentaLight")),
color(Color::Red, text("Red")),
color(Color::RedLight, text("RedLight")),
color(Color::Yellow, text("Yellow")),
color(Color::YellowLight, text("YellowLight")),
}),
vbox({
bgcolor(Color::Default, text("Default")),
bgcolor(Color::Black, text("Black")),
bgcolor(Color::GrayDark, text("GrayDark")),
bgcolor(Color::GrayLight, text("GrayLight")),
bgcolor(Color::White, text("White")),
bgcolor(Color::Blue, text("Blue")),
bgcolor(Color::BlueLight, text("BlueLight")),
bgcolor(Color::Cyan, text("Cyan")),
bgcolor(Color::CyanLight, text("CyanLight")),
bgcolor(Color::Green, text("Green")),
bgcolor(Color::GreenLight, text("GreenLight")),
bgcolor(Color::Magenta, text("Magenta")),
bgcolor(Color::MagentaLight, text("MagentaLight")),
bgcolor(Color::Red, text("Red")),
bgcolor(Color::RedLight, text("RedLight")),
bgcolor(Color::Yellow, text("Yellow")),
bgcolor(Color::YellowLight, text("YellowLight")),
}),
}),
}) |
border;
auto palette_256_color_display = text("256 colors palette:");
{
std::vector<std::vector<ColorInfo>> info_columns = ColorInfoSorted2D();
Elements columns;
for (auto& column : info_columns) {
Elements column_elements;
for (auto& it : column) {
column_elements.push_back(
text(" ") | bgcolor(Color(Color::Palette256(it.index_256))));
}
columns.push_back(hbox(std::move(column_elements)));
}
palette_256_color_display = vbox({
palette_256_color_display,
separator(),
vbox(columns),
}) |
border;
}
// True color display.
auto true_color_display = text("TrueColors: 24bits:");
{
int saturation = 255;
Elements array;
for (int value = 0; value < 255; value += 16) {
Elements line;
for (int hue = 0; hue < 255; hue += 6) {
line.push_back(text("") //
| color(Color::HSV(hue, saturation, value)) //
| bgcolor(Color::HSV(hue, saturation, value + 8)));
}
array.push_back(hbox(std::move(line)));
}
true_color_display = vbox({
true_color_display,
separator(),
vbox(std::move(array)),
}) |
border;
}
return flexbox(
{
basic_color_display,
palette_256_color_display,
true_color_display,
},
FlexboxConfig().SetGap(1, 1));
});
// ---------------------------------------------------------------------------
// Gauges
// ---------------------------------------------------------------------------
auto render_gauge = [&shift](int delta) {
float progress = (shift + delta) % 1000 / 1000.f;
float progress = (shift + delta) % 500 / 500.f;
return hbox({
text(std::to_string(int(progress * 100)) + "% ") |
size(WIDTH, EQUAL, 5),
@@ -331,25 +388,24 @@ int main(int argc, const char* argv[]) {
auto gauge_component = Renderer([render_gauge] {
return vbox({
render_gauge(0) | color(Color::Black),
render_gauge(100) | color(Color::GrayDark),
render_gauge(50) | color(Color::GrayLight),
render_gauge(6894) | color(Color::White),
separator(),
render_gauge(6841) | color(Color::Blue),
render_gauge(9813) | color(Color::BlueLight),
render_gauge(98765) | color(Color::Cyan),
render_gauge(98) | color(Color::CyanLight),
render_gauge(9846) | color(Color::Green),
render_gauge(1122) | color(Color::GreenLight),
render_gauge(84) | color(Color::Magenta),
render_gauge(645) | color(Color::MagentaLight),
render_gauge(568) | color(Color::Red),
render_gauge(2222) | color(Color::RedLight),
render_gauge(220) | color(Color::Yellow),
render_gauge(348) | color(Color::YellowLight),
}) |
border;
render_gauge(0) | color(Color::Black),
render_gauge(100) | color(Color::GrayDark),
render_gauge(50) | color(Color::GrayLight),
render_gauge(6894) | color(Color::White),
separator(),
render_gauge(6841) | color(Color::Blue),
render_gauge(9813) | color(Color::BlueLight),
render_gauge(98765) | color(Color::Cyan),
render_gauge(98) | color(Color::CyanLight),
render_gauge(9846) | color(Color::Green),
render_gauge(1122) | color(Color::GreenLight),
render_gauge(84) | color(Color::Magenta),
render_gauge(645) | color(Color::MagentaLight),
render_gauge(568) | color(Color::Red),
render_gauge(2222) | color(Color::RedLight),
render_gauge(220) | color(Color::Yellow),
render_gauge(348) | color(Color::YellowLight),
});
});
// ---------------------------------------------------------------------------
@@ -363,48 +419,36 @@ int main(int argc, const char* argv[]) {
};
auto paragraph_renderer_left = Renderer([&] {
auto title_style = bold | bgcolor(Color::Blue) | color(Color::Black);
std::string str =
"Lorem Ipsum is simply dummy text of the printing and typesetting "
"industry. Lorem Ipsum has been the industry's standard dummy text "
"ever since the 1500s, when an unknown printer took a galley of type "
"and scrambled it to make a type specimen book.";
return vbox({
// [ Left ]
text("Align left:") | title_style,
paragraphAlignLeft(str),
// [ Center ]
text("Align center:") | title_style,
paragraphAlignCenter(str),
// [ Right ]
text("Align right:") | title_style,
paragraphAlignRight(str),
// [ Justify]
text("Align justify:") | title_style,
paragraphAlignJustify(str),
// [ Side by side ]
text("Side by side:") | title_style,
hbox({
paragraph(str),
separator() | color(Color::Blue),
paragraph(str),
}),
// [ Misc ]
text("Elements with different size:") | title_style,
flexbox({
make_box(10, 5),
make_box(9, 4),
make_box(8, 4),
make_box(6, 3),
make_box(10, 5),
make_box(9, 4),
make_box(8, 4),
make_box(6, 3),
make_box(10, 5),
make_box(9, 4),
make_box(8, 4),
make_box(6, 3),
}),
window(text("Align left:"), paragraphAlignLeft(str)),
window(text("Align center:"), paragraphAlignCenter(str)),
window(text("Align right:"), paragraphAlignRight(str)),
window(text("Align justify:"), paragraphAlignJustify(str)),
window(text("Side by side"), hbox({
paragraph(str),
separator(),
paragraph(str),
})),
window(text("Elements with different size:"),
flexbox({
make_box(10, 5),
make_box(9, 4),
make_box(8, 4),
make_box(6, 3),
make_box(10, 5),
make_box(9, 4),
make_box(8, 4),
make_box(6, 3),
make_box(10, 5),
make_box(9, 4),
make_box(8, 4),
make_box(6, 3),
})),
}) |
vscroll_indicator | yframe | flex;
});
@@ -420,7 +464,7 @@ int main(int argc, const char* argv[]) {
&paragraph_renderer_split_position);
auto paragraph_renderer_group_renderer =
Renderer(paragraph_renderer_group,
[&] { return paragraph_renderer_group->Render() | border; });
[&] { return paragraph_renderer_group->Render(); });
// ---------------------------------------------------------------------------
// Tabs
@@ -430,7 +474,8 @@ int main(int argc, const char* argv[]) {
std::vector<std::string> tab_entries = {
"htop", "color", "spinner", "gauge", "compiler", "paragraph",
};
auto tab_selection = Toggle(&tab_entries, &tab_index);
auto tab_selection =
Menu(&tab_entries, &tab_index, MenuOption::HorizontalAnimated());
auto tab_content = Container::Tab(
{
htop,
@@ -450,18 +495,23 @@ int main(int argc, const char* argv[]) {
auto main_renderer = Renderer(main_container, [&] {
return vbox({
text("FTXUI Demo") | bold | hcenter,
tab_selection->Render() | hcenter,
tab_selection->Render(),
tab_content->Render() | flex,
});
});
bool refresh_ui_continue = true;
std::atomic<bool> refresh_ui_continue = true;
std::thread refresh_ui([&] {
while (refresh_ui_continue) {
using namespace std::chrono_literals;
std::this_thread::sleep_for(0.05s);
shift++;
screen.PostEvent(Event::Custom);
// The |shift| variable belong to the main thread. `screen.Post(task)`
// will execute the update on the thread where |screen| lives (e.g. the
// main thread). Using `screen.Post(task)` is threadsafe.
screen.Post([&] { shift++; });
// After updating the state, request a new frame to be drawn. This is done
// by simulating a new "custom" event to be handled.
screen.Post(Event::Custom);
}
});

View File

@@ -1,17 +1,14 @@
#include <memory> // for shared_ptr, __shared_ptr_access
#include <string> // for string, basic_string, allocator
#include <string> // for string, allocator, basic_string
#include <vector> // for vector
#include "ftxui/component/captured_mouse.hpp" // for ftxui
#include "ftxui/component/component.hpp" // for Checkbox, Maybe, Radiobox, Renderer, Vertical
#include "ftxui/component/component_base.hpp" // for ComponentBase
#include "ftxui/component/screen_interactive.hpp" // for Component, ScreenInteractive
#include "ftxui/dom/elements.hpp" // for Element, operator|, border
#include "ftxui/component/component.hpp" // for operator|, Maybe, Checkbox, Radiobox, Renderer, Vertical
#include "ftxui/component/component_base.hpp" // for Component
#include "ftxui/component/screen_interactive.hpp" // for ScreenInteractive
#include "ftxui/dom/elements.hpp" // for Element, border, color, operator|, text
#include "ftxui/screen/color.hpp" // for Color, Color::Red
using namespace ftxui;
Component Border(Component child) {
return Renderer(child, [child] { return child->Render() | border; });
}
int main(int argc, const char* argv[]) {
std::vector<std::string> entries = {
@@ -21,20 +18,19 @@ int main(int argc, const char* argv[]) {
};
int menu_1_selected = 0;
int menu_2_selected = 0;
auto menu_1 = Radiobox(&entries, &menu_1_selected);
auto menu_2 = Radiobox(&entries, &menu_2_selected);
menu_1 = Border(menu_1);
menu_2 = Border(menu_2);
bool menu_1_show = false;
bool menu_2_show = false;
auto layout = Container::Vertical({
Checkbox("Show menu_1", &menu_1_show),
Maybe(menu_1, &menu_1_show),
Radiobox(&entries, &menu_1_selected) | border | Maybe(&menu_1_show),
Checkbox("Show menu_2", &menu_2_show),
Maybe(menu_2, &menu_2_show),
Radiobox(&entries, &menu_2_selected) | border | Maybe(&menu_2_show),
Renderer([] {
return text("You found the secret combinaison!") | color(Color::Red);
}) | Maybe([&] { return menu_1_selected == 1 && menu_2_selected == 2; }),
});
auto screen = ScreenInteractive::TerminalOutput();

View File

@@ -1,25 +1,31 @@
#include <functional> // for function
#include <iostream> // for basic_ostream::operator<<, operator<<, endl, basic_ostream, basic_ostream<>::__ostream_type, cout, ostream
#include <memory> // for shared_ptr, __shared_ptr_access
#include <string> // for to_string, allocator
#include <memory> // for allocator, shared_ptr, __shared_ptr_access
#include <string> // for char_traits, to_string, operator+, string, basic_string
#include "ftxui/component/captured_mouse.hpp" // for ftxui
#include "ftxui/component/component.hpp" // for MenuEntry, Renderer, Vertical
#include "ftxui/component/component_base.hpp" // for ComponentBase
#include "ftxui/component/component_options.hpp" // for MenuEntryOption
#include "ftxui/component/screen_interactive.hpp" // for ScreenInteractive
#include "ftxui/dom/elements.hpp" // for operator|, separator, Element, Decorator, color, text, hbox, size, bold, frame, inverted, vbox, HEIGHT, LESS_THAN, border
#include "ftxui/dom/elements.hpp" // for operator|, Element, separator, text, hbox, size, frame, color, vbox, HEIGHT, LESS_THAN, bold, border, inverted
#include "ftxui/screen/color.hpp" // for Color, Color::Blue, Color::Cyan, Color::Green, Color::Red, Color::Yellow
using namespace ftxui;
// Define a special style for some menu entry.
MenuEntryOption Colored(ftxui::Color c) {
MenuEntryOption special_style;
special_style.style_normal = Decorator(color(c));
special_style.style_focused = Decorator(color(c)) | inverted;
special_style.style_selected = Decorator(color(c)) | bold;
special_style.style_selected_focused = Decorator(color(c)) | inverted | bold;
return special_style;
MenuEntryOption option;
option.transform = [c](EntryState state) {
state.label = (state.active ? "> " : " ") + state.label;
Element e = text(state.label) | color(c);
if (state.focused)
e = e | inverted;
if (state.active)
e = e | bold;
return e;
};
return option;
}
int main(int argc, const char* argv[]) {

View File

@@ -0,0 +1,66 @@
#include <iostream> // for basic_ostream::operator<<, operator<<, endl, basic_ostream, basic_ostream<>::__ostream_type, cout, ostream
#include <memory> // for shared_ptr, __shared_ptr_access
#include <string> // for to_string, allocator
#include "ftxui/component/captured_mouse.hpp" // for ftxui
#include "ftxui/component/component.hpp" // for MenuEntryAnimated, Renderer, Vertical
#include "ftxui/component/component_base.hpp" // for ComponentBase
#include "ftxui/component/component_options.hpp" // for MenuEntryAnimated
#include "ftxui/component/screen_interactive.hpp" // for ScreenInteractive
#include "ftxui/dom/elements.hpp" // for operator|, separator, Element, Decorator, color, text, hbox, size, bold, frame, inverted, vbox, HEIGHT, LESS_THAN, border
#include "ftxui/screen/color.hpp" // for Color, Color::Blue, Color::Cyan, Color::Green, Color::Red, Color::Yellow
using namespace ftxui;
// Define a special style for some menu entry.
MenuEntryOption Colored(ftxui::Color c) {
MenuEntryOption option;
option.animated_colors.foreground.enabled = true;
option.animated_colors.background.enabled = true;
option.animated_colors.background.active = c;
option.animated_colors.background.inactive = Color::Black;
option.animated_colors.foreground.active = Color::White;
option.animated_colors.foreground.inactive = c;
return option;
}
int main(int argc, const char* argv[]) {
auto screen = ScreenInteractive::TerminalOutput();
int selected = 0;
auto menu = Container::Vertical(
{
MenuEntry(" 1. rear", Colored(Color::Red)),
MenuEntry(" 2. drown", Colored(Color::Yellow)),
MenuEntry(" 3. nail", Colored(Color::Green)),
MenuEntry(" 4. quit", Colored(Color::Cyan)),
MenuEntry(" 5. decorative", Colored(Color::Blue)),
MenuEntry(" 7. costume"),
MenuEntry(" 8. pick"),
MenuEntry(" 9. oral"),
MenuEntry("11. minister"),
MenuEntry("12. football"),
MenuEntry("13. welcome"),
MenuEntry("14. copper"),
MenuEntry("15. inhabitant"),
},
&selected);
// Display together the menu with a border
auto renderer = Renderer(menu, [&] {
return vbox({
hbox(text("selected = "), text(std::to_string(selected))),
separator(),
menu->Render() | frame,
}) |
border | bgcolor(Color::Black);
});
screen.Loop(renderer);
std::cout << "Selected element = " << selected << std::endl;
}
// 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.

View File

@@ -1,100 +1,258 @@
#include <array> // for array
#include <chrono> // for milliseconds
#include <functional> // for function
#include <memory> // for shared_ptr, __shared_ptr_access, allocator
#include <string> // for string, basic_string
#include <memory> // for __shared_ptr_access, shared_ptr, allocator
#include <string> // for string, char_traits, operator+, basic_string
#include <vector> // for vector
#include "ftxui/component/captured_mouse.hpp" // for ftxui
#include "ftxui/component/component.hpp" // for Menu, Horizontal, Renderer
#include "ftxui/component/component_base.hpp" // for ComponentBase
#include "ftxui/component/component_options.hpp" // for MenuOption
#include "ftxui/component/screen_interactive.hpp" // for ScreenInteractive
#include "ftxui/dom/elements.hpp" // for operator|, color, separator, Decorator, bgcolor, flex, Element, bold, hbox, border, dim
#include "ftxui/screen/color.hpp" // for Color, Color::Blue, Color::BlueLight, Color::Red, Color::Yellow
#include "ftxui/component/animation.hpp" // for ElasticOut, Linear
#include "ftxui/component/component.hpp" // for Menu, Horizontal, Renderer, Vertical
#include "ftxui/component/component_base.hpp" // for ComponentBase
#include "ftxui/component/component_options.hpp" // for MenuOption, EntryState, MenuEntryOption, AnimatedColorOption, AnimatedColorsOption, UnderlineOption
#include "ftxui/component/mouse.hpp" // for ftxui
#include "ftxui/component/screen_interactive.hpp" // for Component, ScreenInteractive
#include "ftxui/dom/elements.hpp" // for separator, operator|, Element, text, bgcolor, hbox, bold, color, filler, border, vbox, borderDouble, dim, flex, hcenter
#include "ftxui/screen/color.hpp" // for Color, Color::Red, Color::Black, Color::Yellow, Color::Blue, Color::Default, Color::White
using namespace ftxui;
Component VMenu1(std::vector<std::string>* entries, int* selected);
Component VMenu2(std::vector<std::string>* entries, int* selected);
Component VMenu3(std::vector<std::string>* entries, int* selected);
Component VMenu4(std::vector<std::string>* entries, int* selected);
Component VMenu5(std::vector<std::string>* entries, int* selected);
Component VMenu6(std::vector<std::string>* entries, int* selected);
Component VMenu7(std::vector<std::string>* entries, int* selected);
Component VMenu8(std::vector<std::string>* entries, int* selected);
Component HMenu1(std::vector<std::string>* entries, int* selected);
Component HMenu2(std::vector<std::string>* entries, int* selected);
Component HMenu3(std::vector<std::string>* entries, int* selected);
Component HMenu4(std::vector<std::string>* entries, int* selected);
Component HMenu5(std::vector<std::string>* entries, int* selected);
int main(int argc, const char* argv[]) {
using namespace ftxui;
auto screen = ScreenInteractive::TerminalOutput();
std::vector<std::string> entries = {
"Monkey", "Dog", "Cat", "Bird", "Elephant",
std::vector<std::string> entries{
"Monkey", "Dog", "Cat", "Bird", "Elephant", "Cat",
};
int menu_1_selected_ = 0;
int menu_2_selected_ = 0;
int menu_3_selected_ = 0;
int menu_4_selected_ = 0;
int menu_5_selected_ = 0;
int menu_6_selected_ = 0;
std::array<int, 12> selected = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
MenuOption option_1;
option_1.style_focused = bold | color(Color::Blue);
option_1.style_selected = color(Color::Blue);
option_1.style_selected_focused = bold | color(Color::Blue);
option_1.on_enter = screen.ExitLoopClosure();
auto menu_1_ = Menu(&entries, &menu_1_selected_, &option_1);
auto vmenu_1_ = VMenu1(&entries, &selected[0]);
auto vmenu_2_ = VMenu2(&entries, &selected[1]);
auto vmenu_3_ = VMenu3(&entries, &selected[2]);
auto vmenu_4_ = VMenu4(&entries, &selected[3]);
auto vmenu_5_ = VMenu5(&entries, &selected[4]);
auto vmenu_6_ = VMenu6(&entries, &selected[5]);
auto vmenu_7_ = VMenu7(&entries, &selected[6]);
auto vmenu_8_ = VMenu8(&entries, &selected[7]);
MenuOption option_2;
option_2.style_focused = bold | color(Color::Blue);
option_2.style_selected = color(Color::Blue);
option_2.style_selected_focused = bold | color(Color::Blue);
option_2.on_enter = screen.ExitLoopClosure();
auto menu_2_ = Menu(&entries, &menu_2_selected_, &option_2);
auto hmenu_1_ = HMenu1(&entries, &selected[8]);
auto hmenu_2_ = HMenu2(&entries, &selected[9]);
auto hmenu_3_ = HMenu3(&entries, &selected[10]);
auto hmenu_4_ = HMenu4(&entries, &selected[11]);
auto hmenu_5_ = HMenu5(&entries, &selected[12]);
MenuOption option_3;
option_3.style_selected = color(Color::Blue);
option_3.style_focused = bgcolor(Color::Blue);
option_3.style_selected_focused = bgcolor(Color::Blue);
option_3.on_enter = screen.ExitLoopClosure();
auto menu_3_ = Menu(&entries, &menu_3_selected_, &option_3);
MenuOption option_4;
option_4.style_selected = bgcolor(Color::Blue);
option_4.style_focused = bgcolor(Color::BlueLight);
option_4.style_selected_focused = bgcolor(Color::BlueLight);
option_4.on_enter = screen.ExitLoopClosure();
auto menu_4_ = Menu(&entries, &menu_4_selected_, &option_4);
MenuOption option_5;
option_5.style_normal = bgcolor(Color::Blue);
option_5.style_selected = bgcolor(Color::Yellow);
option_5.style_focused = bgcolor(Color::Red);
option_5.style_selected_focused = bgcolor(Color::Red);
option_5.on_enter = screen.ExitLoopClosure();
auto menu_5_ = Menu(&entries, &menu_5_selected_, &option_5);
MenuOption option_6;
option_6.style_normal = dim | color(Color::Blue);
option_6.style_selected = color(Color::Blue);
option_6.style_focused = bold | color(Color::Blue);
option_6.style_selected_focused = bold | color(Color::Blue);
option_6.on_enter = screen.ExitLoopClosure();
auto menu_6_ = Menu(&entries, &menu_6_selected_, &option_6);
auto container = Container::Horizontal({
menu_1_,
menu_2_,
menu_3_,
menu_4_,
menu_5_,
menu_6_,
auto container = Container::Vertical({
Container::Horizontal({
vmenu_1_,
vmenu_2_,
vmenu_3_,
vmenu_4_,
vmenu_5_,
vmenu_6_,
vmenu_7_,
vmenu_8_,
}),
hmenu_1_,
hmenu_2_,
hmenu_3_,
hmenu_4_,
hmenu_5_,
});
// clang-format off
auto renderer = Renderer(container, [&] {
return
hbox({
menu_1_->Render() | flex, separator(),
menu_2_->Render() | flex, separator(),
menu_3_->Render() | flex, separator(),
menu_4_->Render() | flex, separator(),
menu_5_->Render() | flex, separator(),
menu_6_->Render() | flex,
}) | border;
return //
hbox({
vbox({
hbox({
vmenu_1_->Render(),
separator(),
vmenu_2_->Render(),
separator(),
vmenu_3_->Render(),
separator(),
vmenu_4_->Render(),
separator(),
vmenu_5_->Render(),
vmenu_6_->Render(),
separator(),
vmenu_7_->Render(),
separator(),
vmenu_8_->Render(),
}),
separator(),
hmenu_1_->Render(),
separator(),
hmenu_2_->Render(),
separator(),
hmenu_3_->Render(),
separator(),
hmenu_4_->Render(),
hmenu_5_->Render(),
}) | border,
filler(),
});
});
// clang-format on
screen.Loop(renderer);
}
Component VMenu1(std::vector<std::string>* entries, int* selected) {
auto option = MenuOption::Vertical();
option.entries.transform = [](EntryState state) {
state.label = (state.active ? "> " : " ") + state.label;
Element e = text(state.label);
if (state.focused)
e = e | bgcolor(Color::Blue);
if (state.active)
e = e | bold;
return e;
};
return Menu(entries, selected, option);
}
Component VMenu2(std::vector<std::string>* entries, int* selected) {
auto option = MenuOption::Vertical();
option.entries.transform = [](EntryState state) {
state.label += (state.active ? " <" : " ");
Element e = hbox(filler(), text(state.label));
if (state.focused)
e = e | bgcolor(Color::Red);
if (state.active)
e = e | bold;
return e;
};
return Menu(entries, selected, option);
}
Component VMenu3(std::vector<std::string>* entries, int* selected) {
auto option = MenuOption::Vertical();
option.entries.transform = [](EntryState state) {
Element e = state.active ? text("[" + state.label + "]")
: text(" " + state.label + " ");
if (state.focused)
e = e | bold;
if (state.focused)
e = e | color(Color::Blue);
if (state.active)
e = e | bold;
return e;
};
return Menu(entries, selected, option);
}
Component VMenu4(std::vector<std::string>* entries, int* selected) {
auto option = MenuOption::Vertical();
option.entries.transform = [](EntryState state) {
if (state.active && state.focused) {
return text(state.label) | color(Color::Yellow) | bgcolor(Color::Black) |
bold;
}
if (state.active) {
return text(state.label) | color(Color::Yellow) | bgcolor(Color::Black);
}
if (state.focused) {
return text(state.label) | color(Color::Black) | bgcolor(Color::Yellow) |
bold;
}
return text(state.label) | color(Color::Black) | bgcolor(Color::Yellow);
};
return Menu(entries, selected, option);
}
Component VMenu5(std::vector<std::string>* entries, int* selected) {
auto option = MenuOption::Vertical();
option.entries.transform = [](EntryState state) {
auto element = text(state.label);
if (state.active && state.focused) {
return element | borderDouble;
}
if (state.active) {
return element | border;
}
if (state.focused) {
return element | bold;
}
return element;
};
return Menu(entries, selected, option);
}
Component VMenu6(std::vector<std::string>* entries, int* selected) {
auto option = MenuOption::VerticalAnimated();
option.underline.color_inactive = Color::Default;
option.underline.color_active = Color::Red;
option.underline.SetAnimationFunction(animation::easing::Linear);
return Menu(entries, selected, option);
}
Component VMenu7(std::vector<std::string>* entries, int* selected) {
auto option = MenuOption::Vertical();
option.entries.animated_colors.foreground.enabled = true;
option.entries.animated_colors.background.enabled = true;
option.entries.animated_colors.background.active = Color::Red;
option.entries.animated_colors.background.inactive = Color::Black;
option.entries.animated_colors.foreground.active = Color::White;
option.entries.animated_colors.foreground.inactive = Color::Red;
return Menu(entries, selected, option);
}
Component VMenu8(std::vector<std::string>* entries, int* selected) {
auto option = MenuOption::Vertical();
option.entries.animated_colors.foreground.Set(Color::Red, Color::White,
std::chrono::milliseconds(500));
return Menu(entries, selected, option);
}
Component HMenu1(std::vector<std::string>* entries, int* selected) {
return Menu(entries, selected, MenuOption::Horizontal());
}
Component HMenu2(std::vector<std::string>* entries, int* selected) {
return Menu(entries, selected, MenuOption::Toggle());
}
Component HMenu3(std::vector<std::string>* entries, int* selected) {
auto option = MenuOption::Toggle();
option.elements_infix = [] { return text(" 🮣🮠 "); };
return Menu(entries, selected, option);
}
Component HMenu4(std::vector<std::string>* entries, int* selected) {
return Menu(entries, selected, MenuOption::HorizontalAnimated());
}
Component HMenu5(std::vector<std::string>* entries, int* selected) {
auto option = MenuOption::HorizontalAnimated();
option.underline.SetAnimation(std::chrono::milliseconds(1500),
animation::easing::ElasticOut);
option.entries.transform = [](EntryState state) {
Element e = text(state.label) | hcenter | flex;
if (state.active && state.focused)
e = e | bold;
if (!state.focused && !state.active)
e = e | dim;
return e;
};
option.underline.color_inactive = Color::Default;
option.underline.color_active = Color::Red;
return Menu(entries, selected, option);
}
// 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.

View File

@@ -0,0 +1,94 @@
#include <chrono> // for operator""ms, literals
#include <memory> // for allocator, shared_ptr, __shared_ptr_access
#include <string> // for string, operator+, to_string, basic_string
#include <vector> // for vector
#include "ftxui/component/animation.hpp" // for BackOut, Duration
#include "ftxui/component/component.hpp" // for Menu, Renderer, Vertical
#include "ftxui/component/component_base.hpp" // for ComponentBase
#include "ftxui/component/component_options.hpp" // for MenuOption, UnderlineOption
#include "ftxui/component/mouse.hpp" // for ftxui
#include "ftxui/component/screen_interactive.hpp" // for Component, ScreenInteractive
#include "ftxui/dom/elements.hpp" // for text, Element, operator|, borderEmpty, inverted
#include "ftxui/screen/color.hpp" // for Color, Color::Blue, Color::Red
using namespace ftxui;
Component DummyComponent(int id) {
return Renderer([id](bool focused) {
auto t = text("component " + std::to_string(id));
if (focused)
t = t | inverted;
return t;
});
}
Component Text(const std::string& t) {
return Renderer([t] { return text(t) | borderEmpty; });
}
int main(int argc, const char* argv[]) {
using namespace std::literals;
std::vector<std::string> tab_values{
"Tab 1", "Tab 2", "Tab 3", "A very very long tab", "",
};
int tab_selected = 0;
auto container = Container::Vertical({});
int frame_count = 0;
container->Add(Renderer(
[&] { return text("Frame count: " + std::to_string(frame_count++)); }));
{
auto option = MenuOption::HorizontalAnimated();
container->Add(Text("This demonstrate the Menu component"));
container->Add(Menu(&tab_values, &tab_selected, option));
}
{
container->Add(Text("Set underline color to blue"));
auto option = MenuOption::HorizontalAnimated();
option.underline.color_inactive = Color::Blue;
container->Add(Menu(&tab_values, &tab_selected, option));
}
{
container->Add(Text("Set underline active color to red"));
auto option = MenuOption::HorizontalAnimated();
option.underline.color_active = Color::Red;
container->Add(Menu(&tab_values, &tab_selected, option));
}
{
container->Add(Text("Set animation duration to 0ms"));
auto option = MenuOption::HorizontalAnimated();
option.underline.SetAnimationDuration(0ms);
container->Add(Menu(&tab_values, &tab_selected, option));
}
{
container->Add(Text("Set animation easing function to back-out"));
auto option = MenuOption::HorizontalAnimated();
option.underline.SetAnimationFunction(animation::easing::BackOut);
option.underline.SetAnimationDuration(350ms);
container->Add(Menu(&tab_values, &tab_selected, option));
}
// option.underline_animation_follower_delay = 250ms
{
container->Add(Text("Add delay to desynchronize animation"));
auto option = MenuOption::HorizontalAnimated();
option.underline.follower_delay = 250ms;
container->Add(Menu(&tab_values, &tab_selected, option));
}
container->SetActiveChild(container->ChildAt(2));
auto screen = ScreenInteractive::TerminalOutput();
screen.Loop(container);
}
// 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.

View File

@@ -1,94 +1,83 @@
#include <memory> // for allocator, shared_ptr, __shared_ptr_access
#include <string> // for string, basic_string, char_traits, operator+
#include <vector> // for vector
#include <ftxui/component/component_options.hpp> // for ButtonOption
#include <ftxui/component/mouse.hpp> // for ftxui
#include <functional> // for function
#include <memory> // for allocator, shared_ptr
#include "ftxui/component/captured_mouse.hpp" // for ftxui
#include "ftxui/component/component.hpp" // for Button, Renderer, Horizontal, Tab
#include "ftxui/component/component_base.hpp" // for ComponentBase
#include "ftxui/component/screen_interactive.hpp" // for ScreenInteractive
#include "ftxui/dom/elements.hpp" // for operator|, Element, filler, text, hbox, separator, center, vbox, bold, border, clear_under, dbox, size, GREATER_THAN, HEIGHT
#include "ftxui/component/component.hpp" // for Button, operator|=, Renderer, Vertical, Modal
#include "ftxui/component/screen_interactive.hpp" // for ScreenInteractive, Component
#include "ftxui/dom/elements.hpp" // for operator|, separator, text, size, Element, vbox, border, GREATER_THAN, WIDTH, center, HEIGHT
using namespace ftxui;
auto button_style = ButtonOption::Animated();
// Definition of the main component. The details are not important.
Component MainComponent(std::function<void()> show_modal,
std::function<void()> exit) {
auto component = Container::Vertical({
Button("Show modal", show_modal, button_style),
Button("Quit", exit, button_style),
});
// Polish how the two buttons are rendered:
component |= Renderer([&](Element inner) {
return vbox({
text("Main component"),
separator(),
inner,
}) //
| size(WIDTH, GREATER_THAN, 15) //
| size(HEIGHT, GREATER_THAN, 15) //
| border //
| center; //
});
return component;
}
// Definition of the modal component. The details are not important.
Component ModalComponent(std::function<void()> do_nothing,
std::function<void()> hide_modal) {
auto component = Container::Vertical({
Button("Do nothing", do_nothing, button_style),
Button("Quit modal", hide_modal, button_style),
});
// Polish how the two buttons are rendered:
component |= Renderer([&](Element inner) {
return vbox({
text("Modal component "),
separator(),
inner,
}) //
| size(WIDTH, GREATER_THAN, 30) //
| border; //
});
return component;
}
int main(int argc, const char* argv[]) {
using namespace ftxui;
auto screen = ScreenInteractive::TerminalOutput();
// There are two layers. One at depth = 0 and the modal window at depth = 1;
int depth = 0;
// State of the application:
bool modal_shown = false;
// The current rating of FTXUI.
std::string rating = "3/5 stars";
// Some actions modifying the state:
auto show_modal = [&] { modal_shown = true; };
auto hide_modal = [&] { modal_shown = false; };
auto exit = screen.ExitLoopClosure();
auto do_nothing = [&] {};
// At depth=0, two buttons. One for rating FTXUI and one for quitting.
auto button_rate_ftxui = Button("Rate FTXUI", [&] { depth = 1; });
auto button_quit = Button("Quit", screen.ExitLoopClosure());
// Instanciate the main and modal components:
auto main_component = MainComponent(show_modal, exit);
auto modal_component = ModalComponent(do_nothing, hide_modal);
auto depth_0_container = Container::Horizontal({
button_rate_ftxui,
button_quit,
});
auto depth_0_renderer = Renderer(depth_0_container, [&] {
return vbox({
text("Modal dialog example"),
separator(),
text("☆☆☆ FTXUI:" + rating + " ☆☆☆") | bold,
filler(),
hbox({
button_rate_ftxui->Render(),
filler(),
button_quit->Render(),
}),
}) |
border | size(HEIGHT, GREATER_THAN, 18) | center;
});
// Use the `Modal` function to use together the main component and its modal
// window. The |modal_shown| boolean controls whether the modal is shown or
// not.
main_component |= Modal(modal_component, &modal_shown);
// At depth=1, The "modal" window.
std::vector<std::string> rating_labels = {
"1/5 stars", "2/5 stars", "3/5 stars", "4/5 stars", "5/5 stars",
};
auto on_rating = [&](std::string new_rating) {
rating = new_rating;
depth = 0;
};
auto depth_1_container = Container::Horizontal({
Button(&rating_labels[0], [&] { on_rating(rating_labels[0]); }),
Button(&rating_labels[1], [&] { on_rating(rating_labels[1]); }),
Button(&rating_labels[2], [&] { on_rating(rating_labels[2]); }),
Button(&rating_labels[3], [&] { on_rating(rating_labels[3]); }),
Button(&rating_labels[4], [&] { on_rating(rating_labels[4]); }),
});
auto depth_1_renderer = Renderer(depth_1_container, [&] {
return vbox({
text("Do you like FTXUI?"),
separator(),
hbox(depth_1_container->Render()),
}) |
border;
});
auto main_container = Container::Tab(
{
depth_0_renderer,
depth_1_renderer,
},
&depth);
auto main_renderer = Renderer(main_container, [&] {
Element document = depth_0_renderer->Render();
if (depth == 1) {
document = dbox({
document,
depth_1_renderer->Render() | clear_under | center,
});
}
return document;
});
screen.Loop(main_renderer);
screen.Loop(main_component);
return 0;
}
// Copyright 2020 Arthur Sonzogni. All rights reserved.
// Copyright 2022 Arthur Sonzogni. All rights reserved.
// Use of this source code is governed by the MIT license that can be found in
// the LICENSE file.

View File

@@ -0,0 +1,94 @@
#include <memory> // for allocator, shared_ptr, __shared_ptr_access
#include <string> // for string, basic_string, char_traits, operator+
#include <vector> // for vector
#include "ftxui/component/captured_mouse.hpp" // for ftxui
#include "ftxui/component/component.hpp" // for Button, Renderer, Horizontal, Tab
#include "ftxui/component/component_base.hpp" // for ComponentBase
#include "ftxui/component/screen_interactive.hpp" // for ScreenInteractive
#include "ftxui/dom/elements.hpp" // for operator|, Element, filler, text, hbox, separator, center, vbox, bold, border, clear_under, dbox, size, GREATER_THAN, HEIGHT
int main(int argc, const char* argv[]) {
using namespace ftxui;
auto screen = ScreenInteractive::TerminalOutput();
// There are two layers. One at depth = 0 and the modal window at depth = 1;
int depth = 0;
// The current rating of FTXUI.
std::string rating = "3/5 stars";
// At depth=0, two buttons. One for rating FTXUI and one for quitting.
auto button_rate_ftxui = Button("Rate FTXUI", [&] { depth = 1; });
auto button_quit = Button("Quit", screen.ExitLoopClosure());
auto depth_0_container = Container::Horizontal({
button_rate_ftxui,
button_quit,
});
auto depth_0_renderer = Renderer(depth_0_container, [&] {
return vbox({
text("Modal dialog example"),
separator(),
text("☆☆☆ FTXUI:" + rating + " ☆☆☆") | bold,
filler(),
hbox({
button_rate_ftxui->Render(),
filler(),
button_quit->Render(),
}),
}) |
border | size(HEIGHT, GREATER_THAN, 18) | center;
});
// At depth=1, The "modal" window.
std::vector<std::string> rating_labels = {
"1/5 stars", "2/5 stars", "3/5 stars", "4/5 stars", "5/5 stars",
};
auto on_rating = [&](std::string new_rating) {
rating = new_rating;
depth = 0;
};
auto depth_1_container = Container::Horizontal({
Button(&rating_labels[0], [&] { on_rating(rating_labels[0]); }),
Button(&rating_labels[1], [&] { on_rating(rating_labels[1]); }),
Button(&rating_labels[2], [&] { on_rating(rating_labels[2]); }),
Button(&rating_labels[3], [&] { on_rating(rating_labels[3]); }),
Button(&rating_labels[4], [&] { on_rating(rating_labels[4]); }),
});
auto depth_1_renderer = Renderer(depth_1_container, [&] {
return vbox({
text("Do you like FTXUI?"),
separator(),
hbox(depth_1_container->Render()),
}) |
border;
});
auto main_container = Container::Tab(
{
depth_0_renderer,
depth_1_renderer,
},
&depth);
auto main_renderer = Renderer(main_container, [&] {
Element document = depth_0_renderer->Render();
if (depth == 1) {
document = dbox({
document,
depth_1_renderer->Render() | clear_under | center,
});
}
return document;
});
screen.Loop(main_renderer);
return 0;
}
// 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.

View File

@@ -25,7 +25,7 @@ std::string Stringify(Event event) {
out = "(" + out + " ) -> ";
if (event.is_character()) {
out += "character(" + event.character() + ")";
out += "Event::Character(\"" + event.character() + "\")";
} else if (event.is_mouse()) {
out += "mouse";
switch (event.mouse().button) {
@@ -66,6 +66,68 @@ std::string Stringify(Event event) {
out += "(" + //
std::to_string(event.mouse().x) + "," +
std::to_string(event.mouse().y) + ")";
} else if (event == Event::ArrowLeft) {
out += "Event::ArrowLeft";
} else if (event == Event::ArrowRight) {
out += "Event::ArrowRight";
} else if (event == Event::ArrowUp) {
out += "Event::ArrowUp";
} else if (event == Event::ArrowDown) {
out += "Event::ArrowDown";
} else if (event == Event::ArrowLeftCtrl) {
out += "Event::ArrowLeftCtrl";
} else if (event == Event ::ArrowRightCtrl) {
out += "Event::ArrowRightCtrl";
} else if (event == Event::ArrowUpCtrl) {
out += "Event::ArrowUpCtrl";
} else if (event == Event::ArrowDownCtrl) {
out += "Event::ArrowDownCtrl";
} else if (event == Event::Backspace) {
out += "Event::Backspace";
} else if (event == Event::Delete) {
out += "Event::Delete";
} else if (event == Event::Escape) {
out += "Event::Escape";
} else if (event == Event::Return) {
out += "Event::Return";
} else if (event == Event::Tab) {
out += "Event::Tab";
} else if (event == Event::TabReverse) {
out += "Event::TabReverse";
} else if (event == Event::F1) {
out += "Event::F1";
} else if (event == Event::F2) {
out += "Event::F2";
} else if (event == Event::F3) {
out += "Event::F3";
} else if (event == Event::F4) {
out += "Event::F4";
} else if (event == Event::F5) {
out += "Event::F5";
} else if (event == Event::F6) {
out += "Event::F6";
} else if (event == Event::F7) {
out += "Event::F7";
} else if (event == Event::F8) {
out += "Event::F8";
} else if (event == Event::F9) {
out += "Event::F9";
} else if (event == Event::F10) {
out += "Event::F10";
} else if (event == Event::F11) {
out += "Event::F11";
} else if (event == Event::F12) {
out += "Event::F12";
} else if (event == Event::Home) {
out += "Event::Home";
} else if (event == Event::End) {
out += "Event::End";
} else if (event == Event::PageUp) {
out += "Event::PageUp";
} else if (event == Event::PageDown) {
out += "Event::PageDown";
} else if (event == Event::Custom) {
out += "Custom";
} else {
out += "(special)";
}
@@ -84,7 +146,7 @@ int main(int argc, const char* argv[]) {
return window(text("keys"), vbox(std::move(children)));
});
component = CatchEvent(component, [&](Event event) {
component |= CatchEvent([&](Event event) {
keys.push_back(event);
return true;
});

View File

@@ -0,0 +1,49 @@
#include <array> // for array
#include <cmath> // for sin
#include <ftxui/component/component_base.hpp> // for ComponentBase
#include <ftxui/component/component_options.hpp> // for SliderOption
#include <ftxui/dom/elements.hpp> // for size, GREATER_THAN, GaugeDirection, GaugeDirection::Up, HEIGHT
#include <ftxui/util/ref.hpp> // for ConstRef, Ref
#include <memory> // for shared_ptr, __shared_ptr_access
#include "ftxui/component/captured_mouse.hpp" // for ftxui
#include "ftxui/component/component.hpp" // for Horizontal, Slider, operator|=
#include "ftxui/component/screen_interactive.hpp" // for ScreenInteractive
using namespace ftxui;
int main(int argc, const char* argv[]) {
auto screen = ScreenInteractive::TerminalOutput();
std::array<int, 30> values;
for (int i = 0; i < values.size(); ++i) {
values[i] = 50 + 20 * std::sin(i * 0.3);
}
auto layout_horizontal = Container::Horizontal({});
for (int i = 0; i < values.size(); ++i) {
// In C++17:
SliderOption<int> option;
option.value = &values[i];
option.max = 100;
option.increment = 5;
option.direction = GaugeDirection::Up;
layout_horizontal->Add(Slider<int>(option));
/* In C++20:
layout_horizontal->Add(Slider<int>({
.value = &values[i],
.max = 100,
.increment = 5,
.direction = GaugeDirection::Up,
}));
*/
}
layout_horizontal |= size(HEIGHT, GREATER_THAN, 20);
screen.Loop(layout_horizontal);
}
// 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.

View File

@@ -1,5 +1,13 @@
#include "ftxui/component/component.hpp" // for Menu
#include <cstdlib> // for system, EXIT_SUCCESS
#include <iostream> // for operator<<, basic_ostream, basic_ostream::operator<<, cout, endl, flush, ostream, basic_ostream<>::__ostream_type, cin
#include <memory> // for shared_ptr, __shared_ptr_access, allocator
#include <string> // for getline, string
#include "ftxui/component/captured_mouse.hpp" // for ftxui
#include "ftxui/component/component.hpp" // for Button, Horizontal, Renderer
#include "ftxui/component/component_base.hpp" // for ComponentBase
#include "ftxui/component/screen_interactive.hpp" // for ScreenInteractive
#include "ftxui/dom/elements.hpp" // for operator|, filler, Element, borderEmpty, hbox, size, paragraph, vbox, LESS_THAN, border, center, HEIGHT, WIDTH
int main() {
using namespace ftxui;
@@ -10,14 +18,12 @@ int main() {
// temporarily uninstall the terminal hook and execute the provided callback
// function. This allow running the application in a non-interactive mode.
auto btn_run = Button("Execute with restored IO", screen.WithRestoredIO([] {
std::system("bash");
std::cout << "This is a child program using stdin/stdout." << std::endl;
for (int i = 0; i < 10; ++i) {
std::cout << "Please enter 10 strings (" << i << "/10)" << std::flush;
std::string input;
std::getline(std::cin, input);
}
std::system("bash");
}));
auto btn_quit = Button("Quit", screen.ExitLoopClosure());

View File

@@ -9,6 +9,7 @@ example(color_truecolor_RGB)
example(dbox)
example(canvas)
example(gauge)
example(gauge_direction)
example(graph)
example(gridbox)
example(hflow)
@@ -25,7 +26,9 @@ example(style_color)
example(style_dim)
example(style_gallery)
example(style_inverted)
example(style_strikethrough)
example(style_underlined)
example(style_underlined_double)
example(table)
example(vbox_hbox)
example(vflow)

View File

@@ -1,3 +1,4 @@
#include <stdlib.h> // for EXIT_SUCCESS
#include <ftxui/dom/elements.hpp> // for text, operator|, vbox, border, Element, Fit, hbox
#include <ftxui/screen/screen.hpp> // for Full, Screen
#include <memory> // for allocator
@@ -5,7 +6,7 @@
#include "ftxui/dom/node.hpp" // for Render
#include "ftxui/screen/color.hpp" // for ftxui
int main(int argc, const char* argv[]) {
int main() {
using namespace ftxui;
auto document = //
hbox({
@@ -30,6 +31,7 @@ int main(int argc, const char* argv[]) {
auto screen = Screen::Create(Dimension::Full(), Dimension::Fit(document));
Render(screen, document);
screen.Print();
return EXIT_SUCCESS;
}
// Copyright 2020 Arthur Sonzogni. All rights reserved.

View File

@@ -30,7 +30,7 @@ int main(int argc, const char* argv[]) {
// Plot a function:
std::vector<int> ys(100);
for (int x = 0; x < 100; x++)
ys[x] = 80 + 20 * cos(x * 0.2);
ys[x] = int(80 + 20 * cos(x * 0.2));
for (int x = 0; x < 99; x++)
c.DrawPointLine(x, ys[x], x + 1, ys[x + 1], Color::Red);

View File

@@ -5,13 +5,14 @@
#include <utility> // for move
#include <vector> // for vector
using namespace ftxui;
#include "./color_info_sorted_2d.ipp" // for ColorInfoSorted2D
#include "ftxui/dom/elements.hpp" // for text, bgcolor, color, vbox, hbox, separator, operator|, Elements, Element, Fit, border
#include "ftxui/dom/node.hpp" // for Render
#include "ftxui/screen/color.hpp" // for Color, Color::Black, Color::Blue, Color::BlueLight, Color::Cyan, Color::CyanLight, Color::Default, Color::GrayDark, Color::GrayLight, Color::Green, Color::GreenLight, Color::Magenta, Color::MagentaLight, Color::Red, Color::RedLight, Color::White, Color::Yellow, Color::YellowLight, Color::Palette256, ftxui
int main(int argc, const char* argv[]) {
using namespace ftxui;
#include "./color_info_sorted_2d.ipp" // for ColorInfoSorted2D
int main() {
// clang-format off
auto basic_color_display =
vbox(
@@ -82,14 +83,18 @@ int main(int argc, const char* argv[]) {
// True color display.
auto true_color_display = text("TrueColors: 24bits:");
{
int saturation = 255;
const int max_value = 255;
const int value_increment = 8;
const int hue_increment = 6;
int saturation = max_value;
Elements array;
for (int value = 0; value < 255; value += 16) {
for (int value = 0; value < max_value; value += 2 * value_increment) {
Elements line;
for (int hue = 0; hue < 255; hue += 6) {
line.push_back(text("") //
| color(Color::HSV(hue, saturation, value)) //
| bgcolor(Color::HSV(hue, saturation, value + 8)));
for (int hue = 0; hue < max_value; hue += hue_increment) {
line.push_back(
text("") //
| color(Color::HSV(hue, saturation, value)) //
| bgcolor(Color::HSV(hue, saturation, value + value_increment)));
}
array.push_back(hbox(std::move(line)));
}

View File

@@ -1,12 +1,13 @@
#include <cmath>
#include <algorithm>
#include <cmath>
#include <ftxui/screen/color_info.hpp> // for ftxui::ColorInfo
std::vector<std::vector<ColorInfo>> ColorInfoSorted2D() {
std::vector<std::vector<ftxui::ColorInfo>> ColorInfoSorted2D() {
// Acquire the color information for the palette256.
std::vector<ColorInfo> info_gray;
std::vector<ColorInfo> info_color;
std::vector<ftxui::ColorInfo> info_gray;
std::vector<ftxui::ColorInfo> info_color;
for (int i = 16; i < 256; ++i) {
ColorInfo info = GetColorInfo(Color::Palette256(i));
ftxui::ColorInfo info = GetColorInfo(ftxui::Color::Palette256(i));
if (info.saturation == 0)
info_gray.push_back(info);
else
@@ -16,10 +17,10 @@ std::vector<std::vector<ColorInfo>> ColorInfoSorted2D() {
// Sort info_color by hue.
std::sort(
info_color.begin(), info_color.end(),
[](const ColorInfo& A, const ColorInfo& B) { return A.hue < B.hue; });
[](const ftxui::ColorInfo& A, const ftxui::ColorInfo& B) { return A.hue < B.hue; });
// Make 8 colums, one gray and seven colored.
std::vector<std::vector<ColorInfo>> info_columns(8);
std::vector<std::vector<ftxui::ColorInfo>> info_columns(8);
info_columns[0] = info_gray;
for (size_t i = 0; i < info_color.size(); ++i) {
info_columns[1 + 7 * i / info_color.size()].push_back(info_color[i]);
@@ -28,13 +29,13 @@ std::vector<std::vector<ColorInfo>> ColorInfoSorted2D() {
// Minimize discontinuities for every columns.
for (auto& column : info_columns) {
std::sort(column.begin(), column.end(),
[](const ColorInfo& A, const ColorInfo& B) {
[](const ftxui::ColorInfo& A, const ftxui::ColorInfo& B) {
return A.value < B.value;
});
for (size_t i = 0; i < column.size() - 1; ++i) {
for (int i = 0; i < int(column.size()) - 1; ++i) {
int best_index = i + 1;
int best_distance = 255 * 255 * 3;
for (size_t j = i + 1; j < column.size(); ++j) {
for (int j = i + 1; j < column.size(); ++j) {
int dx = column[i].red - column[j].red;
int dy = column[i].green - column[j].green;
int dz = column[i].blue - column[j].blue;

View File

@@ -2,7 +2,7 @@
#include <ftxui/dom/elements.hpp> // for text, gauge, operator|, flex, hbox, Element
#include <ftxui/screen/screen.hpp> // for Screen
#include <iostream> // for cout, endl, ostream
#include <string> // for allocator, operator+, char_traits, operator<<, string, to_string, basic_string
#include <string> // for allocator, char_traits, operator+, operator<<, string, to_string, basic_string
#include <thread> // for sleep_for
#include "ftxui/dom/node.hpp" // for Render

View File

@@ -0,0 +1,79 @@
#include <chrono> // for operator""s, chrono_literals
#include <ftxui/dom/elements.hpp> // for filler, operator|, separator, text, border, Element, vbox, vtext, hbox, center, gaugeDown, gaugeLeft, gaugeRight, gaugeUp
#include <ftxui/screen/screen.hpp> // for Screen
#include <iostream> // for cout, endl, ostream
#include <string> // for allocator, operator+, operator<<, string, to_string
#include <thread> // for sleep_for
#include "ftxui/dom/node.hpp" // for Render
#include "ftxui/screen/color.hpp" // for ftxui
int main(int argc, const char* argv[]) {
using namespace ftxui;
using namespace std::chrono_literals;
std::string reset_position;
for (float percentage = 0.0f; percentage <= 1.0f; percentage += 0.002f) {
std::string data_downloaded =
std::to_string(int(percentage * 5000)) + "/5000";
auto gauge_up = //
hbox({
vtext("gauge vertical"),
separator(),
gaugeUp(percentage),
}) |
border;
auto gauge_down = //
hbox({
vtext("gauge vertical"),
separator(),
gaugeDown(percentage),
}) |
border;
auto gauge_right = //
vbox({
text("gauge horizontal"),
separator(),
gaugeRight(percentage),
}) |
border;
auto gauge_left = //
vbox({
text("gauge horizontal"),
separator(),
gaugeLeft(percentage),
}) |
border;
auto document = hbox({
gauge_up,
filler(),
vbox({
gauge_right,
filler(),
text(data_downloaded) | border | center,
filler(),
gauge_left,
}),
filler(),
gauge_down,
});
auto screen = Screen(32, 16);
Render(screen, document);
std::cout << reset_position;
screen.Print();
reset_position = screen.ResetPosition();
std::this_thread::sleep_for(0.01s);
}
std::cout << std::endl;
}
// Copyright 2022 Arthur Sonzogni. All rights reserved.
// Use of this source code is governed by the MIT license that can be found in
// the LICENSE file.

View File

@@ -1,9 +1,10 @@
#include <chrono> // for operator""s, chrono_literals
#include <cmath> // for sin
#include <ftxui/dom/elements.hpp> // for operator|, graph, separator, color, Element, vbox, flex, inverted, Fit, hbox, size, border, GREATER_THAN, HEIGHT
#include <ftxui/dom/elements.hpp> // for graph, operator|, separator, color, Element, vbox, flex, inverted, operator|=, Fit, hbox, size, border, GREATER_THAN, HEIGHT
#include <ftxui/screen/screen.hpp> // for Full, Screen
#include <functional> // for ref, reference_wrapper
#include <iostream> // for cout, ostream
#include <memory> // for shared_ptr
#include <string> // for operator<<, string
#include <thread> // for sleep_for
#include <vector> // for vector
@@ -13,15 +14,15 @@
class Graph {
public:
std::vector<int> operator()(int width, int height) {
std::vector<int> operator()(int width, int height) const {
std::vector<int> output(width);
for (int i = 0; i < width; ++i) {
float v = 0;
v += 0.1f * sin((i + shift) * 0.1f);
v += 0.2f * sin((i + shift + 10) * 0.15f);
v += 0.1f * sin((i + shift) * 0.03f);
v *= height;
v += 0.5f * height;
v += 0.1f * sin((i + shift) * 0.1f); // NOLINT
v += 0.2f * sin((i + shift + 10) * 0.15f); // NOLINT
v += 0.1f * sin((i + shift) * 0.03f); // NOLINT
v *= height; // NOLINT
v += 0.5f * height; // NOLINT
output[i] = static_cast<int>(v);
}
return output;
@@ -37,7 +38,7 @@ std::vector<int> triangle(int width, int height) {
return output;
}
int main(int argc, const char* argv[]) {
int main() {
using namespace ftxui;
using namespace std::chrono_literals;
@@ -45,23 +46,26 @@ int main(int argc, const char* argv[]) {
std::string reset_position;
for (int i = 0;; ++i) {
auto document =
hbox({
vbox({
graph(std::ref(my_graph)),
separator(),
graph(triangle) | inverted,
}) | flex,
auto document = hbox({
vbox({
graph(std::ref(my_graph)),
separator(),
vbox({
graph(std::ref(my_graph)) | color(Color::BlueLight),
separator(),
graph(std::ref(my_graph)) | color(Color::RedLight),
separator(),
graph(std::ref(my_graph)) | color(Color::YellowLight),
}) | flex,
}) |
border | size(HEIGHT, GREATER_THAN, 40);
graph(triangle) | inverted,
}) | flex,
separator(),
vbox({
graph(std::ref(my_graph)) | color(Color::BlueLight),
separator(),
graph(std::ref(my_graph)) | color(Color::RedLight),
separator(),
graph(std::ref(my_graph)) | color(Color::YellowLight),
}) | flex,
});
document |= border;
const int min_width = 40;
document |= size(HEIGHT, GREATER_THAN, min_width);
auto screen = Screen::Create(Dimension::Full(), Dimension::Fit(document));
Render(screen, document);
@@ -69,7 +73,8 @@ int main(int argc, const char* argv[]) {
screen.Print();
reset_position = screen.ResetPosition();
std::this_thread::sleep_for(0.03s);
const auto sleep_time = 0.03s;
std::this_thread::sleep_for(sleep_time);
my_graph.shift++;
}

View File

@@ -1,16 +1,14 @@
#include <stddef.h> // for size_t
#include <stdio.h> // for getchar
#include <ftxui/dom/elements.hpp> // for operator|, size, Element, text, hcenter, Decorator, Fit, WIDTH, hflow, window, EQUAL, GREATER_THAN, HEIGHT, bold, border, dim, LESS_THAN
#include <ftxui/screen/screen.hpp> // for Full, Screen
#include <memory> // for allocator, shared_ptr
#include <string> // for operator+, to_string, char_traits, string
#include <string> // for allocator, char_traits, operator+, to_string, string
#include "ftxui/dom/node.hpp" // for Render
#include "ftxui/screen/color.hpp" // for ftxui
int main(int argc, const char* argv[]) {
using namespace ftxui;
auto make_box = [](size_t dimx, size_t dimy) {
auto make_box = [](int dimx, int dimy) {
std::string title = std::to_string(dimx) + "x" + std::to_string(dimy);
return window(text(title) | hcenter | bold,
text("content") | hcenter | dim) |

View File

@@ -1,11 +1,10 @@
#include <chrono> // for operator""s, chrono_literals
#include <ftxui/screen/screen.hpp> // for Full, Screen
#include <ftxui/screen/screen.hpp> // for Screen
#include <iostream> // for cout, ostream
#include <memory> // for allocator, shared_ptr
#include <string> // for operator<<, string
#include <string> // for allocator, operator<<, string
#include <thread> // for sleep_for
#include "ftxui/dom/elements.hpp" // for paragraph, text, operator|, Element, border, color, hflow, spinner, vbox, bold, dim, underlined
#include "ftxui/dom/elements.hpp" // for paragraph, text, operator|, Element, border, Fit, color, hflow, spinner, vbox, bold, dim, underlined
#include "ftxui/dom/node.hpp" // for Render
#include "ftxui/screen/box.hpp" // for ftxui
#include "ftxui/screen/color.hpp" // for Color, Color::Red

View File

@@ -2,7 +2,7 @@
#include <ftxui/dom/elements.hpp> // for operator|, text, Element, hbox, bold, color, filler, separator, vbox, window, gauge, Fit, size, dim, EQUAL, WIDTH
#include <ftxui/screen/screen.hpp> // for Full, Screen
#include <iostream> // for cout, endl, ostream
#include <list> // for list, operator!=, _List_iterator, _List_iterator<>::_Self
#include <list> // for list, operator==, _List_iterator, _List_iterator<>::_Self
#include <memory> // for allocator, shared_ptr, allocator_traits<>::value_type
#include <string> // for string, operator<<, to_string
#include <thread> // for sleep_for
@@ -41,7 +41,7 @@ int main(int argc, const char* argv[]) {
int remaining_threads = 12;
int nb_queued = remaining_tasks.size();
int nb_queued = (int)remaining_tasks.size();
int nb_active = 0;
int nb_done = 0;

View File

@@ -17,7 +17,7 @@ int main(int argc, const char* argv[]) {
std::string reset_position;
for (int index = 0; index < 200; ++index) {
std::vector<Element> entries;
for (int i = 0; i < 22; ++i) {
for (int i = 0; i < 23; ++i) {
if (i != 0)
entries.push_back(separator());
entries.push_back( //

View File

@@ -10,14 +10,16 @@ int main(int argc, const char* argv[]) {
// clang-format off
auto document =
hbox({
text("normal") , text(" ") ,
text("bold") | bold , text(" ") ,
text("dim") | dim , text(" ") ,
text("inverted") | inverted , text(" ") ,
text("underlined")| underlined , text(" ") ,
text("blink") | blink , text(" ") ,
text("color") | color(Color::Blue) , text(" ") ,
text("bgcolor") | bgcolor(Color::Blue),
text("normal") , text(" ") ,
text("bold") | bold , text(" ") ,
text("dim") | dim , text(" ") ,
text("inverted") | inverted , text(" ") ,
text("underlined") | underlined , text(" ") ,
text("underlinedDouble") | underlinedDouble , text(" ") ,
text("blink") | blink , text(" ") ,
text("strikethrough") | strikethrough , text(" ") ,
text("color") | color(Color::Blue) , text(" ") ,
text("bgcolor") | bgcolor(Color::Blue) ,
});
// clang-format on
auto screen = Screen::Create(Dimension::Full(), Dimension::Fit(document));

View File

@@ -0,0 +1,25 @@
#include <ftxui/dom/elements.hpp> // for text, operator|, strikethrough, Fit, hbox, Element
#include <ftxui/screen/screen.hpp> // for Full, Screen
#include <memory> // for allocator
#include "ftxui/dom/node.hpp" // for Render
#include "ftxui/screen/color.hpp" // for ftxui
int main(int argc, const char* argv[]) {
using namespace ftxui;
auto document = //
hbox({
text("This text is "),
text("strikethrough") | strikethrough,
text(". Do you like it?"),
});
auto screen = Screen::Create(Dimension::Full(), Dimension::Fit(document));
Render(screen, document);
screen.Print();
return 0;
}
// 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.

View File

@@ -0,0 +1,25 @@
#include <ftxui/dom/elements.hpp> // for text, operator|, underlinedDouble, Fit, hbox, Element
#include <ftxui/screen/screen.hpp> // for Full, Screen
#include <memory> // for allocator
#include "ftxui/dom/node.hpp" // for Render
#include "ftxui/screen/color.hpp" // for ftxui
int main(int argc, const char* argv[]) {
using namespace ftxui;
auto document = //
hbox({
text("This text is "),
text("underlinedDouble") | underlinedDouble,
text(". Do you like it?"),
});
auto screen = Screen::Create(Dimension::Full(), Dimension::Fit(document));
Render(screen, document);
screen.Print();
return 0;
}
// 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.

View File

@@ -1,16 +1,14 @@
#include <stddef.h> // for size_t
#include <stdio.h> // for getchar
#include <ftxui/dom/elements.hpp> // for operator|, Element, size, text, hcenter, Fit, vflow, window, EQUAL, bold, border, dim, HEIGHT, WIDTH
#include <ftxui/screen/screen.hpp> // for Full, Screen
#include <memory> // for allocator, shared_ptr
#include <string> // for operator+, to_string, char_traits, string
#include <string> // for allocator, char_traits, operator+, to_string, string
#include "ftxui/dom/node.hpp" // for Render
#include "ftxui/screen/color.hpp" // for ftxui
int main(int argc, const char* argv[]) {
using namespace ftxui;
auto make_box = [](size_t dimx, size_t dimy) {
auto make_box = [](int dimx, int dimy) {
std::string title = std::to_string(dimx) + "x" + std::to_string(dimy);
return window(text(title) | hcenter | bold,
text("content") | hcenter | dim) |

View File

@@ -1,25 +1,32 @@
#include <ftxui/dom/elements.hpp> // for operator|, color, Element, bgcolor, graph, border
#include <stdlib.h> // for EXIT_SUCCESS
#include <ftxui/dom/elements.hpp> // for operator|=, Element, bgcolor, color, graph, border
#include <ftxui/screen/screen.hpp> // for Fixed, Screen
#include <vector> // for vector
#include "ftxui/dom/node.hpp" // for Render
#include "ftxui/screen/color.hpp" // for Color, Color::DarkBlue, Color::Green, Color::Red, ftxui
#include "ftxui/dom/node.hpp" // for Render
#include "ftxui/screen/color.hpp" // for Color, Color::DarkBlue, Color::Red, ftxui
int main(void) {
int main() {
using namespace ftxui;
Element document = graph([](int x, int y) {
std::vector<int> result(x, 0);
for (int i{0}; i < x; ++i) {
result[i] = ((3 * i) / 2) % y;
}
return result;
}) |
color(Color::Red) | border | color(Color::Green) |
bgcolor(Color::DarkBlue);
std::vector<int> result(x, 0);
for (int i{0}; i < x; ++i) {
result[i] = ((3 * i) / 2) % y;
}
return result;
});
auto screen = Screen::Create(Dimension::Fixed(80), Dimension::Fixed(10));
document |= color(Color::Red);
document |= bgcolor(Color::DarkBlue);
document |= border;
const int width = 80;
const int height = 10;
auto screen =
Screen::Create(Dimension::Fixed(width), Dimension::Fixed(height));
Render(screen, document);
screen.Print();
return EXIT_SUCCESS;
}
// Copyright 2020 Arthur Sonzogni. All rights reserved.

View File

@@ -2,8 +2,22 @@
<head>
<meta charset="utf-8">
<title>FTXUI examples WebAssembly</title>
<script src="https://cdn.jsdelivr.net/npm/xterm@4.11.0/lib/xterm.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/xterm@4.18.0/lib/xterm.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/xterm-addon-webgl@0.11.4/lib/xterm-addon-webgl.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/xterm-addon-fit@0.5.0/lib/xterm-addon-fit.min.js"></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/xterm@4.11.0/css/xterm.css"></link>
<!--Add COOP/COEP via a ServiceWorker to use SharedArrayBuffer-->
<script>
if ("serviceWorker" in navigator && !window.crossOriginIsolated) {
navigator.serviceWorker.register(new URL("./sw.js", location.href)).then(
registration => {
if (registration.active && !navigator.serviceWorker.controller) {
window.location.reload();
}
},
);
}
</script>
</head>
<body>
<script id="example_script"></script>
@@ -43,12 +57,12 @@
});
let stdin_buffer = [];
let stdin = () => {
const stdin = () => {
return stdin_buffer.shift() || 0;
}
stdout_buffer = [];
let stdout = code => {
let stdout_buffer = [];
const stdout = code => {
if (code == 0) {
term.write(new Uint8Array(stdout_buffer));
stdout_buffer = [];
@@ -56,20 +70,53 @@
stdout_buffer.push(code)
}
}
let stderr = code => console.log(code);
var term = new Terminal();
term.open(document.querySelector('#terminal'));
term.resize(140,43);
let stderrbuffer = [];
const stderr = code => {
if (code == 0 || code == 10) {
console.error(String.fromCodePoint(...stderrbuffer));
stderrbuffer = [];
} else {
stderrbuffer.push(code)
}
}
const term = new Terminal();
const term_element = document.querySelector('#terminal');
term.open(term_element);
const webgl_addon = new (WebglAddon.WebglAddon)();
term.loadAddon(webgl_addon);
const onBinary = e => {
for(c of e)
stdin_buffer.push(c.charCodeAt(0));
}
term.onBinary(onBinary);
term.onData(onBinary)
term.resize(140,43);
window.Module = {
preRun: () => { FS.init(stdin, stdout, stderr); },
preRun: () => {
FS.init(stdin, stdout, stderr);
},
postRun: [],
onRuntimeInitialized: () => {},
onRuntimeInitialized: () => {
if (window.Module._ftxui_on_resize == undefined)
return;
const fit_addon = new (FitAddon.FitAddon)();
term.loadAddon(fit_addon);
fit_addon.fit();
const resize_handler = () => {
const {cols, rows} = fit_addon.proposeDimensions();
term.resize(cols, rows);
window.Module._ftxui_on_resize(cols, rows);
};
const resize_observer = new ResizeObserver(resize_handler);
resize_observer.observe(term_element);
resize_handler();
// Disable scrollbar
term.write('\x1b[?47h')
},
};
const words = example.split('/')
@@ -78,6 +125,7 @@
</script>
<style>
body {
background-color:#EEE;
padding:20px;
@@ -112,9 +160,11 @@
}
#terminal {
padding:10px;
width:100%;
height: 500px;
height: calc(clamp(200px, 100vh - 300px, 900px));
overflow: hidden;
border:none;
background-color:black;
padding:auto;
}

25
examples/sw.js Normal file
View File

@@ -0,0 +1,25 @@
// sw.js
self.addEventListener("install", () => self.skipWaiting());
self.addEventListener("activate", e => e.waitUntil(self.clients.claim()));
self.addEventListener("fetch", e => {
if (e.request.mode != 'navigate' &&
!e.request.url.includes(".worker.js")) {
return;
}
e.respondWith((async () => {
const response = await fetch(e.request);
const newHeaders = new Headers(response.headers);
newHeaders.set("Cross-Origin-Embedder-Policy", "require-corp");
newHeaders.set("Cross-Origin-Opener-Policy", "same-origin");
const moddedResponse = new Response(response.body, {
status: response.status,
statusText: response.statusText,
headers: newHeaders,
});
return moddedResponse;
})());
});

View File

@@ -0,0 +1,119 @@
#ifndef FTXUI_ANIMATION_HPP
#define FTXUI_ANIMATION_HPP
#include <chrono> // for milliseconds, duration, steady_clock, time_point
#include <functional> // for function
#include "ftxui/component/event.hpp"
namespace ftxui {
namespace animation {
// Components who haven't completed their animation can call this function to
// request a new frame to be drawn later.
//
// When there is no new events and no animations to complete, no new frame is
// drawn.
void RequestAnimationFrame();
using Clock = std::chrono::steady_clock;
using TimePoint = std::chrono::time_point<Clock>;
using Duration = std::chrono::duration<double>;
// Parameter of Component::OnAnimation(param).
class Params {
public:
Params(Duration duration) : duration_(duration) {}
/// The duration this animation step represents.
Duration duration() const { return duration_; }
private:
Duration duration_;
};
namespace easing {
using Function = std::function<float(float)>;
// Linear interpolation (no easing)
float Linear(float p);
// Quadratic easing; p^2
float QuadraticIn(float p);
float QuadraticOut(float p);
float QuadraticInOut(float p);
// Cubic easing; p^3
float CubicIn(float p);
float CubicOut(float p);
float CubicInOut(float p);
// Quartic easing; p^4
float QuarticIn(float p);
float QuarticOut(float p);
float QuarticInOut(float p);
// Quintic easing; p^5
float QuinticIn(float p);
float QuinticOut(float p);
float QuinticInOut(float p);
// Sine wave easing; sin(p * PI/2)
float SineIn(float p);
float SineOut(float p);
float SineInOut(float p);
// Circular easing; sqrt(1 - p^2)
float CircularIn(float p);
float CircularOut(float p);
float CircularInOut(float p);
// Exponential easing, base 2
float ExponentialIn(float p);
float ExponentialOut(float p);
float ExponentialInOut(float p);
// Exponentially-damped sine wave easing
float ElasticIn(float p);
float ElasticOut(float p);
float ElasticInOut(float p);
// Overshooting cubic easing;
float BackIn(float p);
float BackOut(float p);
float BackInOut(float p);
// Exponentially-decaying bounce easing
float BounceIn(float p);
float BounceOut(float p);
float BounceInOut(float p);
} // namespace easing
class Animator {
public:
Animator(float* from,
float to = 0.f,
Duration duration = std::chrono::milliseconds(250),
easing::Function easing_function = easing::Linear,
Duration delay = std::chrono::milliseconds(0));
void OnAnimation(Params&);
float to() const { return to_; }
private:
float* value_;
float from_;
float to_;
Duration duration_;
easing::Function easing_function_;
Duration current_;
};
} // namespace animation
} // namespace ftxui
#endif /* end of include guard: FTXUI_ANIMATION_HPP */
// Copyright 2022 Arthur Sonzogni. All rights reserved.
// Use of this source code is governed by the MIT license that can be found in
// the LICENSE file.

View File

@@ -4,12 +4,13 @@
#include <functional> // for function
#include <memory> // for make_shared, shared_ptr
#include <string> // for wstring
#include <utility> // for forward
#include <vector> // for vector
#include "ftxui/component/component_base.hpp" // for Component, Components
#include "ftxui/component/component_options.hpp" // for ButtonOption, CheckboxOption, InputOption, MenuOption, RadioboxOption, ToggleOption
#include "ftxui/dom/elements.hpp" // for Element
#include "ftxui/util/ref.hpp" // for Ref, ConstStringRef, ConstStringListRef, StringRef
#include "ftxui/component/component_base.hpp" // for Component, Components
#include "ftxui/component/component_options.hpp" // for ButtonOption, CheckboxOption, MenuOption
#include "ftxui/dom/elements.hpp" // for Element
#include "ftxui/util/ref.hpp" // for ConstRef, Ref, ConstStringRef, ConstStringListRef, StringRef
namespace ftxui {
struct ButtonOption;
@@ -18,14 +19,21 @@ struct Event;
struct InputOption;
struct MenuOption;
struct RadioboxOption;
struct ToggleOption;
struct MenuEntryOption;
template <class T, class... Args>
std::shared_ptr<T> Make(Args&&... args) {
return std::make_shared<T>(args...);
return std::make_shared<T>(std::forward<Args>(args)...);
}
// Pipe operator to decorate components.
using ComponentDecorator = std::function<Component(Component)>;
using ElementDecorator = std::function<Element(Element)>;
Component operator|(Component component, ComponentDecorator decorator);
Component operator|(Component component, ElementDecorator decorator);
Component& operator|=(Component& component, ComponentDecorator decorator);
Component& operator|=(Component& component, ElementDecorator decorator);
namespace Container {
Component Vertical(Components children);
Component Vertical(Components children, int* selector);
@@ -37,43 +45,86 @@ Component Tab(Components children, int* selector);
Component Button(ConstStringRef label,
std::function<void()> on_click,
Ref<ButtonOption> = {});
Ref<ButtonOption> = ButtonOption::Simple());
Component Checkbox(ConstStringRef label,
bool* checked,
Ref<CheckboxOption> option = {});
Ref<CheckboxOption> option = CheckboxOption::Simple());
Component Input(StringRef content,
ConstStringRef placeholder,
Ref<InputOption> option = {});
Component Menu(ConstStringListRef entries,
int* selected_,
Ref<MenuOption> = {});
Ref<MenuOption> = MenuOption::Vertical());
Component MenuEntry(ConstStringRef label, Ref<MenuEntryOption> = {});
Component Dropdown(ConstStringListRef entries, int* selected);
Component Radiobox(ConstStringListRef entries,
int* selected_,
Ref<RadioboxOption> option = {});
Component Toggle(ConstStringListRef entries,
int* selected,
Ref<ToggleOption> option = {});
template <class T> // T = {int, float, long}
Component Slider(ConstStringRef label, T* value, T min, T max, T increment);
Component Toggle(ConstStringListRef entries, int* selected);
// General slider constructor:
template <typename T>
Component Slider(SliderOption<T> options = {});
// Shorthand without the `SliderOption` constructor:
Component Slider(ConstStringRef label,
Ref<int> value,
ConstRef<int> min = 0,
ConstRef<int> max = 100,
ConstRef<int> increment = 5);
Component Slider(ConstStringRef label,
Ref<float> value,
ConstRef<float> min = 0.f,
ConstRef<float> max = 100.f,
ConstRef<float> increment = 5.f);
Component Slider(ConstStringRef label,
Ref<long> value,
ConstRef<long> min = 0l,
ConstRef<long> max = 100l,
ConstRef<long> increment = 5l);
Component ResizableSplitLeft(Component main, Component back, int* main_size);
Component ResizableSplitRight(Component main, Component back, int* main_size);
Component ResizableSplitTop(Component main, Component back, int* main_size);
Component ResizableSplitBottom(Component main, Component back, int* main_size);
Component Renderer(Component child, std::function<Element()>);
Component Renderer(std::function<Element()>);
Component Renderer(std::function<Element(bool /* focused */)>);
ComponentDecorator Renderer(ElementDecorator);
Component CatchEvent(Component child, std::function<bool(Event)>);
ComponentDecorator CatchEvent(std::function<bool(Event)> on_event);
Component Maybe(Component, const bool* show);
Component Maybe(Component, std::function<bool()>);
ComponentDecorator Maybe(const bool* show);
ComponentDecorator Maybe(std::function<bool()>);
Component Modal(Component main, Component modal, const bool* show_modal);
ComponentDecorator Modal(Component modal, const bool* show_modal);
Component Collapsible(ConstStringRef label,
Component child,
Ref<bool> show = false);
} // namespace ftxui
Component Hoverable(Component component, bool* hover);
Component Hoverable(Component component,
std::function<void()> on_enter,
std::function<void()> on_leave);
Component Hoverable(Component component, //
std::function<void(bool)> on_change);
ComponentDecorator Hoverable(bool* hover);
ComponentDecorator Hoverable(std::function<void()> on_enter,
std::function<void()> on_leave);
ComponentDecorator Hoverable(std::function<void(bool)> on_change);
// Include component using the old deprecated wstring.
#include "ftxui/component/deprecated.hpp"
} // namespace ftxui
#endif /* end of include guard: FTXUI_COMPONENT_HPP */

View File

@@ -13,6 +13,10 @@ class Delegate;
class Focus;
struct Event;
namespace animation {
class Params;
} // namespace animation
class ComponentBase;
using Component = std::shared_ptr<ComponentBase>;
using Components = std::vector<Component>;
@@ -42,6 +46,9 @@ class ComponentBase {
// Returns whether the event was handled or not.
virtual bool OnEvent(Event);
// Handle an animation step.
virtual void OnAnimation(animation::Params& params);
// Focus management ----------------------------------------------------------
//
// If this component contains children, this indicates which one is active,

View File

@@ -1,58 +1,136 @@
#ifndef FTXUI_COMPONENT_COMPONENT_OPTIONS_HPP
#define FTXUI_COMPONENT_COMPONENT_OPTIONS_HPP
#include <ftxui/dom/elements.hpp>
#include <ftxui/util/ref.hpp>
#include <chrono> // for milliseconds
#include <ftxui/component/animation.hpp> // for Duration, QuadraticInOut, Function
#include <ftxui/dom/elements.hpp> // for Element, GaugeDirection, GaugeDirection::Right
#include <ftxui/util/ref.hpp> // for Ref, ConstRef
#include <functional> // for function
#include <optional> // for optional
#include <string> // for string
#include "ftxui/screen/color.hpp" // for Color, Color::GrayDark, Color::White
namespace ftxui {
/// @brief Option for the Menu component.
/// @brief arguments for |ButtonOption::transform|, |CheckboxOption::transform|,
/// |Radiobox::transform|, |MenuEntryOption::transform|,
/// |MenuOption::transform|.
struct EntryState {
std::string label; /// < The label to display.
bool state; /// < The state of the button/checkbox/radiobox
bool active; /// < Whether the entry is the active one.
bool focused; /// < Whether the entry is one focused by the user.
};
struct UnderlineOption {
bool enabled = false;
Color color_active = Color::White;
Color color_inactive = Color::GrayDark;
animation::easing::Function leader_function =
animation::easing::QuadraticInOut;
animation::easing::Function follower_function =
animation::easing::QuadraticInOut;
animation::Duration leader_duration = std::chrono::milliseconds(250);
animation::Duration leader_delay = std::chrono::milliseconds(0);
animation::Duration follower_duration = std::chrono::milliseconds(250);
animation::Duration follower_delay = std::chrono::milliseconds(0);
void SetAnimation(animation::Duration d, animation::easing::Function f);
void SetAnimationDuration(animation::Duration d);
void SetAnimationFunction(animation::easing::Function f);
void SetAnimationFunction(animation::easing::Function f_leader,
animation::easing::Function f_follower);
};
/// @brief Option about a potentially animated color.
/// @ingroup component
struct MenuOption {
Decorator style_normal = nothing; ///< style.
Decorator style_focused = inverted; ///< Style when focused.
Decorator style_selected = bold; ///< Style when selected.
Decorator style_selected_focused =
Decorator(inverted) | bold; ///< Style when selected and focused.
struct AnimatedColorOption {
void Set(
Color inactive,
Color active,
animation::Duration duration = std::chrono::milliseconds(250),
animation::easing::Function function = animation::easing::QuadraticInOut);
/// Called when the selected entry changes.
std::function<void()> on_change = [] {};
/// Called when the user presses enter.
std::function<void()> on_enter = [] {};
bool enabled = false;
Color inactive;
Color active;
animation::Duration duration = std::chrono::milliseconds(250);
animation::easing::Function function = animation::easing::QuadraticInOut;
};
Ref<int> focused_entry = 0;
struct AnimatedColorsOption {
AnimatedColorOption background;
AnimatedColorOption foreground;
};
/// @brief Option for the MenuEntry component.
/// @ingroup component
struct MenuEntryOption {
Decorator style_normal = nothing; ///< style.
Decorator style_focused = inverted; ///< Style when focused.
Decorator style_selected = bold; ///< Style when selected.
Decorator style_selected_focused =
Decorator(inverted) | bold; ///< Style when selected and focused.
std::function<Element(const EntryState& state)> transform;
AnimatedColorsOption animated_colors;
};
/// @brief Option for the Button component.
/// @brief Option for the Menu component.
/// @ingroup component
struct MenuOption {
// Standard constructors:
static MenuOption Horizontal();
static MenuOption HorizontalAnimated();
static MenuOption Vertical();
static MenuOption VerticalAnimated();
static MenuOption Toggle();
// Style:
UnderlineOption underline;
MenuEntryOption entries;
enum Direction { Up, Down, Left, Right };
Direction direction = Down;
std::function<Element()> elements_prefix;
std::function<Element()> elements_infix;
std::function<Element()> elements_postfix;
// Observers:
std::function<void()> on_change; ///> Called when the selected entry changes.
std::function<void()> on_enter; ///> Called when the user presses enter.
Ref<int> focused_entry = 0;
};
/// @brief Option for the AnimatedButton component.
/// @ingroup component
struct ButtonOption {
/// Whether to show a border around the button.
bool border = true;
// Standard constructors:
static ButtonOption Ascii();
static ButtonOption Simple();
static ButtonOption Border();
static ButtonOption Animated();
static ButtonOption Animated(Color color);
static ButtonOption Animated(Color background, Color foreground);
static ButtonOption Animated(Color background,
Color foreground,
Color background_active,
Color foreground_active);
// Style:
std::function<Element(const EntryState&)> transform;
AnimatedColorsOption animated_colors;
};
/// @brief Option for the Checkbox component.
/// @ingroup component
struct CheckboxOption {
std::string style_checked = ""; ///< Prefix for a "checked" state.
std::string style_unchecked = ""; ///< Prefix for a "unchecked" state.
Decorator style_normal = nothing; ///< style.
Decorator style_focused = inverted; ///< Style when focused.
Decorator style_selected = bold; ///< Style when selected.
Decorator style_selected_focused =
Decorator(inverted) | bold; ///< Style when selected and focused.
// Standard constructors:
static CheckboxOption Simple();
// Style:
std::function<Element(const EntryState&)> transform;
// Observer:
/// Called when the user change the state.
std::function<void()> on_change = []() {};
std::function<void()> on_change = [] {};
};
/// @brief Option for the Input component.
@@ -74,35 +152,29 @@ struct InputOption {
/// @brief Option for the Radiobox component.
/// @ingroup component
struct RadioboxOption {
std::string style_checked = ""; ///< Prefix for a "checked" state.
std::string style_unchecked = ""; ///< Prefix for a "unchecked" state.
Decorator style_normal = nothing; ///< style.
Decorator style_focused = inverted; ///< Style when focused.
Decorator style_selected = bold; ///< Style when selected.
Decorator style_selected_focused =
Decorator(inverted) | bold; ///< Style when selected and focused.
// Standard constructors:
static RadioboxOption Simple();
// Style:
std::function<Element(const EntryState&)> transform;
// Observers:
/// Called when the selected entry changes.
std::function<void()> on_change = []() {};
std::function<void()> on_change = [] {};
Ref<int> focused_entry = 0;
};
/// @brief Option for the Toggle component.
/// @ingroup component
struct ToggleOption {
Decorator style_normal = nothing; ///< style.
Decorator style_focused = inverted; ///< Style when focused.
Decorator style_selected = bold; ///< Style when selected.
Decorator style_selected_focused =
Decorator(inverted) | bold; ///< Style when selected and focused.
/// Called when the selected entry changes.
std::function<void()> on_change = [] {};
/// Called when the user presses enter.
std::function<void()> on_enter = [] {};
Ref<int> focused_entry = 0;
// @brief Option for the `Slider` component.
// @ingroup component
template <typename T>
struct SliderOption {
Ref<T> value;
ConstRef<T> min = T(0);
ConstRef<T> max = T(100);
ConstRef<T> increment = (max() - min()) / 20;
GaugeDirection direction = GaugeDirection::Right;
Color color_active = Color::White;
Color color_inactive = Color::GrayDark;
};
} // namespace ftxui

View File

@@ -1,17 +0,0 @@
#ifndef FTXUI_COMPONENT_DEPRECATED_HPP
#define FTXUI_COMPONENT_DEPRECATED_HPP
#include "ftxui/component/component.hpp"
namespace ftxui {
Component Input(WideStringRef content,
ConstStringRef placeholder,
Ref<InputOption> option = {});
} // namespace ftxui
#endif /* FTXUI_COMPONENT_DEPRECATED_HPP */
// Copyright 2021 Arthur Sonzogni. All rights reserved.
// Use of this source code is governed by the MIT license that can be found in
// the LICENSE file.

View File

@@ -2,7 +2,8 @@
#define FTXUI_COMPONENT_EVENT_HPP
#include <ftxui/component/mouse.hpp> // for Mouse
#include <string> // for string, operator==
#include <functional>
#include <string> // for string, operator==
#include <vector>
namespace ftxui {
@@ -37,6 +38,11 @@ struct Event {
static const Event ArrowUp;
static const Event ArrowDown;
static const Event ArrowLeftCtrl;
static const Event ArrowRightCtrl;
static const Event ArrowUpCtrl;
static const Event ArrowDownCtrl;
// --- Other ---
static const Event Backspace;
static const Event Delete;
@@ -53,16 +59,14 @@ struct Event {
static const Event PageDown;
// --- Custom ---
static Event Custom;
static const Event Custom;
//--- Method section ---------------------------------------------------------
bool is_character() const { return type_ == Type::Character; }
std::string character() const { return input_; }
bool is_mouse() const { return type_ == Type::Mouse; }
struct Mouse& mouse() {
return mouse_;
}
struct Mouse& mouse() { return mouse_; }
bool is_cursor_reporting() const { return type_ == Type::CursorReporting; }
int cursor_x() const { return cursor_.x; }

View File

@@ -0,0 +1,39 @@
#ifndef FTXUI_COMPONENT_LOOP_HPP
#define FTXUI_COMPONENT_LOOP_HPP
#include <memory> // for shared_ptr
#include "ftxui/component/component_base.hpp" // for ComponentBase
namespace ftxui {
class ComponentBase;
using Component = std::shared_ptr<ComponentBase>;
class ScreenInteractive;
class Loop {
public:
Loop(ScreenInteractive* screen, Component component);
~Loop();
bool HasQuitted();
void RunOnce();
void RunOnceBlocking();
void Run();
private:
// This class is non copyable.
Loop(const ScreenInteractive&) = delete;
Loop& operator=(const Loop&) = delete;
ScreenInteractive* screen_;
Component component_;
};
} // namespace ftxui
#endif // FTXUI_COMPONENT_LOOP_HPP
// Copyright 2022 Arthur Sonzogni. All rights reserved.
// Use of this source code is governed by the MIT license that can be found in
// the LICENSE file.

View File

@@ -86,11 +86,25 @@ class ReceiverImpl {
return false;
}
bool ReceiveNonBlocking(T* t) {
std::unique_lock<std::mutex> lock(mutex_);
if (queue_.empty())
return false;
*t = queue_.front();
queue_.pop();
return true;
}
bool HasPending() {
std::unique_lock<std::mutex> lock(mutex_);
return !queue_.empty();
}
bool HasQuitted() {
std::unique_lock<std::mutex> lock(mutex_);
return queue_.empty() && !senders_;
}
private:
friend class SenderImpl<T>;

View File

@@ -7,47 +7,70 @@
#include <memory> // for shared_ptr
#include <string> // for string
#include <thread> // for thread
#include <variant> // for variant
#include "ftxui/component/animation.hpp" // for TimePoint
#include "ftxui/component/captured_mouse.hpp" // for CapturedMouse
#include "ftxui/component/event.hpp" // for Event
#include "ftxui/component/task.hpp" // for Task, Closure
#include "ftxui/screen/screen.hpp" // for Screen
namespace ftxui {
class ComponentBase;
class Loop;
struct Event;
using Component = std::shared_ptr<ComponentBase>;
class ScreenInteractivePrivate;
class ScreenInteractive : public Screen {
public:
using Callback = std::function<void()>;
// Constructors:
static ScreenInteractive FixedSize(int dimx, int dimy);
static ScreenInteractive Fullscreen();
static ScreenInteractive FitComponent();
static ScreenInteractive TerminalOutput();
void Loop(Component);
Callback ExitLoopClosure();
// Return the currently active screen, nullptr if none.
static ScreenInteractive* Active();
// Start/Stop the main loop.
void Loop(Component);
void Exit();
Closure ExitLoopClosure();
// Post tasks to be executed by the loop.
void Post(Task task);
void PostEvent(Event event);
void RequestAnimationFrame();
CapturedMouse CaptureMouse();
// Decorate a function. The outputted one will execute similarly to the
// inputted one, but with the currently active screen terminal hooks
// temporarily uninstalled.
Callback WithRestoredIO(Callback);
Closure WithRestoredIO(Closure);
private:
void ExitNow();
void Install();
void Uninstall();
void Main(Component component);
ScreenInteractive* suspended_screen_ = nullptr;
void PreMain();
void PostMain();
bool HasQuitted();
void RunOnce(Component component);
void RunOnceBlocking(Component component);
void HandleTask(Component component, Task& task);
void Draw(Component component);
void EventLoop(Component component);
void ResetCursorPosition();
void Signal(int signal);
ScreenInteractive* suspended_screen_ = nullptr;
enum class Dimension {
FitComponent,
Fixed,
@@ -61,20 +84,34 @@ class ScreenInteractive : public Screen {
Dimension dimension,
bool use_alternative_screen);
Sender<Event> event_sender_;
Receiver<Event> event_receiver_;
Sender<Task> task_sender_;
Receiver<Task> task_receiver_;
std::string set_cursor_position;
std::string reset_cursor_position;
std::atomic<bool> quit_ = false;
std::thread event_listener_;
std::thread animation_listener_;
bool animation_requested_ = false;
animation::TimePoint previous_animation_time_;
int cursor_x_ = 1;
int cursor_y_ = 1;
bool mouse_captured = false;
bool previous_frame_resized_ = false;
bool frame_valid_ = false;
friend class Loop;
public:
class Private {
public:
static void Signal(ScreenInteractive& s, int signal) { s.Signal(signal); }
};
friend Private;
};
} // namespace ftxui

View File

@@ -0,0 +1,18 @@
#ifndef FTXUI_COMPONENT_ANIMATION_HPP
#define FTXUI_COMPONENT_ANIMATION_HPP
#include <functional>
#include <variant>
#include "ftxui/component/event.hpp"
namespace ftxui {
class AnimationTask {};
using Closure = std::function<void()>;
using Task = std::variant<Event, Closure, AnimationTask>;
} // namespace ftxui
#endif // FTXUI_COMPONENT_ANIMATION_HPP
// Copyright 2022 Arthur Sonzogni. All rights reserved.
// Use of this source code is governed by the MIT license that can be found in
// the LICENSE file.

View File

@@ -1,7 +1,7 @@
#ifndef FTXUI_DOM_CANVAS_HPP
#define FTXUI_DOM_CANVAS_HPP
#include <stddef.h> // for size_t
#include <cstddef> // for size_t
#include <functional> // for function
#include <string> // for string
#include <unordered_map> // for unordered_map
@@ -9,11 +9,17 @@
#include "ftxui/screen/color.hpp" // for Color
#include "ftxui/screen/screen.hpp" // for Pixel
#ifdef DrawText
// Workaround for WinUsr.h (via Windows.h) defining macros that break things.
// https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-drawtext
#undef DrawText
#endif
namespace ftxui {
struct Canvas {
public:
Canvas() {}
Canvas() = default;
Canvas(int width, int height);
// Getters:
@@ -114,7 +120,8 @@ struct Canvas {
struct XYHash {
size_t operator()(const XY& xy) const {
return static_cast<size_t>(xy.x * 1024 + xy.y);
constexpr size_t shift = 1024;
return size_t(xy.x) * shift + size_t(xy.y);
}
};

View File

@@ -1,5 +1,5 @@
#ifndef FTXUI_DOM_DEPRECRATED_HPP
#define FTXUI_DOM_DEPRECRATED_HPP
#ifndef FTXUI_DOM_DEPRECATED_HPP
#define FTXUI_DOM_DEPRECATED_HPP
#include "ftxui/dom/elements.hpp"
@@ -9,7 +9,7 @@ Element vtext(std::wstring text);
Elements paragraph(std::wstring text);
} // namespace ftxui
#endif /* end of include guard: FTXUI_DOM_DEPRECRATED_HPP */
#endif // FTXUI_DOM_DEPRECATED_HPP
// Copyright 2021 Arthur Sonzogni. All rights reserved.
// Use of this source code is governed by the MIT license that can be found in

View File

@@ -21,19 +21,21 @@ using Decorator = std::function<Element(Element)>;
using GraphFunction = std::function<std::vector<int>(int, int)>;
enum BorderStyle { LIGHT, HEAVY, DOUBLE, ROUNDED, EMPTY };
enum class GaugeDirection { Left, Up, Right, Down };
// Pipe elements into decorator togethers.
// For instance the next lines are equivalents:
// -> text("ftxui") | bold | underlined
// -> underlined(bold(text("FTXUI")))
Element operator|(Element, Decorator);
Element& operator|=(Element&, Decorator);
Elements operator|(Elements, Decorator);
Decorator operator|(Decorator, Decorator);
// --- Widget ---
Element text(std::string text);
Element vtext(std::string text);
Element separator(void);
Element separator();
Element separatorLight();
Element separatorHeavy();
Element separatorDouble();
@@ -41,7 +43,20 @@ Element separatorEmpty();
Element separatorStyled(BorderStyle);
Element separator(Pixel);
Element separatorCharacter(std::string);
Element gauge(float ratio);
Element separatorHSelector(float left,
float right,
Color unselected_color,
Color selected_color);
Element separatorVSelector(float up,
float down,
Color unselected_color,
Color selected_color);
Element gauge(float progress);
Element gaugeLeft(float progress);
Element gaugeRight(float progress);
Element gaugeUp(float progress);
Element gaugeDown(float progress);
Element gaugeDirection(float progress, GaugeDirection);
Element border(Element);
Element borderLight(Element);
Element borderHeavy(Element);
@@ -49,14 +64,14 @@ Element borderDouble(Element);
Element borderRounded(Element);
Element borderEmpty(Element);
Decorator borderStyled(BorderStyle);
Decorator borderWith(Pixel);
Decorator borderWith(const Pixel&);
Element window(Element title, Element content);
Element spinner(int charset_index, size_t image_index);
Element paragraph(std::string text);
Element paragraphAlignLeft(std::string text);
Element paragraphAlignRight(std::string text);
Element paragraphAlignCenter(std::string text);
Element paragraphAlignJustify(std::string text);
Element paragraph(const std::string& text);
Element paragraphAlignLeft(const std::string& text);
Element paragraphAlignRight(const std::string& text);
Element paragraphAlignCenter(const std::string& text);
Element paragraphAlignJustify(const std::string& text);
Element graph(GraphFunction);
Element emptyElement();
Element canvas(ConstRef<Canvas>);
@@ -68,13 +83,16 @@ Element bold(Element);
Element dim(Element);
Element inverted(Element);
Element underlined(Element);
Element underlinedDouble(Element);
Element blink(Element);
Element strikethrough(Element);
Decorator color(Color);
Decorator bgcolor(Color);
Element color(Color, Element);
Element bgcolor(Color, Element);
Decorator focusPosition(int x, int y);
Decorator focusPositionRelative(float x, float y);
Element automerge(Element child);
// --- Layout is
// Horizontal, Vertical or stacked set of elements.
@@ -110,9 +128,6 @@ enum Direction { WIDTH, HEIGHT };
enum Constraint { LESS_THAN, EQUAL, GREATER_THAN };
Decorator size(Direction, Constraint, int value);
// --
Decorator reflect(Box& box);
// --- 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
@@ -123,7 +138,21 @@ Element yframe(Element);
Element focus(Element);
Element select(Element);
// --- Cursor ---
// Those are similar to `focus`, but also change the shape of the cursor.
Element focusCursorBlock(Element);
Element focusCursorBlockBlinking(Element);
Element focusCursorBar(Element);
Element focusCursorBarBlinking(Element);
Element focusCursorUnderline(Element);
Element focusCursorUnderlineBlinking(Element);
// --- Misc ---
Element vscroll_indicator(Element);
Decorator reflect(Box& box);
// Before drawing the |element| clear the pixel below. This is useful in
// combinaison with dbox.
Element clear_under(Element element);
// --- Util --------------------------------------------------------------------
Element hcenter(Element);
@@ -132,10 +161,6 @@ Element center(Element);
Element align_right(Element);
Element nothing(Element element);
// Before drawing the |element| clear the pixel below. This is useful in
// combinaison with dbox.
Element clear_under(Element element);
namespace Dimension {
Dimensions Fit(Element&);
} // namespace Dimension
@@ -147,7 +172,7 @@ Dimensions Fit(Element&);
// Include old definitions using wstring.
#include "ftxui/dom/deprecated.hpp"
#endif /* end of include guard: FTXUI_DOM_ELEMENTS_HPP */
#endif // FTXUI_DOM_ELEMENTS_HPP
// Copyright 2020 Arthur Sonzogni. All rights reserved.
// Use of this source code is governed by the MIT license that can be found in

View File

@@ -108,7 +108,7 @@ struct FlexboxConfig {
} // namespace ftxui
#endif /* end of include guard: FTXUI_DOM_FLEXBOX_CONFIG_HPP */
#endif // FTXUI_DOM_FLEXBOX_CONFIG_HPP
// Copyright 2021 Arthur Sonzogni. All rights reserved.
// Use of this source code is governed by the MIT license that can be found in

View File

@@ -20,6 +20,11 @@ class Node {
public:
Node();
Node(Elements children);
Node(const Node&) = delete;
Node(const Node&&) = delete;
Node& operator=(const Node&) = delete;
Node& operator=(const Node&&) = delete;
virtual ~Node();
// Step 1: Compute layout requirement. Tell parent what dimensions this
@@ -50,12 +55,12 @@ class Node {
Box box_;
};
void Render(Screen& screen, const Element& node);
void Render(Screen& screen, const Element& element);
void Render(Screen& screen, Node* node);
} // namespace ftxui
#endif /* end of include guard: FTXUI_DOM_NODE_HPP */
#endif // FTXUI_DOM_NODE_HPP
// Copyright 2020 Arthur Sonzogni. All rights reserved.
// Use of this source code is governed by the MIT license that can be found in

View File

@@ -28,7 +28,7 @@ struct Requirement {
} // namespace ftxui
#endif /* end of include guard: FTXUI_DOM_REQUIREMENT_HPP */
#endif // FTXUI_DOM_REQUIREMENT_HPP
// Copyright 2020 Arthur Sonzogni. All rights reserved.
// Use of this source code is governed by the MIT license that can be found in

View File

@@ -5,7 +5,7 @@
#include <string> // for string
#include <vector> // for vector
#include "ftxui/dom/elements.hpp" // for BorderStyle, LIGHT, Element, Decorator
#include "ftxui/dom/elements.hpp" // for Element, BorderStyle, LIGHT, Decorator
namespace ftxui {
@@ -52,10 +52,10 @@ class Table {
void Initialize(std::vector<std::vector<Element>>);
friend TableSelection;
std::vector<std::vector<Element>> elements_;
int input_dim_x_;
int input_dim_y_;
int dim_x_;
int dim_y_;
int input_dim_x_ = 0;
int input_dim_y_ = 0;
int dim_x_ = 0;
int dim_y_ = 0;
};
class TableSelection {

View File

@@ -1,10 +1,13 @@
#ifndef FTXUI_DOM_TAKE_ANY_ARGS_HPP
#define FTXUI_DOM_TAKE_ANY_ARGS_HPP
// IWYU pragma: private, include "ftxui/dom/elements.hpp"
#include <type_traits>
namespace ftxui {
template <class T>
void Merge(Elements&, T) {}
void Merge(Elements& /*container*/, T /*element*/) {}
template <>
inline void Merge(Elements& container, Element element) {
@@ -38,6 +41,8 @@ TAKE_ANY_ARGS(dbox)
TAKE_ANY_ARGS(hflow)
} // namespace ftxui
#endif // FTXUI_DOM_TAKE_ANY_ARGS_HPP
// 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.

View File

@@ -9,15 +9,16 @@ struct Box {
int y_min = 0;
int y_max = 0;
static Box Intersection(Box a, Box b);
bool Contain(int x, int y);
static auto Intersection(Box a, Box b) -> Box;
static auto Union(Box a, Box b) -> Box;
bool Contain(int x, int y) const;
bool operator==(const Box& other) const;
bool operator!=(const Box& other) const;
};
} // namespace ftxui
#endif /* end of include guard: FTXUI_SCREEN_BOX_HPP */
#endif // FTXUI_SCREEN_BOX_HPP
// Copyright 2020 Arthur Sonzogni. All rights reserved.
// Use of this source code is governed by the MIT license that can be found in

View File

@@ -1,8 +1,8 @@
#ifndef FTXUI_SCREEN_COLOR
#define FTXUI_SCREEN_COLOR
#ifndef FTXUI_SCREEN_COLOR_HPP
#define FTXUI_SCREEN_COLOR_HPP
#include <stdint.h> // for uint8_t
#include <string> // for wstring
#include <cstdint> // for uint8_t
#include <string> // for wstring
#ifdef RGB
// Workaround for wingdi.h (via Windows.h) defining macros that break things.
@@ -27,6 +27,7 @@ class Color {
Color(uint8_t red, uint8_t green, uint8_t blue);
static Color RGB(uint8_t red, uint8_t green, uint8_t blue);
static Color HSV(uint8_t hue, uint8_t saturation, uint8_t value);
static Color Interpolate(float t, const Color& a, const Color& b);
//---------------------------
// List of colors:
@@ -312,12 +313,8 @@ class Color {
Palette256,
TrueColor,
};
ColorType type_;
union {
uint8_t index_ = 0;
uint8_t red_;
};
ColorType type_ = ColorType::Palette1;
uint8_t red_ = 0;
uint8_t green_ = 0;
uint8_t blue_ = 0;
};
@@ -332,7 +329,7 @@ Color operator""_rgb(unsigned long long int combined);
} // namespace ftxui
#endif /* end of include guard: FTXUI_COLOR_H_ */
#endif // FTXUI_SCREEN_COLOR_HPP
// Copyright 2020 Arthur Sonzogni. All rights reserved.
// Use of this source code is governed by the MIT license that can be found in

View File

@@ -1,7 +1,7 @@
#ifndef FTXUI_SCREEN_COLOR_INFO_HPP
#define FTXUI_SCREEN_COLOR_INFO_HPP
#include <stdint.h>
#include <cstdint>
#include <ftxui/screen/color.hpp>
namespace ftxui {
@@ -23,7 +23,7 @@ ColorInfo GetColorInfo(Color::Palette16 index);
} // namespace ftxui
#endif /* end of include guard: FTXUI_SCREEN_COLOR_INFO_HPP */
#endif // FTXUI_SCREEN_COLOR_INFO_HPP
// Copyright 2020 Arthur Sonzogni. All rights reserved.
// Use of this source code is governed by the MIT license that can be found in

View File

@@ -8,7 +8,7 @@ int wchar_width(wchar_t);
int wstring_width(const std::wstring&);
} // namespace ftxui
#endif /* end of include guard: FTXUI_SCREEN_DEPRECATED_HPP */
#endif // FTXUI_SCREEN_DEPRECATED_HPP
// Copyright 2021 Arthur Sonzogni. All rights reserved.
// Use of this source code is governed by the MIT license that can be found in

View File

@@ -1,5 +1,5 @@
#ifndef FTXUI_SCREEN_SCREEN
#define FTXUI_SCREEN_SCREEN
#ifndef FTXUI_SCREEN_SCREEN_HPP
#define FTXUI_SCREEN_SCREEN_HPP
#include <memory>
#include <string> // for string, allocator, basic_string
@@ -14,6 +14,8 @@ namespace ftxui {
/// @brief A unicode character and its associated style.
/// @ingroup screen
struct Pixel {
bool operator==(const Pixel& other) const;
// The graphemes stored into the pixel. To support combining characters,
// like: a⃦, this can potentially contains multiple codepoitns.
std::string character = " ";
@@ -28,6 +30,8 @@ struct Pixel {
bool dim : 1;
bool inverted : 1;
bool underlined : 1;
bool underlined_double : 1;
bool strikethrough : 1;
bool automerge : 1;
Pixel()
@@ -36,6 +40,8 @@ struct Pixel {
dim(false),
inverted(false),
underlined(false),
underlined_double(false),
strikethrough(false),
automerge(false) {}
};
@@ -68,21 +74,33 @@ class Screen {
int dimy() const { return dimy_; }
// Move the terminal cursor n-lines up with n = dimy().
std::string ResetPosition(bool clear = false);
std::string ResetPosition(bool clear = false) const;
// Fill with space.
void Clear();
void ApplyShader();
Box stencil;
struct Cursor {
int x = 0;
int y = 0;
enum Shape {
Hidden = 0,
BlockBlinking = 1,
Block = 2,
UnderlineBlinking = 3,
Underline = 4,
BarBlinking = 5,
Bar = 6,
};
Shape shape;
};
Cursor cursor() const { return cursor_; }
void SetCursor(Cursor cursor) { cursor_ = cursor; }
Box stencil;
protected:
int dimx_;
int dimy_;
@@ -92,7 +110,7 @@ class Screen {
} // namespace ftxui
#endif /* end of include guard: FTXUI_SCREEN_SCREEN */
#endif // FTXUI_SCREEN_SCREEN_HPP
// Copyright 2020 Arthur Sonzogni. All rights reserved.
// Use of this source code is governed by the MIT license that can be found in

View File

@@ -26,6 +26,33 @@ int GlyphPosition(const std::string& input,
// Returns the number of glyphs in |input|.
int GlyphCount(const std::string& input);
// Properties from:
// https://www.unicode.org/Public/UCD/latest/ucd/auxiliary/WordBreakProperty.txt
enum class WordBreakProperty {
ALetter,
CR,
Double_Quote,
Extend,
ExtendNumLet,
Format,
Hebrew_Letter,
Katakana,
LF,
MidLetter,
MidNum,
MidNumLet,
Newline,
Numeric,
Regional_Indicator,
Single_Quote,
WSegSpace,
ZWJ,
};
std::vector<WordBreakProperty> Utf8ToWordBreakProperty(
const std::string& input);
bool IsWordBreakingCharacter(const std::string& input, size_t glyph_index);
// Map every cells drawn by |input| to their corresponding Glyphs. Half-size
// Glyphs takes one cell, full-size Glyphs take two cells.
std::vector<int> CellToGlyphIndex(const std::string& input);

View File

@@ -1,5 +1,5 @@
#ifndef FTXUI_CORE_TERMINAL_HPP
#define FTXUI_CORE_TERMINAL_HPP
#ifndef FTXUI_SCREEN_TERMINAL_HPP
#define FTXUI_SCREEN_TERMINAL_HPP
namespace ftxui {
struct Dimensions {
@@ -18,11 +18,13 @@ enum Color {
TrueColor,
};
Color ColorSupport();
void SetColorSupport(Color color);
} // namespace Terminal
} // namespace ftxui
#endif /* end of include guard: FTXUI_CORE_TERMINAL_HPP */
#endif // FTXUI_SCREEN_TERMINAL_HPP
// Copyright 2020 Arthur Sonzogni. All rights reserved.
// Use of this source code is governed by the MIT license that can be found in

View File

@@ -27,7 +27,8 @@ template <typename T>
class Ref {
public:
Ref() {}
Ref(T t) : owned_(t) {}
Ref(const T& t) : owned_(t) {}
Ref(T&& t) : owned_(std::forward<T>(t)) {}
Ref(T* t) : address_(t) {}
T& operator*() { return address_ ? *address_ : owned_; }
T& operator()() { return address_ ? *address_ : owned_; }
@@ -54,23 +55,6 @@ class StringRef {
std::string* address_ = nullptr;
};
/// @brief An adapter. Own or reference a constant string. For convenience, this
/// class convert multiple mutable string toward a shared representation.
class WideStringRef {
public:
WideStringRef(std::wstring* ref) : address_(ref) {}
WideStringRef(std::wstring ref) : owned_(std::move(ref)) {}
WideStringRef(const wchar_t* ref) : WideStringRef(std::wstring(ref)) {}
WideStringRef(const char* ref)
: WideStringRef(to_wstring(std::string(ref))) {}
std::wstring& operator*() { return address_ ? *address_ : owned_; }
std::wstring* operator->() { return address_ ? address_ : &owned_; }
private:
std::wstring owned_;
std::wstring* address_ = nullptr;
};
/// @brief An adapter. Own or reference a constant string. For convenience, this
/// class convert multiple immutable string toward a shared representation.
class ConstStringRef {
@@ -82,6 +66,9 @@ class ConstStringRef {
ConstStringRef(const wchar_t* ref) : ConstStringRef(std::wstring(ref)) {}
ConstStringRef(const char* ref)
: ConstStringRef(to_wstring(std::string(ref))) {}
const std::string& operator()() const {
return address_ ? *address_ : owned_;
}
const std::string& operator*() const { return address_ ? *address_ : owned_; }
const std::string* operator->() const {
return address_ ? address_ : &owned_;

View File

@@ -1,17 +1,27 @@
[
{ include: ["<bits/chrono.h>", "private", "<chrono>", "public"]},
{ include: ["<bits/std_abs.h>", "private", "<cmath>", "public"]},
{ include: ["<bits/termios-c_cc.h>", "private", "<termios.h>", "public"]},
{ include: ["<bits/termios-c_lflag.h>", "private", "<termios.h>", "public"]},
{ include: ["<bits/termios-struct.h>", "private", "<termios.h>", "public"]},
{ include: ["<bits/termios-tcflow.h>", "private", "<termios.h>", "public"]},
{ include: ["<ext/alloc_traits.h>", "private", "<vector>", "public"] },
{ symbol: [ "ftxui", "private", "", "public" ] },
{ symbol: [ "char_traits", "private", "<string>", "public" ] },
{ symbol: [ "ECHO", "private", "<termios.h>", "public" ] },
{ symbol: [ "ICANON", "private", "<termios.h>", "public" ] },
{ symbol: [ "TCSANOW", "private", "<termios.h>", "public" ] },
{ symbol: [ "VMIN", "private", "<termios.h>", "public" ] },
{ symbol: [ "VTIME", "private", "<termios.h>", "public" ] },
{ symbol: [ "__shared_ptr_access", "private", "<memory>", "public" ] },
{ symbol: [ "termios", "private", "<termios.h>", "public" ] },
{ symbol: ["__alloc_traits<>:value_type", "private", "<vector>", "public" ] },
{ include: ["<gtest/internal/gtest-internal.h>", "private", "<gtest/gtest.h>", "public" ] },
{ include: ["<gtest/internal/gtest-string.h>", "private", "<gtest/gtest.h>", "public" ] },
{ include: ["<gtest/gtest-death-test.h>", "private", "<gtest/gtest.h>", "public" ] },
{ include: ["<gtest/gtest-message.h>", "private", "<gtest/gtest.h>", "public" ] },
{ include: ["<gtest/gtest-param-test.h>", "private", "<gtest/gtest.h>", "public" ] },
{ include: ["<gtest/gtest-printers.h>", "private", "<gtest/gtest.h>", "public" ] },
{ include: ["<gtest/gtest-test-part.h>", "private", "<gtest/gtest.h>", "public" ] },
{ include: ["<gtest/gtest-typed-test.h>", "private", "<gtest/gtest.h>", "public" ] },
{ symbol: ["ftxui", "private", "", "public" ] },
{ symbol: ["char_traits", "private", "<string>", "public" ] },
{ symbol: ["ECHO", "private", "<termios.h>", "public" ] },
{ symbol: ["ICANON", "private", "<termios.h>", "public" ] },
{ symbol: ["TCSANOW", "private", "<termios.h>", "public" ] },
{ symbol: ["VMIN", "private", "<termios.h>", "public" ] },
{ symbol: ["VTIME", "private", "<termios.h>", "public" ] },
{ symbol: ["__shared_ptr_access", "private", "<memory>", "public" ] },
{ symbol: ["termios", "private", "<termios.h>", "public" ] },
{ symbol: ["__alloc_traits<>:value_type", "private", "<vector>", "public" ] }
]

View File

@@ -0,0 +1,293 @@
#include <cmath> // for sin, pow, sqrt, cos
#include <ratio> // for ratio
#include <utility> // for move
#include "ftxui/component/animation.hpp"
namespace ftxui::animation {
namespace easing {
namespace {
constexpr float kPi = 3.14159265358979323846F;
constexpr float kPi2 = kPi / 2.F;
} // namespace
// Easing function have been taken out of:
// https://github.com/warrenm/AHEasing/blob/master/AHEasing/easing.c
//
// Corresponding license:
// Copyright (c) 2011, Auerhaus Development, LLC
//
// This program is free software. It comes without any warranty, to
// the extent permitted by applicable law. You can redistribute it
// and/or modify it under the terms of the Do What The Fuck You Want
// To Public License, Version 2, as published by Sam Hocevar. See
// http://sam.zoy.org/wtfpl/COPYING for more details.
// Modeled after the line y = x
float Linear(float p) {
return p;
}
// Modeled after the parabola y = x^2
float QuadraticIn(float p) {
return p * p;
}
// Modeled after the parabola y = -x^2 + 2x
float QuadraticOut(float p) {
return -(p * (p - 2));
}
// Modeled after the piecewise quadratic
// y = (1/2)((2x)^2) ; [0, 0.5)
// y = -(1/2)((2x-1)*(2x-3) - 1) ; [0.5, 1]
float QuadraticInOut(float p) {
if (p < 0.5F) { // NOLINT
return 2 * p * p;
} else {
return (-2 * p * p) + (4 * p) - 1;
}
}
// Modeled after the cubic y = x^3
float CubicIn(float p) {
return p * p * p;
}
// Modeled after the cubic y = (x - 1)^3 + 1
float CubicOut(float p) {
const float f = (p - 1);
return f * f * f + 1;
}
// Modeled after the piecewise cubic
// y = (1/2)((2x)^3) ; [0, 0.5)
// y = (1/2)((2x-2)^3 + 2) ; [0.5, 1]
float CubicInOut(float p) {
if (p < 0.5F) { // NOLINT
return 4 * p * p * p;
} else {
const float f = ((2 * p) - 2);
return 0.5F * f * f * f + 1; // NOLINT
}
}
// Modeled after the quartic x^4
float QuarticIn(float p) {
return p * p * p * p;
}
// Modeled after the quartic y = 1 - (x - 1)^4
float QuarticOut(float p) {
const float f = (p - 1);
return f * f * f * (1 - p) + 1;
}
// Modeled after the piecewise quartic
// y = (1/2)((2x)^4) ; [0, 0.5)
// y = -(1/2)((2x-2)^4 - 2) ; [0.5, 1]
float QuarticInOut(float p) {
if (p < 0.5F) { // NOLINT
return 8 * p * p * p * p; // NOLINT
} else {
const float f = (p - 1);
return -8 * f * f * f * f + 1; // NOLINT
}
}
// Modeled after the quintic y = x^5
float QuinticIn(float p) {
return p * p * p * p * p;
}
// Modeled after the quintic y = (x - 1)^5 + 1
float QuinticOut(float p) {
const float f = (p - 1);
return f * f * f * f * f + 1;
}
// Modeled after the piecewise quintic
// y = (1/2)((2x)^5) ; [0, 0.5)
// y = (1/2)((2x-2)^5 + 2) ; [0.5, 1]
float QuinticInOut(float p) {
if (p < 0.5F) { // NOLINT
return 16 * p * p * p * p * p; // NOLINT
} else { // NOLINT
float f = ((2 * p) - 2); // NOLINT
return 0.5 * f * f * f * f * f + 1; // NOLINT
}
}
// Modeled after quarter-cycle of sine wave
float SineIn(float p) {
return std::sin((p - 1) * kPi2) + 1;
}
// Modeled after quarter-cycle of sine wave (different phase)
float SineOut(float p) {
return std::sin(p * kPi2);
}
// Modeled after half sine wave
float SineInOut(float p) {
return 0.5F * (1 - std::cos(p * kPi)); // NOLINT
}
// Modeled after shifted quadrant IV of unit circle
float CircularIn(float p) {
return 1 - std::sqrt(1 - (p * p));
}
// Modeled after shifted quadrant II of unit circle
float CircularOut(float p) {
return std::sqrt((2 - p) * p);
}
// Modeled after the piecewise circular function
// y = (1/2)(1 - sqrt(1 - 4x^2)) ; [0, 0.5)
// y = (1/2)(sqrt(-(2x - 3)*(2x - 1)) + 1) ; [0.5, 1]
float CircularInOut(float p) {
if (p < 0.5F) { // NOLINT
return 0.5F * (1 - std::sqrt(1 - 4 * (p * p))); // NOLINT
} else {
return 0.5F * (std::sqrt(-((2 * p) - 3) * ((2 * p) - 1)) + 1); // NOLINT
}
}
// Modeled after the exponential function y = 2^(10(x - 1))
float ExponentialIn(float p) {
return (p == 0.0) ? p : std::pow(2, 10 * (p - 1)); // NOLINT
}
// Modeled after the exponential function y = -2^(-10x) + 1
float ExponentialOut(float p) {
return (p == 1.0) ? p : 1 - std::pow(2, -10 * p); // NOLINT
}
// Modeled after the piecewise exponential
// y = (1/2)2^(10(2x - 1)) ; [0,0.5)
// y = -(1/2)*2^(-10(2x - 1))) + 1 ; [0.5,1]
float ExponentialInOut(float p) {
if (p == 0.0 || p == 1.F) {
return p;
}
if (p < 0.5F) { // NOLINT
return 0.5 * std::pow(2, (20 * p) - 10); // NOLINT
} else { // NOLINT
return -0.5 * std::pow(2, (-20 * p) + 10) + 1; // NOLINT
}
}
// Modeled after the damped sine wave y = sin(13pi/2*x)*pow(2, 10 * (x - 1))
float ElasticIn(float p) {
return std::sin(13.F * kPi2 * p) * std::pow(2.F, 10.F * (p - 1)); // NOLINT
}
// Modeled after the damped sine wave y = sin(-13pi/2*(x + 1))*pow(2, -10x) +
// 1
float ElasticOut(float p) {
// NOLINTNEXTLINE
return std::sin(-13.F * kPi2 * (p + 1)) * std::pow(2.F, -10.F * p) + 1;
}
// Modeled after the piecewise exponentially-damped sine wave:
// y = (1/2)*sin(13pi/2*(2*x))*pow(2, 10 * ((2*x) - 1)) ; [0,0.5)
// y = (1/2)*(sin(-13pi/2*((2x-1)+1))*pow(2,-10(2*x-1)) + 2) ; [0.5, 1]
float ElasticInOut(float p) {
if (p < 0.5F) { // NOLINT
return 0.5 * std::sin(13.F * kPi2 * (2 * p)) * // NOLINT
std::pow(2, 10 * ((2 * p) - 1)); // NOLINT
} else { // NOLINT
return 0.5 * (std::sin(-13.F * kPi2 * ((2 * p - 1) + 1)) * // NOLINT
std::pow(2, -10 * (2 * p - 1)) + // NOLINT
2); // NOLINT
}
}
// Modeled after the overshooting cubic y = x^3-x*sin(x*pi)
float BackIn(float p) {
return p * p * p - p * std::sin(p * kPi);
}
// Modeled after overshooting cubic y = 1-((1-x)^3-(1-x)*sin((1-x)*pi))
float BackOut(float p) {
const float f = (1 - p);
return 1 - (f * f * f - f * std::sin(f * kPi));
}
// Modeled after the piecewise overshooting cubic function:
// y = (1/2)*((2x)^3-(2x)*sin(2*x*pi)) ; [0, 0.5)
// y = (1/2)*(1-((1-x)^3-(1-x)*sin((1-x)*pi))+1) ; [0.5, 1]
float BackInOut(float p) {
if (p < 0.5F) { // NOLINT
const float f = 2 * p;
return 0.5F * (f * f * f - f * std::sin(f * kPi)); // NOLINT
} else {
float f = (1 - (2 * p - 1)); // NOLINT
return 0.5F * (1 - (f * f * f - f * std::sin(f * kPi))) + 0.5; // NOLINT
}
}
float BounceIn(float p) {
return 1 - BounceOut(1 - p);
}
float BounceOut(float p) {
if (p < 4 / 11.0) { // NOLINT
return (121 * p * p) / 16.0; // NOLINT
} else if (p < 8 / 11.0) { // NOLINT
return (363 / 40.0 * p * p) - (99 / 10.0 * p) + 17 / 5.0; // NOLINT
} else if (p < 9 / 10.0) { // NOLINT
return (4356 / 361.0 * p * p) - (35442 / 1805.0 * p) + // NOLINT
16061 / 1805.0; // NOLINT
} else { // NOLINT
return (54 / 5.0 * p * p) - (513 / 25.0 * p) + 268 / 25.0; // NOLINT
}
}
float BounceInOut(float p) { // NOLINT
if (p < 0.5F) { // NOLINT
return 0.5F * BounceIn(p * 2); // NOLINT
} else { // NOLINT
return 0.5F * BounceOut(p * 2 - 1) + 0.5F; // NOLINT
}
}
} // namespace easing
Animator::Animator(float* from,
float to,
Duration duration,
easing::Function easing_function,
Duration delay)
: value_(from),
from_(*from),
to_(to),
duration_(duration),
easing_function_(std::move(easing_function)),
current_(-delay) {
RequestAnimationFrame();
}
void Animator::OnAnimation(Params& params) {
current_ += params.duration();
if (current_ >= duration_) {
*value_ = to_;
return;
}
if (current_ <= Duration()) {
*value_ = from_;
} else {
*value_ = from_ +
(to_ - from_) * easing_function_(current_ / duration_); // NOLINT
}
RequestAnimationFrame();
}
} // namespace ftxui::animation

View File

@@ -0,0 +1,38 @@
#include <gtest/gtest.h>
#include <functional> // for function
#include <vector> // for allocator, vector
#include "ftxui/component/animation.hpp" // for Function, BackIn, BackInOut, BackOut, BounceIn, BounceInOut, BounceOut, CircularIn, CircularInOut, CircularOut, CubicIn, CubicInOut, CubicOut, ElasticIn, ElasticInOut, ElasticOut, ExponentialIn, ExponentialInOut, ExponentialOut, Linear, QuadraticIn, QuadraticInOut, QuadraticOut, QuarticIn, QuarticInOut, QuarticOut, QuinticIn, QuinticInOut, QuinticOut, SineIn, SineInOut, SineOut
namespace ftxui {
TEST(AnimationTest, StartAndEnd) {
std::vector<animation::easing::Function> functions = {
animation::easing::Linear, animation::easing::QuadraticIn,
animation::easing::QuadraticOut, animation::easing::QuadraticInOut,
animation::easing::CubicIn, animation::easing::CubicOut,
animation::easing::CubicInOut, animation::easing::QuarticIn,
animation::easing::QuarticOut, animation::easing::QuarticInOut,
animation::easing::QuinticIn, animation::easing::QuinticOut,
animation::easing::QuinticInOut, animation::easing::SineIn,
animation::easing::SineOut, animation::easing::SineInOut,
animation::easing::CircularIn, animation::easing::CircularOut,
animation::easing::CircularInOut, animation::easing::ExponentialIn,
animation::easing::ExponentialOut, animation::easing::ExponentialInOut,
animation::easing::ElasticIn, animation::easing::ElasticOut,
animation::easing::ElasticInOut, animation::easing::BackIn,
animation::easing::BackOut, animation::easing::BackInOut,
animation::easing::BounceIn, animation::easing::BounceOut,
animation::easing::BounceInOut,
};
for (auto& it : functions) {
EXPECT_NEAR(0.F, it(0.F), 1.0e-4);
EXPECT_NEAR(1.F, it(1.F), 1.0e-4);
}
}
} // namespace ftxui
// Copyright 2022 Arthur Sonzogni. All rights reserved.
// Use of this source code is governed by the MIT license that can be found in
// the LICENSE file.

View File

@@ -2,65 +2,33 @@
#include <memory> // for shared_ptr
#include <utility> // for move
#include "ftxui/component/captured_mouse.hpp" // for CapturedMouse
#include "ftxui/component/component.hpp" // for Make, Button
#include "ftxui/component/component_base.hpp" // for ComponentBase
#include "ftxui/component/component_options.hpp" // for ButtonOption
#include "ftxui/component/event.hpp" // for Event, Event::Return
#include "ftxui/component/animation.hpp" // for Animator, Params (ptr only)
#include "ftxui/component/captured_mouse.hpp" // for CapturedMouse
#include "ftxui/component/component.hpp" // for Make, Button
#include "ftxui/component/component_base.hpp" // for ComponentBase
#include "ftxui/component/component_options.hpp" // for ButtonOption, AnimatedColorOption, AnimatedColorsOption, EntryState
#include "ftxui/component/event.hpp" // for Event, Event::Return
#include "ftxui/component/mouse.hpp" // for Mouse, Mouse::Left, Mouse::Pressed
#include "ftxui/component/screen_interactive.hpp" // for Component
#include "ftxui/dom/elements.hpp" // for operator|, Element, nothing, reflect, text, border, inverted
#include "ftxui/screen/box.hpp" // for Box
#include "ftxui/util/ref.hpp" // for ConstStringRef, Ref
#include "ftxui/dom/elements.hpp" // for operator|, Decorator, Element, operator|=, bgcolor, color, reflect, text, bold, border, inverted, nothing
#include "ftxui/screen/box.hpp" // for Box
#include "ftxui/screen/color.hpp" // for Color
#include "ftxui/util/ref.hpp" // for Ref, ConstStringRef
namespace ftxui {
namespace {
class ButtonBase : public ComponentBase {
public:
ButtonBase(ConstStringRef label,
std::function<void()> on_click,
Ref<ButtonOption> option)
: label_(label), on_click_(on_click), option_(std::move(option)) {}
// Component implementation:
Element Render() override {
auto style = Focused() ? inverted : nothing;
auto my_border = option_->border ? border : nothing;
return text(*label_) | my_border | style | reflect(box_);
Element DefaultTransform(EntryState params) { // NOLINT
auto element = text(params.label) | border;
if (params.active) {
element |= bold;
}
bool OnEvent(Event event) override {
if (event.is_mouse() && box_.Contain(event.mouse().x, event.mouse().y)) {
if (!CaptureMouse(event))
return false;
TakeFocus();
if (event.mouse().button == Mouse::Left &&
event.mouse().motion == Mouse::Pressed) {
on_click_();
return true;
}
return false;
}
if (event == Event::Return) {
on_click_();
return true;
}
return false;
if (params.focused) {
element |= inverted;
}
bool Focusable() const final { return true; }
private:
ConstStringRef label_;
std::function<void()> on_click_;
Box box_;
Ref<ButtonOption> option_;
};
return element;
}
} // namespace
@@ -87,10 +55,135 @@ class ButtonBase : public ComponentBase {
/// │Click to quit│
/// └─────────────┘
/// ```
// NOLINTNEXTLINE(readability-function-cognitive-complexity)
Component Button(ConstStringRef label,
std::function<void()> on_click,
Ref<ButtonOption> option) {
return Make<ButtonBase>(label, std::move(on_click), std::move(option));
class Impl : public ComponentBase {
public:
Impl(ConstStringRef label,
std::function<void()> on_click,
Ref<ButtonOption> option)
: label_(std::move(label)),
on_click_(std::move(on_click)),
option_(std::move(option)) {}
// Component implementation:
Element Render() override {
const bool active = Active();
const bool focused = Focused();
const bool focused_or_hover = focused || mouse_hover_;
float target = focused_or_hover ? 1.F : 0.F; // NOLINT
if (target != animator_background_.to()) {
SetAnimationTarget(target);
}
auto focus_management = focused ? focus : active ? select : nothing;
const EntryState state = {
*label_,
false,
active,
focused_or_hover,
};
auto element =
(option_->transform ? option_->transform : DefaultTransform) //
(state);
return element | AnimatedColorStyle() | focus_management | reflect(box_);
}
Decorator AnimatedColorStyle() {
Decorator style = nothing;
if (option_->animated_colors.background.enabled) {
style = style | bgcolor(Color::Interpolate(
animation_foreground_, //
option_->animated_colors.background.inactive,
option_->animated_colors.background.active));
}
if (option_->animated_colors.foreground.enabled) {
style = style | color(Color::Interpolate(
animation_foreground_, //
option_->animated_colors.foreground.inactive,
option_->animated_colors.foreground.active));
}
return style;
}
void SetAnimationTarget(float target) {
if (option_->animated_colors.foreground.enabled) {
animator_foreground_ =
animation::Animator(&animation_foreground_, target,
option_->animated_colors.foreground.duration,
option_->animated_colors.foreground.function);
}
if (option_->animated_colors.background.enabled) {
animator_background_ =
animation::Animator(&animation_background_, target,
option_->animated_colors.background.duration,
option_->animated_colors.background.function);
}
}
void OnAnimation(animation::Params& p) override {
animator_background_.OnAnimation(p);
animator_foreground_.OnAnimation(p);
}
void OnClick() {
on_click_();
animation_background_ = 0.5F; // NOLINT
animation_foreground_ = 0.5F; // NOLINT
SetAnimationTarget(1.F); // NOLINT
}
bool OnEvent(Event event) override {
if (event.is_mouse()) {
return OnMouseEvent(event);
}
if (event == Event::Return) {
OnClick();
return true;
}
return false;
}
bool OnMouseEvent(Event event) {
mouse_hover_ =
box_.Contain(event.mouse().x, event.mouse().y) && CaptureMouse(event);
if (!mouse_hover_) {
return false;
}
if (event.mouse().button == Mouse::Left &&
event.mouse().motion == Mouse::Pressed) {
TakeFocus();
OnClick();
return true;
}
return false;
}
bool Focusable() const final { return true; }
private:
ConstStringRef label_;
std::function<void()> on_click_;
bool mouse_hover_ = false;
Box box_;
Ref<ButtonOption> option_;
float animation_background_ = 0;
float animation_foreground_ = 0;
animation::Animator animator_background_ =
animation::Animator(&animation_background_);
animation::Animator animator_foreground_ =
animation::Animator(&animation_foreground_);
};
return Make<Impl>(std::move(label), std::move(on_click), std::move(option));
}
} // namespace ftxui

View File

@@ -0,0 +1,195 @@
#include <gtest/gtest.h> // for AssertionResult, Message, TestPartResult, EXPECT_EQ, Test, EXPECT_FALSE, EXPECT_TRUE, TestInfo (ptr only), TEST
#include <chrono> // for operator""s, chrono_literals
#include <memory> // for __shared_ptr_access, shared_ptr, allocator
#include <string> // for string
#include "ftxui/component/animation.hpp" // for Duration, Params
#include "ftxui/component/component.hpp" // for Button, Horizontal
#include "ftxui/component/component_base.hpp" // for ComponentBase
#include "ftxui/component/component_options.hpp" // for ButtonOption
#include "ftxui/component/event.hpp" // for Event, Event::Return, Event::ArrowLeft, Event::ArrowRight
#include "ftxui/component/mouse.hpp" // for Mouse, Mouse::Left, Mouse::Pressed
#include "ftxui/dom/node.hpp" // for Render
#include "ftxui/screen/screen.hpp" // for Screen
#include "ftxui/screen/terminal.hpp" // for SetColorSupport, Color, TrueColor
namespace ftxui {
namespace {
Event MousePressed(int x, int y) {
Mouse mouse;
mouse.button = Mouse::Left;
mouse.motion = Mouse::Pressed;
mouse.shift = false;
mouse.meta = false;
mouse.control = false;
mouse.x = x;
mouse.y = y;
return Event::Mouse("jjj", mouse);
}
} // namespace
using namespace std::chrono_literals;
TEST(ButtonTest, Basic) {
int press_count = 0;
std::string last_press = "";
auto btn1 = Button("btn1", [&] {
press_count++;
last_press = "btn1";
});
auto btn2 = Button("btn2", [&] {
press_count++;
last_press = "btn2";
});
int selected = 0;
auto container = Container::Horizontal(
{
btn1,
btn2,
},
&selected);
(void)container->Render();
EXPECT_EQ(selected, 0);
EXPECT_TRUE(btn1->Focused());
EXPECT_FALSE(btn2->Focused());
container->OnEvent(Event::ArrowLeft);
EXPECT_EQ(selected, 0);
EXPECT_TRUE(btn1->Focused());
EXPECT_FALSE(btn2->Focused());
container->OnEvent(Event::ArrowRight);
EXPECT_EQ(selected, 1);
EXPECT_FALSE(btn1->Focused());
EXPECT_TRUE(btn2->Focused());
container->OnEvent(Event::ArrowRight);
EXPECT_EQ(selected, 1);
EXPECT_FALSE(btn1->Focused());
EXPECT_TRUE(btn2->Focused());
EXPECT_EQ(press_count, 0);
container->OnEvent(Event::Return);
EXPECT_EQ(press_count, 1);
EXPECT_EQ(last_press, "btn2");
container->OnEvent(Event::Return);
EXPECT_EQ(press_count, 2);
EXPECT_EQ(last_press, "btn2");
container->OnEvent(Event::ArrowLeft);
container->OnEvent(Event::Return);
EXPECT_EQ(press_count, 3);
EXPECT_EQ(last_press, "btn1");
(void)container->Render();
}
TEST(ButtonTest, Animation) {
Terminal::SetColorSupport(Terminal::Color::TrueColor);
int press_count = 0;
std::string last_press = "";
auto option = ButtonOption::Animated();
auto btn1 = Button(
"btn1",
[&] {
press_count++;
last_press = "btn1";
},
option);
auto btn2 = Button(
"btn2",
[&] {
press_count++;
last_press = "btn2";
},
option);
int selected = 0;
auto container = Container::Horizontal(
{
btn1,
btn2,
},
&selected);
{
Screen screen(12, 3);
Render(screen, container->Render());
EXPECT_EQ(screen.ToString(),
"\x1B[1m\x1B[38;2;192;192;192m\x1B[48;2;0;0;0m \x1B[22m "
" \x1B[39m\x1B[49m\r\n\x1B[1m\x1B[38;2;192;192;192m\x1B[48;2;0;0;"
"0m btn1 \x1B[22m btn2 "
"\x1B[39m\x1B[49m\r\n\x1B[1m\x1B[38;2;192;192;192m\x1B[48;2;0;0;"
"0m \x1B[22m \x1B[39m\x1B[49m");
}
selected = 1;
{
Screen screen(12, 3);
Render(screen, container->Render());
EXPECT_EQ(screen.ToString(),
"\x1B[38;2;192;192;192m\x1B[48;2;0;0;0m \x1B[1m "
"\x1B[22m\x1B[39m\x1B[49m\r\n\x1B[38;2;192;192;192m\x1B[48;2;0;0;"
"0m btn1 \x1B[1m btn2 "
"\x1B[22m\x1B[39m\x1B[49m\r\n\x1B[38;2;192;192;192m\x1B[48;2;0;0;"
"0m \x1B[1m \x1B[22m\x1B[39m\x1B[49m");
}
animation::Params params(2s);
container->OnAnimation(params);
{
Screen screen(12, 3);
Render(screen, container->Render());
EXPECT_EQ(
screen.ToString(),
"\x1B[38;2;192;192;192m\x1B[48;2;0;0;0m "
"\x1B[1m\x1B[38;2;255;255;255m\x1B[48;2;128;128;128m "
"\x1B[22m\x1B[39m\x1B[49m\r\n\x1B[38;2;192;192;192m\x1B[48;2;0;0;0m "
"btn1 \x1B[1m\x1B[38;2;255;255;255m\x1B[48;2;128;128;128m btn2 "
"\x1B[22m\x1B[39m\x1B[49m\r\n\x1B[38;2;192;192;192m\x1B[48;2;0;0;0m "
" \x1B[1m\x1B[38;2;255;255;255m\x1B[48;2;128;128;128m "
"\x1B[22m\x1B[39m\x1B[49m");
}
EXPECT_EQ(selected, 1);
container->OnEvent(MousePressed(3, 1));
EXPECT_EQ(selected, 0);
{
Screen screen(12, 3);
Render(screen, container->Render());
EXPECT_EQ(
screen.ToString(),
"\x1B[1m\x1B[38;2;223;223;223m\x1B[48;2;64;64;64m "
"\x1B[22m\x1B[38;2;255;255;255m\x1B[48;2;128;128;128m "
"\x1B[39m\x1B[49m\r\n\x1B[1m\x1B[38;2;223;223;223m\x1B[48;2;64;64;64m "
"btn1 \x1B[22m\x1B[38;2;255;255;255m\x1B[48;2;128;128;128m btn2 "
"\x1B[39m\x1B[49m\r\n\x1B[1m\x1B[38;2;223;223;223m\x1B[48;2;64;64;64m "
" \x1B[22m\x1B[38;2;255;255;255m\x1B[48;2;128;128;128m "
"\x1B[39m\x1B[49m");
}
container->OnAnimation(params);
{
Screen screen(12, 3);
Render(screen, container->Render());
EXPECT_EQ(
screen.ToString(),
"\x1B[1m\x1B[38;2;255;255;255m\x1B[48;2;128;128;128m "
"\x1B[22m\x1B[38;2;192;192;192m\x1B[48;2;0;0;0m "
"\x1B[39m\x1B[49m\r\n\x1B[1m\x1B[38;2;255;255;255m\x1B[48;2;128;128;"
"128m btn1 \x1B[22m\x1B[38;2;192;192;192m\x1B[48;2;0;0;0m btn2 "
"\x1B[39m\x1B[49m\r\n\x1B[1m\x1B[38;2;255;255;255m\x1B[48;2;128;128;"
"128m \x1B[22m\x1B[38;2;192;192;192m\x1B[48;2;0;0;0m "
"\x1B[39m\x1B[49m");
}
}
} // namespace ftxui
// Copyright 2022 Arthur Sonzogni. All rights reserved.
// Use of this source code is governed by the MIT license that can be found in
// the LICENSE file.

View File

@@ -1,9 +1,10 @@
#include <functional> // for function
#include <memory> // for __shared_ptr_access, __shared_ptr_access<>::element_type, shared_ptr
#include <utility> // for move
#include <type_traits> // for remove_reference, remove_reference<>::type
#include <utility> // for move
#include "ftxui/component/component.hpp" // for Component, Make, CatchEvent
#include "ftxui/component/component_base.hpp" // for ComponentBase
#include "ftxui/component/component.hpp" // for Make, CatchEvent, ComponentDecorator
#include "ftxui/component/component_base.hpp" // for Component, ComponentBase
#include "ftxui/component/event.hpp" // for Event
namespace ftxui {
@@ -11,15 +12,16 @@ namespace ftxui {
class CatchEventBase : public ComponentBase {
public:
// Constructor.
CatchEventBase(std::function<bool(Event)> on_event)
explicit CatchEventBase(std::function<bool(Event)> on_event)
: on_event_(std::move(on_event)) {}
// Component implementation.
bool OnEvent(Event event) override {
if (on_event_(event))
if (on_event_(event)) {
return true;
else
} else {
return ComponentBase::OnEvent(event);
}
}
protected:
@@ -39,7 +41,14 @@ class CatchEventBase : public ComponentBase {
/// auto renderer = Renderer([] {
/// return text("My interface");
/// });
/// screen.Loop(renderer);
/// auto component = CatchEvent(renderer, [&](Event event) {
/// if (event == Event::Character('q')) {
/// screen.ExitLoopClosure()();
/// return true;
/// }
/// return false;
/// });
/// screen.Loop(component);
/// ```
Component CatchEvent(Component child,
std::function<bool(Event event)> on_event) {
@@ -48,6 +57,33 @@ Component CatchEvent(Component child,
return out;
}
/// @brief Decorate a component, using |on_event| to catch events. This function
/// must returns true when the event has been handled, false otherwise.
/// @param on_event The function drawing the interface.
/// @ingroup component
///
/// ### Example
///
/// ```cpp
/// auto screen = ScreenInteractive::TerminalOutput();
/// auto renderer = Renderer([] { return text("Hello world"); });
/// renderer |= CatchEvent([&](Event event) {
/// if (event == Event::Character('q')) {
/// screen.ExitLoopClosure()();
/// return true;
/// }
/// return false;
/// });
/// screen.Loop(renderer);
/// ```
ComponentDecorator CatchEvent(std::function<bool(Event)> on_event) {
return [on_event = std::move(on_event)](Component child) {
return CatchEvent(std::move(child), [on_event = on_event](Event event) {
return on_event(std::move(event));
});
};
}
} // namespace ftxui
// Copyright 2021 Arthur Sonzogni. All rights reserved.

View File

@@ -1,14 +1,13 @@
#include <functional> // for function
#include <memory> // for shared_ptr
#include <utility> // for move
#include "ftxui/component/captured_mouse.hpp" // for CapturedMouse
#include "ftxui/component/component.hpp" // for Make, Component, Checkbox
#include "ftxui/component/component_base.hpp" // for ComponentBase
#include "ftxui/component/component_options.hpp" // for CheckboxOption
#include "ftxui/component/component.hpp" // for Make, Checkbox
#include "ftxui/component/component_base.hpp" // for Component, ComponentBase
#include "ftxui/component/component_options.hpp" // for CheckboxOption, EntryState
#include "ftxui/component/event.hpp" // for Event, Event::Return
#include "ftxui/component/mouse.hpp" // for Mouse, Mouse::Left, Mouse::Pressed
#include "ftxui/dom/elements.hpp" // for operator|, text, Element, hbox, reflect, focus, nothing, select
#include "ftxui/dom/elements.hpp" // for operator|, Element, reflect, focus, nothing, select
#include "ftxui/screen/box.hpp" // for Box
#include "ftxui/util/ref.hpp" // for Ref, ConstStringRef
@@ -18,40 +17,34 @@ namespace {
class CheckboxBase : public ComponentBase {
public:
CheckboxBase(ConstStringRef label, bool* state, Ref<CheckboxOption> option)
: label_(label), state_(state), option_(std::move(option)) {
#if defined(FTXUI_MICROSOFT_TERMINAL_FALLBACK)
// Microsoft terminal do not use fonts able to render properly the default
// radiobox glyph.
if (option_->style_checked == "")
option_->style_checked = "[X]";
if (option_->style_unchecked == "")
option_->style_unchecked = "[ ]";
#endif
}
: label_(std::move(label)), state_(state), option_(std::move(option)) {}
private:
// Component implementation.
Element Render() override {
bool is_focused = Focused();
bool is_active = Active();
auto style = (is_focused || hovered_) ? option_->style_selected_focused
: is_active ? option_->style_selected
: option_->style_normal;
const bool is_focused = Focused();
const bool is_active = Active();
auto focus_management = is_focused ? focus : is_active ? select : nothing;
return hbox({
text(*state_ ? option_->style_checked
: option_->style_unchecked),
text(*label_) | style | focus_management,
}) |
reflect(box_);
auto state = EntryState{
*label_,
*state_,
is_active,
is_focused || hovered_,
};
auto element =
(option_->transform ? option_->transform
: CheckboxOption::Simple().transform)(state);
return element | focus_management | reflect(box_);
}
bool OnEvent(Event event) override {
if (!CaptureMouse(event))
if (!CaptureMouse(event)) {
return false;
}
if (event.is_mouse())
if (event.is_mouse()) {
return OnMouseEvent(event);
}
hovered_ = false;
if (event == Event::Character(' ') || event == Event::Return) {
@@ -66,11 +59,13 @@ class CheckboxBase : public ComponentBase {
bool OnMouseEvent(Event event) {
hovered_ = box_.Contain(event.mouse().x, event.mouse().y);
if (!CaptureMouse(event))
if (!CaptureMouse(event)) {
return false;
}
if (!hovered_)
if (!hovered_) {
return false;
}
if (event.mouse().button == Mouse::Left &&
event.mouse().motion == Mouse::Pressed) {
@@ -117,7 +112,7 @@ class CheckboxBase : public ComponentBase {
Component Checkbox(ConstStringRef label,
bool* checked,
Ref<CheckboxOption> option) {
return Make<CheckboxBase>(label, checked, std::move(option));
return Make<CheckboxBase>(std::move(label), checked, std::move(option));
}
} // namespace ftxui

View File

@@ -1,10 +1,12 @@
#include <string> // for string
#include <utility> // for move
#include <functional> // for function
#include <memory> // for shared_ptr, allocator
#include <utility> // for move
#include "ftxui/component/component.hpp" // for Checkbox, Maybe, Make, Vertical, Collapsible
#include "ftxui/component/component_base.hpp" // for Component, ComponentBase
#include "ftxui/component/component_options.hpp" // for CheckboxOption
#include "ftxui/util/ref.hpp" // for Ref, ConstStringRef
#include "ftxui/component/component_options.hpp" // for CheckboxOption, EntryState
#include "ftxui/dom/elements.hpp" // for operator|=, text, hbox, Element, bold, inverted
#include "ftxui/util/ref.hpp" // for Ref, ConstStringRef
namespace ftxui {
@@ -24,25 +26,32 @@ namespace ftxui {
///
/// ▼ Show details
/// <details component>
/// ```
///  ```
Component Collapsible(ConstStringRef label, Component child, Ref<bool> show) {
class Impl : public ComponentBase {
public:
Impl(ConstStringRef label, Component child, Ref<bool> show)
: label_(label), show_(std::move(show)) {
Impl(ConstStringRef label, Component child, Ref<bool> show) : show_(show) {
CheckboxOption opt;
opt.style_checked = "";
opt.style_unchecked = "";
opt.transform = [](EntryState s) { // NOLINT
auto prefix = text(s.state ? "" : ""); // NOLINT
auto t = text(s.label);
if (s.active) {
t |= bold;
}
if (s.focused) {
t |= inverted;
}
return hbox({prefix, t});
};
Add(Container::Vertical({
Checkbox(label_, show_.operator->(), opt),
Checkbox(std::move(label), show_.operator->(), opt),
Maybe(std::move(child), show_.operator->()),
}));
}
ConstStringRef label_;
Ref<bool> show_;
};
return Make<Impl>(label, std::move(child), std::move(show));
return Make<Impl>(std::move(label), std::move(child), show);
}
} // namespace ftxui

View File

@@ -0,0 +1,53 @@
#include <gtest/gtest.h>
#include <memory> // for __shared_ptr_access, shared_ptr, allocator
#include "ftxui/component/component.hpp" // for Collapsible, Renderer
#include "ftxui/component/component_base.hpp" // for ComponentBase
#include "ftxui/component/event.hpp" // for Event, Event::Return, Event::ArrowDown
#include "ftxui/dom/elements.hpp" // for text, Element
#include "ftxui/dom/node.hpp" // for Render
#include "ftxui/screen/screen.hpp" // for Screen
namespace ftxui {
TEST(CollapsibleTest, Basic) {
auto child = Renderer([] { return text("child"); });
bool show = false;
auto collapsible = Collapsible("parent", child, &show);
EXPECT_TRUE(collapsible->Focused());
EXPECT_FALSE(child->Focused());
EXPECT_FALSE(collapsible->OnEvent(Event::ArrowDown));
EXPECT_TRUE(collapsible->Focused());
EXPECT_FALSE(child->Focused());
{
Screen screen(8, 3);
Render(screen, collapsible->Render());
EXPECT_EQ(screen.ToString(),
"\xE2\x96\xB6 \x1B[1m\x1B[7mparent\x1B[22m\x1B[27m\r\n"
" \r\n"
" ");
}
collapsible->OnEvent(Event::Return);
EXPECT_EQ(show, true);
{
Screen screen(8, 3);
Render(screen, collapsible->Render());
EXPECT_EQ(screen.ToString(),
"\xE2\x96\xBC \x1B[1m\x1B[7mparent\x1B[22m\x1B[27m\r\n"
"child \r\n"
" ");
}
collapsible->OnEvent(Event::Return);
EXPECT_EQ(show, false);
}
} // namespace ftxui
// Copyright 2022 Arthur Sonzogni. All rights reserved.
// Use of this source code is governed by the MIT license that can be found in
// the LICENSE file.

View File

@@ -1,6 +1,6 @@
#include <stddef.h> // for size_t
#include <algorithm> // for find_if
#include <cassert> // for assert
#include <cstddef> // for size_t
#include <iterator> // for begin, end
#include <utility> // for move
#include <vector> // for vector, __alloc_traits<>::value_type
@@ -12,6 +12,10 @@
#include "ftxui/component/screen_interactive.hpp" // for Component, ScreenInteractive
#include "ftxui/dom/elements.hpp" // for text, Element
namespace ftxui::animation {
class Params;
} // namespace ftxui::animation
namespace ftxui {
namespace {
@@ -33,7 +37,7 @@ ComponentBase* ComponentBase::Parent() const {
/// @brief Access the child at index `i`.
/// @ingroup component
Component& ComponentBase::ChildAt(size_t i) {
assert(i < ChildCount());
assert(i < ChildCount()); // NOLINT
return children_[i];
}
@@ -57,8 +61,9 @@ void ComponentBase::Add(Component child) {
/// @see Parent
/// @ingroup component
void ComponentBase::Detach() {
if (!parent_)
if (parent_ == nullptr) {
return;
}
auto it = std::find_if(std::begin(parent_->children_), //
std::end(parent_->children_), //
[this](const Component& that) { //
@@ -72,8 +77,9 @@ void ComponentBase::Detach() {
/// @brief Remove all children.
/// @ingroup component
void ComponentBase::DetachAllChildren() {
while (!children_.empty())
while (!children_.empty()) {
children_[0]->Detach();
}
}
/// @brief Draw the component.
@@ -81,8 +87,9 @@ void ComponentBase::DetachAllChildren() {
/// ftxui::ComponentBase.
/// @ingroup component
Element ComponentBase::Render() {
if (children_.size() == 1)
if (children_.size() == 1) {
return children_.front()->Render();
}
return text("Not implemented component");
}
@@ -93,19 +100,35 @@ Element ComponentBase::Render() {
/// The default implementation called OnEvent on every child until one return
/// true. If none returns true, return false.
/// @ingroup component
bool ComponentBase::OnEvent(Event event) {
for (Component& child : children_) {
if (child->OnEvent(event))
bool ComponentBase::OnEvent(Event event) { // NOLINT
for (Component& child : children_) { // NOLINT
if (child->OnEvent(event)) {
return true;
}
}
return false;
}
/// @brief Called in response to an animation event.
/// @param animation_params the parameters of the animation
/// The default implementation dispatch the event to every child.
/// @ingroup component
void ComponentBase::OnAnimation(animation::Params& params) {
for (const Component& child : children_) {
child->OnAnimation(params);
}
}
/// @brief Return the currently Active child.
/// @return the currently Active child.
/// @ingroup component
Component ComponentBase::ActiveChild() {
return children_.empty() ? nullptr : children_.front();
for (auto& child : children_) {
if (child->Focusable()) {
return child;
}
}
return nullptr;
}
/// @brief Return true when the component contains focusable elements.
@@ -113,9 +136,10 @@ Component ComponentBase::ActiveChild() {
/// keyboard.
/// @ingroup component
bool ComponentBase::Focusable() const {
for (const Component& child : children_) {
if (child->Focusable())
for (const Component& child : children_) { // NOLINT
if (child->Focusable()) {
return true;
}
}
return false;
}
@@ -123,30 +147,31 @@ bool ComponentBase::Focusable() const {
/// @brief Returns if the element if the currently active child of its parent.
/// @ingroup component
bool ComponentBase::Active() const {
return !parent_ || parent_->ActiveChild().get() == this;
return parent_ == nullptr || parent_->ActiveChild().get() == this;
}
/// @brief Returns if the elements if focused by the user.
/// True when the ComponentBase is focused by the user. An element is Focused
/// when it is with all its ancestors the ActiveChild() of their parents.
/// when it is with all its ancestors the ActiveChild() of their parents, and it
/// Focusable().
/// @ingroup component
bool ComponentBase::Focused() const {
auto current = this;
const auto* current = this;
while (current && current->Active()) {
current = current->parent_;
}
return !current;
return !current && Focusable();
}
/// @brief Make the |child| to be the "active" one.
/// @param child the child to become active.
/// @ingroup component
void ComponentBase::SetActiveChild(ComponentBase*) {}
void ComponentBase::SetActiveChild(ComponentBase* /*child*/) {}
/// @brief Make the |child| to be the "active" one.
/// @param child the child to become active.
/// @ingroup component
void ComponentBase::SetActiveChild(Component child) {
void ComponentBase::SetActiveChild(Component child) { // NOLINT
SetActiveChild(child.get());
}
@@ -164,9 +189,10 @@ void ComponentBase::TakeFocus() {
/// them. It represents a component taking priority over others.
/// @param event
/// @ingroup component
CapturedMouse ComponentBase::CaptureMouse(const Event& event) {
if (event.screen_)
CapturedMouse ComponentBase::CaptureMouse(const Event& event) { // NOLINT
if (event.screen_) {
return event.screen_->CaptureMouse();
}
return std::make_unique<CaptureMouseImpl>();
}

View File

@@ -1,5 +1,5 @@
#include <iostream>
#include <cassert>
#include <iostream>
#include <vector>
#include "ftxui/component/component.hpp"
#include "ftxui/component/terminal_input_parser.hpp"
@@ -44,6 +44,63 @@ int GeneratorInt(const char* data, size_t size) {
return out;
}
Color GeneratorColor(const char* data, size_t size) {
return Color::RGB(GeneratorInt(data, size), GeneratorInt(data, size),
GeneratorInt(data, size));
}
AnimatedColorOption GeneratorAnimatedColorOption(const char* data,
size_t size) {
AnimatedColorOption option;
option.enabled = GeneratorBool(data, size);
option.inactive = GeneratorColor(data, size);
option.active = GeneratorColor(data, size);
option.duration = std::chrono::milliseconds(GeneratorInt(data, size));
return option;
}
AnimatedColorsOption GeneratorAnimatedColorsOptions(const char* data,
size_t size) {
AnimatedColorsOption option;
option.background = GeneratorAnimatedColorOption(data, size);
option.foreground = GeneratorAnimatedColorOption(data, size);
return option;
}
ButtonOption GeneratorButtonOption(const char* data, size_t size) {
ButtonOption option;
option.animated_colors = GeneratorAnimatedColorsOptions(data, size);
return option;
}
UnderlineOption GeneratorUnderlineOption(const char* data, size_t size) {
UnderlineOption option;
option.enabled = GeneratorBool(data, size);
option.color_active = GeneratorColor(data, size);
option.color_inactive = GeneratorColor(data, size);
option.leader_duration = std::chrono::milliseconds(GeneratorInt(data, size));
option.follower_duration =
std::chrono::milliseconds(GeneratorInt(data, size));
option.leader_delay = std::chrono::milliseconds(GeneratorInt(data, size));
option.follower_delay = std::chrono::milliseconds(GeneratorInt(data, size));
return option;
}
MenuEntryOption GeneratorMenuEntryOption(const char* data, size_t size) {
MenuEntryOption option;
option.animated_colors = GeneratorAnimatedColorsOptions(data, size);
return option;
}
MenuOption GeneratorMenuOption(const char* data, size_t size) {
MenuOption option;
option.underline = GeneratorUnderlineOption(data, size);
option.entries = GeneratorMenuEntryOption(data, size);
option.direction =
static_cast<MenuOption::Direction>(GeneratorInt(data, size) % 4);
return option;
}
bool g_bool;
int g_int;
std::vector<std::string> g_list;
@@ -60,13 +117,15 @@ Component GeneratorComponent(const char*& data, size_t& size, int depth) {
value = (value % value_max + value_max) % value_max;
switch (value) {
case 0:
return Button(GeneratorString(data, size), [] {});
return Button(
GeneratorString(data, size), [] {},
GeneratorButtonOption(data, size));
case 1:
return Checkbox(GeneratorString(data, size), &g_bool);
case 2:
return Input(GeneratorString(data, size), GeneratorString(data, size));
case 3:
return Menu(&g_list, &g_int);
return Menu(&g_list, &g_int, GeneratorMenuOption(data, size));
case 4:
return Radiobox(&g_list, &g_int);
case 5:
@@ -151,16 +210,16 @@ extern "C" int LLVMFuzzerTestOneInput(const char* data, size_t size) {
auto screen =
Screen::Create(Dimension::Fixed(width), Dimension::Fixed(height));
auto event_receiver = MakeReceiver<Event>();
auto event_receiver = MakeReceiver<Task>();
{
auto parser = TerminalInputParser(event_receiver->MakeSender());
for (size_t i = 0; i < size; ++i)
parser.Add(data[i]);
}
Event event;
Task event;
while (event_receiver->Receive(&event)) {
component->OnEvent(event);
component->OnEvent(std::get<Event>(event));
auto document = component->Render();
Render(screen, document);
}

View File

@@ -0,0 +1,264 @@
#include "ftxui/component/component_options.hpp"
#include <ftxui/screen/color.hpp> // for Color, Color::Black, Color::White, Color::GrayDark, Color::GrayLight
#include <memory> // for shared_ptr
#include <utility> // for move
#include "ftxui/component/animation.hpp" // for Function, Duration
#include "ftxui/dom/elements.hpp" // for operator|=, text, Element, bold, inverted, operator|, dim, hbox, automerge, borderEmpty, borderLight
namespace ftxui {
void AnimatedColorOption::Set(Color a_inactive,
Color a_active,
animation::Duration a_duration,
animation::easing::Function a_function) {
enabled = true;
inactive = a_inactive;
active = a_active;
duration = a_duration;
function = std::move(a_function);
}
void UnderlineOption::SetAnimation(animation::Duration d,
animation::easing::Function f) {
SetAnimationDuration(d);
SetAnimationFunction(std::move(f));
}
void UnderlineOption::SetAnimationDuration(animation::Duration d) {
leader_duration = d;
follower_duration = d;
}
void UnderlineOption::SetAnimationFunction(animation::easing::Function f) {
leader_function = f;
follower_function = std::move(f);
}
void UnderlineOption::SetAnimationFunction(
animation::easing::Function f_leader,
animation::easing::Function f_follower) {
leader_function = std::move(f_leader);
follower_function = std::move(f_follower);
}
// static
MenuOption MenuOption::Horizontal() {
MenuOption option;
option.direction = Direction::Right;
option.entries.transform = [](const EntryState& state) {
Element e = text(state.label);
if (state.focused) {
e |= inverted;
}
if (state.active) {
e |= bold;
}
if (!state.focused && !state.active) {
e |= dim;
}
return e;
};
option.elements_infix = [] { return text(" "); };
return option;
}
// static
MenuOption MenuOption::HorizontalAnimated() {
auto option = Horizontal();
option.underline.enabled = true;
return option;
}
// static
MenuOption MenuOption::Vertical() {
MenuOption option;
option.entries.transform = [](const EntryState& state) {
Element e = text((state.active ? "> " : " ") + state.label); // NOLINT
if (state.focused) {
e |= inverted;
}
if (state.active) {
e |= bold;
}
if (!state.focused && !state.active) {
e |= dim;
}
return e;
};
return option;
}
// static
MenuOption MenuOption::VerticalAnimated() {
auto option = MenuOption::Vertical();
option.entries.transform = [](const EntryState& state) {
Element e = text(state.label);
if (state.focused) {
e |= inverted;
}
if (state.active) {
e |= bold;
}
if (!state.focused && !state.active) {
e |= dim;
}
return e;
};
option.underline.enabled = true;
return option;
}
// static
MenuOption MenuOption::Toggle() {
auto option = MenuOption::Horizontal();
option.elements_infix = [] { return text("") | automerge; };
return option;
}
/// @brief Create a ButtonOption, highlighted using [] characters.
// static
ButtonOption ButtonOption::Ascii() {
ButtonOption option;
option.transform = [](const EntryState& s) {
const std::string label = s.focused ? "[" + s.label + "]" //
: " " + s.label + " ";
return text(label);
};
return option;
}
/// @brief Create a ButtonOption, inverted when focused.
// static
ButtonOption ButtonOption::Simple() {
ButtonOption option;
option.transform = [](const EntryState& s) {
auto element = text(s.label) | borderLight;
if (s.focused) {
element |= inverted;
}
return element;
};
return option;
}
/// @brief Create a ButtonOption. The button is shown using a border, inverted
/// when focused. This is the current default.
ButtonOption ButtonOption::Border() {
ButtonOption option;
option.transform = [](const EntryState& s) {
auto element = text(s.label) | border;
if (s.active) {
element |= bold;
}
if (s.focused) {
element |= inverted;
}
return element;
};
return option;
}
/// @brief Create a ButtonOption, using animated colors.
// static
ButtonOption ButtonOption::Animated() {
return Animated(Color::Black, Color::GrayLight, //
Color::GrayDark, Color::White);
}
/// @brief Create a ButtonOption, using animated colors.
// static
ButtonOption ButtonOption::Animated(Color color) {
return ButtonOption::Animated(
Color::Interpolate(0.85F, color, Color::Black), // NOLINT
Color::Interpolate(0.10F, color, Color::White), // NOLINT
Color::Interpolate(0.10F, color, Color::Black), // NOLINT
Color::Interpolate(0.85F, color, Color::White)); // NOLINT
}
/// @brief Create a ButtonOption, using animated colors.
// static
ButtonOption ButtonOption::Animated(Color background, Color foreground) {
// NOLINTBEGIN
return ButtonOption::Animated(
/*bakground=*/background,
/*foreground=*/foreground,
/*background_active=*/foreground,
/*foreground_active=*/background);
// NOLINTEND
}
/// @brief Create a ButtonOption, using animated colors.
// static
ButtonOption ButtonOption::Animated(Color background,
Color foreground,
Color background_active,
Color foreground_active) {
ButtonOption option;
option.transform = [](const EntryState& s) {
auto element = text(s.label) | borderEmpty;
if (s.focused) {
element |= bold;
}
return element;
};
option.animated_colors.foreground.Set(foreground, foreground_active);
option.animated_colors.background.Set(background, background_active);
return option;
}
/// @brief Option for standard Checkbox.
// static
CheckboxOption CheckboxOption::Simple() {
auto option = CheckboxOption();
option.transform = [](const EntryState& s) {
#if defined(FTXUI_MICROSOFT_TERMINAL_FALLBACK)
// Microsoft terminal do not use fonts able to render properly the default
// radiobox glyph.
auto prefix = text(s.state ? "[X] " : "[ ] "); // NOLINT
#else
auto prefix = text(s.state ? "" : ""); // NOLINT
#endif
auto t = text(s.label);
if (s.active) {
t |= bold;
}
if (s.focused) {
t |= inverted;
}
return hbox({prefix, t});
};
return option;
}
/// @brief Option for standard Radiobox
// static
RadioboxOption RadioboxOption::Simple() {
auto option = RadioboxOption();
option.transform = [](const EntryState& s) {
#if defined(FTXUI_MICROSOFT_TERMINAL_FALLBACK)
// Microsoft terminal do not use fonts able to render properly the default
// radiobox glyph.
auto prefix = text(s.state ? "(*) " : "( ) "); // NOLINT
#else
auto prefix = text(s.state ? "" : ""); // NOLINT
#endif
auto t = text(s.label);
if (s.active) {
t |= bold;
}
if (s.focused) {
t |= inverted;
}
return hbox({prefix, t});
};
return option;
}
} // namespace ftxui
// Copyright 2022 Arthur Sonzogni. All rights reserved.
// Use of this source code is governed by the MIT license that can be found in
// the LICENSE file.

Some files were not shown because too many files have changed in this diff Show More