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

commit091d9196cbc4a6abc9a9444545d67c58559f9a68
parent74061b7da3
authorLucas Galante <[email protected]>
date2026-07-01 13:13
Expose and support all color styling keys in style.data.tree domain

 src/color.rs                     | 112 +++++++++++++++++++++++++++++++++++++++
 src/widget/container/treelist.rs |  38 +++++++------
 2 files changed, 133 insertions(+), 17 deletions(-)

diff --git a/src/color.rs b/src/color.rs
index d1e7798..d8a0c95 100644
--- a/src/color.rs
+++ b/src/color.rs
@@ -47,6 +47,27 @@ static LAYER_COLOR: RwLock<[f32; 4]> = RwLock::new([0.0, 0.0, 0.0, 0.0]);
 static BACKPLATE_CORNER_RADIUS: RwLock<f32> = RwLock::new(12.0);
 static BUTTON_BACKGROUND_COLOR: RwLock<[f32; 4]> = RwLock::new(BUTTON_IDLE);
 
+static TREE_BACKGROUND_COLOR: RwLock<[f32; 4]> = RwLock::new([0.08, 0.08, 0.12, 0.3]);
+static TREE_BORDER_COLOR: RwLock<[f32; 4]> = RwLock::new([0.18, 0.18, 0.24, 1.0]);
+static TREE_BORDER_HOVER_COLOR: RwLock<[f32; 4]> = RwLock::new([0.25, 0.25, 0.35, 1.0]);
+static TREE_BORDER_FOCUS_COLOR: RwLock<[f32; 4]> = RwLock::new([0.30, 0.50, 0.32, 1.0]);
+
+static TREE_SECTION_BG_COLOR: RwLock<[f32; 4]> = RwLock::new([0.07, 0.07, 0.09, 1.0]);
+static TREE_SECTION_BG_HOVER_COLOR: RwLock<[f32; 4]> = RwLock::new([0.10, 0.12, 0.18, 1.0]);
+
+static TREE_LEAF_BG_EVEN_COLOR: RwLock<[f32; 4]> = RwLock::new([0.09, 0.09, 0.11, 1.0]);
+static TREE_LEAF_BG_ODD_COLOR: RwLock<[f32; 4]> = RwLock::new([0.08, 0.08, 0.10, 1.0]);
+static TREE_LEAF_BG_HOVER_COLOR: RwLock<[f32; 4]> = RwLock::new([0.12, 0.12, 0.16, 1.0]);
+static TREE_LEAF_BG_SELECTED_COLOR: RwLock<[f32; 4]> = RwLock::new([0.15, 0.20, 0.30, 1.0]);
+
+static TREE_SECTION_TEXT_COLOR: RwLock<[f32; 4]> = RwLock::new([0.38, 0.69, 0.94, 1.0]);
+static TREE_LEAF_TEXT_COLOR: RwLock<[f32; 4]> = RwLock::new([0.80, 0.80, 0.83, 1.0]);
+static TREE_LEAF_TEXT_SELECTED_COLOR: RwLock<[f32; 4]> = RwLock::new([0.49, 1.0, 1.0, 1.0]);
+
+static TREE_TYPE_TEXT_COLOR: RwLock<[f32; 4]> = RwLock::new([0.78, 0.47, 0.87, 1.0]);
+static TREE_VALUE_TEXT_COLOR: RwLock<[f32; 4]> = RwLock::new([0.51, 0.51, 0.54, 1.0]);
+static TREE_SEPARATOR_COLOR: RwLock<[f32; 4]> = RwLock::new([0.15, 0.15, 0.19, 1.0]);
+
 pub fn button_background_color() -> [f32; 4] {
     *BUTTON_BACKGROUND_COLOR.read().unwrap()
 }
@@ -240,6 +261,55 @@ fn parse_and_set_colors(content: &str) {
             *lock = [c[0], c[1], c[2], 1.0];
         }
     }
