SIGPIPE 13

Programming, automation, algorithms, macOS, and more.

Disabled Image Buttons

Some time ago Apple introduced these small whitish image buttons mostly for use with table views (for adding and removing items), an example is shown here:

Row of image buttons

The buttons have three states, and Apple use images for each of these three states since the border is part of the image, so if NSControl renders it pressed or disabled, it will affect the border. Unfortunately Interface Builder only lets us set a normal image and an alternate image (which can be used as the pressed-image by setting “behavior” to “momentary change”).

So since I do not want to write custom code each time I make use of such an image button, what I do is set the alternate title of the button to the name of my disabled image, and then I change the subclass to “OakButton”, which is a simple NSButton subclass which reads the alternate title in initWithCoder:, and uses that as the disabled image. The code for this subclass follows:

@interface OakButton : NSButton
{
   NSImage* normalImage;
   NSImage* disabledImage;
}
@end

@implementation OakButton
- (id)initWithCoder:(NSCoder*)aDecoder
{
   if(self = [super initWithCoder:aDecoder])
   {
      [[self cell] setImageDimsWhenDisabled:NO];
      [self setValue:[NSImage imageNamed:[self alternateTitle]] forKey:@"disabledImage"];
      [self setAlternateTitle:@""];
      if([self isEnabled] == NO)
         [self setImage:disabledImage];
   }
   return self;
}

- (void)setEnabled:(BOOL)flag
{
   if(flag != [self isEnabled])
   {
      if(!normalImage)
         [self setValue:[self image] forKey:@"normalImage"];
      [self setImage:flag ? normalImage : disabledImage];
      [super setEnabled:flag];
   }
}

- (void)dealloc
{
   [self setValue:nil forKey:@"disabledImage"];
   [self setValue:nil forKey:@"normalImage"];
   [super dealloc];
}
@end

And here is how I setup the properties in Interface Builder for:

Screengrab of Interface Builders Show Info panel

The icon position (bottom option) needs to be at one of the choices which have both image and text, otherwise Interface Builder won’t let you enter the alternate title. But if you need to use “Size to Fit” (from the Layout menu) you must (temporarily) set it to icon only (the top middle choice).

{{ numberOfCommentsTitle }}

{{ submitComment.success }}

Error Posting Comment

{{ submitComment.error }}