GPU-accelerated UI toolkit (Vulkan)
git clone https://git.lucas.co/cce-ui.git
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);
+ }
}