Rewrite KeyInputTextView into NJKeyInputField. New class communicates using a proper...
authorJoe Wreschnig <joe.wreschnig@gmail.com>
Sun, 3 Mar 2013 14:24:36 +0000 (15:24 +0100)
committerJoe Wreschnig <joe.wreschnig@gmail.com>
Sun, 3 Mar 2013 14:24:36 +0000 (15:24 +0100)
English.lproj/MainMenu.xib
Enjoyable.xcodeproj/project.pbxproj
KeyInputTextView.h [deleted file]
KeyInputTextView.m [deleted file]
NJKeyInputField.h [new file with mode: 0644]
NJKeyInputField.m [new file with mode: 0644]
TargetController.h
TargetController.m
TargetKeyboard.m

index 6797fb3..6e87fb0 100644 (file)
                                                                                        <string key="NSFrame">{{227, 55}, {180, 24}}</string>
                                                                                        <reference key="NSSuperview" ref="606740242"/>
                                                                                        <reference key="NSWindow"/>
-                                                                                       <reference key="NSNextKeyView"/>
                                                                                        <string key="NSReuseIdentifierKey">_NS:9</string>
                                                                                        <bool key="NSEnabled">YES</bool>
                                                                                        <object class="NSSegmentedCell" key="NSCell" id="301345285">
                                                                                        <reference key="NSWindow"/>
                                                                                        <reference key="NSNextKeyView" ref="194275224"/>
                                                                                        <string key="NSReuseIdentifierKey">_NS:9</string>
-                                                                                       <string key="NSClassName">KeyInputTextView</string>
+                                                                                       <string key="NSClassName">NJKeyInputField</string>
                                                                                </object>
                                                                                <object class="NSPopUpButton" id="194275224">
                                                                                        <reference key="NSNextResponder" ref="606740242"/>
                                                <string key="NSFrame">{{57, 4}, {39, 28}}</string>
                                                <reference key="NSSuperview" ref="671181514"/>
                                                <reference key="NSWindow"/>
-                                               <reference key="NSNextKeyView"/>
                                                <bool key="NSEnabled">YES</bool>
                                                <object class="NSButtonCell" key="NSCell" id="1008023024">
                                                        <int key="NSCellFlags">603979776</int>
                                </object>
                                <object class="IBConnectionRecord">
                                        <object class="IBOutletConnection" key="connection">
-                                               <string key="label">targetController</string>
+                                               <string key="label">keyDelegate</string>
                                                <reference key="source" ref="57697638"/>
                                                <reference key="destination" ref="801536542"/>
                                        </object>
-                                       <int key="connectionID">779</int>
-                               </object>
-                               <object class="IBConnectionRecord">
-                                       <object class="IBOutletConnection" key="connection">
-                                               <string key="label">window</string>
-                                               <reference key="source" ref="57697638"/>
-                                               <reference key="destination" ref="808667431"/>
-                                       </object>
-                                       <int key="connectionID">780</int>
+                                       <int key="connectionID">818</int>
                                </object>
                        </array>
                        <object class="IBMutableOrderedSet" key="objectRecords">
                        <nil key="activeLocalization"/>
                        <dictionary class="NSMutableDictionary" key="localizations"/>
                        <nil key="sourceID"/>
-                       <int key="maxID">816</int>
+                       <int key="maxID">818</int>
                </object>
                <object class="IBClassDescriber" key="IBDocument.Classes">
                        <array class="NSMutableArray" key="referencedPartialClassDescriptions">
                                                </object>
                                        </dictionary>
                                        <dictionary class="NSMutableDictionary" key="outlets">
-                                               <string key="exportButton">NSButton</string>
                                                <string key="removeButton">NSButton</string>
                                                <string key="tableView">NSTableView</string>
                                                <string key="targetController">TargetController</string>
                                        </dictionary>
                                        <dictionary class="NSMutableDictionary" key="toOneOutletInfosByName">
