oyvindberg / tui-scala

Beautiful Text-based User Interfaces for Scala
MIT License
207 stars 11 forks source link

Towards immutable (Fixes #9) #26

Closed oyvindberg closed 1 year ago

oyvindberg commented 1 year ago

commit 1: simplify Terminal:

commit 2: Commit only full Cells to Buffer

This touches on the main problem with tui, as far as I see it.

When widgets update the buffer for a given coordinate, it typically patches what is already there. This means that often styles are drawn first, and then text (or vice versa). Especially, widgets can clobber each other's output in this manner, if they are drawn in a hierarchy.

We'll do this inheritance of styles explicitly instead.

This commit sketches an API for composing styles, so you can easily compose things like  style / header_style / label, with the equivalent result of applying the two styles and one content after each other with the old API.

oyvindberg commented 1 year ago

I think I have decided to close this PR for now.

For posterity I'll document here the problem I tried to solve. There will likely be another iteration in the future, guided by an attempt at making the widgets behave more like react components.

The main thing done in this PR is to make Cell writes to the buffer "atomic", in that it doesn't merge with earlier written modifiers/colors.

Typical usage before this PR is some something like this:

- a widget renders it entire viewport with a `Style`. Say this style has a background color set
- then it renders some content `Text` on top, which again has styled. the resulting `Cell`s end up merging the styles from two writes (newer values win, colors are `orElse`d, modifiers sets are `union`ed)
- parent widgets may pre-style viewport of children, or clobber the output after the child has finished rendering.

What I had in mind was something like this:

- the same widget must merge styles before render:
- `style / text` will do the same merge in code, and you write it atomically. 
- You can also overwrite styling in a span/text by composing the style after, so ordering matters: `style / text / moreStyle` will favour the styling in `moreStyle`
- parents can no longer pre-style viewport of children, but can compose and pass in a `style` explicitly

So after trying it out I'm not so convinced it's better. If you want to set a background color you can do so at the top-level now, and you don't have to thread it through every last style in your app.

oyvindberg commented 1 year ago

@ckipp01 feel free to share any thoughts on styling if and when you have them. I think for now let's rather focus on easier things, like the desnakification of all the names :)