mirror of
https://github.com/ratatui-org/ratatui
synced 2024-11-21 20:23:11 +00:00
Merge branch 'main' into jm/fix-canvas-rounding
This commit is contained in:
commit
c75b2802e0
12 changed files with 256 additions and 80 deletions
4
.github/workflows/ci.yml
vendored
4
.github/workflows/ci.yml
vendored
|
@ -75,7 +75,7 @@ jobs:
|
|||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: DavidAnson/markdownlint-cli2-action@v17
|
||||
- uses: DavidAnson/markdownlint-cli2-action@v18
|
||||
with:
|
||||
globs: |
|
||||
'**/*.md'
|
||||
|
@ -94,7 +94,7 @@ jobs:
|
|||
- uses: taiki-e/install-action@cargo-llvm-cov
|
||||
- uses: Swatinem/rust-cache@v2
|
||||
- run: cargo xtask coverage
|
||||
- uses: codecov/codecov-action@v4
|
||||
- uses: codecov/codecov-action@v5
|
||||
with:
|
||||
token: ${{ secrets.CODECOV_TOKEN }}
|
||||
fail_ci_if_error: true
|
||||
|
|
91
Cargo.lock
generated
91
Cargo.lock
generated
|
@ -367,8 +367,10 @@ checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401"
|
|||
dependencies = [
|
||||
"android-tzdata",
|
||||
"iana-time-zone",
|
||||
"js-sys",
|
||||
"num-traits",
|
||||
"serde",
|
||||
"wasm-bindgen",
|
||||
"windows-targets",
|
||||
]
|
||||
|
||||
|
@ -401,9 +403,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "4.5.20"
|
||||
version = "4.5.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b97f376d85a664d5837dbae44bf546e6477a679ff6610010f17276f686d867e8"
|
||||
checksum = "fb3b4b9e5a7c7514dfa52869339ee98b3156b0bfb4e8a77c4ff4babb64b1604f"
|
||||
dependencies = [
|
||||
"clap_builder",
|
||||
"clap_derive",
|
||||
|
@ -422,9 +424,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "clap-verbosity-flag"
|
||||
version = "2.2.2"
|
||||
version = "2.2.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e099138e1807662ff75e2cebe4ae2287add879245574489f9b1588eb5e5564ed"
|
||||
checksum = "34c77f67047557f62582784fd7482884697731b2932c7d37ced54bce2312e1e2"
|
||||
dependencies = [
|
||||
"clap",
|
||||
"log",
|
||||
|
@ -432,9 +434,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "clap_builder"
|
||||
version = "4.5.20"
|
||||
version = "4.5.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "19bc80abd44e4bed93ca373a0704ccbd1b710dc5749406201bb018272808dc54"
|
||||
checksum = "b17a95aa67cc7b5ebd32aa5370189aa0d79069ef1c64ce893bd30fb24bff20ec"
|
||||
dependencies = [
|
||||
"anstream",
|
||||
"anstyle",
|
||||
|
@ -664,6 +666,41 @@ dependencies = [
|
|||
"phf",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "darling"
|
||||
version = "0.20.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6f63b86c8a8826a49b8c21f08a2d07338eec8d900540f8630dc76284be802989"
|
||||
dependencies = [
|
||||
"darling_core",
|
||||
"darling_macro",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "darling_core"
|
||||
version = "0.20.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "95133861a8032aaea082871032f5815eb9e98cef03fa916ab4500513994df9e5"
|
||||
dependencies = [
|
||||
"fnv",
|
||||
"ident_case",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"strsim 0.11.1",
|
||||
"syn 2.0.85",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "darling_macro"
|
||||
version = "0.20.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806"
|
||||
dependencies = [
|
||||
"darling_core",
|
||||
"quote",
|
||||
"syn 2.0.85",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "deltae"
|
||||
version = "0.3.2"
|
||||
|
@ -1175,6 +1212,12 @@ dependencies = [
|
|||
"cc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ident_case"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
|
||||
|
||||
[[package]]
|
||||
name = "idna"
|
||||
version = "0.5.0"
|
||||
|
@ -1209,10 +1252,14 @@ checksum = "b248f5224d1d606005e02c97f5aa4e88eeb230488bcc03bc9ca4d7991399f2b5"
|
|||
|
||||
[[package]]
|
||||
name = "instability"
|
||||
version = "0.3.2"
|
||||
version = "0.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b23a0c8dfe501baac4adf6ebbfa6eddf8f0c07f56b058cc1288017e32397846c"
|
||||
checksum = "b829f37dead9dc39df40c2d3376c179fdfd2ac771f53f55d3c30dc096a3c0c6e"
|
||||
dependencies = [
|
||||
"darling",
|
||||
"indoc",
|
||||
"pretty_assertions",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.85",
|
||||
]
|
||||
|
@ -1561,9 +1608,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "octocrab"
|
||||
version = "0.41.2"
|
||||
version = "0.42.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e2dfd11f6efbd39491d71a3864496f0b6f45e2d01b73b26c55d631c4e0dafaef"
|
||||
checksum = "5235d5839910001bef2c3df99a88688c7c781e5b1fd5fe40c5d8fa8bd786ac5a"
|
||||
dependencies = [
|
||||
"arc-swap",
|
||||
"async-trait",
|
||||
|
@ -1596,6 +1643,7 @@ dependencies = [
|
|||
"tower-http",
|
||||
"tracing",
|
||||
"url",
|
||||
"web-time",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1909,9 +1957,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.88"
|
||||
version = "1.0.89"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7c3a7fc5db1e57d5a779a352c8cdb57b29aa4c40cc69c3a68a7fedc815fbf2f9"
|
||||
checksum = "f139b0662de085916d1fb67d2b4169d1addddda1919e696f3252b740b629986e"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
@ -2492,18 +2540,18 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.214"
|
||||
version = "1.0.215"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f55c3193aca71c12ad7890f1785d2b73e1b9f63a0bbc353c08ef26fe03fc56b5"
|
||||
checksum = "6513c1ad0b11a9376da888e3e0baa0077f1aed55c17f50e7b2397136129fb88f"
|
||||
dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.214"
|
||||
version = "1.0.215"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "de523f781f095e28fa605cdce0f8307e451cc0fd14e2eb4cd2e98a355b147766"
|
||||
checksum = "ad1e866f866923f252f05c889987993144fb74e722403468a4ebd70c3cd756c0"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
@ -3357,6 +3405,17 @@ dependencies = [
|
|||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "web-time"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb"
|
||||
dependencies = [
|
||||
"js-sys",
|
||||
"serde",
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wezterm-bidi"
|
||||
version = "0.2.3"
|
||||
|
|
|
@ -27,14 +27,14 @@ rust-version = "1.74.0"
|
|||
bitflags = "2.6.0"
|
||||
document-features = "0.2.7"
|
||||
indoc = "2.0.5"
|
||||
instability = "0.3.1"
|
||||
instability = "0.3.3"
|
||||
itertools = "0.13.0"
|
||||
pretty_assertions = "1.4.1"
|
||||
ratatui = { path = "ratatui" }
|
||||
ratatui-core = { path = "ratatui-core" }
|
||||
ratatui-widgets = { path = "ratatui-widgets" }
|
||||
rstest = "0.23.0"
|
||||
serde = { version = "1.0.214", features = ["derive"] }
|
||||
serde = { version = "1.0.215", features = ["derive"] }
|
||||
strum = { version = "0.26.3", features = ["derive"] }
|
||||
unicode-segmentation = "1.12.0"
|
||||
# See <https://github.com/ratatui/ratatui/issues/1271> for information about why we pin unicode-width
|
||||
|
|
52
bacon.toml
52
bacon.toml
|
@ -8,26 +8,17 @@
|
|||
default_job = "check"
|
||||
|
||||
[jobs.check]
|
||||
command = ["cargo", "check", "--all-features", "--color", "always"]
|
||||
command = ["cargo", "check", "--all-features"]
|
||||
need_stdout = false
|
||||
|
||||
[jobs.check-all]
|
||||
command = [
|
||||
"cargo",
|
||||
"check",
|
||||
"--all-targets",
|
||||
"--all-features",
|
||||
"--color",
|
||||
"always",
|
||||
]
|
||||
command = ["cargo", "check", "--all-targets", "--all-features"]
|
||||
need_stdout = false
|
||||
|
||||
[jobs.check-crossterm]
|
||||
command = [
|
||||
"cargo",
|
||||
"check",
|
||||
"--color",
|
||||
"always",
|
||||
"--all-targets",
|
||||
"--no-default-features",
|
||||
"--features",
|
||||
|
@ -39,8 +30,6 @@ need_stdout = false
|
|||
command = [
|
||||
"cargo",
|
||||
"check",
|
||||
"--color",
|
||||
"always",
|
||||
"--all-targets",
|
||||
"--no-default-features",
|
||||
"--features",
|
||||
|
@ -52,8 +41,6 @@ need_stdout = false
|
|||
command = [
|
||||
"cargo",
|
||||
"check",
|
||||
"--color",
|
||||
"always",
|
||||
"--all-targets",
|
||||
"--no-default-features",
|
||||
"--features",
|
||||
|
@ -62,34 +49,15 @@ command = [
|
|||
need_stdout = false
|
||||
|
||||
[jobs.clippy]
|
||||
command = ["cargo", "clippy", "--all-targets", "--color", "always"]
|
||||
command = ["cargo", "clippy", "--all-targets"]
|
||||
need_stdout = false
|
||||
|
||||
[jobs.test]
|
||||
command = [
|
||||
"cargo",
|
||||
"test",
|
||||
"--all-features",
|
||||
"--color",
|
||||
"always",
|
||||
"--",
|
||||
"--color",
|
||||
"always", # see https://github.com/Canop/bacon/issues/124
|
||||
]
|
||||
command = ["cargo", "test", "--all-features"]
|
||||
need_stdout = true
|
||||
|
||||
[jobs.test-unit]
|
||||
command = [
|
||||
"cargo",
|
||||
"test",
|
||||
"--lib",
|
||||
"--all-features",
|
||||
"--color",
|
||||
"always",
|
||||
"--",
|
||||
"--color",
|
||||
"always", # see https://github.com/Canop/bacon/issues/124
|
||||
]
|
||||
command = ["cargo", "test", "--lib", "--all-features"]
|
||||
need_stdout = true
|
||||
|
||||
[jobs.doc]
|
||||
|
@ -100,8 +68,6 @@ command = [
|
|||
"-Zunstable-options",
|
||||
"-Zrustdoc-scrape-examples",
|
||||
"--all-features",
|
||||
"--color",
|
||||
"always",
|
||||
"--no-deps",
|
||||
]
|
||||
env.RUSTDOCFLAGS = "--cfg docsrs"
|
||||
|
@ -117,8 +83,6 @@ command = [
|
|||
"-Zunstable-options",
|
||||
"-Zrustdoc-scrape-examples",
|
||||
"--all-features",
|
||||
"--color",
|
||||
"always",
|
||||
"--no-deps",
|
||||
"--open",
|
||||
]
|
||||
|
@ -134,8 +98,6 @@ command = [
|
|||
"--output-path",
|
||||
"target/lcov.info",
|
||||
"--all-features",
|
||||
"--color",
|
||||
"always",
|
||||
]
|
||||
|
||||
[jobs.coverage-unit-tests-only]
|
||||
|
@ -147,8 +109,6 @@ command = [
|
|||
"target/lcov.info",
|
||||
"--lib",
|
||||
"--all-features",
|
||||
"--color",
|
||||
"always",
|
||||
]
|
||||
|
||||
[jobs.hack]
|
||||
|
@ -160,8 +120,6 @@ command = [
|
|||
"--each-feature",
|
||||
# "--all-targets",
|
||||
"--workspace",
|
||||
"--color",
|
||||
"always",
|
||||
]
|
||||
|
||||
# You may define here keybindings that would be specific to
|
||||
|
|
|
@ -1,3 +1,10 @@
|
|||
// show the feature flags in the generated documentation
|
||||
#![cfg_attr(docsrs, feature(doc_cfg))]
|
||||
#![cfg_attr(docsrs, feature(doc_auto_cfg))]
|
||||
#![doc(
|
||||
html_logo_url = "https://raw.githubusercontent.com/ratatui/ratatui/main/assets/logo.png",
|
||||
html_favicon_url = "https://raw.githubusercontent.com/ratatui/ratatui/main/assets/favicon.ico"
|
||||
)]
|
||||
//! **ratatui-core** is the core library of the [ratatui] project,
|
||||
//! providing the essential building blocks for creating rich terminal user interfaces in Rust.
|
||||
//!
|
||||
|
|
|
@ -121,7 +121,7 @@ pub trait StatefulWidget {
|
|||
/// If you don't need this then you probably want to implement [`Widget`] instead.
|
||||
///
|
||||
/// [`Widget`]: super::Widget
|
||||
type State;
|
||||
type State: ?Sized;
|
||||
/// Draws the current state of the widget in the given buffer. That is the only method required
|
||||
/// to implement a custom stateful widget.
|
||||
fn render(self, area: Rect, buf: &mut Buffer, state: &mut Self::State);
|
||||
|
@ -159,4 +159,23 @@ mod tests {
|
|||
widget.render(buf.area, &mut buf, &mut state);
|
||||
assert_eq!(buf, Buffer::with_lines(["Hello world "]));
|
||||
}
|
||||
|
||||
struct Bytes;
|
||||
|
||||
/// A widget with an unsized state type.
|
||||
impl StatefulWidget for Bytes {
|
||||
type State = [u8];
|
||||
fn render(self, area: Rect, buf: &mut Buffer, state: &mut Self::State) {
|
||||
let slice = std::str::from_utf8(state).unwrap();
|
||||
Line::from(format!("Bytes: {slice}")).render(area, buf);
|
||||
}
|
||||
}
|
||||
|
||||
#[rstest]
|
||||
fn render_unsized_state_type(mut buf: Buffer) {
|
||||
let widget = Bytes;
|
||||
let state = b"hello";
|
||||
widget.render(buf.area, &mut buf, &mut state.clone());
|
||||
assert_eq!(buf, Buffer::with_lines(["Bytes: hello "]));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,3 +1,10 @@
|
|||
// show the feature flags in the generated documentation
|
||||
#![cfg_attr(docsrs, feature(doc_cfg))]
|
||||
#![cfg_attr(docsrs, feature(doc_auto_cfg))]
|
||||
#![doc(
|
||||
html_logo_url = "https://raw.githubusercontent.com/ratatui/ratatui/main/assets/logo.png",
|
||||
html_favicon_url = "https://raw.githubusercontent.com/ratatui/ratatui/main/assets/favicon.ico"
|
||||
)]
|
||||
#![warn(missing_docs)]
|
||||
//! **ratatui-widgets** contains all the widgets that were previously part of the [Ratatui] crate.
|
||||
//! It is meant to be used in conjunction with `ratatui`, which provides the core functionality
|
||||
|
|
|
@ -43,7 +43,7 @@ fakeit = "1.1"
|
|||
font8x8 = "0.3.1"
|
||||
futures = "0.3.30"
|
||||
indoc = "2"
|
||||
octocrab = "0.41.0"
|
||||
octocrab = "0.42.0"
|
||||
pretty_assertions = "1.4.0"
|
||||
rand = "0.8.5"
|
||||
rand_chacha = "0.3.1"
|
||||
|
|
|
@ -1,3 +1,11 @@
|
|||
// show the feature flags in the generated documentation
|
||||
#![cfg_attr(docsrs, feature(doc_cfg))]
|
||||
#![cfg_attr(docsrs, feature(doc_auto_cfg))]
|
||||
#![doc(
|
||||
html_logo_url = "https://raw.githubusercontent.com/ratatui/ratatui/main/assets/logo.png",
|
||||
html_favicon_url = "https://raw.githubusercontent.com/ratatui/ratatui/main/assets/favicon.ico"
|
||||
)]
|
||||
#![warn(missing_docs)]
|
||||
//! ![Demo](https://github.com/ratatui/ratatui/blob/87ae72dbc756067c97f6400d3e2a58eeb383776e/examples/demo2-destroy.gif?raw=true)
|
||||
//!
|
||||
//! <div align="center">
|
||||
|
@ -318,13 +326,6 @@
|
|||
//! [Forum]: https://forum.ratatui.rs
|
||||
//! [Sponsors Badge]: https://img.shields.io/github/sponsors/ratatui?logo=github&style=flat-square&color=1370D3
|
||||
|
||||
// show the feature flags in the generated documentation
|
||||
#![cfg_attr(docsrs, feature(doc_auto_cfg))]
|
||||
#![doc(
|
||||
html_logo_url = "https://raw.githubusercontent.com/ratatui/ratatui/main/assets/logo.png",
|
||||
html_favicon_url = "https://raw.githubusercontent.com/ratatui/ratatui/main/assets/favicon.ico"
|
||||
)]
|
||||
|
||||
/// re-export the `crossterm` crate so that users don't have to add it as a dependency
|
||||
#[cfg(feature = "crossterm")]
|
||||
pub use crossterm;
|
||||
|
|
|
@ -61,7 +61,7 @@ pub trait StatefulWidgetRef {
|
|||
/// If you don't need this then you probably want to implement [`WidgetRef`] instead.
|
||||
///
|
||||
/// [`WidgetRef`]: super::WidgetRef
|
||||
type State;
|
||||
type State: ?Sized;
|
||||
/// Draws the current state of the widget in the given buffer. That is the only method required
|
||||
/// to implement a custom stateful widget.
|
||||
fn render_ref(&self, area: Rect, buf: &mut Buffer, state: &mut Self::State);
|
||||
|
@ -70,7 +70,7 @@ pub trait StatefulWidgetRef {
|
|||
/// Blanket implementation of `StatefulWidgetRef` for `&W` where `W` implements `StatefulWidget`.
|
||||
///
|
||||
/// This allows you to render a stateful widget by reference.
|
||||
impl<W, State> StatefulWidgetRef for &W
|
||||
impl<W, State: ?Sized> StatefulWidgetRef for &W
|
||||
where
|
||||
for<'a> &'a W: StatefulWidget<State = State>,
|
||||
{
|
||||
|
@ -119,4 +119,38 @@ mod tests {
|
|||
widget.render_ref(buf.area, &mut buf, &mut state);
|
||||
assert_eq!(buf, Buffer::with_lines(["Hello world "]));
|
||||
}
|
||||
|
||||
#[rstest]
|
||||
fn render_stateful_widget_ref_with_unsized_state(mut buf: Buffer) {
|
||||
struct Bytes;
|
||||
|
||||
impl StatefulWidgetRef for Bytes {
|
||||
type State = [u8];
|
||||
fn render_ref(&self, area: Rect, buf: &mut Buffer, state: &mut Self::State) {
|
||||
let slice = std::str::from_utf8(state).unwrap();
|
||||
Line::from(format!("Bytes: {slice}")).render(area, buf);
|
||||
}
|
||||
}
|
||||
let widget = Bytes;
|
||||
let state = b"hello";
|
||||
widget.render_ref(buf.area, &mut buf, &mut state.clone());
|
||||
assert_eq!(buf, Buffer::with_lines(["Bytes: hello "]));
|
||||
}
|
||||
|
||||
#[rstest]
|
||||
fn render_stateful_widget_with_unsized_state(mut buf: Buffer) {
|
||||
struct Bytes;
|
||||
impl StatefulWidget for &Bytes {
|
||||
type State = [u8];
|
||||
fn render(self, area: Rect, buf: &mut Buffer, state: &mut Self::State) {
|
||||
let slice = std::str::from_utf8(state).unwrap();
|
||||
Line::from(format!("Bytes: {slice}")).render(area, buf);
|
||||
}
|
||||
}
|
||||
let widget = &Bytes;
|
||||
let mut state = b"hello".to_owned();
|
||||
let state = state.as_mut_slice();
|
||||
widget.render_ref(buf.area, &mut buf, state);
|
||||
assert_eq!(buf, Buffer::with_lines(["Bytes: hello "]));
|
||||
}
|
||||
}
|
||||
|
|
91
ratatui/tests/stateful_widget_ref_dyn.rs
Normal file
91
ratatui/tests/stateful_widget_ref_dyn.rs
Normal file
|
@ -0,0 +1,91 @@
|
|||
#![cfg(feature = "unstable-widget-ref")]
|
||||
|
||||
use std::{
|
||||
any::{type_name, Any},
|
||||
cell::RefCell,
|
||||
};
|
||||
|
||||
use pretty_assertions::assert_eq;
|
||||
use ratatui::widgets::StatefulWidgetRef;
|
||||
use ratatui_core::{buffer::Buffer, layout::Rect, text::Line, widgets::Widget};
|
||||
|
||||
trait AnyWindow: StatefulWidgetRef<State = dyn Any> {
|
||||
fn title(&self) -> &str {
|
||||
type_name::<Self>()
|
||||
}
|
||||
}
|
||||
|
||||
struct Window1;
|
||||
|
||||
struct Window1State {
|
||||
pub value: u32,
|
||||
}
|
||||
|
||||
impl AnyWindow for Window1 {}
|
||||
|
||||
impl StatefulWidgetRef for Window1 {
|
||||
type State = dyn Any;
|
||||
|
||||
fn render_ref(&self, area: Rect, buf: &mut Buffer, state: &mut Self::State) {
|
||||
let state = state.downcast_mut::<Window1State>().expect("window1 state");
|
||||
Line::from(format!("{}, u32: {}", self.title(), state.value)).render(area, buf);
|
||||
}
|
||||
}
|
||||
|
||||
struct Window2;
|
||||
|
||||
struct Window2State {
|
||||
pub value: String,
|
||||
}
|
||||
|
||||
impl AnyWindow for Window2 {}
|
||||
|
||||
impl StatefulWidgetRef for Window2 {
|
||||
type State = dyn Any;
|
||||
|
||||
fn render_ref(&self, area: Rect, buf: &mut Buffer, state: &mut Self::State) {
|
||||
let state = state.downcast_mut::<Window2State>().expect("window2 state");
|
||||
Line::from(format!("{}, String: {}", self.title(), state.value)).render(area, buf);
|
||||
}
|
||||
}
|
||||
|
||||
type BoxedWindow = Box<dyn AnyWindow>;
|
||||
type BoxedState = Box<RefCell<dyn Any>>;
|
||||
|
||||
#[test]
|
||||
fn render_dyn_widgets() {
|
||||
let windows: Vec<(BoxedWindow, BoxedState)> = vec![
|
||||
(
|
||||
Box::new(Window1),
|
||||
Box::new(RefCell::new(Window1State { value: 32 })),
|
||||
),
|
||||
(
|
||||
Box::new(Window2),
|
||||
Box::new(RefCell::new(Window2State {
|
||||
value: "Some".to_string(),
|
||||
})),
|
||||
),
|
||||
(
|
||||
Box::new(Window1),
|
||||
Box::new(RefCell::new(Window1State { value: 42 })),
|
||||
),
|
||||
];
|
||||
|
||||
let mut buf = Buffer::empty(Rect::new(0, 0, 50, 3));
|
||||
|
||||
let mut area = Rect::new(0, 0, 50, 1);
|
||||
for (w, s) in &windows {
|
||||
let mut s = s.borrow_mut();
|
||||
w.render_ref(area, &mut buf, &mut *s);
|
||||
area.y += 1;
|
||||
}
|
||||
|
||||
assert_eq!(
|
||||
buf,
|
||||
Buffer::with_lines([
|
||||
"stateful_widget_ref_dyn::Window1, u32: 32 ",
|
||||
"stateful_widget_ref_dyn::Window2, String: Some ",
|
||||
"stateful_widget_ref_dyn::Window1, u32: 42 ",
|
||||
])
|
||||
);
|
||||
}
|
|
@ -6,9 +6,9 @@ license.workspace = true
|
|||
|
||||
[dependencies]
|
||||
cargo_metadata = "0.18.1"
|
||||
clap = { version = "4.5.20", features = ["derive"] }
|
||||
clap = { version = "4.5.21", features = ["derive"] }
|
||||
clap-cargo = { version = "0.14.1", features = ["cargo_metadata"] }
|
||||
clap-verbosity-flag = "2.2.2"
|
||||
clap-verbosity-flag = "2.2.3"
|
||||
color-eyre = "0.6.3"
|
||||
duct = "0.13.7"
|
||||
tracing = "0.1.40"
|
||||
|
|
Loading…
Reference in a new issue