git.lucas.co / cce-ui
GPU-accelerated UI toolkit (Vulkan)
git clone https://git.lucas.co/cce-ui.git

commit9b453a53232cd17767e1e2ac7d16e30d4a92f272
parent27ff64de29
authorLucas Galante <[email protected]>
date2026-07-18 15:05
feat: left-align button and toggle labels in the params pane

The rows form one column, but centered labels started each row's text at a
different x. Button already carried a `justify`, so its rows just opt in;
Toggle's label was hardcoded to centered, so it gains the same field and the
same `with_left_align`/`with_justify` builders, down to Button's 8px inset.

Set at the panel's construction sites rather than in the widgets: both are
shared across the DE, and menus, dialogs and cce-system-settings still center
their labels. Only the params pane opts in.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>

 src/widget/container/parameters_bg.rs |  6 ++++--
 src/widget/input/checkbox.rs          | 27 +++++++++++++++++++++++++--
 2 files changed, 29 insertions(+), 4 deletions(-)

diff --git a/src/widget/container/parameters_bg.rs b/src/widget/container/parameters_bg.rs
index 62f0520..35d777c 100644
--- a/src/widget/container/parameters_bg.rs
+++ b/src/widget/container/parameters_bg.rs
@@ -1882,7 +1882,9 @@ impl ParamController for ParametersBg {
             }).collect();
             self.buttons = self.display_params.iter().map(|p| {
                 if p.2 == "button" {
-                    Some(Button::new(0.0, 0.0, 0.0, 0.0).with_label(&p.0))
+                    // Left-aligned, like the toggles below: the rows form one column, and
+                    // centered labels made each row's text start at a different x.
+                    Some(Button::new(0.0, 0.0, 0.0, 0.0).with_label(&p.0).with_left_align(true))
                 } else {
                     None
                 }
@@ -1907,7 +1909,7 @@ impl ParamController for ParametersBg {
             self.toggles = self.display_params.iter().map(|p| {
                 if p.2 == "toggle" || p.2 == "checkbox" {
                     let on = p.1.trim().to_lowercase() == "true";
-                    let mut t = Toggle::new().with_label(&p.0);
+                    let mut t = Toggle::new().with_label(&p.0).with_left_align(true);
                     t.set_toggled(on);
                     Some(t)
                 } else {
diff --git a/src/widget/input/checkbox.rs b/src/widget/input/checkbox.rs
index d9b530d..0dd87aa 100644
--- a/src/widget/input/checkbox.rs
+++ b/src/widget/input/checkbox.rs
@@ -12,7 +12,9 @@
 use crate::colors;
 use crate::scene::layout::Rect;
 use crate::scene::paint::PaintCtx;
-use crate::widget::{Adapted, ElementState, Event, EventCtx, Input, Layout, MouseButton, Paint};
+use crate::widget::{
+    Adapted, ElementState, Event, EventCtx, Input, Justification, Layout, MouseButton, Paint,
+};
 
 fn parse_bool(val: &str) -> Option<bool> {
     match val.trim().to_lowercase().as_str() {
@@ -221,6 +223,9 @@ pub struct Toggle {
     label: Option<String>,
     hovered: bool,
     focused: bool,
+    /// Where the label sits across the pill. Mirrors `Button::justify` — same enum, same
+    /// 8px edge inset — so the two read as one control set wherever they share a column.
+    justify: Justification,
 }
 
 impl Toggle {
@@ -231,6 +236,7 @@ impl Toggle {
             label: None,
             hovered: false,
             focused: false,
+            justify: Justification::Center,
         })
     }
 
@@ -255,6 +261,18 @@ impl Toggle {
     }
 }
 
+impl Adapted<Toggle> {
+    pub fn with_left_align(mut self, left_align: bool) -> Self {
+        self.justify = if left_align { Justification::Left } else { Justification::Center };
+        self
+    }
+
+    pub fn with_justify(mut self, justify: Justification) -> Self {
+        self.justify = justify;
+        self
+    }
+}
+
 impl Layout for Toggle {
     fn inline_label(&self) -> bool {
         true
@@ -340,9 +358,14 @@ impl Paint for Toggle {
         if let Some(ref label) = self.label {
             let (font_fam, font_size) = crate::layout::control_label_font_parsed();
             let est_w = crate::widget::display::measure_text_width(label, &font_fam, font_size);
+            let tx = match self.justify {
+                Justification::Left => x + 8.0,
+                Justification::Right => x + w - est_w - 8.0,
+                Justification::Center => x + (w - est_w) / 2.0,
+            };
             ctx.text(
                 label.clone(),
-                x + (w - est_w) / 2.0,
+                tx,
                 crate::layout::align_text_y(y, h, font_size, 0.0),
                 font_size,
                 colors::control_label_color_for_state(self.hovered, self.focused),