egui/text_selection/
visuals.rs1use crate::*;
2
3use self::layers::ShapeIdx;
4
5use super::CursorRange;
6
7pub fn paint_text_selection(
8 painter: &Painter,
9 visuals: &Visuals,
10 galley_pos: Pos2,
11 galley: &Galley,
12 cursor_range: &CursorRange,
13 mut out_shaped_idx: Option<&mut Vec<ShapeIdx>>,
14) {
15 if cursor_range.is_empty() {
16 return;
17 }
18
19 let color = visuals.selection.bg_fill.linear_multiply(0.5);
21 let [min, max] = cursor_range.sorted_cursors();
22 let min = min.rcursor;
23 let max = max.rcursor;
24
25 for ri in min.row..=max.row {
26 let row = &galley.rows[ri];
27 let left = if ri == min.row {
28 row.x_offset(min.column)
29 } else {
30 row.rect.left()
31 };
32 let right = if ri == max.row {
33 row.x_offset(max.column)
34 } else {
35 let newline_size = if row.ends_with_newline {
36 row.height() / 2.0 } else {
38 0.0
39 };
40 row.rect.right() + newline_size
41 };
42 let rect = Rect::from_min_max(
43 galley_pos + vec2(left, row.min_y()),
44 galley_pos + vec2(right, row.max_y()),
45 );
46 let shape_idx = painter.rect_filled(rect, 0.0, color);
47 if let Some(out_shaped_idx) = &mut out_shaped_idx {
48 out_shaped_idx.push(shape_idx);
49 }
50 }
51}
52
53pub fn paint_cursor_end(painter: &Painter, visuals: &Visuals, cursor_rect: Rect) {
57 let stroke = visuals.text_cursor.stroke;
58
59 let top = cursor_rect.center_top();
60 let bottom = cursor_rect.center_bottom();
61
62 painter.line_segment([top, bottom], (stroke.width, stroke.color));
63
64 if false {
65 let extrusion = 3.0;
67 let width = 1.0;
68 painter.line_segment(
69 [top - vec2(extrusion, 0.0), top + vec2(extrusion, 0.0)],
70 (width, stroke.color),
71 );
72 painter.line_segment(
73 [bottom - vec2(extrusion, 0.0), bottom + vec2(extrusion, 0.0)],
74 (width, stroke.color),
75 );
76 }
77}
78
79pub fn paint_text_cursor(
81 ui: &Ui,
82 painter: &Painter,
83 primary_cursor_rect: Rect,
84 time_since_last_edit: f64,
85) {
86 if ui.visuals().text_cursor.blink {
87 let on_duration = ui.visuals().text_cursor.on_duration;
88 let off_duration = ui.visuals().text_cursor.off_duration;
89 let total_duration = on_duration + off_duration;
90
91 let time_in_cycle = (time_since_last_edit % (total_duration as f64)) as f32;
92
93 let wake_in = if time_in_cycle < on_duration {
94 paint_cursor_end(painter, ui.visuals(), primary_cursor_rect);
96 on_duration - time_in_cycle
97 } else {
98 total_duration - time_in_cycle
100 };
101
102 ui.ctx().request_repaint_after_secs(wake_in);
103 } else {
104 paint_cursor_end(painter, ui.visuals(), primary_cursor_rect);
105 }
106}