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

commitc472cea9dedc49b3c83a45a996d80242845accca
parente050d6a4a1
authorLucas Galante <[email protected]>
date2026-07-03 01:40
Added style.data.textbox.multiline.border_width configuration support

 src/layout.rs                | 23 +++++++++++++++++++++++
 src/widget/input/text_box.rs | 35 ++++++++++++++++++++++++++++++++---
 2 files changed, 55 insertions(+), 3 deletions(-)

diff --git a/src/layout.rs b/src/layout.rs
index 549e11a..932d835 100644
--- a/src/layout.rs
+++ b/src/layout.rs
@@ -92,6 +92,7 @@ fn flatten_json_to_flat_props(val: &serde_json::Value, prefix: &str, flat_props:
                 "style.control.spinbox.corner_radius" => "spinbox_corner_radius",
                 "style.textbox.height" | "style.data.textbox.height" => "textbox_height",
                 "style.textbox.multiline.line_wrap" | "style.data.textbox.multiline.line_wrap" => "textbox_line_wrap",
+                "style.textbox.multiline.border_width" | "style.data.textbox.multiline.border_width" => "textbox_multiline_border_width",
                 "style.control.toggle.font" => "toggle_font",
                 "style.control.toggle.height" => "toggle_height",
                 "style.control.toggle.border_width" => "toggle_border_width",
@@ -265,6 +266,7 @@ static PLATE_OPACITY: RwLock<f32> = RwLock::new(1.0);
 static PAGE_OPACITY: RwLock<f32> = RwLock::new(1.0);
 static LAYER_OPACITY: RwLock<f32> = RwLock::new(1.0);
 static TEXTBOX_LINE_WRAP: RwLock<bool> = RwLock::new(true);
+static TEXTBOX_MULTILINE_BORDER_WIDTH: RwLock<f32> = RwLock::new(1.0);
 
 
 
@@ -457,6 +459,15 @@ pub fn reload_config() {
                     *lock = wrap;
                 }
             }
+            if let Some(rest) = trimmed.strip_prefix("textbox_multiline_border_width") {
+                let rest = rest.trim_start_matches(|c: char| c == ' ' || c == '=' || c == '"');
+                let val_str = rest.trim_end_matches('"').trim();
+                if let Ok(val) = val_str.parse::<f32>() {
+                    if let Ok(mut lock) = TEXTBOX_MULTILINE_BORDER_WIDTH.write() {
+                        *lock = val;
+                    }
+                }
+            }
             if let Some(rest) = trimmed.strip_prefix("breadcrumb_corner_radius") {
                 let rest = rest.trim_start_matches(|c: char| c == ' ' || c == '=' || c == '"');
                 let val_str = rest.trim_end_matches('"').trim();
@@ -2428,6 +2439,18 @@ pub fn set_textbox_line_wrap(wrap: bool) {
     }
 }
 
+pub fn textbox_multiline_border_width() -> f32 {
+    lazy_init_style_registry();
+    *TEXTBOX_MULTILINE_BORDER_WIDTH.read().unwrap()
+}
+
+pub fn set_textbox_multiline_border_width(width: f32) {
+    lazy_init_style_registry();
+    if let Ok(mut lock) = TEXTBOX_MULTILINE_BORDER_WIDTH.write() {
+        *lock = width;
+    }
+}
+
 pub fn breadcrumb_corner_radius() -> f32 {
     lazy_init_style_registry();
     get_style_registry().read().unwrap().get_float("breadcrumb_corner_radius").unwrap_or(4.0)
diff --git a/src/widget/input/text_box.rs b/src/widget/input/text_box.rs
index 418db06..5c2cd62 100644
--- a/src/widget/input/text_box.rs
+++ b/src/widget/input/text_box.rs
@@ -275,6 +275,14 @@ impl TextBox {
         self
     }
 
+    fn border_width(&self) -> f32 {
+        if self.multiline {
+            crate::layout::textbox_multiline_border_width()
+        } else {
+            1.0
+        }
+    }
+
     pub fn set_placeholder(&mut self, placeholder: &str) {
         self.placeholder = Some(placeholder.to_string());
     }
@@ -990,10 +998,11 @@ impl Element for TextBox {
         
         let top = self.base.label_offset();
         let visual_h = self.base.h - top;
+        let border_w = self.border_width();
         if self.disabled {
             if self.draw_bg_border {
                 quads.push((self.base.x, self.base.y + top, self.base.w, visual_h, [0.12, 0.12, 0.16, 1.0]));
-                quads.push((self.base.x + 1.0, self.base.y + top + 1.0, self.base.w - 2.0, visual_h - 2.0, [0.06, 0.06, 0.08, 1.0]));
+                quads.push((self.base.x + border_w, self.base.y + top + border_w, self.base.w - 2.0 * border_w, visual_h - 2.0 * border_w, [0.06, 0.06, 0.08, 1.0]));
             }
             return quads;
         }
@@ -1012,7 +1021,7 @@ impl Element for TextBox {
                 [0.18, 0.18, 0.24, 1.0]
             };
             quads.push((self.base.x, self.base.y + top, self.base.w, visual_h, border_color));
-            quads.push((self.base.x + 1.0, self.base.y + top + 1.0, self.base.w - 2.0, visual_h - 2.0, bg_color));
+            quads.push((self.base.x + border_w, self.base.y + top + border_w, self.base.w - 2.0 * border_w, visual_h - 2.0 * border_w, bg_color));
         }
 
         if self.editing || self.select_anchor.is_some() {
@@ -1162,8 +1171,9 @@ impl Element for TextBox {
         };
         
         if self.draw_bg_border {
+            let border_w = self.border_width();
             quads.push((self.base.x, self.base.y + top, self.base.w, visual_h, radius, border_color, (r1, r2, r3, r4)));
-            quads.push((self.base.x + 1.0, self.base.y + top + 1.0, self.base.w - 2.0, visual_h - 2.0, radius - 1.0, bg_color, (r1, r2, r3, r4)));
+            quads.push((self.base.x + border_w, self.base.y + top + border_w, self.base.w - 2.0 * border_w, visual_h - 2.0 * border_w, (radius - border_w).max(0.0), bg_color, (r1, r2, r3, r4)));
         }
 
         if self.editing || self.select_anchor.is_some() {
@@ -1685,5 +1695,24 @@ mod tests {
         assert_eq!(tb.text, "");
         assert_eq!(tb.edit_buffer, "");
     }
+
+    #[test]
+    fn test_multiline_textbox_border_width() {
+        let _dummy = crate::context::UiContext::new();
+        let tb_single = TextBox::new("Singleline".to_string()).with_multiline(false);
+        let tb_multi = TextBox::new("Multiline".to_string()).with_multiline(true);
+
+        // Default border width
+        assert_eq!(tb_single.border_width(), 1.0);
+        assert_eq!(tb_multi.border_width(), 1.0);
+
+        // Configure custom border width
+        crate::layout::set_textbox_multiline_border_width(4.5);
+        assert_eq!(tb_single.border_width(), 1.0);
+        assert_eq!(tb_multi.border_width(), 4.5);
+
+        // Reset to default
+        crate::layout::set_textbox_multiline_border_width(1.0);
+    }
 }