2024-01-24 19:50:18 +00:00
|
|
|
//! # [Ratatui] Block example
|
|
|
|
//!
|
|
|
|
//! The latest version of this example is available in the [examples] folder in the repository.
|
|
|
|
//!
|
|
|
|
//! Please note that the examples are designed to be run against the `main` branch of the Github
|
|
|
|
//! repository. This means that you may not be able to compile with the latest release version on
|
|
|
|
//! crates.io, or the one that you have installed locally.
|
|
|
|
//!
|
|
|
|
//! See the [examples readme] for more information on finding examples that match the version of the
|
|
|
|
//! library you are using.
|
|
|
|
//!
|
2024-08-21 18:35:08 +00:00
|
|
|
//! [Ratatui]: https://github.com/ratatui/ratatui
|
|
|
|
//! [examples]: https://github.com/ratatui/ratatui/blob/main/examples
|
|
|
|
//! [examples readme]: https://github.com/ratatui/ratatui/blob/main/examples/README.md
|
2024-01-24 19:50:18 +00:00
|
|
|
|
feat(terminal): Add ratatui::init() and restore() methods (#1289)
These are simple opinionated methods for creating a terminal that is
useful to use in most apps. The new init method creates a crossterm
backend writing to stdout, enables raw mode, enters the alternate
screen, and sets a panic handler that restores the terminal on panic.
A minimal hello world now looks a bit like:
```rust
use ratatui::{
crossterm::event::{self, Event},
text::Text,
Frame,
};
fn main() {
let mut terminal = ratatui::init();
loop {
terminal
.draw(|frame: &mut Frame| frame.render_widget(Text::raw("Hello World!"), frame.area()))
.expect("Failed to draw");
if matches!(event::read().expect("failed to read event"), Event::Key(_)) {
break;
}
}
ratatui::restore();
}
```
A type alias `DefaultTerminal` is added to represent this terminal
type and to simplify any cases where applications need to pass this
terminal around. It is equivalent to:
`Terminal<CrosstermBackend<Stdout>>`
We also added `ratatui::try_init()` and `try_restore()`, for situations
where you might want to handle initialization errors yourself instead
of letting the panic handler fire and cleanup. Simple Apps should
prefer the `init` and `restore` functions over these functions.
Corresponding functions to allow passing a `TerminalOptions` with
a `Viewport` (e.g. inline, fixed) are also available
(`init_with_options`,
and `try_init_with_options`).
The existing code to create a backend and terminal will remain and
is not deprecated by this approach. This just provides a simple one
line initialization using the common options.
---------
Co-authored-by: Orhun Parmaksız <orhunparmaksiz@gmail.com>
2024-08-22 12:16:35 +00:00
|
|
|
use color_eyre::Result;
|
2023-08-04 07:46:37 +00:00
|
|
|
use ratatui::{
|
feat(terminal): Add ratatui::init() and restore() methods (#1289)
These are simple opinionated methods for creating a terminal that is
useful to use in most apps. The new init method creates a crossterm
backend writing to stdout, enables raw mode, enters the alternate
screen, and sets a panic handler that restores the terminal on panic.
A minimal hello world now looks a bit like:
```rust
use ratatui::{
crossterm::event::{self, Event},
text::Text,
Frame,
};
fn main() {
let mut terminal = ratatui::init();
loop {
terminal
.draw(|frame: &mut Frame| frame.render_widget(Text::raw("Hello World!"), frame.area()))
.expect("Failed to draw");
if matches!(event::read().expect("failed to read event"), Event::Key(_)) {
break;
}
}
ratatui::restore();
}
```
A type alias `DefaultTerminal` is added to represent this terminal
type and to simplify any cases where applications need to pass this
terminal around. It is equivalent to:
`Terminal<CrosstermBackend<Stdout>>`
We also added `ratatui::try_init()` and `try_restore()`, for situations
where you might want to handle initialization errors yourself instead
of letting the panic handler fire and cleanup. Simple Apps should
prefer the `init` and `restore` functions over these functions.
Corresponding functions to allow passing a `TerminalOptions` with
a `Viewport` (e.g. inline, fixed) are also available
(`init_with_options`,
and `try_init_with_options`).
The existing code to create a backend and terminal will remain and
is not deprecated by this approach. This just provides a simple one
line initialization using the common options.
---------
Co-authored-by: Orhun Parmaksız <orhunparmaksiz@gmail.com>
2024-08-22 12:16:35 +00:00
|
|
|
crossterm::event::{self, Event, KeyCode, KeyEventKind},
|
2024-05-29 11:42:29 +00:00
|
|
|
layout::{Alignment, Constraint, Layout, Rect},
|
|
|
|
style::{Style, Stylize},
|
|
|
|
text::Line,
|
2024-09-20 07:21:26 +00:00
|
|
|
widgets::{Block, BorderType, Borders, Padding, Paragraph, Wrap},
|
feat(terminal): Add ratatui::init() and restore() methods (#1289)
These are simple opinionated methods for creating a terminal that is
useful to use in most apps. The new init method creates a crossterm
backend writing to stdout, enables raw mode, enters the alternate
screen, and sets a panic handler that restores the terminal on panic.
A minimal hello world now looks a bit like:
```rust
use ratatui::{
crossterm::event::{self, Event},
text::Text,
Frame,
};
fn main() {
let mut terminal = ratatui::init();
loop {
terminal
.draw(|frame: &mut Frame| frame.render_widget(Text::raw("Hello World!"), frame.area()))
.expect("Failed to draw");
if matches!(event::read().expect("failed to read event"), Event::Key(_)) {
break;
}
}
ratatui::restore();
}
```
A type alias `DefaultTerminal` is added to represent this terminal
type and to simplify any cases where applications need to pass this
terminal around. It is equivalent to:
`Terminal<CrosstermBackend<Stdout>>`
We also added `ratatui::try_init()` and `try_restore()`, for situations
where you might want to handle initialization errors yourself instead
of letting the panic handler fire and cleanup. Simple Apps should
prefer the `init` and `restore` functions over these functions.
Corresponding functions to allow passing a `TerminalOptions` with
a `Viewport` (e.g. inline, fixed) are also available
(`init_with_options`,
and `try_init_with_options`).
The existing code to create a backend and terminal will remain and
is not deprecated by this approach. This just provides a simple one
line initialization using the common options.
---------
Co-authored-by: Orhun Parmaksız <orhunparmaksiz@gmail.com>
2024-08-22 12:16:35 +00:00
|
|
|
DefaultTerminal, Frame,
|
2023-08-04 07:46:37 +00:00
|
|
|
};
|
2017-05-08 19:34:41 +00:00
|
|
|
|
2023-08-04 07:46:37 +00:00
|
|
|
fn main() -> Result<()> {
|
feat(terminal): Add ratatui::init() and restore() methods (#1289)
These are simple opinionated methods for creating a terminal that is
useful to use in most apps. The new init method creates a crossterm
backend writing to stdout, enables raw mode, enters the alternate
screen, and sets a panic handler that restores the terminal on panic.
A minimal hello world now looks a bit like:
```rust
use ratatui::{
crossterm::event::{self, Event},
text::Text,
Frame,
};
fn main() {
let mut terminal = ratatui::init();
loop {
terminal
.draw(|frame: &mut Frame| frame.render_widget(Text::raw("Hello World!"), frame.area()))
.expect("Failed to draw");
if matches!(event::read().expect("failed to read event"), Event::Key(_)) {
break;
}
}
ratatui::restore();
}
```
A type alias `DefaultTerminal` is added to represent this terminal
type and to simplify any cases where applications need to pass this
terminal around. It is equivalent to:
`Terminal<CrosstermBackend<Stdout>>`
We also added `ratatui::try_init()` and `try_restore()`, for situations
where you might want to handle initialization errors yourself instead
of letting the panic handler fire and cleanup. Simple Apps should
prefer the `init` and `restore` functions over these functions.
Corresponding functions to allow passing a `TerminalOptions` with
a `Viewport` (e.g. inline, fixed) are also available
(`init_with_options`,
and `try_init_with_options`).
The existing code to create a backend and terminal will remain and
is not deprecated by this approach. This just provides a simple one
line initialization using the common options.
---------
Co-authored-by: Orhun Parmaksız <orhunparmaksiz@gmail.com>
2024-08-22 12:16:35 +00:00
|
|
|
color_eyre::install()?;
|
|
|
|
let terminal = ratatui::init();
|
|
|
|
let result = run(terminal);
|
|
|
|
ratatui::restore();
|
|
|
|
result
|
2021-11-01 21:27:46 +00:00
|
|
|
}
|
2018-09-23 18:59:51 +00:00
|
|
|
|
feat(terminal): Add ratatui::init() and restore() methods (#1289)
These are simple opinionated methods for creating a terminal that is
useful to use in most apps. The new init method creates a crossterm
backend writing to stdout, enables raw mode, enters the alternate
screen, and sets a panic handler that restores the terminal on panic.
A minimal hello world now looks a bit like:
```rust
use ratatui::{
crossterm::event::{self, Event},
text::Text,
Frame,
};
fn main() {
let mut terminal = ratatui::init();
loop {
terminal
.draw(|frame: &mut Frame| frame.render_widget(Text::raw("Hello World!"), frame.area()))
.expect("Failed to draw");
if matches!(event::read().expect("failed to read event"), Event::Key(_)) {
break;
}
}
ratatui::restore();
}
```
A type alias `DefaultTerminal` is added to represent this terminal
type and to simplify any cases where applications need to pass this
terminal around. It is equivalent to:
`Terminal<CrosstermBackend<Stdout>>`
We also added `ratatui::try_init()` and `try_restore()`, for situations
where you might want to handle initialization errors yourself instead
of letting the panic handler fire and cleanup. Simple Apps should
prefer the `init` and `restore` functions over these functions.
Corresponding functions to allow passing a `TerminalOptions` with
a `Viewport` (e.g. inline, fixed) are also available
(`init_with_options`,
and `try_init_with_options`).
The existing code to create a backend and terminal will remain and
is not deprecated by this approach. This just provides a simple one
line initialization using the common options.
---------
Co-authored-by: Orhun Parmaksız <orhunparmaksiz@gmail.com>
2024-08-22 12:16:35 +00:00
|
|
|
fn run(mut terminal: DefaultTerminal) -> Result<()> {
|
2018-09-23 18:59:51 +00:00
|
|
|
loop {
|
feat(terminal): Add ratatui::init() and restore() methods (#1289)
These are simple opinionated methods for creating a terminal that is
useful to use in most apps. The new init method creates a crossterm
backend writing to stdout, enables raw mode, enters the alternate
screen, and sets a panic handler that restores the terminal on panic.
A minimal hello world now looks a bit like:
```rust
use ratatui::{
crossterm::event::{self, Event},
text::Text,
Frame,
};
fn main() {
let mut terminal = ratatui::init();
loop {
terminal
.draw(|frame: &mut Frame| frame.render_widget(Text::raw("Hello World!"), frame.area()))
.expect("Failed to draw");
if matches!(event::read().expect("failed to read event"), Event::Key(_)) {
break;
}
}
ratatui::restore();
}
```
A type alias `DefaultTerminal` is added to represent this terminal
type and to simplify any cases where applications need to pass this
terminal around. It is equivalent to:
`Terminal<CrosstermBackend<Stdout>>`
We also added `ratatui::try_init()` and `try_restore()`, for situations
where you might want to handle initialization errors yourself instead
of letting the panic handler fire and cleanup. Simple Apps should
prefer the `init` and `restore` functions over these functions.
Corresponding functions to allow passing a `TerminalOptions` with
a `Viewport` (e.g. inline, fixed) are also available
(`init_with_options`,
and `try_init_with_options`).
The existing code to create a backend and terminal will remain and
is not deprecated by this approach. This just provides a simple one
line initialization using the common options.
---------
Co-authored-by: Orhun Parmaksız <orhunparmaksiz@gmail.com>
2024-08-22 12:16:35 +00:00
|
|
|
terminal.draw(draw)?;
|
2023-08-04 07:46:37 +00:00
|
|
|
if let Event::Key(key) = event::read()? {
|
feat(terminal): Add ratatui::init() and restore() methods (#1289)
These are simple opinionated methods for creating a terminal that is
useful to use in most apps. The new init method creates a crossterm
backend writing to stdout, enables raw mode, enters the alternate
screen, and sets a panic handler that restores the terminal on panic.
A minimal hello world now looks a bit like:
```rust
use ratatui::{
crossterm::event::{self, Event},
text::Text,
Frame,
};
fn main() {
let mut terminal = ratatui::init();
loop {
terminal
.draw(|frame: &mut Frame| frame.render_widget(Text::raw("Hello World!"), frame.area()))
.expect("Failed to draw");
if matches!(event::read().expect("failed to read event"), Event::Key(_)) {
break;
}
}
ratatui::restore();
}
```
A type alias `DefaultTerminal` is added to represent this terminal
type and to simplify any cases where applications need to pass this
terminal around. It is equivalent to:
`Terminal<CrosstermBackend<Stdout>>`
We also added `ratatui::try_init()` and `try_restore()`, for situations
where you might want to handle initialization errors yourself instead
of letting the panic handler fire and cleanup. Simple Apps should
prefer the `init` and `restore` functions over these functions.
Corresponding functions to allow passing a `TerminalOptions` with
a `Viewport` (e.g. inline, fixed) are also available
(`init_with_options`,
and `try_init_with_options`).
The existing code to create a backend and terminal will remain and
is not deprecated by this approach. This just provides a simple one
line initialization using the common options.
---------
Co-authored-by: Orhun Parmaksız <orhunparmaksiz@gmail.com>
2024-08-22 12:16:35 +00:00
|
|
|
if key.kind == KeyEventKind::Press && key.code == KeyCode::Char('q') {
|
|
|
|
break Ok(());
|
2018-12-07 15:17:33 +00:00
|
|
|
}
|
2018-08-12 17:44:52 +00:00
|
|
|
}
|
2018-09-23 18:59:51 +00:00
|
|
|
}
|
2021-11-01 21:27:46 +00:00
|
|
|
}
|
|
|
|
|
feat(terminal): Add ratatui::init() and restore() methods (#1289)
These are simple opinionated methods for creating a terminal that is
useful to use in most apps. The new init method creates a crossterm
backend writing to stdout, enables raw mode, enters the alternate
screen, and sets a panic handler that restores the terminal on panic.
A minimal hello world now looks a bit like:
```rust
use ratatui::{
crossterm::event::{self, Event},
text::Text,
Frame,
};
fn main() {
let mut terminal = ratatui::init();
loop {
terminal
.draw(|frame: &mut Frame| frame.render_widget(Text::raw("Hello World!"), frame.area()))
.expect("Failed to draw");
if matches!(event::read().expect("failed to read event"), Event::Key(_)) {
break;
}
}
ratatui::restore();
}
```
A type alias `DefaultTerminal` is added to represent this terminal
type and to simplify any cases where applications need to pass this
terminal around. It is equivalent to:
`Terminal<CrosstermBackend<Stdout>>`
We also added `ratatui::try_init()` and `try_restore()`, for situations
where you might want to handle initialization errors yourself instead
of letting the panic handler fire and cleanup. Simple Apps should
prefer the `init` and `restore` functions over these functions.
Corresponding functions to allow passing a `TerminalOptions` with
a `Viewport` (e.g. inline, fixed) are also available
(`init_with_options`,
and `try_init_with_options`).
The existing code to create a backend and terminal will remain and
is not deprecated by this approach. This just provides a simple one
line initialization using the common options.
---------
Co-authored-by: Orhun Parmaksız <orhunparmaksiz@gmail.com>
2024-08-22 12:16:35 +00:00
|
|
|
fn draw(frame: &mut Frame) {
|
2024-08-06 03:15:14 +00:00
|
|
|
let (title_area, layout) = calculate_layout(frame.area());
|
2023-08-04 07:46:37 +00:00
|
|
|
|
|
|
|
render_title(frame, title_area);
|
|
|
|
|
|
|
|
let paragraph = placeholder_paragraph();
|
|
|
|
|
|
|
|
render_borders(¶graph, Borders::ALL, frame, layout[0][0]);
|
|
|
|
render_borders(¶graph, Borders::NONE, frame, layout[0][1]);
|
|
|
|
render_borders(¶graph, Borders::LEFT, frame, layout[1][0]);
|
|
|
|
render_borders(¶graph, Borders::RIGHT, frame, layout[1][1]);
|
|
|
|
render_borders(¶graph, Borders::TOP, frame, layout[2][0]);
|
|
|
|
render_borders(¶graph, Borders::BOTTOM, frame, layout[2][1]);
|
|
|
|
|
|
|
|
render_border_type(¶graph, BorderType::Plain, frame, layout[3][0]);
|
|
|
|
render_border_type(¶graph, BorderType::Rounded, frame, layout[3][1]);
|
|
|
|
render_border_type(¶graph, BorderType::Double, frame, layout[4][0]);
|
|
|
|
render_border_type(¶graph, BorderType::Thick, frame, layout[4][1]);
|
|
|
|
|
|
|
|
render_styled_block(¶graph, frame, layout[5][0]);
|
|
|
|
render_styled_borders(¶graph, frame, layout[5][1]);
|
|
|
|
render_styled_title(¶graph, frame, layout[6][0]);
|
|
|
|
render_styled_title_content(¶graph, frame, layout[6][1]);
|
|
|
|
render_multiple_titles(¶graph, frame, layout[7][0]);
|
|
|
|
render_multiple_title_positions(¶graph, frame, layout[7][1]);
|
|
|
|
render_padding(¶graph, frame, layout[8][0]);
|
|
|
|
render_nested_blocks(¶graph, frame, layout[8][1]);
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Calculate the layout of the UI elements.
|
|
|
|
///
|
|
|
|
/// Returns a tuple of the title area and the main areas.
|
|
|
|
fn calculate_layout(area: Rect) -> (Rect, Vec<Vec<Rect>>) {
|
2024-01-05 15:45:14 +00:00
|
|
|
let main_layout = Layout::vertical([Constraint::Length(1), Constraint::Min(0)]);
|
2024-02-02 04:26:35 +00:00
|
|
|
let block_layout = Layout::vertical([Constraint::Max(4); 9]);
|
|
|
|
let [title_area, main_area] = main_layout.areas(area);
|
2024-01-05 15:45:14 +00:00
|
|
|
let main_areas = block_layout
|
|
|
|
.split(main_area)
|
2023-08-04 07:46:37 +00:00
|
|
|
.iter()
|
|
|
|
.map(|&area| {
|
2024-01-05 15:45:14 +00:00
|
|
|
Layout::horizontal([Constraint::Percentage(50), Constraint::Percentage(50)])
|
2023-08-04 07:46:37 +00:00
|
|
|
.split(area)
|
|
|
|
.to_vec()
|
|
|
|
})
|
2024-08-26 20:59:30 +00:00
|
|
|
.collect();
|
2023-08-04 07:46:37 +00:00
|
|
|
(title_area, main_areas)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn render_title(frame: &mut Frame, area: Rect) {
|
|
|
|
frame.render_widget(
|
|
|
|
Paragraph::new("Block example. Press q to quit")
|
|
|
|
.dark_gray()
|
|
|
|
.alignment(Alignment::Center),
|
|
|
|
area,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
fn placeholder_paragraph() -> Paragraph<'static> {
|
|
|
|
let text = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.";
|
|
|
|
Paragraph::new(text.dark_gray()).wrap(Wrap { trim: true })
|
|
|
|
}
|
|
|
|
|
|
|
|
fn render_borders(paragraph: &Paragraph, border: Borders, frame: &mut Frame, area: Rect) {
|
|
|
|
let block = Block::new()
|
|
|
|
.borders(border)
|
2024-03-02 09:06:53 +00:00
|
|
|
.title(format!("Borders::{border:#?}"));
|
2023-08-04 07:46:37 +00:00
|
|
|
frame.render_widget(paragraph.clone().block(block), area);
|
|
|
|
}
|
|
|
|
|
|
|
|
fn render_border_type(
|
|
|
|
paragraph: &Paragraph,
|
|
|
|
border_type: BorderType,
|
|
|
|
frame: &mut Frame,
|
|
|
|
area: Rect,
|
|
|
|
) {
|
2024-05-02 10:09:48 +00:00
|
|
|
let block = Block::bordered()
|
2023-08-04 07:46:37 +00:00
|
|
|
.border_type(border_type)
|
|
|
|
.title(format!("BorderType::{border_type:#?}"));
|
|
|
|
frame.render_widget(paragraph.clone().block(block), area);
|
|
|
|
}
|
|
|
|
fn render_styled_borders(paragraph: &Paragraph, frame: &mut Frame, area: Rect) {
|
2024-05-02 10:09:48 +00:00
|
|
|
let block = Block::bordered()
|
2023-08-04 07:46:37 +00:00
|
|
|
.border_style(Style::new().blue().on_white().bold().italic())
|
|
|
|
.title("Styled borders");
|
|
|
|
frame.render_widget(paragraph.clone().block(block), area);
|
|
|
|
}
|
|
|
|
|
|
|
|
fn render_styled_block(paragraph: &Paragraph, frame: &mut Frame, area: Rect) {
|
2024-05-02 10:09:48 +00:00
|
|
|
let block = Block::bordered()
|
2023-08-04 07:46:37 +00:00
|
|
|
.style(Style::new().blue().on_white().bold().italic())
|
|
|
|
.title("Styled block");
|
|
|
|
frame.render_widget(paragraph.clone().block(block), area);
|
|
|
|
}
|
|
|
|
|
|
|
|
fn render_styled_title(paragraph: &Paragraph, frame: &mut Frame, area: Rect) {
|
2024-05-02 10:09:48 +00:00
|
|
|
let block = Block::bordered()
|
2023-08-04 07:46:37 +00:00
|
|
|
.title("Styled title")
|
|
|
|
.title_style(Style::new().blue().on_white().bold().italic());
|
|
|
|
frame.render_widget(paragraph.clone().block(block), area);
|
|
|
|
}
|
|
|
|
|
|
|
|
fn render_styled_title_content(paragraph: &Paragraph, frame: &mut Frame, area: Rect) {
|
|
|
|
let title = Line::from(vec![
|
|
|
|
"Styled ".blue().on_white().bold().italic(),
|
|
|
|
"title content".red().on_white().bold().italic(),
|
|
|
|
]);
|
2024-05-02 10:09:48 +00:00
|
|
|
let block = Block::bordered().title(title);
|
2023-08-04 07:46:37 +00:00
|
|
|
frame.render_widget(paragraph.clone().block(block), area);
|
|
|
|
}
|
|
|
|
|
|
|
|
fn render_multiple_titles(paragraph: &Paragraph, frame: &mut Frame, area: Rect) {
|
2024-05-02 10:09:48 +00:00
|
|
|
let block = Block::bordered()
|
2023-08-04 07:46:37 +00:00
|
|
|
.title("Multiple".blue().on_white().bold().italic())
|
|
|
|
.title("Titles".red().on_white().bold().italic());
|
|
|
|
frame.render_widget(paragraph.clone().block(block), area);
|
|
|
|
}
|
|
|
|
|
|
|
|
fn render_multiple_title_positions(paragraph: &Paragraph, frame: &mut Frame, area: Rect) {
|
2024-05-02 10:09:48 +00:00
|
|
|
let block = Block::bordered()
|
2024-09-20 07:21:26 +00:00
|
|
|
.title(Line::from("top left").left_aligned())
|
|
|
|
.title(Line::from("top center").centered())
|
|
|
|
.title(Line::from("top right").right_aligned())
|
|
|
|
.title_bottom(Line::from("bottom left").left_aligned())
|
|
|
|
.title_bottom(Line::from("bottom center").centered())
|
|
|
|
.title_bottom(Line::from("bottom right").right_aligned());
|
2023-08-04 07:46:37 +00:00
|
|
|
frame.render_widget(paragraph.clone().block(block), area);
|
|
|
|
}
|
|
|
|
|
|
|
|
fn render_padding(paragraph: &Paragraph, frame: &mut Frame, area: Rect) {
|
2024-05-02 10:09:48 +00:00
|
|
|
let block = Block::bordered()
|
|
|
|
.padding(Padding::new(5, 10, 1, 2))
|
|
|
|
.title("Padding");
|
2023-08-04 07:46:37 +00:00
|
|
|
frame.render_widget(paragraph.clone().block(block), area);
|
|
|
|
}
|
|
|
|
|
|
|
|
fn render_nested_blocks(paragraph: &Paragraph, frame: &mut Frame, area: Rect) {
|
2024-05-02 10:09:48 +00:00
|
|
|
let outer_block = Block::bordered().title("Outer block");
|
|
|
|
let inner_block = Block::bordered().title("Inner block");
|
2023-08-04 07:46:37 +00:00
|
|
|
let inner = outer_block.inner(area);
|
|
|
|
frame.render_widget(outer_block, area);
|
|
|
|
frame.render_widget(paragraph.clone().block(inner_block), inner);
|
2016-10-15 22:38:20 +00:00
|
|
|
}
|