-                                               <object class="IBToOneOutletInfo" key="exportButton">
-                                                       <string key="name">exportButton</string>
-                                                       <string key="candidateClassName">NSButton</string>
-                                               </object>
                                                <object class="IBToOneOutletInfo" key="removeButton">
                                                        <string key="name">removeButton</string>
                                                        <string key="candidateClassName">NSButton</string>
                                        </object>
                                </object>
                                <object class="IBPartialClassDescription">
-                                       <string key="className">KeyInputTextView</string>
+                                       <string key="className">NJKeyInputField</string>
                                        <string key="superclassName">NSTextField</string>
-                                       <dictionary class="NSMutableDictionary" key="outlets">
-                                               <string key="targetController">TargetController</string>
-                                               <string key="window">NSWindow</string>
-                                       </dictionary>
-                                       <dictionary class="NSMutableDictionary" key="toOneOutletInfosByName">
-                                               <object class="IBToOneOutletInfo" key="targetController">
-                                                       <string key="name">targetController</string>
-                                                       <string key="candidateClassName">TargetController</string>
-                                               </object>
-                                               <object class="IBToOneOutletInfo" key="window">
-                                                       <string key="name">window</string>
-                                                       <string key="candidateClassName">NSWindow</string>
+                                       <object class="NSMutableDictionary" key="outlets">
+                                               <string key="NS.key.0">keyDelegate</string>
+                                               <string key="NS.object.0">id</string>
+                                       </object>
+                                       <object class="NSMutableDictionary" key="toOneOutletInfosByName">
+                                               <string key="NS.key.0">keyDelegate</string>
+                                               <object class="IBToOneOutletInfo" key="NS.object.0">
+                                                       <string key="name">keyDelegate</string>
+                                                       <string key="candidateClassName">id</string>
                                                </object>
-                                       </dictionary>
+                                       </object>
                                        <object class="IBClassDescriptionSource" key="sourceIdentifier">
                                                <string key="majorKey">IBProjectSource</string>
-                                               <string key="minorKey">./Classes/KeyInputTextView.h</string>
+                                               <string key="minorKey">./Classes/NJKeyInputField.h</string>
                                        </object>
                                </object>
                                <object class="IBPartialClassDescription">
                                                <string key="configPopup">NSPopUpButton</string>
                                                <string key="configsController">ConfigsController</string>
                                                <string key="joystickController">JoystickController</string>
-                                               <string key="keyInput">KeyInputTextView</string>
+                                               <string key="keyInput">NJKeyInputField</string>
                                                <string key="mouseBtnSelect">NSSegmentedControl</string>
                                                <string key="mouseDirSelect">NSSegmentedControl</string>
                                                <string key="radioButtons">NSMatrix</string>
                                                </object>
                                                <object class="IBToOneOutletInfo" key="keyInput">
                                                        <string key="name">keyInput</string>
-                                                       <string key="candidateClassName">KeyInputTextView</string>
+                                                       <string key="candidateClassName">NJKeyInputField</string>
                                                </object>
                                                <object class="IBToOneOutletInfo" key="mouseBtnSelect">
                                                        <string key="name">mouseBtnSelect</string>
index f07f6d7..e75f56c 100644 (file)
@@ -24,7 +24,7 @@
                D5617FD60FAFD06000928B3A /* Target.m in Sources */ = {isa = PBXBuildFile; fileRef = D5617FD50FAFD06000928B3A /* Target.m */; };
                D5617FD90FAFD1E600928B3A /* TargetKeyboard.m in Sources */ = {isa = PBXBuildFile; fileRef = D5617FD80FAFD1E600928B3A /* TargetKeyboard.m */; };
                D5617FE40FAFD7B000928B3A /* TargetController.m in Sources */ = {isa = PBXBuildFile; fileRef = D5617FE30FAFD7B000928B3A /* TargetController.m */; };
