소스 검색

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 개월 전
부모
커밋
9e41126dab
1개의 변경된 파일32개의 추가작업 그리고 11개의 파일을 삭제
  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?()