+
+    if let Some(c) = get_color("/style/data/tree/background_color") {
+        if let Ok(mut lock) = TREE_BACKGROUND_COLOR.write() { *lock = c; }
+    }
+    if let Some(c) = get_color("/style/data/tree/border_color") {
+        if let Ok(mut lock) = TREE_BORDER_COLOR.write() { *lock = c; }
+    }
+    if let Some(c) = get_color("/style/data/tree/border_hover_color") {
+        if let Ok(mut lock) = TREE_BORDER_HOVER_COLOR.write() { *lock = c; }
+    }
+    if let Some(c) = get_color("/style/data/tree/border_focus_color") {
+        if let Ok(mut lock) = TREE_BORDER_FOCUS_COLOR.write() { *lock = c; }
+    }
+    if let Some(c) = get_color("/style/data/tree/section_bg_color") {
+        if let Ok(mut lock) = TREE_SECTION_BG_COLOR.write() { *lock = c; }
+    }
+    if let Some(c) = get_color("/style/data/tree/section_bg_hover_color") {
+        if let Ok(mut lock) = TREE_SECTION_BG_HOVER_COLOR.write() { *lock = c; }
+    }
+    if let Some(c) = get_color("/style/data/tree/leaf_bg_even_color") {
+        if let Ok(mut lock) = TREE_LEAF_BG_EVEN_COLOR.write() { *lock = c; }
+    }
+    if let Some(c) = get_color("/style/data/tree/leaf_bg_odd_color") {
+        if let Ok(mut lock) = TREE_LEAF_BG_ODD_COLOR.write() { *lock = c; }
+    }
+    if let Some(c) = get_color("/style/data/tree/leaf_bg_hover_color") {
+        if let Ok(mut lock) = TREE_LEAF_BG_HOVER_COLOR.write() { *lock = c; }
+    }
+    if let Some(c) = get_color("/style/data/tree/leaf_bg_selected_color") {
+        if let Ok(mut lock) = TREE_LEAF_BG_SELECTED_COLOR.write() { *lock = c; }
+    }
+    if let Some(c) = get_color("/style/data/tree/section_text_color") {
+        if let Ok(mut lock) = TREE_SECTION_TEXT_COLOR.write() { *lock = c; }
+    }
+    if let Some(c) = get_color("/style/data/tree/leaf_text_color") {
+        if let Ok(mut lock) = TREE_LEAF_TEXT_COLOR.write() { *lock = c; }
+    }
+    if let Some(c) = get_color("/style/data/tree/leaf_text_selected_color") {
+        if let Ok(mut lock) = TREE_LEAF_TEXT_SELECTED_COLOR.write() { *lock = c; }
+    }
+    if let Some(c) = get_color("/style/data/tree/type_text_color") {
+        if let Ok(mut lock) = TREE_TYPE_TEXT_COLOR.write() { *lock = c; }
+    }
+    if let Some(c) = get_color("/style/data/tree/value_text_color") {
+        if let Ok(mut lock) = TREE_VALUE_TEXT_COLOR.write() { *lock = c; }
+    }
+    if let Some(c) = get_color("/style/data/tree/separator_color") {
+        if let Ok(mut lock) = TREE_SEPARATOR_COLOR.write() { *lock = c; }
+    }
 }
 
 fn load_colors_once() {
@@ -585,3 +655,45 @@ pub fn active_backplate_opacity() -> f32 {
     page_low_color()[3]
 }
 
+pub fn tree_background_color() -> [f32; 4] { *TREE_BACKGROUND_COLOR.read().unwrap() }
+pub fn tree_border_color() -> [f32; 4] { *TREE_BORDER_COLOR.read().unwrap() }
+pub fn tree_border_hover_color() -> [f32; 4] { *TREE_BORDER_HOVER_COLOR.read().unwrap() }
+pub fn tree_border_focus_color() -> [f32; 4] { *TREE_BORDER_FOCUS_COLOR.read().unwrap() }
+
+pub fn tree_section_bg_color() -> [f32; 4] { *TREE_SECTION_BG_COLOR.read().unwrap() }
+pub fn tree_section_bg_hover_color() -> [f32; 4] { *TREE_SECTION_BG_HOVER_COLOR.read().unwrap() }
+
+pub fn tree_leaf_bg_even_color() -> [f32; 4] { *TREE_LEAF_BG_EVEN_COLOR.read().unwrap() }
+pub fn tree_leaf_bg_odd_color() -> [f32; 4] { *TREE_LEAF_BG_ODD_COLOR.read().unwrap() }
+pub fn tree_leaf_bg_hover_color() -> [f32; 4] { *TREE_LEAF_BG_HOVER_COLOR.read().unwrap() }
+pub fn tree_leaf_bg_selected_color() -> [f32; 4] { *TREE_LEAF_BG_SELECTED_COLOR.read().unwrap() }
+
+pub fn tree_section_text_color() -> [f32; 4] { *TREE_SECTION_TEXT_COLOR.read().unwrap() }
+pub fn tree_leaf_text_color() -> [f32; 4] { *TREE_LEAF_TEXT_COLOR.read().unwrap() }
+pub fn tree_leaf_text_selected_color() -> [f32; 4] { *TREE_LEAF_TEXT_SELECTED_COLOR.read().unwrap() }
+
+pub fn tree_type_text_color() -> [f32; 4] { *TREE_TYPE_TEXT_COLOR.read().unwrap() }
+pub fn tree_value_text_color() -> [f32; 4] { *TREE_VALUE_TEXT_COLOR.read().unwrap() }
+pub fn tree_separator_color() -> [f32; 4] { *TREE_SEPARATOR_COLOR.read().unwrap() }
+
+pub fn set_tree_background_color(c: [f32; 4]) { if let Ok(mut lock) = TREE_BACKGROUND_COLOR.write() { *lock = c; } }
+pub fn set_tree_border_color(c: [f32; 4]) { if let Ok(mut lock) = TREE_BORDER_COLOR.write() { *lock = c; } }
+pub fn set_tree_border_hover_color(c: [f32; 4]) { if let Ok(mut lock) = TREE_BORDER_HOVER_COLOR.write() { *lock = c; } }
+pub fn set_tree_border_focus_color(c: [f32; 4]) { if let Ok(mut lock) = TREE_BORDER_FOCUS_COLOR.write() { *lock = c; } }
+
+pub fn set_tree_section_bg_color(c: [f32; 4]) { if let Ok(mut lock) = TREE_SECTION_BG_COLOR.write() { *lock = c; } }
+pub fn set_tree_section_bg_hover_color(c: [f32; 4]) { if let Ok(mut lock) = TREE_SECTION_BG_HOVER_COLOR.write() { *lock = c; } }
+
+pub fn set_tree_leaf_bg_even_color(c: [f32; 4]) { if let Ok(mut lock) = TREE_LEAF_BG_EVEN_COLOR.write() { *lock = c; } }
+pub fn set_tree_leaf_bg_odd_color(c: [f32; 4]) { if let Ok(mut lock) = TREE_LEAF_BG_ODD_COLOR.write() { *lock = c; } }
+pub fn set_tree_leaf_bg_hover_color(c: [f32; 4]) { if let Ok(mut lock) = TREE_LEAF_BG_HOVER_COLOR.write() { *lock = c; } }
+pub fn set_tree_leaf_bg_selected_color(c: [f32; 4]) { if let Ok(mut lock) = TREE_LEAF_BG_SELECTED_COLOR.write() { *lock = c; } }
+
+pub fn set_tree_section_text_color(c: [f32; 4]) { if let Ok(mut lock) = TREE_SECTION_TEXT_COLOR.write() { *lock = c; } }
+pub fn set_tree_leaf_text_color(c: [f32; 4]) { if let Ok(mut lock) = TREE_LEAF_TEXT_COLOR.write() { *lock = c; } }
+pub fn set_tree_leaf_text_selected_color(c: [f32; 4]) { if let Ok(mut lock) = TREE_LEAF_TEXT_SELECTED_COLOR.write() { *lock = c; } }
+
+pub fn set_tree_type_text_color(c: [f32; 4]) { if let Ok(mut lock) = TREE_TYPE_TEXT_COLOR.write() { *lock = c; } }
+pub fn set_tree_value_text_color(c: [f32; 4]) { if let Ok(mut lock) = TREE_VALUE_TEXT_COLOR.write() { *lock = c; } }
+pub fn set_tree_separator_color(c: [f32; 4]) { if let Ok(mut lock) = TREE_SEPARATOR_COLOR.write() { *lock = c; } }
+
diff --git a/src/widget/container/treelist.rs b/src/widget/container/treelist.rs
index 1b722e6..b9024be 100644
--- a/src/widget/container/treelist.rs
+++ b/src/widget/container/treelist.rs
@@ -220,11 +220,11 @@ impl Element for TreeList {
         let is_hovered = self.hovered() || self.hovered_row_idx.is_some() || self.scroll_box.base.hovered;
         if self.scroll_box.show_border {
             let box_border_color = if is_focused {
-                [0.30, 0.50, 0.32, 1.0]
+                crate::color::tree_border_focus_color()
             } else if is_hovered {
-                [0.25, 0.25, 0.35, 1.0]
+                crate::color::tree_border_hover_color()
             } else {
-                [0.18, 0.18, 0.24, 1.0]
+                crate::color::tree_border_color()
             };
             Some((box_border_color, 1.0))
         } else {
@@ -393,20 +393,20 @@ impl Element for TreeList {
             let bg_color = match item {
                 TreeElement::Section { .. } => {
                     if Some(i) == self.hovered_row_idx {
-                        [0.10, 0.12, 0.18, 1.0]
+                        crate::color::tree_section_bg_hover_color()
                     } else {
-                        [0.07, 0.07, 0.09, 1.0]
+                        crate::color::tree_section_bg_color()
                     }
                 }
                 TreeElement::Leaf { original_idx, .. } => {
                     if Some(*original_idx) == self.selected_key_idx {
-                        [0.15, 0.20, 0.30, 1.0]
+                        crate::color::tree_leaf_bg_selected_color()
                     } else if Some(i) == self.hovered_row_idx {
-                        [0.12, 0.12, 0.16, 1.0]
+                        crate::color::tree_leaf_bg_hover_color()
                     } else if i % 2 == 0 {
-                        [0.09, 0.09, 0.11, 1.0]
+                        crate::color::tree_leaf_bg_even_color()
                     } else {
-                        [0.08, 0.08, 0.10, 1.0]
+                        crate::color::tree_leaf_bg_odd_color()
                     }
                 }
             };
@@ -415,7 +415,7 @@ impl Element for TreeList {
             
             // Draw column separator lines and color preview for Leaf rows
             if let TreeElement::Leaf { ref val, original_idx, .. } = item {
-                let separator_color = [0.15, 0.15, 0.19, 1.0];
+                let separator_color = crate::color::tree_separator_color();
                 quads.push((list_left + 180.0, draw_y, 1.0, draw_h, separator_color));
                 quads.push((list_left + 235.0, draw_y, 1.0, draw_h, separator_color));
 
@@ -447,6 +447,10 @@ impl Element for TreeList {
     }
 
     fn text_labels(&self) -> Vec<TextLabel> {
+        let f32_to_rgb = |c: [f32; 4]| -> [u8; 3] {
+            [(c[0] * 255.0).round() as u8, (c[1] * 255.0).round() as u8, (c[2] * 255.0).round() as u8]
+        };
+
         let mut labels = Vec::new();
         let list_left = self.scroll_box.base.x;
         let list_top = self.scroll_box.viewport_y;
@@ -466,7 +470,7 @@ impl Element for TreeList {
                         x: list_left + 8.0 + *indent as f32 * 12.0,
                         y: row_y + 6.0,
                         font_size: 12.0,
-                        color: [0x61, 0xaf, 0xef],
+                        color: f32_to_rgb(crate::color::tree_section_text_color()),
                     });
                 }
                 TreeElement::Leaf { name, indent, val, original_idx, .. } => {
@@ -478,9 +482,9 @@ impl Element for TreeList {
                     };
 
                     let color = if Some(*original_idx) == self.selected_key_idx {
-                        [0x7d, 0xff, 0xff]
+                        f32_to_rgb(crate::color::tree_leaf_text_selected_color())
                     } else {
-                        [0xcc, 0xcc, 0xd4]
+                        f32_to_rgb(crate::color::tree_leaf_text_color())
                     };
 
                     labels.push(TextLabel {
@@ -523,7 +527,7 @@ impl Element for TreeList {
                             x: list_left + 190.0,
                             y: row_y + 6.0,
                             font_size: 12.0,
-                            color: [0xc6, 0x78, 0xdd],
+                            color: f32_to_rgb(crate::color::tree_type_text_color()),
                         });
                     }
 
@@ -545,7 +549,7 @@ impl Element for TreeList {
                             x: label_x,
                             y: row_y + 6.0,
                             font_size: 12.0,
-                            color: [0x83, 0x83, 0x8a],
+                            color: f32_to_rgb(crate::color::tree_value_text_color()),
                         });
                     }
                 }
@@ -595,9 +599,9 @@ impl Element for TreeList {
         // Solid border if active
         if let Some((border_color, thickness)) = self.solid_border() {
             quads.push((x, y, w, h, radius, border_color, (r1, r2, r3, r4)));
-            quads.push((x + thickness, y + thickness, w - 2.0 * thickness, h - 2.0 * thickness, radius - thickness, crate::color::list_bg_color(), (r1, r2, r3, r4)));
+            quads.push((x + thickness, y + thickness, w - 2.0 * thickness, h - 2.0 * thickness, radius - thickness, crate::color::tree_background_color(), (r1, r2, r3, r4)));
         } else {
-            quads.push((x, y, w, h, radius, crate::color::list_bg_color(), (r1, r2, r3, r4)));
+            quads.push((x, y, w, h, radius, crate::color::tree_background_color(), (r1, r2, r3, r4)));
         }
 
         for &child_ptr in &self.children(ctx) {