-               D5617FE70FAFDB5800928B3A /* KeyInputTextView.m in Sources */ = {isa = PBXBuildFile; fileRef = D5617FE60FAFDB5800928B3A /* KeyInputTextView.m */; };
+               D5617FE70FAFDB5800928B3A /* NJKeyInputField.m in Sources */ = {isa = PBXBuildFile; fileRef = D5617FE60FAFDB5800928B3A /* NJKeyInputField.m */; };
                D594BE860FAE6219007A85F2 /* Joystick.m in Sources */ = {isa = PBXBuildFile; fileRef = D594BE850FAE6219007A85F2 /* Joystick.m */; };
                D594BE8A0FAE64AD007A85F2 /* JSAction.m in Sources */ = {isa = PBXBuildFile; fileRef = D594BE890FAE64AD007A85F2 /* JSAction.m */; };
                D594BEF90FAE6FF2007A85F2 /* JoystickController.m in Sources */ = {isa = PBXBuildFile; fileRef = D594BEF80FAE6FF2007A85F2 /* JoystickController.m */; };
@@ -72,8 +72,8 @@
                D5617FD80FAFD1E600928B3A /* TargetKeyboard.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TargetKeyboard.m; sourceTree = "<group>"; };
                D5617FE20FAFD7B000928B3A /* TargetController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TargetController.h; sourceTree = "<group>"; };
                D5617FE30FAFD7B000928B3A /* TargetController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TargetController.m; sourceTree = "<group>"; };
-               D5617FE50FAFDB5800928B3A /* KeyInputTextView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KeyInputTextView.h; sourceTree = "<group>"; };
-               D5617FE60FAFDB5800928B3A /* KeyInputTextView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = KeyInputTextView.m; sourceTree = "<group>"; };
+               D5617FE50FAFDB5800928B3A /* NJKeyInputField.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NJKeyInputField.h; sourceTree = "<group>"; };
+               D5617FE60FAFDB5800928B3A /* NJKeyInputField.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = NJKeyInputField.m; sourceTree = "<group>"; };
                D594BE840FAE6219007A85F2 /* Joystick.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Joystick.h; sourceTree = "<group>"; };
                D594BE850FAE6219007A85F2 /* Joystick.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Joystick.m; sourceTree = "<group>"; };
                D594BE880FAE64AD007A85F2 /* JSAction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSAction.h; sourceTree = "<group>"; };
                                D5617FD80FAFD1E600928B3A /* TargetKeyboard.m */,
                                D5617FE20FAFD7B000928B3A /* TargetController.h */,
                                D5617FE30FAFD7B000928B3A /* TargetController.m */,
-                               D5617FE50FAFDB5800928B3A /* KeyInputTextView.h */,
-                               D5617FE60FAFDB5800928B3A /* KeyInputTextView.m */,
+                               D5617FE50FAFDB5800928B3A /* NJKeyInputField.h */,
+                               D5617FE60FAFDB5800928B3A /* NJKeyInputField.m */,
                                8BD9B54115C230FE00929C5D /* TargetMouseMove.h */,
                                8BD9B54215C230FE00929C5D /* TargetMouseMove.m */,
                                8B7E476A15C314A200C588FA /* TargetMouseBtn.h */,
                                D5617FD60FAFD06000928B3A /* Target.m in Sources */,
                                D5617FD90FAFD1E600928B3A /* TargetKeyboard.m in Sources */,
                                D5617FE40FAFD7B000928B3A /* TargetController.m in Sources */,
-                               D5617FE70FAFDB5800928B3A /* KeyInputTextView.m in Sources */,
+                               D5617FE70FAFDB5800928B3A /* NJKeyInputField.m in Sources */,
                                D5F809710FB093400006A4DE /* TargetConfig.m in Sources */,
                                8BD9B54315C230FF00929C5D /* TargetMouseMove.m in Sources */,
                                8B7E476C15C314A200C588FA /* TargetMouseBtn.m in Sources */,
