2

I have a search field whose original width is small (because it looks better that way). However, when the user clicks on the search field, I want to make its width bigger by a certain amount. When the user clicks outside, I want to resize it to the original size. I also want to do all the resizes with animations.

Here is what I have so far:

#define kAddedWidth 85

@implementation ToolbarSearchField

- (id)initWithFrame: (NSRect)frameRect
{
    self = [super initWithFrame: frameRect];
    if (self) {
        originalSize = self.frame.size.width;
    }

    return self;
}
- (void)awakeFromNib
{
    [super awakeFromNib];
    originalSize = self.frame.size.width;
}

- (BOOL)becomeFirstResponder
{    
    NSRect newFrame = NSMakeRect(self.frame.origin.x, self.frame.origin.y, originalSize + kAddedWidth, self.frame.size.height);    
    [[self animator] setFrame: newFrame];

    return [super becomeFirstResponder];
}

- (BOOL)resignFirstResponder
{    
    NSRect newFrame = NSMakeRect(self.frame.origin.x, self.frame.origin.y, originalSize, self.frame.size.height);
    [[self animator] setFrame: newFrame];

    return [super resignFirstResponder];
}

@end

originalSize is an iVar.

The problem is that this isn't resizing anything. Clicking on the field or outside isn't doing a single bit.

I did some NSLog debugging and it seems that when I click on the field becomeFirstResponder gets called and immediately after that resignFirstResponder is called, nullifying the resize animation. However, the field is still active and blinking the insertion point. Have any ideas?

The Solution:

Thanks to Peter Hosey's answer, I managed to solve this. Here is my solution:

#define kAddedWidth (self.superview.bounds.size.width - self.frame.origin.x * 2 - originalSize)

@implementation ToolbarSearchField

- (id)initWithFrame: (NSRect)frameRect
{
    self = [super initWithFrame: frameRect];
    if (self) {
        originalSize = self.frame.size.width;
    }

    return self;
}
- (void)awakeFromNib
{
    [super awakeFromNib];
    originalSize = self.frame.size.width;
}

- (void)textDidBeginEditing: (NSNotification*)notification
{    
    [super textDidBeginEditing: notification];
    isEditing = YES;

    NSRect newFrame = NSMakeRect(self.frame.origin.x, self.frame.origin.y, originalSize + kAddedWidth, self.frame.size.height);
    [[self animator] setFrame: newFrame];
}
- (void)textDidEndEditing: (NSNotification*)notification
{    
    [super textDidEndEditing: notification];
    isEditing = NO;

    if ([self.stringValue isEqualToString: @""]) {
        NSRect newFrame = NSMakeRect(self.frame.origin.x, self.frame.origin.y, originalSize, self.frame.size.height);
        [[self animator] setFrame: newFrame]; 
    }
}

- (void)mouseDown: (NSEvent*)theEvent
{
    if (!isEditing) {
        NSRect newFrame = NSMakeRect(self.frame.origin.x, self.frame.origin.y, originalSize + kAddedWidth, self.frame.size.height);
        [[self animator] setFrame: newFrame];
    }

    [super mouseDown: theEvent];
}

Whenever the field is clicked and it isn't editing already, animate to a bigger size. Whenever the field ends editing, animate only if it doesn't have text. If it has text then it is better not to make the field smaller.

Alex
  • 5,009
  • 3
  • 39
  • 73

1 Answers1

3

Fields don't handle text input. That responsibility goes to the field editor, which is an instance of NSText (or of some subclass thereof) owned by the window.

You might try implementing the textDidBeginEditing: method and the textDidEndEditing: method instead.

A search for “field editor” turns up several relevant results in several different programming guides.

Peter Hosey
  • 95,783
  • 15
  • 211
  • 370