Skip to main content

cranpose_ui/
ui_text.rs

1use crate::{
2    SharedText,
3    localization::{DeferredMessage, localized_message},
4};
5
6/// UI text that can retain either literal content or a deferred translation.
7/// Deferred text resolves during composition and follows the nearest language provider.
8#[derive(Clone, Debug, Default, PartialEq)]
9pub enum UiText {
10    /// No text.
11    #[default]
12    Empty,
13    /// Literal content, such as an external error or a user-provided document title.
14    Text(SharedText),
15    /// A translation request whose arguments have already been captured.
16    Message(DeferredMessage),
17}
18
19impl UiText {
20    /// Resolves the current text during composition.
21    #[track_caller]
22    pub fn resolve(&self) -> SharedText {
23        match self {
24            Self::Empty => "".into(),
25            Self::Text(text) => text.clone(),
26            Self::Message(message) => localized_message(message),
27        }
28    }
29
30    /// Whether no content is present, without formatting a deferred request.
31    pub fn is_empty(&self) -> bool {
32        matches!(self, Self::Empty) || matches!(self, Self::Text(text) if text.is_empty())
33    }
34
35    /// Removes the text and releases any retained message arguments.
36    pub fn clear(&mut self) {
37        *self = Self::Empty;
38    }
39}
40
41impl From<DeferredMessage> for UiText {
42    fn from(message: DeferredMessage) -> Self {
43        Self::Message(message)
44    }
45}
46
47impl From<SharedText> for UiText {
48    fn from(text: SharedText) -> Self {
49        Self::Text(text)
50    }
51}
52
53impl From<String> for UiText {
54    fn from(text: String) -> Self {
55        Self::Text(text.into())
56    }
57}
58
59impl From<&'static str> for UiText {
60    fn from(text: &'static str) -> Self {
61        Self::Text(text.into())
62    }
63}
64
65impl std::fmt::Display for UiText {
66    fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
67        match self {
68            Self::Empty => Ok(()),
69            Self::Text(text) => formatter.write_str(text.as_str()),
70            Self::Message(message) => formatter.write_str(&message.fallback_text()),
71        }
72    }
73}
74
75impl crate::widgets::text::IntoTextSource for UiText {
76    #[track_caller]
77    fn into_text_source(self) -> crate::widgets::text::TextSource {
78        self.resolve().into_text_source()
79    }
80}