cranpose-ui 0.1.171

UI primitives for Cranpose
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
//! High level UI primitives built on top of the Compose core runtime.

use std::{
    ops::{Deref, DerefMut},
    rc::Rc,
};

use cranpose_core::{ApplierGuard, MemoryApplier, NodeError, NodeId, RuntimeHandle, location_key};
pub use cranpose_core::{Composition, Key};
pub use cranpose_macros::composable;

pub mod announce;
pub mod bring_into_view;
pub mod clipboard_session;
mod cursor_animation;
mod debug;
pub mod density;
pub mod draggable;
mod draw;
pub mod fling_animation;
mod focus_dispatch;
pub mod focus_manager;
mod focus_navigation;
pub mod focus_order;
pub mod font_scale;
mod interaction;
mod key_event;
pub mod layout;
pub mod layout_direction;
pub mod lazy_item;
mod lazy_prefetch;
pub mod modal;
mod modifier;
mod modifier_nodes;
pub mod nine_patch;
mod pointer_dispatch;
pub mod pointer_icon_session;
mod primitives;
mod render_state;
mod renderer;
pub mod round_scaling_list;
pub mod round_scroll_indicator;
pub mod safe_area;
pub mod scroll;
pub mod scrollbar;
pub mod selection_container;
mod semantics_dispatch;
mod subcompose_layout;
pub mod text;
mod text_field_decorator_node;
pub mod text_field_focus;
mod text_field_handler;
mod text_field_input;
mod text_field_modifier_node;
pub mod text_input_session;
pub mod text_layout_result;
mod text_modifier_node;
pub mod text_selection;
mod unhandled_keys;
pub mod widgets;
mod word_boundaries;
pub mod zoom;

