macosswiftuiappkitnsbutton

NSButton inside a NSViewRepresentable gives no "visual feedback" if clicked


I built a NativeButton based on a NSButton with a NSViewRepresentable to detect Rightclicks.
It works fine, but I do not get "visual feedback" as with a normal Button, if it's clicked.
How can I accomplish that the Button get dark, if it's clicked (as any normal Button)?

struct TEST_NativeButton: View {
  var body: some View {
    VStack{
      Text("Test Native Button")
      NativeButton(
        rightClickAction: {print("rightclick")},
        leftClickAction: {print("leftclick")}
      )
      { print("standard action")
      }
    }.frame(width: 200, height: 200)
  }
}

struct NativeButton: NSViewRepresentable {
  typealias NSViewType = NativeNSButton

  let rightClickAction: ActionFunction
  let leftClickAction: ActionFunction
  let standardAction: ActionFunction

  init(
        rightClickAction : ActionFunction?  = nil,
        leftClickAction :  ActionFunction?  = nil,
        standardAction:    @escaping ActionFunction
  )
  {
    if let rightClickAction = rightClickAction{
      self.rightClickAction = rightClickAction
    } else {
      self.rightClickAction = {}
    }

    if let  leftClickAction = leftClickAction{
      self.leftClickAction = leftClickAction
    } else {
      self.leftClickAction = standardAction
    }

    self.standardAction = standardAction

  }

  func makeNSView(context: Context) -> NativeNSButton {
    NativeNSButton(
                  rightClickAction: rightClickAction,
                  leftClickAction: leftClickAction,
                  standardAction: standardAction)
  }

  func updateNSView(_ nsView: NativeNSButton, context: Context) {
    //ToDo auf änderungen am Titel reagieren
    return
  }
}

class NativeNSButton: NSButton {
  let standardAction: () -> Void
  let rightClickAction: () -> Void
  let leftClickAction: () -> Void

  init(
        rightClickAction : @escaping () -> Void,
        leftClickAction :  @escaping () -> Void,
        standardAction:    @escaping () -> Void) {

    self.standardAction = standardAction
    self.rightClickAction = rightClickAction
    self.leftClickAction = leftClickAction

    super.init(frame: .zero)

    self.title = title
    self.alignment = alignment
    self.target = self
    self.action = #selector(clickButton(_:))

    bezelStyle = .rounded
    isBordered = true
    focusRingType = .none

    self.translatesAutoresizingMaskIntoConstraints = false
    self.setContentHuggingPriority(.defaultHigh, for: .vertical)
    self.setContentHuggingPriority(.defaultHigh, for: .horizontal)
  }

  required init?(coder: NSCoder) {
    fatalError()
  }

  override func mouseDown(with theEvent: NSEvent) {
    //print("left mouse")
    leftClickAction()
  }

  override func rightMouseDown(with theEvent: NSEvent) {
    //print("right mouse")
    rightClickAction()
  }

  @objc func clickButton(_ sender: BbcNSButton) {
    //print("standard action")
    standardAction()
  }
}

The standard action is used for detection Keyboard-Shortcuts (removed in this example).


Solution

  • Call super method

    override func mouseDown(with theEvent: NSEvent) {
        super.mouseDown(with: theEvent)
        //print("left mouse")
        leftClickAction()
      }