Update scroll offsets for text inputs to ensure cursor visibility.
(&mut self)
| 6277 | |
| 6278 | /// Update scroll offsets for text inputs to ensure cursor visibility. |
| 6279 | pub fn update_text_input_scroll(&mut self) { |
| 6280 | let focused = self.focused_element_id; |
| 6281 | if focused == 0 { |
| 6282 | return; |
| 6283 | } |
| 6284 | // Get bounding box for the focused text input |
| 6285 | let (visible_width, visible_height) = self.layout_element_map |
| 6286 | .get(&focused) |
| 6287 | .map(|item| (item.bounding_box.width, item.bounding_box.height)) |
| 6288 | .unwrap_or((0.0, 0.0)); |
| 6289 | if visible_width <= 0.0 { |
| 6290 | return; |
| 6291 | } |
| 6292 | |
| 6293 | // Get cursor x-position |
| 6294 | if let Some(state) = self.text_edit_states.get(&focused) { |
| 6295 | let config_idx = self.text_input_element_ids.iter() |
| 6296 | .position(|&id| id == focused); |
| 6297 | if let Some(idx) = config_idx { |
| 6298 | if let Some(cfg) = self.text_input_configs.get(idx) { |
| 6299 | if let Some(ref measure_fn) = self.measure_text_fn { |
| 6300 | let disp_text = crate::text_input::display_text( |
| 6301 | &state.text, |
| 6302 | &cfg.placeholder, |
| 6303 | cfg.is_password && !cfg.is_multiline, |
| 6304 | ); |
| 6305 | if !state.text.is_empty() { |
| 6306 | if cfg.is_multiline { |
| 6307 | // Multiline: use visual lines with word wrapping |
| 6308 | let visual_lines = crate::text_input::wrap_lines( |
| 6309 | &disp_text, |
| 6310 | visible_width, |
| 6311 | cfg.font_asset, |
| 6312 | cfg.font_size, |
| 6313 | measure_fn.as_ref(), |
| 6314 | ); |
| 6315 | #[cfg(feature = "text-styling")] |
| 6316 | let raw_cursor = state.cursor_pos_raw(); |
| 6317 | #[cfg(not(feature = "text-styling"))] |
| 6318 | let raw_cursor = state.cursor_pos; |
| 6319 | let (cursor_line, cursor_col) = crate::text_input::cursor_to_visual_pos(&visual_lines, raw_cursor); |
| 6320 | let vl_text = visual_lines.get(cursor_line).map(|vl| vl.text.as_str()).unwrap_or(""); |
| 6321 | let line_positions = crate::text_input::compute_char_x_positions( |
| 6322 | vl_text, |
| 6323 | cfg.font_asset, |
| 6324 | cfg.font_size, |
| 6325 | measure_fn.as_ref(), |
| 6326 | ); |
| 6327 | let cursor_x = line_positions.get(cursor_col).copied().unwrap_or(0.0); |
| 6328 | let cfg_font_asset = cfg.font_asset; |
| 6329 | let cfg_font_size = cfg.font_size; |
| 6330 | let cfg_line_height_val = cfg.line_height; |
| 6331 | let natural_height = self.font_height(cfg_font_asset, cfg_font_size); |
| 6332 | let line_height = if cfg_line_height_val > 0 { cfg_line_height_val as f32 } else { natural_height }; |
| 6333 | if let Some(state_mut) = self.text_edit_states.get_mut(&focused) { |
| 6334 | state_mut.ensure_cursor_visible(cursor_x, visible_width); |
| 6335 | state_mut.ensure_cursor_visible_vertical(cursor_line, line_height, visible_height); |
| 6336 | } |
no test coverage detected