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