#[doc(hidden)]
pub use announce::{Announcement, Announcer, announce, drain_announcements, local_announcer};
pub use bring_into_view::{
    BringIntoViewResponder, local_bring_into_view_responder, scroll_delta_to_reveal,
};
pub use cranpose_foundation::{
    CanvasSemanticsNode, CollectionInfo, DelegatableNode, LiveRegionMode, ModifierNode,
    ModifierNodeElement, NodeCapabilities, NodeState, ProgressBarRangeInfo, ScrollAxisRange,
    SemanticsConfiguration, SemanticsCustomAction, SemanticsDismiss, SemanticsExpand,
    SemanticsLongClick, SemanticsMagicTap, SemanticsScrollBy, SemanticsScrollToIndex,
    SemanticsSetProgress, SemanticsSetSelection, SemanticsSetText, SemanticsSpec,
    SemanticsWidgetRole,
    lazy::{
        LazyItems, LazyListItemInfo, LazyListLayoutInfo, LazyListScope, LazyListState,
        rememberLazyListState, rememberLazyListStateWithPosition,
    },
    text::{TextFieldBuffer, TextFieldLineLimits, TextFieldState, TextFieldValue, TextRange},
};
pub use cranpose_ui_graphics::{
    BlurredEdgeTreatment, ColorFilter, CursorIcon, CustomPointerIcon, Dp, ImageBitmap,
    ImageSampling, PointerIcon, PointerIconError,
};
pub use cranpose_ui_layout::IntrinsicSize;
pub use cursor_animation::{
    is_cursor_visible, next_cursor_blink_time, reset_cursor_blink, start_cursor_blink,
    stop_cursor_blink, tick_cursor_blink,
};
pub use debug::{
    ModifierChainTraceGuard, format_layout_tree, format_modifier_chain, format_render_scene,
    format_screen_summary, install_modifier_chain_trace, log_layout_tree, log_modifier_chain,
    log_render_scene, log_screen_summary,
};
pub use density::{Density, DensityMeasureScope, density, local_density};
pub use draggable::{DragDeltaHandler, DraggableState, rememberDraggableState};
pub use draw::{
    DrawCacheBuilder, DrawCommand, DrawCommandFn, command_draw_scope, command_draw_scope_reusing,
    execute_draw_commands,
};
pub use focus_dispatch::{
    active_focus_target, clear_focus_invalidations, has_pending_focus_invalidations,
    keyboard_focus_visible, process_focus_invalidations, schedule_focus_invalidation,
    set_active_focus_target, set_keyboard_focus_visible,
};
pub use focus_manager::{FocusManager, local_focus_manager, request_focus_from_platform};
pub use focus_navigation::{KeyboardFocusTarget, keyboard_focus_target};
pub use focus_order::{
    FocusEntry, collect_focus_order, collect_focus_order_under, focus_order_len,
    selectable_group_of, set_focus_order,
};
pub use font_scale::{FontScaleCurve, MAX_FONT_SCALE_KNOTS};
pub use interaction::{
    Interaction, MutableInteractionSource, PressInteraction, PressInteractionCancel,
    PressInteractionPress, PressInteractionRelease, collect_is_pressed_as_state,
    rememberMutableInteractionSource,
};
pub use key_event::{KeyCode, KeyEvent, KeyEventType, Modifiers};
pub use layout::{
    LayoutAllocationDebugStats, LayoutBox, LayoutEngine, LayoutMeasurements, LayoutNodeData,
    LayoutNodeKind, LayoutTree, MeasureLayoutOptions, SemanticsAction, SemanticsCallback,
    SemanticsNode, SemanticsRole, SemanticsText, SemanticsTree, build_layout_tree_from_applier,
    build_semantics_tree_from_applier, build_semantics_tree_from_layout_tree,
    core::{
        Alignment, Arrangement, HorizontalAlignment, LinearArrangement, Measurable, Placeable,
        VerticalAlignment,
    },
    measure_layout, measure_layout_with_options, top_modal_from_applier, tree_needs_layout,
    tree_needs_semantics,
};
pub use layout_direction::{
    LayoutDirection, ProvideLayoutDirection, layout_direction, local_layout_direction,
};
pub use lazy_item::{ProvideLazyItemKey, lazy_item_key, local_lazy_item_key};
pub use lazy_prefetch::{
    has_lazy_prefetch_requests, lazy_prefetch_item_cost, take_lazy_prefetch_requests,
    with_lazy_prefetch_pass,
};
pub use modal::{
    ModalRegistration, clear_modals, dispatch_modal_back, local_modal_depth, modal_depth,
};
pub use modifier::{
    BlendMode, Brush, Color, CompositingStrategy, CornerRadii, DpOffset, DragAndDropEvent,
    DragAndDropOutcome, DragAndDropPayload, DragAndDropPoint, DragAndDropSource,
    DragAndDropSourceElement, DragAndDropSourceNode, DragAndDropState, DragAndDropTarget,
    DragAndDropTargetElement, DragAndDropTargetNode, EdgeInsets, FocusDirection, FocusRequestError,
    FocusRequester, GlassMaterial, GraphicsLayer, LayerShape, Modifier, ModifierLocalKey,
    ModifierLocalReadScope, ModifierNodeSlices, ModifierNodeSlicesDebugStats, Point, PointerEvent,
    PointerEventKind, PointerInputScope, PointerSource, Rect, RenderEffect, ResolvedBackground,
    ResolvedModifiers, RotaryInputModifierNode, RotaryScrollEvent, RoundedCornerShape,
    RuntimeShader, SemanticsRequester, Shadow, ShadowScope, Size, TransformOrigin,
    WindowRootDescriptor, WindowRootElement, WindowRootEntry, WindowRootNode, WindowRootRegistry,
    collect_modifier_slices, collect_semantics_from_modifier, collect_slices_from_modifier,
    is_window_root, nearest_window_root, nearest_window_roots, window_roots, window_roots_revision,
};
#[cfg(feature = "test-helpers")]
pub use modifier::{last_fling_velocity, reset_last_fling_velocity};
pub use modifier_nodes::{
    AlphaElement, AlphaNode, BackgroundElement, BackgroundNode, ClickableElement, ClickableNode,
    CornerShapeElement, CornerShapeNode, FillDirection, FillElement, FillNode,
    FractionalOffsetElement, FractionalOffsetNode, OffsetElement, OffsetNode, PaddingElement,
    PaddingNode, SizeElement, SizeNode,
};
pub use nine_patch::{
    NinePatchInsets, PatchFill, PatchQuad, nine_patch_quads, tile_count, tile_quads,
};
#[doc(hidden)]
pub use pointer_dispatch::{
    clear_pointer_repasses, has_pending_pointer_repasses, process_pointer_repasses,
    schedule_pointer_repass,
};
pub use primitives::{
    AnimatedVisibility, BasicText, BasicTextField, BasicTextFieldDecorated,
    BasicTextFieldDecorationScope, BasicTextFieldOptions, BasicTextFieldWithOptions,
    BasicTextWithOptions, BitmapPainter, BitmapRegionPainter, Box, BoxScope, BoxSpec,
    BoxWithConstraints, BoxWithConstraintsScope, BoxWithConstraintsScopeImpl, Button, ButtonSpec,
    Canvas, Column, ColumnSpec, ContentScale, Crossfade, DEFAULT_ALPHA, EnterTransition,
    ExitTransition, ForEach, Image, Layout, LayoutNode, Painter, Row, RowSpec, Spacer,
    SubcomposeLayout, SvgPainter, SvgPainterError, Text, TextWithOptions, fade_in, fade_out,
    rememberSvg, slide_in_vertically, slide_out_vertically,
};
#[cfg(any(test, feature = "test-helpers"))]
#[doc(hidden)]
pub use render_state::reset_render_state_for_tests;
pub use render_state::{
    AppContext, AppContextScope, MAX_FONT_SCALE, MIN_FONT_SCALE, current_density,
    current_font_scale, current_font_scale_curve, scale_sp, set_density, set_font_scale,
    set_font_scale_curve,
};
#[doc(hidden)]
pub use render_state::{
    clear_transient_scroll_motion_contexts, debug_last_fling_velocity,
    debug_reset_last_fling_velocity, has_current_app_context, has_pending_draw_repasses,
    has_pending_layout_repasses, has_pending_measure_repasses, peek_focus_invalidation,
    peek_layout_invalidation, peek_pointer_invalidation, peek_render_invalidation,
    pending_layout_repass_nodes_snapshot, pending_measure_repass_nodes_snapshot,
    prune_draw_observations_to_nodes, request_current_draw_redraw, request_focus_invalidation,
    request_layout_invalidation, request_pointer_invalidation, request_render_invalidation,
    schedule_draw_repass, schedule_layout_repass, schedule_measure_repass, take_draw_repass_nodes,
    take_focus_invalidation, take_geometry_scene_nodes, take_layout_invalidation,
    take_layout_repass_nodes, take_measure_repass_nodes, take_pointer_invalidation,
    take_render_invalidation,
};
pub use renderer::{HeadlessRenderer, PaintLayer, RecordedRenderScene, RenderOp};
pub use safe_area::{WindowInsets, local_ime_insets, local_safe_area_insets, window_insets};
pub use scroll::{ScrollElement, ScrollMetrics, ScrollNode, ScrollSettlePolicy, ScrollState};
pub use scrollbar::{ThumbBounds, ThumbGeometry, content_delta_for_thumb_drag, thumb_geometry};
#[doc(hidden)]
pub use semantics_dispatch::{
    clear_semantics_invalidations, has_pending_semantics_invalidations,
    process_semantics_invalidations, schedule_semantics_invalidation,
};
pub use subcompose_layout::{
    Constraints, MeasureResult, Placement, SubcomposeLayoutNode, SubcomposeLayoutScope,
    SubcomposeMeasureScope, SubcomposeMeasureScopeImpl, clean_slot_skip_count,
};
pub use text::{
    LinkAnnotation, ParagraphStyle, PlatformParagraphStyle, PlatformSpanStyle, PlatformTextStyle,
    PreparedTextLayout, SpanStyle, StringAnnotation, TextDrawStyle, TextLayoutOptions,
    TextLayoutResult, TextLinePrefixWidths, TextMeasurer, TextMetrics, TextOptions, TextOverflow,
    TextShaping, TextStyle, get_cursor_x_for_offset, get_offset_for_position, layout_text,
    measure_text, measure_text_for_node, measure_text_with_options,
    measure_text_with_options_for_node, prepare_text_layout, prepare_text_layout_for_node,
    set_text_measurer,
};
pub use text_field_focus::{ImeEditorState, has_focused_field};
pub use text_field_modifier_node::{TextFieldElement, TextFieldModifierNode, TextPanResolver};
pub use text_input_session::PlatformTextInputHandler;
pub use text_modifier_node::{TextModifierElement, TextModifierNode};
pub use unhandled_keys::{UnhandledKeyEvents, dispatch_unhandled_key_event};
pub use widgets::{
    clickable_text::ClickableText,
    lazy_list::{LazyColumn, LazyColumnSpec, LazyRow, LazyRowSpec},
    linked_text::LinkedText,
    popup::{dismiss_top_popup, dismissable_popup_open},
    slider::{Slider, SliderOrientation, SliderScope, SliderSpec},
    swipe_to_dismiss::{
        SwipeDismissDirection, SwipeDismissSide, SwipeDismissState, SwipeToDismiss,
        SwipeToDismissBox, SwipeToDismissSpec, rememberSwipeDismissState,
    },
    text_selection_menu::local_on_light_surface,
};
pub use zoom::ZoomState;

