GPU-accelerated UI toolkit (Vulkan)
git clone https://git.lucas.co/cce-ui.git
Add support for style.spinbox.button_padding
src/layout.rs | 39 +++++++++++++++++++++
src/widget/input/spinbox.rs | 85 +++++++++++++++++++++++++++++++--------------
2 files changed, 97 insertions(+), 27 deletions(-)
diff --git a/src/layout.rs b/src/layout.rs
index 785567e..1678787 100644
--- a/src/layout.rs
+++ b/src/layout.rs
@@ -26,6 +26,7 @@ fn flatten_json_to_flat_props(val: &serde_json::Value, prefix: &str, flat_props:
"style.slider.height" => "slider_height",
"style.slider.corner_radius" => "slider_corner_radius",
"style.spinbox.height" => "spinbox_height",
+ "style.spinbox.button_padding" => "spinbox_button_padding",
"style.textbox.height" => "textbox_height",
"style.toggle.font" => "toggle_font",
"style.toggle.height" => "toggle_height",
@@ -109,6 +110,7 @@ pub fn parse_font_string(s: &str) -> (String, Option<f32>) {
static SECTION_PADDING: RwLock<f32> = RwLock::new(8.0);
static SPINBOX_HEIGHT: RwLock<f32> = RwLock::new(26.0);
+static SPINBOX_BUTTON_PADDING: RwLock<f32> = RwLock::new(0.0);
static COLOR_SELECTOR_HEIGHT: RwLock<f32> = RwLock::new(22.0);
static TEXTBOX_HEIGHT: RwLock<f32> = RwLock::new(44.0);
static FONT_SELECTOR_HEIGHT: RwLock<f32> = RwLock::new(44.0);
@@ -285,6 +287,15 @@ pub fn reload_config() {
}
}
}
+ if let Some(rest) = trimmed.strip_prefix("spinbox_button_padding") {
+ 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) = SPINBOX_BUTTON_PADDING.write() {
+ *lock = val;
+ }
+ }
+ }
if let Some(rest) = trimmed.strip_prefix("spinbox_corner_radius") {
let rest = rest.trim_start_matches(|c: char| c == ' ' || c == '=' || c == '"');
let val_str = rest.trim_end_matches('"').trim();
@@ -2220,6 +2231,34 @@ pub fn set_spinbox_corner_radius(radius: f32) {
}
}
+pub fn spinbox_button_padding() -> f32 {
+ use std::sync::Once;
+ static INIT: Once = Once::new();
+ INIT.call_once(|| {
+ if let Some(content) = read_config() {
+ for line in content.lines() {
+ let trimmed = line.trim();
+ if let Some(rest) = trimmed.strip_prefix("spinbox_button_padding") {
+ 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) = SPINBOX_BUTTON_PADDING.write() {
+ *lock = val;
+ }
+ }
+ }
+ }
+ }
+ });
+ *SPINBOX_BUTTON_PADDING.read().unwrap()
+}
+
+pub fn set_spinbox_button_padding(padding: f32) {
+ if let Ok(mut lock) = SPINBOX_BUTTON_PADDING.write() {
+ *lock = padding;
+ }
+}
+
pub fn textbox_corner_radius() -> f32 {
use std::sync::Once;
static INIT: Once = Once::new();
diff --git a/src/widget/input/spinbox.rs b/src/widget/input/spinbox.rs
index 625c5f1..107d90c 100644
--- a/src/widget/input/spinbox.rs
+++ b/src/widget/input/spinbox.rs
@@ -148,8 +148,16 @@ impl Element for Spinbox {
self.hover_inc = false;
return changed || was != self.base.hovered;
}
- let hd = px >= self.base.x + self.base.w * 0.55 && px < self.base.x + self.base.w * 0.775;
- let hi = px >= self.base.x + self.base.w * 0.775;
+ let top = self.base.label_offset();
+ let visual_h = self.base.h - top;
+ let p = crate::layout::spinbox_button_padding();
+ let btn_y = self.base.y + top + p;
+ let btn_h = (visual_h - 2.0 * p).max(0.0);
+ let split_dec = self.base.x + self.base.w * 0.55;
+
+ let in_y = py >= btn_y && py < btn_y + btn_h;
+ let hd = in_y && px >= split_dec + p && px < self.base.x + self.base.w * 0.775;
+ let hi = in_y && px >= self.base.x + self.base.w * 0.775 && px < self.base.x + self.base.w - p;
let changed = hd != self.hover_dec || hi != self.hover_inc;
self.hover_dec = hd;
self.hover_inc = hi;
@@ -167,25 +175,29 @@ impl Element for Spinbox {
if !self.hit_test(px, py, ctx) { return false; }
match state {
ElementState::Pressed => {
- let display_w = self.base.w * 0.55;
- let btn_w = self.base.w * 0.225;
- let split_dec = self.base.x + display_w;
- let split_inc = self.base.x + display_w + btn_w;
- if px >= split_dec && px < split_inc {
+ let top = self.base.label_offset();
+ let visual_h = self.base.h - top;
+ let p = crate::layout::spinbox_button_padding();
+ let btn_y = self.base.y + top + p;
+ let btn_h = (visual_h - 2.0 * p).max(0.0);
+ let split_dec = self.base.x + self.base.w * 0.55;
+
+ let in_y = py >= btn_y && py < btn_y + btn_h;
+ if in_y && px >= split_dec + p && px < self.base.x + self.base.w * 0.775 {
let old_val = self.value;
self.value = (self.value - self.step).max(self.min);
if self.value != old_val {
self.just_changed = true;
}
true
- } else if px >= split_inc {
+ } else if in_y && px >= self.base.x + self.base.w * 0.775 && px < self.base.x + self.base.w - p {
let old_val = self.value;
self.value = (self.value + self.step).min(self.max);
if self.value != old_val {
self.just_changed = true;
}
true
- } else {
+ } else if px < split_dec {
self.editing = true;
if self.decimals > 0 {
let divisor = 10.0f32.powi(self.decimals as i32);
@@ -200,6 +212,8 @@ impl Element for Spinbox {
self.cursor_idx = click_idx;
focus::set_focused(self);
true
+ } else {
+ false
}
}
ElementState::Released => {
@@ -323,10 +337,9 @@ impl Element for Spinbox {
let mut quads = Vec::new();
let top = self.base.label_offset();
let visual_h = self.base.h - top;
- let btn_w = self.base.w * 0.225;
let display_w = self.base.w * 0.55;
+ let p = crate::layout::spinbox_button_padding();
let split_dec = self.base.x + display_w;
- let split_inc = self.base.x + display_w + btn_w;
let inc_col = if self.hover_inc { colors::SPINBOX_BUTTON_HOVER } else { colors::SPINBOX_BUTTON };
let dec_col = if self.hover_dec { colors::SPINBOX_BUTTON_HOVER } else { colors::SPINBOX_BUTTON };
@@ -337,8 +350,16 @@ impl Element for Spinbox {
};
quads.push((self.base.x, self.base.y + top, display_w, visual_h, display_bg));
- quads.push((split_dec, self.base.y + top, btn_w, visual_h, dec_col));
- quads.push((split_inc, self.base.y + top, btn_w, visual_h, inc_col));
+
+ let btn_y = self.base.y + top + p;
+ let btn_h = (visual_h - 2.0 * p).max(0.0);
+ let pair_w = (self.base.w * 0.45 - 2.0 * p).max(0.0);
+ let btn_w_padded = pair_w / 2.0;
+
+ if btn_h > 0.0 && btn_w_padded > 0.0 {
+ quads.push((split_dec + p, btn_y, btn_w_padded, btn_h, dec_col));
+ quads.push((split_dec + p + btn_w_padded, btn_y, btn_w_padded, btn_h, inc_col));
+ }
if self.editing {
let border_color = [0.20, 0.50, 0.85, 1.0];
@@ -392,20 +413,30 @@ impl Element for Spinbox {
});
}
- labels.push(TextLabel {
- text: "-".to_string(),
- x: self.base.x + self.base.w * 0.6625 - 4.0,
- y: crate::layout::align_text_y(self.base.y, self.base.h, 12.0, top),
- font_size: 12.0,
- color: [0xcc, 0xcc, 0xd4],
- });
- labels.push(TextLabel {
- text: "+".to_string(),
- x: self.base.x + self.base.w * 0.8875 - 4.0,
- y: crate::layout::align_text_y(self.base.y, self.base.h, 12.0, top),
- font_size: 12.0,
- color: [0xcc, 0xcc, 0xd4],
- });
+ let p = crate::layout::spinbox_button_padding();
+ let split_dec = self.base.x + self.base.w * 0.55;
+ let pair_w = (self.base.w * 0.45 - 2.0 * p).max(0.0);
+ let btn_w_padded = pair_w / 2.0;
+
+ if btn_w_padded > 0.0 {
+ let dec_center_x = split_dec + p + btn_w_padded * 0.5;
+ let inc_center_x = split_dec + p + btn_w_padded * 1.5;
+
+ labels.push(TextLabel {
+ text: "-".to_string(),
+ x: dec_center_x - 4.0,
+ y: crate::layout::align_text_y(self.base.y, self.base.h, 12.0, top),
+ font_size: 12.0,
+ color: [0xcc, 0xcc, 0xd4],
+ });
+ labels.push(TextLabel {
+ text: "+".to_string(),
+ x: inc_center_x - 4.0,
+ y: crate::layout::align_text_y(self.base.y, self.base.h, 12.0, top),
+ font_size: 12.0,
+ color: [0xcc, 0xcc, 0xd4],
+ });
+ }
labels
}