How do you handle a double click on a ruler?

48 Views Asked by At

I have a ruler in SwiftUI that looks like this:

struct RulerScrollView<Content: View>: NSViewRepresentable {
    @ObservedObject var dm: DrawModel
    let content: Content

    init(_ dm: DrawModel, @ViewBuilder content: () -> Content ) {
        self.dm             = dm
        self.content        = content()
    }

    override func mouseDown(with event: NSEvent) {
         if event.clickCount == 2 {
              NotificationCenter.default.post(name: Notification.Name("ShowRulerSettings"), object: nil)
         }
    }

    func makeNSView(context: Context) -> NSScrollView {
        let scrollView = NSScrollView()
        scrollView.hasVerticalRuler = true
        scrollView.hasHorizontalRuler = true
        scrollView.rulersVisible = dm.showRulers

        let hostingView = NSHostingView(rootView: content)
        hostingView.wantsLayer = true
        hostingView.layer?.backgroundColor = NSColor.white.cgColor
        scrollView.documentView = hostingView

        return scrollView
    }

    func updateNSView(_ nsView: NSScrollView, context: Context) {
             nsView.rulersVisible = dm.showRulers
    }
}

Which is called like this:

Stack {
    RulerScrollView( dm ) {
        DrawingView( dm )
            .onReceive(dm.$showRulerSettings) { isShowingRulerSettings = $0 }
    }
    .background(Color.white)
}
.alert(isPresented: $isShowingRulerSettings) {
 Alert(title: Text("Ruler Settings"), message: Text("Settings here"), primaryButton: .default(Text("OK")), secondaryButton: .cancel()) }

Unfortunately I get this error:

'override' can only be specified on class members

1

There are 1 best solutions below

0
Keith On

I added this to my RulerView:

func makeCoordinator() -> Coordinator {
     Coordinator(onRulerDoubleClick: onRulerDoubleClick)
}

class Coordinator: NSObject {
    var onRulerDoubleClick: () -> Void
     
    init(onRulerDoubleClick: @escaping () -> Void) {
          self.onRulerDoubleClick = onRulerDoubleClick
    }
     
    @objc func handleRulerDoubleClick(_ gestureRecognizer: NSClickGestureRecognizer) {
         onRulerDoubleClick() // Trigger the callback for double-click event
    }
}

I added this to makeNSView:

let horizontal = NSClickGestureRecognizer(target: context.coordinator, action: #selector(Coordinator.handleRulerDoubleClick))
horizontal.numberOfClicksRequired = 2
scrollView.horizontalRulerView?.addGestureRecognizer(horizontal)

let vertical = NSClickGestureRecognizer(target: context.coordinator, action: #selector(Coordinator.handleRulerDoubleClick))
vertical.numberOfClicksRequired = 2
scrollView.verticalRulerView?.addGestureRecognizer(vertical)

Then I called it like this:

RulerView( dm ) {
    DrawingView( dm )
} onRulerDoubleClick: { isShowingRulerSettings.toggle( )}
.popover(isPresented: $isShowingRulerSettings, arrowEdge: .trailing) {
     RulerSettings( dm )
}

I find NS a bit painful and I'm hoping SwiftUI continues to grow. :) The popover is not showing up in the right place (on the ruler). It's on the content window. One step at a time :)