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
+@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 resignIfFirstResponder];
}
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 @"";
default:
}
- (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 stringForKeyCode:keyCode];
}
- (void)keyDown:(NSEvent *)event {
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;
+ long code = 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 {
// 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<NJKeyInputFieldDelegate, NSTextFieldDelegate>)delegate {
- [super setDelegate:delegate];
-}
-
-- (id <NJKeyInputFieldDelegate, NSTextFieldDelegate>)delegate {
- return (id)[super delegate];
-}
-
@end