I want to add the ability to use a date picker when editing a particular column in my table view, and used the code snippet from here, which worked well. However NSDatePicker
is not appropriate for my needs so I am using my own custom view, created using IB and loaded via a NSViewController
subclass to edit the date.
However I cannot figure out how to dismiss the pop-up menu in a way that accepts the edit, i.e. returns YES
in userAcceptedEdit
:
BOOL userAcceptedEdit = [menu popUpMenuPositioningItem:nil
atLocation:frame.origin
inView:tableView];
This was working fine when NSDatePicker
was the menu's view, but not with my custom view.
I am trapping the enter key actions from the text fields in my custom view, but all I can figure out is how to cancel the menu tracking which makes userAcceptedEdit == NO
:
MyCustomViewController.mm:
- (IBAction)textFieldAction:(id)sender {
logdbg(@"Action");
NSMenu* menu = [[self.view enclosingMenuItem] menu];
[menu cancelTracking];
}
The Views in Menu Items section of Apple's Application Menu and Pop-up List Programming Topics doesn't cover it either...
EDIT Here is a sample project, that demonstrates the issue.
Can someone provide some guidance please?
You should also be able to set the textFields' delegate to the NSViewController, implement NSTextFieldDelegate within the ViewController and do something like this
- (void)controlTextDidEndEditing:(NSNotification *)aNotification{
// NSTextField * textField = [aNotification object];
NSUInteger whyEnd = [[[aNotification userInfo] objectForKey:@"NSTextMovement"] unsignedIntValue];
if(whyEnd == NSReturnTextMovement){
// Create new event here using the below routine
/*
[[self window] keyDown: [NSEvent keyEventWithType:(NSEventType)type
location:(NSPoint)location
modifierFlags:(NSUInteger)flags
timestamp:(NSTimeInterval)time
windowNumber:(NSInteger)windowNum
context:(NSGraphicsContext *)context
characters:(NSString *)characters
charactersIgnoringModifiers:(NSString *)unmodCharacters
isARepeat:(BOOL)repeatKey
keyCode:(unsigned short)code]
];
*/
}
}
Here you are essentially TRANSLATING the notification to an EVENT by creating a NEW event to pass along to the parent view
Should also be noted that this becomes the central "dispatch" return catcher for all textfields.
Here is a great link on using the NSEvent creation methods: http://advinprog.blogspot.com/2008/06/so-you-want-to-post-keyboard-event-in.html
Notice in this writeup how the simulate a key_down and a key_up!!!
Ha! Did it. Changed the NSTextField
to NSTextView
, subclassed it, and here we go:
@interface LNTextView : NSTextView
@end
@implementation LNTextView
- (void)keyDown:(NSEvent *)theEvent
{
if(theEvent.keyCode == 36)
{
[[self window] keyDown:theEvent];
}
}
@end
I noticed that, normally, when enter key is pressed on NSDatePicker
, the keyDown:
eventually goes to the menu's window and then it is accepted. So this is what I did here. NSTextField
uses a text view internally, so it cannot hear keyDown:
messages, thus the need to switch to full blown NSTextView
instead.
You could still use your text field, and create a new NSEvent
using + (NSEvent *)keyEventWithType:(NSEventType)type location:(NSPoint)location modifierFlags:(NSUInteger)flags timestamp:(NSTimeInterval)time windowNumber:(NSInteger)windowNum context:(NSGraphicsContext *)context characters:(NSString *)characters charactersIgnoringModifiers:(NSString *)unmodCharacters isARepeat:(BOOL)repeatKey keyCode:(unsigned short)code
in your action method, passing it to the field's window instead of calling cancelTracking
on the menu.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With