diff --git a/KeyInputTextView.h b/KeyInputTextView.h
deleted file mode 100644 (file)
index 485af1c..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-//
-//  KeyInputTextView.h
-//  Enjoy
-//
-//  Created by Sam McCall on 5/05/09.
-//  Copyright 2009 University of Otago. All rights reserved.
-//
-
-@class TargetController;
-
-@interface KeyInputTextView : NSTextField {
-       IBOutlet NSWindow *window;
-       IBOutlet TargetController *targetController;
-}
-
-@property (assign) int vk;
-@property (readonly) BOOL hasKey;
-@property (assign) BOOL enabled;
-
-+ (NSString *)stringForKeyCode:(int)keycode;
-
-- (void)clear;
-
-@end
diff --git a/KeyInputTextView.m b/KeyInputTextView.m
deleted file mode 100644 (file)
index 6c8e094..0000000
+++ /dev/null
@@ -1,213 +0,0 @@
-//
-//  KeyInputTextView.m
-//  Enjoy
-//
-//  Created by Sam McCall on 5/05/09.
-//
-
-#import "KeyInputTextView.h"
-
-#import "TargetController.h"
-
-@implementation KeyInputTextView {
-    int vk;
-    BOOL enabled;
-}
-
-- (id)initWithFrame:(NSRect)frameRect {
-    if ((self = [super initWithFrame:frameRect])) {
-        self.alignment = NSCenterTextAlignment;
-        [self setEditable:NO];
-        [self setSelectable:NO];
-    }
-    return self;
-}
-
-- (void)clear {
-    self.vk = -1;
-    [targetController keyChanged];
-    [self resignIfFirstResponder];
-}
-
-- (BOOL)hasKey {
-    return self.vk >= 0;
-}
-
-+ (NSString *)stringForKeyCode:(int)keycode {
-    switch(keycode) {
-        case   -1: return @"";
-        case 0x7a: return @"F1";
-        case 0x78: return @"F2";
-        case 0x63: return @"F3";
-        case 0x76: return @"F4";
-        case 0x60: return @"F5";
-        case 0x61: return @"F6";
-        case 0x62: return @"F7";
-        case 0x64: return @"F8";
-        case 0x65: return @"F9";
-        case 0x6d: return @"F10";
-        case 0x67: return @"F11";
-        case 0x6f: return @"F12";
-        case 0x69: return @"F13";
-        case 0x6b: return @"F14";
-        case 0x71: return @"F15";
-        case 0x6a: return @"F16";
-        case 0x40: return @"F17";
-        case 0x4f: return @"F18";
-        case 0x50: return @"F19";
-            
-        case 0x35: return @"Esc";
-        case 0x32: return @"`";
-            
-        case 0x12: return @"1";
-        case 0x13: return @"2";
-        case 0x14: return @"3";
-        case 0x15: return @"4";
-        case 0x17: return @"5";
-        case 0x16: return @"6";
-        case 0x1a: return @"7";
-        case 0x1c: return @"8";
-        case 0x19: return @"9";
-        case 0x1d: return @"0";
-        case 0x1b: return @"-";
-        case 0x18: return @"=";
-            
-        case 0x3f: return @"Fn";
-        case 0x39: return @"Caps Lock";
-        case 0x38: return @"Left Shift";
-        case 0x3b: return @"Left Control";
-        case 0x3a: return @"Left Option";
-        case 0x37: return @"Left Command";
-        case 0x36: return @"Right Command";
-        case 0x3d: return @"Right Option";
-        case 0x3e: return @"Right Control";
-        case 0x3c: return @"Right Shift";
-            
-        case 0x73: return @"Home";
-        case 0x74: return @"Page Up";
-        case 0x75: return @"Delete";
-        case 0x77: return @"End";
-        case 0x79: return @"Page Down";
-            
-        case 0x30: return @"Tab";
-        case 0x33: return @"Backspace";
-        case 0x24: return @"Return";
-        case 0x31: return @"Space";
-            
-        case 0x0c: return @"Q";
-        case 0x0d: return @"W";
-        case 0x0e: return @"E";
-        case 0x0f: return @"R";
-        case 0x11: return @"T";
-        case 0x10: return @"Y";
-        case 0x20: return @"U";
-        case 0x22: return @"I";
-        case 0x1f: return @"O";
-        case 0x23: return @"P";
-        case 0x21: return @"[";
-        case 0x1e: return @"]";
-        case 0x2a: return @"\\";
-        case 0x00: return @"A";
-        case 0x01: return @"S";
-        case 0x02: return @"D";
-        case 0x03: return @"F";
-        case 0x05: return @"G";
-        case 0x04: return @"H";
-        case 0x26: return @"J";
-        case 0x28: return @"K";
-        case 0x25: return @"L";
-        case 0x29: return @";";
-        case 0x27: return @"'";
-        case 0x06: return @"Z";
-        case 0x07: return @"X";
-        case 0x08: return @"C";
-        case 0x09: return @"V";
-        case 0x0b: return @"B";
-        case 0x2d: return @"N";
-        case 0x2e: return @"M";
-        case 0x2b: return @",";
-        case 0x2f: return @".";
-        case 0x2c: return @"/";
-            
-        case 0x47: return @"Clear";
-        case 0x51: return @"Keypad =";
-        case 0x4b: return @"Keypad /";
-        case 0x43: return @"Keypad *";
-        case 0x59: return @"Keypad 7";
-        case 0x5b: return @"Keypad 8";
-        case 0x5c: return @"Keypad 9";
-        case 0x4e: return @"Keypad -";
-        case 0x56: return @"Keypad 4";
-        case 0x57: return @"Keypad 5";
-        case 0x58: return @"Keypad 6";
-        case 0x45: return @"Keypad +";
-        case 0x53: return @"Keypad 1";
-        case 0x54: return @"Keypad 2";
-        case 0x55: return @"Keypad 3";
-        case 0x52: return @"Keypad 0";
-        case 0x41: return @"Keypad .";
-        case 0x4c: return @"Enter";
-            
-        case 0x7e: return @"Up";
-        case 0x7d: return @"Down";
-        case 0x7b: return @"Left";
-        case 0x7c: return @"Right";
-    }
-    return [[NSString alloc] initWithFormat: @"Key 0x%x",keycode];
-}
-
-- (BOOL)acceptsFirstResponder {
-    return self.enabled;
-}
-
-- (BOOL)becomeFirstResponder {
-    self.backgroundColor = NSColor.selectedTextBackgroundColor;
-    return [super becomeFirstResponder];
-}
-
-- (BOOL)resignFirstResponder {
-    self.backgroundColor = NSColor.textBackgroundColor;
-    return [super resignFirstResponder];
-}
-
-- (void)setVk:(int)key {
-    vk = key;
-    [self setStringValue:[KeyInputTextView stringForKeyCode:key]];
-}
-
-- (int)vk {
-    return vk;
-}
-
-- (void)keyDown:(NSEvent *)evt {
-    if (!evt.isARepeat) {
-        self.vk = evt.keyCode;
-        [targetController keyChanged];
-        [self resignIfFirstResponder];
-    }
-}
-
-- (void)mouseDown:(NSEvent *)theEvent {
-    [targetController keyChanged];
-    [self.window makeFirstResponder:self];
-}
-
-- (void)flagsChanged:(NSEvent *)evt {
-    self.vk = evt.keyCode;
-    [targetController keyChanged];
-    [self resignIfFirstResponder];
-}
-
-- (void)setEnabled:(BOOL)newEnabled {
-    enabled = newEnabled;
-
-    if (!enabled)
-        [self resignIfFirstResponder];
-}
-
-- (BOOL)enabled {
-    return enabled;
-}
-
-
-@end
diff --git a/NJKeyInputField.h b/NJKeyInputField.h
new file mode 100644 (file)
index 0000000..ad026d3
--- /dev/null
@@ -0,0 +1,45 @@
+//
+//  NJKeyInputField.h
+//  Enjoyable
+//
+//  Copyright 2013 Joe Wreschnig.
+//
+
+#import <Cocoa/Cocoa.h>
+
+extern CGKeyCode NJKeyInputFieldEmpty;
+
+@protocol NJKeyInputFieldDelegate;
+
+@interface NJKeyInputField : NSTextField
+    // An NJKeyInputField is a NSTextField-like widget that receives
+    // exactly one key press, and displays the name of that key, then
+    // resigns its first responder status. It can also inform a
+    // special delegate when its content changes.
+
++ (NSString *)stringForKeyCode:(CGKeyCode)keyCode;
+    // Give the string name for a virtual key code.
+
+@property (nonatomic, weak) IBOutlet id <NJKeyInputFieldDelegate> keyDelegate;
+
+@property (nonatomic, assign) CGKeyCode keyCode;
+    // The currently displayed key code, or NJKeyInputFieldEmpty if no
+    // key is active.  Changing this will update the display but not
+    // inform the delegate.
+
+@property (nonatomic, readonly) BOOL hasKeyCode;
+    // True if any key is active, false otherwise.
+
+- (void)clear;
+    // Clear the currently active key and call the delegate.
+
+@end
+
+@protocol NJKeyInputFieldDelegate <NSObject>
+
+- (void)keyInputField:(NJKeyInputField *)keyInput
+         didChangeKey:(CGKeyCode)keyCode;
+- (void)keyInputFieldDidClear:(NJKeyInputField *)keyInput;
+
+@end
+
diff --git a/NJKeyInputField.m b/NJKeyInputField.m
new file mode 100644 (file)
index 0000000..13aa138
--- /dev/null
@@ -0,0 +1,209 @@
+//
+//  NJKeyInputField.h
+//  Enjoyable
+//
+//  Copyright 2013 Joe Wreschnig.
+//
+
+#import "NJKeyInputField.h"
+
+CGKeyCode NJKeyInputFieldEmpty = 0xFFFF;
+
+@implementation NJKeyInputField
+
+- (id)initWithFrame:(NSRect)frameRect {
+    if ((self = [super initWithFrame:frameRect])) {
+        self.alignment = NSCenterTextAlignment;
+        [self setEditable:NO];
+        [self setSelectable:NO];
+    }
+    return self;
+}
+
+- (void)clear {
+    self.keyCode = NJKeyInputFieldEmpty;
+    [self.keyDelegate keyInputFieldDidClear:self];
+    [self resignIfFirstResponder];
+}
+
+- (BOOL)hasKeyCode {
+    return self.keyCode >= 0;
+}
+
++ (NSString *)stringForKeyCode:(CGKeyCode)keyCode {
+    switch (keyCode) {
+        case 0xffff: return @"";
+        case 0x7a: return @"F1";
+        case 0x78: return @"F2";
+        case 0x63: return @"F3";
+        case 0x76: return @"F4";
+        case 0x60: return @"F5";
+        case 0x61: return @"F6";
+        case 0x62: return @"F7";
+        case 0x64: return @"F8";
+        case 0x65: return @"F9";
+        case 0x6d: return @"F10";
+        case 0x67: return @"F11";
+        case 0x6f: return @"F12";
+        case 0x69: return @"F13";
+        case 0x6b: return @"F14";
+        case 0x71: return @"F15";
+        case 0x6a: return @"F16";
+        case 0x40: return @"F17";
+        case 0x4f: return @"F18";
+        case 0x50: return @"F19";
+            
+        case 0x35: return @"Esc";
+        case 0x32: return @"`";
+            
+        case 0x12: return @"1";
+        case 0x13: return @"2";
+        case 0x14: return @"3";
+        case 0x15: return @"4";
+        case 0x17: return @"5";
+        case 0x16: return @"6";
+        case 0x1a: return @"7";
+        case 0x1c: return @"8";
+        case 0x19: return @"9";
+        case 0x1d: return @"0";
+        case 0x1b: return @"-";
+        case 0x18: return @"=";
+            
+        case 0x3f: return @"Fn";
+        case 0x36: return @"Right Command";
+        case 0x37: return @"Left Command";
+        case 0x38: return @"Left Shift";
+        case 0x39: return @"Caps Lock";
+        case 0x3a: return @"Left Option";
+        case 0x3b: return @"Left Control";
+        case 0x3c: return @"Right Shift";
+        case 0x3d: return @"Right Option";
+        case 0x3e: return @"Right Control";
+            
+        case 0x73: return @"Home";
+        case 0x74: return @"Page Up";
+        case 0x75: return @"Delete";
+        case 0x77: return @"End";
+        case 0x79: return @"Page Down";
+            
+        case 0x30: return @"Tab";
+        case 0x33: return @"Backspace";
+        case 0x24: return @"Return";
+        case 0x31: return @"Space";
+            
+        case 0x0c: return @"Q";
+        case 0x0d: return @"W";
+        case 0x0e: return @"E";
+        case 0x0f: return @"R";
+        case 0x11: return @"T";
+        case 0x10: return @"Y";
+        case 0x20: return @"U";
+        case 0x22: return @"I";
+        case 0x1f: return @"O";
+        case 0x23: return @"P";
+        case 0x21: return @"[";
+        case 0x1e: return @"]";
+        case 0x2a: return @"\\";
+        case 0x00: return @"A";
+        case 0x01: return @"S";
+        case 0x02: return @"D";
+        case 0x03: return @"F";
+        case 0x05: return @"G";
+        case 0x04: return @"H";
+        case 0x26: return @"J";
+        case 0x28: return @"K";
+        case 0x25: return @"L";
+        case 0x29: return @";";
+        case 0x27: return @"'";
+        case 0x06: return @"Z";
+        case 0x07: return @"X";
+        case 0x08: return @"C";
+        case 0x09: return @"V";
+        case 0x0b: return @"B";
+        case 0x2d: return @"N";
+        case 0x2e: return @"M";
+        case 0x2b: return @",";
+        case 0x2f: return @".";
+        case 0x2c: return @"/";
+            
+        case 0x47: return @"Clear";
+        case 0x51: return @"Keypad =";
+        case 0x4b: return @"Keypad /";
+        case 0x43: return @"Keypad *";
+        case 0x59: return @"Keypad 7";
+        case 0x5b: return @"Keypad 8";
+        case 0x5c: return @"Keypad 9";
+        case 0x4e: return @"Keypad -";
+        case 0x56: return @"Keypad 4";
+        case 0x57: return @"Keypad 5";
+        case 0x58: return @"Keypad 6";
+        case 0x45: return @"Keypad +";
+        case 0x53: return @"Keypad 1";
+        case 0x54: return @"Keypad 2";
+        case 0x55: return @"Keypad 3";
+        case 0x52: return @"Keypad 0";
+        case 0x41: return @"Keypad .";
+        case 0x4c: return @"Enter";
+            
+        case 0x7e: return @"Up";
+        case 0x7d: return @"Down";
+        case 0x7b: return @"Left";
+        case 0x7c: return @"Right";
+        default:
+            return [[NSString alloc] initWithFormat:@"Key 0x%x", keyCode];
+    }
+}
+
+- (BOOL)acceptsFirstResponder {
+    return self.isEnabled;
+}
+
+- (BOOL)becomeFirstResponder {
+    self.backgroundColor = NSColor.selectedTextBackgroundColor;
+    return [super becomeFirstResponder];
+}
+
+- (BOOL)resignFirstResponder {
+    self.backgroundColor = NSColor.textBackgroundColor;
+    return [super resignFirstResponder];
+}
+
+- (void)setKeyCode:(CGKeyCode)keyCode {
+    _keyCode = keyCode;
+    self.stringValue = [NJKeyInputField stringForKeyCode:keyCode];
+}
+
+- (void)keyDown:(NSEvent *)theEvent {
+    if (!theEvent.isARepeat) {
+        if ((theEvent.modifierFlags & NSAlternateKeyMask)
+            && theEvent.keyCode == 0x35) {
+            // Allow Alt+Escape to clear the field.
+            self.keyCode = NJKeyInputFieldEmpty;
+            [self.keyDelegate keyInputFieldDidClear:self];
+        } else {
+            self.keyCode = theEvent.keyCode;
+            [self.keyDelegate keyInputField:self didChangeKey:_keyCode];
+        }
+        [self resignIfFirstResponder];
+    }
+}
+
+- (void)mouseDown:(NSEvent *)theEvent {
+    if (self.acceptsFirstResponder)
+        [self.window makeFirstResponder:self];
+}
+
+- (void)flagsChanged:(NSEvent *)theEvent {
+    // Many keys are only available on MacBook keyboards by using the
+    // Fn modifier key (e.g. Fn+Left for Home), so delay processing
+    // modifiers until the up event is received in order to let the
+    // 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)) {
+        self.keyCode = theEvent.keyCode;
+        [self.keyDelegate keyInputField:self didChangeKey:_keyCode];
+    }
+}
+
+@end
index 9c9ee2c..9c03c08 100644 (file)
@@ -6,14 +6,15 @@
 //  Copyright 2009 University of Otago. All rights reserved.
 //
 
