zaxis 0.1.0

Diagnostics

Usage errors, value normalization, platform failures and the debug overlay.

zaxis does not panic on mistakes in how it is driven and does not print anything. Problems are collected while the UI is built and handed to the application:

for problem in context.diagnostics() {
    // problem.kind, problem.id, problem.rect, problem.message
}
context.set_diagnostic_handler(Some(Box::new(|d| eprintln!("{:?}: {}", d.kind, d.message))));
context.set_debug_overlay(zaxis::DebugOverlay::ISSUES);

Context::diagnostics() lists the problems of the last completed pass; it is empty for a correct UI. Detection costs nothing while nothing is wrong. The handler is called once for each distinct problem, the first time it appears, so a misconfigured widget cannot flood a log; diagnostics() keeps describing it every pass while it persists.

DiagnosticKindMeaningWhat the library does
IdCollisionTwo widgets, columns, panels, rows or options used one id in a passKeeps drawing both (the second under a derived id)
UnbalancedScopeA scroll, placement or visual scope was left open at the end of a passCloses it so the next pass starts clean
NoLayoutSpaceAn interactive widget finished layout with an empty rectangleRegisters nothing for it
PopupWithoutAnchorA popup had a non-finite anchor or no room beside itDoes not open it
InvalidValueA builder or style value was out of rangeUses the normalized value, below
InvalidModelA model passed to a component is inconsistent, such as a tree cycleSame list as TreeOutput::issues; the component repairs what it can
InvalidUsageAn API contract was broken, such as an extra Grid cell or an unknown split panelMakes the call harmless
MissingAccessibleNameA control that a screen reader announces by name has none. Checked only while the accessibility tree is collected; see AccessibilityPublishes the control without a name
ExternalThe clipboard, a native window drag or an image failedReports it; nothing else changes

Value normalization

One rule for every component: an out-of-range value never panics. NaN, infinity, zero or a negative number from configuration is replaced by the nearest valid value, or ignored when there is none, and an InvalidValue diagnostic names the call site.

Kind of valueExamplesRule
Must be positivewidth, height, font_size, step, size, row heights, scaleAnything not finite and > 0 is ignored: the previous value or the theme default stays
May be zerogaps, paddings, thickness, radii, offsets >= 0, opacitiesNegative becomes 0; NaN and infinity are ignored
Positions and anglesoffset, pivot, rotating, scroll offsets and targetsNaN and infinity are ignored
WeightsColumnWidth::Remainder, SplitSize::WeightAnything not finite and > 0 counts as 1
FractionsProgressState::Determinate, drag opacitiesClamped to 0..=1; NaN becomes 0
RangesSlider::new, NumberInput::rangeDescending ends are swapped; a non-finite end gives 0..=1 (slider) or is ignored
Motionpresence, reveal, shared and highlight transitionsA repeating or reversing tween plays once, forward
StylesComboBoxStyle, NumberStyle, ContextMenuStyle, split surfacesThe same rules, field by field, on a copy used for the pass

Duplicate ids, a Grid without columns, extra cells, unknown panel ids and similar mistakes in how widgets are combined follow the same idea: the pass completes, the mistake is a diagnostic. assert! remains only for violations of the library's own invariants, never for application data.

Platform and resource failures

FailureWhere it reaches the application
run event-loop, window or unrecoverable GPU errorsResult<(), RunError> returned by run
GPU device lostThe runner recreates the renderer; Frame::device_resets() counts recoveries and Frame::last_device_loss() gives the reason. If recreation fails, run returns RunError::Render
Image decodingImageState::Error(ImageError) through Image::show, Context::image_state, and an External diagnostic on the image's rectangle
Clipboard unavailable or refusedAn External diagnostic; an empty clipboard is not an error
Native window drag or resize refused by the OSAn External diagnostic

Failures that happen between passes, such as a refused clipboard write, appear in the list of the next completed pass.

Debug overlay

Context::set_debug_overlay(DebugOverlay) draws on top of every layer. It is off by default, costs nothing while off, and never changes layout, hit testing or the cached geometry of the application's own elements, so it is safe to enable in a running app.

FieldDraws
issuesA red frame and a short message on the rectangle of each diagnostic
boundsThe bounds of the topmost hit region under the cursor
clipThe clip rectangle of that region
hitsEvery hit region under the cursor, with its kind

DebugOverlay::OFF, ISSUES and ALL cover the usual choices. The custom_widget and validation examples toggle it with F3.

Edit on GitHub

On this page