ArthurSonzogni / FTXUI

:computer: C++ Functional Terminal User Interface. :heart:
MIT License
6.73k stars 401 forks source link

Add canvas element #154

Closed felixjulianheitmann closed 2 years ago

felixjulianheitmann commented 3 years ago

I really enjoy playing with your library and the command line tools.

I just wanted to illustrate a geometric configuration of points in a circle and wanted to write to the pixels. I know, I can somehow access the pixels of the terminal, but I would really like to define an area like a canvas of certain width and height. There, I would like to be able to edit the different pixels in either black/white, as characters or maybe some form of ASCII art greyscale. But that is not necessary.

I just want to put some x or similar on certain pixels in a fixed size drawing plane.

If I have find the time, I will try my best with a PR.

ArthurSonzogni commented 3 years ago

At some point, I wanted to add some kind of support for braille drawing like: https://github.com/asciimoo/drawille

Otherwise, yes, adding some dom elements for arbitrary drawing would be nice. What kind of API are you thinking about?

felixjulianheitmann commented 3 years ago

Admittedly, that looks cool.

I was thinking of a canvas function that takes fixed size parameters and maybe a function as third argument that gets called when rendering. Along the lines of

canvas(Dimension width, Dimension height, std::function<void ()> draw)

I am not set on the draw function signature, though, because I am unsure what it would do.

Maybe it should return a vector of Pixel that know their content and position - I haven't looked into your Pixel class yet. That information could then be used by the canvas' render function.

Another touch could be, that draw takes width and height in number of pixels as parameter. The user could then position pixels on the canvas according to the given sizes. It would not need to be fixed size anymore but that depends on how you do the sizing of all elements on screen. That is witchcraft to me.

I hope that gives an idea of what I was imagining.

Felix

Edit: Similar to the graph function

ArthurSonzogni commented 2 years ago

Here it is: https://github.com/ArthurSonzogni/FTXUI/pull/287

@felixjulianheitmann would you have any comments about the API before I merge the PR?

See youtube video: https://www.youtube.com/watch?v=fyFo4OU-hiQ https://twitter.com/i/status/1473245522953654273

felixjulianheitmann commented 2 years ago

Hi, the feature set looks great. It's a little sad that using the canvas class breaks the FTXUI philosophy of everything being either an Element or a Component. I get that I need to be able to call member functions of the canvas class in order to manipulate it but now calling auto foo = Canvas(...) behaves differently from auto foo = gauge(...) for example.

I guess more in sync with the rest of the library would have been to pass a canvas manipulation function to a factory method that would then maybe take the Canvas object as a parameter to manipulate its content. Similar to what I proposed above like

canvas(Dimension width, Dimension height, std::function<void (Canvas &canvas)> draw)

However, I don't want to judge your decisions because I haven't tried implementing it myself. It might turn out to be way more cumbersome the way I suggested. I just thought It might be more in line with other components.

Anyways, thank you for the implementation because it looks and works great!

ArthurSonzogni commented 2 years ago

Thanks! Those are great ideas. I think we can support both.

One think I wanted to be able to reuse a Canvas for multiple frame without having to reconstruct it from scratch every time, because this can be a large 2d array if we fill data in most cells. So we support passing a canvas by value and by address.

Adding your version taking a function, that modify a given canvas is great, because it is more functional. Also we can provide a version where the size isn't given but based on the actual size taken by the element. Similar to what we do for graph.

Le jeu. 23 déc. 2021, 23:15, Felix Heitmann @.***> a écrit :

Hi, the feature set looks great. It's a little sad that using the canvas class breaks the FTXUI philosophy of everything being either an Element or a Component. I get that I need to be able to call member functions of the canvas class in order to manipulate it but now calling auto foo = Canvas(...) behaves differently from auto foo = gauge(...) for example.

I guess more in sync with the rest of the library would have been to pass a canvas manipulation function to a factory method that would then maybe take the Canvas object as a parameter to manipulate its content. Similar to what I proposed above like

canvas(Dimension width, Dimension height, std::function<void (Canvas &canvas)> draw)

However, I don't want to judge your decisions because I haven't tried implementing it myself. It might turn out to be way more cumbersome the way I suggested. I just thought It might be more in line with other components.

Anyways, thank you for the implementation because it looks and works great!

— Reply to this email directly, view it on GitHub https://github.com/ArthurSonzogni/FTXUI/issues/154#issuecomment-1000544796, or unsubscribe https://github.com/notifications/unsubscribe-auth/ABEJ4QQDMMRIL4VVRUPGOGLUSONRFANCNFSM5AM7YCRA . Triage notifications on the go with GitHub Mobile for iOS https://apps.apple.com/app/apple-store/id1477376905?ct=notification-email&mt=8&pt=524675 or Android https://play.google.com/store/apps/details?id=com.github.android&referrer=utm_campaign%3Dnotification-email%26utm_medium%3Demail%26utm_source%3Dgithub.

You are receiving this because you commented.Message ID: @.***>

felixjulianheitmann commented 2 years ago

That sounds great, IMO. I didn't think about performance too much, to be honest, but you're definitely right, that recreating the whole canvas every frame is not that efficient.

Good luck!

ArthurSonzogni commented 2 years ago

Thanks again!