Build visual lines with wrap. Returns the lines and uses `style` for the text content.
(&self, inner_width: u16, style: &TextInputStyle)
| 310 | |
| 311 | /// Build visual lines with wrap. Returns the lines and uses `style` for the text content. |
| 312 | fn build_visual_lines(&self, inner_width: u16, style: &TextInputStyle) -> Vec<Line<'static>> { |
| 313 | let prefix_w = style.prefix_display_width(); |
| 314 | let avail = Self::avail_width(inner_width, prefix_w); |
| 315 | let mut visual_lines: Vec<Line<'static>> = Vec::new(); |
| 316 | |
| 317 | for (i, logical_line) in self.input.split('\n').enumerate() { |
| 318 | let prefix = if i == 0 { |
| 319 | style.first_line_prefix |
| 320 | } else { |
| 321 | style.continuation_prefix |
| 322 | }; |
| 323 | if logical_line.is_empty() { |
| 324 | visual_lines.push(Line::from(vec![Span::raw(prefix.to_string())])); |
| 325 | } else { |
| 326 | let mut chars = logical_line.chars().peekable(); |
| 327 | let mut first_segment = true; |
| 328 | while chars.peek().is_some() { |
| 329 | let seg_prefix = if first_segment { |
| 330 | prefix |
| 331 | } else { |
| 332 | style.continuation_prefix |
| 333 | }; |
| 334 | let mut segment = String::new(); |
| 335 | let mut seg_w = 0usize; |
| 336 | while let Some(&ch) = chars.peek() { |
| 337 | let ch_w = UnicodeWidthChar::width(ch).unwrap_or(0); |
| 338 | if seg_w + ch_w > avail && seg_w > 0 { |
| 339 | break; |
| 340 | } |
| 341 | segment.push(ch); |
| 342 | seg_w += ch_w; |
| 343 | chars.next(); |
| 344 | } |
| 345 | visual_lines.push(Line::from(vec![ |
| 346 | Span::raw(seg_prefix.to_string()), |
| 347 | Span::styled(segment, style.text_style), |
| 348 | ])); |
| 349 | first_segment = false; |
| 350 | } |
| 351 | } |
| 352 | } |
| 353 | |
| 354 | visual_lines |
| 355 | } |
| 356 | |
| 357 | /// Render the text input content into the given inner area (no block/border). |
| 358 | /// Sets cursor position on frame. Pass `show_cursor = false` to skip cursor. |