dear_imgui_rs/widget/
text.rs1use crate::Ui;
18use crate::style::StyleColor;
19use crate::sys;
20
21impl Ui {
22 #[doc(alias = "CalcTextSize")]
27 pub fn calc_text_size(&self, text: impl AsRef<str>) -> [f32; 2] {
28 self.calc_text_size_with_opts(text, false, -1.0)
29 }
30
31 #[doc(alias = "CalcTextSize")]
41 pub fn calc_text_size_with_opts(
42 &self,
43 text: impl AsRef<str>,
44 hide_text_after_double_hash: bool,
45 wrap_width: f32,
46 ) -> [f32; 2] {
47 Self::assert_finite_f32("Ui::calc_text_size_with_opts()", "wrap_width", wrap_width);
48 let text = text.as_ref();
49
50 self.run_with_bound_context(|| unsafe {
51 self.calc_text_size_bound(text, hide_text_after_double_hash, wrap_width)
52 })
53 }
54
55 pub(crate) unsafe fn calc_text_size_bound(
62 &self,
63 text: &str,
64 hide_text_after_double_hash: bool,
65 wrap_width: f32,
66 ) -> [f32; 2] {
67 let text_range = self.scratch_txt_range(text);
68 let size = unsafe {
69 sys::igCalcTextSize(
70 text_range.start,
71 text_range.end,
72 hide_text_after_double_hash,
73 wrap_width,
74 )
75 };
76 [size.x, size.y]
77 }
78
79 #[doc(alias = "TextColored")]
93 pub fn text_colored(&self, color: [f32; 4], text: impl AsRef<str>) {
94 let s = text.as_ref();
95
96 let _token = self.push_style_color(StyleColor::Text, color);
98
99 self.run_with_bound_context(|| unsafe {
101 let begin = s.as_ptr() as *const std::os::raw::c_char;
102 let end = begin.add(s.len());
103 sys::igTextEx(begin, end, 0); })
105 }
106
107 #[doc(alias = "TextDisabled")]
120 pub fn text_disabled(&self, text: impl AsRef<str>) {
121 let s = text.as_ref();
122
123 let disabled_color = self.style_color(StyleColor::TextDisabled);
125
126 let _token = self.push_style_color(StyleColor::Text, disabled_color);
128
129 self.run_with_bound_context(|| unsafe {
131 let begin = s.as_ptr() as *const std::os::raw::c_char;
132 let end = begin.add(s.len());
133 sys::igTextEx(begin, end, 0); })
135 }
136
137 #[doc(alias = "TextWrapped")]
142 pub fn text_wrapped(&self, text: impl AsRef<str>) {
143 let s = text.as_ref();
144 let _wrap = self.push_text_wrap_pos(0.0);
145 self.run_with_bound_context(|| unsafe {
146 let begin = s.as_ptr() as *const std::os::raw::c_char;
147 let end = begin.add(s.len());
148 sys::igTextUnformatted(begin, end);
149 })
150 }
151
152 #[doc(alias = "LabelText")]
154 pub fn label_text(&self, label: impl AsRef<str>, text: impl AsRef<str>) {
155 let (label_ptr, text_ptr) = self.scratch_txt_two(label, text);
156 self.run_with_bound_context(|| unsafe {
157 const FMT: &[u8; 3] = b"%s\0";
159 sys::igLabelText(
160 label_ptr,
161 FMT.as_ptr() as *const std::os::raw::c_char,
162 text_ptr,
163 );
164 })
165 }
166
167 #[doc(alias = "TextLink")]
169 pub fn text_link(&self, label: impl AsRef<str>) -> bool {
170 self.run_with_bound_context(|| unsafe { sys::igTextLink(self.scratch_txt(label)) })
171 }
172
173 #[doc(alias = "TextLinkOpenURL")]
176 pub fn text_link_open_url(&self, label: impl AsRef<str>, url: impl AsRef<str>) -> bool {
177 let (label_ptr, url_ptr) = self.scratch_txt_two(label, url);
178 self.run_with_bound_context(|| unsafe { sys::igTextLinkOpenURL(label_ptr, url_ptr) })
179 }
180}
181
182#[cfg(test)]
183mod tests {
184 fn setup_context() -> crate::Context {
185 let mut ctx = crate::Context::create();
186 ctx.io_mut().set_display_size([128.0, 128.0]);
187 ctx.io_mut().set_delta_time(1.0 / 60.0);
188 ctx.font_atlas()
189 .try_claim_legacy_renderer()
190 .expect("legacy renderer font atlas should be available")
191 .build();
192 ctx
193 }
194
195 #[test]
196 fn calc_text_size_supports_default_and_advanced_options() {
197 let mut ctx = setup_context();
198 let ui = ctx.frame();
199
200 let default_size = ui.calc_text_size("Column##sort_key");
201 let explicit_default = ui.calc_text_size_with_opts("Column##sort_key", false, -1.0);
202 let visible_label = ui.calc_text_size_with_opts("Column##sort_key", true, -1.0);
203 let trailing_hash = ui.calc_text_size_with_opts("Column#", true, -1.0);
204
205 assert_eq!(default_size, explicit_default);
206 assert!(visible_label[0] < default_size[0]);
207 assert_eq!(visible_label[1], default_size[1]);
208 assert_eq!(trailing_hash, ui.calc_text_size("Column#"));
209
210 let unwrapped = ui.calc_text_size("one two three four");
211 let wrapped = ui.calc_text_size_with_opts("one two three four", false, unwrapped[0] / 2.0);
212 assert!(wrapped[0] < unwrapped[0]);
213 assert!(wrapped[1] > unwrapped[1]);
214
215 for wrap_width in [f32::NAN, f32::INFINITY, f32::NEG_INFINITY] {
216 assert!(
217 std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {
218 let _ = ui.calc_text_size_with_opts("text", false, wrap_width);
219 }))
220 .is_err()
221 );
222 }
223 }
224}