Commit graph

1066 commits

Author SHA1 Message Date
Josh McKinney
78f1c1446b
chore: small fixes to constraint-explorer (#894) 2024-01-30 21:27:56 -08:00
Dheepak Krishnamurthy
9ec43eff1c
feat: Constraint Explorer example (#893)
Here's a constraint explorer demo put together with @joshka 


https://github.com/ratatui-org/ratatui/assets/1813121/08d7d8f6-d013-44b4-8331-f4eee3589cce

It allows users to interactive explore how the constraints behave with
respect to each other and compare that across flex modes. It allows
users to swap constraints out for other constraints, increment or
decrement the values, add and remove constraints, and add spacing

It is also a good example for how to structure a simple TUI with several
Ratatui code patterns that are useful for refactoring.

Fixes: https://github.com/ratatui-org/ratatui/issues/792

---------

Co-authored-by: Josh McKinney <joshka@users.noreply.github.com>
2024-01-31 00:12:29 -05:00
Dheepak Krishnamurthy
4ee4e6d78a
feat: Make spacing work in Flex::SpaceAround and Flex::SpaceBetween (#892)
This PR implements user provided spacing gaps for `SpaceAround` and
`SpaceBetween`.


https://github.com/ratatui-org/ratatui/assets/1813121/2e260708-e8a7-48ef-aec7-9cf84b655e91

Now user provided spacing gaps always take priority in all `Flex` modes.
2024-01-30 23:34:59 -05:00
Josh McKinney
525479546a
refactor: make layout tests a bit easier to understand (#890) 2024-01-29 23:07:18 -08:00
Dheepak Krishnamurthy
cf861232c7
refactor(Scrollbar): Rewrite scrollbar implementation (#847)
Implementation was simplified and calculates the size of the thumb a
bit more proportionally to the content that is visible.

Co-authored-by: Josh McKinney <joshka@users.noreply.github.com>
2024-01-29 23:05:24 -08:00
Dheepak Krishnamurthy
dd5ca3a0c8
feat: Better weights for constraints (#889)
This PR is a split of reworking the weights from #888 

This keeps the same ranking of weights, just uses a different numerical
value so that the lowest weight is `WEAK` (`1.0`).

No tests are changed as a result of this change, and running the
following multiple times did not cause any errors for me:

```rust
for i in {0..100}
do
 cargo test --lib --
 if [ $? -ne 0 ]; then
 echo "Test failed. Exiting loop."
 break
 fi
done
```
2024-01-29 22:16:49 -08:00
Dheepak Krishnamurthy
aeec16369b
feat: Change rounding to make tests stable (#888)
This fixes some unstable tests
2024-01-30 00:33:33 -05:00
dependabot[bot]
eb31617539
chore(deps): update termwiz requirement from 0.20.0 to 0.22.0 (#885)
Updates the requirements on [termwiz](https://github.com/wez/wezterm) to
permit the latest version.
<details>
<summary>Commits</summary>
<ul>
<li>See full diff in <a
href="https://github.com/wez/wezterm/commits">compare view</a></li>
</ul>
</details>
<br />


Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-01-29 20:02:44 -08:00
dependabot[bot]
1ad629acd7
chore(deps): update derive_builder requirement from 0.12.0 to 0.13.0 (#887) 2024-01-29 17:12:43 +01:00
dependabot[bot]
04e6ccd448
chore(deps): update strum requirement from 0.25 to 0.26 (#886) 2024-01-29 16:59:42 +01:00
Dheepak Krishnamurthy
540fd2df03
feat(layout)!: Change Flex::default() (#881)
This PR makes a number of simplifications to the layout and constraint
features that were added after v0.25.0.

For users upgrading from v0.25.0, the net effect of this PR (along with
the other PRs) is the following:

- New `Flex` modes have been added.
  - `Flex::Start` (new default)
  - `Flex::Center`
  - `Flex::End`
  - `Flex::SpaceAround`
  - `Flex::SpaceBetween`
  - `Flex::Legacy` (old default)
- `Min(v)` grows to allocate excess space in all `Flex` modes instead of
shrinking (except in `Flex::Legacy` where it retains old behavior).
- `Fill(1)` grows to allocate excess space, growing equally with
`Min(v)`.

---

The following contains a summary of the changes in this PR and the
motivation behind them.

**`Flex`**

- Removes `Flex::Stretch`
- Renames `Flex::StretchLast` to `Flex::Legacy`

**`Constraint`**

- Removes `Fixed`
- Makes `Min(v)` grow as much as possible everywhere (except
`Flex::Legacy` where it retains the old behavior)
- Makes `Min(v)` grow equally as `Fill(1)` while respecting `Min` lower
bounds. When `Fill` and `Min` are used together, they both fill excess
space equally.

Allowing `Min(v)` to grow still allows users to build the same layouts
as before with `Flex::Start` with no breaking changes to the behavior.

This PR also removes the unstable feature `SegmentSize`.

This is a breaking change to the behavior of constraints. If users want
old behavior, they can use `Flex::Legacy`.

```rust
Layout::vertical([Length(25), Length(25)]).flex(Flex::Legacy)
```

Users that have constraint that exceed the available space will probably
not see any difference or see an improvement in their layouts. Any
layout with `Min` will be identical in `Flex::Start` and `Flex::Legacy`
so any layout with `Min` will not be breaking.

Previously, `Table` used `EvenDistribution` internally by default, but
with that gone the default is now `Flex::Start`. This changes the
behavior of `Table` (for the better in most cases). The only way for
users to get exactly the same as the old behavior is to change their
constraints. I imagine most users will be happier out of the box with
the new Table default.

Resolves https://github.com/ratatui-org/ratatui/issues/843

Thanks to @joshka for the direction
2024-01-29 09:37:50 -05:00
Josh McKinney
984afd580b
chore: cache dependencies in the CI workflow to speed up builds (#883) 2024-01-29 14:43:48 +01:00
Josh McKinney
bbcfa55a88
feat(layout): add Rect::contains method (#882)
This is useful for performing hit tests (i.e. did the user click in an
area).
2024-01-29 04:44:22 -08:00
Dheepak Krishnamurthy
1cbe1f52ab
feat(constraints): Rename Constraint::Proportional to Constraint::Fill (#880)
`Constraint::Fill` is a more intuitive name for the behavior, and it is
shorter.

Resolves #859
2024-01-28 05:41:01 -05:00
Dheepak Krishnamurthy
663bbde9c3
test(layout): Convert layout tests to use rstest (#879)
This PR makes all the letters test use `rstest`
2024-01-28 05:11:40 -05:00
Dheepak Krishnamurthy
27e9216cea
feat(table): Remove allow deprecated attribute used previously for segment_size (#875) 2024-01-27 13:45:55 -08:00
Dheepak Krishnamurthy
be4fdaa0c7
feat: Change priority of constraints and add split_with_spacers (#788)
Follow up to https://github.com/ratatui-org/ratatui/pull/783

This PR introduces different priorities for each kind of constraint.
This PR also adds tests that specifies this behavior. This PR resolves a
number of broken tests.

Fixes https://github.com/ratatui-org/ratatui/issues/827

With this PR, the layout algorithm will do the following in order:

1. Ensure that all the segments are within the user provided area and
ensure that all segments and spacers are aligned next to each other
2. if a user provides a `layout.spacing`, it will enforce it.
3. ensure proportional elements are all proportional to each other
4. if a user provides a `Fixed(v)` constraint, it will enforce it. 
5. `Min` / `Max` binding inequality constraints
6. `Length`
7. `Percentage`
8. `Ratio`
9. collapse `Min` or collapse `Max`
10. grow `Proportional` as much as possible
11. grow spacers as much as possible

This PR also returns the spacer areas as `Rects` to the user. Users can
then draw into the spacers as they see fit (thanks @joshka for the
idea). Here's a screenshot with the modified flex example:

<img width="569" alt="image"
src="https://github.com/ratatui-org/ratatui/assets/1813121/46c8901d-882c-43b0-ba87-b1d455099d8f">

This PR introduces a `strengths` module that has "default" weights that
give stable solutions as well as predictable behavior.
2024-01-27 15:35:42 -05:00
Eeelco
c1ed5c3637
feat(Span): add alignment functions (#873)
Implemented functions that convert Span into a
left-/center-/right-aligned Line. Implemented unit tests.

Closes #853 
---------

Signed-off-by: Eelco Empting <me@eelco.de>
2024-01-27 10:57:06 -08:00
Emirhan TALA
4b8e54e811
docs(examples): refactor Tabs example (#861)
- Used a few new techniques from the 0.26 features (ref widgets, text rendering,
  dividers / padding etc.)
- Updated the app to a simpler application approach
- Use color_eyre
- Make it look pretty (colors, new proportional borders)

![Made with VHS](https://vhs.charm.sh/vhs-4WW21XTtepDhUSq4ZShO56.gif)

---------
Fixes https://github.com/ratatui-org/ratatui/issues/819
Co-authored-by: Josh McKinney <joshka@users.noreply.github.com>
2024-01-27 02:39:40 -08:00
Emirhan TALA
5b7ad2ad82
docs(examples): update gauge example (#863)
- colored gauges
- removed box borders
- show the difference between ratio / percentage and unicode / no unicode better
- better application approach (consistent with newer examples)
- various changes for 0.26 featuers
- impl `Widget` for `&App`
- use color_eyre

for gauge.tape

- change to get better output from the new code

---------
Fixes: https://github.com/ratatui-org/ratatui/issues/846
Co-authored-by: Josh McKinney <joshka@users.noreply.github.com>
2024-01-27 01:47:17 -08:00
Valentin271
ba20372c23
chore(CONTRIBUTING): remove part about squashing commits (#874)
Removes the part about squashing commits from the CONTRIBUTING file.

We no longer require that because github squashes commits when merging.
This will cleanup the CONTRIBUTING file a bit which is already quite
dense.
2024-01-26 18:30:15 +01:00
Josh McKinney
f383625f0e
docs(examples): add note about example versions to all examples (#871) 2024-01-24 11:50:18 -08:00
Josh McKinney
847bacf32e
docs(examples): refactor demo2 (#836)
Simplified a bunch of the logic in the demo2 example
- Moved destroy mode to its own file.
- Moved error handling to its own file.
- Removed AppContext
- Implemented Widget for &App. The app state is small enough that it
  doesn't matter here and we could just copy or clone the app state on
  every frame, but for larger apps this can be a significant performance
  improvement.
- Made the tabs stateful
- Made the term module just a collection of functions rather than a
  struct.
- Changed to use color_eyre for error handling.
- Changed keyboard shortcuts and rearranged the bottom bar.
- Use strum for the tabs enum.
2024-01-24 11:44:16 -08:00
Josh McKinney
815757fcbb
feat(widgets): implement Widget for Widget refs (#833)
Many widgets can be rendered without changing their state.

This commit implements The `Widget` trait for references to
widgets and changes their implementations to be immutable.

This allows us to render widgets without consuming them by passing a ref
to the widget when calling `Frame::render_widget()`.

```rust
// this might be stored in a struct
let paragraph = Paragraph::new("Hello world!");

let [left, right] = area.split(&Layout::horizontal([20, 20]));
frame.render_widget(&paragraph, left);
frame.render_widget(&paragraph, right); // we can reuse the widget
```

Implemented for all widgets except BarChart (which has an implementation
that modifies the internal state and requires a rewrite to fix.

Other widgets will be implemented in follow up commits.

Fixes: https://github.com/ratatui-org/ratatui/discussions/164
Replaces PRs: https://github.com/ratatui-org/ratatui/pull/122 and
https://github.com/ratatui-org/ratatui/pull/16
Enables: https://github.com/ratatui-org/ratatui/issues/132
Validated as a viable working solution by:
https://github.com/ratatui-org/ratatui/pull/836
2024-01-24 10:34:10 -08:00
Josh McKinney
736605ec88
feat(layout): Add default impl for Position (#869) 2024-01-24 17:47:29 +01:00
Josh McKinney
6e76729ce8
chore: move example vhs tapes to a folder (#867) 2024-01-24 08:22:46 -08:00
Josh McKinney
7f42ec9713
refactor(colors_rgb): impl widget on mutable refs (#865)
This commit refactors the colors_rgb example to implement the Widget
trait on mutable references to the app and its sub-widgets. This allows
the app to update its state while it is being rendered.

Additionally the main and run functions are refactored to be similar to
the other recent examples. This uses a pattern where the App struct has
a `run` method that takes a terminal as an argument, and the main
function is in control of initializing and restoring the terminal and
installing the error hooks.
2024-01-24 07:13:11 -08:00
Dheepak Krishnamurthy
d7132011f9
feat: Add Color::from_hsl (#772)
This PR adds `Color::from_hsl` that returns a valid `Color::Rgb`. 

```rust
let color: Color = Color::from_hsl(360.0, 100.0, 100.0);
assert_eq!(color, Color::Rgb(255, 255, 255));

let color: Color = Color::from_hsl(0.0, 0.0, 0.0);
assert_eq!(color, Color::Rgb(0, 0, 0));
```

HSL stands for Hue (0-360 deg), Saturation (0-100%), and Lightness
(0-100%) and working with HSL the values can be more intuitive. For
example, if you want to make a red color more orange, you can change the
Hue closer toward yellow on the color wheel (i.e. increase the Hue).

Related #763
2024-01-24 04:42:39 -08:00
Eeelco
d726e928d2
feat(Paragraph): add alignment convenience functions (#866)
Added convenience functions left_aligned(), centered() and
right_aligned() plus unit tests. Updated example code.

Signed-off-by: Eelco Empting <me@eelco.de>
2024-01-24 03:31:52 -08:00
Eeelco
b80264de87
feat(Text): add alignment convenience functions (#862)
Adds convenience functions `left_aligned()`, `centered()` and
`right_aligned()` plus unit tests.
2024-01-23 20:28:38 +01:00
Emirhan TALA
804c841fdc
docs(examples): update list example and list.tape (#864)
This PR adds:

- subjectively better-looking list example
- change list example to a todo list example
- status of a TODO can be changed, further info can be seen under the list.
2024-01-23 17:22:37 +01:00
Eeelco
79ceb9f7b6
feat(Line): add alignment convenience functions (#856)
This adds convenience functions `left_aligned()`, `centered()` and
`right_aligned()` plus unit tests. Updated example code.
2024-01-22 18:30:01 +01:00
Dheepak Krishnamurthy
f780be31f3
test(layout): parameterized tests 🚨 (#858) 2024-01-21 10:37:17 -05:00
Emirhan TALA
eb1484b6db
docs(examples): update tabs example and tabs.tape (#855)
This PR adds:

for tabs.rs

- general refactoring on code
- subjectively better looking front
- add tailwind colors

for tabs.tape

- change to get better output from the new code

Here is the new output:

![tabs](https://github.com/ratatui-org/ratatui/assets/30180366/0a9371a5-e90d-42ba-aba5-70cbf66afd1f)
2024-01-21 10:23:50 +01:00
Emirhan TALA
6ecaeed549
docs(Text): add overview of the relevant methods (#857)
Add an overview of the relevant methods under `Constructor Methods`, `Setter Methods`, and `Other Methods` subtitles.
2024-01-20 23:32:33 +01:00
Emirhan TALA
a489d85f2d
feat(table): deprecate SegmentSize on table (#842)
This adds for table:

- Added new flex method with flex field
- Deprecated segment_size method and removed segment_size field
- Updated documentation
- Updated tests
2024-01-19 17:58:12 +01:00
Valentin271
065b6b05b7
docs(terminal): document buffer diffing better (#852) 2024-01-19 17:44:50 +01:00
Josh McKinney
1e755967c5
feat(layout): increase default cache size to 500 (#850)
This is a somewhat arbitrary size for the layout cache based on adding
the columns and rows on my laptop's terminal (171+51 = 222) and doubling
it for good measure and then adding a bit more to make it a round
number. This gives enough entries to store a layout for every row and
every column, twice over, which should be enough for most apps. For
those that need more, the cache size can be set with
`Layout::init_cache()`.

Fixes: https://github.com/ratatui-org/ratatui/issues/820
2024-01-19 15:35:33 +01:00
Linda_pp
1d3fbc1b15
perf(buffer)!: apply SSO technique to text buffer in buffer::Cell (#601)
Use CompactString instead of String to store the Cell::symbol field.
This saves reduces the size of memory allocations at runtime.
2024-01-19 04:50:42 -08:00
Emirhan TALA
330a899eac
docs(examples): update table example and table.tape (#840)
In table.rs
- added scrollbar to the table
- colors changed to use style::palette::tailwind
- now colors can be changed with keys (l or →) for the next color, (h or
←) for the previous color
- added a footer for key info

For table.tape
- typing speed changed to 0.75s from 0.5s
- screen size changed to fit
- pushed keys changed to show the current example better

Fixes: https://github.com/ratatui-org/ratatui/issues/800
2024-01-19 03:26:09 -08:00
Emirhan TALA
405a125c82
feat: add wide and tall proportional border set (#848)
Adds `PROPORTIONAL_WIDE` and `PROPORTIONAL_TALL` border sets.

`symbols::border::PROPORTIONAL_WIDE`
```
▄▄▄▄
█xx█
█xx█
▀▀▀▀
```

`symbols::border::PROPORTIONAL_TALL`
```
█▀▀█
█xx█
█xx█
█▄▄█
```

Fixes: https://github.com/ratatui-org/ratatui/issues/834
2024-01-19 00:24:49 -08:00
bblsh
b3a57f3dff
fix(list): Modify List and List example to support saving offsets. (#667)
The current `List` example will unselect and reset the position of a
list.

This PR will save the last selected item, and updates `List` to honor
its offset, preventing the list from resetting when the user
`unselect()`s a `StatefulList`.
2024-01-19 09:17:39 +01:00
Josh McKinney
2819eea82b
feat(layout): add Position struct (#790)
This stores the x and y coordinates (columns and rows)

- add conversions from Rect
- add conversion with Size to Rect
- add Rect::as_position
2024-01-18 14:07:36 +01:00
Josh McKinney
41de8846fd
docs(examples): document incompatible examples better (#844)
Examples often take advantage of unreleased API changes, which makes
them not copy-paste friendly.
2024-01-18 01:56:06 -08:00
Valentin271
68d5783a69
feat(text): add style and alignment (#807)
Fixes #758, fixes #801

This PR adds:

- `style` and `alignment` to `Text`
- impl `Widget` for `Text`
- replace `Text` manual draw to call for Widget impl

All places that use `Text` have been updated and support its new
features expect paragraph which still has a custom implementation.
2024-01-17 18:54:53 +01:00
Orhun Parmaksız
d49bbb2590
chore(ci): update the job description for installing cargo-nextest (#839) 2024-01-17 18:08:06 +01:00
Josh McKinney
fd4703c086
refactor(block): move padding and title into separate files (#837) 2024-01-17 06:18:36 -08:00
Emirhan TALA
0df935473f
feat(Padding): add new constructors for padding (#828)
Adds `proportional`, `symmetric`, `left`, `right`, `top`, and `bottom`
constructors for Padding struct.

Proportional is 
```
/// **NOTE**: Terminal cells are often taller than they are wide, so to make horizontal and vertical
/// padding seem equal, doubling the horizontal padding is usually pretty good.
```

Fixes: https://github.com/ratatui-org/ratatui/issues/798
2024-01-17 04:50:08 -08:00
Dheepak Krishnamurthy
9df6cebb58
feat: Table column calculation uses layout spacing (#824)
This uses the new `spacing` feature of the `Layout` struct to allocate
columns spacing in the `Table` widget.
This changes the behavior of the table column layout in the following
ways:

1. Selection width is always allocated.
- if a user does not want a selection width ever they should use
`HighlightSpacing::Never`
2. Column spacing is prioritized over other constraints
- if a user does not want column spacing, they should use
`Table::new(...).column_spacing(0)`

---------

Co-authored-by: Josh McKinney <joshka@users.noreply.github.com>
2024-01-16 21:51:25 -05:00
Dheepak Krishnamurthy
f299463847
feat: Add one eighth wide and tall border sets (#831)
This PR adds the
[`McGugan`](https://www.willmcgugan.com/blog/tech/post/ceo-just-wants-to-draw-boxes/)
border set, which allows for tighter borders.

For example, with the `flex` example you can get this effect (top is
mcgugan wide, bottom is mcgugan tall):

<img width="759" alt="image"
src="https://github.com/ratatui-org/ratatui/assets/1813121/756bb50e-f8c3-4eec-abe8-ce358058a526">

<img width="759" alt="image"
src="https://github.com/ratatui-org/ratatui/assets/1813121/583485ef-9eb2-4b45-ab88-90bd7cb14c54">

As of this PR, `MCGUGAN_WIDE` has to be styled manually, like so:

```rust
            let main_color = color_for_constraint(*constraint);
            let cell = buf.get_mut(block.x, block.y + 1);
            cell.set_style(Style::reset().fg(main_color).reversed());
            let cell = buf.get_mut(block.x, block.y + 2);
            cell.set_style(Style::reset().fg(main_color).reversed());
            let cell = buf.get_mut(block.x + block.width.saturating_sub(1), block.y + 1);
            cell.set_style(Style::reset().fg(main_color).reversed());
            let cell = buf.get_mut(block.x + block.width.saturating_sub(1), block.y + 2);
            cell.set_style(Style::reset().fg(main_color).reversed());

```

`MCGUGAN_TALL` has to be styled manually, like so:

```rust
            let main_color = color_for_constraint(*constraint);
            for x in block.x + 1..(block.x + block.width).saturating_sub(1) {
                let cell = buf.get_mut(x, block.y);
                cell.set_style(Style::reset().fg(main_color).reversed());
                let cell = buf.get_mut(x, block.y + block.height - 1);
                cell.set_style(Style::reset().fg(main_color).reversed());
            }

```
2024-01-16 21:03:06 -05:00