Как принять редактирование и отклонить всплывающее меню, содержащее пользовательский вид?
Я хочу добавить возможность использования выбора даты при редактировании определенного столбца в моем представлении таблицы и использовать фрагмент кода из здесь, который работал хорошо. Однако NSDatePicker
не подходит для моих нужд, поэтому я использую собственное собственное представление, созданное с помощью IB и загружаемое через подкласс NSViewController
для редактирования даты.
Однако я не могу понять, как отклонить всплывающее меню таким образом, который принимает редактирование, т.е. возвращает YES
в userAcceptedEdit
:
BOOL userAcceptedEdit = [menu popUpMenuPositioningItem:nil
atLocation:frame.origin
inView:tableView];
Это прекрасно работало, когда NSDatePicker
был видом меню, но не с моим пользовательским представлением.
Я улавливаю действия клавиш ввода из текстовых полей в своем пользовательском представлении, но все, что я могу выяснить, - это отменить отслеживание меню, которое делает userAcceptedEdit == NO
:
MyCustomViewController.mm:
- (IBAction)textFieldAction:(id)sender {
logdbg(@"Action");
NSMenu* menu = [[self.view enclosingMenuItem] menu];
[menu cancelTracking];
}
Представления в пунктах меню в разделе "Меню приложений Apple" и "Всплывающие списки" не охватывают его также...
EDIT Вот образец проекта, который демонстрирует проблему.
Может ли кто-нибудь дать некоторые рекомендации?
Ответы
Ответ 1
Вы также должны установить делегат textFields в NSViewController, реализовать NSTextFieldDelegate в ViewController и сделать что-то вроде этого
- (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]
];
*/
}
}
Здесь вы, по сути, ПЕРЕВЕСТИ ИЗОБРЕТЕНИЯ к СОБЫТИЮ, создав новое событие, чтобы перейти к родительскому представлению
Следует также отметить, что это становится центральной утилитой возврата отправки для всех текстовых полей.
Вот отличная ссылка на использование методов создания NSEvent:
http://advinprog.blogspot.com/2008/06/so-you-want-to-post-keyboard-event-in.html
Обратите внимание на эту запись, как имитировать key_down и key_up!!!
Ответ 2
Ха! Сделал это. Изменен NSTextField
на NSTextView
, подклассифицирован он, и вот мы идем:
@interface LNTextView : NSTextView
@end
@implementation LNTextView
- (void)keyDown:(NSEvent *)theEvent
{
if(theEvent.keyCode == 36)
{
[[self window] keyDown:theEvent];
}
}
@end
Я заметил, что обычно, когда клавиша ввода нажата на NSDatePicker
, keyDown:
в конечном итоге переходит в окно меню, а затем принимается. Так вот что я здесь сделал. NSTextField
использует текстовый вид внутри, поэтому он не может слышать сообщения keyDown:
, поэтому нужно переключиться на полноэкранный NSTextView
.
Вы все равно можете использовать свое текстовое поле и создать новый NSEvent
с помощью + (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
в своем методе действий, передав его в окно поля вместо вызова cancelTracking
в меню.