Files
ltk/CHANGELOG.md
Pedro M. de Echanove Pasquin d31e7222da
Some checks failed
CI / build + test (push) Has been cancelled
CI / cargo audit (push) Has been cancelled
list_item: trailing icon slot and horizontal inset override
Disclosure arrows in list rows could only be text: the trailing slot draws a string, so apps fell back to the "›" glyph at 14 px, which cannot use the theme's arrow SVGs and looks thin next to 24 px leading icons. Add ListItem::trailing_icon( rgba, w, h ): a right-aligned icon drawn at the new theme::TRAILING_ICON_SIZE (21 px, 1.5x the old glyph em box), vertically centered. It coexists with trailing text, which shifts to the icon's left. Like the leading icon, symbolic assets are pre-tinted by the caller (tint_symbolic), so the widget stays colour-agnostic.
Add ListItem::pad_h( impl Into<Length> ), a per-item override of the horizontal inset between the row edge and its content (leading icon/label on the left, trailing text/icon on the right). Resolution follows the Separator pattern: an explicit Length wins, otherwise the theme default (16 px through geom_px) applies, so existing rows are unaffected. This lets an app whose enclosing view already provides the margin bring row content flush instead of stacking both insets.
Document both builders in docs/widgets.md and the changelog, and rework the list_item rustdoc example to point at trailing_icon with a theme icon for disclosure arrows instead of the text glyph.
2026-07-30 11:19:37 +02:00

6.8 KiB

Changelog

All notable changes to ltk are documented here. The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.

[Unreleased]

Added

  • ListItem::trailing_icon( rgba, w, h ) — right-aligned icon slot (disclosure arrow) drawn at TRAILING_ICON_SIZE (21 px) and vertically centered, alongside the existing leading icon. Coexists with trailing text, which shifts to the icon's left. Symbolic icons should be pre-tinted by the caller (tint_symbolic), matching the leading-icon contract.

  • ListItem::pad_h( impl Into<Length> ) — per-item override of the horizontal inset between the row edge and its content; without it the theme default (16 px) applies.

  • Responsive sizing system with two selectable modes via WidgetScaling (Fluid / Physical; set_widget_scaling / widget_scaling, default Fluid). New Length constructors — orient( portrait, landscape ) (a percentage of the width in portrait, of the height in landscape), fluid( px ) (surface-proportional, calibrated against set_fluid_reference and bounded by FLUID_MIN / FLUID_MAX), dp( px ) (constant physical size scaled by set_density / density), and widget( px ) (picks fluid or dp per the active mode). Canvas::geom_px (geometry, physical layout space) and Canvas::font_px (font, bridging the logical / physical split per mode) give widgets and apps one resolution path.

  • Button::font_size / height / width and TextEdit::height builders, all impl Into<Length>, so control boxes scale with the surface. Text::line_height( mult ) opens the gap between wrapped lines. Separator::pad_v (with Length::px( 0.0 ) for a flush divider).

  • Performance guardrails: opt-in diagnostics via LTK_PERF_WARN=1 (stuck animation, sustained software-render animation, low poll_interval) and a ~30 Hz software-animation cap overridable with App::cap_software_animation.

  • test-support Cargo feature gates the test_support module so third-party builds never see it (ltk's own make test enables it).

Changed

  • OverlaySpec::size is now ( Length, Length ) (was ( u32, u32 )), resolved against the main surface when the overlay is materialized; wrap existing sizes in Length::px( … ) for the old fixed behaviour.
  • TextEdit::font_size and Separator::thickness / pad_v now take impl Into<Length> (were f32), resolved like the button label (font space) / geometry space; the f32 sentinels are gone (f32 call sites still compile via Into<Length>).
  • Renamed set_design_reference / design_referenceset_fluid_reference / fluid_reference. Length::dp changed meaning — it used to be a surface-proportional value, and that behaviour now lives on Length::fluid; dp is the constant-physical-size unit.
  • Widget struct fields are now pub( crate ) (configured through builders), except the value / state types apps read or construct (Time, Date, ComboState).

0.2.0 — 2026-06-25

This release adds the primitives an embedder needs to drive ltk as the render backend for a retained, externally-owned widget tree (for example projecting an Android view hierarchy onto an ltk surface). Each is kept general rather than tied to one consumer.

Added

  • Canvas::set_clip_path — anti-aliased clipping to an arbitrary vector path (&[PathCmd]) on both backends. The software backend installs a tiny-skia coverage mask; the GLES backend captures the clipped draws into an offscreen layer and composites them back through an anti-aliased coverage mask. Complements the existing rect clip (set_clip_rects) for shaped clips such as a circular avatar, a rounded card or a VectorDrawable mask. See examples/clip_path.rs.
  • Canvas::fill_path / Canvas::stroke_path over a new PathCmd command list (MoveTo / LineTo / QuadTo / CubicTo / Close, in surface coordinates) — renders an arbitrary vector path, a Path, a VectorDrawable or a Lottie frame. The software backend rasterises directly with tiny-skia; the GLES backend rasterises into a tiny-skia pixmap and uploads it, so both backends share the same path rasteriser and stay at visual parity.
  • Canvas::read_rgba_pixels — reads any canvas into tightly packed straight-alpha RGBA8 (top-left row first), on both the GLES and software backends (the software path un-premultiplies its pixmap). Canvas::is_software lets a caller branch on the backend (e.g. honour a real path clip on software but only a bounding rect on GLES).
  • measure_text( text, size ) (re-exported at the crate root) — measures one line with the default UI font and the system fallback chain, returning (width, line_height) in pixels without a live Canvas, for an embedder's measure pass that must match the renderer's metrics. Backed by a process-wide cached primary-font handle.
  • Stack::push_placed — appends a child at an exact rect, bypassing alignment and intrinsic sizing, so a view tree whose geometry is computed elsewhere can be projected onto a Stack in paint order. Stack::push_placed_clipped additionally clips the child's subtree to a rect (Android's clipChildren): overflowing content is not painted.
  • ExternalSource::Cpu and the External::cpu constructor — an immediate-mode CPU drawing closure invoked once per frame with the canvas and the widget's laid-out rect, working on both backends. Hosts a custom View.onDraw straight onto the ltk canvas without a GL texture round-trip, unlike the existing Texture source which only renders on GLES.
  • RichText widget — wrapped paragraph text carrying a Msg per clickable link range; the layout pass emits one hit rect per link line so taps land on the link rather than the whole paragraph. The ltk side of an Android Spanned carrying URLSpan / ClickableSpan.

Fixed

  • GLES clip-layer composite no longer renders path-clipped content vertically flipped: the offscreen layer was sampled at the inverted screen Y. The software backend was unaffected.
  • Gesture: the horizontal pager is driven only once the swipe axis locks horizontal. Previously the pre-lock lateral drift of a vertical gesture could arm the consumer's pager without a matching release event, which could freeze the surface until an unrelated gesture reset it.
  • Software/GLES parity: the software backend now snaps glyph pen positions and image destinations to integer pixels (rounding to nearest), matching the GLES backend. Previously it truncated, so text and 1:1 images could land up to half a pixel off between backends and sample ~1 px softer.

Changed

  • Default theme launcher SVGs replaced with renderer-compatible versions.

0.1.0 — 2026-03-10

  • Initial release.