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