mirror of
https://github.com/trezor/trezor-firmware.git
synced 2025-01-10 23:40:58 +00:00
chore(core/rust): Split FormattedText into separate mod
This commit is contained in:
parent
d5a74a8614
commit
334a143b76
@ -8,4 +8,7 @@ pub mod tuple;
|
||||
pub use base::{Child, Component, Event, EventCtx, Never, TimerToken};
|
||||
pub use empty::Empty;
|
||||
pub use label::{Label, LabelStyle};
|
||||
pub use text::{FormattedText, LineBreaking, PageBreaking, TextLayout};
|
||||
pub use text::{
|
||||
formatted::FormattedText,
|
||||
layout::{LineBreaking, PageBreaking, TextLayout},
|
||||
};
|
||||
|
270
core/embed/rust/src/ui/component/text/formatted.rs
Normal file
270
core/embed/rust/src/ui/component/text/formatted.rs
Normal file
@ -0,0 +1,270 @@
|
||||
use core::{
|
||||
iter::{Enumerate, Peekable},
|
||||
slice,
|
||||
};
|
||||
|
||||
use heapless::LinearMap;
|
||||
|
||||
use crate::ui::{
|
||||
component::{Component, Event, EventCtx, Never},
|
||||
display::{Color, Font},
|
||||
geometry::Rect,
|
||||
};
|
||||
|
||||
use super::layout::{
|
||||
DefaultTextTheme, LayoutSink, LineBreaking, Op, PageBreaking, TextLayout, TextRenderer,
|
||||
};
|
||||
|
||||
pub const MAX_ARGUMENTS: usize = 6;
|
||||
|
||||
pub struct FormattedText<F, T> {
|
||||
layout: TextLayout,
|
||||
format: F,
|
||||
args: LinearMap<&'static [u8], T, MAX_ARGUMENTS>,
|
||||
}
|
||||
|
||||
impl<F, T> FormattedText<F, T> {
|
||||
pub fn new<D: DefaultTextTheme>(area: Rect, format: F) -> Self {
|
||||
Self {
|
||||
layout: TextLayout::new::<D>(area),
|
||||
format,
|
||||
args: LinearMap::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn with(mut self, key: &'static [u8], value: T) -> Self {
|
||||
if self.args.insert(key, value).is_err() {
|
||||
// Map is full, ignore.
|
||||
#[cfg(feature = "ui_debug")]
|
||||
panic!("text args map is full");
|
||||
}
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_format(mut self, format: F) -> Self {
|
||||
self.format = format;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_text_font(mut self, text_font: Font) -> Self {
|
||||
self.layout.text_font = text_font;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_text_color(mut self, text_color: Color) -> Self {
|
||||
self.layout.text_color = text_color;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_line_breaking(mut self, line_breaking: LineBreaking) -> Self {
|
||||
self.layout.line_breaking = line_breaking;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_page_breaking(mut self, page_breaking: PageBreaking) -> Self {
|
||||
self.layout.page_breaking = page_breaking;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn layout_mut(&mut self) -> &mut TextLayout {
|
||||
&mut self.layout
|
||||
}
|
||||
}
|
||||
|
||||
impl<F, T> FormattedText<F, T>
|
||||
where
|
||||
F: AsRef<[u8]>,
|
||||
T: AsRef<[u8]>,
|
||||
{
|
||||
fn layout_content(&self, sink: &mut dyn LayoutSink) {
|
||||
let mut cursor = self.layout.initial_cursor();
|
||||
let mut ops = Tokenizer::new(self.format.as_ref()).flat_map(|arg| match arg {
|
||||
Token::Literal(literal) => Some(Op::Text(literal)),
|
||||
Token::Argument(b"mono") => Some(Op::Font(self.layout.mono_font)),
|
||||
Token::Argument(b"bold") => Some(Op::Font(self.layout.bold_font)),
|
||||
Token::Argument(b"normal") => Some(Op::Font(self.layout.normal_font)),
|
||||
Token::Argument(argument) => self
|
||||
.args
|
||||
.get(argument)
|
||||
.map(|value| Op::Text(value.as_ref())),
|
||||
});
|
||||
self.layout.layout_ops(&mut ops, &mut cursor, sink);
|
||||
}
|
||||
}
|
||||
|
||||
impl<F, T> Component for FormattedText<F, T>
|
||||
where
|
||||
F: AsRef<[u8]>,
|
||||
T: AsRef<[u8]>,
|
||||
{
|
||||
type Msg = Never;
|
||||
|
||||
fn event(&mut self, _ctx: &mut EventCtx, _event: Event) -> Option<Self::Msg> {
|
||||
None
|
||||
}
|
||||
|
||||
fn paint(&mut self) {
|
||||
self.layout_content(&mut TextRenderer);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "ui_debug")]
|
||||
mod trace {
|
||||
use crate::ui::geometry::Point;
|
||||
|
||||
use super::*;
|
||||
|
||||
pub struct TraceSink<'a>(pub &'a mut dyn crate::trace::Tracer);
|
||||
|
||||
impl<'a> LayoutSink for TraceSink<'a> {
|
||||
fn text(&mut self, _cursor: Point, _layout: &TextLayout, text: &[u8]) {
|
||||
self.0.bytes(text);
|
||||
}
|
||||
|
||||
fn hyphen(&mut self, _cursor: Point, _layout: &TextLayout) {
|
||||
self.0.string("-");
|
||||
}
|
||||
|
||||
fn ellipsis(&mut self, _cursor: Point, _layout: &TextLayout) {
|
||||
self.0.string("...");
|
||||
}
|
||||
|
||||
fn line_break(&mut self, _cursor: Point) {
|
||||
self.0.string("\n");
|
||||
}
|
||||
}
|
||||
|
||||
pub struct TraceText<'a, F, T>(pub &'a FormattedText<F, T>);
|
||||
|
||||
impl<'a, F, T> crate::trace::Trace for TraceText<'a, F, T>
|
||||
where
|
||||
F: AsRef<[u8]>,
|
||||
T: AsRef<[u8]>,
|
||||
{
|
||||
fn trace(&self, d: &mut dyn crate::trace::Tracer) {
|
||||
self.0.layout_content(&mut TraceSink(d));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "ui_debug")]
|
||||
impl<F, T> crate::trace::Trace for FormattedText<F, T>
|
||||
where
|
||||
F: AsRef<[u8]>,
|
||||
T: AsRef<[u8]>,
|
||||
{
|
||||
fn trace(&self, t: &mut dyn crate::trace::Tracer) {
|
||||
t.open("Text");
|
||||
t.field("content", &trace::TraceText(self));
|
||||
t.close();
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Eq)]
|
||||
pub enum Token<'a> {
|
||||
/// Process literal text content.
|
||||
Literal(&'a [u8]),
|
||||
/// Process argument with specified descriptor.
|
||||
Argument(&'a [u8]),
|
||||
}
|
||||
|
||||
/// Processes a format string into an iterator of `Token`s.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// let parser = Tokenizer::new("Nice to meet {you}, where you been?");
|
||||
/// assert!(matches!(parser.next(), Some(Token::Literal("Nice to meet "))));
|
||||
/// assert!(matches!(parser.next(), Some(Token::Argument("you"))));
|
||||
/// assert!(matches!(parser.next(), Some(Token::Literal(", where you been?"))));
|
||||
/// ```
|
||||
pub struct Tokenizer<'a> {
|
||||
input: &'a [u8],
|
||||
inner: Peekable<Enumerate<slice::Iter<'a, u8>>>,
|
||||
}
|
||||
|
||||
impl<'a> Tokenizer<'a> {
|
||||
/// Create a new tokenizer for bytes of a formatting string `input`,
|
||||
/// returning an iterator.
|
||||
pub fn new(input: &'a [u8]) -> Self {
|
||||
Self {
|
||||
input,
|
||||
inner: input.iter().enumerate().peekable(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Iterator for Tokenizer<'a> {
|
||||
type Item = Token<'a>;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
const ASCII_OPEN_BRACE: u8 = b'{';
|
||||
const ASCII_CLOSED_BRACE: u8 = b'}';
|
||||
|
||||
match self.inner.next() {
|
||||
// Argument token is starting. Read until we find '}', then parse the content between
|
||||
// the braces and return the token. If we encounter the end of string before the closing
|
||||
// brace, quit.
|
||||
Some((open, &ASCII_OPEN_BRACE)) => loop {
|
||||
match self.inner.next() {
|
||||
Some((close, &ASCII_CLOSED_BRACE)) => {
|
||||
break Some(Token::Argument(&self.input[open + 1..close]));
|
||||
}
|
||||
None => {
|
||||
break None;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
},
|
||||
// Literal token is starting. Read until we find '{' or the end of string, and return
|
||||
// the token. Use `peek()` for matching the opening brace, se we can keep it
|
||||
// in the iterator for the above code.
|
||||
Some((start, _)) => loop {
|
||||
match self.inner.peek() {
|
||||
Some(&(open, &ASCII_OPEN_BRACE)) => {
|
||||
break Some(Token::Literal(&self.input[start..open]));
|
||||
}
|
||||
None => {
|
||||
break Some(Token::Literal(&self.input[start..]));
|
||||
}
|
||||
_ => {
|
||||
self.inner.next();
|
||||
}
|
||||
}
|
||||
},
|
||||
None => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn tokenizer_yields_expected_tokens() {
|
||||
use std::array::IntoIter;
|
||||
|
||||
assert!(Tokenizer::new(b"").eq(IntoIter::new([])));
|
||||
assert!(Tokenizer::new(b"x").eq(IntoIter::new([Token::Literal(b"x")])));
|
||||
assert!(Tokenizer::new(b"x\0y").eq(IntoIter::new([Token::Literal("x\0y".as_bytes())])));
|
||||
assert!(Tokenizer::new(b"{").eq(IntoIter::new([])));
|
||||
assert!(Tokenizer::new(b"x{").eq(IntoIter::new([Token::Literal(b"x")])));
|
||||
assert!(Tokenizer::new(b"x{y").eq(IntoIter::new([Token::Literal(b"x")])));
|
||||
assert!(Tokenizer::new(b"{}").eq(IntoIter::new([Token::Argument(b"")])));
|
||||
assert!(Tokenizer::new(b"x{}y{").eq(IntoIter::new([
|
||||
Token::Literal(b"x"),
|
||||
Token::Argument(b""),
|
||||
Token::Literal(b"y"),
|
||||
])));
|
||||
assert!(Tokenizer::new(b"{\0}").eq(IntoIter::new([Token::Argument("\0".as_bytes()),])));
|
||||
assert!(Tokenizer::new(b"{{y}").eq(IntoIter::new([Token::Argument(b"{y"),])));
|
||||
assert!(Tokenizer::new(b"{{{{xyz").eq(IntoIter::new([])));
|
||||
assert!(Tokenizer::new(b"x{}{{}}}}").eq(IntoIter::new([
|
||||
Token::Literal(b"x"),
|
||||
Token::Argument(b""),
|
||||
Token::Argument(b"{"),
|
||||
Token::Literal(b"}}}"),
|
||||
])));
|
||||
}
|
||||
}
|
@ -1,160 +1,9 @@
|
||||
use core::{
|
||||
iter::{Enumerate, Peekable},
|
||||
slice,
|
||||
};
|
||||
|
||||
use heapless::LinearMap;
|
||||
|
||||
use crate::ui::{
|
||||
component::{Component, Event, EventCtx, Never},
|
||||
display,
|
||||
display::{Color, Font},
|
||||
geometry::{Offset, Point, Rect},
|
||||
};
|
||||
|
||||
pub const MAX_ARGUMENTS: usize = 6;
|
||||
|
||||
pub struct FormattedText<F, T> {
|
||||
layout: TextLayout,
|
||||
format: F,
|
||||
args: LinearMap<&'static [u8], T, MAX_ARGUMENTS>,
|
||||
}
|
||||
|
||||
impl<F, T> FormattedText<F, T> {
|
||||
pub fn new<D: DefaultTextTheme>(area: Rect, format: F) -> Self {
|
||||
Self {
|
||||
layout: TextLayout::new::<D>(area),
|
||||
format,
|
||||
args: LinearMap::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn with(mut self, key: &'static [u8], value: T) -> Self {
|
||||
if self.args.insert(key, value).is_err() {
|
||||
// Map is full, ignore.
|
||||
#[cfg(feature = "ui_debug")]
|
||||
panic!("text args map is full");
|
||||
}
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_format(mut self, format: F) -> Self {
|
||||
self.format = format;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_text_font(mut self, text_font: Font) -> Self {
|
||||
self.layout.text_font = text_font;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_text_color(mut self, text_color: Color) -> Self {
|
||||
self.layout.text_color = text_color;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_line_breaking(mut self, line_breaking: LineBreaking) -> Self {
|
||||
self.layout.line_breaking = line_breaking;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_page_breaking(mut self, page_breaking: PageBreaking) -> Self {
|
||||
self.layout.page_breaking = page_breaking;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn layout_mut(&mut self) -> &mut TextLayout {
|
||||
&mut self.layout
|
||||
}
|
||||
}
|
||||
|
||||
impl<F, T> FormattedText<F, T>
|
||||
where
|
||||
F: AsRef<[u8]>,
|
||||
T: AsRef<[u8]>,
|
||||
{
|
||||
fn layout_content(&self, sink: &mut dyn LayoutSink) {
|
||||
let mut cursor = self.layout.initial_cursor();
|
||||
let mut ops = Tokenizer::new(self.format.as_ref()).flat_map(|arg| match arg {
|
||||
Token::Literal(literal) => Some(Op::Text(literal)),
|
||||
Token::Argument(b"mono") => Some(Op::Font(self.layout.mono_font)),
|
||||
Token::Argument(b"bold") => Some(Op::Font(self.layout.bold_font)),
|
||||
Token::Argument(b"normal") => Some(Op::Font(self.layout.normal_font)),
|
||||
Token::Argument(argument) => self
|
||||
.args
|
||||
.get(argument)
|
||||
.map(|value| Op::Text(value.as_ref())),
|
||||
});
|
||||
self.layout.layout_ops(&mut ops, &mut cursor, sink);
|
||||
}
|
||||
}
|
||||
|
||||
impl<F, T> Component for FormattedText<F, T>
|
||||
where
|
||||
F: AsRef<[u8]>,
|
||||
T: AsRef<[u8]>,
|
||||
{
|
||||
type Msg = Never;
|
||||
|
||||
fn event(&mut self, _ctx: &mut EventCtx, _event: Event) -> Option<Self::Msg> {
|
||||
None
|
||||
}
|
||||
|
||||
fn paint(&mut self) {
|
||||
self.layout_content(&mut TextRenderer);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "ui_debug")]
|
||||
mod trace {
|
||||
use super::*;
|
||||
|
||||
pub struct TraceSink<'a>(pub &'a mut dyn crate::trace::Tracer);
|
||||
|
||||
impl<'a> LayoutSink for TraceSink<'a> {
|
||||
fn text(&mut self, _cursor: Point, _layout: &TextLayout, text: &[u8]) {
|
||||
self.0.bytes(text);
|
||||
}
|
||||
|
||||
fn hyphen(&mut self, _cursor: Point, _layout: &TextLayout) {
|
||||
self.0.string("-");
|
||||
}
|
||||
|
||||
fn ellipsis(&mut self, _cursor: Point, _layout: &TextLayout) {
|
||||
self.0.string("...");
|
||||
}
|
||||
|
||||
fn line_break(&mut self, _cursor: Point) {
|
||||
self.0.string("\n");
|
||||
}
|
||||
}
|
||||
|
||||
pub struct TraceText<'a, F, T>(pub &'a FormattedText<F, T>);
|
||||
|
||||
impl<'a, F, T> crate::trace::Trace for TraceText<'a, F, T>
|
||||
where
|
||||
F: AsRef<[u8]>,
|
||||
T: AsRef<[u8]>,
|
||||
{
|
||||
fn trace(&self, d: &mut dyn crate::trace::Tracer) {
|
||||
self.0.layout_content(&mut TraceSink(d));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "ui_debug")]
|
||||
impl<F, T> crate::trace::Trace for FormattedText<F, T>
|
||||
where
|
||||
F: AsRef<[u8]>,
|
||||
T: AsRef<[u8]>,
|
||||
{
|
||||
fn trace(&self, t: &mut dyn crate::trace::Tracer) {
|
||||
t.open("Text");
|
||||
t.field("content", &trace::TraceText(self));
|
||||
t.close();
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
pub enum LineBreaking {
|
||||
/// Break line only at whitespace, if possible. If we don't find any
|
||||
@ -409,83 +258,6 @@ impl LayoutSink for TextRenderer {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Eq)]
|
||||
pub enum Token<'a> {
|
||||
/// Process literal text content.
|
||||
Literal(&'a [u8]),
|
||||
/// Process argument with specified descriptor.
|
||||
Argument(&'a [u8]),
|
||||
}
|
||||
|
||||
/// Processes a format string into an iterator of `Token`s.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// let parser = Tokenizer::new("Nice to meet {you}, where you been?");
|
||||
/// assert!(matches!(parser.next(), Some(Token::Literal("Nice to meet "))));
|
||||
/// assert!(matches!(parser.next(), Some(Token::Argument("you"))));
|
||||
/// assert!(matches!(parser.next(), Some(Token::Literal(", where you been?"))));
|
||||
/// ```
|
||||
pub struct Tokenizer<'a> {
|
||||
input: &'a [u8],
|
||||
inner: Peekable<Enumerate<slice::Iter<'a, u8>>>,
|
||||
}
|
||||
|
||||
impl<'a> Tokenizer<'a> {
|
||||
/// Create a new tokenizer for bytes of a formatting string `input`,
|
||||
/// returning an iterator.
|
||||
pub fn new(input: &'a [u8]) -> Self {
|
||||
Self {
|
||||
input,
|
||||
inner: input.iter().enumerate().peekable(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Iterator for Tokenizer<'a> {
|
||||
type Item = Token<'a>;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
const ASCII_OPEN_BRACE: u8 = b'{';
|
||||
const ASCII_CLOSED_BRACE: u8 = b'}';
|
||||
|
||||
match self.inner.next() {
|
||||
// Argument token is starting. Read until we find '}', then parse the content between
|
||||
// the braces and return the token. If we encounter the end of string before the closing
|
||||
// brace, quit.
|
||||
Some((open, &ASCII_OPEN_BRACE)) => loop {
|
||||
match self.inner.next() {
|
||||
Some((close, &ASCII_CLOSED_BRACE)) => {
|
||||
break Some(Token::Argument(&self.input[open + 1..close]));
|
||||
}
|
||||
None => {
|
||||
break None;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
},
|
||||
// Literal token is starting. Read until we find '{' or the end of string, and return
|
||||
// the token. Use `peek()` for matching the opening brace, se we can keep it
|
||||
// in the iterator for the above code.
|
||||
Some((start, _)) => loop {
|
||||
match self.inner.peek() {
|
||||
Some(&(open, &ASCII_OPEN_BRACE)) => {
|
||||
break Some(Token::Literal(&self.input[start..open]));
|
||||
}
|
||||
None => {
|
||||
break Some(Token::Literal(&self.input[start..]));
|
||||
}
|
||||
_ => {
|
||||
self.inner.next();
|
||||
}
|
||||
}
|
||||
},
|
||||
None => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Eq)]
|
||||
pub enum Op<'a> {
|
||||
/// Render text with current color and font.
|
||||
@ -613,35 +385,3 @@ impl Span {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn tokenizer_yields_expected_tokens() {
|
||||
use std::array::IntoIter;
|
||||
|
||||
assert!(Tokenizer::new(b"").eq(IntoIter::new([])));
|
||||
assert!(Tokenizer::new(b"x").eq(IntoIter::new([Token::Literal(b"x")])));
|
||||
assert!(Tokenizer::new(b"x\0y").eq(IntoIter::new([Token::Literal("x\0y".as_bytes())])));
|
||||
assert!(Tokenizer::new(b"{").eq(IntoIter::new([])));
|
||||
assert!(Tokenizer::new(b"x{").eq(IntoIter::new([Token::Literal(b"x")])));
|
||||
assert!(Tokenizer::new(b"x{y").eq(IntoIter::new([Token::Literal(b"x")])));
|
||||
assert!(Tokenizer::new(b"{}").eq(IntoIter::new([Token::Argument(b"")])));
|
||||
assert!(Tokenizer::new(b"x{}y{").eq(IntoIter::new([
|
||||
Token::Literal(b"x"),
|
||||
Token::Argument(b""),
|
||||
Token::Literal(b"y"),
|
||||
])));
|
||||
assert!(Tokenizer::new(b"{\0}").eq(IntoIter::new([Token::Argument("\0".as_bytes()),])));
|
||||
assert!(Tokenizer::new(b"{{y}").eq(IntoIter::new([Token::Argument(b"{y"),])));
|
||||
assert!(Tokenizer::new(b"{{{{xyz").eq(IntoIter::new([])));
|
||||
assert!(Tokenizer::new(b"x{}{{}}}}").eq(IntoIter::new([
|
||||
Token::Literal(b"x"),
|
||||
Token::Argument(b""),
|
||||
Token::Argument(b"{"),
|
||||
Token::Literal(b"}}}"),
|
||||
])));
|
||||
}
|
||||
}
|
2
core/embed/rust/src/ui/component/text/mod.rs
Normal file
2
core/embed/rust/src/ui/component/text/mod.rs
Normal file
@ -0,0 +1,2 @@
|
||||
pub mod formatted;
|
||||
pub mod layout;
|
@ -4,7 +4,7 @@ use crate::{
|
||||
error::Error,
|
||||
micropython::{buffer::Buffer, map::Map, obj::Obj, qstr::Qstr},
|
||||
ui::{
|
||||
component::{Child, Text},
|
||||
component::{Child, FormattedText},
|
||||
display,
|
||||
layout::obj::LayoutObj,
|
||||
},
|
||||
@ -64,7 +64,7 @@ extern "C" fn ui_layout_new_confirm_action(
|
||||
let obj = LayoutObj::new(Child::new(Dialog::new(
|
||||
display::screen(),
|
||||
|area| {
|
||||
Text::new::<theme::T1DefaultText>(area, format)
|
||||
FormattedText::new::<theme::T1DefaultText>(area, format)
|
||||
.with(b"action", action.unwrap_or("".into()))
|
||||
.with(b"description", description.unwrap_or("".into()))
|
||||
},
|
||||
@ -125,7 +125,7 @@ mod tests {
|
||||
let layout = Child::new(Dialog::new(
|
||||
display::screen(),
|
||||
|area| {
|
||||
Text::new::<theme::T1DefaultText>(
|
||||
FormattedText::new::<theme::T1DefaultText>(
|
||||
area,
|
||||
"Testing text layout, with some text, and some more text. And {param}",
|
||||
)
|
||||
|
@ -1,5 +1,5 @@
|
||||
use crate::ui::{
|
||||
component::text::DefaultTextTheme,
|
||||
component::text::layout::DefaultTextTheme,
|
||||
display::{Color, Font},
|
||||
};
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
use crate::ui::{
|
||||
component::{label::LabelStyle, text::DefaultTextTheme},
|
||||
component::{label::LabelStyle, text::layout::DefaultTextTheme},
|
||||
display::{Color, Font},
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user