ferroui_controls/documents/
inline.rs1use super::{TextElement, TextElementImpl};
2use crate::Control;
3use ferroui_base::media::text_formatting::{GenericTextRunProperties, TextRun, TextRunProperties};
4use ferroui_base::media::{BaselineAlignment, IBrush, TextDecorationCollection, Typeface};
5use ferroui_base::{
6 ferro_class, ferro_property, AttachedProperty, FerroObjectImpl, FerroObjectImplExt, FerroProperty,
7 FerroPropertyChangedEventArgs, Size, StyledElementImpl, StyledProperty, StyledPropertyOptions,
8};
9use std::rc::Rc;
10
11#[repr(C)]
15pub struct Inline {
16 base: TextElement,
17}
18
19ferro_class! {
20 Inline: TextElement, virtuals InlineImpl: TextElementImpl {
21 #[doc(hidden)]
23 fn build_text_run(this, text_runs: &mut Vec<Rc<dyn TextRun>>);
24 #[doc(hidden)]
27 fn measure_embedded_controls(this, block_size: Size) -> bool;
28 #[doc(hidden)]
30 fn append_text(this, string_builder: &mut String);
31 }
32}
33
34ferroui_base::ferro_impl_classes!(Inline: StyledElementImpl);
35ferroui_base::ferro_impl_classes!(Inline: TextElementImpl);
36
37impl FerroObjectImpl for Inline {
38 fn on_property_changed(this: &Self, change: &FerroPropertyChangedEventArgs<'_>) {
39 Self::parent_on_property_changed(this, change);
40
41 match change.property().name() {
42 "TextDecorations" | "BaselineAlignment" => {
43 if let Some(host) = this.inline_host() {
44 host.invalidate();
45 }
46 }
47 _ => {}
48 }
49 }
50}
51
52impl InlineImpl for Inline {
53 fn build_text_run(_this: &Self, _text_runs: &mut Vec<Rc<dyn TextRun>>) {
54 panic!("Inline is abstract.")
55 }
56
57 fn measure_embedded_controls(_this: &Self, _block_size: Size) -> bool {
58 false
59 }
60
61 fn append_text(_this: &Self, _string_builder: &mut String) {
62 panic!("Inline is abstract.")
63 }
64}
65
66ferroui_base::ferro_properties! { impl Inline {
67 ferro_property!(
68 pub fn text_decorations_property() -> AttachedProperty<Option<TextDecorationCollection>> {
70 FerroProperty::register_attached_with::<Inline, Inline, _>(
71 "TextDecorations",
72 StyledPropertyOptions::new(None).inherits(true),
73 )
74 }
75 );
76
77 ferro_property!(
78 pub fn baseline_alignment_property() -> StyledProperty<BaselineAlignment> {
80 FerroProperty::register::<Inline, _>("BaselineAlignment", BaselineAlignment::Baseline)
81 }
82 );
83} }
84
85impl Inline {
86 pub fn construct() -> Self {
88 Self { base: TextElement::construct() }
89 }
90
91 pub fn text_decorations(&self) -> Option<TextDecorationCollection> {
94 self.get_value(Self::text_decorations_property())
95 }
96
97 pub fn set_text_decorations(&self, value: Option<TextDecorationCollection>) {
98 self.set_value(Self::text_decorations_property(), value)
99 }
100
101 pub fn baseline_alignment(&self) -> BaselineAlignment {
104 self.get_value(Self::baseline_alignment_property())
105 }
106
107 pub fn set_baseline_alignment(&self, value: BaselineAlignment) {
108 self.set_value(Self::baseline_alignment_property(), value)
109 }
110
111 pub fn get_text_decorations(control: &Control) -> Option<TextDecorationCollection> {
114 control.get_value(Self::text_decorations_property())
115 }
116
117 pub fn set_text_decorations_on(control: &Control, value: Option<TextDecorationCollection>) {
120 control.set_value(Self::text_decorations_property(), value)
121 }
122
123 pub fn create_text_run_properties(&self) -> Rc<dyn TextRunProperties> {
125 let parent_or_self_background = self.background().or_else(|| self.find_parent_background());
126
127 let typeface =
128 Typeface::with_style(self.font_family(), self.font_style(), self.font_weight(), self.font_stretch());
129
130 Rc::new(GenericTextRunProperties::with_all(
131 typeface,
132 self.font_size(),
133 self.text_decorations(),
134 self.foreground(),
135 parent_or_self_background,
136 self.baseline_alignment(),
137 None,
138 self.font_features(),
139 ))
140 }
141
142 fn find_parent_background(&self) -> Option<Rc<dyn IBrush>> {
143 let mut parent = self.parent();
144
145 while let Some(inline) = parent.and_then(|parent| parent.cast::<Inline>()) {
146 if let Some(background) = inline.background() {
147 return Some(background);
148 }
149
150 parent = inline.parent();
151 }
152
153 None
154 }
155}