Skip to content

Commit

Permalink
Merge pull request #16 from preiter93/v0.9
Browse files Browse the repository at this point in the history
V0.9
  • Loading branch information
preiter93 authored and phire22 committed May 11, 2024
2 parents 23c6cac + eea2f1e commit ff82747
Show file tree
Hide file tree
Showing 22 changed files with 1,227 additions and 797 deletions.
26 changes: 26 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,29 @@
Prerelease
----------

0.9.0 - 11 May 2024
===================
- Introduced `PreRender` trait as a replacement for `ListableWidget`.
- This change is non-breaking
- It provides a more concise and clearer interface.
Migration Guide
- Update trait implementations to use the new `pre_render` signature:

```rust
fn pre_render(&mut self, context: &PreRenderContext) -> u16 {
let main_axis_size = // The widgets size in the main axis

if context.is_selected {
self = // You can modify the selected item here
}

main_axis_size
}
```
- Deprecated ListState::selected(). Use the struct field selected instead.
- Updated examples
- Add example for long lists

Released
--------

Expand Down
9 changes: 6 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "tui-widget-list"
version = "0.8.3"
version = "0.9.0"
edition = "2021"
authors = ["preiter <[email protected]>"]
description = "Widget List for TUI/Ratatui"
Expand All @@ -19,10 +19,13 @@ crossterm = "0.27"
name = "simple"

[[example]]
name = "paragraph"
name = "simple_deprecated"

[[example]]
name = "mixed"
name = "long"

[[example]]
name = "var_sizes"

[[example]]
name = "demo"
21 changes: 21 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
MIT License

Copyright (c) 2024 Philipp Reiter

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
83 changes: 50 additions & 33 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,85 +1,102 @@
## A versatile widget list for Ratatui

<div align="center">

[![Continuous Integration](https://github.com/preiter93/tui-widget-list/actions/workflows/ci.yml/badge.svg)](https://github.com/preiter93/tui-widget-list/actions/workflows/ci.yml)

</div>

This crate provides a stateful widget [`List`] implementation for `Ratatui`, enabling listing
widgets that implement the [`ListableWidget`] trait. The associated [`ListState`], offers functionalities
widgets that implement the [`PreRender`] trait. The associated [`ListState`], offers functionalities
such as navigating to the next and previous items.
Additionally, the lists support both horizontal and vertical scrolling.

### Configuration
The [`List`] can be customized with the following options:
- `scroll_direction`: Specifies whether the list is vertically or horizontally scrollable.
- `style`: Defines the base style of the list.
- `block`: Optional outer block surrounding the list.
- [`List::scroll_direction`]: Specifies whether the list is vertically or horizontally scrollable.
- [`List::style`]: Defines the base style of the list.
- [`List::block`]: Optional outer block surrounding the list.

You can adjust the behavior of [`ListState`] with the following options:
- `circular`: Determines if the selection is circular. When enabled, selecting the last item loops back to the first. Enabled by default.
- [`ListState::circular`]: Determines if the selection is circular. When enabled, selecting the last item loops back to the first. Enabled by default.

### Example
```rust
use ratatui::buffer::Buffer;
use ratatui::layout::Rect;
use ratatui::style::{Color, Style, Stylize};
use ratatui::text::Text;
use ratatui::widgets::{Paragraph, Widget};
use ratatui::Frame;
use tui_widget_list::{List, ListState, ListableWidget, ScrollAxis};
use ratatui::prelude::*;
use tui_widget_list::{List, ListState, PreRender, PreRenderContext};

#[derive(Debug, Clone)]
pub struct ListItem {
text: String,
style: Style,
height: usize,
}

impl ListItem {
pub fn new<T: Into<String>>(text: T, height: usize) -> Self {
pub fn new<T: Into<String>>(text: T) -> Self {
Self {
text: text.into(),
style: Style::default(),
height,
}
}
}

impl ListableWidget for ListItem {
fn size(&self, _: &ScrollAxis) -> usize {
self.height
}
impl PreRender for ListItem {
fn pre_render(&mut self, context: &PreRenderContext) -> u16 {
// Set alternating styles
if context.index % 2 == 0 {
self.style = Style::default().bg(Color::Rgb(28, 28, 32));
} else {
self.style = Style::default().bg(Color::Rgb(0, 0, 0));
}

fn highlight(self) -> Self {
Self {
style: self.style.reversed(),
..self
}
}
// Highlight the selected widget
if context.is_selected {
self.style = Style::default()
.bg(Color::Rgb(255, 153, 0))
.fg(Color::Rgb(28, 28, 32));
};

// Example: set main axis size to 1
let main_axis_size = 1;

main_axis_size
}
}

impl Widget for ListItem {
fn render(self, area: Rect, buf: &mut Buffer) {
Paragraph::new(Text::from(self.text))
.style(self.style)
.render(area, buf);
Line::from(self.text).style(self.style).render(area, buf);
}
}

pub fn render(f: &mut Frame) {
let list = List::new(vec![
ListItem::new("hello", 1),
ListItem::new("world", 2),
ListItem::new("Item 1"),
ListItem::new("Item 2"),
]);
let mut state = ListState::default();
f.render_stateful_widget(list, f.size(), &mut state);
}
```

### Long lists

`tui-widget-list` also allows to render long lists with thousands of items efficiently.
Check out the [example](https://github.com/preiter93/tui-widget-list/tree/main/examples/long.rs)
for demonstration. Note that the key is to create the items only once and implement `Widget` and
`PreRender` on the references to the list item.

For more examples see [tui-widget-list](https://github.com/preiter93/tui-widget-list/tree/main/examples).

![](examples/demo.gif?v=1)
### Documentation
[docs.rs](https://docs.rs/tui-widget-list/)

### Demos

#### Simple list with alternating colors

![](examples/tapes/simple.gif?v=1)

#### Vertically and horizontally scrollable

License: MIT
![](examples/tapes/demo.gif?v=1)
Binary file removed examples/demo.gif
Binary file not shown.
Loading

0 comments on commit ff82747

Please sign in to comment.