Posts tagged ‘Cocoa’

NSView with gradient background

In Mac OS X 10.5 a new class NSGradient is introduced, that makes it really easy to work with gradients (as you might have guessed from the name). The sample code below shows a basic yet functional implementation of an NSView subclass that has either an colored or gradient background.

ColorGradientView.h

@interface ColorGradientView : NSView
{
  NSColor *startingColor;
  NSColor *endingColor;
  int angle;
}

// Define the variables as properties
@property(nonatomic, retain) NSColor *startingColor;
@property(nonatomic, retain) NSColor *endingColor;
@property(assign) int angle;

@end

ColorGradientView.m

#import "GradientView.h"
@implementation ColorGradientView

// Automatically create accessor methods
@synthesize startingColor;
@synthesize endingColor;
@synthesize angle;

- (id)initWithFrame:(NSRect)frame {
  self = [super initWithFrame:frame];
  if (self) {
    // Initialization code here.
    [self setStartingColor:[NSColor colorWithCalibratedWhite:1.0 alpha:1.0]];
    [self setEndingColor:nil];
    [self setAngle:270];
  }
  return self;
}

- (void)drawRect:(NSRect)rect {
  if (endingColor == nil || [startingColor isEqual:endingColor]) {
    // Fill view with a standard background color
    [startingColor set];
    NSRectFill(rect);
  }
  else {
    // Fill view with a top-down gradient
    // from startingColor to endingColor
    NSGradient* aGradient = [[NSGradient alloc]
        initWithStartingColor:startingColor
        endingColor:endingColor];
    [aGradient drawInRect:[self bounds] angle:angle];
  }
}

@end

Note that the code is based on the new garbage collection mechanism available in Objective-C 2.0, so there are no retain or release calls.

In the following picture you see a gradient effect from top to bottom to give a subtle 3d appearance:

To achieve this, add a NSView in Interface Builder and define its class as ColorGradientView. In your controller, add a ColorGradientView outlet (e.g. myGradientView) and in Interface Builder attach the view to the outlet. Add the following 3 lines to the - (void)awakeFromNib method in the controller:


[myGradientView setStartingColor:
    [NSColor colorWithCalibratedWhite:0.85 alpha:1.0]];
[myGradientView setEndingColor:
    [NSColor colorWithCalibratedWhite:0.7 alpha:1.0]];
[myGradientView setAngle:270];

In upcoming post I will go into details of how to create the Safari like buttons that you see in the screen shot.

Build a toolbar in Interface Builder

Interface Builder 3 (IB3), part of the development tools that are shipped with Mac OS X Leopard, finally allows building an application window toolbar. Until the release of IB3 the setup had to be done entirely in code, or through a 3rd party extension to IB. Allthough the toolbar in the application I’m working on was working fine, I couldn’t resist the temptation to move its definition into my NIB file and clean up my code a bit.

In the objects library, under Application there is a new set of objects filed as Toolbar. You can drop a toolbar object onto a window which will give you a standard implementation of the toolbar, with icons for Show colors, Show fonts, Print and Customize. Select the toolbar to change its default properties in the Attribute Inspector window. Note that a new toolbar has the Customizable checkbox unchecked, meaning that a user of you application can’t customize the toolbar. Simply check it to change this behaviour.

To change the toolbar, you need to click on it in the window where you dropped it, which shows a panel containing the allowed toolbar items.

From the object library you can add toolbar items, either one of the standard items or an image item. Alternatively you can drop an image directly from the media library which will create an image item. On the Attribute Inspector window you can change the attributes for an image toolbar item (on Toolbar Item Attributes), and add a Tooltip (on Toolbar Item Identity). To change the standard toolbar that will be active when the application is started, drag items from the panel onto the toolbar, or drag items you don’t want out of the toolbar.

The standard items will have default activities attached to them, for the image items you added yourself you will have to add an action by Control-dragging from the item to an object (usually FirstResponder or File’s Owner) and selecting the action you want executed when the item is clicked.

This is all really easy, as long as you keep in mind that attributes and actions are specified on the items in the panel with the allowed items, rather on the items in the toolbar itself. While most of the configuration can now be done in IB, you still need to implement the method:

- (BOOL)validateToolbarItem:(NSToolbarItem *)theItem

in the class that is the delegate for the toolbar. In the implementation of the method you need to check for which item it was called, and return YES or NO depending on whether you want the item to be active (clickable) or not. You set tag values for the different items in IB against which you can check for which item the validateToolbarItem method is called. A sample implementation for a save button in a document based application could look like this:

- (BOOL)validateToolbarItem:(NSToolbarItem *)theItem
{
    if ([theItem tag] == 1001) // Save toolbar item
        return [self isDocumentEdited];
    return YES;
}

One thing to note: if you have put a toolbar into your NIB file, you will need to save the file in either XIB3.x or NIB3.x format. Saving in NIB2.x format is not supported, so you lose backwards compatibility with IB2.