Get mouse clicks on NSTokenField
Asked Answered
R

1

7

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.

Ridgway answered 26/8, 2016 at 18:23 Comment(15)
Did you try implementing the other TrackMouse methods of the NSTextAttachmentCell protocol?Jd
Yes I did. I also implemented hitTestForEvent(event: NSEvent, inRect cellFrame: NSRect, ofView controlView: NSView) and wantsToTrackMouseForEvent(theEvent: NSEvent, inRect cellFrame: NSRect, ofView controlView: NSView?, atCharacterIndex charIndex: Int). No change.Ridgway
OEXTokenField implements NSTextViewDelegate method textView:clickedOnCell:inRect:atIndex:.Jd
I am aware and the problem is that doesn't get called. That is also a part I didn't understand from that code. I implemented it to be complete but it was never called. Also it is the token that should receive the mouse events and not the TokenField. I can get the mouse position in the TokenField but I don't know how to map this on the Token.Ridgway
clickedOnCell is called in OEXTokenField because the tokenfield is the delegate of the field editor.Jd
Can't you add a transparant area to the removal icon to catch mousedowns?Jd
I will try both suggestions. Thank you.Ridgway
@Willeke: Can you be a bit more specific? The delegate of the CustomTokenField is of the type NSTokenFieldDelegate and it inherits from NSTextFieldDelegate and not NSTextViewDelegate. The NSTextFieldDelegate doesn't have the mouse methods because it isn't a view. Am I missing what you suggested?Ridgway
Do you know what the field editor is?Jd
Apparently not. Please explain.Ridgway
The field editor is a single NSTextView object that is shared among all the controls, including text fields, in a window. The focused text field uses this text view for editing. The focused text field is the delegate of the text view. and can implement NSTextViewDelegate methods.Jd
Is the token field focused or should click also work when another control has focus?Jd
The token field has focus. Let me look into this and see if this leads to a solution. Thank you for your support.Ridgway
@Willeke: Again thank you for your patience. I am still running in a dead end. I have read everything I could about the Field Editor and it seems that the Field Editor only gets enabled when the content is being edited. In my case there is no editing, just clicking. I have tried to access the Field Editor through the Window and setup the delegate before hand but that doesn't seem to work. Am I wrong in concluding it only works if I'm editing? Currently the behavior of the TokenField is set to 'None'.Ridgway
Apparently behavior None is not going to work. Is behavior Selectable an option?Jd
L
0

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!

Localism answered 23/4, 2017 at 21:40 Comment(3)
I have not tried that. In the end I have given up on this, I could not solve it.Ridgway
Have you achieved what you said? I'm also looking for it. Can you give me some help?Oven
@DivenLee I can't remember to be honest, I stopped working on that project nearly 2 years ago now :( sorryLocalism

© 2022 - 2024 — McMap. All rights reserved.