StratoSDK is a framework with a declarative approach similar to Flutter/React, written and designed entirely for Rust.
| 1 | use pathfinder_geometry::{ |
| 2 | rect::RectF, |
| 3 | vector::{vec2f, Vector2F}, |
| 4 | }; |
| 5 | |
| 6 | /// Parameters for creating a visual tick mark that indicates a newline in text selection. |
| 7 | /// |
| 8 | /// Used to render small rectangular indicators at line endings when text selections |
| 9 | /// extend beyond the end of a line. |
| 10 | pub struct NewlineTickParams { |
| 11 | /// The top-left corner position where the tick should be drawn |
| 12 | pub tick_origin: Vector2F, |
| 13 | /// The width of the tick mark in pixels |
| 14 | pub tick_width: f32, |
| 15 | /// The height of the tick mark in pixels |
| 16 | pub tick_height: f32, |
| 17 | } |
| 18 | |
| 19 | /// Creates a rectangle for rendering a newline tick mark in text selection. |
| 20 | /// |
| 21 | /// The tick mark provides a visual indicator when a text selection extends beyond |
| 22 | /// the end of a line, helping users understand that the selection continues to the |
| 23 | /// next line. |
| 24 | pub fn create_newline_tick_rect(params: NewlineTickParams) -> RectF { |
| 25 | RectF::new( |
| 26 | params.tick_origin, |
| 27 | vec2f(params.tick_width, params.tick_height), |
| 28 | ) |
| 29 | } |
| 30 | |
| 31 | /// Calculates the appropriate width for a newline tick mark based on font size. |
| 32 | /// |
| 33 | /// Returns a width that scales proportionally with the font size to ensure the |
| 34 | /// tick mark remains visible and appropriately sized across different text scales. |
| 35 | pub fn calculate_tick_width(font_size: f32) -> f32 { |
| 36 | font_size / 2.0 |
| 37 | } |
| 38 | |
| 39 | /// Determines if a text selection crosses a newline using row-based coordinates. |
| 40 | /// |
| 41 | /// This function checks whether a selection that intersects with the current row |
| 42 | /// extends beyond the end of that row, indicating that a newline tick should be |
| 43 | /// displayed. Returns `false` for the last line since there's no newline after it. |
| 44 | pub fn selection_crosses_newline_row_based( |
| 45 | current_row: usize, |
| 46 | is_last_line: bool, |
| 47 | selection_start_row: usize, |
| 48 | selection_end_row: usize, |
| 49 | selection_end_column: usize, |
| 50 | line_end_index: usize, |
| 51 | ) -> bool { |
| 52 | if is_last_line { |
| 53 | return false; |
| 54 | } |
| 55 | |
| 56 | let selection_starts_before_or_at_line = selection_start_row <= current_row; |
| 57 | |
| 58 | let selection_ends_beyond_line = current_row < selection_end_row |
| 59 | || (current_row == selection_end_row && selection_end_column >= line_end_index); |
| 60 | |
| 61 | selection_starts_before_or_at_line && selection_ends_beyond_line |
| 62 | } |
| 63 | |
| 64 | /// Determines if a text selection crosses a newline using character offset coordinates. |
| 65 | /// |
| 66 | /// This function checks whether a selection intersects with a line and extends beyond |
| 67 | /// the end of that line, indicating that a newline tick should be displayed. Uses |
| 68 | /// absolute character positions rather than row/column coordinates. Returns `false` |
| 69 | /// for the last line since there's no newline after it. |
| 70 | pub fn selection_crosses_newline_offset_based( |
| 71 | is_last_line: bool, |
| 72 | selection_start: usize, |
| 73 | selection_end: usize, |
| 74 | line_start_offset: usize, |
| 75 | line_end_offset: usize, |
| 76 | ) -> bool { |
| 77 | if is_last_line { |
| 78 | return false; |
| 79 | } |
| 80 | |
| 81 | let selection_intersects_line = |
| 82 | selection_end > line_start_offset && selection_start <= line_end_offset; |
| 83 | |
| 84 | let selection_extends_beyond_line = selection_end > line_end_offset; |
| 85 | |
| 86 | selection_intersects_line && selection_extends_beyond_line |
| 87 | } |
| 88 |