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

commita87d177646feb24363af50c20e69e6b60ceef3b2
parent94d84d07d0
authorLucas Galante <[email protected]>
date2026-07-01 09:30
Implement right-click context menu with key path label, Copy Key, and Copy Value on TreeList rows

 src/widget/container/treelist.rs | 54 ++++++++++++++++++++++++++++++++++++++++
 src/widget/core.rs               |  6 +++++
 src/widget/mod.rs                |  2 ++
 3 files changed, 62 insertions(+)

diff --git a/src/widget/container/treelist.rs b/src/widget/container/treelist.rs
index 9d9974b..785a2f8 100644
--- a/src/widget/container/treelist.rs
+++ b/src/widget/container/treelist.rs
@@ -257,6 +257,36 @@ impl Element for TreeList {
                 }
             }
         }
+
+        if button == MouseButton::Right && state == ElementState::Pressed {
+            if px >= list_left && px <= list_left + list_width && py >= list_top && py <= list_bottom {
+                self.focus();
+                let relative_y = py - list_top + self.scroll_box.scroll_y;
+                let row_idx = (relative_y / self.item_height) as usize;
+                if row_idx < self.items.len() {
+                    let item = self.items[row_idx].clone();
+                    if let TreeElement::Leaf { original_idx, ref path, ref name, indent, ref val } = item {
+                        self.selected_key_idx = Some(original_idx);
+                        self.clicked_item = Some(TreeElement::Leaf {
+                            path: path.clone(),
+                            name: name.clone(),
+                            indent,
+                            val: val.clone(),
+                            original_idx,
+                        });
+                        
+                        let options = vec![
+                            path.clone(),
+                            "Copy Key".to_string(),
+                            "Copy Value".to_string(),
+                        ];
+                        let scroll_offset = crate::widget::hover_animation::get_scroll_offset();
+                        ctx.show_context_menu(px, py - scroll_offset, options, 1, self.as_ptr_mut());
+                        changed = true;
+                    }
+                }
+            }
+        }
         changed
     }
 
@@ -511,6 +541,30 @@ impl Element for TreeList {
     fn clear_children(&mut self, _ctx: &mut UiContext) {
         self.children.clear();
     }
+
+    fn copy_key(&self) {
+        if let Some(idx) = self.selected_key_idx {
+            if idx < self.flat_keys.len() {
+                let key_path = &self.flat_keys[idx].0;
+                clipboard::copy_to_clipboard(key_path);
+            }
+        }
+    }
+
+    fn copy_value(&self) {
+        if let Some(idx) = self.selected_key_idx {
+            if idx < self.flat_keys.len() {
+                let val = &self.flat_keys[idx].1;
+                let val_str = match val {
+                    serde_json::Value::String(s) => s.clone(),
+                    serde_json::Value::Bool(b) => b.to_string(),
+                    serde_json::Value::Number(n) => n.to_string(),
+                    other => serde_json::to_string(other).unwrap_or_default(),
+                };
+                clipboard::copy_to_clipboard(&val_str);
+            }
+        }
+    }
 }
 
 fn parse_hex_f32(s: &str) -> Option<[f32; 4]> {
diff --git a/src/widget/core.rs b/src/widget/core.rs
index 45ec05e..a402534 100644
--- a/src/widget/core.rs
+++ b/src/widget/core.rs
@@ -546,6 +546,12 @@ pub mod context_menu {
                                         "Select All" => {
                                             target.select_all();
                                         }
+                                        "Copy Key" => {
+                                            target.copy_key();
+                                        }
+                                        "Copy Value" => {
+                                            target.copy_value();
+                                        }
                                         _ => {}
                                     }
                                 }
diff --git a/src/widget/mod.rs b/src/widget/mod.rs
index 3cafa77..110e824 100644
--- a/src/widget/mod.rs
+++ b/src/widget/mod.rs
@@ -293,6 +293,8 @@ pub trait Element {
         }
     }
     fn select_all(&mut self) {}
+    fn copy_key(&self) {}
+    fn copy_value(&self) {}
 
     fn set_rect(&mut self, x: f32, y: f32, w: f32, h: f32) {
         if let Some(b) = self.base_mut() {