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