-1

I need to prevent the popup's menu to be opened when some conditions are met, so I implemented "willOpenMenu" to know when the menu is about to be opened:

class MyPopUpButton: NSPopUpButton { 
    override func willOpenMenu(_ menu: NSMenu, with event: NSEvent) {
        print("willOpenMenu")
        // it fires, but what I can do to prevent menu to be opened??
    }
}

How can I prevent, now, the menu to not show up?

EDIT below, in order, what happens when you click on a popup (Type column), when a "Value" column is under editing enter image description here

enter image description here

Mike97
  • 596
  • 5
  • 20
  • 3
    Disable the button? But you wouldn't do that _in_ this method; you'd do it before this method ever has a chance to be called. Keep the button disabled until the "conditions are met". Learn about validation, bindings, etc. – matt Nov 18 '17 at 15:27
  • mmh, I need the button to be enabled next time (and check it again), also for its appearance. Will this happen with the button disabled? – Mike97 Nov 18 '17 at 15:30
  • edited the previous comment. This popup is inside an outline view (it's a plist editor). making the button disabled will have, as I said a bad look. – Mike97 Nov 18 '17 at 15:34
  • 1
    What will the user think when the popup button doesn't pop up? If a control doesn't work, it should be visible. At least show a menu with the current value. – Willeke Nov 18 '17 at 17:04
  • @Willeke, Yes Is what I want to avoid for a good reason. May be that I was not clear enough. Suppose you click in the "Type" column of the Xcode's plist editor when you have the "Value" column under editing but the current value is a bad "Date string"... the editor ask with an alert if you want "Keep editing". If that happen is because you click outside the "Value" field. The problem is that, if you click on the popup button as well (Type colum), the alert shown... but also the popup button's menu ..on top of the alert. What I want to avoid, but I did not say that it should be not visible. – Mike97 Nov 18 '17 at 19:34
  • ..or be disabled – Mike97 Nov 18 '17 at 19:45
  • In the plist editor, I don't get a menu on top of the alert. In my (quick & dirty) test app, the text field isn't validated when I click on the popup button. – Willeke Nov 18 '17 at 21:40
  • @Willeke I've added some pictures (the site apparently wont allow me to upload more than 2 of it and miss the one where I edited the value column with an invalid date). The outline has this optional func selectionShouldChange(in outlineView: NSOutlineView) -> Bool { return self.outline.wrongValue ? false : true } to determine the row changing. Apparently I need something similar for column changing. NSTableView has it, I wonder if... P.S. this plist editor will be totally free... – Mike97 Nov 18 '17 at 23:34
  • forgot to mention that everythings is programmatically done, no one view comes from IB. – Mike97 Nov 18 '17 at 23:45
  • Is the outline view cell based? – Willeke Nov 19 '17 at 00:11
  • no, is view based....a big work in my free time :-) – Mike97 Nov 19 '17 at 00:16

1 Answers1

1

Finally I found the way:

override func willOpenMenu(_ menu: NSMenu, with event: NSEvent) {
    if (self.outline != nil) {
        /*
         the following is needed when user click on the type column:
         He can have ongoing edits on some rows, so changing first responder
         We can aesily inform the outline that We're playing with something else
         and have to force ask the user in case edits are wrong.
         This also prevent a crash.
         */
        if (self.outline?.wrongValue)! {
            // this grant the popup menu to not showup (or disappear so quickly)
            menu.cancelTrackingWithoutAnimation() 
        }
        self.window?.makeFirstResponder(self)
        self.window?.makeFirstResponder(self.outline)
    }
}

self.outline is a get/set variable. "wrongvalue" works this way:

override func controlTextDidBeginEditing(_ obj: Notification) {
    if obj.object is MyTextField {
        self.outline.wrongValue = true
    }
}

    override func controlTextDidEndEditing(_ obj: Notification) {
        if obj.object is MyTextField {
            /*
             some code here to check if stringValue is ok for the selected tag, otherwise
             show the relative alert, the popup menu will not show up anymore
             because cancelTracking is called on it
             */
            self.outline.wrongValue = false
        }
    }

cancelTracking() was the key!

Mike97
  • 596
  • 5
  • 20