macoscocoafieldeditor

Cocoa: Making NSTextField editable after a click and short delay (like renaming in Finder)


I cannot find a simple example of how to use an NSTextField to edit it's contents in place.

Exactly like in the Finder - you're able to click, and with a short delay the text field becomes editable.

It seems like it's some combination of the textField, it's cell, and the fieldEditor? Problem is I can't find the most basic example of how to do it.

I've tried subclassing NSTextField with a couple different tests but it hasn't worked:

#import "GWTextField.h"
@implementation GWTextField
- (id) initWithFrame:(NSRect)frameRect {
    self = [super initWithFrame:frameRect];
    return self;
}
- (void) mouseDown:(NSEvent *)theEvent {
    [super mouseDown:theEvent];
    [self.cell editWithFrame:self.frame inView:self.superview editor:[self.cell fieldEditorForView:self] delegate:self event:theEvent];
    //[self setEditable:TRUE];
    //[self setSelectable:TRUE];
    //[self selectText:nil];
    [NSTimer scheduledTimerWithTimeInterval:.3 target:self selector:@selector(edit:) userInfo:nil repeats:FALSE];
}
- (void) edit:(id) sende {
    NSLog(@"edit");
    [[NSApplication sharedApplication].mainWindow makeFirstResponder:self];
    [self selectText:nil];
}
@end

Any ideas?


Solution

  • I came up with a better solution to the edit in place problem. I believe this is how to properly do edit in place with NSCell. Please show and tell if this is wrong.

    #import <Cocoa/Cocoa.h>
    @interface EditTextField : NSTextField <NSTextDelegate>
    @end
    
    ---
    
    #import "EditTextField.h"
    
    @implementation EditTextField
    
    - (void) mouseDown:(NSEvent *)theEvent {
        if(theEvent.clickCount == 2) {
            self.editable = TRUE;
            NSText * fieldEditor = [self.window fieldEditor:TRUE forObject:self];
            [self.cell editWithFrame:self.bounds inView:self editor:fieldEditor delegate:self event:theEvent];
        } else {
            [super mouseDown:theEvent];
        }
    }
    
    - (void) cancelOperation:(id)sender {
        [self.cell endEditing:nil];
        self.editable = FALSE;
    }
    
    - (BOOL) textView:(NSTextView *) textView doCommandBySelector:(SEL) commandSelector {
        NSString * selector = NSStringFromSelector(commandSelector);
        if([selector isEqualToString:@"insertNewline:"]) {
            NSText * fieldEditor = [self.window fieldEditor:TRUE forObject:self];
            [self.cell endEditing:fieldEditor];
            self.editable = FALSE;
            return TRUE;
        }
        return FALSE;
    }
    
    @end