Clamp text input scroll offsets to valid ranges. For multiline: clamp scroll_offset_y to [0, total_height - visible_height]. For single-line: clamp scroll_offset to [0, total_width - visible_width].
(&mut self)
| 6756 | /// For multiline: clamp scroll_offset_y to [0, total_height - visible_height]. |
| 6757 | /// For single-line: clamp scroll_offset to [0, total_width - visible_width]. |
| 6758 | pub fn clamp_text_input_scroll(&mut self) { |
| 6759 | for i in 0..self.text_input_element_ids.len() { |
| 6760 | let elem_id = self.text_input_element_ids[i]; |
| 6761 | let cfg = match self.text_input_configs.get(i) { |
| 6762 | Some(c) => c, |
| 6763 | None => continue, |
| 6764 | }; |
| 6765 | |
| 6766 | let font_asset = cfg.font_asset; |
| 6767 | let font_size = cfg.font_size; |
| 6768 | let cfg_line_height = cfg.line_height; |
| 6769 | let is_multiline = cfg.is_multiline; |
| 6770 | let is_password = cfg.is_password; |
| 6771 | |
| 6772 | let (visible_width, visible_height) = self.layout_element_map.get(&elem_id) |
| 6773 | .map(|item| (item.bounding_box.width, item.bounding_box.height)) |
| 6774 | .unwrap_or((200.0, 0.0)); |
| 6775 | |
| 6776 | let text_empty = self.text_edit_states.get(&elem_id) |
| 6777 | .map(|s| s.text.is_empty()) |
| 6778 | .unwrap_or(true); |
| 6779 | |
| 6780 | if text_empty { |
| 6781 | if let Some(state_mut) = self.text_edit_states.get_mut(&elem_id) { |
| 6782 | state_mut.scroll_offset = 0.0; |
| 6783 | state_mut.scroll_offset_y = 0.0; |
| 6784 | } |
| 6785 | continue; |
| 6786 | } |
| 6787 | |
| 6788 | if let Some(ref measure_fn) = self.measure_text_fn { |
| 6789 | let disp_text = self.text_edit_states.get(&elem_id) |
| 6790 | .map(|s| crate::text_input::display_text(&s.text, "", is_password && !is_multiline)) |
| 6791 | .unwrap_or_default(); |
| 6792 | |
| 6793 | if is_multiline { |
| 6794 | let visual_lines = crate::text_input::wrap_lines( |
| 6795 | &disp_text, |
| 6796 | visible_width, |
| 6797 | font_asset, |
| 6798 | font_size, |
| 6799 | measure_fn.as_ref(), |
| 6800 | ); |
| 6801 | let natural_height = self.font_height(font_asset, font_size); |
| 6802 | let font_height = if cfg_line_height > 0 { cfg_line_height as f32 } else { natural_height }; |
| 6803 | let total_height = visual_lines.len() as f32 * font_height; |
| 6804 | let max_scroll = (total_height - visible_height).max(0.0); |
| 6805 | if let Some(state_mut) = self.text_edit_states.get_mut(&elem_id) { |
| 6806 | if state_mut.scroll_offset_y > max_scroll { |
| 6807 | state_mut.scroll_offset_y = max_scroll; |
| 6808 | } |
| 6809 | } |
| 6810 | } else { |
| 6811 | // Single-line: clamp horizontal scroll |
| 6812 | let char_x_positions = crate::text_input::compute_char_x_positions( |
| 6813 | &disp_text, |
| 6814 | font_asset, |
| 6815 | font_size, |
no test coverage detected