From c29128592795f48493ef9129b9a175c5aa29f5fd Mon Sep 17 00:00:00 2001 From: grdddj Date: Thu, 4 May 2023 16:09:31 +0200 Subject: [PATCH] chore(core/rust): make TextBox common component --- .../rust/src/ui/component/text/common.rs | 105 ++++++++++++++++++ core/embed/rust/src/ui/component/text/mod.rs | 2 +- .../ui/model_tt/component/keyboard/common.rs | 96 +--------------- 3 files changed, 107 insertions(+), 96 deletions(-) create mode 100644 core/embed/rust/src/ui/component/text/common.rs diff --git a/core/embed/rust/src/ui/component/text/common.rs b/core/embed/rust/src/ui/component/text/common.rs new file mode 100644 index 0000000000..4e35cdb719 --- /dev/null +++ b/core/embed/rust/src/ui/component/text/common.rs @@ -0,0 +1,105 @@ +use crate::ui::{component::EventCtx, util::ResultExt}; +use heapless::String; + +/// Reified editing operations of `TextBox`. +/// +/// Note: This does not contain all supported editing operations, only the ones +/// we currently use. +pub enum TextEdit { + ReplaceLast(char), + Append(char), +} + +/// Wraps a character buffer of maximum length `L` and provides text editing +/// operations over it. Text ops usually take a `EventCtx` to request a paint +/// pass in case of any state modification. +pub struct TextBox { + text: String, +} + +impl TextBox { + /// Create a new `TextBox` with content `text`. + pub fn new(text: String) -> Self { + Self { text } + } + + /// Create an empty `TextBox`. + pub fn empty() -> Self { + Self::new(String::new()) + } + + pub fn content(&self) -> &str { + &self.text + } + + pub fn len(&self) -> usize { + self.text.len() + } + + pub fn is_empty(&self) -> bool { + self.text.is_empty() + } + + pub fn is_full(&self) -> bool { + self.text.len() == self.text.capacity() + } + + /// Delete the last character of content, if any. + pub fn delete_last(&mut self, ctx: &mut EventCtx) { + let changed = self.text.pop().is_some(); + if changed { + ctx.request_paint(); + } + } + + /// Replaces the last character of the content with `ch`. If the content is + /// empty, `ch` is appended. + pub fn replace_last(&mut self, ctx: &mut EventCtx, ch: char) { + let previous = self.text.pop(); + self.text + .push(ch) + .assert_if_debugging_ui("TextBox has zero capacity"); + let changed = previous != Some(ch); + if changed { + ctx.request_paint(); + } + } + + /// Append `ch` at the end of the content. + pub fn append(&mut self, ctx: &mut EventCtx, ch: char) { + self.text.push(ch).assert_if_debugging_ui("TextBox is full"); + ctx.request_paint(); + } + + /// Append `slice` at the end of the content. + pub fn append_slice(&mut self, ctx: &mut EventCtx, slice: &str) { + self.text + .push_str(slice) + .assert_if_debugging_ui("TextBox is full"); + ctx.request_paint(); + } + + /// Replace the textbox content with `text`. + pub fn replace(&mut self, ctx: &mut EventCtx, text: &str) { + if self.text != text { + self.text.clear(); + self.text + .push_str(text) + .assert_if_debugging_ui("TextBox is full"); + ctx.request_paint(); + } + } + + /// Clear the textbox content. + pub fn clear(&mut self, ctx: &mut EventCtx) { + self.replace(ctx, ""); + } + + /// Apply a editing operation to the text buffer. + pub fn apply(&mut self, ctx: &mut EventCtx, edit: TextEdit) { + match edit { + TextEdit::ReplaceLast(char) => self.replace_last(ctx, char), + TextEdit::Append(char) => self.append(ctx, char), + } + } +} diff --git a/core/embed/rust/src/ui/component/text/mod.rs b/core/embed/rust/src/ui/component/text/mod.rs index 517840e64f..6cec1a6802 100644 --- a/core/embed/rust/src/ui/component/text/mod.rs +++ b/core/embed/rust/src/ui/component/text/mod.rs @@ -1,5 +1,5 @@ +pub mod common; pub mod formatted; -mod iter; pub mod layout; pub mod paragraphs; diff --git a/core/embed/rust/src/ui/model_tt/component/keyboard/common.rs b/core/embed/rust/src/ui/model_tt/component/keyboard/common.rs index 8b1ecee709..0220ad4f79 100644 --- a/core/embed/rust/src/ui/model_tt/component/keyboard/common.rs +++ b/core/embed/rust/src/ui/model_tt/component/keyboard/common.rs @@ -1,12 +1,9 @@ -use heapless::String; - use crate::{ time::Duration, ui::{ - component::{Event, EventCtx, TimerToken}, + component::{text::common::TextEdit, Event, EventCtx, TimerToken}, display::{self, Color, Font}, geometry::{Offset, Point, Rect}, - util::ResultExt, }, }; @@ -116,97 +113,6 @@ impl MultiTapKeyboard { } } -/// Reified editing operations of `TextBox`. -/// -/// Note: This does not contain all supported editing operations, only the ones -/// we currently use. -pub enum TextEdit { - ReplaceLast(char), - Append(char), -} - -/// Wraps a character buffer of maximum length `L` and provides text editing -/// operations over it. Text ops usually take a `EventCtx` to request a paint -/// pass in case of any state modification. -pub struct TextBox { - text: String, -} - -impl TextBox { - /// Create a new `TextBox` with content `text`. - pub fn new(text: String) -> Self { - Self { text } - } - - /// Create an empty `TextBox`. - pub fn empty() -> Self { - Self::new(String::new()) - } - - pub fn content(&self) -> &str { - &self.text - } - - pub fn is_empty(&self) -> bool { - self.text.is_empty() - } - - pub fn is_full(&self) -> bool { - self.text.len() == self.text.capacity() - } - - /// Delete the last character of content, if any. - pub fn delete_last(&mut self, ctx: &mut EventCtx) { - let changed = self.text.pop().is_some(); - if changed { - ctx.request_paint(); - } - } - - /// Replaces the last character of the content with `ch`. If the content is - /// empty, `ch` is appended. - pub fn replace_last(&mut self, ctx: &mut EventCtx, ch: char) { - let previous = self.text.pop(); - self.text - .push(ch) - .assert_if_debugging_ui("TextBox has zero capacity"); - let changed = previous != Some(ch); - if changed { - ctx.request_paint(); - } - } - - /// Append `ch` at the end of the content. - pub fn append(&mut self, ctx: &mut EventCtx, ch: char) { - self.text.push(ch).assert_if_debugging_ui("TextBox is full"); - ctx.request_paint(); - } - - /// Replace the textbox content with `text`. - pub fn replace(&mut self, ctx: &mut EventCtx, text: &str) { - if self.text != text { - self.text.clear(); - self.text - .push_str(text) - .assert_if_debugging_ui("TextBox is full"); - ctx.request_paint(); - } - } - - /// Clear the textbox content. - pub fn clear(&mut self, ctx: &mut EventCtx) { - self.replace(ctx, ""); - } - - /// Apply a editing operation to the text buffer. - pub fn apply(&mut self, ctx: &mut EventCtx, edit: TextEdit) { - match edit { - TextEdit::ReplaceLast(char) => self.replace_last(ctx, char), - TextEdit::Append(char) => self.append(ctx, char), - } - } -} - /// Create a visible "underscoring" of the last letter of a text. pub fn paint_pending_marker(text_baseline: Point, text: &str, font: Font, color: Color) { // Measure the width of the last character of input.