GPU-accelerated UI toolkit (Vulkan)
git clone https://git.lucas.co/cce-ui.git
fix: serve the params sliders' fill, readout, and thumb to legacy hosts
A host on the legacy flat views (the designer's params pane) lost three
of the slider's four parts: rounded_quads skipped slider rows (fill +
readout box), and the thumb knob is a Prim::Sphere, which no flat view
carries — only the recess carve survived, an empty well.
rounded_quads now includes slider rows, and a spheres() view serves the
thumbs off the new Slider::thumb_sphere (shared by paint so the two
paths can't drift), drawn after reliefs per the widget's own
fill -> carve -> thumb order.
Co-Authored-By: Claude Fable 5 <[email protected]>
src/widget/container/parameters_bg.rs | 33 +++++++++++++++++++++++++++++++++
src/widget/input/slider.rs | 35 +++++++++++++++++++++++------------
2 files changed, 56 insertions(+), 12 deletions(-)
diff --git a/src/widget/container/parameters_bg.rs b/src/widget/container/parameters_bg.rs
index 33f952d..8d893d7 100644
--- a/src/widget/container/parameters_bg.rs
+++ b/src/widget/container/parameters_bg.rs
@@ -870,6 +870,13 @@ impl ParametersBg {
if let Some(tb) = &self.texts[i] {
out.extend(tb.all_rounded_quads(ctx));
}
+ } else if p.2.starts_with("slider") {
+ // Track (square style only — the recessed style has no track
+ // background), value fill, and readout box; the thumb knob is a
+ // `Prim::Sphere` and rides `spheres()` instead.
+ if let Some(s) = &self.sliders[i] {
+ out.extend(s.all_rounded_quads(ctx));
+ }
} else if p.2.starts_with("choice") {
if let Some(d) = &self.choices[i] {
out.extend(d.all_rounded_quads(ctx));
@@ -946,6 +953,32 @@ impl ParametersBg {
out
}
+ /// The sphere companion to [`Self::rounded_quads`]: the slider rows' thumb
+ /// knobs, which are `Prim::Sphere` — a prim NO legacy flat view carries, so
+ /// a host rendering this panel through the legacy views must read this
+ /// getter or the knobs vanish. Returned unclipped; the host clips to the
+ /// pane's scroll viewport and draws these AFTER [`Self::reliefs`], matching
+ /// the widget's own fill → carve → thumb order.
+ pub fn spheres(&self) -> Vec<(f32, f32, f32, [f32; 4])> {
+ if !self.visible {
+ return Vec::new();
+ }
+ let mut out = Vec::new();
+ let hidden = self.hidden_rows();
+ for (i, p) in self.display_params.iter().enumerate() {
+ if hidden[i] || !p.2.starts_with("slider") {
+ continue;
+ }
+ if let Some(s) = &self.sliders[i] {
+ let (x, y, w, h) = s.rect();
+ if let Some(sphere) = s.inner().thumb_sphere(Rect { x, y, width: w, height: h }) {
+ out.push(sphere);
+ }
+ }
+ }
+ out
+ }
+
}
impl Layout for ParametersBg {
diff --git a/src/widget/input/slider.rs b/src/widget/input/slider.rs
index 5b0c96c..4be0574 100644
--- a/src/widget/input/slider.rs
+++ b/src/widget/input/slider.rs
@@ -126,6 +126,24 @@ impl Slider {
Some((g.track_x, g.y, g.track_w, g.h, radius, depth))
}
+ /// The thumb knob's circle (cx, cy, radius, color) for hosts that draw this
+ /// control through the legacy flat views (see `ParametersBg::spheres`): the
+ /// `Prim::Sphere` the rounded-corner paint emits — no flat view can carry
+ /// it. None under the square style, whose quad thumb already reaches the
+ /// plain-quad view. The same geometry `paint` draws.
+ pub fn thumb_sphere(&self, rect: Rect) -> Option<(f32, f32, f32, [f32; 4])> {
+ if crate::layout::slider_corner_radius() <= 0.0 {
+ return None;
+ }
+ let g = self.geom(rect);
+ let recess_t = crate::layout::bevel_width().min(g.h * 0.2);
+ let thumb_x = g.track_x + self.value * (g.track_w - g.thumb_size);
+ let thumb_y = g.y + (g.h - g.thumb_size) / 2.0;
+ let diameter = if self.recessed { g.h - recess_t } else { g.thumb_size };
+ let color = if self.dragging { colors::slider_thumb_drag() } else { colors::slider_thumb() };
+ Some((thumb_x + g.thumb_size / 2.0, thumb_y + g.thumb_size / 2.0, diameter / 2.0, color))
+ }
+
fn geom(&self, rect: Rect) -> SliderGeom {
let side = side_offset(&self.label);
let x = rect.x + side;
@@ -313,18 +331,11 @@ impl Paint for Slider {
// reads wrong — the thumb should stay round under any corner style.
let thumb_y = g.y + (g.h - g.thumb_size) / 2.0;
let thumb_color = if self.dragging { colors::slider_thumb_drag() } else { colors::slider_thumb() };
- if rounded {
- // Recessed style: the knob sits IN the well, so its diameter is the
- // flat floor between the walls (each intrudes half its width) —
- // drawn size only; the drag/hit geometry keeps the full thumb_size.
- let diameter =
- if self.recessed { g.h - recess_t } else { g.thumb_size };
- ctx.sphere(
- thumb_x + g.thumb_size / 2.0,
- thumb_y + g.thumb_size / 2.0,
- diameter / 2.0,
- thumb_color,
- );
+ // Recessed style: the knob sits IN the well, so its diameter is the
+ // flat floor between the walls (each intrudes half its width) —
+ // drawn size only; the drag/hit geometry keeps the full thumb_size.
+ if let Some((cx, cy, r, c)) = self.thumb_sphere(rect) {
+ ctx.sphere(cx, cy, r, c);
} else {
rrect(
Rect { x: thumb_x, y: thumb_y, width: g.thumb_size, height: g.thumb_size },