1mod align;
32pub mod authoring;
33mod button;
34mod canvas;
35mod checkbox;
36mod container;
37mod divider;
38pub mod drag;
39pub mod either;
40mod flex;
41mod gesture;
42mod icon;
43mod icon_button;
44pub mod icons;
45mod image;
46mod indexed_stack;
47mod list_view;
48pub mod motion;
49pub mod nav;
50mod overlay;
51mod padding;
52mod pan_zoom;
53pub mod physics;
54pub mod pinch;
55mod platform_view;
56mod radio;
57mod repaint_boundary;
58mod safe_area;
59mod scaffold;
60mod scroll;
61pub mod scroll_controller;
62mod scroll_core;
63mod selection_toolbar;
64mod sized;
65mod slider;
66mod slivers;
67mod stack;
68mod text;
69mod textinput;
70mod texture_view;
71mod viewport;
72
73use std::hash::{Hash, Hasher};
74
75pub use align::{Align, AlignView, AlignWidget, Alignment};
76pub use button::{Button, ButtonStyle, ButtonView, ButtonWidget, button};
77pub use canvas::{CanvasView, CanvasWidget, canvas};
78pub use checkbox::{Checkbox, CheckboxView, CheckboxWidget, checkbox};
79pub use container::{BorderStyle, ContainerView, ContainerWidget, colored_box, container};
80pub use divider::{DividerView, DividerWidget, divider};
81pub use drag::{
82 AUTO_SCROLL_EDGE_PX, AUTO_SCROLL_MAX_PX_PER_S, AutoScroll, AutoScrollZone,
83 AutoScrollZoneWidget, DRAG_THRESHOLD, DragCoordinator, DragHighlight, DragKind, DragPhase,
84 DragPolicy, DragSession, DragSourceId, DragState, DragStateChange, DragSubscription,
85 DragTargetId, DragTargetView, DragTargetWidget, DraggableView, DraggableWidget, GHOST_OPACITY,
86 HIGHLIGHT_FALLBACK, ReorderableListView, SourceFeedback, auto_scroll_zone, drag_target,
87 draggable, reorderable_list,
88};
89pub use either::{
90 Either, EitherOf3, EitherOf3Widget, EitherOf4, EitherOf4Widget, EitherOf5, EitherOf5Widget,
91 EitherOf6, EitherOf6Widget, EitherOf7, EitherOf7Widget, EitherOf8, EitherOf8Widget,
92 EitherWidget, either,
93};
94pub use flex::{
95 Axis, Column, CrossAxisAlignment, FlexChild, FlexView, FlexWidget, MainAxisAlignment, Row,
96 column, flexible, inflexible, keyed, row,
97};
98pub use frust_core::ScrollAxis;
101pub use gesture::{GestureDetector, GestureDetectorView, GestureDetectorWidget};
102pub use icon::{Icon, IconData, IconSource, IconView, IconWidget, icon};
103pub use icon_button::{IconButton, IconButtonView, IconButtonWidget, icon_button};
104pub use image::{Image, ImageError, ImageFit, ImageSource, ImageView, ImageWidget};
105pub use indexed_stack::{IndexedStack, IndexedStackView, IndexedStackWidget, indexed_stack};
106pub use list_view::{ListView, ListViewWidget, list_view};
107pub use nav::hero::{HeroView, HeroWidget, hero};
108pub use nav::navigator::{
109 BackPolicy, NavigatorController, NavigatorId, NavigatorView, NavigatorWidget, PageBuilder,
110 PageVisibility, PopResult, PushOptions, ReplaceOptions, ResultCallback, RouteChangeCallback,
111 VisibilityCallback, navigator, overlay_host,
112};
113pub use nav::path::{Location, PathPattern, RouteParams};
114pub use nav::route::{NavRequest, NavWaker, RouteNavigator};
115pub use nav::route_state::{NavChange, RouteStack};
116pub use nav::router::{
117 DEFAULT_REDIRECT_LIMIT, ErrorBuilder, Redirect, Resolution, ResolvedPage, Route, RouteBuilder,
118 Router, shell_route,
119};
120pub use nav::transition::{PageTransition, Timing, TransitionSpec, TransitionState};
121pub use overlay::{
122 DEFAULT_OFFSET, DEFAULT_PADDING, OverlayAlign, OverlayAnchor, OverlayPlacement,
123 OverlayPortalView, OverlayPortalWidget, OverlaySide, OverlaySlot, overlay_portal, place,
124};
125pub use padding::{EdgeInsets, Padding, PaddingView, PaddingWidget};
126pub use pan_zoom::{
127 DEFAULT_MAX_SCALE, DEFAULT_MIN_SCALE, PanZoomController, PanZoomTransform, PanZoomView,
128 PanZoomWidget, pan_zoom,
129};
130pub use physics::effect::OverscrollEffect;
131pub use physics::parity::{
132 AlwaysScrollable, Bouncing, Clamping, DecelerationRate, NeverScrollable,
133};
134pub use physics::rubber_band::RubberBand;
135pub use physics::{
136 MAX_FLING_VELOCITY, MIN_FLING_VELOCITY, ScrollMetrics, ScrollPhysics, Simulation,
137 SpringDescription, Tolerance,
138};
139pub use pinch::{
140 PINCH_SLOP, PinchDetectorView, PinchDetectorWidget, PinchRecognizer, pinch_detector,
141};
142pub use platform_view::{
143 PlatformViewView, PlatformViewWidget, ShieldView, ShieldWidget, platform_view, shield,
144};
145pub use radio::{Radio, RadioView, RadioWidget, radio};
146pub use repaint_boundary::{RepaintBoundaryView, RepaintBoundaryWidget, repaint_boundary};
147pub use safe_area::{SafeAreaView, SafeAreaWidget, safe_area};
148pub use scaffold::{ScaffoldView, ScaffoldWidget, scaffold};
149pub use scroll::{ScrollInfo, ScrollView, ScrollWidget, scroll_view};
150pub use scroll_controller::{AnimateTo, ScrollController, ScrollSubscription};
151pub use selection_toolbar::selection_toolbar;
152pub use sized::{SizedBox, SizedBoxView, SizedBoxWidget};
153pub use slider::{Slider, SliderView, SliderWidget, slider};
154pub use slivers::{
155 KeepAliveHandle, KeepAliveView, KeepAliveWidget, SliverBoxView, SliverBoxWidget,
156 SliverFillRemainingView, SliverFillRemainingWidget, SliverFixedExtentListView,
157 SliverFixedExtentListWidget, SliverGridDelegate, SliverGridView, SliverGridWidget,
158 SliverListView, SliverListWidget, SliverPaddingView, SliverPaddingWidget,
159 SliverPersistentHeaderDelegate, SliverPersistentHeaderView, SliverPersistentHeaderWidget,
160 keep_alive, sliver_box, sliver_fill_remaining, sliver_fixed_extent_list,
161 sliver_fixed_extent_list_keyed, sliver_grid, sliver_grid_keyed, sliver_list, sliver_padding,
162 sliver_persistent_header,
163};
164pub use stack::{Stack, StackView, StackWidget, stack};
165pub use text::{TextView, TextWidget, text};
166pub use textinput::{TextInput, TextInputView, TextInputWidget, text_input};
167pub use texture_view::{TextureFit, TextureView, TextureWidget, texture_fit_rect, texture_view};
168pub use viewport::{CustomScrollView, DEFAULT_CACHE_EXTENT, ViewportWidget, custom_scroll_view};
169
170#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
181pub struct ChildKey(u64);
182
183impl ChildKey {
184 pub fn new(value: impl Hash) -> Self {
187 let mut hasher = std::collections::hash_map::DefaultHasher::new();
188 value.hash(&mut hasher);
189 ChildKey(hasher.finish())
190 }
191}
192
193macro_rules! child_key_from {
194 ($($t:ty),* $(,)?) => {
195 $(
196 impl From<$t> for ChildKey {
197 fn from(value: $t) -> Self {
198 ChildKey::new(value)
199 }
200 }
201 )*
202 };
203}
204
205child_key_from!(
209 u8, u16, u32, u64, usize, i8, i16, i32, i64, isize, char, &str, String
210);
211
212#[cfg(any(test, feature = "test-support"))]
223pub mod test_support {
224 use frust_core::{
225 AnyView, BoxConstraints, BuildCtx, ChangeFlags, EventCtx, EventResult, InputEvent,
226 LayoutCtx, PaintCtx, PaintScene, View, Widget, any,
227 };
228 use kurbo::{Affine, Point, Size};
229 use peniko::Color;
230
231 pub struct Leaf {
233 intrinsic: Size,
234 }
235
236 pub fn leaf(width: f64, height: f64) -> Leaf {
238 Leaf {
239 intrinsic: Size::new(width, height),
240 }
241 }
242
243 pub fn leaf_any(width: f64, height: f64) -> AnyView<()> {
245 any(leaf(width, height))
246 }
247
248 impl Leaf {
249 pub fn into_any(self) -> AnyView<()> {
251 any(self)
252 }
253 }
254
255 pub struct LeafWidget {
257 intrinsic: Size,
258 }
259
260 impl View<()> for Leaf {
261 type Element = LeafWidget;
262 fn build(&self, _ctx: &mut BuildCtx<'_>) -> LeafWidget {
263 LeafWidget {
264 intrinsic: self.intrinsic,
265 }
266 }
267 fn rebuild(
268 &self,
269 prev: &Self,
270 element: &mut LeafWidget,
271 _ctx: &mut BuildCtx<'_>,
272 ) -> ChangeFlags {
273 if prev.intrinsic != self.intrinsic {
274 element.intrinsic = self.intrinsic;
275 ChangeFlags::LAYOUT
276 } else {
277 ChangeFlags::NONE
278 }
279 }
280 }
281
282 impl Widget for LeafWidget {
283 fn layout(&mut self, _ctx: &mut LayoutCtx, bc: &BoxConstraints) -> Size {
284 bc.constrain(self.intrinsic)
285 }
286 fn paint(&mut self, ctx: &mut PaintCtx, scene: &mut dyn PaintScene) {
287 scene.fill_rect(ctx.origin(), ctx.size(), Color::BLACK);
288 }
289 }
290
291 pub struct SwapLeaf;
294
295 pub fn swap_leaf() -> SwapLeaf {
297 SwapLeaf
298 }
299
300 impl SwapLeaf {
301 pub fn into_any(self) -> AnyView<()> {
303 any(self)
304 }
305 }
306
307 pub struct SwapLeafWidget;
309
310 impl View<()> for SwapLeaf {
311 type Element = SwapLeafWidget;
312 fn build(&self, _ctx: &mut BuildCtx<'_>) -> SwapLeafWidget {
313 SwapLeafWidget
314 }
315 fn rebuild(
316 &self,
317 _prev: &Self,
318 _element: &mut SwapLeafWidget,
319 _ctx: &mut BuildCtx<'_>,
320 ) -> ChangeFlags {
321 ChangeFlags::NONE
322 }
323 }
324
325 impl Widget for SwapLeafWidget {
326 fn layout(&mut self, _ctx: &mut LayoutCtx, bc: &BoxConstraints) -> Size {
327 bc.constrain(Size::new(7.0, 7.0))
328 }
329 fn paint(&mut self, _ctx: &mut PaintCtx, _scene: &mut dyn PaintScene) {}
330 }
331
332 pub struct Probe {
336 id: u32,
337 }
338
339 pub fn probe(id: u32) -> Probe {
341 Probe { id }
342 }
343
344 impl Probe {
345 pub fn into_any(self) -> AnyView<Vec<u32>> {
347 any(self)
348 }
349 }
350
351 pub struct ProbeWidget {
353 id: u32,
354 }
355
356 impl View<Vec<u32>> for Probe {
357 type Element = ProbeWidget;
358 fn build(&self, _ctx: &mut BuildCtx<'_>) -> ProbeWidget {
359 ProbeWidget { id: self.id }
360 }
361 fn rebuild(
362 &self,
363 _prev: &Self,
364 _element: &mut ProbeWidget,
365 _ctx: &mut BuildCtx<'_>,
366 ) -> ChangeFlags {
367 ChangeFlags::NONE
368 }
369 }
370
371 impl Widget for ProbeWidget {
372 fn layout(&mut self, _ctx: &mut LayoutCtx, bc: &BoxConstraints) -> Size {
373 bc.max()
374 }
375 fn paint(&mut self, _ctx: &mut PaintCtx, _scene: &mut dyn PaintScene) {}
376 fn event(&mut self, ctx: &mut EventCtx, _event: &InputEvent) -> EventResult {
377 ctx.state_mut::<Vec<u32>>().push(self.id);
378 ctx.request_redraw();
379 EventResult::Handled
380 }
381 }
382
383 #[derive(Default)]
388 pub struct RecordingScene {
389 pub rects: Vec<(Point, Size)>,
390 pub layers: Vec<(Point, Size, f32)>,
391 pub layer_pops: u32,
392 pub transforms: Vec<Affine>,
393 pub transform_pops: u32,
394 }
395
396 impl PaintScene for RecordingScene {
397 fn fill_rect(&mut self, origin: Point, size: Size, _color: Color) {
398 self.rects.push((origin, size));
399 }
400 fn draw_text(&mut self, _origin: Point, _text: &str) {}
401 fn push_layer(&mut self, origin: Point, size: Size, alpha: f32) {
402 self.layers.push((origin, size, alpha));
403 }
404 fn pop_layer(&mut self) {
405 self.layer_pops += 1;
406 }
407 fn push_transform(&mut self, transform: Affine) {
408 self.transforms.push(transform);
409 }
410 fn pop_transform(&mut self) {
411 self.transform_pops += 1;
412 }
413 }
414}