/// In-memory composition helper used by tests.
pub struct TestComposition {
    _scope: render_state::AppContextScope,
    app_context: Rc<AppContext>,
    composition: Composition<MemoryApplier>,
}

impl TestComposition {
    pub fn root(&self) -> Option<NodeId> {
        self.app_context.enter(|| self.composition.root())
    }

    pub fn runtime_handle(&self) -> RuntimeHandle {
        self.app_context.enter(|| self.composition.runtime_handle())
    }

    pub fn should_render(&self) -> bool {
        self.app_context.enter(|| self.composition.should_render())
    }

    pub fn take_root_render_request(&mut self) -> bool {
        let app_context = Rc::clone(&self.app_context);
        app_context.enter(|| self.composition.take_root_render_request())
    }

    pub fn flush_pending_node_updates(&mut self) -> Result<(), NodeError> {
        let app_context = Rc::clone(&self.app_context);
        app_context.enter(|| self.composition.flush_pending_node_updates())
    }

    pub fn process_invalid_scopes(&mut self) -> Result<bool, NodeError> {
        let app_context = Rc::clone(&self.app_context);
        app_context.enter(|| self.composition.process_invalid_scopes())
    }

    pub fn render(&mut self, root_key: Key, content: impl FnMut()) -> Result<(), NodeError> {
        let app_context = Rc::clone(&self.app_context);
        app_context.enter(|| self.composition.render(root_key, content))
    }

