diff --git a/CHANGELOG.md b/CHANGELOG.md index 46cfb8a3..56af8650 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,17 +2,160 @@ ## To be released -### Breaking Changes +### Breaking changes -* `Terminal::draw()` now requires a closure that takes `&mut Frame`. +#### Easier cursor management + +A new method has been added to `Frame` called `set_cursor`. It lets you specify where the cursor +should be placed after the draw call. Furthermore like any other widgets, if you do not set a cursor +position during a draw call, the cursor is automatically hidden. + +For example: + +```rust +fn draw_input(f: &mut Frame, app: &App) { + if app.editing { + let input_width = app.input.width() as u16; + // The cursor will be placed just after the last character of the input + f.set_cursor((input_width + 1, 0)); + } else { + // We are no longer editing, the cursor does not have to be shown, set_cursor is not called and + // thus automatically hidden. + } +} +``` + +In order to make this possible, the draw closure takes in input `&mut Frame` instead of `mut Frame`. + +#### Advanced text styling + +It has been reported several times that the text styling capabilities were somewhat limited in many +places of the crate. To solve the issue, this release includes a new set of text primitives that are +now used by a majority of widgets to provide flexible text styling. + +`Text` is replaced by the following types: +- `Span`: a string with a unique style. +- `Spans`: a string with multiple styles. +- `Text`: a multi-lines string with multiple styles. + +However, you do not always need this complexity so the crate provides `From` implementations to +let you use simple strings as a default and switch to the previous primitives when you need +additional styling capabilities. + +For example, the title of a `Block` can be set in the following ways: + +```rust +// A title with no styling +Block::default().title("My title"); +// A yellow title +Block::default().title(Span::styled("My title", Style::default().fg(Color::Yellow))); +// A title where "My" is bold and "title" is a simple string +Block::default().title(vec![ + Span::styled("My", Style::default().add_modifier(Modifier::BOLD)), + Span::from("title") +]); +``` + +- `Buffer::set_spans` and `Buffer::set_span` were added. +- `Paragraph::new` expects an input that can be converted to a `Text`. +- `Block::title_style` is deprecated. +- `Block::title` expects a `Spans`. +- `Tabs` expects a list of `Spans`. +- `Gauge` custom label is now a `Span`. +- `Axis` title and labels are `Spans` (as a consequence `Chart` no longer has generic bounds). + +#### Incremental styling + +Previously `Style` was used to represent an exhaustive set of style rules to be applied to an UI +element. It implied that whenever you wanted to change even only one property you had to provide the +complete style. For example, if you had a `Block` where you wanted to have a green background and +a title in bold, you had to do the following: + +```rust +let style = Style::default().bg(Color::Green); +Block::default() + .style(style) + .title("My title") + // Here we reused the style otherwise the background color would have been reset + .title_style(style.modifier(Modifier::BOLD)); +``` + +In this new release, you may now write this as: + +```rust +Block::default() + .style(Style::default().bg(Color::Green)) + // The style is not overidden anymore, we simply add new style rule for the title. + .title(Span::styled("My title", Style::default().add_modifier(Modifier::BOLD))) +``` + +In addition, the crate now provides a method `patch` to combine two styles into a new set of style +rules: + +```rust +let style = Style::default().modifer(Modifier::BOLD); +let style = style.patch(Style::default().add_modifier(Modifier::ITALIC)); +// style.modifer == Modifier::BOLD | Modifier::ITALIC, the modifier has been enriched not overidden +``` + +- `Style::modifier` has been removed in favor of `Style::add_modifier` and `Style::remove_modifier`. +- `Buffer::set_style` has been added. `Buffer::set_background` is deprecated. +- `BarChart::style` no longer set the style of the bars. Use `BarChart::bar_style` in replacement. +- `Gauge::style` no longer set the style of the gauge. Use `Gauge::gauge_style` in replacement. + +#### List with item on multiple lines + +The `List` widget has been refactored once again to support items with variable heights and complex +styling. + +- `List::new` expects an input that can be converted to a `Vec` where `ListItem` is a +wrapper around the item content to provide additional styling capabilities. `ListItem` contains a +`Text`. +- `List::items` has been removed. + +```rust +// Before +let items = vec![ + "Item1", + "Item2", + "Item3" +]; +List::default().items(items.iters()); + +// After +let items = vec![ + ListItem::new("Item1"), + ListItem::new("Item2"), + ListItem::new("Item3"), +]; +List::new(items); +``` + +See the examples for more advanced usages. + +#### More wrapping options + +`Paragraph::wrap` expects `Wrap` instead of `bool` to let users decided whether they want to trim +whitespaces when the text is wrapped. + +```rust +// before +Paragraph::new(text).wrap(true) +// after +Paragraph::new(text).wrap(Wrap { trim: true }) // to have the same behavior +Paragraph::new(text).wrap(Wrap { trim: false }) // to use the new behavior +``` + +#### Horizontal scrolling in paragraph + +You can now scroll horizontally in `Paragraph`. The argument of `Paragraph::scroll` has thus be +changed from `u16` to `(u16, u16)`. ### Features -* Add feature-gated (`serde`) serialization of `Style`. -* Add `Frame::set_cursor()` to dictate where the cursor should be placed after - the call to `Terminial::draw()`. Calling this method would also make the - cursor visible after the call to `draw()`. See example usage in - *examples/user_input.rs*. +#### Serialization of style + +You can now serialize and de-serialize `Style` using the optional `serde` feature. ## v0.9.5 - 2020-05-21 @@ -257,15 +400,15 @@ from an enum to a bitflags struct. So instead of writing: ```rust -let style = Style::default().modifier(Modifier::Italic); +let style = Style::default().add_modifier(Modifier::Italic); ``` one should use: ```rust -let style = Style::default().modifier(Modifier::ITALIC); +let style = Style::default().add_modifier(Modifier::ITALIC); // or -let style = Style::default().modifier(Modifier::ITALIC | Modifier::BOLD); +let style = Style::default().add_modifier(Modifier::ITALIC | Modifier::BOLD); ``` ### Bug Fixes