Commit graph

1282 commits

Author SHA1 Message Date
Jack Wills
14c67fbb52
fix(list): highlight symbol when using a multi-bytes char (#924)
ratatui v0.26.0 brought a regression in the List widget, in which the
highlight symbol width was incorrectly calculated - specifically when
the highlight symbol was a multi-char character, e.g. `▶`.
2024-02-05 20:59:19 +01:00
Mo
096346350e
perf: Use drain instead of remove in chart examples (#922) 2024-02-05 04:54:05 -08:00
Valentin271
61a827821d
docs(canvas): add documentation to canvas module (#913)
Document the whole `canvas` module. With this, the whole `widgets`
module is documented.
2024-02-03 13:58:29 -08:00
Dheepak Krishnamurthy
fbb5dfaaa9
fix: Scrollbar rendering when no track symbols are provided (#911) 2024-02-03 16:06:44 +01:00
Orhun Parmaksız
d2d91f754c
docs(changelog): add sponsors section (#908)
<!-- Please read CONTRIBUTING.md before submitting any pull request. -->
2024-02-02 17:28:23 +01:00
Dheepak Krishnamurthy
bcf43688ec
docs: Update BREAKING-CHANGES.md summary (#907)
Update summary section
2024-02-02 03:50:07 -05:00
Orhun Parmaksız
b7942ee252
chore(release): prepare for 0.26.0 (#905)
🐭

---------

Co-authored-by: Josh McKinney <joshka@users.noreply.github.com>
2024-02-02 00:16:00 -08:00
Josh McKinney
c8dd87918d
feat: add WidgetRef and StatefulWidgetRef traits (#903)
The Widget trait consumes self, which makes it impossible to use in a
boxed context. Previously we implemented the Widget trait for &T, but
this was not enough to render a boxed widget. We now have a new trait
called `WidgetRef` that allows rendering a widget by reference. This
trait is useful when you want to store a reference to one or more
widgets and render them later. Additionaly this makes it possible to
render boxed widgets where the type is not known at compile time (e.g.
in a composite layout with multiple panes of different types).

This change also adds a new trait called `StatefulWidgetRef` which is
the stateful equivalent of `WidgetRef`.

Both new traits are gated behind the `unstable-widget-ref` feature flag
as we may change the exact name / approach a little on this based on
further discussion.

Blanket implementation of `Widget` for `&W` where `W` implements
`WidgetRef` and `StatefulWidget` for `&W` where `W` implements
`StatefulWidgetRef` is provided. This allows you to render a widget by
reference and a stateful widget by reference.

A blanket implementation of `WidgetRef` for `Option<W>` where `W`
implements `WidgetRef` is provided. This makes it easier to render
child widgets that are optional without the boilerplate of unwrapping
the option. Previously several widgets implemented this manually. This
commits expands the pattern to apply to all widgets.

```rust
struct Parent {
    child: Option<Child>,
}

impl WidgetRef for Parent {
    fn render_ref(&self, area: Rect, buf: &mut Buffer) {
        self.child.render_ref(area, buf);
    }
}
```

```rust
let widgets: Vec<Box<dyn WidgetRef>> = vec![Box::new(Greeting), Box::new(Farewell)];
for widget in widgets {
    widget.render_ref(buf.area, &mut buf);
}
assert_eq!(buf, Buffer::with_lines(["Hello        Goodbye"]));
```
2024-02-02 00:02:16 -08:00
Dheepak Krishnamurthy
652dc469ea
docs: Update BREAKING-CHANGES.md with flex section (#906)
Follow up to: https://github.com/ratatui-org/ratatui/pull/881
2024-02-02 00:40:11 -05:00
Josh McKinney
87bf1dd9df
feat: replace Rect::split with Layout::areas and spacers (#904)
In a recent commit we added Rec::split, but this feels more ergonomic as
Layout::areas. This also adds Layout::spacers to get the spacers between
the areas.
2024-02-01 20:26:35 -08:00
Josh McKinney
f8367fdfdd
chore: allow Buffer::with_lines to accept IntoIterator (#901)
This can make it easier to use `Buffer::with_lines` with iterators that
don't necessarily produce a `Vec`. For example, this allows using
`Buffer::with_lines` with `&[&str]` directly, without having to call
`collect` on it first.
2024-01-31 14:12:10 -08:00
Josh McKinney
9ba7354335
feat(text): implement iterators for Text (#900)
This allows iterating over the `Lines`s of a text using `for` loops and
other iterator methods.

- add `iter` and `iter_mut` methods to `Text`
- implement `IntoIterator` for `Text`, `&Text`, and `&mut Text` traits
- update call sites to iterate over `Text` rather than `Text::lines`
2024-01-31 13:44:39 -08:00
Dheepak Krishnamurthy
dab08b99b6
feat: show space constrained UIs conditionally (#895)
With this PR the constraint explorer demo only shows space constrained
UIs instead:

Smallest (15 row height):

<img width="759" alt="image"
src="https://github.com/ratatui-org/ratatui/assets/1813121/37a4a027-6c6d-4feb-8104-d732aee298ac">

Small (20 row height):

<img width="759" alt="image"
src="https://github.com/ratatui-org/ratatui/assets/1813121/f76e025f-0061-4f09-9c91-2f7b00fcfb9e">

Medium (30 row height):

<img width="758" alt="image"
src="https://github.com/ratatui-org/ratatui/assets/1813121/81b070da-1bfb-40c5-9fbc-c1ab44ce422e">

Full (40 row height):

<img width="760" alt="image"
src="https://github.com/ratatui-org/ratatui/assets/1813121/7bb8a8c4-1a77-4bbc-a346-c8b5c198c6d3">
2024-01-31 13:01:29 -08:00
Josh McKinney
2a12f7bddf
feat: impl Widget for &BarChart (#897)
BarChart had some internal mutations that needed to be removed to
implement the Widget trait for &BarChart to bring it in line with the
other widgets.
2024-01-31 11:21:32 -08:00
Josh McKinney
4278b4088d
feat(line): implement iterators for Line (#896)
This allows iterating over the `Span`s of a line using `for` loops and
other iterator methods.

- add `iter` and `iter_mut` methods to `Line`
- implement `IntoIterator` for `Line`, `&Line`, and `&mut Line` traits
- update call sites to iterate over `Line` rather than `Line::spans`
2024-01-31 17:33:30 +01:00
Dheepak Krishnamurthy
86168aa711
docs: Fix docstring for Max constraints (#898) 2024-01-31 17:31:05 +01:00
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