1#[cfg(not(feature = "std"))]
4use alloc::{
5 string::{String, ToString},
6 vec::Vec,
7};
8use core::cmp;
9
10use unicode_segmentation::UnicodeSegmentation;
11
12use crate::{
13 Action, Attrs, AttrsList, BorrowedWithFontSystem, BufferLine, BufferRef, Change, ChangeItem,
14 Color, Cursor, Edit, FontSystem, LayoutRun, LineEnding, LineIter, Renderer, Selection, Shaping,
15};
16
17#[derive(Debug, Clone)]
19pub struct Editor<'buffer> {
20 buffer_ref: BufferRef<'buffer>,
21 cursor: Cursor,
22 cursor_x_opt: Option<i32>,
23 selection: Selection,
24 cursor_moved: bool,
25 auto_indent: bool,
26 change: Option<Change>,
27}
28
29fn cursor_glyph_opt(cursor: &Cursor, run: &LayoutRun) -> Option<(usize, f32)> {
30 if cursor.line == run.line_i {
31 for (glyph_i, glyph) in run.glyphs.iter().enumerate() {
32 if cursor.index == glyph.start {
33 return Some((glyph_i, 0.0));
34 } else if cursor.index > glyph.start && cursor.index < glyph.end {
35 let mut before = 0;
37 let mut total = 0;
38
39 let cluster = &run.text[glyph.start..glyph.end];
40 for (i, _) in cluster.grapheme_indices(true) {
41 if glyph.start + i < cursor.index {
42 before += 1;
43 }
44 total += 1;
45 }
46
47 let offset = glyph.w * (before as f32) / (total as f32);
48 return Some((glyph_i, offset));
49 }
50 }
51 match run.glyphs.last() {
52 Some(glyph) => {
53 if cursor.index == glyph.end {
54 return Some((run.glyphs.len(), 0.0));
55 }
56 }
57 None => {
58 return Some((0, 0.0));
59 }
60 }
61 }
62 None
63}
64
65fn cursor_position(cursor: &Cursor, run: &LayoutRun) -> Option<(i32, i32)> {
66 let (cursor_glyph, cursor_glyph_offset) = cursor_glyph_opt(cursor, run)?;
67 let x = run.glyphs.get(cursor_glyph).map_or_else(
68 || {
69 run.glyphs.last().map_or(0, |glyph| {
70 if glyph.level.is_rtl() {
71 glyph.x as i32
72 } else {
73 (glyph.x + glyph.w) as i32
74 }
75 })
76 },
77 |glyph| {
78 if glyph.level.is_rtl() {
79 (glyph.x + glyph.w - cursor_glyph_offset) as i32
80 } else {
81 (glyph.x + cursor_glyph_offset) as i32
82 }
83 },
84 );
85
86 Some((x, run.line_top as i32))
87}
88
89impl<'buffer> Editor<'buffer> {
90 pub fn new(buffer: impl Into<BufferRef<'buffer>>) -> Self {
92 Self {
93 buffer_ref: buffer.into(),
94 cursor: Cursor::default(),
95 cursor_x_opt: None,
96 selection: Selection::None,
97 cursor_moved: false,
98 auto_indent: false,
99 change: None,
100 }
101 }
102
103 #[cfg(feature = "swash")]
105 #[allow(clippy::too_many_arguments)]
106 pub fn draw<F>(
107 &self,
108 font_system: &mut FontSystem,
109 cache: &mut crate::SwashCache,
110 text_color: Color,
111 cursor_color: Color,
112 selection_color: Color,
113 selected_text_color: Color,
114 callback: F,
115 ) where
116 F: FnMut(i32, i32, u32, u32, Color),
117 {
118 let mut renderer = crate::LegacyRenderer {
119 font_system,
120 cache,
121 callback,
122 };
123 self.render(
124 &mut renderer,
125 text_color,
126 cursor_color,
127 selection_color,
128 selected_text_color,
129 );
130 }
131
132 pub fn render<R: Renderer>(
133 &self,
134 renderer: &mut R,
135 text_color: Color,
136 cursor_color: Color,
137 selection_color: Color,
138 selected_text_color: Color,
139 ) {
140 let selection_bounds = self.selection_bounds();
141 self.with_buffer(|buffer| {
142 for run in buffer.layout_runs() {
143 let line_i = run.line_i;
144 let line_y = run.line_y;
145 let line_top = run.line_top;
146 let line_height = run.line_height;
147
148 if let Some((start, end)) = selection_bounds {
150 if line_i >= start.line && line_i <= end.line {
151 let mut range_opt = None;
152 for glyph in run.glyphs {
153 let cluster = &run.text[glyph.start..glyph.end];
155 let total = cluster.grapheme_indices(true).count();
156 let mut c_x = glyph.x;
157 let c_w = glyph.w / total as f32;
158 for (i, c) in cluster.grapheme_indices(true) {
159 let c_start = glyph.start + i;
160 let c_end = glyph.start + i + c.len();
161 if (start.line != line_i || c_end > start.index)
162 && (end.line != line_i || c_start < end.index)
163 {
164 range_opt = match range_opt.take() {
165 Some((min, max)) => Some((
166 cmp::min(min, c_x as i32),
167 cmp::max(max, (c_x + c_w) as i32),
168 )),
169 None => Some((c_x as i32, (c_x + c_w) as i32)),
170 };
171 } else if let Some((min, max)) = range_opt.take() {
172 renderer.rectangle(
173 min,
174 line_top as i32,
175 cmp::max(0, max - min) as u32,
176 line_height as u32,
177 selection_color,
178 );
179 }
180 c_x += c_w;
181 }
182 }
183
184 if run.glyphs.is_empty() && end.line > line_i {
185 range_opt = Some((0, buffer.size().0.unwrap_or(0.0) as i32));
187 }
188
189 if let Some((mut min, mut max)) = range_opt.take() {
190 if end.line > line_i {
191 if run.rtl {
193 min = 0;
194 } else {
195 max = buffer.size().0.unwrap_or(0.0) as i32;
196 }
197 }
198 renderer.rectangle(
199 min,
200 line_top as i32,
201 cmp::max(0, max - min) as u32,
202 line_height as u32,
203 selection_color,
204 );
205 }
206 }
207 }
208
209 if let Some((x, y)) = cursor_position(&self.cursor, &run) {
211 renderer.rectangle(x, y, 1, line_height as u32, cursor_color);
212 }
213
214 for glyph in run.glyphs {
215 let physical_glyph = glyph.physical((0., line_y), 1.0);
216
217 let mut glyph_color = glyph.color_opt.map_or(text_color, |some| some);
218 if text_color != selected_text_color {
219 if let Some((start, end)) = selection_bounds {
220 if line_i >= start.line
221 && line_i <= end.line
222 && (start.line != line_i || glyph.end > start.index)
223 && (end.line != line_i || glyph.start < end.index)
224 {
225 glyph_color = selected_text_color;
226 }
227 }
228 }
229
230 renderer.glyph(physical_glyph, glyph_color);
231 }
232 }
233 });
234 }
235}
236
237impl<'buffer> Edit<'buffer> for Editor<'buffer> {
238 fn buffer_ref(&self) -> &BufferRef<'buffer> {
239 &self.buffer_ref
240 }
241
242 fn buffer_ref_mut(&mut self) -> &mut BufferRef<'buffer> {
243 &mut self.buffer_ref
244 }
245
246 fn cursor(&self) -> Cursor {
247 self.cursor
248 }
249
250 fn set_cursor(&mut self, cursor: Cursor) {
251 if self.cursor != cursor {
252 self.cursor = cursor;
253 self.cursor_moved = true;
254 self.with_buffer_mut(|buffer| buffer.set_redraw(true));
255 }
256 }
257
258 fn selection(&self) -> Selection {
259 self.selection
260 }
261
262 fn set_selection(&mut self, selection: Selection) {
263 if self.selection != selection {
264 self.selection = selection;
265 self.with_buffer_mut(|buffer| buffer.set_redraw(true));
266 }
267 }
268
269 fn auto_indent(&self) -> bool {
270 self.auto_indent
271 }
272
273 fn set_auto_indent(&mut self, auto_indent: bool) {
274 self.auto_indent = auto_indent;
275 }
276
277 fn tab_width(&self) -> u16 {
278 self.with_buffer(super::super::buffer::Buffer::tab_width)
279 }
280
281 fn set_tab_width(&mut self, font_system: &mut FontSystem, tab_width: u16) {
282 self.with_buffer_mut(|buffer| buffer.set_tab_width(font_system, tab_width));
283 }
284
285 fn shape_as_needed(&mut self, font_system: &mut FontSystem, prune: bool) {
286 if self.cursor_moved {
287 let cursor = self.cursor;
288 self.with_buffer_mut(|buffer| buffer.shape_until_cursor(font_system, cursor, prune));
289 self.cursor_moved = false;
290 } else {
291 self.with_buffer_mut(|buffer| buffer.shape_until_scroll(font_system, prune));
292 }
293 }
294
295 fn delete_range(&mut self, start: Cursor, end: Cursor) {
296 let change_item = self.with_buffer_mut(|buffer| {
297 let mut change_lines = Vec::new();
299
300 let end_line_opt = if end.line > start.line {
302 let after = buffer.lines[end.line].split_off(end.index);
304
305 let removed = buffer.lines.remove(end.line);
307 change_lines.insert(0, removed);
308
309 Some(after)
310 } else {
311 None
312 };
313
314 for line_i in (start.line + 1..end.line).rev() {
316 let removed = buffer.lines.remove(line_i);
317 change_lines.insert(0, removed);
318 }
319
320 {
322 let line = &mut buffer.lines[start.line];
323
324 let after_opt = if start.line == end.line {
326 Some(line.split_off(end.index))
327 } else {
328 None
329 };
330
331 let removed = line.split_off(start.index);
333 change_lines.insert(0, removed);
334
335 if let Some(after) = after_opt {
337 line.append(&after);
338 }
339
340 if let Some(mut end_line) = end_line_opt {
342 if end_line.ending() == LineEnding::None {
344 end_line.set_ending(line.ending());
345 }
346 line.append(&end_line);
347 }
348 }
349
350 let mut text = String::new();
351 let mut last_ending: Option<LineEnding> = None;
352 for line in change_lines {
353 if let Some(ending) = last_ending {
354 text.push_str(ending.as_str());
355 }
356 text.push_str(line.text());
357 last_ending = Some(line.ending());
358 }
359
360 ChangeItem {
361 start,
362 end,
363 text,
364 insert: false,
365 }
366 });
367
368 if let Some(ref mut change) = self.change {
369 change.items.push(change_item);
370 }
371 }
372
373 fn insert_at(
374 &mut self,
375 mut cursor: Cursor,
376 data: &str,
377 attrs_list: Option<AttrsList>,
378 ) -> Cursor {
379 let mut remaining_split_len = data.len();
380 if remaining_split_len == 0 {
381 return cursor;
382 }
383
384 let change_item = self.with_buffer_mut(|buffer| {
385 let start = cursor;
387
388 while cursor.line >= buffer.lines.len() {
390 let mut last_ending = LineEnding::None;
392 if let Some(last_line) = buffer.lines.last_mut() {
393 last_ending = last_line.ending();
394 if last_ending == LineEnding::None {
396 last_line.set_ending(LineEnding::default());
397 }
398 }
399 let line = BufferLine::new(
400 String::new(),
401 last_ending,
402 AttrsList::new(&attrs_list.as_ref().map_or_else(
403 || {
404 buffer
405 .lines
406 .last()
407 .map_or_else(Attrs::new, |line| line.attrs_list().defaults())
408 },
409 |x| x.defaults(),
410 )),
411 Shaping::Advanced,
412 );
413 buffer.lines.push(line);
414 }
415
416 let line: &mut BufferLine = &mut buffer.lines[cursor.line];
417 let insert_line = cursor.line + 1;
418
419 let after: BufferLine = line.split_off(cursor.index);
421 let after_len = after.text().len();
422
423 let mut final_attrs = attrs_list.unwrap_or_else(|| {
425 AttrsList::new(&line.attrs_list().get_span(cursor.index.saturating_sub(1)))
426 });
427
428 let mut lines: Vec<_> = LineIter::new(data).collect();
430 if lines.last().map(|line| line.1).unwrap_or(LineEnding::None) != LineEnding::None {
432 lines.push((Default::default(), LineEnding::None));
433 }
434 let mut lines_iter = lines.into_iter();
435
436 if let Some((range, ending)) = lines_iter.next() {
438 let data_line = &data[range];
439 let mut these_attrs = final_attrs.split_off(data_line.len());
440 remaining_split_len -= data_line.len() + ending.as_str().len();
441 core::mem::swap(&mut these_attrs, &mut final_attrs);
442 line.append(&BufferLine::new(
443 data_line,
444 ending,
445 these_attrs,
446 Shaping::Advanced,
447 ));
448 }
449 if let Some((range, ending)) = lines_iter.next_back() {
451 let data_line = &data[range];
452 remaining_split_len -= data_line.len() + ending.as_str().len();
453 let mut tmp = BufferLine::new(
454 data_line,
455 ending,
456 final_attrs.split_off(remaining_split_len),
457 Shaping::Advanced,
458 );
459 tmp.append(&after);
460 buffer.lines.insert(insert_line, tmp);
461 cursor.line += 1;
462 } else {
463 line.append(&after);
464 }
465 for (range, ending) in lines_iter.rev() {
467 let data_line = &data[range];
468 remaining_split_len -= data_line.len() + ending.as_str().len();
469 let tmp = BufferLine::new(
470 data_line,
471 ending,
472 final_attrs.split_off(remaining_split_len),
473 Shaping::Advanced,
474 );
475 buffer.lines.insert(insert_line, tmp);
476 cursor.line += 1;
477 }
478
479 assert_eq!(remaining_split_len, 0);
480
481 cursor.index = buffer.lines[cursor.line].text().len() - after_len;
483
484 ChangeItem {
485 start,
486 end: cursor,
487 text: data.to_string(),
488 insert: true,
489 }
490 });
491
492 if let Some(ref mut change) = self.change {
493 change.items.push(change_item);
494 }
495
496 cursor
497 }
498
499 fn copy_selection(&self) -> Option<String> {
500 let (start, end) = self.selection_bounds()?;
501 self.with_buffer(|buffer| {
502 let mut selection = String::new();
503 {
505 if start.line == end.line {
507 selection.push_str(&buffer.lines[start.line].text()[start.index..end.index]);
508 } else {
509 selection.push_str(&buffer.lines[start.line].text()[start.index..]);
510 selection.push('\n');
511 }
512 }
513
514 for line_i in start.line + 1..end.line {
516 selection.push_str(buffer.lines[line_i].text());
517 selection.push('\n');
518 }
519
520 if end.line > start.line {
522 selection.push_str(&buffer.lines[end.line].text()[..end.index]);
524 }
525
526 Some(selection)
527 })
528 }
529
530 fn delete_selection(&mut self) -> bool {
531 let Some((start, end)) = self.selection_bounds() else {
532 return false;
533 };
534
535 self.cursor = start;
537
538 self.selection = Selection::None;
540
541 self.delete_range(start, end);
543
544 true
545 }
546
547 fn apply_change(&mut self, change: &Change) -> bool {
548 if let Some(pending) = self.change.take() {
550 if !pending.items.is_empty() {
551 log::warn!("pending change caused apply_change to be ignored!");
553 self.change = Some(pending);
554 return false;
555 }
556 }
557
558 for item in &change.items {
559 if item.insert {
561 self.cursor = self.insert_at(item.start, &item.text, None);
562 } else {
563 self.cursor = item.start;
564 self.delete_range(item.start, item.end);
565 }
566 }
567 true
568 }
569
570 fn start_change(&mut self) {
571 if self.change.is_none() {
572 self.change = Some(Change::default());
573 }
574 }
575
576 fn finish_change(&mut self) -> Option<Change> {
577 self.change.take()
578 }
579
580 fn action(&mut self, font_system: &mut FontSystem, action: Action) {
581 let old_cursor = self.cursor;
582
583 match action {
584 Action::Motion(motion) => {
585 let cursor = self.cursor;
586 let cursor_x_opt = self.cursor_x_opt;
587 if let Some((new_cursor, new_cursor_x_opt)) = self.with_buffer_mut(|buffer| {
588 buffer.cursor_motion(font_system, cursor, cursor_x_opt, motion)
589 }) {
590 self.cursor = new_cursor;
591 self.cursor_x_opt = new_cursor_x_opt;
592 }
593 }
594 Action::Escape => {
595 match self.selection {
596 Selection::None => {}
597 _ => self.with_buffer_mut(|buffer| buffer.set_redraw(true)),
598 }
599 self.selection = Selection::None;
600 }
601 Action::Insert(character) => {
602 if character.is_control() && !['\t', '\n', '\u{92}'].contains(&character) {
603 log::debug!("Refusing to insert control character {character:?}");
605 } else if character == '\n' {
606 self.action(font_system, Action::Enter);
607 } else {
608 let mut str_buf = [0u8; 8];
609 let str_ref = character.encode_utf8(&mut str_buf);
610 self.insert_string(str_ref, None);
611 }
612 }
613 Action::Enter => {
614 if self.auto_indent {
616 let mut string = String::from("\n");
617 self.with_buffer(|buffer| {
618 let line = &buffer.lines[self.cursor.line];
619 let text = line.text();
620 for c in text.chars() {
621 if c.is_whitespace() {
622 string.push(c);
623 } else {
624 break;
625 }
626 }
627 });
628 self.insert_string(&string, None);
629 } else {
630 self.insert_string("\n", None);
631 }
632
633 let line_i = self.cursor.line;
635 self.with_buffer_mut(|buffer| {
636 buffer.line_layout(font_system, line_i);
637 });
638 }
639 Action::Backspace => {
640 if self.delete_selection() {
641 } else {
643 let end = self.cursor;
645
646 if self.cursor.index > 0 {
647 self.cursor.index = self.with_buffer(|buffer| {
649 buffer.lines[self.cursor.line].text()[..self.cursor.index]
650 .char_indices()
651 .next_back()
652 .map_or(0, |(i, _)| i)
653 });
654 } else if self.cursor.line > 0 {
655 self.cursor.line -= 1;
657 self.cursor.index =
658 self.with_buffer(|buffer| buffer.lines[self.cursor.line].text().len());
659 }
660
661 if self.cursor != end {
662 self.delete_range(self.cursor, end);
664 }
665 }
666 }
667 Action::Delete => {
668 if self.delete_selection() {
669 } else {
671 let mut start = self.cursor;
673 let mut end = self.cursor;
674
675 self.with_buffer(|buffer| {
676 if start.index < buffer.lines[start.line].text().len() {
677 let line = &buffer.lines[start.line];
678
679 let range_opt = line
680 .text()
681 .grapheme_indices(true)
682 .take_while(|(i, _)| *i <= start.index)
683 .last()
684 .map(|(i, c)| i..(i + c.len()));
685
686 if let Some(range) = range_opt {
687 start.index = range.start;
688 end.index = range.end;
689 }
690 } else if start.line + 1 < buffer.lines.len() {
691 end.line += 1;
692 end.index = 0;
693 }
694 });
695
696 if start != end {
697 self.cursor = start;
698 self.delete_range(start, end);
699 }
700 }
701 }
702 Action::Indent => {
703 let (start, end) = match self.selection_bounds() {
705 Some(some) => some,
706 None => (self.cursor, self.cursor),
707 };
708
709 let tab_width: usize = self.tab_width().into();
711 for line_i in start.line..=end.line {
712 let mut after_whitespace = 0;
714 let mut required_indent = 0;
715 self.with_buffer(|buffer| {
716 let line = &buffer.lines[line_i];
717 let text = line.text();
718
719 if self.selection == Selection::None {
720 let whitespace_length = match line.text()[0..self.cursor.index]
722 .chars()
723 .rev()
724 .position(|c| !c.is_whitespace())
725 {
726 Some(length) => length,
727 None => self.cursor.index,
729 };
730 required_indent = tab_width - (whitespace_length % tab_width);
731 after_whitespace = self.cursor.index;
732 } else {
733 for (count, (index, c)) in text.char_indices().enumerate() {
735 if !c.is_whitespace() {
736 after_whitespace = index;
737 required_indent = tab_width - (count % tab_width);
738 break;
739 }
740 }
741 }
742 });
743
744 self.insert_at(
745 Cursor::new(line_i, after_whitespace),
746 &" ".repeat(required_indent),
747 None,
748 );
749
750 if self.cursor.line == line_i {
752 if self.cursor.index < after_whitespace {
754 self.cursor.index = after_whitespace;
755 }
756 self.cursor.index += required_indent;
757 }
758
759 match self.selection {
761 Selection::None => {}
762 Selection::Normal(ref mut select)
763 | Selection::Line(ref mut select)
764 | Selection::Word(ref mut select) => {
765 if select.line == line_i && select.index >= after_whitespace {
766 select.index += required_indent;
767 }
768 }
769 }
770 self.with_buffer_mut(|buffer| buffer.set_redraw(true));
772 }
773 }
774 Action::Unindent => {
775 let (start, end) = match self.selection_bounds() {
777 Some(some) => some,
778 None => (self.cursor, self.cursor),
779 };
780
781 let tab_width: usize = self.tab_width().into();
783 for line_i in start.line..=end.line {
784 let mut last_indent = 0;
786 let mut after_whitespace = 0;
787 self.with_buffer(|buffer| {
788 let line = &buffer.lines[line_i];
789 let text = line.text();
790 after_whitespace = text.len();
792 for (count, (index, c)) in text.char_indices().enumerate() {
793 if !c.is_whitespace() {
794 after_whitespace = index;
795 break;
796 }
797 if count % tab_width == 0 {
798 last_indent = index;
799 }
800 }
801 });
802
803 if last_indent == after_whitespace {
805 continue;
806 }
807
808 self.delete_range(
810 Cursor::new(line_i, last_indent),
811 Cursor::new(line_i, after_whitespace),
812 );
813
814 if self.cursor.line == line_i && self.cursor.index > last_indent {
816 self.cursor.index -= after_whitespace - last_indent;
817 }
818
819 match self.selection {
821 Selection::None => {}
822 Selection::Normal(ref mut select)
823 | Selection::Line(ref mut select)
824 | Selection::Word(ref mut select) => {
825 if select.line == line_i && select.index > last_indent {
826 select.index -= after_whitespace - last_indent;
827 }
828 }
829 }
830
831 self.with_buffer_mut(|buffer| buffer.set_redraw(true));
833 }
834 }
835 Action::Click { x, y } => {
836 self.set_selection(Selection::None);
837
838 if let Some(new_cursor) = self.with_buffer(|buffer| buffer.hit(x as f32, y as f32))
839 {
840 if new_cursor != self.cursor {
841 self.cursor = new_cursor;
842 self.with_buffer_mut(|buffer| buffer.set_redraw(true));
843 }
844 }
845 }
846 Action::DoubleClick { x, y } => {
847 self.set_selection(Selection::None);
848
849 if let Some(new_cursor) = self.with_buffer(|buffer| buffer.hit(x as f32, y as f32))
850 {
851 if new_cursor != self.cursor {
852 self.cursor = new_cursor;
853 self.with_buffer_mut(|buffer| buffer.set_redraw(true));
854 }
855 self.selection = Selection::Word(self.cursor);
856 self.with_buffer_mut(|buffer| buffer.set_redraw(true));
857 }
858 }
859 Action::TripleClick { x, y } => {
860 self.set_selection(Selection::None);
861
862 if let Some(new_cursor) = self.with_buffer(|buffer| buffer.hit(x as f32, y as f32))
863 {
864 if new_cursor != self.cursor {
865 self.cursor = new_cursor;
866 }
867 self.selection = Selection::Line(self.cursor);
868 self.with_buffer_mut(|buffer| buffer.set_redraw(true));
869 }
870 }
871 Action::Drag { x, y } => {
872 if self.selection == Selection::None {
873 self.selection = Selection::Normal(self.cursor);
874 self.with_buffer_mut(|buffer| buffer.set_redraw(true));
875 }
876
877 if let Some(new_cursor) = self.with_buffer(|buffer| buffer.hit(x as f32, y as f32))
878 {
879 if new_cursor != self.cursor {
880 self.cursor = new_cursor;
881 self.with_buffer_mut(|buffer| buffer.set_redraw(true));
882 }
883 }
884 }
885 Action::Scroll { pixels } => {
886 self.with_buffer_mut(|buffer| {
887 let mut scroll = buffer.scroll();
888 scroll.vertical += pixels;
890 buffer.set_scroll(scroll);
891 });
892 }
893 }
894
895 if old_cursor != self.cursor {
896 self.cursor_moved = true;
897 self.with_buffer_mut(|buffer| buffer.set_redraw(true));
898
899 }
915 }
916
917 fn cursor_position(&self) -> Option<(i32, i32)> {
918 self.with_buffer(|buffer| {
919 buffer
920 .layout_runs()
921 .find_map(|run| cursor_position(&self.cursor, &run))
922 })
923 }
924}
925
926impl BorrowedWithFontSystem<'_, Editor<'_>> {
927 #[cfg(feature = "swash")]
928 pub fn draw<F>(
929 &mut self,
930 cache: &mut crate::SwashCache,
931 text_color: Color,
932 cursor_color: Color,
933 selection_color: Color,
934 selected_text_color: Color,
935 f: F,
936 ) where
937 F: FnMut(i32, i32, u32, u32, Color),
938 {
939 self.inner.draw(
940 self.font_system,
941 cache,
942 text_color,
943 cursor_color,
944 selection_color,
945 selected_text_color,
946 f,
947 );
948 }
949}