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