    pub fn applier_mut(&mut self) -> TestApplierGuard<'_> {
        let scope = self.app_context.enter_scope();
        let applier = self.composition.applier_mut();
        TestApplierGuard {
            _scope: scope,
            applier,
        }
    }

    pub fn with_app_context<R>(&self, block: impl FnOnce() -> R) -> R {
        self.app_context.enter(block)
    }
}

pub struct TestApplierGuard<'a> {
    _scope: render_state::AppContextScope,
    applier: ApplierGuard<'a, MemoryApplier>,
}

impl Deref for TestApplierGuard<'_> {
    type Target = MemoryApplier;

    fn deref(&self) -> &Self::Target {
        &self.applier
    }
}

impl DerefMut for TestApplierGuard<'_> {
    fn deref_mut(&mut self) -> &mut Self::Target {
        &mut self.applier
    }
}

/// Build a composition with a simple in-memory applier and run the provided closure once.
pub fn run_test_composition(build: impl FnMut()) -> TestComposition {
    let app_context = AppContext::new();
    app_context.enter(|| {
        #[cfg(test)]
        reset_render_state_for_tests();
    });
    let mut test_composition = TestComposition {
        _scope: app_context.enter_scope(),
        app_context,
        composition: Composition::new(MemoryApplier::new()),
    };
    test_composition
        .render(location_key(file!(), line!(), column!()), build)
        .expect("initial render succeeds");
    test_composition
}

pub use cranpose_core::MutableState as SnapshotState;

#[cfg(test)]
#[path = "tests/anchor_async_tests.rs"]
mod anchor_async_tests;

#[cfg(test)]
#[path = "tests/animated_visibility_tests.rs"]
mod animated_visibility_tests;

#[cfg(test)]
#[path = "tests/lazy_recycle_effect_tests.rs"]
mod lazy_recycle_effect_tests;

#[cfg(test)]
#[path = "tests/measure_time_ui_task_tests.rs"]
mod measure_time_ui_task_tests;

#[cfg(test)]
#[path = "tests/animation_frame_pump_tests.rs"]
mod animation_frame_pump_tests;

#[cfg(test)]
#[path = "tests/crossfade_tests.rs"]
mod crossfade_tests;

#[cfg(test)]
#[path = "tests/async_runtime_full_layout_test.rs"]
mod async_runtime_full_layout_test;

#[cfg(test)]
#[path = "tests/cursor_position_tests.rs"]
mod cursor_position_tests;

#[cfg(test)]
#[path = "tests/popup_tests.rs"]
mod popup_tests;

#[cfg(test)]
#[path = "tests/selection_handle_tests.rs"]
mod selection_handle_tests;

#[cfg(test)]
#[path = "tests/tab_switching_tests.rs"]
mod tab_switching_tests;

#[cfg(test)]
#[path = "tests/lazy_list_viewport_tests.rs"]
mod lazy_list_viewport_tests;

#[cfg(test)]
#[path = "tests/swipe_to_dismiss_lazy_tests.rs"]
mod swipe_to_dismiss_lazy_tests;

#[cfg(test)]
#[path = "tests/top_modal_tests.rs"]
mod top_modal_tests;

#[cfg(test)]
#[path = "tests/swipe_to_dismiss_render_tests.rs"]
mod swipe_to_dismiss_render_tests;

#[cfg(test)]
#[path = "tests/lazy_list_recompose_tests.rs"]
mod lazy_list_recompose_tests;

#[cfg(test)]
#[path = "tests/lazy_row_tests.rs"]
mod lazy_row_tests;

#[cfg(test)]
#[path = "tests/wear_widget_tests.rs"]
mod wear_widget_tests;

#[cfg(test)]
#[path = "tests/ios_fling_measurement.rs"]
mod ios_fling_measurement;