-@class KeyInputTextView;
+#import "NJKeyInputField.h"
+
 @class ConfigsController;
 @class JoystickController;
 @class Target;
 @class TargetMouseMove;
 
-@interface TargetController : NSObject {
-    IBOutlet KeyInputTextView *keyInput;
+@interface TargetController : NSObject <NJKeyInputFieldDelegate> {
+    IBOutlet NJKeyInputField *keyInput;
     IBOutlet NSMatrix *radioButtons;
     IBOutlet NSSegmentedControl *mouseDirSelect;
     IBOutlet NSSegmentedControl *mouseBtnSelect;
@@ -26,7 +27,6 @@
 
 @property (assign) BOOL enabled;
 
-- (void)keyChanged;
 - (void)loadCurrent;
 - (void)refreshConfigs;
 - (IBAction)configChosen:(id)sender;
index 1f285ec..48119c2 100644 (file)
@@ -11,7 +11,7 @@
 #import "Config.h"
 #import "JSAction.h"
 #import "JoystickController.h"
-#import "KeyInputTextView.h"
+#import "NJKeyInputField.h"
 #import "TargetConfig.h"
 #import "TargetController.h"
 #import "TargetKeyboard.h"
@@ -26,7 +26,7 @@
     NSInteger row = radioButtons.selectedRow;
     
     if (row != 1) {
-        keyInput.vk = -1;
+        keyInput.keyCode = -1;
         [keyInput resignIfFirstResponder];
     }
     
     [self commit];
 }
 
-- (void)keyChanged {
+- (void)keyInputField:(NJKeyInputField *)keyInput didChangeKey:(CGKeyCode)keyCode {
     [radioButtons selectCellAtRow:1 column:0];
     [radioButtons.window makeFirstResponder:radioButtons];
     [self commit];
 }
 
+- (void)keyInputFieldDidClear:(NJKeyInputField *)keyInput {
+    [radioButtons selectCellAtRow:0 column:0];
+    [self commit];
+}
+
 - (void)configChosen:(id)sender {
     [radioButtons selectCellAtRow:2 column:0];
     [configPopup.window makeFirstResponder:configPopup];
         case 0:
             return nil;
         case 1:
-            if (keyInput.hasKey) {
+            if (keyInput.hasKeyCode) {
                 TargetKeyboard *k = [[TargetKeyboard alloc] init];
-                k.vk = keyInput.vk;
+                k.vk = keyInput.keyCode;
                 return k;
             } else {
                 return nil;
 
     if ([target isKindOfClass:TargetKeyboard.class]) {
         [radioButtons selectCellAtRow:1 column:0];
-        keyInput.vk = [(TargetKeyboard*)target vk];
+        keyInput.keyCode = [(TargetKeyboard*)target vk];
     } else if ([target isKindOfClass:TargetConfig.class]) {
         [radioButtons selectCellAtRow:2 column:0];
         NSUInteger idx = [configsController.configs
index a3a0b51..eab2d4e 100644 (file)
@@ -7,7 +7,7 @@
 
 #import "TargetKeyboard.h"
 
-#import "KeyInputTextView.h"
+#import "NJKeyInputField.h"
 
 @implementation TargetKeyboard