I've been reading the Cocoa Event Handling Guide to understand how to handle keyboard events for my application. However, I'm not quite sure if the solution I've found is the idiomatic way to approach this problem or even the best.
I have a view called CustomView
and controller called CustomViewController
that contains a NSTextView
(within a NSScrollView
) and a NSTextField
. Basically a chat window.
What I would like is that even if the NSTextField
is not selected, and the user starts typing, the NSTextField
should be made the first responder and the text the user types should be appended to the NSTextField
.
I've come up with a solution (below) where my RootWindowController
captures keyDown
events, makes the NSTextField
the first responder, gets the field editor, and appends the text.
Is this the idiomatic approach Cocoa developers take or is their a simpler way that I am missing? Code is below. Thanks.
RootWindowController.m
#import "RootWindowController.h"
@implementation RootWindowController
- (id)initWithWindow:(NSWindow *)window
{
self = [super initWithWindow:window];
if (self) {
self.customViewController = [[CustomViewController alloc] init];
NSView *contentView = self.window.contentView;
CGFloat viewWidth = contentView.frame.size.width;
CGFloat viewHeight = contentView.frame.size.height;
self.customViewController.customView.textField.frame =
NSMakeRect(0, 0, viewWidth, 50);
self.customViewController.customView.scrollView.frame =
NSMakeRect(0, 51, viewWidth, viewHeight - 50);
self.customViewController.customView.textView.frame =
NSMakeRect(0, 51, viewWidth, viewHeight - 50);
self.window.contentView = self.customViewController.customView;
}
return self;
}
- (void)keyDown:(NSEvent *)theEvent
{
[self.window
makeFirstResponder:self.customViewController.customView.textField];
NSString *characters = theEvent.characters;
NSText *fieldEditor = [self.window fieldEditor:YES
forObject:self.customViewController.customView.textField];
[fieldEditor setString:
[NSString stringWithFormat:@"%@%@", fieldEditor.string, characters]];
[fieldEditor setSelectedRange:NSMakeRange(fieldEditor.string.length, 0)];
[fieldEditor setNeedsDisplay:YES];
}
@end
CustomViewController.m
#import "CustomViewController.h"
@implementation CustomViewController
- (id)init
{
self = [super init];
if (self) {
self.customView = [[CustomView alloc] initWithFrame:NSZeroRect];
[self.customView setAutoresizesSubviews:YES];
self.view = self.customView;
}
return self;
}
@end
CustomView.m
#import "CustomView.h"
@implementation CustomView
- (id)initWithFrame:(NSRect)frame
{
self = [super initWithFrame:frame];
if (self) {
self.scrollView = [[NSScrollView alloc] initWithFrame:NSZeroRect];
self.textView = [[NSTextView alloc] initWithFrame:NSZeroRect];
self.textField = [[NSTextField alloc] initWithFrame:NSZeroRect];
[self.textView setAutoresizesSubviews:YES];
[self.scrollView setDocumentView:self.textView];
[self.scrollView setHasVerticalScroller:YES];
[self.scrollView setAutoresizesSubviews:YES];
[self.textField setStringValue:@"Placeholder Text"];
[self addSubview:self.scrollView];
[self addSubview:self.textField];
[self.textView setNeedsDisplay:YES];
}
return self;
}
- (BOOL)acceptsFirstResponder
{
return YES;
}
@end