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

commita2f8f3e9aafa5afa1aed03aa9efa523f6a9763f0
parent62061adb0f
authorLucas Galante <[email protected]>
date2026-07-03 17:24
feat: add support for Ctrl-scroll pinch zoom on Graph canvas

 src/widget/display/graph.rs | 46 ++++++++++++++++++++++++++++++++++++---------
 1 file changed, 37 insertions(+), 9 deletions(-)

diff --git a/src/widget/display/graph.rs b/src/widget/display/graph.rs
index 9c031a4..e3982fc 100644
--- a/src/widget/display/graph.rs
+++ b/src/widget/display/graph.rs
@@ -209,6 +209,16 @@ impl Graph {
             self.skipped_col_w /= 1.1;
         }
     }
+
+    pub fn zoom_by_factor(&mut self, factor: f32) {
+        let new_grid_x = self.grid_size_x * factor;
+        if new_grid_x >= 40.0 && new_grid_x <= 400.0 {
+            self.grid_size_x = new_grid_x;
+            self.grid_size_y *= factor;
+            self.skipped_row_h *= factor;
+            self.skipped_col_w *= factor;
+        }
+    }
 }
 
 fn read_zoom_bindings() -> (String, String) {
@@ -958,16 +968,34 @@ impl Element for Graph {
 
     fn mouse_wheel(&mut self, delta: &MouseScrollDelta, px: f32, py: f32, ctx: &mut UiContext) -> bool {
         if self.hit_test(px, py, ctx) {
-            match delta {
-                MouseScrollDelta::LineDelta(x, y) => {
-                    self.grid_origin_x += *x * 15.0;
-                    self.grid_origin_y += *y * 15.0;
-                    true
+            if ctx.ctrl_pressed {
+                match delta {
+                    MouseScrollDelta::LineDelta(_x, y) => {
+                        if *y > 0.0 {
+                            self.zoom_by_factor(1.1);
+                        } else if *y < 0.0 {
+                            self.zoom_by_factor(1.0 / 1.1);
+                        }
+                        true
+                    }
+                    MouseScrollDelta::PixelDelta(pos) => {
+                        let factor = 1.0 + (pos.y as f32 * 0.015);
+                        self.zoom_by_factor(factor);
+                        true
+                    }
                 }
-                MouseScrollDelta::PixelDelta(pos) => {
-                    self.grid_origin_x += pos.x as f32;
-                    self.grid_origin_y += pos.y as f32;
-                    true
+            } else {
+                match delta {
+                    MouseScrollDelta::LineDelta(x, y) => {
+                        self.grid_origin_x += *x * 15.0;
+                        self.grid_origin_y += *y * 15.0;
+                        true
+                    }
+                    MouseScrollDelta::PixelDelta(pos) => {
+                        self.grid_origin_x += pos.x as f32;
+                        self.grid_origin_y += pos.y as f32;
+                        true
+                    }
                 }
             }
         } else {