1use std::any::Any;
2use std::cell::Cell;
3use std::rc::Rc;
4
5use sequoia_core::{Color, Dirty, ImageSource, Point, Rect, RenderList, Size, Vec2, WindowId};
6use sequoia_draw::ShapeCache;
7use sequoia_input::{CursorIcon, Event, EventPhase, Modifiers, PenTool};
8use sequoia_layout::{
9 ContainerStyle, DockStyle, GridPlacement, GridStyle, LayoutCtx, LayoutStyle, MasonryStyle,
10 WrapStyle,
11};
12use sequoia_reactive::Environment;
13use sequoia_style::{BoxStyle, Theme, VisualState};
14use sequoia_text::{
15 ElideMode, FontStyle, FontWeight, LetterSpacing, LineHeight, RichAlign, RichParagraph,
16 ShapedText, TextSpan, TextSystem, WrapMode,
17};
18
19use crate::any::AnyView;
20use crate::dnd::{DragEnd, DragOptions, DragPayload, DragSession, DropPosition};
21use crate::live::Prop;
22use crate::overlay::{OverlayEntry, OverlayId};
23use crate::runtime::{ElementId, Runtime};
24use crate::surface::SurfaceInputBinding;
25
26pub trait View {
27 fn body(&self) -> impl View + 'static;
28
29 #[doc(hidden)]
30 fn is_leaf(&self) -> bool {
31 false
32 }
33
34 #[doc(hidden)]
35 fn children_override(&self) -> Option<Vec<AnyView>> {
36 None
37 }
38
39 #[doc(hidden)]
40 fn keyed_children(&self) -> Option<Vec<(u64, AnyView)>> {
41 None
42 }
43
44 #[doc(hidden)]
45 fn layout_style(&self) -> LayoutStyle {
46 LayoutStyle::default()
47 }
48
49 fn layout_style_ctx(&self, _rt: &Runtime, _el: ElementId) -> LayoutStyle {
50 self.layout_style()
51 }
52
53 #[doc(hidden)]
59 fn signal_dirty(&self) -> Dirty {
60 Dirty::LAYOUT | Dirty::CHILDREN
61 }
62
63 #[doc(hidden)]
69 fn invalidate_cache(&self) {}
70
71 #[doc(hidden)]
72 fn has_visual_state(&self) -> bool {
73 false
74 }
75
76 #[doc(hidden)]
77 fn wants_hover_updates(&self) -> bool {
78 false
79 }
80
81 fn accessibility(&self) -> Option<crate::a11y::Accessible> {
82 None
83 }
84
85 #[doc(hidden)]
86 fn container(&self) -> Option<ContainerStyle> {
87 None
88 }
89
90 #[doc(hidden)]
91 fn grid(&self) -> Option<GridStyle> {
92 None
93 }
94
95 #[doc(hidden)]
96 fn dock(&self) -> Option<DockStyle> {
97 None
98 }
99
100 #[doc(hidden)]
101 fn wrap(&self) -> Option<WrapStyle> {
102 None
103 }
104
105 #[doc(hidden)]
106 fn masonry(&self) -> Option<MasonryStyle> {
107 None
108 }
109
110 #[doc(hidden)]
111 fn flex_weights(&self) -> Option<&[f32]> {
112 None
113 }
114
115 #[doc(hidden)]
116 fn grid_placement(&self) -> Option<GridPlacement> {
117 None
118 }
119
120 #[doc(hidden)]
121 fn grid_placements(&self) -> Option<Vec<GridPlacement>> {
122 None
123 }
124
125 #[doc(hidden)]
126 fn intrinsic_size(&self, _ctx: &mut LayoutCtx) -> Option<Size> {
127 None
128 }
129
130 #[doc(hidden)]
134 fn baseline_offset(&self, _ctx: &mut LayoutCtx, _width: f32) -> Option<f32> {
135 None
136 }
137
138 #[doc(hidden)]
139 fn contain_size(&self) -> bool {
140 false
141 }
142
143 fn arrange_override(
144 &self,
145 _rt: &Runtime,
146 _el: ElementId,
147 _rect: Rect,
148 _ctx: &mut LayoutCtx,
149 ) -> bool {
150 false
151 }
152
153 fn clip_self(&self) -> bool {
154 false
155 }
156
157 fn clip_radius(&self) -> f32 {
158 0.0
159 }
160
161 fn paint_opacity(&self) -> Option<f32> {
162 None
163 }
164
165 fn cache_layer(&self) -> bool {
171 false
172 }
173
174 fn paint_opacity_ctx(&self, _rt: &Runtime, _el: ElementId) -> Option<f32> {
175 self.paint_opacity()
176 }
177
178 fn paint_offset(&self) -> Vec2 {
179 Vec2::ZERO
180 }
181
182 fn paint_offset_ctx(&self, _rt: &Runtime, _el: ElementId) -> Vec2 {
183 self.paint_offset()
184 }
185
186 fn paint_scale(&self) -> f32 {
187 1.0
188 }
189
190 fn paint_scale_ctx(&self, _rt: &Runtime, _el: ElementId) -> f32 {
191 self.paint_scale()
192 }
193
194 fn paint_rotation(&self) -> f32 {
195 0.0
196 }
197
198 fn paint_rotation_ctx(&self, _rt: &Runtime, _el: ElementId) -> f32 {
199 self.paint_rotation()
200 }
201
202 fn foreground_filter(&self) -> Option<sequoia_style::Filter> {
203 None
204 }
205
206 #[doc(hidden)]
207 fn surface_target(&self) -> Option<Rc<dyn Any>> {
208 None
209 }
210
211 #[doc(hidden)]
212 fn surface_input(&self) -> Option<SurfaceInputBinding> {
213 None
214 }
215
216 #[doc(hidden)]
217 fn on_event(&self, _event: &Event, _ctx: &mut EventCtx) {}
218
219 #[doc(hidden)]
220 fn captures_pointer(&self) -> bool {
221 false
222 }
223
224 fn captures_pointer_ctx(&self, _rt: &Runtime, _el: ElementId) -> bool {
225 self.captures_pointer()
226 }
227
228 fn reuse_state(&self, _old: &Self) {}
229
230 fn hit_testable(&self) -> bool {
231 true
232 }
233
234 fn test_id(&self) -> Option<String> {
235 None
236 }
237
238 #[doc(hidden)]
239 fn focusable(&self) -> bool {
240 false
241 }
242
243 fn focus_trap(&self) -> bool {
244 false
245 }
246
247 fn accepts_tab(&self) -> bool {
248 false
249 }
250
251 fn accepts_text_input(&self) -> bool {
257 false
258 }
259
260 fn ime_caret_rect(&self) -> Option<Rect> {
265 None
266 }
267
268 #[doc(hidden)]
269 fn cursor_icon(&self, _state: VisualState) -> CursorIcon {
270 CursorIcon::Default
271 }
272
273 #[doc(hidden)]
274 fn paint_self(&self, _ctx: &mut PaintCtx) {}
275
276 fn paint_foreground(&self, _ctx: &mut PaintCtx) {}
277
278 fn accepts_drop(&self, _payload: &DragPayload) -> bool {
279 false
280 }
281
282 fn on_drag_over(&self, _pos: DropPosition, _ctx: &mut EventCtx) {}
283
284 fn on_drop(&self, _pos: DropPosition, _ctx: &mut EventCtx) {}
285
286 fn on_drag_start(&self, _ctx: &mut EventCtx) {}
287
288 fn on_drag_end(&self, _end: DragEnd, _ctx: &mut EventCtx) {}
289
290 #[doc(hidden)]
291 fn on_mount(&self) {}
292
293 #[doc(hidden)]
294 fn on_unmount(&self) {}
295}
296
297pub struct EventCtx<'a> {
298 pub phase: EventPhase,
299 pub element: ElementId,
300 pub state: VisualState,
301 pub hover_self: bool,
302 pub pos: Point,
303 pub rect: Rect,
304 pub environment: &'a Environment,
305 pub window: WindowId,
306 pub(crate) stopped: &'a Cell<bool>,
307 pub(crate) handled: &'a Cell<bool>,
308 pub(crate) capture_req: &'a Cell<Option<ElementId>>,
309 pub(crate) release_req: &'a Cell<bool>,
310 pub(crate) focus_req: &'a Cell<bool>,
311 pub(crate) text: &'a mut TextSystem,
312 pub(crate) runtime: &'a Runtime,
313}
314
315impl EventCtx<'_> {
316 pub fn local_pos(&self) -> Point {
317 Point::new(self.pos.x - self.rect.left(), self.pos.y - self.rect.top())
318 }
319
320 pub fn stop_propagation(&mut self) {
321 self.stopped.set(true);
322 }
323
324 pub fn handled(&mut self) {
325 self.handled.set(true);
326 self.stopped.set(true);
327 }
328
329 pub fn capture_pointer(&mut self) {
330 self.capture_req.set(Some(self.element));
331 self.release_req.set(false);
332 }
333
334 pub fn release_pointer(&mut self) {
335 self.release_req.set(true);
336 self.capture_req.set(None);
337 }
338
339 pub fn request_focus(&mut self) {
340 self.focus_req.set(true);
341 }
342
343 pub fn begin_drag<T: 'static>(&self, payload: T, options: DragOptions) {
344 self.runtime.begin_pending(
345 self.element,
346 DragPayload::new(payload),
347 self.pos,
348 self.rect,
349 options,
350 );
351 }
352
353 pub fn drag_session(&self) -> Option<DragSession> {
354 self.runtime.current_drag()
355 }
356
357 pub fn drop_position(&self, modifiers: Modifiers) -> DropPosition {
358 DropPosition::in_rect(self.pos, self.rect, modifiers)
359 }
360
361 pub fn cancel_drag(&mut self) {
362 self.runtime.cancel_drag(&mut *self.text);
363 }
364
365 pub fn pressure(&self) -> f32 {
366 self.runtime.pointer_pressure()
367 }
368
369 pub fn tool(&self) -> PenTool {
370 self.runtime.pointer_tool()
371 }
372
373 pub fn text_width(&mut self, text: &str, size: f32) -> f32 {
374 self.text.text_width(text, size)
375 }
376
377 pub fn text_width_weighted(&mut self, text: &str, size: f32, weight: FontWeight) -> f32 {
378 self.text.text_width_weighted(text, size, weight)
379 }
380
381 pub fn text_width_weighted_spaced(
382 &mut self,
383 text: &str,
384 size: f32,
385 weight: FontWeight,
386 spacing: LetterSpacing,
387 ) -> f32 {
388 self.text
389 .text_width_weighted_spaced(text, size, weight, spacing)
390 }
391
392 pub fn caret_positions(&mut self, text: &str, size: f32, weight: FontWeight) -> Vec<f32> {
393 self.text.caret_positions(text, size, weight)
394 }
395
396 pub fn caret_positions_spaced(
397 &mut self,
398 text: &str,
399 size: f32,
400 weight: FontWeight,
401 spacing: LetterSpacing,
402 ) -> Vec<f32> {
403 self.text
404 .caret_positions_spaced(text, size, weight, spacing)
405 }
406
407 pub fn char_index_from_x(
408 &mut self,
409 text: &str,
410 size: f32,
411 weight: FontWeight,
412 x: f32,
413 ) -> usize {
414 self.text.char_index_from_x(text, size, weight, x)
415 }
416
417 pub fn char_index_from_x_spaced(
418 &mut self,
419 text: &str,
420 size: f32,
421 weight: FontWeight,
422 x: f32,
423 spacing: LetterSpacing,
424 ) -> usize {
425 self.text
426 .char_index_from_x_spaced(text, size, weight, x, spacing)
427 }
428
429 pub fn shape_rich_full(
430 &mut self,
431 spans: &[TextSpan],
432 size: f32,
433 width: f32,
434 mode: WrapMode,
435 spacing: LetterSpacing,
436 align: RichAlign,
437 ) -> std::rc::Rc<RichParagraph> {
438 self.text
439 .shape_rich_full(spans, size, width, mode, spacing, align)
440 }
441
442 pub fn request_frame(&self) {
443 self.runtime.request_frame();
444 }
445
446 pub fn hide_overlay(&self, id: OverlayId) -> bool {
447 self.runtime.overlay_hide(id)
448 }
449
450 pub fn has_overlay(&self, id: OverlayId) -> bool {
451 self.runtime.overlay_exists(id)
452 }
453
454 pub fn overlay_rect(&self, id: OverlayId) -> Option<Rect> {
455 self.runtime.overlay_rect(id)
456 }
457
458 pub fn overlay_set_position(&self, id: OverlayId, x: f32, y: f32) -> bool {
459 self.runtime.overlay_set_position(id, x, y)
460 }
461
462 pub fn has_focus_within(&self) -> bool {
463 self.runtime.focus_in_subtree(self.element)
464 }
465
466 pub fn window_rect(&self) -> Rect {
467 self.runtime.window_rect()
468 }
469
470 pub fn window_size(&self) -> Size {
471 self.runtime.window_size_value()
472 }
473
474 pub fn scale(&self) -> f32 {
475 self.runtime.scale()
476 }
477
478 pub fn safe_insets(&self) -> sequoia_core::Edges {
479 self.runtime.safe_insets()
480 }
481
482 pub fn runtime(&self) -> &Runtime {
483 self.runtime
484 }
485
486 pub fn element(&self) -> ElementId {
487 self.element
488 }
489}
490
491#[derive(Clone, Copy, Debug, Default, PartialEq)]
492pub struct TextMetrics {
493 pub width: f32,
496
497 pub height: f32,
500
501 pub ascent: f32,
503
504 pub descent: f32,
506
507 pub line_gap: f32,
510}
511
512fn metrics_from_shaped(shaped: &ShapedText) -> TextMetrics {
513 let line_height = shaped.line_height();
514 let ascent = shaped.first_baseline();
515 TextMetrics {
516 width: shaped.width(),
517 height: shaped.height(),
518 ascent,
519 descent: (line_height - ascent).max(0.0),
520 line_gap: 0.0,
521 }
522}
523
524pub struct PaintCtx<'a> {
525 pub(crate) list: &'a mut RenderList,
526 pub(crate) text: &'a mut TextSystem,
527
528 pub environment: &'a Environment,
529
530 pub rect: Rect,
531
532 pub element: ElementId,
533
534 pub state: VisualState,
535
536 pub window: WindowId,
537
538 pub hovered_subtree: bool,
539 pub(crate) runtime: &'a Runtime,
540
541 pub(crate) shapes: &'a ShapeCache,
542
543 pub(crate) draw_offset: Vec2,
544
545 pub(crate) offset_stack: Vec<Vec2>,
546}
547
548impl PaintCtx<'_> {
549 pub fn theme(&self) -> Theme {
550 self.environment.get::<Theme>().unwrap_or_else(Theme::dark)
551 }
552
553 pub fn runtime(&self) -> &Runtime {
554 self.runtime
555 }
556
557 pub fn window_rect(&self) -> Rect {
558 self.runtime.window_rect()
559 }
560
561 pub fn window_size(&self) -> Size {
562 self.runtime.window_size_value()
563 }
564
565 pub fn scale(&self) -> f32 {
566 self.runtime.scale()
567 }
568
569 pub fn safe_insets(&self) -> sequoia_core::Edges {
570 self.runtime.safe_insets()
571 }
572
573 pub fn element(&self) -> ElementId {
574 self.element
575 }
576
577 pub fn measure_text(&mut self, text: &str, size: f32) -> TextMetrics {
579 if text.is_empty() || !(size > 0.0) {
580 return TextMetrics::default();
581 }
582 let shaped = self.text.shape(text, size);
583 metrics_from_shaped(&shaped)
584 }
585
586 pub fn text_metrics(&mut self, size: f32) -> TextMetrics {
592 if !(size > 0.0) {
593 return TextMetrics::default();
594 }
595 let shaped = self.text.shape("Mg", size);
596 TextMetrics {
597 width: 0.0,
598 ..metrics_from_shaped(&shaped)
599 }
600 }
601
602 pub fn baseline_centered(rect_top: f32, rect_h: f32, size: f32) -> f32 {
607 rect_top + rect_h * 0.5 + size * 0.35
608 }
609
610 pub fn baseline_top(rect_top: f32, size: f32) -> f32 {
614 rect_top + size * 1.35 * 0.5 + size * 0.35
615 }
616
617 pub fn quad(&mut self, rect: Rect, color: Color, radius: f32) {
618 let rect = if rect.is_empty() {
619 Rect::from_xywh(rect.origin.x, rect.origin.y, 1.0, 1.0)
620 } else {
621 rect
622 };
623 self.list.push_quad(rect, color, radius);
624 }
625
626 pub fn bordered_quad(
627 &mut self,
628 rect: Rect,
629 background: Color,
630 radius: f32,
631 border_width: f32,
632 border_color: Color,
633 ) {
634 self.list
635 .push_bordered_quad(rect, background, radius, border_width, border_color);
636 }
637
638 pub fn paint_box(&mut self, style: BoxStyle) {
639 let rect = self.rect;
640 self.paint_box_in(style, rect);
641 }
642
643 pub fn paint_box_in(&mut self, style: BoxStyle, rect: Rect) {
644 style.paint(self.list, rect);
645 }
646
647 pub fn push_clip(&mut self, rect: Rect) {
648 self.list.push_clip(rect);
649 }
650 pub fn pop_clip(&mut self) {
651 self.list.pop_clip();
652 }
653 pub fn push_rounded_clip(&mut self, rect: Rect, radius: f32) {
654 self.list.push_rounded_clip(rect, radius);
655 }
656
657 pub fn list_clip_depth(&self) -> usize {
658 self.list.clip_depth()
659 }
660
661 pub fn push_backdrop(&mut self, rect: Rect, backdrop: sequoia_style::Backdrop) {
662 if backdrop.is_empty() {
663 return;
664 }
665 self.list.push_backdrop(
666 rect,
667 backdrop.radius,
668 backdrop.blur_px(),
669 backdrop.dim,
670 backdrop.noise,
671 backdrop.span_mask(),
672 );
673 }
674
675 pub fn draw_text(&mut self, text: &str, origin: (f32, f32), size: f32, color: Color) {
681 self.draw_text_weighted(text, origin, size, FontWeight::NORMAL, color);
682 }
683
684 pub fn draw_text_tl(&mut self, text: &str, top_left: (f32, f32), size: f32, color: Color) {
689 if text.is_empty() || !(size > 0.0) {
690 return;
691 }
692 let ascent = self.text_metrics(size).ascent;
693 self.draw_text(text, (top_left.0, top_left.1 + ascent), size, color);
694 }
695
696 pub fn draw_text_weighted(
697 &mut self,
698 text: &str,
699 origin: (f32, f32),
700 size: f32,
701 weight: FontWeight,
702 color: Color,
703 ) {
704 let shaped = self.text.shape_weighted(text, size, weight);
705 self.text.draw(&shaped, origin, color, self.list);
706 }
707
708 pub fn draw_text_wrapped(
709 &mut self,
710 text: &str,
711 origin: (f32, f32),
712 size: f32,
713 weight: FontWeight,
714 width: f32,
715 mode: WrapMode,
716 color: Color,
717 ) {
718 self.draw_text_wrapped_spaced(text, origin, size, weight, width, mode, 0.0, color);
719 }
720
721 pub fn draw_text_wrapped_spaced(
722 &mut self,
723 text: &str,
724 origin: (f32, f32),
725 size: f32,
726 weight: FontWeight,
727 width: f32,
728 mode: WrapMode,
729 spacing: LetterSpacing,
730 color: Color,
731 ) {
732 let shaped = self
733 .text
734 .shape_wrapped_spaced(text, size, weight, width, mode, spacing);
735 self.text.draw(&shaped, origin, color, self.list);
736 }
737
738 pub fn draw_text_spaced(
739 &mut self,
740 text: &str,
741 origin: (f32, f32),
742 size: f32,
743 spacing: LetterSpacing,
744 color: Color,
745 ) {
746 self.draw_text_weighted_spaced(text, origin, size, FontWeight::NORMAL, spacing, color);
747 }
748
749 pub fn draw_text_weighted_spaced(
750 &mut self,
751 text: &str,
752 origin: (f32, f32),
753 size: f32,
754 weight: FontWeight,
755 spacing: LetterSpacing,
756 color: Color,
757 ) {
758 let shaped = self.text.shape_spaced(text, size, weight, spacing);
759 self.text.draw(&shaped, origin, color, self.list);
760 }
761
762 pub fn draw_text_styled_spaced(
763 &mut self,
764 text: &str,
765 origin: (f32, f32),
766 size: f32,
767 weight: FontWeight,
768 spacing: LetterSpacing,
769 family: Option<&str>,
770 style: FontStyle,
771 color: Color,
772 ) {
773 let shaped = self
774 .text
775 .shape_spaced_styled(text, size, weight, spacing, family, style);
776 self.text.draw(&shaped, origin, color, self.list);
777 }
778
779 pub fn draw_text_wrapped_styled_spaced(
780 &mut self,
781 text: &str,
782 origin: (f32, f32),
783 size: f32,
784 weight: FontWeight,
785 width: f32,
786 mode: WrapMode,
787 spacing: LetterSpacing,
788 family: Option<&str>,
789 style: FontStyle,
790 color: Color,
791 ) {
792 let shaped = self
793 .text
794 .shape_wrapped_styled_spaced(text, size, weight, width, mode, spacing, family, style);
795 self.text.draw(&shaped, origin, color, self.list);
796 }
797
798 #[allow(clippy::too_many_arguments)]
799 pub fn shape_wrapped_styled_spaced_lh(
800 &mut self,
801 text: &str,
802 size: f32,
803 weight: FontWeight,
804 width: f32,
805 mode: WrapMode,
806 spacing: LetterSpacing,
807 family: Option<&str>,
808 style: FontStyle,
809 line_height: LineHeight,
810 ) -> Rc<ShapedText> {
811 self.text.shape_wrapped_styled_spaced_lh(
812 text,
813 size,
814 weight,
815 width,
816 mode,
817 spacing,
818 family,
819 style,
820 line_height,
821 )
822 }
823
824 pub fn draw_shaped(&mut self, shaped: &ShapedText, origin: (f32, f32), color: Color) {
825 self.text.draw(shaped, origin, color, self.list);
826 }
827
828 #[allow(clippy::too_many_arguments)]
829 pub fn shape_rich_full_lh(
830 &mut self,
831 spans: &[TextSpan],
832 size: f32,
833 width: f32,
834 mode: WrapMode,
835 spacing: LetterSpacing,
836 align: RichAlign,
837 line_height: LineHeight,
838 ) -> Rc<RichParagraph> {
839 self.text
840 .shape_rich_full_lh(spans, size, width, mode, spacing, align, line_height)
841 }
842
843 #[allow(clippy::too_many_arguments)]
844 pub fn elide_lines_styled_spaced(
845 &mut self,
846 text: &str,
847 size: f32,
848 weight: FontWeight,
849 width: f32,
850 mode: WrapMode,
851 spacing: LetterSpacing,
852 family: Option<&str>,
853 style: FontStyle,
854 line_height: LineHeight,
855 max_lines: usize,
856 ) -> String {
857 self.text.elide_lines_styled_spaced(
858 text,
859 size,
860 weight,
861 width,
862 mode,
863 spacing,
864 family,
865 style,
866 line_height,
867 max_lines,
868 )
869 }
870
871 #[allow(clippy::too_many_arguments)]
872 pub fn elide_rich_lines(
873 &mut self,
874 spans: &[TextSpan],
875 size: f32,
876 width: f32,
877 mode: WrapMode,
878 spacing: LetterSpacing,
879 align: RichAlign,
880 line_height: LineHeight,
881 max_lines: usize,
882 ) -> Vec<TextSpan> {
883 self.text.elide_rich_lines(
884 spans,
885 size,
886 width,
887 mode,
888 spacing,
889 align,
890 line_height,
891 max_lines,
892 )
893 }
894
895 pub fn draw_rich(&mut self, rich: &RichParagraph, origin: (f32, f32), default_color: Color) {
896 self.text.draw_rich(rich, origin, default_color, self.list);
897 }
898
899 pub fn draw_rich_spans(
900 &mut self,
901 spans: &[TextSpan],
902 origin: (f32, f32),
903 size: f32,
904 width: f32,
905 mode: WrapMode,
906 spacing: LetterSpacing,
907 align: RichAlign,
908 default_color: Color,
909 ) {
910 let rich = self
911 .text
912 .shape_rich_full(spans, size, width, mode, spacing, align);
913 self.text.draw_rich(&rich, origin, default_color, self.list);
914 }
915
916 pub fn text_width(&mut self, text: &str, size: f32) -> f32 {
917 self.text.shape(text, size).width()
918 }
919
920 pub fn text_width_weighted(&mut self, text: &str, size: f32, weight: FontWeight) -> f32 {
921 self.text.shape_weighted(text, size, weight).width()
922 }
923
924 pub fn text_width_weighted_spaced(
925 &mut self,
926 text: &str,
927 size: f32,
928 weight: FontWeight,
929 spacing: LetterSpacing,
930 ) -> f32 {
931 self.text.shape_spaced(text, size, weight, spacing).width()
932 }
933
934 pub fn text_width_styled_spaced(
935 &mut self,
936 text: &str,
937 size: f32,
938 weight: FontWeight,
939 spacing: LetterSpacing,
940 family: Option<&str>,
941 style: FontStyle,
942 ) -> f32 {
943 self.text
944 .text_width_styled_spaced(text, size, weight, spacing, family, style)
945 }
946
947 pub fn elide_spaced(
948 &mut self,
949 text: &str,
950 size: f32,
951 weight: FontWeight,
952 max_width: f32,
953 mode: ElideMode,
954 spacing: LetterSpacing,
955 ) -> String {
956 self.text
957 .elide_spaced(text, size, weight, max_width, mode, spacing)
958 }
959
960 pub fn elide_styled_spaced(
961 &mut self,
962 text: &str,
963 size: f32,
964 weight: FontWeight,
965 max_width: f32,
966 mode: ElideMode,
967 spacing: LetterSpacing,
968 family: Option<&str>,
969 style: FontStyle,
970 ) -> String {
971 self.text
972 .elide_styled_spaced(text, size, weight, max_width, mode, spacing, family, style)
973 }
974
975 pub fn caret_positions(&mut self, text: &str, size: f32, weight: FontWeight) -> Vec<f32> {
976 self.text.caret_positions(text, size, weight)
977 }
978
979 pub fn caret_positions_spaced(
980 &mut self,
981 text: &str,
982 size: f32,
983 weight: FontWeight,
984 spacing: LetterSpacing,
985 ) -> Vec<f32> {
986 self.text
987 .caret_positions_spaced(text, size, weight, spacing)
988 }
989
990 pub fn shape_rich_full(
991 &mut self,
992 spans: &[TextSpan],
993 size: f32,
994 width: f32,
995 mode: WrapMode,
996 spacing: LetterSpacing,
997 align: RichAlign,
998 ) -> std::rc::Rc<RichParagraph> {
999 self.text
1000 .shape_rich_full(spans, size, width, mode, spacing, align)
1001 }
1002
1003 pub fn scale_factor(&self) -> f32 {
1004 self.text.scale_factor()
1005 }
1006
1007 pub fn request_frame(&self) {
1008 self.runtime.request_frame();
1009 }
1010
1011 pub fn live_color_exp(&self, prop: Prop, target: Color, rate: f32) -> Color {
1012 self.runtime
1013 .live_color_exp(self.element, prop, target, rate)
1014 .0
1015 }
1016
1017 pub fn draw_sprite(
1018 &mut self,
1019 key: u64,
1020 width: u32,
1021 height: u32,
1022 alpha: &[u8],
1023 rect: Rect,
1024 color: Color,
1025 ) {
1026 self.text
1027 .draw_sprite(key, width, height, alpha, rect, color, self.list);
1028 }
1029
1030 pub fn image(&mut self, rect: Rect, uv: [f32; 4], source: ImageSource) {
1031 self.list.push_image(rect, uv, source);
1032 }
1033
1034 pub fn show_overlay(&self, entry: OverlayEntry) -> OverlayId {
1035 self.runtime.overlay_show(entry.owned_by(self.element))
1036 }
1037
1038 pub fn hide_overlay(&self, id: OverlayId) -> bool {
1039 self.runtime.overlay_hide(id)
1040 }
1041
1042 pub fn has_overlay(&self, id: OverlayId) -> bool {
1043 self.runtime.overlay_exists(id)
1044 }
1045
1046 pub fn overlay_rect(&self, id: OverlayId) -> Option<Rect> {
1047 self.runtime.overlay_rect(id)
1048 }
1049
1050 pub fn drag_session(&self) -> Option<DragSession> {
1051 self.runtime.current_drag()
1052 }
1053
1054 pub fn is_drag_target(&self) -> bool {
1055 self.runtime.drag_target_contains(self.element)
1056 }
1057
1058 pub fn has_focus_within(&self) -> bool {
1059 self.runtime.focus_in_subtree(self.element)
1060 }
1061}
1062
1063pub trait CustomLayout {
1064 fn arrange(&self, rt: &Runtime, el: ElementId, rect: Rect, ctx: &mut LayoutCtx) -> bool;
1065}