X-Git-Url: https://git.yukkurigames.com/?p=enjoyable.git;a=blobdiff_plain;f=Classes%2FNJKeyInputField.m;h=3cdbd7ce63b84747167a81ca5a923174ef6d1282;hp=2bdbfc6c7a64840e83b953f36506fa4fb059b88e;hb=baa03e73a5af66b725f58fa5efd04bf54b7b2eed;hpb=4078855cc6ff4cdf6d6f7032f511a73b44f70837 diff --git a/Classes/NJKeyInputField.m b/Classes/NJKeyInputField.m index 2bdbfc6..3cdbd7c 100644 --- a/Classes/NJKeyInputField.m +++ b/Classes/NJKeyInputField.m @@ -12,26 +12,50 @@ enum { kVK_RightCommand = kVK_Command - 1, + kVK_Insert = 0x72, + kVK_Power = 0x7f, + kVK_ApplicationMenu = 0x6e, kVK_MAX = 0xFFFF, }; const CGKeyCode NJKeyInputFieldEmpty = kVK_MAX; -@implementation NJKeyInputField +@interface NJKeyInputField () +@end + +@implementation NJKeyInputField { + NSTextField *field; + NSImageView *warning; +} - (id)initWithFrame:(NSRect)frameRect { if ((self = [super initWithFrame:frameRect])) { - self.alignment = NSCenterTextAlignment; - self.editable = NO; - self.selectable = NO; + field = [[NSTextField alloc] initWithFrame:self.bounds]; + field.alignment = NSCenterTextAlignment; + field.editable = NO; + field.selectable = NO; + field.delegate = self; + [self addSubview:field]; + + warning = [[NSImageView alloc] init]; + warning.image = [NSImage imageNamed:@"NSInvalidDataFreestanding"]; + CGSize imgSize = warning.image.size; + CGRect bounds = self.bounds; + warning.frame = CGRectMake(bounds.size.width - (imgSize.width + 4), + (bounds.size.height - imgSize.height) / 2, + imgSize.width, imgSize.height); + + warning.toolTip = NSLocalizedString(@"invalid key code", + @"shown when the user types an invalid key code"); + warning.hidden = YES; + [self addSubview:warning]; } return self; } - (void)clear { self.keyCode = NJKeyInputFieldEmpty; - if ([self.delegate respondsToSelector:@selector(keyInputFieldDidClear:)]) - [self.delegate keyInputFieldDidClear:self]; + [self.delegate keyInputFieldDidClear:self]; [self resignIfFirstResponder]; } @@ -39,7 +63,7 @@ const CGKeyCode NJKeyInputFieldEmpty = kVK_MAX; return self.keyCode != NJKeyInputFieldEmpty; } -+ (NSString *)stringForKeyCode:(CGKeyCode)keyCode { ++ (NSString *)displayNameForKeyCode:(CGKeyCode)keyCode { switch (keyCode) { case kVK_F1: return @"F1"; case kVK_F2: return @"F2"; @@ -173,7 +197,15 @@ const CGKeyCode NJKeyInputFieldEmpty = kVK_MAX; return NSLocalizedString(@"Key Pad ,", @"numeric pad key"); case kVK_JIS_Eisu: return @"英数"; case kVK_JIS_Kana: return @"かな"; - + + case kVK_Power: return @"⌽"; + case kVK_VolumeUp: return @"🔊"; + case kVK_VolumeDown: return @"🔉"; + + case kVK_Insert: + return NSLocalizedString(@"Insert", "keyboard key"); + case kVK_ApplicationMenu: + return NSLocalizedString(@"Menu", "keyboard key"); case kVK_MAX: // NJKeyInputFieldEmpty return @""; @@ -189,18 +221,18 @@ const CGKeyCode NJKeyInputFieldEmpty = kVK_MAX; } - (BOOL)becomeFirstResponder { - self.backgroundColor = NSColor.selectedTextBackgroundColor; + field.backgroundColor = NSColor.selectedTextBackgroundColor; return [super becomeFirstResponder]; } - (BOOL)resignFirstResponder { - self.backgroundColor = NSColor.textBackgroundColor; + field.backgroundColor = NSColor.textBackgroundColor; return [super resignFirstResponder]; } - (void)setKeyCode:(CGKeyCode)keyCode { _keyCode = keyCode; - self.stringValue = [NJKeyInputField stringForKeyCode:keyCode]; + field.stringValue = [NJKeyInputField displayNameForKeyCode:keyCode]; } - (void)keyDown:(NSEvent *)event { @@ -209,22 +241,59 @@ const CGKeyCode NJKeyInputFieldEmpty = kVK_MAX; if ((event.modifierFlags & IGNORE) && event.keyCode == kVK_Delete) { // Allow Alt/Command+Delete to clear the field. self.keyCode = NJKeyInputFieldEmpty; - if ([self.delegate respondsToSelector:@selector(keyInputFieldDidClear:)]) - [self.delegate keyInputFieldDidClear:self]; + [self.delegate keyInputFieldDidClear:self]; } else if (!(event.modifierFlags & IGNORE)) { self.keyCode = event.keyCode; - if ([self.delegate respondsToSelector:@selector(keyInputField:didChangeKey:)]) - [self.delegate keyInputField:self didChangeKey:self.keyCode]; + [self.delegate keyInputField:self didChangeKey:self.keyCode]; } [self resignIfFirstResponder]; } } + +static BOOL isValidKeyCode(long code) { + return code < 0xFFFF && code >= 0; +} + +- (void)controlTextDidChange:(NSNotification *)obj { + char *error = NULL; + long code = strtol(field.stringValue.UTF8String, &error, 16); + warning.hidden = (isValidKeyCode(code) && !*error) || !field.stringValue.length; +} + +- (void)controlTextDidEndEditing:(NSNotification *)obj { + [field.cell setPlaceholderString:@""]; + field.editable = NO; + field.selectable = NO; + warning.hidden = YES; + char *error = NULL; + const char *s = field.stringValue.UTF8String; + short code = (short)strtol(s, &error, 16); + if (!*error && isValidKeyCode(code) && field.stringValue.length) { + self.keyCode = code; + [self.delegate keyInputField:self didChangeKey:self.keyCode]; + } else { + self.keyCode = self.keyCode; + } +} + - (void)mouseDown:(NSEvent *)theEvent { - if (self.window.firstResponder == self) - [self.window makeFirstResponder:nil]; - else if (self.acceptsFirstResponder) - [self.window makeFirstResponder:self]; + if (self.isEnabled) { + if (theEvent.modifierFlags & NSCommandKeyMask) { + field.editable = YES; + field.selectable = YES; + field.stringValue = @""; + [field.cell setPlaceholderString: + NSLocalizedString(@"enter key code", + @"shown when user must enter a key code to map to")]; + [self.window makeFirstResponder:field]; + } else { + if (self.window.firstResponder == self) + [self.window makeFirstResponder:nil]; + else if (self.acceptsFirstResponder) + [self.window makeFirstResponder:self]; + } + } } - (void)flagsChanged:(NSEvent *)theEvent { @@ -234,19 +303,11 @@ const CGKeyCode NJKeyInputFieldEmpty = kVK_MAX; // user type these virtual keys. However, there is no actual event // for modifier key up - so detect it by checking to see if any // modifiers are still down. - if (!(theEvent.modifierFlags & NSDeviceIndependentModifierFlagsMask)) { + if (!field.isEditable + && !(theEvent.modifierFlags & NSDeviceIndependentModifierFlagsMask)) { self.keyCode = theEvent.keyCode; - if ([self.delegate respondsToSelector:@selector(keyInputField:didChangeKey:)]) - [self.delegate keyInputField:self didChangeKey:_keyCode]; + [self.delegate keyInputField:self didChangeKey:_keyCode]; } } -- (void)setDelegate:(id)delegate { - [super setDelegate:delegate]; -} - -- (id )delegate { - return (id)[super delegate]; -} - @end