1use crate::bindings::ui;
2use crate::drawing::DrawContext;
3use crate::event::{
4 FocusChangedEventArgs, GestureEventArgs, KeyEventArgs, LongPressEventArgs, PointerEventArgs,
5 PointerType, SelectionChangedEventArgs, TextChangedEventArgs, WheelEventArgs,
6 DEFAULT_LONG_PRESS_MINIMUM_DURATION_MS, DEFAULT_LONG_PRESS_MOVEMENT_TOLERANCE,
7};
8use crate::ffi::{
9 AlignItems, AlignSelf, BorderStyle, CursorStyle, FlexDirection, FlexWrap, GridUnit,
10 HandleValue, ImageSamplingKind, JustifyContent, NodeType, ObjectFit, Orientation, PositionType,
11 SemanticCheckedState, SemanticRole, TextAlign, TextOverflow, TextVerticalAlign, Unit,
12 Visibility,
13};
14use crate::theme;
15use crate::transitions::NodeTransitions;
16use crate::typography::{FontFamily, FontStack, FontStyle, FontWeight};
17use std::any::Any;
18use std::cell::RefCell;
19use std::rc::{Rc, Weak};
20
21mod core;
22mod custom_drawable;
23mod flex_box;
24mod grid;
25mod helpers;
26mod image;
27mod presenter_host_style;
28mod scroll_bar;
29mod scroll_box;
30mod scroll_state;
31mod scroll_view;
32mod svg_node;
33mod text_node;
34mod virtual_list;
35
36#[doc(hidden)]
37pub use core::NodeRef;
38pub use core::{ContextMenuEventArgs, Node, NodeHandle};
39pub(crate) use core::{WeakFlexBox, WeakNodeRef};
40pub use custom_drawable::{CustomDrawable, DrawableInvalidator};
41pub use flex_box::{Border, FlexBox, GradientStop};
42pub use grid::{Grid, GridTrack};
43pub(crate) use helpers::*;
44pub use helpers::{
45 auto, column, custom_drawable, fill, flex_box, grid, image, pct, portal, px, row, scroll_box,
46 scroll_view, svg, text, viewport_height, viewport_width, virtual_list, Length,
47};
48pub use image::ImageNode;
49pub(crate) use presenter_host_style::HostStyleLayers;
50pub use presenter_host_style::{Corners, EdgeInsets, PresenterHostStyle, Shadow};
51pub use scroll_bar::{ScrollBar, ScrollBarStyle, ScrollBarVisibility};
52pub use scroll_box::ScrollBox;
53pub use scroll_state::ScrollState;
54pub use scroll_view::ScrollView;
55pub use svg_node::SvgNode;
56pub use text_node::TextNode;
57pub use virtual_list::VirtualList;
58
59pub type Image = ImageNode;
60pub type Portal = FlexBox;
61pub type Svg = SvgNode;
62pub type Text = TextNode;
63
64pub trait HasFlexBoxRoot {
65 fn flex_box_root(&self) -> &FlexBox;
66
67 #[doc(hidden)]
68 fn set_flex_box_surface_width(&self, value: f32, unit: Unit) {
69 self.flex_box_root().width(value, unit);
70 }
71
72 #[doc(hidden)]
73 fn set_flex_box_surface_height(&self, value: f32, unit: Unit) {
74 self.flex_box_root().height(value, unit);
75 }
76
77 #[doc(hidden)]
78 fn append_flex_box_surface_child(&self, child: NodeRef) {
79 self.flex_box_root()
80 .retained_node_ref()
81 .append_child_ref(&child);
82 }
83}
84
85pub trait ThemeBindable: Sized + 'static {
86 #[doc(hidden)]
87 fn theme_binding_node(&self) -> NodeRef;
88
89 #[doc(hidden)]
90 fn weak_theme_target(&self) -> Box<dyn Fn() -> Option<Self>>;
91
92 fn bind_theme(&self, handler: impl Fn(&Self, crate::theme::Theme) + 'static) -> &Self {
93 let target = self.weak_theme_target();
94 let guard = crate::theme::subscribe(move |theme| {
95 if let Some(control) = target() {
96 handler(&control, theme);
97 }
98 });
99 self.theme_binding_node().retain_attachment(Rc::new(guard));
100 self
101 }
102}
103
104impl HasFlexBoxRoot for FlexBox {
105 fn flex_box_root(&self) -> &FlexBox {
106 self
107 }
108}
109
110impl ThemeBindable for FlexBox {
111 fn theme_binding_node(&self) -> NodeRef {
112 self.retained_node_ref()
113 }
114
115 fn weak_theme_target(&self) -> Box<dyn Fn() -> Option<Self>> {
116 let weak = self.downgrade();
117 Box::new(move || weak.upgrade())
118 }
119}
120
121pub trait HasTextNode {
122 fn text_node(&self) -> &TextNode;
123
124 #[doc(hidden)]
125 fn set_text_surface_content(&self, content: String) {
126 self.text_node().text(content);
127 }
128
129 #[doc(hidden)]
130 fn set_text_surface_font_stack(&self, stack: FontStack, size: f32) {
131 self.text_node().font_stack(stack, size);
132 }
133
134 #[doc(hidden)]
135 fn set_text_surface_font_family(&self, family: FontFamily) {
136 self.text_node().font_family(family);
137 }
138
139 #[doc(hidden)]
140 fn set_text_surface_font_weight(&self, weight: FontWeight) {
141 self.text_node().font_weight(weight);
142 }
143
144 #[doc(hidden)]
145 fn set_text_surface_font_style(&self, style: FontStyle) {
146 self.text_node().font_style(style);
147 }
148
149 #[doc(hidden)]
150 fn set_text_surface_font_size(&self, size: f32) {
151 self.text_node().font_size(size);
152 }
153
154 #[doc(hidden)]
155 fn set_text_surface_color(&self, color: u32) {
156 self.text_node().text_color(color);
157 }
158}
159
160pub trait TextLayoutSurface: HasTextNode {
161 fn width(&self, width: f32, unit: Unit) -> &Self {
162 self.text_node().width(width, unit);
163 self
164 }
165
166 fn height(&self, height: f32, unit: Unit) -> &Self {
167 self.text_node().height(height, unit);
168 self
169 }
170
171 fn width_len(&self, length: Length) -> &Self {
172 let (value, unit) = length;
173 self.text_node().width(value, unit);
174 self
175 }
176
177 fn height_len(&self, length: Length) -> &Self {
178 let (value, unit) = length;
179 self.text_node().height(value, unit);
180 self
181 }
182
183 fn fill_width(&self) -> &Self {
184 self.text_node().fill_width();
185 self
186 }
187
188 fn fill_height(&self) -> &Self {
189 self.text_node().fill_height();
190 self
191 }
192
193 fn fill_size(&self) -> &Self {
194 self.text_node().fill_size();
195 self
196 }
197
198 fn fill_width_percent(&self, percent: f32) -> &Self {
199 self.text_node().fill_width_percent(percent);
200 self
201 }
202
203 fn fill_height_percent(&self, percent: f32) -> &Self {
204 self.text_node().fill_height_percent(percent);
205 self
206 }
207
208 fn min_width(&self, value: f32, unit: Unit) -> &Self {
209 self.text_node().min_width(value, unit);
210 self
211 }
212
213 fn max_width(&self, value: f32, unit: Unit) -> &Self {
214 self.text_node().max_width(value, unit);
215 self
216 }
217
218 fn min_height(&self, value: f32, unit: Unit) -> &Self {
219 self.text_node().min_height(value, unit);
220 self
221 }
222
223 fn max_height(&self, value: f32, unit: Unit) -> &Self {
224 self.text_node().max_height(value, unit);
225 self
226 }
227
228 fn text_align(&self, align: TextAlign) -> &Self {
229 self.text_node().text_align(align);
230 self
231 }
232
233 fn text_vertical_align(&self, align: TextVerticalAlign) -> &Self {
234 self.text_node().text_vertical_align(align);
235 self
236 }
237
238 fn text_limits(&self, max_chars: i32, max_lines: i32) -> &Self {
239 self.text_node().text_limits(max_chars, max_lines);
240 self
241 }
242
243 fn max_lines(&self, max_lines: i32) -> &Self {
244 self.text_node().max_lines(max_lines);
245 self
246 }
247
248 fn wrapping(&self, wrap: bool) -> &Self {
249 self.text_node().wrapping(wrap);
250 self
251 }
252
253 fn text_overflow(&self, overflow: TextOverflow) -> &Self {
254 self.text_node().text_overflow(overflow);
255 self
256 }
257
258 fn text_overflow_fade(&self, horizontal: bool, vertical: bool) -> &Self {
259 self.text_node().text_overflow_fade(horizontal, vertical);
260 self
261 }
262}
263
264impl<T: HasTextNode> TextLayoutSurface for T {}
265
266pub trait TextContentSurface: HasTextNode {
267 fn text(&self, content: impl Into<String>) -> &Self {
268 self.set_text_surface_content(content.into());
269 self
270 }
271
272 fn content(&self) -> String {
273 self.text_node().content()
274 }
275}
276
277impl<T: HasTextNode> TextContentSurface for T {}
278
279pub trait TextTypographySurface: HasTextNode {
280 fn font_stack(&self, stack: FontStack, size: f32) -> &Self {
281 self.set_text_surface_font_stack(stack, size);
282 self
283 }
284
285 fn font_family(&self, family: FontFamily) -> &Self {
286 self.set_text_surface_font_family(family);
287 self
288 }
289
290 fn font_weight(&self, weight: FontWeight) -> &Self {
291 self.set_text_surface_font_weight(weight);
292 self
293 }
294
295 fn font_style(&self, style: FontStyle) -> &Self {
296 self.set_text_surface_font_style(style);
297 self
298 }
299
300 fn font_size(&self, size: f32) -> &Self {
301 self.set_text_surface_font_size(size);
302 self
303 }
304
305 fn line_height(&self, line_height: f32) -> &Self {
306 self.text_node().line_height(line_height);
307 self
308 }
309
310 fn text_color(&self, color: u32) -> &Self {
311 self.set_text_surface_color(color);
312 self
313 }
314}
315
316impl<T: HasTextNode> TextTypographySurface for T {}
317
318pub trait TextSelectionSurface: HasTextNode {
319 fn uses_default_selection_behavior(&self) -> bool {
320 self.text_node().uses_default_selection_behavior()
321 }
322
323 fn is_selectable_text(&self) -> bool {
324 self.text_node().is_selectable_text()
325 }
326
327 fn selection_start(&self) -> u32 {
328 self.text_node().selection_start()
329 }
330
331 fn selection_end(&self) -> u32 {
332 self.text_node().selection_end()
333 }
334
335 fn selectable(&self, selectable: bool) -> &Self {
336 self.text_node().selectable(selectable);
337 self
338 }
339
340 fn selection_color(&self, color: u32) -> &Self {
341 self.text_node().selection_color(color);
342 self
343 }
344
345 fn selection_range(&self, start: u32, end: u32) -> &Self {
346 self.text_node().selection_range(start, end);
347 self
348 }
349
350 fn caret_color(&self, color: u32) -> &Self {
351 self.text_node().caret_color(color);
352 self
353 }
354}
355
356impl<T: HasTextNode> TextSelectionSurface for T {}
357
358pub trait TextEditingSurface: HasTextNode {
359 fn is_editable_text(&self) -> bool {
360 self.text_node().is_editable_text()
361 }
362
363 fn editable(&self, editable: bool) -> &Self {
364 self.text_node().editable(editable);
365 self
366 }
367
368 fn obscured(&self, obscured: bool) -> &Self {
369 self.text_node().obscured(obscured);
370 self
371 }
372}
373
374impl<T: HasTextNode> TextEditingSurface for T {}
375
376pub trait TextEventSurface: HasTextNode {
377 fn on_text_changed(&self, handler: impl Fn(TextChangedEventArgs) + 'static) -> &Self {
378 self.text_node().on_text_changed(handler);
379 self
380 }
381
382 fn on_selection_changed(&self, handler: impl Fn(SelectionChangedEventArgs) + 'static) -> &Self {
383 self.text_node().on_selection_changed(handler);
384 self
385 }
386}
387
388impl<T: HasTextNode> TextEventSurface for T {}
389
390pub trait TextSurface:
391 TextLayoutSurface
392 + TextContentSurface
393 + TextTypographySurface
394 + TextSelectionSurface
395 + TextEditingSurface
396 + TextEventSurface
397{
398}
399
400impl<T> TextSurface for T where
401 T: TextLayoutSurface
402 + TextContentSurface
403 + TextTypographySurface
404 + TextSelectionSurface
405 + TextEditingSurface
406 + TextEventSurface
407{
408}
409
410impl HasTextNode for TextNode {
411 fn text_node(&self) -> &TextNode {
412 self
413 }
414}
415
416pub trait LayoutSurface {
417 #[doc(hidden)]
418 fn layout_surface_root(&self) -> &FlexBox;
419
420 #[doc(hidden)]
421 fn set_layout_surface_width(&self, value: f32, unit: Unit);
422
423 #[doc(hidden)]
424 fn set_layout_surface_height(&self, value: f32, unit: Unit);
425
426 fn width(&self, width: f32, unit: Unit) -> &Self {
427 self.set_layout_surface_width(width, unit);
428 self
429 }
430
431 fn width_len(&self, length: Length) -> &Self {
432 let (value, unit) = length;
433 self.set_layout_surface_width(value, unit);
434 self
435 }
436
437 fn height(&self, height: f32, unit: Unit) -> &Self {
438 self.set_layout_surface_height(height, unit);
439 self
440 }
441
442 fn height_len(&self, length: Length) -> &Self {
443 let (value, unit) = length;
444 self.set_layout_surface_height(value, unit);
445 self
446 }
447
448 fn fill_width(&self) -> &Self {
449 self.layout_surface_root().fill_width();
450 self
451 }
452
453 fn fill_height(&self) -> &Self {
454 self.layout_surface_root().fill_height();
455 self
456 }
457
458 fn fill_size(&self) -> &Self {
459 self.layout_surface_root().fill_size();
460 self
461 }
462
463 fn fill_width_percent(&self, percent: f32) -> &Self {
464 self.layout_surface_root().fill_width_percent(percent);
465 self
466 }
467
468 fn fill_height_percent(&self, percent: f32) -> &Self {
469 self.layout_surface_root().fill_height_percent(percent);
470 self
471 }
472
473 fn min_width(&self, value: f32, unit: Unit) -> &Self {
474 self.layout_surface_root().min_width(value, unit);
475 self
476 }
477
478 fn min_width_len(&self, length: Length) -> &Self {
479 self.layout_surface_root().min_width_len(length);
480 self
481 }
482
483 fn max_width(&self, value: f32, unit: Unit) -> &Self {
484 self.layout_surface_root().max_width(value, unit);
485 self
486 }
487
488 fn max_width_len(&self, length: Length) -> &Self {
489 self.layout_surface_root().max_width_len(length);
490 self
491 }
492
493 fn min_height(&self, value: f32, unit: Unit) -> &Self {
494 self.layout_surface_root().min_height(value, unit);
495 self
496 }
497
498 fn min_height_len(&self, length: Length) -> &Self {
499 self.layout_surface_root().min_height_len(length);
500 self
501 }
502
503 fn max_height(&self, value: f32, unit: Unit) -> &Self {
504 self.layout_surface_root().max_height(value, unit);
505 self
506 }
507
508 fn max_height_len(&self, length: Length) -> &Self {
509 self.layout_surface_root().max_height_len(length);
510 self
511 }
512
513 fn margin(&self, left: f32, top: f32, right: f32, bottom: f32) -> &Self {
514 self.layout_surface_root().margin(left, top, right, bottom);
515 self
516 }
517
518 fn position_type(&self, position_type: PositionType) -> &Self {
519 self.layout_surface_root().position_type(position_type);
520 self
521 }
522
523 fn position_absolute(&self) -> &Self {
524 self.layout_surface_root()
525 .position_type(PositionType::Absolute);
526 self
527 }
528
529 fn position(&self, left: f32, top: f32) -> &Self {
530 self.layout_surface_root().position(left, top);
531 self
532 }
533}
534
535impl<T: HasFlexBoxRoot> LayoutSurface for T {
536 fn layout_surface_root(&self) -> &FlexBox {
537 self.flex_box_root()
538 }
539
540 fn set_layout_surface_width(&self, value: f32, unit: Unit) {
541 self.set_flex_box_surface_width(value, unit);
542 }
543
544 fn set_layout_surface_height(&self, value: f32, unit: Unit) {
545 self.set_flex_box_surface_height(value, unit);
546 }
547}
548
549pub trait BoxStyleSurface {
550 #[doc(hidden)]
551 fn box_style_surface_root(&self) -> &FlexBox;
552
553 fn interactive(&self, interactive: bool) -> &Self {
554 self.box_style_surface_root().interactive(interactive);
555 self
556 }
557
558 fn padding(&self, left: f32, top: f32, right: f32, bottom: f32) -> &Self {
559 self.box_style_surface_root()
560 .padding(left, top, right, bottom);
561 self
562 }
563
564 fn clear_padding(&self) -> &Self {
565 self.box_style_surface_root().clear_padding();
566 self
567 }
568
569 fn corner_radius(&self, radius: f32) -> &Self {
570 self.box_style_surface_root().corner_radius(radius);
571 self
572 }
573
574 fn clear_corners(&self) -> &Self {
575 self.box_style_surface_root().clear_corners();
576 self
577 }
578
579 fn corners(&self, tl: f32, tr: f32, br: f32, bl: f32) -> &Self {
580 self.box_style_surface_root().corners(tl, tr, br, bl);
581 self
582 }
583
584 fn border(&self, width: f32, color: u32) -> &Self {
585 self.box_style_surface_root().border(width, color);
586 self
587 }
588
589 fn border_config(&self, border: Border) -> &Self {
590 self.box_style_surface_root().border_config(border);
591 self
592 }
593
594 fn clear_border(&self) -> &Self {
595 self.box_style_surface_root().clear_border();
596 self
597 }
598
599 fn bg_color(&self, color: u32) -> &Self {
600 self.box_style_surface_root().bg_color(color);
601 self
602 }
603
604 fn clear_bg_color(&self) -> &Self {
605 self.box_style_surface_root().clear_bg_color();
606 self
607 }
608
609 fn opacity(&self, value: f32) -> &Self {
610 self.box_style_surface_root().opacity(value);
611 self
612 }
613
614 fn clear_opacity(&self) -> &Self {
615 self.box_style_surface_root().clear_opacity();
616 self
617 }
618
619 fn blur(&self, sigma: f32) -> &Self {
620 self.box_style_surface_root().blur(sigma);
621 self
622 }
623
624 fn drop_shadow(
625 &self,
626 color: u32,
627 offset_x: f32,
628 offset_y: f32,
629 blur_sigma: f32,
630 spread: f32,
631 ) -> &Self {
632 self.box_style_surface_root()
633 .drop_shadow(color, offset_x, offset_y, blur_sigma, spread);
634 self
635 }
636
637 fn clear_drop_shadow(&self) -> &Self {
638 self.box_style_surface_root().clear_drop_shadow();
639 self
640 }
641
642 fn background_blur(&self, sigma: f32) -> &Self {
643 self.box_style_surface_root().background_blur(sigma);
644 self
645 }
646
647 fn linear_gradient(
648 &self,
649 start_x: f32,
650 start_y: f32,
651 end_x: f32,
652 end_y: f32,
653 offsets: Vec<f32>,
654 colors: Vec<u32>,
655 ) -> &Self {
656 self.box_style_surface_root()
657 .linear_gradient(start_x, start_y, end_x, end_y, offsets, colors);
658 self
659 }
660
661 fn linear_gradient_stops(
662 &self,
663 start_x: f32,
664 start_y: f32,
665 end_x: f32,
666 end_y: f32,
667 stops: Vec<GradientStop>,
668 ) -> &Self {
669 self.box_style_surface_root()
670 .linear_gradient_stops(start_x, start_y, end_x, end_y, stops);
671 self
672 }
673
674 fn transitions(&self, transitions: Option<NodeTransitions>) -> &Self {
675 self.box_style_surface_root().transitions(transitions);
676 self
677 }
678
679 fn clip_to_bounds(&self, clip: bool) -> &Self {
680 self.box_style_surface_root().clip_to_bounds(clip);
681 self
682 }
683}
684
685impl<T: HasFlexBoxRoot> BoxStyleSurface for T {
686 fn box_style_surface_root(&self) -> &FlexBox {
687 self.flex_box_root()
688 }
689}
690
691pub trait FlexLayoutSurface {
692 #[doc(hidden)]
693 fn flex_layout_surface_root(&self) -> &FlexBox;
694
695 fn flex_direction(&self, direction: FlexDirection) -> &Self {
696 self.flex_layout_surface_root().flex_direction(direction);
697 self
698 }
699
700 fn flex_basis(&self, basis: f32) -> &Self {
701 self.flex_layout_surface_root().flex_basis(basis);
702 self
703 }
704
705 fn justify_content(&self, justify: JustifyContent) -> &Self {
706 self.flex_layout_surface_root().justify_content(justify);
707 self
708 }
709
710 fn clear_justify_content(&self) -> &Self {
711 self.flex_layout_surface_root().clear_justify_content();
712 self
713 }
714
715 fn align_items(&self, align: AlignItems) -> &Self {
716 self.flex_layout_surface_root().align_items(align);
717 self
718 }
719
720 fn clear_align_items(&self) -> &Self {
721 self.flex_layout_surface_root().clear_align_items();
722 self
723 }
724
725 fn align_self(&self, align: AlignSelf) -> &Self {
726 self.flex_layout_surface_root().align_self(align);
727 self
728 }
729
730 fn flex_wrap(&self, wrap: FlexWrap) -> &Self {
731 self.flex_layout_surface_root().flex_wrap(wrap);
732 self
733 }
734}
735
736impl<T: HasFlexBoxRoot> FlexLayoutSurface for T {
737 fn flex_layout_surface_root(&self) -> &FlexBox {
738 self.flex_box_root()
739 }
740}
741
742pub trait ChildContainerSurface {
750 #[doc(hidden)]
751 fn append_surface_child(&self, child: NodeRef);
752
753 fn child<T: Node>(&self, child: &T) -> &Self {
754 self.append_surface_child(child.retained_node_ref());
755 self
756 }
757
758 fn children<I, C>(&self, children: I) -> &Self
759 where
760 I: IntoIterator<Item = C>,
761 C: Into<Child>,
762 {
763 for child in children {
764 self.append_surface_child(child.into().node_ref);
765 }
766 self
767 }
768}
769
770impl<T: HasFlexBoxRoot> ChildContainerSurface for T {
771 fn append_surface_child(&self, child: NodeRef) {
772 self.append_flex_box_surface_child(child);
773 }
774}
775
776pub trait FlexBoxSurface:
777 LayoutSurface + BoxStyleSurface + FlexLayoutSurface + ChildContainerSurface
778{
779}
780
781impl<T> FlexBoxSurface for T where
782 T: LayoutSurface + BoxStyleSurface + FlexLayoutSurface + ChildContainerSurface
783{
784}
785
786#[derive(Clone)]
787pub struct Child {
788 pub(crate) node_ref: NodeRef,
789}
790
791impl Child {
792 pub fn from_node<T: Node>(value: &T) -> Self {
793 Self {
794 node_ref: value.retained_node_ref(),
795 }
796 }
797}
798
799impl<T: Node> From<T> for Child {
800 fn from(value: T) -> Self {
801 Self {
802 node_ref: value.retained_node_ref(),
803 }
804 }
805}