Get mouse clicks on NSTokenField

597 Views Asked by At

I would like to implement a NSTokenField that will show Tokens that - when hovering over the token - show a removal icon. Subsequently when I click on the icon I want the token to be removed.

After a lot of searching it seems that this is not possible with the standard NSTokenField. If someone knows how please let me know.

I have taken a look at https://github.com/octiplex/OEXTokenField and based on that code I have made a CustomTokenField implementation in Swift. So far so good I have a working CustomTokenField and when I hover over the token it shows a removal icon.

The next phase turns out to be a problem that I cannot figure out myself. How can I get a click on the token trigger a callback.?

The token class is derived from the NSTextAttachmentCell and the CustomTokenField is derived from the NStokenField:

class CustomTokenAttachmentCell: NSTextAttachmentCell {
    . . .
}

class CustomTokenField: NSTokenField {
    . . .
}

I have tried to approach this using two different angles:

Through the CustomTokenAttachmentCell

The NSTextAttachmentCell implements the NSTextAttachmentCellProtocol.

public protocol NSTextAttachmentCellProtocol : NSObjectProtocol {
    . . .
    public func wantsToTrackMouse() -> Bool
    public func highlight(flag: Bool, withFrame cellFrame: NSRect, inView controlView: NSView?)
    public func trackMouse(theEvent: NSEvent, inRect cellFrame: NSRect, ofView controlView: NSView?, untilMouseUp flag: Bool) -> Bool
    . . .
}

This is hopeful. So I implemented these methods in CustomTokenAttachmentCell and wantsToTrackMouse() is actually being called. I have implemented that to return ‘true’.

override func trackMouse(theEvent: NSEvent, inRect cellFrame: NSRect, ofView controlView: NSView?, untilMouseUp flag: Bool) -> Bool {
    Swift.print(“trackMouse”)
    return true
}

override func highlight(flag: Bool, withFrame cellFrame: NSRect, inView controlView: NSView?) {
    Swift.print("highlight")
}

override func wantsToTrackMouse() -> Bool {
    Swift.print(“trackMouse”)
    return true
}

The other two methods are never called. Is there something else that needs to be done to make that they are being called?

Through the CustomTokenField

I also tried to approach this from the CustomTokenField. It is possible to get mouse events using MouseDown(), however I could not find a way to actually access the Tokens from the cells.

I have seen many posts here on StackOverflow and I have seen tips but none of them seems to point in the right direction.

Somehow I have come to the conclusion that you can only get mouse events in the case there is a NSControl in the hierarchy. For tokens that is not the case. An NSControl is part of the hierarchy for views hence my attempt to achieve this through the CustomTokenField but I run in a dead-end there as well. E.g. this question Clicking token in NSTokenField is exactly the same but setting the action or target will generate a fatal error because the setAction and setTarget are stubs for the base class.

I am a beginning programmer on Coacoa, so hopefully this is just a matter of lack of knowledge.

Any advise would be appreciated.

1

There are 1 best solutions below

3
Gligor On

Have you tried adding an NSButton on top of all of the whole CustomTokenAttachmentCell view? Then add an @IBOutlet action to the button for the click and pass that via delegation to the TokenField where you can control the tokens that are displayed.

I am also trying to implement this in my app, so if you are able to share any of the code it would be greatly appreciated. Thanks!