Browse Source

Fix draw canvas undo and redo buttons not responding to clicks.

Route button hits before drawing gestures, keep controls visible above text fields, and refresh enabled state when snapshots are pushed.

Co-authored-by: Cursor <cursoragent@cursor.com>
AhtashamShahzad1 1 month ago
parent
commit
9e41126dab
1 changed files with 32 additions and 11 deletions
  1. 32 11
      smart_printer/DrawPrintView.swift

+ 32 - 11
smart_printer/DrawPrintView.swift

@@ -177,10 +177,6 @@ final class DrawPrintOverlayView: NSView, AppearanceRefreshable {
             self?.pickImage()
         }
 
-        canvasView.onUndoStateChanged = { [weak self] canUndo, canRedo in
-            self?.canvasView.updateUndoButtons(canUndo: canUndo, canRedo: canRedo)
-        }
-
         canvasContainer.addSubview(canvasView)
 
         addSubview(backButton)
@@ -292,11 +288,6 @@ final class BlankCanvasView: NSView, AppearanceRefreshable {
         redoButton.refreshAppearance()
     }
 
-    func updateUndoButtons(canUndo: Bool, canRedo: Bool) {
-        undoButton.setActionEnabled(canUndo)
-        redoButton.setActionEnabled(canRedo)
-    }
-
     private func setup() {
         wantsLayer = true
         layer?.cornerRadius = AppTheme.contentPanelCornerRadius
@@ -324,6 +315,26 @@ final class BlankCanvasView: NSView, AppearanceRefreshable {
         ])
     }
 
+    override func hitTest(_ point: NSPoint) -> NSView? {
+        for button in [redoButton, undoButton] {
+            let localPoint = convert(point, to: button)
+            if let hit = button.hitTest(localPoint) {
+                return hit
+            }
+        }
+        return super.hitTest(point)
+    }
+
+    private func bringUndoButtonsToFront() {
+        addSubview(redoButton, positioned: .above, relativeTo: nil)
+        addSubview(undoButton, positioned: .below, relativeTo: redoButton)
+    }
+
+    private func updateUndoButtons(canUndo: Bool, canRedo: Bool) {
+        undoButton.setActionEnabled(canUndo)
+        redoButton.setActionEnabled(canRedo)
+    }
+
     override func draw(_ dirtyRect: NSRect) {
         NSColor.white.setFill()
         NSBezierPath(
@@ -364,6 +375,9 @@ final class BlankCanvasView: NSView, AppearanceRefreshable {
 
     override func mouseDown(with event: NSEvent) {
         let point = convert(event.locationInWindow, from: nil)
+        if undoButton.frame.contains(point) || redoButton.frame.contains(point) {
+            return
+        }
 
         switch activeTool {
         case .draw:
@@ -487,6 +501,7 @@ final class BlankCanvasView: NSView, AppearanceRefreshable {
         undoStack.append(CanvasSnapshot(strokes: strokes, texts: textItems, images: imageItems))
         redoStack.removeAll()
         if undoStack.count > 50 { undoStack.removeFirst() }
+        notifyUndoState()
     }
 
     private func undo() {
@@ -511,13 +526,16 @@ final class BlankCanvasView: NSView, AppearanceRefreshable {
         for item in textItems {
             installTextField(for: item)
         }
+        bringUndoButtonsToFront()
         needsDisplay = true
         notifyUndoState()
     }
 
     private func notifyUndoState() {
-        onUndoStateChanged?(!undoStack.isEmpty, !redoStack.isEmpty)
-        updateUndoButtons(canUndo: !undoStack.isEmpty, canRedo: !redoStack.isEmpty)
+        let canUndo = !undoStack.isEmpty
+        let canRedo = !redoStack.isEmpty
+        onUndoStateChanged?(canUndo, canRedo)
+        updateUndoButtons(canUndo: canUndo, canRedo: canRedo)
     }
 
     private func installTextField(for item: CanvasTextData) {
@@ -533,6 +551,7 @@ final class BlankCanvasView: NSView, AppearanceRefreshable {
         field.target = self
         field.action = #selector(textFieldEdited(_:))
         addSubview(field)
+        bringUndoButtonsToFront()
     }
 
     @objc private func textFieldEdited(_ sender: NSTextField) {
@@ -899,6 +918,8 @@ private final class CanvasHistoryButton: NSControl, AppearanceRefreshable {
         actionEnabled = enabled
     }
 
+    override func mouseDown(with event: NSEvent) {}
+
     override func mouseUp(with event: NSEvent) {
         guard actionEnabled, bounds.contains(convert(event.locationInWindow, from: nil)) else { return }
         onClick?()