PATH Documentation > Release Notes

Mac OS X Developer Release Notes:
Cocoa Application Framework (10.4 and Earlier)

This document contains the release notes for Mac OS X 10.4, its updates, and earlier. Please refer to the current release notes for AppKit before referring to this document, as the more recent changes in the current release could have obsoleted some of the items discussed here.

The notes below are split into the following sections:





Notes specific to MacOS X 10.4

New features in Tiger

The following are some of the new features in AppKit, Foundation, and related areas in Tiger.

AppKit (these are described in greater detail further below in this file):

Foundation (these are described in the Foundation release notes):

Some of the other new Mac OS X APIs to be aware of:



NSDatePicker and NSDatePickerCell

AppKit has a new date/time control, whose API is declared in NSDatePicker.h and NSDatePickerCell.h. Currently this class pair provides two styles of date/time control: a "text field and stepper" style that is similar to Carbon's familiar "ClockDate" control, and a graphical "clock and calendar" variant like those that appear in the "Date & Time" System Preferences panel.

A date picker's "objectValue" is an NSDate. The "-dateValue/-setDateValue:" accessor pair provides a type-specific equivalent to the inherited "-objectValue/-setObjectValue:" methods.

A date picker additionally has a "mode" attribute and a "timeInterval" attribute that are not currently used. These attributes exist to support the possibility of a "date range" control mode in the future. The time interval is not applicable, and always zero, when the control is in NSSingleDateMode (the only mode supported by the currently supplied control styles). In NSRangeDateMode, it will specify the duration of the range, which extends forward in time from the cell's dateValue.

An instance's "datePickerElements" attribute determines which components of its value it considers to be specified/specifiable. This setting is composed by bitwise-ORing together one or more of the "DatePickerElementFlag" values declared in NSDatePickerCell.h. It influences both display and editing behavior, as appropriate for the style of date control in use.
typedef unsigned int NSDatePickerElementFlags;
enum {
/* Time Elements */
NSHourMinuteDatePickerElementFlag = 0x000c,
NSHourMinuteSecondDatePickerElementFlag = 0x000e,
NSTimeZoneDatePickerElementFlag     = 0x0010,
    /* Date Elements */
NSYearMonthDatePickerElementFlag     = 0x00c0,
NSYearMonthDayDatePickerElementFlag     = 0x00e0,
NSEraDatePickerElementFlag         = 0x0100,
};
For a case where the "time" portion of the date value is not of interest, for example, this could be set to NSYearMonthDayDatePickerElementFlag. NSTimeZoneDatePickerElementFlag and NSEraDatePickerElementFlag have been declared for possible future use, and do not yet have any effect.

A date picker also has a "calendar", "locale", and "timeZone" that influence date display and editing. In Tiger, date picker functionality supports Gregorian format date display and editing only, but the calendar and locale settings will be used to support other calendars and date formats in the future.

A date picker has a "minDate" and a "maxDate" that can be used to impose a simple range constraint on the possible values the date picker can take. (Both default to nil, meaning that the date value is unconstrained.) Clients can impose more sophisticated constraints in addition to this basic range constraint by providing a delegate object that validates proposed changes to the cell's value. A date picker never allows itself to get into a state where its current value does not satisfy the constraints imposed by minDate, maxDate, and the delegate's validation method (if provided). Its -setObjectValue:/-setDateValue: and -setTimeInterval: accessors will likewise constrain their received parameters to valid values.

The signature of the optional delegate method is:
- (void)dateCell:(NSDatePickerCell *)aDatePickerCell
validateProposedDateValue:(NSDate **)proposedDateValue
timeInterval:(NSTimeInterval *)proposedTimeInterval;
If an date picker has a delegate assigned to it, and the delegate responds to this selector, this method will be invoked each time the user attempts to make a change to the date picker's value, giving the delegate the opportunity to approve, modify, or reject the change.

"proposedDateValue" points to the proposed new dateValue. "proposedTimeInterval" points to the proposed new timeInterval, which will always be zero if the cell is not in NSDateRangeMode. Implementors may find it helpful to consult the NSDatePickerCell's current dateValue and timeInterval for comparison, to determine which of these values (potentially one or both) the cell is proposing to change.

On entry to this delegate method, the start and end points of the proposed range are guaranteed to lie between the NSDatePickerCell's minDate and maxDate, and *proposedTimeInterval is guaranteed to be nonnegative. The delegate can leave *proposedDateValue untouched to accept it, or replace it with a pointer to another NSDate instance. (The replacement value should be autoreleased or otherwise not require a subsequent release.) Likewise, this method can leave the proposedTimeInterval untouched to accept it, or replace its value through the provided pointer.


NSTokenField and NSTokenFieldCell (Section updated since WWDC)

There is a new token field control that behaves like the address field in Mail.app. The new widget supports tokenizing based on a character set (comma by default) and on end editing. In addition, we join tokens for multiple selection using a comma if comma is in the tokenizing character set; Otherwise, we join with space. We invoke text completion after a specified delay.

The tokens are draggable. By default, we put the tokens on the pasteboard using the NSStringPboardType (joined in the same way as the multiple token selection).

Use NSControl/NSCell's setObjectValue: method to set the token field's array of represented objects. If the array contains objects other than NSStrings, you must implement the tokenField:displayStringForRepresentedObject: delegate method.

Known NSTokenField Issues:
- NSTokenFieldCell are not fully functional inside of an NSTableView/Matrix.
- NSTokenField's cell must be a subclass of NSTokenField.

Please refer to NSTokenField.h and NSTokenFieldCell.h for the complete API.


NSLevelIndicator/NSLevelIndicatorCell

There is now a level indicator control and corresponding cell class. This control can display one of 4 styles of capacity, ranking, or relevancy. The capacity style can either be continuous or discrete. The ranking appearance is similar to the iTunes 'stars' ranking and the relevancy ranking can be used to display search ranking in a table.

Depending on the style, there is different behaviour. For relevancy and continuous capacity, the bar is drawn to fill the cell frame and the min/max/value can be any value. For the discrete styles for capacity and rating level, all values are rounded to the nearest integer when displaying. For the rating level, the images are not stretched or shrunk. For the the discrete capacity, the cell will stretch each segment the same amount to fill the cell frame as much as possible. -cellSizeForBounds: will reflect this.

If the cell is editable, the value can be changed by having the user track using the mouse or using the up/down or left/right arrows though only the rating one should be used in that manner. Any of the styles can be marked editable or have tick marks though in most cases, it only the ranking style should be editable and the continuous capacity indictor needs tick marks.

By default, the cell image is nil but if -setImage:, it replaces the default stars with the custom image for the NSRatingLevelIndicatorStyle style. Setting the image has no effect on the other styles. The image is lightened for highlighted selection and the dots for empty spots are still drawn. The image is not stretched no space is added between images.

See the cell for descriptions of the control methods:
@interface NSLevelIndicator : NSControl
- (double)minValue;
- (void)setMinValue:(double)minValue;
- (double)maxValue;
- (void)setMaxValue:(double)maxValue;
- (double)warningValue;
- (void)setWarningValue:(double)warningValue;
- (double)criticalValue;
- (void)setCriticalValue:(double)criticalValue;
- (NSTickMarkPosition)tickMarkPosition;
- (void)setTickMarkPosition:(NSTickMarkPosition)position;
- (int)numberOfTickMarks;
- (void)setNumberOfTickMarks:(int)count;
- (int)numberOfMajorTickMarks;
- (void)setNumberOfMajorTickMarks:(int)count;
- (double)tickMarkValueAtIndex:(int)index;
- (NSRect)rectOfTickMarkAtIndex:(int)index;
@end
Here is the cell declaration:
enum {
NSRelevancyLevelIndicatorStyle,
NSContinuousCapacityLevelIndicatorStyle,
NSDiscreteCapacityLevelIndicatorStyle,
NSRatingLevelIndicatorStyle
} NSLevelIndicatorStyle;
@interface NSLevelIndicatorCell : NSActionCell
- (id)initWithLevelIndicatorStyle:(NSLevelIndicatorStyle)levelIndicatorStyle;
Create new cell with indicator style. Default for -init is NSRelevancyLevelIndicatorStyle. Default value and minimum value are 0, default maximum value depends on the style. For continuous styles, the maximum is 100.0. For discrete ones, it's 5.0
- (void)setLevelIndicatorStyle:(NSLevelIndicatorStyle)levelIndicatorStyle;
- (NSLevelIndicatorStyle)levelIndicatorStyle;
Get/set display style. Will not affect values. Setting will notify enclosing control to update.
- (double)minValue;
- (void)setMinValue:(double)minValue;
- (double)maxValue;
- (void)setMaxValue:(double)maxValue;
These are the same method names as NSSlider and set min/max values for ranking. Setting will notify enclosing control to update.
- (double)warningValue;
- (void)setWarningValue:(double)warningValue;
- (double)criticalValue;
- (void)setCriticalValue:(double)criticalValue;
These set and get the 'warning' and 'critical' values where the indicator goes from green to yellow to red. The order of the values determines which side is green and which side is red. If the critical value is greater than the warning value, then the indicator is green below the warning, yellow above that but below the critical, and red above. If the critical value is less than the warning value, the indicator is red when the value is below the critical value, yellow up to the critical value, and then green to the maximum value. If the values are the same, the indicator is always green.
- (void)setTickMarkPosition:(NSTickMarkPosition)position;
- (NSTickMarkPosition)tickMarkPosition;
- (void)setNumberOfTickMarks:(int)count;
- (int)numberOfTickMarks;
- (NSRect)rectOfTickMarkAtIndex:(int)index;
- (double)tickMarkValueAtIndex:(int)index;
These methods for tick marks are identical to the NSSliderCell APIs with the same behaviour. Set the number of ticks to 0 to not have any. Default is 0. An exception is raised if index is out of range. Setting will notify enclosing control to update if necessary.
- (void)setNumberOfMajorTickMarks:(int)count;
- (int)numberOfMajorTickMarks;
We also allow larger or 'major' tick marks. The count must be less than or equal to the number of tick marks. Setting will notify enclosing control to update if necessary. The major tick marks will be drawn in place of the minor ones.


Resolution Independent UI

As an ongoing effort, we're adding "resolution independent UI." This enables users to choose between more detail or larger user interface without actually having to change physical screen resolution.

In the AppKit we intend to concentrate on the "framework scaling" model (as described in the "Resolution Independent UI" release note), which by default causes windows to be scaled. One fundamental change in this mode is that when drawing to the screen, 1 point in the base window coordinate system is no longer necessarily the same as 1 pixel in the backing store of the window. Although we intend much of the support for this mode to be provided by the AppKit, there are some things applications will need to do themselves or watch out for, as outlined below.

For testing purposes developers can change the display resolution using the Quartz Debug application (located in the folder /Developer/Applications/Performance Tools). Note that because the work for supporting resolution independence in both Cocoa and Carbon is ongoing and not yet complete, there are various drawing problems when running with non-integral scale factors in Tiger. This is especially true when Quartz 2D Extreme acceleration is enabled.

Applying the scale factor

Windows are scaled using a transformation on the coordinate system of the top level view (the frameView). The dimensions of the frame of the frameView are equal to the dimensions of the window frame, as in the non-scaled case, but the dimensions of the bounds of the frameView are scaled by dividing the dimensions of the frame by the scaleFactor. For non-integral scaleFactors, the frame is kept integral but the bounds are allowed to have a fractional component. So, for example, a 100x100 window will have a frameView whose bounds is 80x80 for a userSpaceScaleFactor of 1.25. We consider the window frame to be in pixels, and the frameView bounds to be in points. Drawing within the window content is then done in points. Note that this implies that all views within the window are scaled, but we have decided that views whose only scaling is this base scaling for resolution independence purposes will return NO from -isRotatedOrScaledFromBase, so that scrolling, etc. will continue to go through the fast path.

Implications for view positioning and window sizing

Applications must not assume that the window frame and contained view frames use the same coordinate systems. For example, applications that use the window frame to position views will not get correct results. Likewise, applications that compute a change in window frame based on view size (eg. when adding an auxiliary view) will be incorrect. One mechanism for converting between coordinate systems correctly is -[NSView convertRect/Size/Point to/fromView:nil]. Another is -[NSWindow frameRectForContentRect:] and its inverse -[NSWindow contentRectForFrameRect:].

Images

Each imageRep that contains bitmap data indicates its own DPI, since it has both size in points and pixel width and height. An imageRep with 72 DPI has a 1-1 correspondence between points and pixels. An imageRep with 144 DPI has two times more pixels than points in both dimensions. We now create cachedImage reps with the scale factor of the destination window. For a window with a userSpaceScaleFactor of 1.25, a cachedImageRep of 100x100 points would report a size of 100x100, and a pixelWidth and pixelHeight of 125.

Compositing

Historically, compositing has been done in the base coordinate system, regardless of the destination coordinate system. To allow composite: to continue to work in a resolution independent environment, we define the base coordinate system of scaled windows to include the current scale factor.

Example 1 - compositing 72dpi 100x100 source image to view in 1.25x scaled window

A 72dpi 100x100 source image will contain 100x100 pixels. When composited into a 100x100 rect in a view in a scaled window, this image will be scaled to fill 125x125 pixels in the window using the appropriate interpolation algorithm. Any coordinate transforms on the destination view aside from window scaling will be ignored.

Example 2 - compositing 90dpi 100x100 source image to view in 1.25x scaled window

A 90dpi 100x100 source image will contain 125x125 pixels. When composited into a 100x100 rect in a view in a scaled window, this image will exactly fit 125x125 pixels in the window, so no interpolation will be needed. Any coordinate transforms on the destination view aside from window scaling will be ignored.

Example 3 - creating cached image rep from 72dpi 100x100 source image

A 72dpi 100x100 source image will contain 100x100 pixels. The cached image rep will be created with size 100x100, but will hold 125x125 pixels. The source image will be scaled to fit the pixel size of the cached image rep, using the appropriate interpolation. When the cached image rep is later drawn into a scaled window, this will be a 1 to 1 copy from cached image rep pixels to destination window pixels.

Dealing with non-integral view coordinates

In the past, view coordinates have been modified to land on integral boundaries in order to use an exact number of pixels. In a scaled window, any computation to put a view on integral boundaries should be done in the window coordinate system (pixels) then converted to the view coordinate system.

API for "application scaling" mode

The following API allow applications to use their own techniques to achieve resolution independence themselves. One use of this API might be to generate an inverse scaling on the bounds of a view that wants to draw in pixels rather than points.

This is the default scaling from user space to device space on the given screen:
@interface NSScreen : NSObject
...
- (float)userSpaceScaleFactor
...
@end
Since the scale factor gets applied to individual windows, we also provide a method to ask a window for its scaling. By default, this scale factor will be equal to the scale factor of the NSScreen on which the window was created, or the highest scale factor of the available NSScreens if no screen was specified at creation time. (Note that for the foreseeable future the scale factor of all NSScreens will be equal at any given time):
@interface NSWindow : NSResponder
...
- (float)userSpaceScaleFactor
...
@end
It might also be necessary to allow creation of windows without a scale factor, especially for custom windows. You can create an unscaled window by specifying a styleMask of NSUnscaledWindowMask at creation time.

An unscaled window would then return 1.0 for -userSpaceScaleFactor.

Impact on existing API

Both NSWindow and NSScreen define a -deviceDescription method, This method returns an NSDictionary containing a NSDeviceResolution key. NSDeviceResolution has historically contained an NSSize of (72.0, 72.0). On a scaled system, NSDeviceResolution will contain an NSSize of (72.0*userSpaceScaleFactor, 72.0*userSpaceScaleFactor).


NSAnimation

This base class implements timing for animation in Cocoa. There is one subclass available for view animation. The animation can run in the main event thread in blocking mode (i.e. not returning until done), in non-blocking mode so that events are still accepted and in an separate private thread.
typedef enum {
NSAnimationEaseInOut, /* s-curve, default */
NSAnimationEaseIn,
NSAnimationEaseOut,
NSAnimationLinear
} NSAnimationCurve;
typedef enum {
NSAnimationBlocking,
NSAnimationNonblocking,
NSAnimationNonblockingThreaded
} NSAnimationBlockingMode;
typedef float NSAnimationProgress;                      // value in range 0..1
extern NSString *NSAnimationProgressMarkNotification;   // has single entry in user info dictionary
extern NSString *NSAnimationProgressMark; // NSNumber(float) with NSAnimationProgress
@interface NSAnimation
- (id)initWithDuration:(NSTimeInterval)duration animationCurve:(NSAnimationCurve)animationCurve;
- (void)startAnimation;
- (void)stopAnimation;
- (BOOL)isAnimating;
Starts and stops the animation. Doesn't reset the progress when stopped. If at a progress of 1.0, calling -startAnimation starts again at progress 0.0. You can play an animation with no view, target or action. If the mode is set to NSAnimationBlocking, then -startAnimation only returns after the animation has run. The delegate can still stop the animation while running if necessary. When -startAnimation is called, the animation retains itself and then is autoreleased on -stopAnimation.
- (NSAnimationProgress)currentProgress;
- (void)setCurrentProgress:(NSAnimationProgress)progress;
Set/get the current progress (values 0.0...1.0). Can change while running. Out of range values are pinned to 0.0 or 1.0. The -setCurrentProgress method is called while playing to change the progress for the next frame. Subclasses should override to get the value and do their action. This action may be in a secondary thread if requested.
- (void)setDuration:(NSTimeInterval)duration;
- (NSTimeInterval)duration;
Set/get the duration of the effect. Duration is in seconds. Can change while running. Negative values raise an exception. If the duration set is past the current time and the animation is playing, the animation is ended.
- (NSAnimationBlockingMode)animationBlockingMode;
- (void)setAnimationBlockingMode:(NSAnimationBlockingMode)animationBlockingMode;
Set/get mode for running animation. Will take effect the next time the animation is started. Has no effect if animation already running. Default is NSAnimationBlocking. If set to NSAnimationBlocking, animation is run in main thread in custom run loop mode blocking UI. If animation is run NSAnimationNonblocking then animation is run in main thread in the common run loop modes or the ones specified in -runLoopModesForAnimating. NSAnimationNonblockingThreaded spawns a new thread that runs the animation.
- (void)setFrameRate:(float)framesPerSecond;
- (float)frameRate;
Set/get the frame rate (updates/second) of the effect. The frame rate is not guaranteed. Can be changed while running and will be used at the next frame. Value must be positive. A value of 0.0 means as fast as possible (currently limited to 30 fps). Negative values raise an exception.
- (void)setAnimationCurve:(NSAnimationCurve)curve;
- (NSAnimationCurve)animationCurve;
Set/get the animation curve. Predefined curves are linear, ease in (slow down as we reach end), ease out (slowly speed up start), and ease in/outS-curve. This setting is ignored if the delegate implements -animation:valueForProgress:. Invalid values raise an exception.
- (float)currentValue;
This is the current value of the effect based on the current progress. It is derived from the animation curve or from the delegate. This is a read-only setting. A subclass can override this method to provide a custom curve. The current value can be less than 0.0 or larger than 1.0. For example, by allowing the size to be greater then 1.0, one could do a 'rubber effect' where temporarily, the size of the view is larger than the final.
- (void)setDelegate:(id)delegate;
- (id)delegate;
Set/get the delegate. This is a weak reference - the delegate is not retained.
- (NSArray *)progressMarks;
- (void)setProgressMarks:(NSArray *)progressMarks;
These set/get all the progress marks at once. Array contains a list of NSNumbers containing NSAnimationProgress (floats). If there are no progress marks set, -progressMarks returns an empty array. Passing in nil to -setProgressMarks: will clear all progress marks..
- (void)addProgressMark:(NSAnimationProgress)progress;
- (void)removeProgressMark:(NSAnimationProgress)progress;
These set and clear 'progress marks'. These are used to notify the delegate or post a notification that the particular progress point has been reached. They can be used to synchronize animations (e.g. starting a new animation when the first one has reached the half-way point.) The notifications are only sent if the animation is playing. They can be called during playing of the animation. The notification is sent as soon as the progress point is passed so the actual currentProgress may be different from the requsted mark point. Valid intervals are from 0.0 to 1.0. Both 0.0 and 1.0 marks will always be send. Multiple marks may be sent during a single frame if the times are close enough together..
- (void)startWhenAnimation:(NSAnimation *)animation reachesProgress:(NSAnimationProgress)startProgress;
- (void)stopWhenAnimation:(NSAnimation *)animation reachesProgress:(NSAnimationProgress)stopProgress;
- (void)clearStartAnimation;
- (void)clearStopAnimation;
This links another animation to this one. When the linked animation reaches a certain progress point, the animation starts and/or stops. You can only have one animation set as a start animation and one set as a stop animation. Setting a new will will clear out the old one. You can also clear out the old one using -clearStartAnimation or -clearStopAnimation.
- (NSArray *)runLoopModesForAnimating;
By default, it returns nil. Custom subclass can override to return specific list run loop modes to run animation timer in. If it returns nil, the animation is run in any of default, modal, and event tracking modes. Ignored if animation mode isn't set to NSAnimationNonblocking.

Delegate Methods
- (BOOL)animationShouldStart:(NSAnimation *)animation;
- (void)animationDidStop:(NSAnimation *)animation;
- (void)animationDidEnd:(NSAnimation *)animation;
Called on start/stop animation and when animation reaches a progress vallue of 1.0. -animationShouldStart: can return NO to cancel the start. -animationDidStop: is called when the animation is explicitly stopped. -animationDidEnd: is called when it ends by reaching a progress value of 1.0. Only called if actual change occurs (i.e. won't call -animationShouldStart: if already playing)
- (float)animation:(NSAnimation *)animation valueForProgress:(NSAnimationProgress)progress;
Delegate can provide custom curve values. progress will always be from 0.0 to 1.0.
- (void)animation:(NSAnimation *)animation didReachProgressMark:(NSAnimationProgress)progress;
Called when the animation reaches a previously marked progress value. The actual current progress may be past the one passed in. Can also use the NSAnimationProgressMarkNotification notification.


NSViewAnimation

This is the only public subclass of NSAnimation. It takes an array of dictionaries that are copied and parses the dictionary. The dictionary contains a target which is required and which can be a window or view. It takes an optional start and/or end frame which if not defined uses the current frame when the animation starts. It can optionally take an effect which will, fade in or out the view or window. If the target is a view and the effect is to fade out or the end frame is empty, the view is hidden at the end. If the effect is to fade in and the end frame is non-empty and the view starts hidden, it is unhidden at the end. If there is no effect, the view frame is changed while animating. If the target is a window, the window is similarly ordered in or out. The animation is non-blocking by default, a duration of 0.5 seconds and the ease in-out curve.
APPKIT_EXTERN NSString *NSViewAnimationTargetKey;       // NSWindow* or NSView* (required)
APPKIT_EXTERN NSString *NSViewAnimationStartFrameKey; // NSValue*(NSRect) (optional)
APPKIT_EXTERN NSString *NSViewAnimationEndFrameKey; // NSValue*(NSRect) (optional)
APPKIT_EXTERN NSString *NSViewAnimationEffectKey; // NSString*(effect strings)(optional)
APPKIT_EXTERN NSString *NSViewAnimationFadeInEffect;
APPKIT_EXTERN NSString *NSViewAnimationFadeOutEffect;
@interface NSViewAnimation
- (id)initWithViewAnimations:(NSArray *)viewAnimations;
- (NSArray *)viewAnimations;
- (void)setViewAnimations:(NSArray *)viewAnimations;
@end

AppKit Extensions to support use of CoreImage API (Section added since WWDC)

The following API has been added to facilitate more convenient use of CoreImage functionality by Cocoa applications.

There is a new NSImageRep subclass called NSCIImageRep, which makes it possible to construct an NSImage that references a CIImage, as in the following code sample:
CIImage ciImage = [aCIFilter valueForKey:@"outputImage"];
CGRect extent = [ciImage extent];
/* Be careful here. A CIImage can have infinite extent. The following is OK only if you know your CIImage is of finite extent. */
NSImage *image = [[NSImage alloc] initWithSize:NSMakeSize(extent.size.width, extent.size.height)];
NSCIImageRep *ciImageRep = [NSCIImageRep imageRepWithCIImage:outputImage];
[image addRepresentation:ciImageRep];
The resultant NSImage should be usable in any context where an NSImage is called for. CoreImage will automatically render the result on demand. Note that CIImage instances are immutable, so when a change is made to a CIFilter parameter that affects the filter's output image, a new "outputImage" must be requested from the filter, and a new NSCIImageRep constructed from it.

NSCIImageRep.h also adds three new methods to CIImage via a category. The first enables clients to create a CIImage from an NSBitmapImageRep:
@interface CIImage (NSAppKitAdditions)
- (id)initWithBitmapImageRep:(NSBitmapImageRep *)bitmapImageRep;
The remaining two provide a convenient means to render all or part of a CIImage into the current NSGraphicsContext. They behave identically to the like methods in NSImage:
- (void)drawInRect:(NSRect)rect fromRect:(NSRect)fromRect operation:(NSCompositingOperation)op fraction:(float)delta;
- (void)drawAtPoint:(NSPoint)point fromRect:(NSRect)fromRect operation:(NSCompositingOperation)op fraction:(float)delta;
@end
NSGraphicsContext has a new method, -CIContext, that returns an associated CIContext that can be used to render into the NSGraphicsContext. The CIContext is created on demand, and remains in existence for the lifetime of its owning NSGraphicsContext. If desired, a CIContext can be asked to free the resources it holds by sending it a -reclaimResources or -clearCaches message.

New methods have been added to facilitate conversion between NSColor and CIColor types (the declarations are in NSColor.h):
@interface NSColor (NSQuartzCoreAdditions)
+ (NSColor *)colorWithCIColor:(CIColor *)color;
@end
@interface CIColor (NSAppKitAdditions)
- (id)initWithColor:(NSColor *)color;
@end
An NSColor can be converted to a CIColor as long as it isn't a pattern color. A CIColor can always be converted to an NSColor.

See the Core Image documentation for additional information on the use of Core Image functionality.


New NSResponder-Based Error Presentation (Section added since WWDC)

A new mechanism has been added to Cocoa to enable user-friendly error alerts that are informative, take proper advantage of sheets, and are easily customizable. Cocoa affords customization by publishing an overridable NSResponder method and an NSApplication delegate method that can be implemented. Such a method will typically examine the passed-in NSError object and, using the NSError's domain and code to determine what kind of error is to be presented, return a different NSError object if appropriate. NSError's existing underlyingError attribute makes it feasible to replace one NSError with another that is more presentable without destroying any information about the original detected cause of the problem.

Sometimes it is appropriate to present the user with error recovery options, and act accordingly after the user has chosen one of the options. For example, NSDocument can, when a document being saved is found to be locked, offer to override the lock and save anyway (it doesn't though, in Tiger). Cocoa supports this sort of functionality with the localizedRecoverySuggestion, localizedRecoveryOptions and recoveryAttempter attributes that have been added to Foundation's NSError class and that are honored by various AppKit classes that deal in NSErrors. See the "NSError" section of the Foundation release notes.

Three new methods have been added to the NSResponder class:
- (void)presentError:(NSError *)error modalForWindow:(NSWindow *)window
delegate:(id)delegate didPresentSelector:(SEL)didPresentSelector contextInfo:(void *)contextInfo;
Present an error alert to the user, as a document-modal panel. When the user has dismissed the alert and any recovery possible for the error and chosen by the user has been attempted, send the selected message to the specified delegate. The method selected by didPresentSelector must have the same signature as:
- (void)didPresentErrorWithRecovery:(BOOL)didRecover contextInfo:(void *)contextInfo;
The default implementation of this method always invokes [self willPresentError:error] to give subclassers an opportunity to customize error presentation. It then forwards the message, passing the customized error, to the next responder or, if there is no next responder, NSApp. NSApplication's override of this method invokes [[NSAlert alertWithError:theErrorToPresent] beginSheetModalForWindow:window modalDelegate:self didEndSelector:selectorForAPrivateMethod contextInfo:privateContextInfo]. When the user has dismissed the alert, the error's recovery attempter is sent an -attemptRecoveryFromError:optionIndex:delegate:didRecoverSelector:contextInfo: message, if the error had recovery options and a recovery delegate.

Errors for which ([[error domain] isEqualToString:NSCocoaErrorDomain] && [error code]==NSUserCancelledError) are a special case, because they do not actually represent errors and should not be presented as such to the user. NSApplication's override of this method does not present an alert to the user for these kinds of errors. Instead it merely invokes the delegate specifying didRecover==NO.

Between the responder chain in a typical application and various overrides of this method in AppKit classes, objects are given the opportunity to present errors in orders like these:

For windows owned by documents:
view -> superviews -> window -> window controller -> document -> document controller -> application

For windows that have window controllers but aren't associated with documents:
view -> superviews -> window -> window controller -> application

For windows that have no window controller at all:
view -> superviews -> window -> application

You can invoke this method to present error alert sheets. For example, Cocoa's own -[NSDocument saveToURL:ofType:forSaveOperation:delegate:didSaveSelector:contextInfo:] invokes this method when it's just invoked -saveToURL:ofType:forSaveOperation:error: and that method has returned NO.

You probably shouldn't override this method, because you have no way of reliably predicting whether this method vs. -presentError will be invoked for any particular error. You should instead override the -willPresentError: method described below.
- (BOOL)presentError:(NSError *)error;
Present an error alert to the user, as an application-modal panel, and return YES if error recovery was done, NO otherwise. This method behaves much like the previous one except it does not return until the user has dismissed the alert and, if the error had recovery options and a recovery delegate, the error's recovery delegate has been sent an -attemptRecoveryFromError:optionIndex: message.

You can invoke this method to present error alert dialog boxes. For example, Cocoa's own [NSDocumentController openDocument:] invokes this method when it's just invoked -openDocumentWithContentsOfURL:display:error: and that method has returned nil.

You probably shouldn't override this method, because you have no way of reliably predicting whether this method vs. -presentError:modalForWindow:delegate:didPresentSelector:contextInfo: will be invoked for any particular error. You should instead override the -willPresentError: method described below.
- (NSError *)willPresentError:(NSError *)error;
Given that the receiver is about to present an error (perhaps by just forwarding it to the next responder), return the error that should actually be presented. The default implementation of this method merely returns the passed-in error.

You can override this method to customize the presentation of errors by examining the passed-in error and if, for example, its localized description or recovery information is unsuitably generic, returning a more specific one. When you override this method always check the NSError's domain and code to discriminate between errors whose presentation you want to customize and those you don't. For those you don't just return [super willPresentError:error]. Don't make decisions based on the NSError's localized description, recovery suggestion, or recovery options because it's usually not a good idea to try to parse localized text.

NSDocument and NSDocumentController are not subclasses of NSResponder, and documents and the shared document controller are not in the responder chain, for historical reasons. NSDocument and NSDocumentController nonetheless implement the three new methods described above, and error presentation messages are by default forwarded as if documents and the shared document controller are in the responder chain. (NSWindowController also overrides the error presentation methods to help make this happen.)

In many applications it will be appropriate to override -willPresentError: in a subclass of NSWindowController, NSDocument, or NSDocumentController, but in some applications it will be easiest to customize some error presentation on a per-application basis. So that you don't have to subclass NSApplication to do so, a new application delegate method has been added:
- (NSError *)application:(NSApplication *)application willPresentError:(NSError *)error;
Given that the application object is about to present an error, return the error that should actually be presented.

You can implement this delegate method to customize the presentation of any error presented by your application, as long as no code in your application overrides -presentError:modalForWindow:delegate:didPresentSelector:contextInfo: or -presentError: in a way that prevent errors from being passed down to the application object. Your implementation of this delegate method should follow the advice given for overriding of -[NSResponder willPresentError:], except that it should just return the passed-in error instead of [super willPresentError:error].


New Error Presentation Method in NSAlert (Section added since WWDC)

We may in the future add to NSError still more attributes that are meant to contribute to the presentation of the error to the user. In that case it would be ideal if NSErrors carrying such attributes were presented properly, so a new method has been added to NSAlert to reduce the need for NSErrors to be picked apart by code that is naive of future NSError additions:
+ (NSAlert *)alertWithError:(NSError *)error;
Given an NSError, create an NSAlert that can be used to present the error to the user. The error's localized description, recovery suggestion, and recovery options will be used to set the alert's message text, informative text, and button titles, respectively.


NSDocument/NSDocumentController Error Handling (Section updated since WWDC)

In previous releases of Mac OS X Cocoa's NSDocument and NSDocumentController classes presented alerts that weren't informative, and it was very difficult to customize them. Both classes have been updated to take advantage of the NSError class that was added to Cocoa in Mac OS 10.3. Methods have been added to both classes, and methods have been deprecated. The new methods all consistently deal in NSURLs, replacing the melange of paths and URLs that previously existed.


New NSDocument Methods for Error Handling (Section updated since WWDC)

- (id)initWithContentsOfURL:(NSURL *)absoluteURL ofType:(NSString *)typeName error:(NSError **)outError;
Initialize a document located by a URL, of a specified type, and return it if successful. If not successful, return nil after setting *outError to an NSError that encapsulates the reason why the document could not be initialized. The default implementation of this method invokes [self init], [self readFromURL:absoluteURL ofType:typeName error:outError], [self setFileURL:absoluteURL], [self setFileType:typeName], and [self setFileModificationDate:theModificationDate].

This method replaces -initWithContentsOfFile:ofType: and -initWithContentsOfURL:ofType:, which are now deprecated. For backward binary compatibility -initWithContentsOfFile:ofType: is still invoked when appropriate if it is overridden. -initWithContentsOfURL:ofType: is never invoked from anywhere within Cocoa, as in Mac OS 10.3 and earlier.
- (BOOL)revertToContentsOfURL:(NSURL *)absoluteURL ofType:(NSString *)typeName error:(NSError **)outError;
Discard all unsaved document modifications and replace the document's contents by reading a file or file package located by a URL, of a specified type, and return YES if successful. If not successful, return NO after setting *outError to an NSError that encapsulates the reason why the document could not be reverted. The default implementation of this method invokes [self readFromURL:absoluteURL ofType:typeName error:outError], [self setFileModificationDate:theModificationDate], [self updateChangeCount:NSChangeCleared], and, if the document has an undo manager, [[self undoManager] removeAllActions]. It also deletes autosaved contents files when they have become obsolete.

This method replaces -revertToSavedFromFile:ofType: and -revertToSavedFromURL:ofType: which are now deprecated. For backward binary compatibility, -revertToSavedFromFile:ofType is still invoked when appropriate if overridden. -revertToSavedFromURL:ofType: is never invoked from anywhere within Cocoa, as in Mac OS 10.3 and earlier.
- (BOOL)readFromURL:(NSURL *)absoluteURL ofType:(NSString *)typeName error:(NSError **)outError;
- (BOOL)readFromFileWrapper:(NSFileWrapper *)fileWrapper ofType:(NSString *)typeName error:(NSError **)outError;
- (BOOL)readFromData:(NSData *)data ofType:(NSString *)typeName error:(NSError **)outError;
- (BOOL)writeToURL:(NSURL *)absoluteURL ofType:(NSString *)typeName error:(NSError **)outError;
- (NSFileWrapper *)fileWrapperOfType:(NSString *)typeName error:(NSError **)outError;
- (NSData *)dataOfType:(NSString *)typeName error:(NSError **)outError;
Methods that are meant to be optionally overridden in the same manner as the non-NSError-returning methods that they replace. See the comments in <AppKit/NSDocument.h> for details.

The replaced methods are -readFromFile:ofType:, -loadFileWrapperRepresentation:ofType:, -loadDataRepresentation:ofType:, -writeToFile:ofType:, -fileWrapperRepresentationOfType:, and -dataRepresentationOfType:. They are all now deprecated. For backward binary compatibility, the old methods are still invoked when appropriate if overridden. Also deprecated are -readFromURL:ofType: and -writeToURL:ofType:, which are never invoked from anywhere within Cocoa, as in Mac OS 10.3 and earlier.
- (BOOL)writeSafelyToURL:(NSURL *)absoluteURL ofType:(NSString *)typeName
forSaveOperation:(NSSaveOperationType)saveOperation
error:(NSError **)outError;
- (BOOL)writeToURL:(NSURL *)absoluteURL ofType:(NSString *)typeName
forSaveOperation:(NSSaveOperationType)saveOperation
originalContentsURL:(NSURL *)absoluteOriginalContentsURL
error:(NSError **)outError;
- (NSDictionary *)fileAttributesToWriteToURL:(NSURL *)absoluteURL ofType:(NSString *)typeName
forSaveOperation:(NSSaveOperationType)saveOperation
originalContentsURL:(NSURL *)absoluteOriginalContentsURL
error:(NSError **)outError;
More methods that are meant to be optionally overridden in the same manner as the non-NSError-returning methods that they replace. See the comments in <AppKit/NSDocument.h> for details.

The replaced methods are -writeWithBackupToFile:ofType:saveOperation:, -writeToFile:ofType:originalFile:saveOperation:, and -fileAttributesToWriteToFile:ofType:saveOperation:. They are all now deprecated. For backward binary compatibility, the old methods are still invoked when appropriate if overridden.
- (void)setFileURL:(NSURL *)absoluteURL;
- (NSURL *)fileURL;
Accessors for the location of the document's on-disk representation. The set method doesn't actually rename the document, it's just for recording the document's location during initial opening or saving. The default implementation of -setFileURL: just records the URL so that the default implementation of -fileURL can return it. The default implementation of -fileURL returns whatever was stored by a previous invocation of the default implementation of -setFileURL:.

As part of the parallel effort to use NSURLs consistently, these methods replace -setFileName: and -fileName, which are now deprecated. For backward binary compatibility the old methods are still invoked when appropriate if overridden.
- (void)saveToURL:(NSURL *)absoluteURL ofType:(NSString *)typeName
forSaveOperation:(NSSaveOperationType)saveOperation
delegate:(id)delegate didSaveSelector:(SEL)didSaveSelector contextInfo:(void *)contextInfo;
Save the contents of the document to a file or file package located by a URL, formatted to a specified type, for a particular kind of save operation. When saving is completed, regardless of success or failure, send the message selected by didSaveSelector to the delegate, with the contextInfo as the last argument. The method selected by didSaveSelector must have the same signature as:
- (void)document:(NSDocument *)document didSave:(BOOL)didSaveSuccessfully contextInfo:(void *)contextInfo;
The default implementation of this method first makes sure that any editor registered using Cocoa Bindings' NSEditorRegistration informal protocol has committed its changes (except for autosave operations), then invokes [self saveToURL:absoluteURL ofType:typeName forSaveOperation:saveOperation error:&anError] and, if NO is returned, presents the error to the user in a document-modal panel before messaging the delegate.

As part of the parallel effort to use NSURLs consistently, this method replaces -saveToFile:saveOperation:delegate:didSaveSelector:contextInfo:, which is now deprecated. For backward binary compatibility the old method is still invoked when appropriate if overridden.


New NSDocumentController Methods for Error Handling (Section updated since WWDC)

- (id)openUntitledDocumentAndDisplay:(BOOL)displayDocument error:(NSError **)outError;
- (id)makeUntitledDocumentOfType:(NSString *)typeName error:(NSError **)outError;
- (id)openDocumentWithContentsOfURL:(NSURL *)absoluteURL display:(BOOL)displayDocument error:(NSError **)outError;
- (id)makeDocumentWithContentsOfURL:(NSURL *)absoluteURL ofType:(NSString *)typeName error:(NSError **)outError;
Methods that are meant to be optionally overridden in the same manner as the non-NSError-returning methods that they replace. See the comments in <AppKit/NSDocumentController.h> for details.

The replaced methods are -openUntitledDocumentOfType:display:, -makeUntitledDocumentOfType:, -openDocumentWithContentsOfFile:display:, and makeDocumentWithContentsOfFile:ofType:. They are all now deprecated. For backward binary compatibility, the old methods are still invoked when appropriate if overridden. Also deprecated are -openDocumentWithContentsOfURL:display: and -makeDocumentWithContentsOfURL:ofType:, which are never invoked from anywhere within Cocoa, as in Mac OS 10.3 and earlier.
- (id)documentForURL:(NSURL *)absoluteURL;
Given a URL, return the open document whose file or file package is located by the URL, or nil if there is no such open document. The default implementation of this method queries each open document to find one whose URL matches, and returns the first one whose URL does match.

As part of the parallel effort to use NSURLs consistently, this method replaces -documentForFileName:, which is now deprecated. For backward binary compatibility the old method is still invoked when appropriate if overridden.

-fileNamesFromRunningOpenPanel: is also deprecated. It is no longer invoked by -openDocument: unless it is overridden. The existing -URLsFromRunningOpenPanel: method is now used instead.

Finally, -setShouldCreateUI: and -shouldCreateUI are deprecated, because as used by NSDocumentController in the past they are not useful. -shouldCreateUI is still invoked by the also-deprecated -openUntitledDocumentOfType:display:, -openDocumentWithContentsOfFile:display:, and -openDocumentWithContentsOfURL:display: methods, and also the new -openUntitledDocumentAndDisplay:error: and -openDocumentWithContentsOfURL: display:error: methods, but only for backward compatibility. If your NSDocument subclass is sending itself a -makeWindowControllers message during initialization, and you're using -setShouldCreateUI: to keep NSDocumentController from sending another -makeWindowControllers message, you should considering fixing your NSDocument subclass, because NSDocuments should never need to invoke -makeWindowControllers during initialization.


Use of NSSaveAsOperation Instead of NSSaveOperation in NSDocument

-saveDocumentWithDelegate:didSaveSelector:contextInfo: now invokes -runModalSavePanelForSaveOperation:delegate:didSaveSelector:contextInfo: with NSSaveAsOperation instead of NSSaveOperation when a save panel is going to be presented. Checking saveOperation==NSSaveOperation without also checking [self fileName] or [self fileURL] is now valid, for apps that require Tiger.


Change to NSDocument's Standard Save Panel Accessory View

The File Format popup in the standard save panel accessory view installed by NSDocument no longer includes export-only file type items for NSSaveOperation and NSSaveAsOperation. Those items were always disabled, but because the user could not possibly cause them to become enabled by doing something in the save panel it was not appropriate to include them.


Change to NSDocumentController's Presentation of Document Opening Errors

In previous releases of Mac OS X NSDocumentController would present an error alert if a document selected by the user with the open panel could not be opened, but it would not present the same alert when the document opening was attempted as a result of the user double-clicking on the document's icon in the Finder, or dragging of the document's icon onto the application's icon. This has been fixed. NSDocumentController now consistently presents an error alert whenever document opening fails. For backward binary compatibility, NSDocumentController does not do this in applications linked against Mac OS 10.3 or earlier, because several applications have worked around the problem by presenting error alerts of their own (and two error alerts are not better than one).


New NSDocument Initializer Just For New Documents (Section updated since WWDC)

In previous releases of Mac OS X there was no NSDocument initializer that would be invoked when a new document was created but not when a document was being opened. Such an initializer has been added:
- (id)initWithType:(NSString *)typeName error:(NSError **)outError;
Initialize a new empty document of a specified type, and return it if successful. If not successful, return nil after setting *outError to an NSError that encapsulates the reason why the document could not be initialized. The default implementation of this method just invokes [self init] and [self setFileType:typeName].

You can override this method to perform initialization that must be done when creating new documents but should not be done when opening existing documents. Your override should typically invoke super, or at least it must invoke -init, NSDocument's designated initializer, to initialize NSDocument's private instance variables.


New NSDocument Methods for File Modification Dates (Section updated since WWDC)

New NSDocument methods have been added to track the modification date of the document's file on disk:
- (void)setFileModificationDate:(NSDate *)modificationDate;
- (NSDate *)fileModificationDate;
The method -fileModificationDate returns the last known modification date of the document's on-disk representation. -setFileModificationDate: is invoked by the default implementations of -initWithContentsOfURL:ofType:error:, -initForURL:withContentsOfURL:ofType:error:, -revertToContentsOfURL:ofType:error:, and -saveToURL:ofType:forSaveOperation:error:. In a future release -saveDocumentWithDelegate:didSaveSelector:contextInfo: may test the file modification date and warn the user when they may be about to overwrite modifications by something other than the current application.


New NSDocument Method for All Document Saving

A new method has been added to NSDocument so that you can override it to do things before and after any save operation:
- (BOOL)saveToURL:(NSURL *)absoluteURL ofType:(NSString *)typeName
forSaveOperation:(NSSaveOperationType)saveOperation error:(NSError **)outError;
Save the contents of the document to a file or file package located by a URL, formatted to a specified type, for a particular kind of save operation, and return YES if successful. If not successful, return NO after setting *outError to an NSError that encapsulates the reason why the document could not be saved.

The default implementation of this method invokes [self writeSafelyToURL:absoluteURL ofType:typeName forSaveOperation:saveOperation error:outError]. If that returns YES, it also invokes some combination of -setFileModificationDate:, -setFileType:, -setFileURL:, -updateChangeCount:, and -setAutosavedContentsFileURL:, as appropriate for the kind of save operation. It also updates information that -saveDocumentWithDelegate:didSaveSelector:contextInfo: uses to check for modification, renaming, moving, deleting, and trashing of open documents, and deletes autosaved contents files when they have become obsolete. Because this method does several diffferent things, and because the things are likely to change in future releases of Mac OS X, your override of this method should virtually always invoke super, merely adding new behavior before or after the saving.


Document Autosaving

Support for autosaving of documents has been added to Cocoa. The support takes the form of optional periodic autosaving behavior, new autosaving behavior at application-quitting time, and new NSDocument and NSDocumentController methods that you can invoke and override to customize the behavior.


New NSDocumentController Methods for Autosaving

Two new methods have been added to NSDocumentController so that you can enable periodic autosaving and control how often documents are periodically autosaved:
- (void)setAutosavingDelay:(NSTimeInterval)autosavingDelay;
- (NSTimeInterval)autosavingDelay;
The time interval in seconds for periodic autosaving. A value of 0 indicates that periodic autosaving should not be done at all. NSDocumentController will use this number as the amount of time to wait between detecting that a document has unautosaved changes and sending the document an -autosaveDocumentWithDelegate:didAutosaveSelector:contextInfo: message. The default value is 0. You can change it to enable periodic autosaving.

Two new methods that are invoked when reopening autosaved documents have been added to NSDocumentController:
- (BOOL)reopenDocumentForURL:(NSURL *)absoluteDocumentURL
withContentsOfURL:(NSURL *)absoluteDocumentContentsURL error:(NSError **)outError;
Reopen a document located by a URL by reading the contents for the document from another URL, present its user interface, and return YES if successful. If not successful, return NO after setting *outError to an NSError that encapsulates the reason why the document could not be reopened. The default implementation of this method determines the type of document being reopened, sends a -makeDocumentForURL:withContentsOfURL:ofType:error: to instantiate it, then invokes -addDocument: to record its opening. It then sends the document -makeWindowControllers and -showWindows messages.
- (id)makeDocumentForURL:(NSURL *)absoluteDocumentURL withContentsOfURL:(NSURL *)absoluteDocumentContentsURL
ofType:(NSString *)typeName error:(NSError **)outError;
Instantiate a document located by a URL, of a specified type, but by reading the contents for the document from another URL, and return it if successful. If not successful, return nil after setting *outError to an NSError that encapsulates the reason why the document could not be instantiated. The default implementation of this method invokes -documentClassForType: to find out the class of document to instantiate, allocates a document object, and initializes it by sending it an -initForURL:withContentsOfURL:ofType:error: message.


New NSDocument Methods and Enumerators for Autosaving

New methods have been added to NSDocument. New NSDocumentChangeTypes and a new NSSaveOperationType have been added too:
- (BOOL)hasUnautosavedChanges;
Return YES if the document has changes that have not been autosaved, NO otherwise, as determined by the history of previous invocations of -updateChangeCount:. The default implementation of this method returns NO immediately after invocation of -updateChangeCount:NSChangeCleared or -updateChangeCount:NSChangeAutosaved. It will then return YES if a different number of -updateChangeCount:NSChangeDone and -updateChangeCount:NSChangeUndone invocations have been done since. (-updateChangeCount:NSChangeReadOtherContents has no effect on what the default implementation of this method returns.)
- (void)autosaveDocumentWithDelegate:(id)delegate didAutosaveSelector:(SEL)didAutosaveSelector contextInfo:(void *)contextInfo;
Autosave the document's contents at an appropriate location, and then send the message selected by didAutosaveSelector to the delegate, with the contextInfo as the last argument. The method selected by didAutosaveSelector must have the same signature as:
- (void)document:(NSDocument *)document didAutosave:(BOOL)didAutosaveSuccessfully contextInfo:(void *)contextInfo;
If any error occurs while autosaving, it must be reported to the user, typically in a document-modal alert panel, before the delegate is messaged with succeeded:NO.

The default implementation of this method figures out where the autosaved document contents should go and invokes [self saveToURL:autosavedDocumentContentsURL ofType:[self autosavingFileType] forSaveOperation:NSAutosaveOperation delegate:inDelegate didSaveSelector:inDidAutosaveSelector contextInfo:inContextInfo].
- (NSString *)autosavingFileType;
Return the document type that should be used for an autosave operation. The default implementation just returns [self fileType], so for never-been-saved documents this method will return the first type in the array returned by [[self class] writableTypes], or nil if the array is empty. You can override this method and return nil in your override to completely disable autosaving of individual documents (NSDocumentController will not send -autosaveDocumentWithDelegate:didAutosaveSelector:contextInfo: to a document that has no autosaving file type.) You can also override it if your application defines a document type that is specifically designed for autosaving. For example, one that efficiently represents document contents _changes_ instead of complete document contents.
- (void)setAutosavedContentsFileURL:(NSURL *)absoluteURL;
- (NSURL *)autosavedContentsFileURL;
The location of the most recently autosaved document contents. The default implementation of -setAutosavedContentsFileURL: records the URL and notifies the shared document controller that this document should be autoreopened if the application is quit by a fast logout (a feature not in Tiger), or crashes before the document is saved. The default implementation of -autosavedContentsFileURL just returns whatever was stored by a previous invocation of the default implementation of -setAutosavedContentsFileURL:.

For example, -saveToURL:ofType:forSaveOperation:error: invokes -setAutosavedContentsFileURL: to record when autosaving has been done, and both methods as part of deleting autosaved document contents when a regular Save or Save As operation has been done successfully. -revertToContentsOfURL:ofType:error: also invokes these as part of deleting autosaved document contents.

During autosaving a new NSSaveOperationType is used:
NSAutosaveOperation
The writing of a document's current contents to a file or file package that is separate from the document's current one, without changing the document's current one. Backward binary compatibility code in NSDocument ensures that this value is never passed to overrides of methods that take NSSaveOperationTypes. NSSaveToOperation is always used in those cases instead.

After successful autosaving -updateChangeCount: with a new NSDocumentChangeType must be invoked:
NSChangeAutosaved
The value to pass to indicate that the document's contents have been autosaved. For example, -saveToURL:ofType:forSaveOperation:error: uses this for a successful NSAutosaveOperation.

A new method that you can override to customize the reopening of autosaved documents has been added:
- (id)initForURL:(NSURL *)absoluteDocumentURL withContentsOfURL:(NSURL *)absoluteDocumentContentsURL
ofType:(NSString *)typeName error:(NSError **)outError;
Initialize a document located by a URL, of a specified type, but by reading the contents for the document from another URL, and return it if successful. If not successful, return nil after setting *outError to an NSError that encapsulates the reason why the document could not be initialized. The default implementation of this method invokes [self readFromURL:absoluteDocumentContentsURL ofType:typeName error:outError], [self setFileURL:absoluteURL], [self setAutosavedContentsFileURL:absoluteDocumentContentsURL], [self setFileType:typeName], and [self setFileModificationDate:theModificationDate]. It also invokes [self updateChangeCount:NSChangeReadOtherContents] if the two URLs aren't identical, so that -isDocumentEdited will always return YES until the user saves or reverts the document.

To ease the adoption of the autosaving feature introduced in Mac OS 10.4, the default implementation of this method invokes [self initWithContentsOfFile:[absoluteDocumentContentsURL path] ofType:typeName] if -initWithContentsOfFile:ofType: is overridden and the URL uses the "file:" scheme. It still invokes [self setFileModificationDate:theModificationDate] and [self updateChangeCount:NSChangeReadOtherContents] in this situation. It still also invokes [self setFileURL:absoluteURL], to overwrite the incorrect invocation of -setFileName: that the override of -initWithContentsOfFile:ofType: likely did.

absoluteDocumentURL will be nil if the initializing is being done as part of the reopening of an autosaved document when the autosaved document had never been saved in the first place.

During autosaved document reopening -initForURL:withContentsOfURL:ofType:error: uses a new NSDocumentChangeType:
NSChangeReadOtherContents
The value to pass to -updateChangeCount: to indicate that the document has been initialized with the contents of a file or file package other than the one whose location would be returned by -fileURL, and therefore can't possibly be synchronized with its persistent representation. For example, -initForURL:withContentsOfURL:ofType:error: uses this to indicate that an autosaved document is being reopened.


NSDocument/NSDocumentController Support for Dynamically-Enabled Document Types

Several interesting Cocoa applications have implemented dynamically-enabled document types, in which support for additional document types is provided by plugins. Because NSDocumentController and NSDocument access document type declarations in Info.plist in a non-public way, developers have resorted to accessing private NSDocumentController and NSDocument instance variables directly, which is discouraged. To obviate such discouraged behavior, new methods that you can override, in addition to overriding existing methods, have been added so you can safely implement your own dynamically-enabled document typing scheme.


New NSDocumentController Methods for Dynamically-Enabled Document Types

- (NSString *)defaultType;
Return the name of the document type that should be used when creating new documents. The default implementation of this method returns the first Editor type declared in the application's Info.plist, or returns nil if no Editor type is declared. You can override it to customize the type of document that is created when, for instance, the user chooses New in the File menu.

[NSDocumentController openUntitledDocumentAndDisplay:error:] for instance always invokes this method. -[NSDocumentController validateUserInterfaceItem:] also invokes this when deciding whether or not any UI item whose action is newDocument: (the New item in the File menu, typically) should be enabled.
- (NSString *)typeForContentsOfURL:(NSURL *)inAbsoluteURL error:(NSError **)outError;
Given a URL, return the name of the document type that should be used when opening the document at that location, if successful. If not successful, return nil after setting *outError to an NSError that encapsulates the reason why the document's type could not be determined, or the fact that the document's type is just unrecognized. The default implementation of this method invokes -typeFromFileExtension:, possibly twice, passing an HFS file type string for the second invocation. The default implementation is of course subject to change however. You can override this to customize type determination for documents being opened.

[NSDocumentController openDocumentWithContentsOfURL:display:error:] and -[NSDocumentController reopenDocumentForURL:withContentsOfURL:error:] for instance always invoke this method.
- (NSArray *)documentClassNames;
Return the names of NSDocument subclasses supported by this application. The default implementation of this method returns information derived from the application's Info.plist. You can override it to return the names of document classes that are dynamically loaded from plugins.


New NSDocument Method for Dynamically-Enabled Document Types

- (NSArray *)writableTypesForSaveOperation:(NSSaveOperationType)saveOperation;
Return the names of the types to which this document can be saved for a particular kind of save operation. For every kind of save operation except NSSaveToOperation the returned array must only include types for which the the application can play the Editor role. For NSSaveToOperation the returned array may also include types for which the application can only play the Viewer role, and still more types that the application can merely export. The default implementation of this method returns [[self class] writableTypes] with, except during NSSaveToOperations, types for which +isNativeType returns NO filtered out.

You can override this method to limit the set of writable types when the documently currently contains data that is not representable in all writable types. For example, you can disallow saving to .rtf files when the document contains an attachment and can only be saved properly to .rtfd files. NSDocument currently uses this this method during save operations that present save panels, but it may be called at other times in future releases of Mac OS X.

You can invoke this method when creating a custom save panel accessory view to easily present the same set of types that NSDocument would present in its standard file format popup menu.


Proper Invocation of Existing NSDocument Methods for Dynamically-Enabled Document Types

The implementations of the existing NSDocument class methods +readableTypes, +writableTypes, and +isNativeType: have not changed significantly, but they are now invoked when you would expect them to be invoked, so that it is useful to override them. For example, each NSDocument subclass whose name is returned by -[NSDocumentController documentClassNames] is now sent a +readableTypes messages to determine the list of types than can be opened. For another example, the class of a document that is being saved is sent a +writableTypes message to determine the list of of types than can be saved. In the case of an NSSaveOperation or NSSaveAsOperation +isNativeType: is sent for each type returned by +readableTypes, to filter out export-only types.


New NSDocumentController Method to Control the Open Recents Menu

A new method has been added to NSDocumentController so that you can override it to control NSDocumentController's presentation of the standard Open Recents menu:
- (unsigned int)maximumRecentDocumentCount;
Return the maximum number of items that may be presented in the standard Open Recent menu. A value of 0 indicates that NSDocumentController will not attempt to add an Open Recent menu to your application's File menu, though NSDocumentController will not attempt to remove any Open Recent menu item if there is one already there. The default implementation returns a value that is subject to change and may or may not be derived from a setting made by the user in a System Preferences panel.


Changes in NSDocument's Handling of the 'Save' Scripting Command (Section added since WWDC)

The behavior of -[NSDocument(NSScripting) handleSaveScriptCommand:], the method that is typically invoked when a script sends a 'save' command to a document, is changed in Mac OS 10.4. It now implements the behavior described in <http://developer.apple.com/technotes/tn2002/tn2106.html>. Here's a comparison of the old and new behavior:

When an 'in' argument is provided for an already-saved document
- 10.3: Acted like 'Save As...' unless the document class returned NO for +isNativeType:typeDerivedFromFileExtension, in which case acted like 'Save a Copy...' (also known as 'Save To...'). Invoked -writeWithBackupToFile:ofType:saveOperation: directly.
- 10.4: Acts like 'Save a Copy...' Invokes -saveToURL:ofType:forSaveOperation:delegate:didSaveSelector:contextInfo:.

When an 'in' argument is provided for a never-been-saved document
- 10.3: Acted like 'Save As...' unless the document class returned NO for + isNativeType:typeDerivedFromFileExtension, in which case acted like 'Save a Copy...' Invoked -writeWithBackupToFile:ofType:saveOperation: directly.
- 10.4: Acts like 'Save As...' Invokes -saveToURL:ofType:forSaveOperation:delegate:didSaveSelector:contextInfo:.

When no 'in' argument is provided for an already-saved document
- 10.3: Acted like 'Save.' Invoked -saveDocument:.
- 10.4: Acts like 'Save.' Invokes -saveDocumentWithDelegate:didSaveSelector:contextInfo:.

When no 'in' argument is provided for a never-been-saved document
- 10.3: Acted like 'Save As...' Invoked -saveDocumentAs:.
- 10.4: Acts like 'Save,' which in this case is indistinguishable from 'Save As...,' because a save dialog must be presented to the user. Invokes -saveDocumentWithDelegate:didSaveSelector:contextInfo:.

TextEdit, which is not NSDocument-based, has been updated to implement the same behavior.


Changes in NSDocument's Handling of Editors Registered via Cocoa Bindings' NSEditorRegistration Informal Protocol (Section added since WWDC)

In Mac OS 10.3 NSDocument implemented Cocoa Bindings' NSEditorRegistration informal protocol and would tell key-value binding editors to commit and discard their changes at certain times. In Mac OS 10.4 NSDocument's handling of key-value binding editors has been refined. These methods no long tell registered editors to commit their changes:
-saveDocument:, -saveDocumentAs:, and -saveDocumentTo:, and -printDocument:.
-canCloseDocumentWithDelegate:shouldCloseSelector:contextInfo:.
-[NSDocumentController saveAll:].
Instead, these NSDocument methods now tell registered editors to commit their changes:
-saveDocumentWithDelegate:didSaveSelector:contextInfo:
-runModalSavePanelForSaveOperation:delegate:didSaveSelector:contextInfo:
-saveToURL:ofType:forSaveOperation:delegate:didSaveSelector:contextInfo: (except for NSAutosaveOperations)
-printDocumentWithSettings:showPrintPanel:delegate:didPrintSelector:contextInfo:
The end result is that any alert sheets that editors may present when asked to commit are now always presented at the right time.

-revertDocumentToSaved: now tells registered editors to discard after the user has seen the "do you want to revert?" panel and chosen "Revert," instead of before the panel is presented.

-close now tells editors to discard their changes.

-isDocumentEdited now returns YES whenever there are registered key-value binding editors.

For backward binary compatibility, NSDocument will send -commitEditingWithDelegate:didCommitSelector:contextInfo: messages to registered editors that implement the this new method, but will fall back to using the old (but not deprecated) -commitEditing message to those that don't.


Bug Fix for Instantation of NSDocumentController Subclasses (Section added since WWDC)

According to the documentation titled "Creating a Subclass of NSDocumentController:"

"The application will not ask for its shared document controller until after the applicationWillFinishLaunching: message is sent to its delegate. Therefore, you can create an instance of your sub-class of NSDocumentController in your application delegate's applicationWillFinishLaunching: method and that instance will be set as the shared document controller."

In Mac OS 10.0-10.3 this was not always true. Code within AppKit would invoke +[NSDocumentController sharedDocumentController] during the loading of your application's main nib, if it contained an Open Recent menu item, before the sending of -applicationWillFinishLaunching: to the application delegate, preventing the NSDocumentController instantiated by the application delegate from being returned by subsequent invocations of +sharedDocumentController. This was a bug and has been fixed in Mac OS 10.4. (The bug did not affect applications that have no Open Recent menu item in their main nib and let NSDocumentController add one under the first item that had a nil target and an openDocument: action, like Sketch and Property List Editor.)


Bug Fix in -[NSDocument displayName]

In Mac OS 10.3, NSDocuments began sending themselves -displayName messages for the purpose of determining whether or not the document was untitled. NSDocument's implementation of -displayName would return nil in this situation. This interfered with overrides of -displayName that invoked [super displayName] and assumed that a non-nil value would be returned (a valid assumption). This bug has been fixed. -[NSDocument displayName] no longer ever returns nil.


Removal of Obsolete Method Declarations from NSDocument.h and NSDocumentController.h

Four NSDocument methods were marked as obsolete of as Mac OS 10.0, having been superseded by methods whose behavior in the presence of multiple sheets is markedly better:

-canCloseDocument: was replaced by -canCloseDocumentWithDelegate:shouldCloseSelector:contextInfo:
-fileNameFromRunningSavePanelForSaveOperation: was replaced by -saveDocumentWithDelegate:didSaveSelector:contextInfo:
-runModalSavePanel:withAccessoryView: was replaced by -runModalSavePanelForSaveOperation:delegate:didSaveSelector:contextInfo:
-shouldCloseWindowController: was replaced by -shouldCloseWindowController:delegate:shouldCloseSelector:contextInfo:

Two NSDocumentController methods were likewise marked as obsolete at the same time:

-closeAllDocuments: was replaced by -closeAllDocumentsWithDelegate:didCloseAllSelector:contextInfo:
-reviewUnsavedDocumentsWithAlertTitle:cancellable: was replaced by -reviewUnsavedDocumentsWithAlertTitle:cancellable:delegate:didReviewAllSelector:contextInfo:

The declarations for these six methods have been removed from NSDocument.h and NSDocumentController.h. You should stop using or overriding them in your applications and start using or overriding their replacements. However, for backward binary compatibility their implementations remain in Cocoa, in categories named NSDocument(NSCompatibility) and NSDocumentController(Compatibility). If you are not able to migrate to the newer methods, you can do away with any compiler warnings caused by the changes in NSDocument.h and NSDocumentController.h by adding the following declarations to the relevant source code files in your project:
@interface NSDocument(NSDeprecatedLongAgo)
- (BOOL)canCloseDocument;
- (NSString *)fileNameFromRunningSavePanelForSaveOperation:(NSSaveOperationType)saveOperation;
- (int)runModalSavePanel:(NSSavePanel *)savePanel withAccessoryView:(NSView *)accessoryView;
- (BOOL)shouldCloseWindowController:(NSWindowController *)windowController;
@end
@interface NSDocumentController(NSDeprecatedLongAgo)
- (BOOL)closeAllDocuments;
- (BOOL)reviewUnsavedDocumentsWithAlertTitle:(NSString *)title cancellable:(BOOL)cancellable;
@end

Summary of Deprecated NSDocument Methods

Search in the above release notes for information about why each has been deprecated, and when it is still invoked.
- (NSData *)dataRepresentationOfType:(NSString *)type;
- (NSDictionary *)fileAttributesToWriteToFile:(NSString *)fullDocumentPath
ofType:(NSString *)documentTypeName saveOperation:(NSSaveOperationType)saveOperationType;
- (NSString *)fileName;
- (NSFileWrapper *)fileWrapperRepresentationOfType:(NSString *)type;
- (id)initWithContentsOfFile:(NSString *)absolutePath ofType:(NSString *)typeName;
- (id)initWithContentsOfURL:(NSURL *)absoluteURL ofType:(NSString *)typeName;
- (BOOL)loadDataRepresentation:(NSData *)data ofType:(NSString *)type;
- (BOOL)loadFileWrapperRepresentation:(NSFileWrapper *)wrapper ofType:(NSString *)type;
- (void)printShowingPrintPanel:(BOOL)flag;
- (BOOL)readFromFile:(NSString *)fileName ofType:(NSString *)type;
- (BOOL)readFromURL:(NSURL *)url ofType:(NSString *)type;
- (BOOL)revertToSavedFromFile:(NSString *)fileName ofType:(NSString *)type;
- (BOOL)revertToSavedFromURL:(NSURL *)url ofType:(NSString *)type;
- (int)runModalPageLayoutWithPrintInfo:(NSPrintInfo *)printInfo;
- (void)saveToFile:(NSString *)fileName saveOperation:(NSSaveOperationType)saveOperation
delegate:(id)delegate didSaveSelector:(SEL)didSaveSelector contextInfo:(void *)contextInfo;
- (void)setFileName:(NSString *)fileName;
- (BOOL)writeToFile:(NSString *)fileName ofType:(NSString *)type;
- (BOOL)writeToFile:(NSString *)fullDocumentPath ofType:(NSString *)documentTypeName
originalFile:(NSString *)fullOriginalDocumentPath saveOperation:(NSSaveOperationType)saveOperationType;
- (BOOL)writeToURL:(NSURL *)url ofType:(NSString *)type;
- (BOOL)writeWithBackupToFile:(NSString *)fullDocumentPath ofType:(NSString *)documentTypeName
saveOperation:(NSSaveOperationType)saveOperationType;

Summary of Deprecated NSDocumentController Methods

Search in the above release notes for information about why each has been deprecated, and when it is still invoked.
- (id)documentForFileName:(NSString *)fileName;
- (NSArray *)fileNamesFromRunningOpenPanel;
- (id)makeDocumentWithContentsOfFile:(NSString *)fileName ofType:(NSString *)type;
- (id)makeDocumentWithContentsOfURL:(NSURL *)url ofType:(NSString *)type;
- (id)makeUntitledDocumentOfType:(NSString *)type;
- (id)openDocumentWithContentsOfFile:(NSString *)fileName display:(BOOL)display;
- (id)openDocumentWithContentsOfURL:(NSURL *)url display:(BOOL)display;
- (id)openUntitledDocumentOfType:(NSString*)type display:(BOOL)display;
- (void)setShouldCreateUI:(BOOL)flag;
- (BOOL)shouldCreateUI;

NSPersistentDocument

NSPersistentDocument is a subclass of NSDocument that enables easily creating document types which are made persistent by the CoreData framework. NSPersistentDocument instances have an NSManagedObjectContext (and thus a NSPersistentStoreCoordinator - the default implementation creates a separate stack of context, coordinator and persistent store for each document, but that can be re-configured by overriding). The coordinator is created with [self model].

NSPersistentDocument by default stores data in an XML file (an XML persistent store), but that can be reconfigured to SQL or binary formats by overriding the configurePersistentStoreCoordinatorForURL:ofType:error: method.

Summary of how various document operations work:
- Open: Invokes the configure... method with the file URL, adds a store of the default type (XML). Objects will be loaded from the persistent store on demand through the document's context.
- Save: On a new document, will add a store of the default type with the user's chosen URL, then invokes save: on the context. For an already open document, just invokes save: on the context.
- Save As: For a new document, falls back to Save:. For an already open document, migrates the persistent store to the new URL and invokes save: on the context.
- Save To: Not supported in Tiger.
- Revert: Reverts or resets the context. Objects will be loaded again from the persistent store just like the Open: case.

File package support (where potentially multiple persistent stores are inside a file wrapper) is left to subclasses where managing different stores can be done by hand through the coordinator.


NSApplication Support for the Enhanced Print Apple Event

A new Enhanced Print Apple event was defined by Mac OS 10.3 (http://developer.apple.com/technotes/tn2002/tn2082.html) but Cocoa did not support it properly. In Tiger mechanisms have been added to retrofit print event support to existing applications, but they do not work in all cases. To allow you to easily create non-NSDocument-based applications that handle Print Apple events reliably, a new NSApplication delegate has been added, and one deprecated:
- (NSApplicationPrintReply)application:(NSApplication *)application printFiles:(NSArray *)fileNames
withSettings:(NSDictionary *)printSettings showPrintPanels:(BOOL)showPrintPanels;
Given that the application has been asked to print a group of files, print them. printSettings is a dictionary containing NSPrintInfo-compatible print job attributes. Your application should add them to any NSPrintInfo used to print the files, typically by invoking [[thePrintInfo dictionary] addEntriesFromDictionary:printSettings]. showPrintPanels is a flag indicating whether or not a print panel should be presented for each file being printed. If it is NO, no print panels should be presented (but print progress panels should still be presented). See -[NSPrintOperation setShowsPrintPanel:] below. Implementations of this method must return one of the following:
typedef enum NSApplicationPrintReply {
NSPrintingCancelled = 0,
NSPrintingSuccess = 1,
NSPrintingFailure = 3,
NSPrintingReplyLater = 2
} NSApplicationPrintReply;
Return NSPrintingReplyLater if the result of printing cannot be returned immediately, if printing will cause the presentation of a sheet for instance. If your method returns NSPrintingReplyLater it must always invoke -[NSApplication replyToOpenOrPrint:] when the entire print operation has been completed, successfully or not.

This delegate method replaces -application:printFiles:, which is now deprecated. If your application delegate only implements -application:printFiles: it will still be invoked, and NSApplication will use private functionality to arrange for the print settings to take effect despite the fact that an implementation of -application:printFiles: can't possibly know about them.


NSPrintInfo Support for the Enhanced Print Apple Event

Support for attributes corresponding to fields in the Enhanced Print Apple event's "with properties" parameter has been added to NSPrintInfo:
NSString *NSPrintPagesAcross; // an NSNumber containing the number of logical pages to be placed across a physical sheet
NSString *NSPrintPagesDown; // an NSNumber containing the number of logical pages to be placed down a physical sheet
NSString *NSPrintTime; // an NSDate containing the time at which printing should begin
NSString *NSPrintDetailedErrorReporting; // an NSNumber containing a boolean value
NSString *NSPrintFaxNumber; // an NSString containing a fax number
NSString *NSPrintPrinterName; // an NSString containing the name of a printer
Bug: NSPrintTime has no effect in Mac OS 10.4.


NSPrintOperation Support for the Enhanced Print Apple Event

Because presentation of the print panel during handling of the Print event is optional, but the print progress panel should always be presented, new methods have been added to NSPrintOperation to give you individual control over the two kinds of panels:
- (void)setShowsPrintPanel:(BOOL)flag;
- (BOOL)showsPrintPanel;
- (void)setShowsProgressPanel:(BOOL)flag;
- (BOOL)showsProgressPanel;
These methods replace -setShowPanels: and -showPanels, which are now deprecated. The old methods function as they did in Mac OS 10.3, but the return value of -showPanels: is ambiguous (implementation-wise, it returns the same value as -showsPrintPanel).


New NSDocument Methods for the Enhanced Print Apple Event

A new Enhanced Print Apple event was defined by Mac OS 10.3 (<http://developer.apple.com/technotes/tn2002/tn2082.html>) but Cocoa did not support it properly. In Tiger mechanisms have been added to retrofit print event support to existing applications, but they do not work in all cases. To allow you to easily create document-based applications that handle Print Apple events properly, two new methods have been added to NSDocument, and methods have been deprecated:
- (void)printDocumentWithSettings:(NSDictionary *)printSettings showPrintPanel:(BOOL)showPrintPanel
delegate:(id)delegate didPrintSelector:(SEL)didPrintSelector contextInfo:(void *)contextInfo;
Print the document. If showing of the print panel is specified, present it first, and print only if the user OKs the panel. The NSPrintInfo attributes in the passed-in printSettings dictionary should be added to a copy of the document's print info, and the resulting print info should be used for the operation. When printing is completed or has been canceled, send the message selected by didPrintSelector to the delegate, with the contextInfo as the last argument. The method selected by didPrintSelector must have the same signature as:
- (void)document:(NSDocument *)document didPrint:(BOOL)didPrintSuccessfully contextInfo:(void *)contextInfo;
The default implementation of this method first makes sure that any editor registered using Cocoa Bindings' NSEditorRegistration informal protocol has committed its changes, then invokes [self printOperationWithSettings:printSettings error:&anError]. If nil is returned it presents the error to the user in a document-modal panel before messaging the delegate. Otherwise it invokes [thePrintOperation setShowsPrintPanel:showPrintPanel] then [self runModalPrintOperation:thePrintOperation delegate:delegate didRunSelector:didPrintSelector contextInfo:contextInfo]. Your are unlikely to need to override this method.

This method replaces -printShowingPrintPanel:, which is now deprecated. For backward binary compatibility the old method is still invoked when appropriate if it is overridden. When this is done Cocoa uses private functionality to arrange for 1) the print settings to take effect despite the fact that the override of -printShowingPrintPanel: can't possibly know about them, and 2) getting notified when the print operation has been completed, so it can message the delegate at the correct time. Correct messaging of the delegate is necessary for correct handling of the Print Apple event.
- (NSPrintOperation *)printOperationWithSettings:(NSDictionary *)printSettings error:(NSError **)outError;
Create a print operation that can be run to print the document's current contents, and return it if successful. If not successful, return nil after setting *outError to an NSError that encapsulates the reason why the print operation could not be created. The NSPrintInfo attributes in the passed-in printSettings dictionary should be added to a copy of the document's print info, and the resulting print info should be used for the operation. The default implementation of this method does nothing. You must override it to enable printing in your application.

-runModalPageLayoutWithPrintInfo: is now deprecated, because it can only present an application-modal panel, which is a poor user interface in this case. Use -runModalPageLayoutWithPrintInfo:delegate:didRunSelector:contextInfo: instead. -runModalPageLayoutWithPrintInfo: is never invoked from anywhere within Cocoa, as in Mac OS 10.3 and earlier.


NSView Page Header/Footer Printing API (Section added since WWDC)

Tiger adds API that makes it easier for a Cocoa application to include page headers and footers in its printed output. This feature is off by default, but can be enabled using NSPrintInfo's new NSPrintHeaderAndFooter attribute:
APPKIT_EXTERN NSString *NSPrintHeaderAndFooter;
AppKit also recognizes an identically-named user default, so this feature can be easily tested with an existing application executable by launching the application with the default set to YES.

For example:
MyApp.app/Contents/MacOS/MyApp -NSPrintHeaderAndFooter YES

When this feature is enabled, NSView's -drawPageBorderWithSize: method, which previously did nothing, prints a header and footer on each page. (Thus any override of -drawPageBorderWithSize: will need to invoke super's implementation if it wants to inherit this behavior.) The header and footer content are provided by two new NSView methods:
- (NSAttributedString *)pageHeader;
- (NSAttributedString *)pageFooter;
NSView's implementations of these methods provide a default header that includes the print job title (which typically is the same as the document or window title) and the date, and a default footer that includes the page number and page count. A printable view class can override one or both of these methods to substitute its own content in place of these defaults.

Each of these methods is invoked once per page during printing, offering implementors the chance to provide potentially page-specific header/footer content (including an appropriate page number, and perhaps offering different content or alignment for even vs. odd pages, for example). Implementors will typically consult NSPrintOperation's printInfo object to obtain data of interest to include in the header/footer text.

Note that the use of NSAttributedString as the return type for these methods provides for a great deal of power and flexibility. Content can appear both horizontally centered and at the page corners through use of left/center/right aligned tab stops, and images can be included as text attachments.

It is left up to the client application to expose this feature in its user interface, if desired. A simple checkbox in a print sheet accessory view, or the application's Preferences panel, would suffice. An application that provided for user customization the header/footer content could opt to go further.


NSView Drawing Redirection API (Section added since WWDC)

Tiger adds three new methods to NSView that enable an application to ask a view subtree to draw into a specified NSBitmapImageRep or NSGraphicsContext. This feature can be used to take a snapshot of the drawing done by a view and its descendants, either as a cache for computationally expensive view drawing, or for use in some subsequent graphics operation. It does not currently support capture of views that render to hardware-accelerated surfaces (i.e. NSOpenGLViews and NS/QTMovieViews), but otherwise works with all Quartz-based view drawing. The views to be drawn can, but need not, reside in a window. A client can request drawing of a view's entire content, or some rectangular subregion.

Clients of this API should begin by obtaining an NSBitmapImageRep of appropriate dimensions and color depth for capturing the desired view content. Such a bitmap can be obtained using the new NSView method:
- (NSBitmapImageRep *)bitmapImageRepForCachingDisplayInRect:(NSRect)rect;
A client wishing to capture only the parts of the receiver that are not clipped by ancestor views should pass the receiver's "visibleRect" as the NSRect parameter. It is also possible to snapshot parts of a view that are currently clipped (due to an enclosing NSScrollView, for example), by specifying a rectangle that is outside the receiver's visibleRect, but still within its bounds. The -bitmapImageRepForCachingDisplayInRect: method returns a new, autoreleased NSBitmapImageRep instance that is suitable for caching a copy of the specified view area.

Once a suitable target bitmap has been obtained, the client should initialize it as desired before asking the view subtree to draw into it. To initialize the bitmap to fully transparent, for example, one could use the following code:
    NSGraphicsContext *bitmapGraphicsContext = [NSGraphicsContext graphicsContextWithBitmapImageRep:cacheBitmapImageRep];
[NSGraphicsContext saveGraphicsState];
[NSGraphicsContext setCurrentContext:bitmapGraphicsContext];
[[NSColor clearColor] set];
NSRectFill(NSMakeRect(0, 0, [cacheBitmapImageRep size].width, [cacheBitmapImageRep size].height));
[NSGraphicsContext restoreGraphicsState];
The desired view subtree area can then be drawn into the bitmap using the new method:
- (void)cacheDisplayInRect:(NSRect)rect toBitmapImageRep:(NSBitmapImageRep *)bitmapImageRep;
The "rect" parameter should be of the same size as that passed to bitmapImageRepForCachingDisplayInRect:. This method creates an NSGraphicsContext for drawing into the NSBitmapImageRep, translates its coordinate system to place the requested rectangle at the origin, and then asks the view subtree to draw into the NSGraphicsContext using another new NSView method:
- (void)displayRectIgnoringOpacity:(NSRect)aRect inContext:(NSGraphicsContext *)context;
Clients that want to set up a different transform or other graphics context parameters may also send this message directly instead of cacheDisplayInRect:toBitmapImageRep:, but will otherwise usually find the latter approach more convenient.

NSView.h contains a declaration for an additional new method:
- (BOOL)lockFocusIfCanDrawInContext:(NSGraphicsContext *)context;
This is not yet used in Tiger, but may be made functional in the future.


NSView -registeredDraggedTypes API

Tiger adds a -registeredDraggedTypes accessor to NSView. This method can be used to query a view for the set of drag types for which the view has been registered via -registerForDraggedTypes. The elements in the returned array are in no particular order, but the array is guaranteed not to contain duplicate entries.


NSView -drawPageBorderWithSize: fix (Section added since WWDC)

On previous versions of Mac OS X, locking focus to draw in an override of NSView's -drawPageBorderWithSize: method applies a transform and clip that are unsuitable for drawing in the page border area. A workaround for this issue is discussed in Cocoa : Printing : Providing a Custom Pagination Scheme. On Tiger, the workaround is no longer necessary, but will cause no harm in applications that employ it.


NSView +new Behavior Change

For applications linked on or after Tiger, NSView's +new is equivalent to [[ViewClass alloc] init], which is more consistent with the usual meaning of +new than the previous behavior of invoking [[ViewClass alloc] initWithFrame:...].

Thus, if an NSView subclass overrides -init, +new will invoke the subclass's -init implementation, whereas it would have been bypassed in favor of -initWithFrame: before.


NSView Transform Fixes

NSView's -convertRect:fromView: and -convertRect:toView: methods have been fixed in Tiger. Previously, these methods could return a rect of insufficient width or height under some transformations.


NSApplication

In Tiger, we changed the behavior of NSApplication for some modal panels. It is now possible to hide an application while a modal panel is open. It is also possible to quit an application while the open panel is up.

We now show the menuBar earlier in application launch - right after sending the applicationWillFinishLaunching notification. If your application wants to hide the menuBar on launch, you should call +[NSMenu setMenuBarVisible:NO] during applicationWillFinishLaunching.

Applications will no longer be told to open an untitled document if launched as a login item or if launched as a service provider.

The following problems were fixed:

- an application delegate that implemented only application:openFiles: (and not application:openFile:) would not be able to open recent documents.

- NSWorkspaceWillPowerOffNotification was sent whenever an application received a 'quit' AppleEvent, whether from loginwindow, the dock, or an AppleScript. This notification is now only sent for logout, restart, or shutdown.

- drawers and NSStatusItems could prevent an application whose delegate returned YES from -applicationShouldTerminateAfterLastWindowClosed: from terminating when the last window was closed.


Dragging (Section updated since WWDC)

In Tiger, we fixed a problem where the offset passed to -[NSView dragImage:at:offset:event:pasteboard:source:slideBack:] was ignored when positioning the dragged image onscreen, but not ignored when passing the drag location to the source in draggedImage:endedAt:operation:. This offset is now universally ignored, because it no longer makes sense with the underlying implementation. This fix applies only to applications built on Tiger or later for compatibility reasons.

We added a method to the NSDraggingDestination informal protocol to allow dragging destinations to specify that they are not interested in periodic -draggingUpdated messages. On Panther and previous, the dragging code sends periodic -draggingUpdated messages to a destination even if there is no change to the drag (the mouse hasn't moved and modifier flags haven't changed), as documented. We have added a new method to allow dragging destinations to override this behavior.
@interface NSObject(NSDraggingDestination)
...
- (BOOL)wantsPeriodicDraggingUpdates;
...
@end
-wantsPeriodicDraggingUpdates will be sent to the dragging destination view or window if it responds. If the destination responds and returns NO, -draggingUpdated messages will be sent only when the mouse moves or a modifier flag changes. Otherwise, the default behavior will be to continue to send periodic dragging updated messages even if nothing is changing.

We added the ability to specify an HFS promise drag without using dragPromisedFilesOfTypes:fromRect:source:slideBack:event:. A dragging source may now add the NSFilesPromisePboardType to the pasteboard directly, and should call setPropertyList:forType: to write the array of fileTypes as the data for this type. The object passed in the source argument of dragImage:at:offset:event:pasteboard:source:slideBack: must implement namesOfPromisedFilesDroppedAtDestination: to provide the file names when the drag is dropped.

We fixed a bug where hidden views could be the target of a drag.


NSEvent (Section updated since WWDC)

In Tiger, we added a constant, NSDeviceIndependentModifierFlagsMask, to be used in a bitwise-and with -[NSEvent modifierFlags] to retrieve only the device independent modifer flags. This allows applications to mask off the device dependent modifierFlags, include event coalescing information. Eg. an application could detect if any device independent modifier flags are present in theEvent using:
    if (([theEvent modifierFlags] & NSDeviceIndependentMofidierFlagsMask) != 0) ...
We fixed a long standing bug where the event passed to NSApplication and NSWindow -discardEventsMatchingMask:beforeEvent: was ignored, and all events in the queue matching the mask were discarded. For applications built on Tiger or later, we now check event times against the event passed in, and discard only those events whose event time is earlier. For applications built on Panther or earlier, we continue to discard all events in the queue matching the mask.


NSScrollWheel events (Section added since WWDC)

In order to support finer-grained scrolling required by new devices, the NSScrollWheel event and the handling of NSScrollWheel events within NSScrollView has changed. For scrollWheel mice, the delta fields may now contain fractional components. These fractional values are made available to applications built on Tiger or later. Applications built on Tiger or later which do their own handling of the NSScrollWheel event need to be prepared to deal with fractional values, for example by rounding the scroll amount computed from the event to an integral value before scrolling. Applications built on Panther or earlier will receive integral values compatible with the values received on previous releases.

In addition, new devices may send the NSScrollWheel event much more frequently, in some cases with both deltaX and deltaY of 0. These scroll events contain device dependent scroll information which allow NSScrollView to do continuous scrolling, so should be passed to super if your subclass allows NSScrollView to do the scrolling. If your subclass is doing custom scrolling, you should be prepared to ignore NSScrollWheel events whose deltaX and deltaY are both 0. This change affects applications built on Tiger and on previous releases.


Tablet event support

In Panther, tablet drivers started generating native tablet events in addition to mouse events with embedded tablet data. In Tiger, we have added API to define the tablet event types, to provide accessors for tablet event data from native tablet events and mouse events with tablet data, and to allow tablet events to be sent through the responder chain.

Tablet drivers generate tablet events in two ways. In some cases (dual-puck tablet point events, "modern" proximity events), the driver generates pure tablet events. These event have been added to NSEvent.h:
typedef enum _NSEventType {        /* various types of events */
...
NSTabletPoint = 23,
NSTabletProximity = 24,
...
} NSEventType;
Along with the corresponding masks:
enum {                    /* masks for the types of events */
...
NSTabletPointMask = 1 << NSTabletPoint,
NSTabletProximityMask = 1 << NSTabletProximity,
...
};
In other cases (single-puck tablet point events, compatibility proximity events), the driver generates mouseDown/Up/Dragged/Moved events with additional tablet data. These events can be identified by their subtype. We have published the mouse event subtypes so applications can tell when an event has tablet information. These subtypes are declared in terms of constants defined in IOLLEvent.h:
enum {        /* event subtypes for mouse events */
NSMouseEventSubtype = NX_SUBTYPE_DEFAULT,
NSTabletPointEventSubtype = NX_SUBTYPE_TABLET_POINT,
NSTabletProximityEventSubtype = NX_SUBTYPE_TABLET_PROXIMITY
};
The NSPointerType enumeration declares the possible values returned by -pointerType. These values are declared in terms of constants that will be defined in IOLLEvent.h:
/* pointer types for NSTabletProximity events or mouse events with subtype NSTabletProximityEventSubtype*/
typedef enum {
NSUnknownPointingDevice = NX_TABLET_POINTER_UNKNOWN,
NSPenPointingDevice = NX_TABLET_POINTER_PEN,
NSCursorPointingDevice = NX_TABLET_POINTER_CURSOR,
    NSEraserPointingDevice = NX_TABLET_POINTER_ERASER
} NSPointingDeviceType;
The following enumeration declares possible values to be included in the bitwise-or returned by -buttonMask. These values are declared in terms of constants defined in IOLLEvent.h:
/* button masks for NSTabletPoint events or mouse events with subtype NSTabletPointEventSubtype */
enum {
    NSPenTipMask = NX_TABLET_BUTTON_PENTIPMASK,
    NSPenLowerSideMask = NX_TABLET_BUTTON_PENLOWERSIDEMASK,
    NSPenUpperSideMask = NX_TABLET_BUTTON_PENUPPERSIDEMASK
};
The -pressure and -subtype messages are now valid for new event types as described in the comments:
/* This message is valid for all mouse down/up/drag events */
/* This message is also valid for mouse events with subtype NSTabletPointEventSubtype and
for NSTabletPoint events on 10.4 or later */
- (float)pressure;
/* this message is valid for kit, system, and app-defined events */
/* this message is also valid for mouse down/up/drag/move events on 10.4 or later */
- (short)subtype;
In addition, we have added accessors for the fields of the tablet events:
/* this message is valid for mouse events with subtype NSTabletPointEventSubtype or
NSTabletProximityEventSubtype, and for NSTabletPoint and NSTabletProximity events */
- (unsigned int)deviceID; // system-assigned unique device ID
/* these messages are valid for mouse events with subtype NSTabletPointEventSubtype, and for NSTabletPoint events */
- (int)absoluteX; // absolute x coordinate in tablet space at full tablet resolution
- (int)absoluteY; // absolute y coordinate in tablet space at full tablet resolution
- (int)absoluteZ; // absolute z coordinate in tablet space at full tablet resolution
- (unsigned int)buttonMask; // mask indicating which buttons are pressed.
- (NSPoint)tilt; // range is -1 to 1 for both axes
- (float)rotation; // device rotation in degrees
- (float)tangentialPressure; // tangential pressure on the device; range is -1 to 1
- (id)vendorDefined;         // NSArray of 3 vendor defined shorts
/* these messages are valid for mouse events with subtype NSTabletProximityEventSubtype, and  for NSTabletProximity events */
- (unsigned int)vendorID; // vendor defined, typically USB vendor ID
- (unsigned int)tabletID; // vendor defined tablet ID
- (unsigned int)pointingDeviceID; // vendor defined ID of pointing device
- (unsigned int)systemTabletID; // system assigned unique tablet ID
- (unsigned int)vendorPointingDeviceType; // vendor defined pointing device type
- (unsigned int)pointingDeviceSerialNumber; // vendor defined serial number of pointing device
- (unsigned long long)uniqueID; // vendor defined unique ID
- (unsigned int)capabilityMask; // mask representing capabilities of device
- (NSPointingDeviceType)pointingDeviceType; // type of pointing device
- (BOOL)isEnteringProximity; // YES - entering; NO - leaving
Lastly, we have added NSResponder methods for the pure tablet event types:
@interface NSResponder : NSObject <NSCoding>
...
- (void)tabletPoint:(NSEvent *)theEvent;
- (void)tabletProximity:(NSEvent *)theEvent;
...
@end

NSWindow (Section updated since WWDC)

In Tiger, ColorSync has added the ability to update the ColorSync profile attached to a window context. On Panther and previous, the ColorSync profile was defined by the profile of the main display at window server initialization time (=login time) and was cached and used for all new window contexts. In other words, windows could not pick up an updated ColorSync profile until the user logged out and back in. Even new windows created after a ColorSync profile change were not affected by the change. In Tiger, we will maintain this behavior for windows that do not adopt the new API. The profile of the main display will continue to be cached and used for any new window context that does not indicate otherwise. Maintaining this compatibility is important for correctness in apps that are doing cached drawing, and desirable for performance reasons in less sophisticated apps.

We have exposed the new ColorSync support to windows that want to adopt it. Exposing the functionality implies updating the display profile attached to the window CGContextRef, and notifying the window when the display profile has changed.
@interface NSWindow : NSResponder
...
- (void)setDisplaysWhenScreenProfileChanges:(BOOL)flag;
- (BOOL)displaysWhenScreenProfileChanges;
...
@end
If a window returns YES for -displaysWhenScreenProfileChanges, AppKit will call CGWindowContextUpdateDisplayInfo for the window context then tell the window to display, under the following conditions:
- the majority of the window has moved to a different screen and the display profile for the current screen is different than that of the previous screen
- we receive a notification from color sync that the display profile has changed for the screen containing the majority of the window
- the window context is first created (although in this case the window would not need to be told to redisplay)

The default is NO.

We have also added a notification of when the display profile has changed, to be sent after AppKit has called CGWindowContextUpdateDisplayInfo and before the window is told to display, so that the window can update any offscreen caches:
APPKIT_EXTERN NSString *NSWindowDidChangeScreenProfileNotification;
The window delegate can automatically register for this notification by implementing a new delegate method:
@interface NSObject(NSWindowNotifications)
...
- (void)windowDidChangeScreenProfile:(NSNotification *)notification;
...
@end
Adding a child window using -addChildWindow:ordered: now causes the child window to be ordered onscreen in the correct relative location (above or below) if the receiver is onscreen.

We added support for a new window appearance where the background from the titlebar continues into the toolbar, making them appear unified. There is a new styleMask NSUnifiedTitleAndToolbarWindowMask to specify this window appearance.

The toolbar button is now optional:
- (void)setShowsToolbarButton:(BOOL)show;
- (BOOL)showsToolbarButton;

NSWindow -disableScreenUpdatesUntilFlush API (Section added since WWDC)

When a view that renders to a hardware surface (such as an OpenGL view) is placed in an NSScrollView or NSSplitView, there can be a noticeable flicker or lag when the scroll position or splitter position is moved. This happens because each move of the hardware surface takes effect immediately, before the remaining window content has had the chance to draw and flush.

To enable applications to eliminate this visual artifact, Tiger AppKit provides a new NSWindow message, -disableScreenUpdatesUntilFlush. This message asks a window to suspend screen updates until the window's updated content is subsequently flushed to the screen. This message can be sent from a view that is about to move its hardware surface, to insure that the hardware surface move and window redisplay will be visually synchronized. The window responds by immediately disabling screen updates via a call to NSDisableScreenUpdates(), and setting a flag that will cause it to call NSEnableScreenUpdates() later, when the window flushes. It is permissible to send this message to a given window more than once during a given window update cycle; the window will only suspend and re-enable updates once during that cycle.

A view class that renders to a hardware surface can send this message from an override of -renewGState (a method that is is invoked immediately before the view's surface is moved) to effectively defer compositing of the moved surface until the window has finished drawing and flushing its remaining content.
- (void)renewGState {
NSWindow *window = [self window];
if ([window respondsToSelector:@selector(disableScreenUpdatesUntilFlush)]) {
[window disableScreenUpdatesUntilFlush];
}
[super renewGState];
}
In the above example, a -respondsToSelector: check has been used to provide compatibility with previous system releases. On pre-Tiger systems, where NSWindow has no -disableScreenUpdatesUntilFlush method, the -renewGState override will have no effect.


Coalesced Updates (Section added since WWDC)

In Tiger the "coalesced updates" feature of the graphics subsystem improves drawing performance and eliminates visual tearing. However, it also causes applications which flush to the screen faster than 60 fps to stall while drawing. In order to maintain backward compatibility, there are compatibility checks in place where pre-Tiger applications which stall due to over-flushing are reverted back to Panther flushing behavior.

In order to guarantee best performance, applications should refrain from animating at rates above 60 fps. And as before, it's a good idea to use NSView's setNeedsDisplay: and related methods rather than the immediate display method whenever possible, since setNeedsDisplay: enables coalescing drawing updates from different parts of the window and reduces unnecessary flushing to the screen.

The Quartz Debug application provides debugging facilities that can help determine if an application is over-flushing.

We expect to publish a tech note or a Q&A on this topic.


NSWindow live resize optimization

In Tiger, we added content preservation for windows and views during live resize. Prior to this change, the top level view in a window marked itself as needing display in its entire bounds when the window resized. When the top level view was drawn, all subviews were drawn as well, so all views completely redrew during live resize. This isn't always necessary, since in some cases the content of the view is only changing in the newly exposed area. For example in a simple window with left to right orientation, the left side window titlebar buttons and other portions of the window titlebar do not need to redraw.

When this optimization is enabled, any view whose upper left corner moves relative to the upper left of the window is assumed to need complete redraw, because in general view content is position dependent (eg. when you move the splitView bar in the Mail viewer window, the content in the MessageTextView changes relative to the upper left corner of the window). However, any view whose upper left corner remains stationary with respect to the upper left of the window has the opportunity to preserve its content.

On Tiger, content preservation during live resize is enabled by default. However, we provide windows with a way to opt-out of this optimization. If there are no views that can take advantage of it, the window would pay an unneeded expense for preserving the old content.
@interface NSWindow : NSResponder
...
-(void)setPreservesContentDuringLiveResize:(BOOL)flag;
flag - YES to indicate that window should preserve content on live resize, NO otherwise.  Default is YES.
- (BOOL)preservesContentDuringLiveResize;
...
@end
Content preservation at the view level is disabled by default for compatibility with views that should redraw completely when resized. A view can adopt content preservation by implementing the following to return YES:
@interface NSView : NSResponder
...
- (BOOL)preservesContentDuringLiveResize;
...
@end
A view that returns YES for -preservesContentDuringLiveResize is responsible for invalidating its own dirty rects during live resize. Some views may find it convenient to implement setFrameSize: and do their own computation. Other views will want a way to get information about what has changed. We are adding a method that returns the rect representing the previously drawn content, and another method that returns rects representing the minimal area to dirty in the new bounds. These methods can be called during live resize, any time after setFrameSize: has been called on the view for the live resize operation (that is, any time after NSView's implementation of setFrameSize: has been called for that view) and before recursive display of the view hierarchy begins.
@interface NSView : NSResponder
...
/* the rect returned from -rectPreservedDuringLiveResize indicates the rect the view previously occupied,
in the coordinate system of the current bounds. This may be smaller or larger than the current bounds,
depending on whether the view grew or shrunk. The result of this method is an empty rect for a view that
returns NO from -preservesContentDuringLiveResize or a view in a window that returns NO from
-preservesContentDuringLiveResize
*/
-(NSRect)rectPreservedDuringLiveResize;
/* exposedRects - on return from this method, exposedRects contains a list of rects (at most 4)
indicating the parts of the view that are newly exposed. If the view decreased in both height and width,
this list will be empty. If the view increased in both height and width and stayed anchored in the
upper left corner (currently always true but may change in the future), this list will include a
vertical component and a horizontal component indicating the exposed "L".
count - on return, the number of rectangles in the exposedRects list. Can be 0.
The result of this method is the entire view bounds for a view that returns NO from
-preservesContentDuringLiveResize or a view in a window that returns NO from -preservesContentDuringLiveResize
*/
-(void)getRectsExposedDuringLiveResize:(NSRect[4])exposedRects count:(int *)count;
...
@end

NSWindow graphicsContext

A new API graphicsContext is added. It returns an NSGraphicsContext instance associated with the receiver for the calling thread.


New Behavior in -[NSWindow print:]

In Mac OS 10.0-10.3.x -[NSWindow print:] made a copy of [NSPrintInfo sharedPrintInfo], set some print parameters in the copy, and used the copy when creating a print operation. One of the print parameters that was set was orientation, to match the window's orientation. This was inappropriate, because it overrode whatever orientation the user had already set in the shared print info using a page setup panel. This has been fixed. -[NSWindow print:] no longer sets the printing orientation except, for backward binary compatibility, in applications linked against Mac OS 10.3 or earlier.


Window menu (Section added since WWDC)

We have added an "Arrange in Front" alternate menu item for the "Bring All to Front" menu item in the Window menu. Applications should not hard code the indices of items in the Window menu, as the addition of an alternate menu item, or any other Window menu changes, will change the indices of other menu items. We have limited this change to applications built on Tiger or later to preserve binary compatibility.


Metal window background

If you use the background color from a metal window in another window, it will not archive and unarchive correctly, and the unarchived color will lose its dynamic scaling capability. You can avoid this in a metal window by using -[NSWindow backgroundColor] or -[NSColor controlColor] to draw the metal background in custom controls.


NSWindow key view loop

Methods have been added to allow a window to automatically recalculate the key view loop after views have been added.
- (void)setAutorecalculatesKeyViewLoop:(BOOL)flag;
- (BOOL)autorecalculatesKeyViewLoop;
- (void)recalculateKeyViewLoop;
If the autorecalculatesKeyViewLoop is YES, then whenever a view is added to the window, the key view loop is dirtied and recalculated automatically when -[NSWindow selectKeyViewFollowingView] or -[NSWindow selectKeyViewPrecedingView] are called. If autorecalculatesKeyViewLoop is NO, then adding views will not dirty the key view loop and the loop will not be recalculated. You can always call explicitly recalculateKeyViewLoop to recalculate the loop and clear the dirty key view loop flag. The method is also called if the key view loop needs to be calculated when the window is first ordered in. The loop computed is the same as the default one if initialFirstResponder is not set. It is based on the geometric order of the views in the window.


Keyboard Navigation

A window's toolbar and drawers are now reachable using the keyboards <tab> navigating mechanism. The keyboard navigation system expects separate keyboard loops in the toolbar, window content, and each drawer content. For example, the keyboard loop within a window's contentView should be a complete loop (following nextKeyView/previousKeyView) which does not leave the confines of the -contentView. Keyboard navigation is able to reach other loops (for example, travel from the window content to the toolbar), via -nextValidKeyView/-previousValidKeyView. When appropriate, next/previousValidKeyView will return key views in other key loops.


NSAlert

In Tiger, we changed the instance variable names of NSAlert to be prefixed by underscores to be consistent with the AppKit naming conventions. This should not have any binary compatibility implications, but may require source changes in any NSAlert subclass that references instance variables by name. (Of course, since unless otherwise specified instance variables of Cocoa classes are private, applications should not be accessing instance variables.)


NSScreen (Section added since WWDC)

+[NSScreen screens] will no longer return multiple screens when mirroring is enabled.


Text

Text system's backing store string (as obtained by the string methods on NSTextView or NSTextStorage) now do better argument checking for applications linked on Tiger.

Turns out initWithRTF:documentAttributes:, initWithDocFormat:documentAttributes:, and initWithRTFD:documentAttributes: could cause a crash if the document failed to open and the message was sent to NSTextStorage. This has been fixed in Tiger and in 10.3.3, but in earlier 10.3.x releases the only reasonable workaround is to avoid these messages if the data being provided might fail to open. You can use the read method, or call these on NSAttributedString.


NSTypesetter

The set of API introduced as part of NSATSTypesetter in Mac OS X 10.3 Panther is moved to NSTypesetter. Applications can now implement a concrete subclass with a custom layout engine by overriding the layoutParagraphAtPoint: method.

NSSimpleHorizontalTypesetter is deprecated and its interface declaration is moved to a new header NSSimpleHorizontalTypesetter.h.

In addition to the interface migrated from NSATSTypesetter, NSTypesetter has additional new API:

paragraphCharacterRange and paragraphSeparatorCharacterRange return ranges in the character space corresponding to their glyph version counterparts. attributesForExtraLineFragment is for accessing style information that should be used for the extra line fragment. actionForControlCharacterAtIndex: is used for determining actions triggerd from a control character at index.

The new API -getLineFragmentRect:usedRect:emainingRect:forStartingGlyphAtIndex:proposedRect:lineSpacing:paragraphSpacingBefore:paragraphSpacingAfter: supercedes -lineFragmentRectForProposedRect:remainingRect: in NSATSTypesetter.


NSATSTypesetter

lineFragmentRectForProposedRect:remainingRect: is deprecated. Refer to a new API provided by the base NSTypesetter class getLineFragmentRect:usedRect:emainingRect:forStartingGlyphAtIndex:proposedRect:lineSpacing:paragraphSpacingBefore:paragraphSpacingAfter:.


NSTextView Multiple Selection (Section updated since WWDC)

The concept of selection in NSTextView has been extended in order to allow the selection of multiple discontiguous ranges at once. The two new primitives for selection are
- (void)setSelectedRanges:(NSArray *)ranges affinity:(NSSelectionAffinity)affinity stillSelecting:(BOOL)flag;
- (NSArray *)selectedRanges;
parallel to the existing setSelectedRange:affinity:stillSelecting and selectedRange methods. The existing single-range methods setSelectedRange:, setSelectedRange:affinity:stillSelecting, and selectedRange are now defined in terms of these new methods. The affinity and stillSelectingFlag arguments retain their current meanings unaltered. The ranges argument is required to be a non-nil, non-empty array of objects responding to - (NSRange)rangeValue. The selectedRanges method is guaranteed to return an array satisfying the same criteria, and in addition its elements will be sorted ascending by location, and discontiguous (i.e. if r1 appears before r2 then NSMaxRange(r1) < r2.location), and furthermore if there is more than one element then no element will have length zero.

There are several additional new NSTextView methods:
- (void)setSelectedRanges:(NSArray *)ranges;
- (NSArray *)rangesForUserTextChange;
- (NSArray *)rangesForUserCharacterAttributeChange;
- (NSArray *)rangesForUserParagraphAttributeChange;
- (BOOL)shouldChangeTextInRanges:(NSArray *)affectedRanges replacementStrings:(NSArray *)replacementStrings;
The first is a convenience method parallel to the existing setSelectedRange:. The next three are parallel to the existing rangeForUserTextChange, rangeForUserCharacterAttributeChange, and rangeForUserParagraphAttributeChange methods, obeying the same restrictions described above for selectedRanges, except that they will return nil in case the appropriate change is not permitted, in the situations in which the existing single-range methods now return (NSNotFound, 0). The last is similar to the existing shouldChangeTextInRange:replacementString:; the replacementStrings array should either be nil, or else contain one element for each range in affectedRanges.

The existing methods returning a single range will now return the first subrange where there is a multiple-range selection. This means that code that uses the existing single-range APIs will continue to operate, acting on the first selected subrange when there are multiple selections. This is in fact the appropriate behavior for many purposes, and is expected to remain a reasonable default. Most AppKit methods have been updated where appropriate to act on all of the subranges of a multiple selection, particularly methods that modify attributes.

There are two new NSTextView delegate methods:
- (NSArray *)textView:(NSTextView *)textView
willChangeSelectionFromCharacterRanges:(NSArray *)oldSelectedCharRanges
toCharacterRanges:(NSArray *)newSelectedCharRanges;
- (BOOL)textView:(NSTextView *)textView
shouldChangeTextInRanges:(NSArray *)affectedRanges
replacementStrings:(NSArray *)replacementStrings;
in which the arguments satisfy criteria like those of the return value of selectedRanges. In the first, the return value must satisfy criteria like those for the ranges argument to setSelectedRanges:affinity:stillSelecting:.

If a delegate implements the old delegate method
- (NSRange)textView:(NSTextView *)textView
willChangeSelectionFromCharacterRange:(NSRange)oldSelectedCharRange
toCharacterRange:(NSRange)newSelectedCharRange;
and not the new one, then multiple selection will effectively be disallowed; attempts to set the selected ranges will call the old delegate method with the first subrange, and afterwards only a single selected range will be set. If a delegate implements the new method, then the old one will be ignored.

If the delegate implements the old delegate method
- (BOOL)textView:(NSTextView *)textView
shouldChangeTextInRange:(NSRange)affectedCharRange
replacementString:(NSString *)replacementString;
then it will be called with an appropriate range and string. If a delegate implements the new method, then the old one will be ignored.

There are several means provided for users to make a multiple selection. First, command-selection can be used in a text view with the usual meaning--it selects new portions of the text, or unselects already selected portion. Second, option-selection can be used in a text view to make a rectangular selection; there is a distinctive cursor provided for this mode. A default is provided, NSProhibitMultipleTextSelectionByMouse, to control this behavior; if the default is set to YES, then command- and option-selection in text will not have their new special meanings, but will behave as they did in Panther. This mechanism allows the new means of selection to be turned off for applications in which they may not be desired.

In addition, two new NSFindPanelActions are provided, NSFindPanelSelectAll and NSFindPanelSelectAllInSelection, to allow selection of all instances of a particular find string; the standard find panel uses these if the control key is held down. Finally, the styles panel supports selection of all text having a particular style--this could be used, for example to select all text in a given font, then subsequently convert it to a different font, or to select all underlined text and subsequently italicize it.


Removal of Override of -attributedSubstringFromRange: in NSTextStorage Category

In Mac OS 10.0-10.3.x there was an override of -[NSAttributedString attributedSubstringFromRange:] in a private category of NSTextStorage. The override returned an instance of NSSubTextStorage, a private subclass of NSTextStorage (and therefore NSAttributedString) used by Cocoa's scripting subsystem. This NSSubTextStorage object responded to all NSAttributedString messages, but its value would change with the value of the "parent" NSAttributedString, which was not correct and caused several difficult-to-diagnose bugs. This override has been removed. NSTextStorages now return nonmutating NSAttributedStrings when sent the -attributedSubstringFromRange: message.


NSParagraphStyle

NSParagraphStyle features new methods hyphenationFactor and tighteningFactorForTruncation. Corresponding writer methods, setHyphenationFactor: and setTighteningFactorForTruncation: are added to NSMutableParagraphStyle.


NSParagraphStyle Header Level

NSParagraphStyle now defines a new attribute, the header level, an integer which should either be 0 or else in the range 1-6. This is currently used only for HTML import/export, defining whether a particular paragraph is a header or not and if so of what level. The relevant methods are
- (int)headerLevel;
on NSParagraphStyle and
- (void)setHeaderLevel:(int)level;
on NSMutableParagraphStyle.


Base writing direction

Accessor methods for the base writing direction, baseWritingDirection and setBaseWritingDirection:, have been added to NSCell, NSControl, and NSText classes.

Also, NSTextView and NSMutableAttributedString now have setBaseWritingDirection:range: API.


NSStringDrawing

New methods have been added to NSString and NSAttributedString categories defined in NSStringDrawing.h. drawWithRect:options: and boundingRectWithSize:options: offer more precise string rendering/sizing functionality.


NSFont and NSFontDescriptor

The NSFont and NSFontDescriptor classes have been restructured. NSFontDescriptor is now promoted to be the primary font reference in AppKit replacing Postscript names. Also, new functionalities such as font matching, font substitution, and font cascading are built into the NSFontDescriptor class.


NSGlyphInfo (Section added since WWDC)

The NSGlyphInfo class now conforms to the NSCopying protocol.


NSTextView Typing Attributes Delegate Method

In addition to the existing notification, NSTextView now has a new delegate method allowing the delegate to intervene to allow, prevent, or modify changes to typing attributes:
- (NSDictionary *)textView:(NSTextView *)textView
shouldChangeTypingAttributes:(NSDictionary *)oldTypingAttributes
toAttributes:(NSDictionary *)newTypingAttributes;

NSTextView undo coalescing (Section added since WWDC)

NSTextView now exposes a new method to control undo coalescing:
- (void)breakUndoCoalescing;
This is useful for instance as a way to get an app to prevent successive typing operations before and after a save from being coalesced into a single undoable item by the text view.


New Responder Methods

NSResponder now defines two new action methods that are implemented in NSTextView. The first is intended to insert a line break (as distinguished from a paragraph break). The NSTextView implementation inserts an NSLineSeparatorCharacter. The second is intended to insert a container break (typically a page break). The NSTextView implementation inserts an NSFormFeedCharacter.
- (void)insertLineBreak:(id)sender;
- (void)insertContainerBreak:(id)sender;

Text Tables (Section updated since WWDC)

The Cocoa text system now supports tables. The basic object involved is a new class, NSTextBlock, which represents a block of text that is to be laid out in a sub-region of the text container. The most important subclass is NSTextTableBlock, which represents a block of text that appears as a cell in a table. The table itself is represented by a separate class, NSTextTable, which is referenced by all of its NSTextTableBlocks and which controls their sizing and positioning.

Text blocks appear as attributes on paragraphs, as part of the paragraph style. An NSParagraphStyle now may have an array of text blocks, representing the nested blocks containing the paragraph, in order from outermost to innermost. For example, if block1 contains four paragraphs, the middle two of which are also in the inner block2, then the text blocks array for the first and fourth paragraphs will be (block1), while the text blocks array for the second and third paragraphs will be (block1, block2).

The methods implementing this are
- (NSArray *)textBlocks
on NSParagraphStyle, and
- (void)setTextBlocks:(NSArray *)array
on NSMutableParagraphStyle.

In addition, there are convenience methods on NSAttributedString for determining the range covered by a block or a table (or (NSNotFound, 0) if the given location is not in the specified block or table):
- (NSRange)rangeOfTextBlock:(NSTextBlock *)block atIndex:(unsigned)location;
- (NSRange)rangeOfTextTable:(NSTextTable *)table atIndex:(unsigned)location;
During layout, the typesetter proposes a large rect within which a particular block should fit. For the outermost block, this will be determined by the text container; for inner blocks, it will be determined by the containing block. The block object then decides what subrect of this it should actually take up. There are actually two rects that are determined: first, the layout rect, within which text in the block is to be laid out; second, the bounds rect, which also contains space for padding, borders, border decoration, margins, and so forth. The layout rect is determined immediately before the first glyph in a particular block is laid out, because it is needed for all subsequent layout of text in the block. It will often be quite tall, because at this point the height of the text laid out in the block has not yet been determined. The bounds rect is determined immediately after the last glyph in the block has been laid out, and it is based on the actual used rect for the text within the block.

The methods on NSTextBlock that are called by the typesetter are
- (NSRect)rectForLayoutAtPoint:(NSPoint)startingPoint inRect:(NSRect)rect
textContainer:(NSTextContainer *)textContainer characterRange:(NSRange)charRange;
- (NSRect)boundsRectForContentRect:(NSRect)contentRect inRect:(NSRect)rect
textContainer:(NSTextContainer *)textContainer characterRange:(NSRange)charRange;
An NSTextTableBlock will call upon its NSTextTable to perform these calculations, using its methods
- (NSRect)rectForBlock:(NSTextTableBlock *)block layoutAtPoint:(NSPoint)startingPoint inRect:(NSRect)rect
textContainer:(NSTextContainer *)textContainer characterRange:(NSRange)charRange;
- (NSRect)boundsRectForBlock:(NSTextTableBlock *)block contentRect:(NSRect)contentRect inRect:(NSRect)rect
textContainer:(NSTextContainer *)textContainer characterRange:(NSRange)charRange;
The typesetter stores the results of these methods in the layout manager. The new NSLayoutManager methods are:
- (void)setLayoutRect:(NSRect)rect forTextBlock:(NSTextBlock *)block glyphRange:(NSRange)glyphRange;
- (void)setBoundsRect:(NSRect)rect forTextBlock:(NSTextBlock *)block glyphRange:(NSRange)glyphRange;
- (NSRect)layoutRectForTextBlock:(NSTextBlock *)block glyphRange:(NSRange)glyphRange;
- (NSRect)boundsRectForTextBlock:(NSTextBlock *)block glyphRange:(NSRange)glyphRange;
- (NSRect)layoutRectForTextBlock:(NSTextBlock *)block atIndex:(unsigned)glyphIndex effectiveRange:(NSRangePointer)effectiveGlyphRange;
- (NSRect)boundsRectForTextBlock:(NSTextBlock *)block atIndex:(unsigned)glyphIndex effectiveRange:(NSRangePointer)effectiveGlyphRange;
- (NSRect)lineFragmentRectForGlyphAtIndex:(unsigned)glyphIndex effectiveRange:(NSRangePointer)effectiveGlyphRange
withoutAdditionalLayout:(BOOL)flag;
- (NSRect)lineFragmentUsedRectForGlyphAtIndex:(unsigned)glyphIndex effectiveRange:(NSRangePointer)effectiveGlyphRange
withoutAdditionalLayout:(BOOL)flag;
- (NSTextContainer *)textContainerForGlyphAtIndex:(unsigned)glyphIndex effectiveRange:(NSRangePointer)effectiveGlyphRange
withoutAdditionalLayout:(BOOL)flag;
The first two methods are used by the typesetter to store the information obtained from text blocks. The others are used during layout when it is necessary to determine what space has been taken up by previously laid blocks. The last three are variants of existing methods, that have the option of not causing additional layout; when they are called during layout, they must be called in such a way as not to force further layout so as to avoid an infinite recursion. For the same reason, the ...RectForTextBlock methods cause glyph generation but not layout; if no rect has been set, they return NSZeroRect. The layout rect should be set immediately before the first glyph in the block is laid out; the bounds rect should be set immediately after the last glyph in the block has been laid out. Under some circumstances, the bounds rect may be adjusted subsequently, as additional blocks in the same table are laid out.

At display time, the text is drawn as usual, but the text block is called upon to draw any background or border decoration while glyph backgrounds are being drawn, using the following method:
- (void)drawBackgroundWithFrame:(NSRect)frameRect inView:(NSView *)controlView
characterRange:(NSRange)charRange layoutManager:(NSLayoutManager *)layoutManager;
and again NSTextTableBlocks call upon their NSTextTable for this using its method:
- (void)drawBackgroundForBlock:(NSTextTableBlock *)block withFrame:(NSRect)frameRect
inView:(NSView *)controlView characterRange:(NSRange)charRange
layoutManager:(NSLayoutManager *)layoutManager;
The sizing and positioning model for text blocks involves a number of dimensions for each block, each of which may either have an absolute value in points or else be expressed as a percentage of the containing block. These dimensions include width, height, minimum and maximum width and height, and margin, border, and padding widths for each of the four sides. The default in each case will be 0, meaning no margin/border/padding and the natural width and height. Certain portions of the block will have their own colors, the default being nil for no color.
- (void)setValue:(float)val type:(NSTextBlockValueType)type forDimension:(NSTextBlockDimension)dimension;
- (float)valueForDimension:(NSTextBlockDimension)dimension;
- (NSTextBlockValueType)valueTypeForDimension:(NSTextBlockDimension)dimension;
- (void)setWidth:(float)val type:(NSTextBlockValueType)type forLayer:(NSTextBlockLayer)layer edge:(NSRectEdge)edge;
- (void)setWidth:(float)val type:(NSTextBlockValueType)type forLayer:(NSTextBlockLayer)layer; // Convenience method
- (float)widthForLayer:(NSTextBlockLayer)layer edge:(NSRectEdge)edge;
- (NSTextBlockValueType)widthValueTypeForLayer:(NSTextBlockLayer)layer edge:(NSRectEdge)edge;
- (void)setBackgroundColor:(NSColor *)color;
- (NSColor *)backgroundColor;
- (void)setBorderColor:(NSColor *)color forEdge:(NSRectEdge)edge;
- (void)setBorderColor:(NSColor *)color; // Convenience method sets all edges at once
- (NSColor *)borderColorForEdge:(NSRectEdge)edge;
NSTextTableBlock and NSTextTable instances have additional methods specific to table cells and to tables. For NSTextTableBlock:
- (id)initWithTable:(NSTextTable *)table startingRow:(int)row rowSpan:(int)rowSpan
startingColumn:(int)col columnSpan:(int)colSpan; /* Designated initializer */
- (NSTextTable *)table;
- (int)startingRow;
- (int)rowSpan;
- (int)startingColumn;
- (int)columnSpan;
For NSTextTable:
- (unsigned)numberOfColumns;
- (void)setNumberOfColumns:(unsigned)numCols;
- (NSTextTableLayoutAlgorithm)layoutAlgorithm;
- (void)setLayoutAlgorithm:(NSTextTableLayoutAlgorithm)algorithm;
- (BOOL)collapsesBorders;
- (void)setCollapsesBorders:(BOOL)flag;
- (BOOL)hidesEmptyCells;
- (void)setHidesEmptyCells:(BOOL)flag;

Text Lists

The Cocoa text system now supports lists. The basic object involved is a new class, NSTextList, which represents a section of text that forms a single list. The visible elements of the list, including list markers, will still appear in the text as they do for lists created by hand today. The list object, however, will allow the list to be recognized as such by the text system, so that markers and spacing can be automatically created for the user, and so that lists can be properly noted when saving in various rich text formats.

Text lists appear as attributes on paragraphs, as part of the paragraph style. An NSParagraphStyle now may have an array of text lists, representing the nested lists containing the paragraph, in order from outermost to innermost. For example, if list1 contains four paragraphs, the middle two of which are also in the inner list2, then the text lists array for the first and fourth paragraphs will be (list1), while the text lists array for the second and third paragraphs will be (list1, list2).

The methods implementing this are
- (NSArray *)textLists
on NSParagraphStyle, and
- (void)setTextLists:(NSArray *)array
on NSMutableParagraphStyle.

In addition, there are convenience methods on NSAttributedString for determining the range covered by a list and the ordinal position within a list of a particular item:
- (NSRange)rangeOfTextList:(NSTextList *)list atIndex:(unsigned)location;
- (int)itemNumberInTextList:(NSTextList *)list atIndex:(unsigned)location;
The NSTextList object itself describes the format of lists markers:
- (id)initWithMarkerFormat:(NSString *)format options:(unsigned)mask;
- (NSString *)markerFormat;
- (unsigned)listOptions;
- (NSString *)markerForItemNumber:(int)itemNum;
Here "marker" refers to the computed value for a specific ordinal position in the list, and "marker format" refers to a generic string used to specify the format for all markers in the list. The marker format is interpreted as a constant string, except for a numbering specifier, which will take the form "{<keyword>}". The currently supported values for <keyword> include decimal, lower-roman, upper-roman, lower-alpha, and upper-alpha. Thus "({decimal})" would be the format for a list number (1), (2), (3)... The only option value currently defined is NSTextListPrependEnclosingMarker, signaling that a nested list should include the marker for its enclosing super-list before its own marker.


Text Panels (Section updated since WWDC)

NSTextView now defines several action methods that are intended to bring forward panels to allow the user to manipulate paragraph spacing, links, lists, and tables in the text. TextEdit now has a menu item corresponding to each of these action methods:
- (void)orderFrontSpacingPanel:(id)sender;
- (void)orderFrontLinkPanel:(id)sender;
- (void)orderFrontListPanel:(id)sender;
- (void)orderFrontTablePanel:(id)sender;
There are now several means provided for users to add and manipulate links in text. Links can be created, manipulated, or removed using the link panel; they can also be dragged and dropped or copied and pasted to or from other applications. In addition, if a link is already present in the text, then control-clicking on the link will bring up a contextual menu with several options related to the link.

There are also several means to manipulate lists. There is a popup in the ruler that allows the selection of most basic list styles, and gives access to the list panel, which allows more general configuration of the content of list markers. The positioning of list markers and text is controlled by tab stops, which can be manipulated as usual, and the attributes of marker text may also be manipulated like those of any other text.

There are also several means to manipulate tables. The table panel can be used to add or remove rows and columns, to nest lists, and to join or split cells, as well as to manipulate border colors and sizes and background colors. Cell sizes can be manipulated directly by dragging on cell borders.


Text Import/Export (Section updated since WWDC)

The Cocoa text system can now import the following formats: plain text, RTF, RTFD, SimpleText, doc format, WordML, HTML, and WebArchive. It can now export all of these except for SimpleText. Instead of adding new methods for each new format, NSAttributedString and NSMutableAttributedString now have general-purpose methods that allow the format to be specified as a parameter. The existing methods remain as conveniences.

The new methods on NSAttributedString are:
- (id)initWithURL:(NSURL *)url options:(NSDictionary *)options documentAttributes:(NSDictionary **)dict error:(NSError **)error;
- (id)initWithData:(NSData *)data options:(NSDictionary *)options documentAttributes:(NSDictionary **)dict error:(NSError **)error;
- (NSData *)dataFromRange:(NSRange)range documentAttributes:(NSDictionary *)dict error:(NSError **)error;
- (NSFileWrapper *)fileWrapperFromRange:(NSRange)range documentAttributes:(NSDictionary *)dict error:(NSError **)error;
The first two methods are similar to the existing methods, but with the addition of an error parameter. The last two methods likewise add an error parameter, but in addition they require that the document type be specified in the document attributes dictionary. The last method returns a directory file wrapper if appropriate for the document type, otherwise a regular file wrapper.

The new methods on NSMutableAttributedString are:
- (BOOL)readFromURL:(NSURL *)url options:(NSDictionary *)opts documentAttributes:(NSDictionary **)dict error:(NSError **)error;
- (BOOL)readFromData:(NSData *)data options:(NSDictionary *)opts documentAttributes:(NSDictionary **)dict error:(NSError **)error;
which again are similar to existing methods but with the addition of an error parameter.

There are a number of new constants used in text import/export. There is a new document type
NSString *NSWebArchiveTextDocumentType;
for the WebKit WebArchive type; the actual format used is the data representation of a WebArchive.

Constants have been defined for all of the existing document attributes and options keys; the values are still specified for existing keys for backward compatibility with previous system versions. (To use them in Panther systems, use the actual string value of the identifier, where provided in the comments.) In addition, some new keys have been added (see below) and some have slightly different usages. NSCharacterEncodingDocumentAttribute is now used for both import and export of plain text documents. NSCocoaVersionDocumentAttribute still returns an NSNumber, but now it may have a floating-point value; for Tiger and later, this value will be the NSAppKitVersionNumber for the AppKit version that created the file. Previous values should be interpreted as follows: values less than 100 are pre-Mac OS X; 100 is Mac OS X 10.0 and 10.1; 102 is Mac OS X 10.2 and 10.3.

Various document attributes (author, subject, etc) can now be read and written in rich text files. Keywords for this have been defined in AppKit/NSAttributedString.h:
NSString *NSTitleDocumentAttribute;
NSString *NSCompanyDocumentAttribute;
NSString *NSSubjectDocumentAttribute;
NSString *NSAuthorDocumentAttribute;
NSString *NSKeywordsDocumentAttribute;
NSString *NSCommentDocumentAttribute;
NSString *NSEditorDocumentAttribute;
NSString *NSCreationTimeDocumentAttribute;
NSString *NSCopyrightDocumentAttribute;
TextEdit's "Document Properties" panel demonstrates the use of some of these keywords.


HTML Import/Export (Section updated since WWDC)

The Cocoa text system now imports and exports HTML. HTML import has been completely revised to use WebKit in all cases, and to make use of the new text table and list support. For Tiger, the @"UseWebKit" document option will no longer be relevant, and the NSTimeoutDocumentOption, NSWebPreferencesDocumentOption, and NSWebResourceLoadDelegateDocumentOption will always be available.

There is now an additional document option,
NSString *NSTextSizeMultiplierDocumentOption;
which specifies a scale factor for font sizes, corresponding to WebView's textSizeMultiplier, the same value that is exposed in Safari through the "Make Text Bigger/Smaller" menu and toolbar items.

The NSCharacterEncodingDocumentAttribute is now available for use in HTML export. If it is not specified, the default encoding for HTML export will be UTF-8. Characters not directly representable in the specified encoding will be represented by character references--usually numeric character references, but character entity references may be used in certain special cases. (At present some encodings may not be fully supported.)

The type of HTML generated is controlled by a new document attribute,
NSString *NSExcludedElementsDocumentAttribute;
This should be an NSArray containing strings (case-insensitive) that are names of HTML elements, plus several additional values: DOCTYPE (representing a doctype declaration) and XML (representing an XML declaration), and certain Apple-specific values described below. The elements contained in this list are those that will not be used in HTML generation; the text system will make use of any other HTML elements as it sees fit. By default, if no list is specified, the excluded elements will be those that are deprecated in HTML 4--namely APPLET, BASEFONT, CENTER, DIR, FONT, ISINDEX, MENU, S, STRIKE, and U--plus XML. When XML is on the excluded list, HTML forms will be used where there is a distinction; when it is removed from the list, XHTML forms will be used.

Clients specifying a list will have considerable control over the HTML generated, for example:

- Remove U from this list, and U will be used for underlined text (and the doctype will no longer be strict).
- Remove XML from this list, and an XML declaration will be generated, and XHTML forms will be used.
- Add STYLE to this list, and styles will be inlined rather than placed in the head.
- Remove FONT from this list, and FONT tags will be generated.
- Add B, I, SUB, and SUPER to this list, and CSS will be used for all styling.
- Conversely, add SPAN to this list, and no CSS at all will be used.
- Add A to this list, and all links will be suppressed.
- Add IMG and OBJECT to this list, and all attachments will be stripped.
- Add DOCTYPE to this list, and no doctype will be generated.
- Add META to this list, and all meta tags will be suppressed.
- Add HEAD to this list, and all head information will be suppressed (and styles will be inlined).
- Add BODY to this list, and the body tag will be omitted (but the body will still be generated).
- Add DOCTYPE, HTML, HEAD, and BODY to this list, and the result will be a bare HTML snippet (with styles inlined).
- Add DOCTYPE and every HTML tag except B and I, and the result will be a bare HTML snippet using only B and I.

The doctype generated depends on the list of elements. If XML is on the excluded list, then an HTML doctype will be used; otherwise an XHTML will be used. If any of the HTML 4 deprecated elements is not on the list, or if P is on the list, then a transitional doctype will be used; otherwise a strict doctype will be used. However, in all cases a doctype will be used only if the generated HTML actually conforms to it (for example, all of the relevant doctypes require a TITLE).

There are two Apple-specific values that may be added to the excluded elements array: Apple-converted-space and Apple-converted-tab. If these are absent from the array, then HTML export will add SPAN elements with these class names as a mechanism to preserve certain types of whitespace (tabs and multiple spaces) that otherwise have no faithful representation in HTML. If these are present in the array, then the generated HTML will not contain these somewhat unwieldy SPAN elements. There is a also a third recognized value, Apple-interchange-newline, but its use is not currently enabled. In the case of TextEdit, the presence of these values is controlled by the "Preserve white space" checkbox in the HTML portion of the open and save preferences pane.

The format of the HTML generated is also controlled by a new document attribute,
NSString *NSPrefixSpacesDocumentAttribute;
This should be an NSNumber containing an integer (default 0) representing the number of spaces per level by which certain nested HTML elements (notably elements involved in representing lists and tables) should be indented from the start of the line. This automatic indentation makes the resulting HTML more readable.


RTF

Handling of \expnd was fixed to treat the argument as quarter-points rather than half-points. (Note that in practice this bug didn't have any impact as we always follow \expnd with \expndtw, which correctly specifies the value out in twips.)

RTF files can now handle additional fractional sizes. (RTF spec allows only half-point precision.)

"No kerning" is now preserved in RTF files; it was not being written out correctly.


Command-Line Tool (Section added since WWDC)

There is now a tool, /usr/bin/textutil, that allows command-line access to the import/export facilities of the Cocoa text system. It can be used for inspecting properties of files, for altering attributes, and for conversion between any of the types of files that the text system supports. Examples might include: determining the format and metadata attributes of a file; adding or changing metadata such as author or title; converting between HTML and RTF; extracting the plain text from rich text documents; or converting plain text from one encoding to another. For more information, see "man 1 textutil".


NSFontPanel modes

We added the following modes to NSFontPanel to allow disabling font effects using validModesForFontPanel. However these are actually not yet implemented:
NSFontPanelUnderlineEffectModeMask      = 1<<8,
NSFontPanelStrikethroughEffectModeMask = 1<<9,
NSFontPanelTextColorEffectModeMask = 1<<10,
NSFontPanelDocumentColorEffectModeMask = 1<<11,
NSFontPanelShadowEffectModeMask = 1<<12,
NSFontPanelAllEffectsModeMask = 0XFFF00

Font Effects Color Changes (Section added since WWDC)

In Panther, the font effects portion of the font panel used a private mechanism to handle color changes (foreground color, underline color, strikethrough color, and document background color). In Tiger, it uses the standard changeAttributes:/convertAttributes: mechanism for foreground color, underline color, and strikethrough color, and the standard changeDocumentBackgroundColor: method for document background color. This makes it easier for custom views to respond to these color changes. The previous private mechanism will still be supported, for those views that may have implemented it based on the Panther implementation, but changeAttributes:/convertAttributes: is recommended for future use.


NSLayoutManager Screen Font Changes (Section added since WWDC)

In Panther, a layout manager would not use screen fonts if any text view associated with it was scaled or rotated, regardless of the setting of usesScreenFonts. In Tiger, a layout manager will use screen fonts if usesScreenFonts is set, regardless of the state of text views associated with it. The previous behavior remains in effect for applications linked on Panther or previous. Applications linked on Tiger or beyond will have to manually call setUsesScreenFonts: on their layout managers if they wish the use of screen fonts to change.


NSLayoutManager Glyph Generator

NSLayoutManager now has methods for directly setting and getting its glyph generator:
- (NSGlyphGenerator *)glyphGenerator;
- (void)setGlyphGenerator:(NSGlyphGenerator *)glyphGenerator;

NSSpellChecker Language Argument (Section added since WWDC)

Documentation has stated that the language argument to
- (NSRange)checkSpellingOfString:(NSString *)stringToCheck startingAt:(int)startingOffset
language:(NSString *)language wrap:(BOOL)wrapFlag inSpellDocumentWithTag:(int)tag wordCount:(int *)wordCount;
should be the empty string to specify that the user's currently selected spellchecker should be used. Actually, nil should be used instead; using the empty string would give inconsistent results on pre-Tiger system versions. For Tiger, the empty string will be handled as nil, but nil is still preferred. The same holds for the similar methods
- (int)countWordsInString:(NSString *)stringToCount language:(NSString *)language;
- (NSArray *)completionsForPartialWordRange:(NSRange)range inString:(NSString *)string
language:(NSString *)language inSpellDocumentWithTag:(int)tag;

NSFileWrapper Changes (Section added since WWDC)

- (BOOL)writeToFile:(NSString *)path atomically:(BOOL)atomicFlag updateFilenames:(BOOL)updateFilenamesFlag;
This method was changed to be more efficient when overwriting existing directories. The change in behavior is that it tries to avoid creating new copies of any files which haven't changed.


NSToolbar (Section updated since WWDC)

NSToolbarItem menuFormRepresentation are now only validated when the toolbar is in label only mode. This is a performance win since these menuFormRepresentations are only used when the toolbar is in label only mode.

A bug was discovered in Panther that affected layout of flexibly sized "view" items when in "Icon & Text" mode. In this case, the view portion of a toolbar item was much smaller than the space which was available to it. In essence, these items looked like they had too much empty space on the right and left side. They looked much farther away from adjacent items than desired (besides the fact that the view portion was smaller than it should be). In Panther, the view portion should never have excess spacing on the right and left unless the extent of the toolbar item and its label is larger than the item's maximum specified view size.

NSToolbar now indicates the selection status of items even if they are in the overflow menu. Prior to Tiger, items in the overflow menu did not indicate selection status. Selected items are indicated using the standard menu check mark.

NSToolbarItem's with valid actions and nil targets now work much better. Normally the receiver of a nil-targeted action is found by traversing the responder chain to find a responder that implements the action method. The traversal starts with the 'firstResponder' in the keyWindow. For applications linked on Tiger or later, toolbar item's now start their traversal with the firstResponder of toolbar item's window even if it is not key.

To understand why the old behavior is a problem, imagine the following: You have a nil-targeted "save" item whose action is saveContentsOfWindow:. There are 2 windows "A" and "B" are open with A being the key window. Each window implements saveContentsOfWindow:. Prior to Tiger, validation of window B's "save" item, would always go through the A's validation code. Further, if you cmd-clicked on B's "save" item (ie. perform the click without changing the key window), the action would be executed by A.

NSToolbar validates its toolbar items once before they are shown so that it is animating with up-to-date state.

A NSToolbarItem's menuFormRepresentation that is a submenu can now have an target/action associated with the top-level item. Such items behave like pulldown menu's whose top level item is clickable like a button. If the user mouses up before the pulldown is shown, the top-level item's action is sent. The pulldown menu is shown after a short delay, or if the user moves the mouse. The action methods 'sender' argument will be the top-level menu item. This new behavior is enabled for applications linked on Tiger and later. .

The resizing behavior of NSToolbarFlexibleSpaceItemIdentifier items has changed slightly. The purpose of a flexible spacer is two-fold. First it is used by users that want to right align certain items. Second, it is use to create visual separation. Flexible spacer items used to share an equal amount of the available space with other resizable items. Unfortunately, this steals valuable space from the items with actual content. To address this, flexible spacers no longer resize with an equal weighting.

NSToolbar's layout of resizable items has been improved. For applications linked on Panther or earlier, there is a bug in the layout of resizable items in icon and label mode. Often items that should have been the same size were different in size. In particular, if two items have the same minSize, when they are both wider than their label, yet smaller then their maxSize, they should be the same size. This bug has been fixed for applications linked on or after Tiger.

Prior to Tiger, changing the label of a resizable item could sometimes cause the item to resize on the screen when it was unnecessary to resize. This bug has been fixed for applications linked on or after Tiger.

Prior to Tiger, changing the label of a resizable item could sometimes cause the item to resize on the screen when it was unnecessary to resize. This bug has been fixed for applications linked on or after Tiger.

Layout changes - NSToolbar's margins have changed slightly.

Margins in aqua windows: The inset of the first and last item have changed, but the sum of those two values is the same as in Panther. However, the inter item spacing has changed by 1 pixel per item. This results in a bit more space for the layout algorithm, resulting in slightly larger flexibly sized items.

Margins in metal windows: The layout has the same changes that the aqua windows have, plus a small vertical margin change. Metal windows are now a vertically shorter, with margins that now match Safari and Finder. As a result, metal windows with toolbars will be a few pixels shorter for the same content size.

Drawing the baseline separator: For applications that want their toolbar to look more like the Finder and Safari, NSToolbar allows you to hide the baseline it draws between itself and the main window contents. Developers can also use this API to hide the base line so that they can draw their own custom looking separator. To turn on/off baseline drawing, call the following methods before you attach your toolbar to its window:
- (void)setShowsBaselineSeparator:(BOOL)flag;
- (BOOL)showsBaselineSeparator;

NSToolbarItem

Autovalidation

NSToolbar relies on window update to drive its auto-validation mechanism to enable/disable NSToolbarItems. Unfortunately, window update may not happen at the exact moment a developer needs to update their UI. Also, window update happens very frequently, and can cause performance problems for validators that need to do a lot of work. Therefore, we now provide a way to turn off the default auto validation on a per-item basis.
/* By default NSToolbar automatically invokes its items validate method on a regular basis.
To be in complete control of when the -validate method is invoked, you can disable automatic validation
on a per-item basis. In particular, if your validation code is slow, you may want to do this for performance reasons.
*/
- (void)setAutovalidates:(BOOL)autovalidates;
- (BOOL)autovalidates;
Avoiding Overflow

Some applications would like to suggest that certain toolbar items always be visible, never falling into the overflow menu. For instance, in Safari, the URL field is very important, and should generally always be visible (and not in the overflow menu). Users may find it very useful to define this sort of thing as well. For instance, In Xcode, I might want to suggest that the "build styles" popup always be visible. To accomplish this, we added the following API.
enum {
// The default visibility priority value. By default, all items have this priority
NSToolbarItemVisibilityPriorityStandard = 0,
    // A good value to use for items which should be first to fall into the overflow menu
NSToolbarItemVisibilityPriorityLow = -1000,
    // A good value to use for items you want to stay visible, allowing users to still have highest priority
NSToolbarItemVisibilityPriorityHigh = 1000,
    // Value assigned to an item the user wants to "keep visible". You should only use values less than this
NSToolbarItemVisibilityPriorityUser = 2000
};
/* When a toolbar does not have enough space to fit all its items, it must push some into the overflow menu.
Items with the highest visibility priority level are chosen last for the overflow menu. The default
visibilityPriority value is NSToolbarItemVisibilityPriorityStandard. To suggest that an item always
remain visible, give it a value greater than NSToolbarItemVisibilityPriorityStandard, but less than
NSToolbarItemVisibilityPriorityUser. In configurable toolbars, users can control the setting of any item,
and the value is rememeber by NSToolbar along with its other autosaved information. You should allow
user setting to have the highest priority.
*/
- (void)setVisibilityPriority:(int)visibilityPriority;
- (int)visibilityPriority;
A cautionary note: The toolbar is never meant to be the only way of doing a particular function. This API should not be used as a crutch. In fact, since users can override your suggestion of what should be visible, you are still never guaranteed that an item will always be visible.


NSStatusItem

You can now get and set a separate double click action on an NSStatusItem. This action is called for any even with a clickCount of greater than 1.
- (SEL)doubleAction;
- (void)setDoubleAction:(SEL)aSelector;

NSMenu

A new method has been added to NSMenu that returns the menu bar height for the main menu. This method supersedes +[NSMenuView menuBarHeight]. The method returns the menu bar height if the menu is the application's current main menu and 0 otherwise.
- (float)menuBarHeight;

Dock Menu

In Tiger, we added support for alternate menu items in dock menus. We also added support to invoke the NSMenu delegate methods if a menu delegate is set.


NSSegmentedCell/NSSegmentedControl

A new method has been added to NSSegmentedCell and NSSegmentedControl that selects the cell given the tag. It will search for the item with the tag and then call -[NSSegmentedCell setSelectedSegment]. The function will return YES if the segment is found even if the cell isn't selectable because it's disabled. The control method calls the cell method.
- (BOOL)selectSegmentWithTag:(int)tag;

NSPopUpButtonCell/NSPopUpButton

A new method has been added to NSPopUpButtonCell and NSPopUpButton that selects an item given the tag. It will search for the item with the tag and then call -[NSPopUpButtonCell selectItemAtIndex]. The method will return YES if the item is found. If the item isn't found, the function returns NO and does nothing. The control method calls the cell method.
- (BOOL)selectItemWithTag:(int)tag;

NSFormCell

Placeholder string methods in NSTextFieldCell are also available in NSFormCell.
- (void)setPlaceholderString:(NSString *)string;
- (NSString *)placeholderString;
- (void)setPlaceholderAttributedString:(NSAttributedString *)string;
- (NSAttributedString *)placeholderAttributedString;

NSButtonCell (Section updated since WWDC)

You can now set the background colour of a borderless button. This does not affect the color of bordered buttons such as push buttons.
- (void)setBackgroundColor:(NSColor *)color;
- (NSColor *)backgroundColor;
The drawing of the button background, image, and text has been broken out into 3 separate public methods that give a subclass an override point.
- (void)drawImage:(NSImage *)image withFrame:(NSRect)frame inView:(NSView *)controlView;
- (NSRect)drawTitle:(NSAttributedString *)title withFrame:(NSRect)frame inView:(NSView *)controlView;
- (void)drawBezelWithFrame:(NSRect)frame inView:(NSView *)controlView;
These methods are called if the button has the appropriate setting. -drawBezelWithFrame:inView: is called if the button is bordered. -drawImage:withFrame:inView: and -drawTitle:withFrame:inView: will be called if the button has an image and title respectively. -drawTitle:withFrame:inView: will return the actual rectangle used to render the text (usually centered in the frame passed in.)

There are several new bezel styles available:
    NSSmallSquareBezelStyle = 10
NSTexturedRoundedBezelStyle = 11
The first is a simple square bezel that appears in the accounts preference pane in System Preferences (the '+' and '-' buttons). NSTexturedRoundedBezelStyle is used to create a button similar to the Finder's action (gear) button. It is similar in appearance to a single item segmented control.

Both have regular, pressed, and disabled appearances. The controlSize setting does not apply. NSSmallSquareBezelStyle can scale to any size and NSTexturedRoundedBezelStyle has only a single size and a fixed height.
    NSRoundRectBezelStyle = 12
This is a button with semicircular end caps. It has a gray shading from light to dark. It has regular, pressed, and disabled appearances. You should set the font to be Lucida Grande 12 point.
    NSRecessedBezelStyle = 13
This is a button with semicircular end caps. It appears to have a recessed appearance. It has regular, pressed, selected, and disabled appearances. You should set the font to be Lucida Grande 12 point. This button works when you set -setShowsBorderOnlyWhileMouseInside to YES.
    NSRoundedDisclosureBezelStyle = 14
This button is a square button that is the same as the disclosure button in the save panel. It has regular and selected states. It should not have text or an image set.


NSSearchFieldCell

A flag is available that will cause the search field cell's action to be sent without delay instead of grouping the changes together until the user pauses typing.
- (BOOL)sendsSearchStringImmediately;
- (void)setSendsSearchStringImmediately:(BOOL)flag;

NSCell

The method -setControlView: is now available in NSCell and its subclasses. The implementation in NSCell does nothing. The implementation in NSActionCell saves the view.

You can now set the cell (usually an NSTextFieldCell) to allow or disallow undo. By default, the field is set to allow undo. The undo stack is cleared when the cell begins editing.
- (void)setAllowsUndo:(BOOL)allowsUndo;
- (BOOL)allowsUndo;
You can set the line break mode of a cell for text drawing. This will allow truncation of text in the cell without needing to subclass. Calling -[NSCell setWraps:] will set the mode to NSLineBreakByWordWrapping and NSLineBreakByClipping for YES and NO respectively. -setWraps will return YES if the mode is NSLineBreakByWordWrapping or NSLineBreakByCharWrapping.
- (void)setLineBreakMode:(NSLineBreakMode)mode
- (NSLineBreakMode)lineBreakMode

NSBox (Section added since WWDC)

In Tiger, we added an optimization to draw the background of an NSBox opaquely, if the NSBox is a top level view in the window and fits other criteria. Since we have discovered some applications whose nib layout involves views which overlap the NSBox rather than being completely contained, we have enabled this optimization only for applications built on Tiger or later.


NSComboBox

Calling -[NSComboBox setUsesDataSource:] now always sets indexOfSelectedItem to -1. Prior to Tiger it didn't do this for setUsesDataSource:NO.

copyWithZone: no longer loses font information in the table. Previously, copying a combo box cell would always result in a table using the default font size, even if the combo box cell was using something different like the smallSystemFont.

NSComboBox's popup menu now only shows the scroll bar if it is necessary.

NSComboBox popup window positioning has changed a bit. If the popup can not fit below the text field, NSComboBox now places the combo box above the text field only if there is more space above the combo box than there is below. In the past, NSComboBox didn't pay attention to which side had more space. Further, if there isn't enough room on either side, NSComboBox now shrinks the window to fit on screen.

NSComboBox has fixed a bug in -indexOfSelectedItems which caused the index to be incorrect when used from the NSComboBox action in certain situations.

NSComboBoxCell can now be used inside of an NSMatrix. To function properly, the matrix should use NSTrackModeMatrix for its -mode.


NSBrowser (Section updated since WWDC)

Calling setTitle:ofColumn: during column creation now works. Prior to Tiger, calling it was not possible to set the title of the column being created using this API from either of the delegate "creation" methods: -browser:numberOfRowsInColumn: or -browser:createRowsForColumn:inMatrix:.

The titleFrame passed into drawTitleOfColumn:inRect: is now 2 pixels bigger on each side. In the past, NSBrowser used to inset value returned by titleFrameOfColumn: before calling drawTitleOfColumn:inRect:. This was the wrong thing to do, and also led to certain descenders (like "g", and "j") being clipped at the bottom. Note that the baseline of the text will not move. The new behavior applies unless you are using a subclass of NSBrowser linked before Tiger. For applications linked on or after Tiger, NSBrowserCell now defaults to using NSLineBreakByTruncatingTail for its line break mode. Set -[NSCell setLineBreakMode:] for more information on line break modes.


NSMatrix

When dirtying a cells contents, NSMatrix now pays attention to the cells -focusRingType. In the past, NSMatrix always assumed a -focusRingType of NSFocusRingTypeExterior, causing it to use [self setKeyboardFocusRingNeedsDisplayInRect:cellFrame] always, instead of just for cells that support focus rings.

NSComboBoxCell can now be used inside of an NSMatrix. To function properly, the matrix should use NSTrackModeMatrix for its -mode.


NSOutlineView

-(BOOL)isItemExpanded:(id)item; now returns NO if 'item' is not found.

NSOutlineView now returns valid results from rowForItem:, and levelForItem: when called with children of an item in progress of expanding. While a particular child item is being loaded, these methods will return valid results. Previously they returned -1 while an item was in the process of being loaded by a parent (for instance during an item expand). There is no reason this particular type of information should not be valid during load time, so it is now available.

NSOutlineView's data loading is much lazier now. Data is now requested from the data source on demand. In general, the data source will not be queried for an items data unless that item is visible, or an API is invoked which requires that data to be present.

The following methods, indicated as deprecated since before 10.0, have been removed: -(void)setAutoResizesOutlineColumn: (BOOL)resize; and - (BOOL)autoResizesOutlineColumn; If you are using these methods, switch to using: -(void)setAutoresizesOutlineColumn: (BOOL)resize; and - (BOOL)autoresizesOutlineColumn;

NSOutlineView's outline column now respects the minWidth specified in IB. In the past, NSOutlineView forced the minWidth to the a value large enough to always show the expansion cells, even if that was smaller than the minWidth you specified. This change takes effect for apps linked on or after Tiger.

Drag and Drop

For applications built on Tiger or later, NSOutlineView now allows row dragging to begin with a click in any column. Previously, dragging out was limited to the outline column. Applications built on Tiger and later, can keep the old behavior by simply overriding -(BOOL)canDragRowsWithIndexes:(NSIndexSet *)rowIndexes atPoint:(NSPoint)aPoint; to return YES only when 'aPoint' is in the outline column.

For more drag and drop changes, see NSTableView release notes.

ToolTips

For many reasons, it is difficult to add cell-level toolTips to an NSOutlineView using existing NSView API. To solve this, we are adding new API which will let your delegate supply the tooltip for a cell (column/row intersection) on demand. Note that there are no tooltip tracking tags associated with these tooltips. To take advantage of this new feature, you need to implement the delegate method:
/* When the user pauses over a cell, the value returned from this method will be displayed in a tooltip.
'point' represents the current mouse location in view coordinates. If you don't want a tooltip
at that location, return nil. On entry, 'rect' represents the proposed active
area of the tooltip. By default, rect is computed as [cell drawingRectForBounds:cellFrame].
To control the default active area, you can modify the 'rect' parameter.
*/
- (NSString *)outlineView:(NSOutlineView *)ov toolTipForCell:(NSCell *)cell rect:(NSRectPointer)rect
tableColumn:(NSTableColumn *)tc item:(id)item mouseLocation:(NSPoint)mouseLocation;

NSTableView

Misc

For applications linked on or after Tiger, NSTableView invalidates the table and header view only when the frame size or column sizes has changed. In the past, calls to -tile unnecessarily invalidated the entire table and header view.

For applications linked on or after Tiger, NSTableView's (and NSOutlineView) default data cell now defaults to using NSLineBreakByTruncatingTail for its line break mode. Set -[NSCell setLineBreakMode:] for more information on line break modes.

Deselecting the edited row now ends editing. Due to a bug, in Panther and earlier systems, deselecting sometimes ended editing and sometimes did not. This has been fixed.

Double clicking now only starts editing if the click was in the cellFrame area. Prior to Tiger, double clicking anywhere in the column/row rect started editing. In particular, this had an odd effect in NSOutlineView. So now, double clicking on the left side of the outline disclosure button no longer starts cell editing.

Menu validation has changed slightly. deselectAll: is now disabled if there is no selection in the table. selectAll: is now disabled if the table disallows multiple selections.

Changing the table background color, and grid color now cause a redisplay if needed.

NSTableView is now much more aggressive about making sure the dataCell and headerCell's controlView ivar is set. For example, in Panther and earlier systems, calling [self controlView] would normally return nil for a cell in a table. For applications linked on or after Tiger, this and other related problems have been fixed. In general, NSTableView tries to make sure calling -controlView will return a reference to itself for the cells it uses.

For applications linked on or after Tiger, removing a column from an NSTableView now results in the column's tableView reference to be set to nil.

The attributes of table column's default data cells have changed. In its -init method NSTableColumn now creates a default NSTextFieldCell data cell with the following changed attributes: setDrawsBackground=YES; font=systemFont with size systemFontSize (Lucida Grande, 13). Prior to Tiger, NSTableColumn used to set the default properties to setDrawsBackground=NO, and font=(Lucida Grande, 12). The difference used to present many problems. For instance, if you added columns to your table in code, they would have different font sizes than those from the archived nib. Further, if you chose to display the popular alternating row colors, those data cells whose setDrawsBackground was YES would obscure the blue on every other line. Finally, in most tables it is unnecessary for the cells to draw the background because the table is already drawing the background. The new attributes are only set for applications linked on Tiger and later, and only in NSTableColumn's init method. So, if you have archived nibs with the wrong font size, you should fix them by hand in IB or in code.

Also, in IB it was possible to create new columns that had different properties than the default columns you get when dragging a table from the palette.

Deprecated API

Wherever possible, NSTableView now uses NSIndexSet in its APIs. The following methods have been deprecated:
- (NSImage *)dragImageForRows:(NSArray *)dragRows event:(NSEvent *)dragEvent dragImageOffset:(NSPointPointer)dragImageOffset;
- (BOOL)tableView:(NSTableView *)tv writeRows:(NSArray *)rows toPasteboard:(NSPasteboard *)pboard;
... and replaced with NSIndexSet based versions:
- (NSImage *)dragImageForRowsWithIndexes:(NSIndexSet *)dragRows tableColumns:(NSArray *)tableColumns
event:(NSEvent *)dragEvent offset:(NSPointPointer)dragImageOffset;
- (BOOL)tableView:(NSTableView *)tv writeRowsWithIndexes:(NSIndexSet *)rowIndexes toPasteboard:(NSPasteboard *)pboard;
Accessibility Fixes

Selecting a table row using accesibility APIs now properly consults NSTableView's shouldSelectRow: delegate API.

NSTableView now sets up more NSCell state before calling accessibilityPerformAction: when the action is NSAccessibilityPressAction. In particular, the cells controlView is set to the table, and the table's clickedRow and clickedColumn reflect the row and column of the cell receiving the NSAccessibilityPressAction. Finally, the selectedCell of the table will return the cell handling the NSAccessibilityPressAction. The idea is that NSAccessibilityPressAction should be able to be handled the same as if the user had clicked on the cell with the mouse.

Drag and Drop (Section updated since WWDC)

NSTableView has added API that lets you control where row dragging operations can begin. By default NSTableView allows drags to begin anywhere with a few exceptions: Clicks on a buttons, popup buttons, sliders and other similar controls will track the mouse instead of beginning a row drag. To customize this behavior, override the following method:
/* The return value indicates whether the table can attempt to initiate a row drag at 'mouseDownPoint'.
Return NO to disallow initiating a row drag at the given location.
*/
- (BOOL)canDragRowsWithIndexes:(NSIndexSet *)rowIndexes atPoint:(NSPoint)mouseDownPoint;
NSTable/OutlineViews that are drag destinations now revalidate drags (validateDrop: API) if the modifier keys change.

You can now customize NSTableView's (and NSOutlineView) implementation of -draggingSourceOperationMaskForLocal without subclassing. NSTableView implements the dragging source method -draggingSourceOperationMaskForLocal: for you. By default it disallows dragging to destinations outside its application while allowing any type of drag within its application. There are two options for customizing this behavior. Developers can always subclass and override this method when decisions need to be dynamic. However, In Tiger, we have added an easier way to customize the behavior. Simply use the following new method:
/* Configures the default value returned from -draggingSourceOperationMaskForLocal:.
An isLocal value of YES indicates that 'mask' applies when the destination object is in the same application.
An isLocal value of NO indicates that 'mask' applies when the destination object in an application outside
the receiver's application. NSTableView will archive the values you set.
*/
- (void)setDraggingSourceOperationMask:(unsigned int)mask forLocal:(BOOL)isLocal;
Drag and Drop - File Promise Dragging

NSTableView supports file promised drags via the new pasteboard type NSFilesPromisePboardType. To support file promise drags, clients simply add this type to the pasteboard in tableView:writeRowsWithIndexes:toPasteboard:. When a destination accepts the promise drag, it asks NSTableView to supply the files via -namesOfPromisedFilesDroppedAtDestination:. NSTableView passes the responsibility of the actual file creation to data source that specified the promise drag. It will be sent the following new data source method:
/* Returns an array of filenames for the created files (filenames only, not full paths).  The URL represents
the drop location. For more information on file promise dragging, see documentation on the
NSDraggingSource protocol and -namesOfPromisedFilesDroppedAtDestination:.
*/
- (NSArray *)tableView:(NSTableView *)tableView namesOfPromisedFilesDroppedAtDestination:(NSURL *)dropDestination
forDraggedRowsWithIndexes:(NSIndexSet *)indexSet;
NSOutlineView has its own version:
- (NSArray *)outlineView:(NSOutlineView *)outlineView
namesOfPromisedFilesDroppedAtDestination:(NSURL *)dropDestination
forDraggedItems:(NSArray *)items;
ToolTips

For many reasons, it is difficult to add cell-level toolTips to an NSOutlineView using existing NSView API. To solve this, we are adding new API which will let your delegate supply the tooltip for a cell (column/row intersection) on demand. Note that there are no tooltip tracking tags associated with these tooltips. To take advantage of this new feature, you need to implement the delegate method:
/* When the user pauses over a cell, the value returned from this method will be displayed in a tooltip.
'point' represents the current mouse location in view coordinates. If you don't want a tooltip at that location, return nil.
On entry, 'rect' represents the proposed active area of the tooltip. By default, rect is computed as
[cell drawingRectForBounds:cellFrame]. To control the default active area, you can modify the 'rect' parameter.
*/
- (NSString *)tableView:(NSTableView *)tv toolTipForCell:(NSCell *)cell rect:(NSRectPointer)rect
tableColumn:(NSTableColumn *)tc row:(int)row mouseLocation:(NSPoint)mouseLocation;

Variable Row Heights

Until now, every row in a table view was required to be the same height as every other row. This is appropriate for the vast majority of table view's uses. However, in some cases, it is limiting. Sometimes it can be beneficial to specify the height of a row based on the data that row needs to display. In Tiger, we will allow table view rows to be specified per row if necessary with the following API:
/* If the delegate implements -tableView:heightOfRow:, this method immediately re-tiles the table view using row heights it provides.
*/
- (void)noteHeightOfRowsWithIndexesChanged:(NSIndexSet *)indexSet;

@interface NSObject (NSTableViewDelegate)
/* Optional - Variable Row Heights
Implement this method to support a table with varying row heights. The height returned by this method should not include
intercell spacing and must be >0. Performance Considerations: For large tables in particular, you should make sure that this
method is efficient. NSTableView may cache the values this method returns. So if you would like to change a row's height make
sure to invalidate the row height by calling -noteHeightOfRowsWithIndexesChanged:. NSTableView automatically invalidates its
entire row height cache in -reloadData, and -noteNumberOfRowsChanged.
*/
- (float)tableView:(NSTableView *)tableView heightOfRow:(int)row;
@end
@interface NSObject (NSOutlineViewDelegate)
/* Optional - Variable Row Heights
Implement this method to support an outline view with varying row heights. The height returned by this method should not include
intercell spacing and must be >0. Performance Considerations: For large tables in particular, you should make sure that this
method is efficient. NSTableView may cache the values this method returns. So if you would like to change a row's height make
sure to invalidate the row height by calling -noteHeightOfRowsWithIndexesChanged:. NSTableView automatically invalidates its
entire row height cache in -reloadData, and -noteNumberOfRowsChanged.
*/
- (float)outlineView:(NSOutlineView *)outlineView heightOfRowByItem:(id)item;
@end
Some notes about variable row height table view's:
- The lineScroll of the table's scroll view is controlled by -rowHeight.
- The height of "filler" rows is controlled by -rowHeight. Ie. The distance between grid lines, and alternating row colors past the last table row.


Table Column Resizing - Better algorithm / New APIs

NSTableView currently supports two column autoresizing modes: "resize all" and "resize last".

We are changing behavior of the current "resize all" mode. Its behavior is simplistic and not useful. Currently, as the table resizes, it sets the width of each resizable column to (availableWidth / numResizableColumns), contraining to each min and max. This distribution algorithm doesn't take into account the current relative sizes of each column. This behavior will be replaced with an algorithm that uniformly distributes space while taking into account initial values. The current "resize last" resizes the last resizable column until it reaches its min or max width. This behavior will be retained.

In addition to the existing modes, we will be adding a few more column autoresizing modes to NSTableView. In particular, we are adding a mode which allow developers to turn off column autoresizing. This will be useful for those that want to implement their own column autoresizing algorithm.

Note: "autoresizing" refers to column resizing in response to a frame change. Think live resize. "User resizing" refers to resizing by dragging from the right edge of a column header.

Also note, NSTableView's -sizeToFit, and -sizeLastColumnToFit behavior has been fixed as part of this work to use the new styles and algorithms. During a live resizing operation, these methods use the specific resizing style you have choosen via -setColumnAutoresizingStyle:. When called outside a live resize operation, -sizeToFit resizes columns to fit the visible width using NSTableViewUniformColumnAutoresizingStyle, while -sizeLastColumnToFit resizes columns using NSTableViewLastColumnOnlyAutoresizingStyle.
/* The column auto resizing style controls resizing in response to a table view frame change.
Compatability Note: This method replaces -setAutoresizesAllColumnsToFit:.
*/
typedef enum {
// Turn of column autoresizing
NSTableViewNoColumnAutoresizing = 0,
    // Autoresize all columns by distributing equal shares of space simultaeously
NSTableViewUniformColumnAutoresizingStyle,
    // Autoresize each table column one at a time.
// Proceed to the next column when the current column can no longer be autoresized (when it reaches maximum/minimum size).
NSTableViewSequentialColumnAutoresizingStyle, // Start with the last autoresizable column, proceed to the first.
NSTableViewReverseSequentialColumnAutoresizingStyle, // Start with the first autoresizable column, proceed to the last.
    // Autoresize only one table column one at a time.
// When that table column can no longer be resized, stop autoresizing.
// Normally you should use one of the Sequential autoresizing modes instead.
NSTableViewLastColumnOnlyAutoresizingStyle,
NSTableViewFirstColumnOnlyAutoresizingStyle
} NSTableViewColumnAutoresizingStyle;
- (void)setColumnAutoresizingStyle:(NSTableViewColumnAutoresizingStyle)style;
- (NSTableViewColumnAutoresizingStyle)columnAutoresizingStyle;

/* Deprecated in Mac OS 10.4.  You should use setColumnAutoresizingStyle: instead.
To preserve compatibility, if flag is YES, This method calls setColumnAutoresizingStyle:NSTableViewUniformColumnAutoresizingStyle.
If flag is NO, this method calls setColumnAutoresizingStyle:NSTableViewLastColumnOnlyAutoresizingStyle.
*/
- (void)setAutoresizesAllColumnsToFit:(BOOL)flag;
- (BOOL)autoresizesAllColumnsToFit;

NSTableColumn's resizing characteristics now provide finer controls. We have added API which allows you to declare that the user can resize a column, but that it should not resize during live resize (autoresizing).
/* The resizing mask controls the resizability of a table column.  Compatability Note: This method replaces setResizable.
*/
- (void)setResizingMask:(unsigned)resizingMask;
- (unsigned)resizingMask;
enum {
NSTableColumnNoResizing = 0, // Disallow any kind of resizing.
NSTableColumnAutoresizingMask = ( 1 << 0 ), // This column can be resized as the table is resized.
NSTableColumnUserResizingMask = ( 1 << 1 ), // The user can resize this column manually.
};
/* Deprecated in Mac OS 10.4.  If flag is YES, calls
setResizingMask:(NSTableColumnUserResizingMask | NSTableColumnAutoresizingMask).
If flag is NO, calls setResizingMask:(NSTableColumnNoResizing).
*/
- (void)setResizable:(BOOL)flag;
- (BOOL)isResizable;


Bindings and Binding Options (Section updated since WWDC)

The names of all the bindings and options used in AppKit are now declared through explicit constants in NSKeyValueBinding.h.

To debug problems with key-value coding and key-value observing related to bindings, you can now set a user default NSBindingDebugLogLevel to get more useful logs about the problems (instead of undefined key exceptions, for example). This may be useful when you try to find a misconfigured binding in a large nib file with many bindings. Set the default value to 1 to turn on logging, and to 0 to turn it off.

A new method for returning information about the current bindings of an object has been added to NSObject:
- (NSDictionary *)infoForBinding:(NSString *)binding;
It returns a dictionary with information about an existing binding or nil if it is not bound. See NSKeyValueBinding.h for more details.

Several new bindings are available:
- NSTextView now has an attributedString binding (available if multiple fonts are allowed or not).
- NSView and subclasses now have a toolTip binding.
- NSWindow now has displayPatternTitle bindings to specify the window title through a pattern string with multiple values (and work the same way as the displayPatternValue bindings on text fields).
- NSBox now has a title and displayPatternTitle bindings (that work like the bindings on NSWindow).
- NSSearchField now has a predicate binding (and if bound exposes additional predicate2, predicate3, etc. bindings) - you specify a display name and a prediate format string through the binding's options and typically bind them to the filterPreciate of an array controller.
- NSTableView now has doubleClickArgument/doubleClickTarget bindings that work the same way as the argument/target bindings of buttons - the bindings are used to trigger a method invocation on a double-click in the table view.
- Selection widgets (NSPopUpButton/NSPopUpButtonCell and NSMatrix) now offer a contentObjects binding in addition to the content and contentValues bindings (the contentObjects binding becomes available only if content is bound). This allows you to bind the content of the widget to an array (content binding), the displayed values to a dependent array (contentValues binding - which needs to use a key path that is an extension to the one of the content binding), and the "represented" objects to be handled through the selectedObject/selectedObjects bindings to another depdendent array (contentObjects - which also needs to use a key path that is an extension to the one of the content binding). For example, if you have an array with dictionaries (that can be bound to a controller through the "selection.dictionaries" key) which each have values for a key "displayName" and a key "representedObject", you can bind content of a pop-up button to "selection.dictionaries", contentValues to "selection.dictionaries.displayName" and contentObjects to "selection.dictionaries.representedObject" - the selectedObject will then operate on the "representedObject" values, while the pop-up displays the "displayName" values in the user interface. Of course, if you do not use the contentObjects binding, the represented objects are still the values in the array to which content is bound.

An option for the value bindings on table columns has been added:
NSCreatesSortDescriptorBindingOption
This option can be used to suppress the creation of sort descriptors on a column (binding) basis.

An option to force bindings to handle errors with alert panels instead of sheets has been added to varioius bindings:
NSAlwaysPresentsApplicationModalAlertsBindingOption
A variety of bugs have been fixed, some of the fixes caused a slight change in the behavior of bindings/controllers:
- For bindings with immediate validation turned on, the user interface now correctly reflects values immediately when coerced in the validateValue:forKey: method.
- Bindings on table columns with pop-up data cells and content, contentValues and selectedObject bindings now generate sort descriptors for the selected objects based on the display key (as determined from the contentValues binding).
- Unless explicitly specified, table view content, selectionIndexes and sortDescriptor bindings are automatically generated, derived from the common cases of bindings of table columns. These automatic table view bindings are now created by invoking the public -bind:toObject:withKeyPath:options: on the table view, so that subclasses can intercept the calls if needed.
- In the Panther implementation, when removing objects in the background from the array to which an NSArrayController content was bound (not removing through the controller), an index-out-of-bounds exception was sometimes raised. This situation has been fixed for Tiger.
- In Panther, copying the arrangedObjects array of an NSArrayController copied the items in the array as well. This situation has been fixed for Tiger, now the content objects are not copied any more.
- In Panther, collection values (NSArrays and NSDictionaries) read from an NSUserDefaultsController were returned as immutable collections, making it impossible to add or remove from them directly. The workaround was to use a value transformer to make mutable copies of the collections on read. For Tiger, NSUserDefaultsController now returns collections as mutable instances, which makes the use of a special value transformer obsolete (but you still usually need to turn on the NSHandlesContentAsCompoundValueBindingOption option if you bind the content of an NSArrayController or NSObjectController to a value provided through an NSUserDefaultsController).
- Interface Builder now correctly calls -exposedBindings to populate the Bindings inspector.


NSEditor, bindings error presentation as sheets (Section added since WWDC)

So that support for bindings in Cocoa's own views can present error alerts as sheets when appropriate, a new method has been added to key-value binding's NSObject (NSEditor) category:
- (void)commitEditingWithDelegate:(id)delegate didCommitSelector:(SEL)didCommitSelector contextInfo:(void *)contextInfo;
Given that the receiver has been registered with -objectDidBeginEditing: as the editor of some object, and not yet deregistered by a subsequent invocation of -objectDidEndEditing:, attempt to commit the result of the editing. When committing has either succeeded or failed, send the selected message to the specified object with the context info as the last parameter. The method selected by didCommitSelector must have the same signature as:
- (void)editor:(id)editor didCommit:(BOOL)didCommit contextInfo:(void *)contextInfo;
If an error occurs while attempting to commit, because key-value coding validation fails for example, an implementation of this method should typically send the NSView in which editing is being done a -presentError:modalForWindow:delegate:didRecoverSelector:contextInfo: message, specifying the view's containing window.

Various Cocoa classes use this method whenever possible, instead of the existing -commitEditing method, to enable proper use of sheets when presenting errors. The existing -commitEditing method is not deprecated however, because there are situations in which the success or failure of commitment must be known immediately. Implementations of -commitEditing should typically use -presentError: if an error occurs.

The bindings and controller default implementation of the NSEditor methods will use the new NSResponder-based error presentation API, so that error handling can be customized by individual applications.

Also, due to the sheet based error handling, controller action methods like add:, remove:, fetch:, etc. will now execute their operations deferred, so when the methods return, the operation is not actually performed (it will be later, but programmatic invocations of the action methods cannot rely on the operation to have completed).

CoreData's NSManagedObjectContext does implement both the NSEditor and the NSEditorRegistration methods, like NSController does.


NSObjectController

NSObjectController (and thus the subclasses NSArrayController and NSTreeController) has the following new API to specify a managed object context and a description for how to fetch objects from it (by entity name and fetch predicate). The entity name (if specified) also determines how new objects are created (instead of using a class name).
- (NSManagedObjectContext *)managedObjectContext;
- (void)setManagedObjectContext:(NSManagedObjectContext *)managedObjectContext;
- (NSString *)entityName;
- (void)setEntityName:(NSString *)entityName;
- (NSPredicate *)fetchPredicate;
- (void)setFetchPredicate:(NSPredicate *)predicate;
- (void)fetch:(id)sender;

NSTreeController

Tiger introduces a new controller class in Cocoa, NSTreeController, for managing hierarchical data structures. Much of the API of this class parallels that of the array controller. This class, in conjunction with the new NSIndexPath class in Foundation, enables displaying a tree of model objects in a NSOutlineView or NSBrowser.

Much of the API in this class is either inherited from NSController and NSObjectController or is designed to be similar to the API of the NSArrayController. Many of the concepts are the same except that objects are addressed by NSIndexPath instead of int.

Content of the tree controller can be set to the root of the tree of model objects. Clients can then progressively traverse parts of the tree as necessary by getting model objects based on an NSIndexPath, which represents their depth-first location in the tree. This removes the need for us to pull the entire tree into memory up front. On the down side, this prevents us from offering selectObject: functionality since we don't want to pay the penalty of doing a depth first search for an object in an unordered tree.

The NSTreeController traverses its content tree by using key value coding to find the children of a model object. There are methods for setting the key to use to traverse the tree, as well as 2 other keys used as performance improvement opportunities. If a model object in the tree can report the number of children it has, we can use the countKey to find the number of children instead of getting the entire child array just to message it count. Likewise, we can stop traversing a sub-tree once we encounter an object that tells us it is a leaf node in the tree by return YES for the key set as the leafKey.

It should be noted that because of the nature of selections in unordered trees, implementation of the preservesSelection feature maybe pretty expensive for large, sparse selections combined with broad trees.


NSArrayController (Section added since WWDC)

NSArrayController now supports filtering with NSPredicates:
- (void)setFilterPredicate:(NSPredicate *)filterPredicate;
- (NSPredicate *)filterPredicate;
- (void)setClearsFilterPredicateOnInsertion:(BOOL)flag;
- (BOOL)clearsFilterPredicateOnInsertion;
The filter predicate can be bound to the (enumerated) predicate bindings of NSSearchFields (use the NSDisplayNameBindingOption and NSPredicateFormatBindingOption options to configure the bindings) to automatically set up filtering in the user interface.

NSArrayController also has a new mode to handle multiple selections:
- (void)setAlwaysUsesMultipleValuesMarker:(BOOL)flag;
- (BOOL)alwaysUsesMultipleValuesMarker;
By default, the array controller will look at values of selected objects on a key-by-key basis and indicate selections of multiple different values through the NSMultipleValuesMarker, but provide the common value if all selected objects have the same value. If alwaysUsesMultipleValuesMarker is set to YES, it will use the NSMultipleValuesMarker for all selections with two or more objects (you will typically also set NSAllowsEditingMultipleValuesSelectionBindingOption option of the various value bindings for controls bound to the array controller's selection to NO). This new flag is very useful in applications with very large arrays of objects that don't want to allow editing multiple selected objects at all and also results in strong performance enhancements in certain situations with large arrays.


NSUserDefaultsController (Section added since WWDC)

NSUserDefaultsController has a new method to indicate whether there are unapplied changes:
- (BOOL)hasUnappliedChanges;
For example, you can bind the enabled state of buttons to this method.


NSGraphicsContext

The NSGraphicsContext class now has API to specify the compositing operation setting: compositingOperation and setCompositingOperation:. As with other graphics context state, the setting is saved/restore via saveGraphicsState and restoreGraphicsState methods. The setting has no effect with existing rendering API that take compositing operation as an argument such as -[NSImage compositeToPoint:operation:].

The NSGraphicsContextDestinationAttributeName now allows an instance of NSBitmapImageRep as its value. Currently only non-planar NSBitmapImageRep instances are supported. A convenience factory method graphicsContextWithBitmapImageRep: is also added.

As an example of usage, the following code will resample the bitmap in srcRep to be width x height, with the result going to outputRep:
    NSBitmapImageRep *outputRep = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:NULL
pixelsWide:width pixelsHigh:height bitsPerSample:8 samplesPerPixel:4
hasAlpha:YES isPlanar:NO colorSpaceName:NSCalibratedRGBColorSpace
bytesPerRow:0 bitsPerPixel:0];
    NSGraphicsContext *ctxt = [NSGraphicsContext graphicsContextWithBitmapImageRep:bitmapImageRep];
    [NSGraphicsContext saveGraphicsState];
[NSGraphicsContext setCurrentContext:ctxt];
[[NSGraphicsContext currentContext] setImageInterpolation:NSImageInterpolationHigh];
[srcRep drawInRect:NSMakeRect(0, 0, width, height)];
[NSGraphicsContext restoreGraphicsState];

A factory method graphicsContextWithGraphicsPort:flipped: is added. You can instantiate NSGraphicsContext from any arbitrary CGContextRef using this method. The initialFlippedState argument determines the initial flippedness setting returned from the -isFlipped method.

The class now has the flipped setting accessible via the isFlipped method. The recommended way to determine the current flipped state of rendering coordinate system is now [[NSGraphicsContext currentContext] isFlipped] instead of [[NSView focusView] isFlipped]. Note, as with NSView's counterpart, this setting does not necessarily reflect the current coordinate system.


NSAffineTransform (Section added since WWDC)

The NSAffineTransform class implementation moved from AppKit to Foundation. -transformBezierPath:, -set, and -concat methods are now part of a category implemented in AppKit.


NSBitmapImageRep (Section updated since WWDC)

You can now get and set custom gamma values for PNG files using the NSImageGamma property. If set in the file, the property is set in the bitmap image rep on reading and is used when saving the bitmap as PNG data.

NSBitmapImageRep now supports alternate arrangements of alpha values and formats. The following enum and methods have been added:
typedef enum {
NSAlphaFirstBitmapFormat = 1 << 0, // 0 means is alpha last (RGBA, CMYKA, etc.)
NSAlphaNonpremultipliedBitmapFormat = 1 << 1, // 0 means is premultiplied
NSFloatingPointSamplesBitmapFormat = 1 << 2     // 0 means integer
} NSBitmapFormat;
- (id)initWithBitmapDataPlanes:(unsigned char **)planes
pixelsWide:(int)width pixelsHigh:(int)height bitsPerSample:(int)bps
samplesPerPixel:(int)spp hasAlpha:(BOOL)alpha isPlanar:(BOOL)isPlanar
colorSpaceName:(NSString *)colorSpaceName
bitmapFormat:(NSBitmapFormat)bitmapFormat bytesPerRow:(int)rBytes bitsPerPixel:(int)pBits;
- (NSBitmapFormat)bitmapFormat;
Returns new bitmap image rep using the specified format. Invalid formats will cause the method to return nil. For example, setting a floating point format requires bits/sample to be 32 (though we may support double or so-called half floating point values in the future.). The bitmap format may also be set to non-zero when loading in images from files. For example, PNG files are now loaded in with a format of NSAlphaNonpremultipliedBitmapFormat.

Return format image is in either from loading file or via -initWithBitmapDataPlanes:... or -initWithFocusedViewRect... If created using the older APIs that don't take a bitmap format, the format defaults to 0 (alpha last, premultiplied, integer)

By default, the new formats will be returned for cases where the source of the bitmap data is in the new format (floating point, non-premutliplied, etc.). Pre-Tiger compiled apps will still get the old premultiplied RGBA format. You can also enable or disable it explicity by setting the NSOldBitmapFormatOnly default to YES or NO. -initWithFocusedViewRect: will continue to return bitmap format 0 images.

You can now specify NSJPEG2000FileType as the output format to write JPEG 2000 files.

You can now specify progressive JPEG saving via the bitmap property NSImageProgressive to output progressive JPEG images.

When reading or writing a JPEG file, you can include an NSDictionary as the NSImageEXIFData bitmap image property.

Methods are now available that set/get the color info for a pixel in an NSBitmapImageRep. If the image rep is part of an NSImage and the rep is cached by the NSImage then changing the pixel values may not show up when drawing the image. If you do place the rep inside an image and intend to modify it, use [image setCacheMode:NSImageCacheNever]. For -getPixel:atX:y: and -setPixel:atX:y: you must supply an array to match the rep's samples per pixel and the range of values are based on the rep's bits per sample (e.g. if bps is 4, then values returned are from 0 to 15). Setting values out of range are not defined. If the bitmap has floating point samples, the actual values returned are floats. Similarly, pixel order and premultiplication are assumed to match the rep's bitmap format.
- (void)setColor:(NSColor *)color atX:(int)x y:(int)y;
- (NSColor *)colorAtX:(int)x y:(int)y;
- (void)getPixel:(unsigned int[]) atX:(int)x y:(int)y;
- (void)setPixel:(unsigned int[]) atX:(int)x y:(int)y;
If you do not pass in explicit planes and bytesPerRow values when creating an NSBitmapImageRep, the buffer pointer returned may no longer be the first byte of a malloc'ed block and the bytesPerRow may be padded with extra bytes for performance. If you traverse the bytes, do not assume that bytesPerRow = width * bitsPerSample / 8 otherwise the image may appear skewed.

If you modify the bits of an NSBitmapImageRep directly, you may find cases where the image does not draw the updated image because we now allow Quartz to cache the pixels (possibly in video memory). If you request the bitmap data pointer via -[NSBitmapImageRep getBitmapDataPlanes:] or -[NSBitmapImageRep bitmapData] then the cached information will be cleared and subsequent draws will draw the updated image. If your application just requests the bitmap data pointer once and then continuously modifys it, the image may not update.


NSImage and NSCachedImageRep caching behavior

The behavior of NSCachedImageRep has changed to improve performance when Quartz Extreme is enabled. These changes may affect your code. If the image rep is created via -[NSCachedImageRep initWithSize:depth:separate:alpha:] then after drawing, the image will be be copied from the offscreen window where it is stored and the window may be released. Do not rely on the window or the rectangle to be valid outside of NSImage -lockFocus/unlockFocus calls. If you need the window, calling -[NSCachedImageRep window] will return a valid new window and rectangle that can be used until the next time -[NSCachedImageRep draw] call is made. If the NSCachedImageRep is created via -[NSCachedImageRep: initWithWindow:rect:], after drawing, the contents of the window will be copied and may not reflect the current window contents when drawn later. If you want the imageRep to reflect the current window contents, calling -[NSCachedImageRep window] will release any cached information.


NSImageView now supports cut:, copy:, paste:, and delete: (Section added since WWDC)

For Tiger, NSImageView has acquired action methods that enable it to automatically support cut, copy, and paste behavior. This can pose a compatibility problem for some applications, however, as an NSImageView that is not the firstResponder, but is in the responder chain by virtue of being an ancestor of the firstResponder view, may consume -cut:, -copy:, -paste:, and -delete: action messages that would previously have been passed up the responder chain to a different intended recipient.

By default, NSImageView will provide the new behavior for applications built on Tiger, while suppressing it for compatibility for applications built on Panther and earlier. To allow applications to override this decision and disable or enable the new functionality on a per-instance basis, we have added a new "allowsCutCopyPaste" attribute, and the following corresponding accessor API, to NSImageView:
@interface NSImageView
- (BOOL)allowsCutCopyPaste;
- (void)setAllowsCutCopyPaste:(BOOL)flag;
@end

NSImageCell Animation Playback

Occasionally, the frames in an animaged GIF image will specify a playback duration of zero. On Panther, an animation-enabled NSImageCell plays such an animation back with no delay between frames (i.e. as fast as possible). On Tiger, NSImageCell clamps the frame duration to a minimum of 1/30 of a second, matching the way that Safari and Internet Explorer handle such GIFs.


NSImageCell NSScaleToFit and Copying

On Panther and earlier, an NSImageCell set to NSScaleToFit mode would always make a copy of its assigned image, even when the NSImageCell was sized such that the image would be displayed at exactly its original size. On Tiger, NSImageCell only makes this copy when the image is being displayed at some size other than its exact original size.


NSWorkspace Custom Icon Setting API

NSWorkspace has a new -setIcon:forFile:options: method that creates an icon from a given image and assigns it as the custom icon of a given file or folder:
- (BOOL)setIcon:(NSImage *)image forFile:(NSString *)fullPath options:(unsigned)options;
The "image" parameter specifies an arbitrary image, with or without transparency information (alpha), that will be automatically rescaled to generate the icon's representations. "fullPath" must specify an existing file or folder to which the user has write permissions. The "options" parameter is a bitwise combination of the following flags declared in NSWorkspace.h (it may be zero):
typedef unsigned int NSWorkspaceIconCreationOptions;
enum {
NSExcludeQuickDrawElementsIconCreationOption = 1 << 1,
NSExclude10_4ElementsIconCreationOption = 1 << 2
};
The option flags provide control over the kinds of representations the custom icon will contain.

The "QuickDraw" format allows for icon representations up to 128x128 pixels, and is supported on Mac OS X 10.0 through 10.4.

Mac OS X 10.4 supplements this with a new class of icon representation, designed to support higher resolutions with better storage efficiency. Finder on Mac OS X 10.4 does not yet make use of icons in this new format, but support for generating them is being provided in the -setIcon:forFile:options: API for forward compatibility. This new icon representation is safely ignored by Finder on Mac OS X 10.3, but its presence will prevent display of the file's custom icon on pre-10.3 systems, even if representations in the "QuickDraw" format are also present. Due to this compatibility issue, and to avoid needlessly consuming additional storage, it is recommended that applications that use the -setIcon:forFile:options: API suppress generation of this new representation, pending its use by a future release of the system.

NSExclude10_4ElementsIconCreationOption suppresses generation of representations in the new compressed high-resolution format. NSExcludeQuickDrawElementsIconCreationOption suppresses generation of the QuickDraw-format representations that are understood and used by Mac OS X 10.0 through 10.4. When neither flag is specified, the behavior will be to generate representations in both formats, resulting in a file or folder whose custom icon will be displayable on Mac OS X 10.3 and 10.4.


NSWorkspace (Section added since WWDC)

If the method fullPathForApplication: failed to find an application using the standard LaunchServices database, it would fall back to doing a world-search in the standard places where applications many be found. In practice though the LaunchServices database does include those places, so a brute force search through these just makes the method call considerably slower.

For apps linked on Tiger, this method will no longer do this secondary search.

The method selectFile:inFileViewerRootedAtPath: now consults a user default named "NSFileViewer", and if present, uses it as the bundle ID of the application to use as the file viewer to select the file in. If this default is not set, or there is no corresponding registered application, then Finder is used as normal. selectFile:inFileViewerRootedAtPath: is the method applications should use for "Reveal in Finder" functionality.

Since 10.0, the method getInfoForFile:application:type has been behaving differently than documented. The documentation claimed that the returned type is actually not the file type but one of a small set of predetermined identifiers indicating the kind of file; it turns out this method actually returned the type of the document. In Tiger, we continue with this preexisting behavior; the documentation will be fixed. The other documentation claim, that this method will return NO if the file doesn't exist, is true only when application info is asked for (argument to application: is non-NULL). So this method will return NO only if app info is asked for, and either the file doesn't exist, or LaunchServices does not have an application association for the document.

The NSWorkspaceDidUnmountNotification notification could be sent even for unsuccessful unmount attempts. It is now sent only if the volume is actually unmounted.


NSColor (Section added since WWDC)

Calibrated NSColors (those created with colorWithCalibratedRed:.., colorWithCalibratedHue:.., or colorWithCalibratedWhite:...) now use Quartz generic color spaces, rather than the "display" (aka "device") color spaces. For debugging purposes this behavior can be disabled with the NSUseGenericColorSpaceForCalibrated default. This is a debugging default and will be removed in a future update.

In applications, the proper way to get the device color space behavior is to create colors with colorWithDeviceRed:..., colorWithDeviceWhite:..., etc.

In many cases, as appropriate, the underlying color for NSColors representing colors used in the user interface (for instance, methods such as -[NSColor alternateSelectedControlColor]) has been changed to device color space.


NSColorSpace (Section added since WWDC)

A new class, NSColorSpace, along with new API in NSColor, enables creating NSColor instances which refer to custom color spaces, including those created with ColorSync profiles.

You can create NSColorSpace instances from CMProfileRef instances or NSDatas containing ICC profile data:
- (id)initWithICCProfileData:(NSData *)iccData;
- (id)initWithColorSyncProfile:(void * /* CMProfileRef */)prof;
- (NSData *)ICCProfileData;
- (void * /* CMProfileRef */)colorSyncProfile;
You can query the characteristics of color spaces with:
- (int)numberOfColorComponents;       // Does not include alpha
- (NSColorSpaceModel)colorSpaceModel;
- (NSString *)localizedName; // Will return nil if no localized name
NSColorSpace is intended to be toll-free bridge to CGColorSpaceRef. But this has not been implemented in Tiger.

Note that the existing "color space" concept, where a small number of predefined color spaces are identified by their names, should not be confused with this new NSColorSpace class. Different types of NSColors have traditionally been distinguished by their "color space" (represented by colorSpaceName). This color space determines the primitive accessors for the color, and in general NSColor instances with different colorspaces do not compare equal; NSColor instances in the same colorspace compare equal if all their attributes are equal.

Existing color space names supported by NSColor are NSCalibratedWhiteColorSpace, NSCalibratedRGBColorSpace, NSDeviceWhiteColorSpace, NSDeviceRGBColorSpace , NSDeviceCMYKColorSpace, NSNamedColorSpace, and NSPatternColorSpace. NSColorSpace provides class methods to return instances which correspond to the applicable predefined color space names:
+ (NSColorSpace *)genericRGBColorSpace;   // NSColorSpace corresponding to Cocoa colorspace name NSCalibratedRGBColorSpace
+ (NSColorSpace *)genericGrayColorSpace; // NSColorSpace corresponding to Cocoa colorspace name NSCalibratedWhiteColorSpace
+ (NSColorSpace *)genericCMYKColorSpace;
+ (NSColorSpace *)deviceRGBColorSpace; // NSColorSpace corresponding to Cocoa colorspace name NSDeviceRGBColorSpace
+ (NSColorSpace *)deviceGrayColorSpace; // NSColorSpace corresponding to Cocoa colorspace name NSDeviceWhiteColorSpace
+ (NSColorSpace *)deviceCMYKColorSpace; // NSColorSpace corresponding to Cocoa colorspace name NSDeviceCMYKColorSpace
In order to support custom NSColorSpaces, we enable creating NSColors with the color space name "NSCustomColorSpace". Such colors are created with:
/* Create colors with arbitrary color space. The number of components in the provided array should match
the number dictated by the specified color space, plus one for alpha (1.0 for opaque colors);
otherwise an exception will be raised. If the color space is one which cannot be used with NSColors, nil is returned.
*/
+ (NSColor *)colorWithColorSpace:(NSColorSpace *)space components:(const float *)components count:(int)numberOfComponents;
and the attributes of such colors are accessed with:
/* For colors with custom color space; get the color space and individual floating point components, including alpha.
Note that all these methods will work for other NSColors which have floating point components.
They will raise exceptions otherwise, like other existing color space-specific methods.
*/
- (NSColorSpace *)colorSpace;
- (int)numberOfComponents;
- (void)getComponents:(float *)components;
One additional API added to NSColor allows converting colors between color spaces:
/* colorUsingColorSpace: will convert existing color to a new color space and create a new color,
which will likely have different component values but look the same. It will return the same color
if the color space is already the same as the one specified. Will return nil if conversion is not possible.
*/
- (NSColor *)colorUsingColorSpace:(NSColorSpace *)space;
colorUsingColorSpace: and the three methods above work not only on NSCustomColorSpace colors, but also on other floating component-based colors. Note that colorUsingColorSpace: does not guarantee to return a NSCustomColorSpace color; for instance, if -[NSColor colorUsingColorSpace:[NSColorSpace genericRGBColorSpace]] is sent to a NSCalibratedRGBColorSpace color, the same color might very well be returned. Of course such a color will respond with NSColorSpace genericRGBColorSpace] for its colorSpace, so the result is not that unexpected.

The existing method colorUsingColorSpaceName: is still the sure way to get a color with a certain colorSpaceName for another color (or nil if the conversion is not possible).

When colors with custom color spaces are archived into old (non-keyed) archives, the assumption is that such archives still need to be read on pre-Tiger systems, so the colors are written in a pre-Tiger compatible fashion, by being converted to one of the named colorspaces, without the NSColorSpace instance. it's possible to override this behavior with the NSWriteCustomColorSpacesToOldArchives default; setting this to YES means that custom color spaces will be written to non-keyed archives, making them incompatible with pre-Tiger systems.


NSColorWell (Section added since WWDC)

Removing a NSColorWell from its window now deactivates the color well.


NSColorList (Section added since WWDC)

Non-editable color lists (identified by isEditable returning NO) now raise exceptions when an attempt is made to modify them. This is as documented.


Accessibility Changes

The following method was added:
- (BOOL)accessibilitySetOverrideValue:(id)value forAttribute:(NSString *)attribute;
It allows you to override the value of an attribute or add a new attribute to a particular UI Element --- i.e. an instance of NSObject conforming to the the NSAccessibility protocol. Previously, the only way to accomplish this was to use a custom a subclass for that UI Element and override the appropriate NSAccessibility protocol methods --- e.g. accessibilityAttributeValue.

- This method only works on objects whose class already implements the NSAccessibility protocol.

- The return value indicates if the attempt to override was successful.

- If the specified attribute is already supported by the object, the value you specified wins - i.e. for this instance it will override the attribute value that would have been returned otherwise. This is done outside the NSAccessibility protocol --- accessibilityAttributeValue won't get called when determining an overridden attribute's value.

- If the specified attribute does not exist it will be created. This is done outside the NSAccessibility protocol --- accessibilityAttributeNames will still return the old list which does not contain the new attribute.

- Once again, overriding attributes is done outside the NSAccessibility protocol. Accessing attributes using accessibilityAttributeNames and accessibilityAttributeValue will not return attributes created by the override process nor will it return their overridden values.

- Overridden attributes are not settable. I.e. accessibilitySetValue:forAttribute will never be invoked for an overridden attribute. If you override a settable attribute it will no longer be settable. What's being referred to here is the ability of the assistive app to change the attribute's value. Calling accessibilitySetOverrideValue:forAttribute again will change the overridden value.

- The method, accessibilitySetOverrideValue:forAttribute:, should not be confused with accessibilitySetValue:forAttribute:. The latter method, which is a part of the NSAccessibility protocol, is invoked when an assistive application wants to change the value of an attribute - e.g. alter the setting of a slider.

- If you need to undo the effect of using this method, call it again passing nil for the value.

- You need to ensure you invoke this method on the actual object that represents the UI Element. E.g. in the case of NSButton you'd need to use the underlying NSButtonCell. The NSButton itself is ignored by accessibility. If you're unfamiliar with this concept see the documentation for the accessibilityIsIgnored method of the NSAccessibility protocol.

- This method works on an object representing a single UI Element. When there is no object underlying a UI Element then you won't be able to use it. A common case where this is a problem is when a single object represents multiple UI Elements (e.g. NSSegmentedCell has only a single object but it provides UI Elements for each segment).
NSString *NSAccessibilityRoleDescription(NSString *role, NSString *subrole);
NSString *NSAccessibilityRoleDescriptionForUIElement(id element);
NSString *NSAccessibilityActionDescription(NSString *action);
These functions were added to help with implementing the accessibility protocol --- specifically for returning descriptions of standard roles and actions. E.g. if you implement a button widget that does not inherit from NSButton you should use NSAccessibilityRoleDescription to return a localized role description matching what is returned by standard buttons.

- You should pass nil to NSAccessibilityRoleDescription if there is no sub-role.
- NSAccessibilityRoleDescriptionForUIElement is like NSAccessibilityRoleDescription, but it queries the element to get the role and sub-role. Obviously, NSAccessibilityRoleDescription is more efficient, but this function is useful for accessorizing base classes so that they properly handle derived classes --- which may override the sub-role --- or even the role.


NSOpenGL Pixel Format Attributes

Four new pixel format attribute constants have been added to NSOpenGL.h, to expose new framebuffer options provided by CGL.
NSOpenGLPFAColorFloat         =  58, /* color buffers store floating point pixels    */
NSOpenGLPFAMultisample = 59, /* choose multisampling */
NSOpenGLPFASupersample = 60, /* choose supersampling */
NSOpenGLPFASampleAlpha = 61, /* request alpha filtering */
See the OpenGL release notes for information regarding the correct usage of these features.


Services (Section added since WWDC)

In previous releases, AppKit's deferred Services menu building until the first time an application's menu was accessed. This produced a slight delay in the first menu pull-down, while making the key equivalent shortcuts for Services menu items unusable until the Services menu had been built. Both issues have been fixed in Tiger, making key equivalents for Services menu items usable immediately after app launch, while deferring initialization of the Services menu until it is actually needed.

In Tiger, the Services facility names the communication ports that it uses based on the service provider's bundle identifier. (On previous releases, the process name was used instead.) This change in naming convention will be invisible to most service providers and clients. However, a ".service" bundle can optionally declare services that are provided by another bundle's executable, instead of containing its own executable. In such cases, the bundle that declares the service must specify the provider's bundle identifier as the service's NSPortName, to enable the Services facility to find and (if necessary) launch the provider. The provider bundle can be an ".app" bundle, or a ".service" bundle that has its own executable.


Bug Fix in Handling of NSURLPboardType (Section added since WWDC)

A bug was introduced in Mac OS 10.3 that sometimes prevented NSURLPboardType data from appearing on pasteboards provided by Carbon programs. For example, the invocation of +[NSURL URLFromPasteboard:] in the CocoaDragAndDrop example would incorrectly return nil when an image file was dragged from the Finder and dropped on one of the program's DragDropImageViews. This bug has been fixed.


Delegation and Notification warning (Section added since WWDC)

With AppKit classes which provide delegation and notification (such as NSWindow), if you explicitly register for certain notifications which are also used to send delegate messages, and then you stop being a delegate, you are unregistered for those notifications. It's not clear how this will be addressed in the future, but you should be aware of this potentially unexpected behavior.


Alert panel in Java

Bug where occurrences of "%" would disappear in alert panels in Cocoa Java applications has been fixed for applications linked on Tiger or later. A workaround for earlier applications is to double each "%" that occurs in the message string.





Notes specific to MacOS X 10.3

Aqua Refinements

Panther brings along a bunch of Aqua refinements, which are meant to enhance the look of applications compatibly, without needing any changes to the applications. The changes to user interface elements preserve layout metrics, which helps maintain compatibility. Where appropriate, return values of various APIs (for instance, NSColors) have been changed to support the new look; applications using these APIs will get the new values automatically.


Mini controls

A number of controls now support a control size NSMiniControlSize that is smaller than NSSmallControlSize. The controls that draw with this size are: radio buttons, checkboxes, push buttons, sliders, tab views, steppers, popup and pulldown menus, and comboboxes. Rounded text fields and search fields can now be sized smaller and will use a smaller rounded bezel depending on the height of the text field. NSStepperCell now supports both small and mini sizes. Mini-controls are designed to be used with LucidaGrande 9 pt as the text font.


Bindings (aka Controller Layer)

A major new feature in Cocoa for Panther is the ability to bind UI objects to model objects through controllers. This technology allows Cocoa developers to get much more application implementation done directly in Interface Builder.

The controller layer technology is based in the Model-View-Controller (MVC) design paradigm. Cocoa provides a rich set of view and model classes, but until now there was no powerful and generalized controller functionality. With the new controller layer, Cocoa developers finally have API level and Interface Builder level support for binding display values and characteristics of an application's UI to data held in the application's data model. Via the controller layer, data values and changes can be propagated live between UI elements and the application's data storage without developers having to write all of the glue code they had to before.

In Interface Builder, check out the Controllers palette for NSController classes that can be added to new and existing nibs. These controllers add functionality like selection tracking, propagating edits in the user interface, sorting, and handling input validation. The logic built into the NSUserDefaultsController, NSObjectController, and NSArrayController, which are provided to you by default, allow you to focus on designing the data model and user interface without having to write excessive amounts of glue code to get to a polished application. The controller classes provide the glue logic for you.

In Interface Builder, there is also a new inspector item: the Bindings Inspector. This inspector allows you to bind user interface elements like NSTextField, NSTableView, NSImageView, and NSTabView, to NSController instances in your nib (or controller instances to other controllers). This way you don't have to explicitly make outlet connections to your NSDocument or NSApplication file's owner. Various properties of the widgets (such as the source of a NSTextField's value, or the font and text color of the text field) can be controlled through a controller.

Relevant header files for this technology include <AppKit/NSKeyValueBinding.h>, <AppKit/NSController.h>, <AppKit/NSArrayController.h>, <AppKit/NSObjectController.h>, and <AppKit/NSUserDefaultsController.h>.

Key value coding has also been enhanced to support the bindings technology. Please refer to <Foundation/NSKeyValueCoding.h> and <Foundation/NSKeyValueObserving.h> for more information.

Note that nib files using the new controller layer (instances of NSController subclasses and bindings) can only be loaded and saved on the "10.2 and later" nib file format. Nib files in older formats have to be converted by opening them in Interface Builder and explicitly saving them in the new format.

Also, nib files created with pre-releases of Mac OS X 10.3 may contain bindings that are not legal in the GM release. Those bindings typically result in key-value coding exceptions ("undefined key") at runtime and show up in the "Parameters" section of the Bindings inspector in Interface Builder. You should disconnect the bindings manually and replace them with a new binding (which is usually obvious to pick).

Bindings for menu items and other objects that auto-validate the enabled state (like toolbar items) are ignored unless auto-validation is turned off (in the NSMenu - which can be done in Interface Builder). For example, a menu item with a value binding, but no target/action set, will always be disabled unless auto-validation is turned off manually.

NSControllers ignore the options that can be passed to the -addObserver:forKeyPath:options:context:context: method. So even if you register observers with the NSKeyValueObservingOptionNew or NSKeyValueObservingOptionOld options, you will not receive the values in the change dictionary of the -observeValueForKeyPath:ofObject:change:context: calls. This is usually not a problem, but if you rely on receiving those values, a workaround may be to observe the model objects directly.



NSAlert

We added NSAlert as a new public class. This class provides the functionality previously available only through NSPanel C-based functions, and builds flexibility on top of that functionality. For example, it is now possible to specify a custom icon and assign application specific key equivalents or return values to the NSAlert buttons. It is also possible to use more than three buttons, although this should be done only when strictly necessary. We have also added API for inclusion of a help button on the alert panel.

This API can be used for both modal panels and sheets.

Note that by default, the new return values --- NSAlertFirstButtonReturn, etc --- are easier to use and more flexible, but are not the same as the previous values --- NSAlertDefaultReturn, etc. This is an important point, as your alert return handlers will change behavior if you move your code over without paying attention to this. The following convenience method can be used for easy migration from uses of the C-based APIs, as it sets up compatible return values:
+ (NSAlert *)alertWithMessageText:(NSString *)message
defaultButton:(NSString *)defaultButton
alternateButton:(NSString *)alternateButton
otherButton:(NSString *)otherButton
informativeTextWithFormat:(NSString *)format, ...;
The return values can be customized with the setTag: methods, whose use in the alert panel is reserved for this purpose.

Note that the alert panel also reserves the use of the target and the action.

Please refer to documentation for more detailed info on this new class.


NSSpeechRecognizer / NSSpeechSynthesizer

NSSpeechRecognizer and NSSpeechSynthesizer are two new AppKit classes which provide access to Mac OS X's speech capabilities. There are examples of these classes in use in /Developer/Examples/Speech. In addition, documentation for these classes is available in the Application Kit reference.


NSShadow

NSShadow is a new AppKit class, created for the purpose of holding the parameters of a drop shadow to be used when drawing. Shadows are always drawn in base space (also known as default user space). This means that rotations, translations and so on of the current transformation matrix (the CTM) don't affect the resulting shadow. Another way to think about this is that changes to the CTM don't move or change the light source.

There are two positional parameters for a shadow, an x-offset and a y-offset of the shadow, expressed as a single NSSize, in default user space units, with positive values being up and to the right. There is one additional floating-point parameter, the blur radius, which specifies how much an object's image mask is blurred before it is composited onto the destination. A zero value means no blur, and larger values give correspondingly larger blurs, again in default user space units.

In addition, a shadow may have a color. If no color is set, then the shadow will be drawn using black with an alpha value of 1/3. If a color is set, then the shadow will be drawn using that color. Currently only colors convertible to RGBA are supported.

An NSShadow may currently be used in one of two ways. First, it may be set, like a color or a font, in which case it is applied to all drawing until another shadow is applied or until the next graphics state restore. It may also be used as the value for the new NSShadowAttributeName text attribute, in which case it will be applied to the glyphs corresponding to the characters bearing this attribute. See the section on additional text attributes for the definition of NSShadowAttributeName.


NSNib

NSNib is a new AppKit class representing a nib file. When an NSNib instance is created from a nib file, all of the data needed to instantiate the nib (the object graph as well as images and sounds that might be in the nib bundle) are read from the disk, however the nib is not instantiated until you call one of the instantiation methods. You can use NSNib to quickly reinstantiate a frequently accessed nib file, without loading the nib repeatedly from disk.



NSSegmentedControl, NSSegmentedCell

NSSegmentedControl is a new control that implements a multi-part cell or 'segment' view. Each segment can contain an image, plain label, menu, tag, and tooltip. The segments are autosized unless a specific width is set. The class provides three tracking modes: Radio-like (NSSegmentSwitchTrackingSelectOne), toggling (NSSegmentSwitchTrackingSelectAny), and push-button (NSSegmentSwitchTrackingMomentary).

NSSegmentedControl is a pass through for most of the calls to its cell. It also handles keyboard UI. NSSegmentedCell can be placed inside a matrix though usually it's inside an NSSegmentedControl.

Please refer to documentation for more info on these two classes.

(As an aside, this was the control for which we asked for naming suggestions during WWDC 2003. Many thanks for your cards and letters --- we got hundreds of suggestions!)


NSSearchField and NSSearchFieldCell

New subclasses of NSTextField and NSTextFieldCell have been added that create a standard UI for search fields like the ones in Mail, Safari, and Address Book. This includes a cancel button, search button with menu and the option to send the results while typing or when the user presses return. API for NSSearchField is minimal and forwards to NSSearchFieldCell. You should set the target and action of this control or its cell to the receiver that is interested in the search request. The border is a round text field.

Please refer to documentation for more info on these two classes.


NSSlider

A new style of slider called a circular slider (i.e. dial) is available. You can get it by setting the slider type. You then get a fixed sized slider that goes from minValue to maxValue. minValue is at the top and the value increases as you rotate clockwise to just below maxValue (e.g. if you set min = 0, max = 360, you can get to 359.999). You can show tick marks and have values limited to just the tick marks the same as a regular slider. You can only have regular and small. There is no mini version.
typedef enum {
NSLinearSlider = 0,
NSCircularSlider
} NSSliderType;
- (void)setSliderType:(NSSliderType)sliderType;
- (NSSliderType)sliderType;

New NSOpenPanel / NSSavePanel

Panther features a new user interface for open and save panels, while maintaining compatibility with the existing APIs.

Due to the changes in the panel, the following constants (view tags) are no longer supported. The last three were already marked in NSSavePanel.h as deprecated:
NSFileHandlingPanelImageButton
NSFileHandlingPanelTitleField
NSFileHandlingPanelBrowser
NSFileHandlingPanelForm
NSFileHandlingPanelHomeButton
NSFileHandlingPanelDiskButton
NSFileHandlingPanelDiskEjectButton
Added the following getter methods to match the existing setter methods:
- (id)delegate;                // - (void)setDelegate:(id)delegate;
- (BOOL)canSelectHiddenExtension;    // - (void)setCanSelectHiddenExtension:(BOOL)flag;
Added the following delegate methods to allow accessory views to keep in sync with changes in the state of the panel:
- (void)panel:(id)sender directoryDidChange:(NSString *)path;
- (void)panelSelectionDidChange:(id)sender;
Two methods have been added to allow providing a short message at the top of the panel:
- (NSString *)message;
- (void)setMessage:(NSString *)message;
In Jaguar, the methods directory, filename, and URL were usable only after the panel was dismissed --- and documented as so. This restriction has been lifted in Panther.

The use of -selectText: is deprecated. This method no longer does anything.

One known incompatibility is with applications which messaged the panel after it was released. This often worked before. If you notice that an application crashes after using the open or save panels, you can, as a debugging or temporary measure, set the NSDelayedSavePanelDeallocation user default to YES, which should avoid the problem. This default will be removed in the future.


NSSavePanel

Two methods have been added to NSSavePanel to support changing the label next to the filename edit field - which is normally labelled "Save as:":
- (NSString *)nameFieldLabel;
- (void)setNameFieldLabel:(NSString *)label;
In Jaguar we supported a single required file type with the methods setRequiredFileType and requiredFileType. We now support a list of types:
- (NSArray *)allowedFileTypes;
- (void)setAllowedFileTypes:(NSArray *)types;
The old and new calls interact as follows. Calling setRequiredFileType: is equivalent to calling setAllowedFileTypes: with an array of that one type. Calling requiredFileType will return the first element of the list of allowed types or nil if there are none. As was the case with setRequiredFileType: nil, setAllowedFileTypes:nil means allow any file type. Calling setAllowedFileTypes: with the empty array is not allowed.

In Jaguar, if a user tried to use a filename with a recognized extension that did not match the required type they were given three options: cancel, replace their extension with the required one, or use both (e.g. foo.html.txt). There was no option to use the specified extension. Apps that needed to provide this option (e.g. TextEdit and Safari, so you could use .h or a .html as an alternative to .txt) had special code to work around this limitation.

To address this there are two new methods:
- (BOOL)allowsOtherFileTypes;
- (void)setAllowsOtherFileTypes:(BOOL)flag;
As was the case in Jaguar, if the user tries to save a filename with a recognized extension that's not in the list of allowed types they will be presented with a dialog. However, if allowsOtherFileTypes is YES, then the dialog will present the option of using the extension the user specified. The default setting for allowsOtherFileTypes is NO, otherwise existing applications would start getting extensions they are not prepared to handle.



NSOpenPanel

The following new NSOpenPanel method allows modeless operation of the open panel:
- (void)beginForDirectory:(NSString *)path
file:(NSString *)name
types:(NSArray *)fileTypes
modelessDelegate:(id)delegate
didEndSelector:(SEL)didEndSelector
contextInfo:(void *)contextInfo;
Two methods have been added to allow open panels to have a "New Folder" button - which may be useful in open panels configured to allow folder selection:
- (void)setCanCreateDirectories:(BOOL)flag;
- (BOOL)canCreateDirectories;

NSMenu

NSMenuItems which have submenus now can have a target and action set and the item itself will be selectable. Calling -[NSMenuItem setSubmenu:] will no longer modify the action if it isn't NULL or @selector(submenuAction:). You can turn it off again by setting the action of the item to either NULL or @selector(submenuAction:).

Menubar items will now display an image if you set it.

NSMenuItem has some new setter/getter API to add functionality found in Carbon menus:
- (void)setAlternate:(BOOL)isAlternate;
- (BOOL)isAlternate;
This marks the item as an alternate to the previous menu item. If the item has the same key equivalent as the previous item but has different key equivalent modifiers then the items will be folded into a single visible item and the appropriate item will show while tracking the menu. You can have items with no key equivalent but different modifiers in which case, the only way to access the alternate items is via the mouse. You can have a number of items marked as alternate though if their key equivalents don't match, they may end up as separately visible items. Marking the first item as an alternate has no effect. This flag is archived.
- (void)setIndentationLevel:(int)indentationLevel;
- (int)indentationLevel;
This sets the menu item indentation level from 0 to 15. Indentation levels greater than 15 are pinned to the maximum. Values less than 0 generate an exception. The default indentation level is 0. This value is archived.

You can now specify the font when displaying a context menu using the class method:
+ (void)popUpContextMenu:(NSMenu *)menu
withEvent:(NSEvent *)event
forView:(NSView *)view
withFont:(NSFont *)font;
Passing in nil for the font uses the default font for menu.

You can pass in a custom string for a menu item by setting an attributed string. This will let you add styled text and an embedded image to a menu item string. If the text color is not set, it will be white on selection and grey on disabled. Any colored text will remain unchanged when higlighted. When you set the attributed title, the regular title is also set with the plain string value but when you clear the attributed string title, the title remains unchanged. This string is not archived in in the old nib format.
- (void)setAttributedTitle:(NSAttributedString*)string;
- (NSAttributedString*)attributedTitle;
You can set a help tag for a menu item. This includes items in the main menu bar. This string is not archived in the old nib format.
- (void)setToolTip:(NSString*)toolTip;
- (NSString*)toolTip;
You can now register for a notification when menu tracking ends even if no action is sent. Register for the notification:
NSString *NSMenuDidEndTrackingNotification;
This notification is sent for the main menu bar ([NSApp mainMenu]) and for the root menu of a popup button.

NSMenu now has a delegate that you can use to populate a menu just before it is going to be drawn and to check for key equivalents without creating a menu item. NSMenu has two new methods:
- (void)setDelegate:(id)anObject;
- (id)delegate;
This delegate is not archived in in the old nib format.

To populate the menu, the delegate should implement either:
- (void)menuNeedsUpdate:(NSMenu*)menu;
Which is called when the menu is about to be displayed at the start of a tracking session. You can change the menu by adding, removing or modifying menu items. Any new items should have the proper enable state set.

Alternatively, if population is going to take some time, you can implement a pair of methods:
- (int)numberOfItemsInMenu:(NSMenu*)menu;
- (BOOL)menu:(NSMenu*)menu updateItem:(NSMenuItem*)item atIndex:(int)index shouldCancel:(BOOL)shouldCancel;
The first method returns the number of items in the menu. If the value returned is positive, the menu is resized by either removing or adding items. If you return a negative value, the number of items is left unchanged and update method is not called. Newly created items are blank. Then the second method is repeatedly called for each item at which time, the menu title, image, etc. can be updated. If during the updating, the user does something so that the menu no longer needs to be displayed, then the shouldCancel paramter will be set to YES. You can ignore the flag or stop updating and save where you left off until the next time.

If the delegate implements the method:
- (BOOL)menuHasKeyEquivalent:(NSMenu*)menu forEvent:(NSEvent*)item target:(id*)target action:(SEL*)action;
This method allows the delegate to return the target and action for a key down event. The method should return YES if there would be a valid and enabled item for the key event and return the target and action (both of which can be nil/ NULL to invoke the menu's target and action). If this method isn't defined in the delegate, the menu will be populated to find out if any items have a matching key equivalent. The delegate should return NO if there are no items with that key equivalent or the item would be disabled.

For applications built on Panther or later, menu tracking will now run the runloop in NSEventTrackingRunLoopMode rather than NSDefaultRunLoopMode. This is consistent with tracking in other controls, and fixes a problem where an application could cause menus to get stuck onscreen by intercepting the runloop unexpectedly, eg. by putting up a modal panel while the user was tracking in a menu. This change means that timers and other runloop sources added only for NSDefaultRunLoopMode will not fire during menu tracking. If you want your timer to continue to fire during menu tracking, you should also add it to the runloop for NSEventTrackingRunLoopMode. One easy way to do this is to use kCFRunLoopCommonModes, although that also has the effect of enabling your runloop source while in NSModalPanelRunLoopMode.



Delegation and Notification

With AppKit classes which provide delegation and notification (such as NSWindow), if you explicitly register for certain notifications which are also used to send delegate messages, and then you stop being a delegate, you are unregistered for those notifications. It's not clear how this will be addressed in the future, but you should be aware of this potentially unexpected behavior.


NSColor

You can determine the current system control tint when rendering colors by using the NSColor class method.
+ (NSControlTint)currentControlTint;
This method will currently return either NSBlueControlTint or NSGraphiteControlTint.

The method selectedMenuItemColor now returns a pattern image based on the current appearance (blue or graphite) rather than a solid color.

-[NSColor set] no longer strips the transparency when the output is going to a device other than the screen (for instance, printer or file). Note that this change was introduced in Jaguar software update 10.2.3; and it is active only for applications linked on 10.2 or later. However, an app can choose to force the behavior one way or the other by registering the default NSAllowTransparencyWhenPrinting with YES or NO.

+[NSColor disabledControlTextColor] now returns 50% white rather than 53% white.

It is now possible to set the fill and stroke colors independently with NSColor, with the setFill and setStroke methods. The set method continues to set both. Going forward, all three should be treated as primitives --- that is, methods that need to be implemented by subclassers. For compatibility, there are implementations of setFill and setColor in NSColor, but they work by converting the color to RGB and filling or stroking it.

NSColor has introduced a new method which returns the standard list of alternating colors used by many applications, such as iTunes. NSTableView has added straightforward support for drawing its background using these colors. However, those implementing a custom row based controls may use this new API to draw an alternating background:
+ (NSArray *)controlAlternatingRowBackgroundColors;

NSColorPanel

The color panel can now display arbitrary copyright information for a color list. To provide copyright information, simply add the NSColorListCopyrightInfo key to your color lists strings file (eg. MyColorList.clr/English.lproj/MyColorList.strings).


NSColorWell

Prior to Panther, sometimes just clicking on a color well would cause its action to be sent. This has been fixed. NSColorWell now only sends its action if the color it's holding has indeed changed.

Calling activate: programatically now correctly shows the color panel if it is already not visible.


NSImage

The issue where rendering an NSImage into another lockFocus'ed NSImage could wipe out the graphics state is fixed.

The limitation on the size of an NSCachedImageRep and thus an NSImage that you -lockFocus on has been raised from 10,000 to 32,767. Note that you images below this size may still fail because of memory limitations.


NSImageRep

The NSImageRepRegistryDidChangeNotification now contains the actual NSImageRep class that was added or removed instead of the receiver of the message, which was usually the base NSImageRep class.


NSBitmapImageRep

You can now read and write 5 channel CMYKA images.

If an animated GIF image contains information specifying the number of times to play the GIF, a new property is available as a read-only value.
NSString* NSImageLoopCount;
If set, the extension had an explicit value specified. The loop count value will be between 0 and 65,535 with a value of 0 meaning loop forever. If the property is not present, it was not specified in the file and it will be up to the app to decide how many times to loop

PNG files now have the correct size and DPI set based in the 'pHYs' chunk in the file. This only applies to applications compiled after Jaguar (10.2.x).


NSImageView


NSImageView instances can now automatically play back animated GIF images. This functionality is controlled by the new accessor API:
- (void)setAnimates:(BOOL)flag;
- (BOOL)animates;
An NSImageView whose "animates" property is set to YES will automatically play any animated image that is assigned to it, with the timing and looping characteristics specified by the image data. When "animates" is set to NO, the NSImageView displays the first frame of the animation (consistent with the behavior on Jaguar and earlier). The default is YES for newly created NSImageView instances, NO for previously created NSImageView objects loaded from .nib files.

This setting does not affect the display of ordinary still images.

Applications wanting more control over animation playback can use NSBitmapImageRep's animated image functionality to directly access the animation's individual frames and timing data.


NSView

On Jaguar and earlier, areas of a view that are marked dirty using -setNeedsDisplayInRect: are coalesced (via an NSUnionRect() operation) into a single "dirtyRect" that the view maintains. The drawing thus scheduled is done later at the end of the run loop cycle, when invalidated areas are propagated as needed to each view's ancestors and descendants and -drawRect: is invoked for each view that needs to draw some or all of its contents.

In addition to requiring redrawing of more of a view's area than may be strictly necessary, this "coalescing" of invalidated rectangles into a single rectangle per view had the side effect of sometimes causing invalidation of otherwise "clean" views and view subtrees that happen to share a common container view (e.g. parent NSBox or NSView). An application's susceptibility to this problem depends on its UI layout and invalidation patterns.

On Panther, we maintain a more detailed representation of the invalidated parts of views that enables us to better avoid this problem. Applications automatically inherit most of the benefits of this enhancement automatically. However, there is also new API provided for implementors of NSView subclasses that wish to take advantage of the more detailed dirty area information that is now available to them.

-drawRect: remains the overridable "draw self" callback for view classes. However, the implementor of -drawRect: can now call back to self to request a more detailed description of the area to be drawn than the single NSRect parameter to -drawRect: provides. Specifically, one can request a list of rectangles that more closely approximates the area that needs drawing, via the new method:
- (void)getRectsBeingDrawn:(const NSRect **)rects count:(int *)count;
On return from this method, *rects contains a pointer to the list of NSRect values, and *count is the number of rectangles in the list. Depending on its drawing strategy, a -drawRect: implementation can inspect this list directly to determine what to draw, or it can use the convenience method:
- (BOOL)needsToDrawRect:(NSRect)aRect;
to test individual objects to be drawn one at a time against the list. -needsToDrawRect: returns YES if aRect intersects any of the rectangles in the list, NO otherwise. Use of this convenience method would be appropriate for a view that determines what to draw by simply iterating over a list or hierarchy of drawable objects. A view that can efficiently determine which of its elements needs to be drawn as a function of a given rectangle (such as a view that displays an image or images, or a regular grid of objects) may be better suited to inspecting the rect list directly. Note that the NSRect parameter that -drawRect: receives remains potentially useful as an overall bounding rectangle surrounding the area to be drawn. Intersection tests against this rectangle can be performed as a quick "trivial rejection" test, identifying objects that are clearly outside the area to be drawn. -needsToDrawRect: uses this strategy in its implementation.

To guarantee compatible drawing behavior for existing view classes, AppKit by default enforces clipping to the area that needs drawing. On Jaguar and earlier, clipping was enforced more loosely to the NSRect parameter of -drawRect:.

A view that does not want the default, AppKit-provided clipping (either because its -drawRect: implementation is very careful to draw only within the requested area, or because it sets up its own clipping) can refuse the default clipping by overriding the new -wantsDefaultClipping method to return NO:
- (BOOL)wantsDefaultClipping;
The default implementation provided by NSView returns YES. Any view that returns NO for this method is responsible for setting up its own clipping, or for otherwise insuring that it does not draw outside the requested area. The view will inherit only whatever clipping is provided by its nearest ancestor that does not itself forego the default AppKit-provided clipping.


NSView has new API that allows for hiding individual views or entire view subtrees. A hidden view remains in its superview's list of subviews and participates in autoresizing, but is not displayed and does not receive input events. This facilitates replacing the old technique of removing a view from its superview in order to "hide" it, while avoiding the loss of autoresizing functionality from which that approach has always suffered.

Hiding of views is controlled by the following new NSView methods:
- (void)setHidden:(BOOL)flag;
- (BOOL)isHidden;
- (BOOL)isHiddenOrHasHiddenAncestor;
To hide a view, you send it the message -setHidden:YES. AppKit will mark the area the view occupies in its superview as needing display, and since the view is now hidden it will not be drawn when the next drawing pass happens, so the view will disappear. Any cursor rects, tooltip rects, or tracking rects that the view owns will be disabled during the time the view is hidden.

If a view that has subviews is hidden, its subviews and their descendants will be effectively hidden as well, with the same consequences applying to their cursor/tooltip/tracking rects and ability to receive input events. Note however that -isHidden only returns YES for a view that has itself been explicitly hidden via the -setHidden: API. To ask the broader question of whether a view has become effectively hidden, whether by being explicitly hidden itself or as a consequence of having an ancestor that is now hidden, send the view an -isHiddenOrHasHiddenAncestor message.

If a -setHidden:YES message causes the view that is the window's current firstResponder to become effectively hidden, the nextValidKeyView is made the new first responder. A hidden view remains in the nextKeyView chain it was previously a part of, but is ignored for purposes of keyboard navigation.

To restore a hidden view, send it the message -setHidden:NO. Unless the view remains effectively hidden due to having a hidden ancestor view, AppKit will cause it to again be shown, and will restore any cursor rects, tooltip rects, and tracking rects that it owns.


On MacOS X versions prior to Panther, if an NSView's bounds are changed (via one of the -setBounds...: methods), the receiving view's ability to autoresize subviews is permanently disabled. An example of this behavior can be seen in TextEdit on Jaguar. If you enable "Format-->Wrap To Page" and then set the magnification to anything (even 100%), the NSClipView's bounds are set. If you then convert back to "Wrap to Window" mode, the NSClipView no longer automatically resizes its subviews -- stretching the window will reveal that the NSTextView is not automatically resized.

When bounds are set on an NSView, it creates a transform matrix to adjust view drawing. Since this transform matrix can result in a rotated view, the rules for knowing how to autoresize a subview are unknown, thus NSView simply turns off that behavior.

For applications linked on Panther, this behavior has been adjusted so that if the transform matrix is effectively returned to the "identity" matrix (no warping) autoresize subviews behavior becomes enabled again.


You can ask a view if it should become the key view based on the current keyboard UI mode (all controls/text field only). You should not override this method. Use -[NSView acceptsFirstResponder] for that case.
- (BOOL)canBecomeKeyView;

NSView / NSCell - Focus Ring Drawing API

NSView and NSCell have introduced API which allows developers to control focus ring drawing. Specifically, you can disable a view's focus ring drawing by overriding -focusRingType, or calling -setFocusRingType: with NSFocusRingTypeNone. You should only disable a view from drawing its focus ring in limited situations. Typically you might do so because you want to draw your own focus ring, or because there isn't sufficient space to display a focus ring in the default location. This setting is archived in old and new style nibs.


NSCell

If you set the object value of a cell with a class that responds to the selector -attributedStringValue, then the cell will use that method to fetch the string to draw rather than using -stringValue.

Control tint numbers for the blue (NSBlueControlTint) and graphite (NSGraphiteControlTint) tints have been added to the NSControlTint enum. You can use these in conjunction with +[NSColor currentControlTint] to determine the color to render your custom controls.

NSMiniControlSize, a new size of control that is smaller than NSSmallControlSize has been added to the NSControlSize enum. NSCell and its subclasses and NSProgressIndicator, NSScroller, and NSTabView will accept this new size.


NSButtonCell

Calling -[NSButtonCell setImageDimsWhenDisabled:] would be ignored and the image would always render dimmed. It now checks the flag and will not dim the image if the flag is set to NO.

Several new button bezel styles have been added:

NSTexturedSquareBezelStyle will get you a bezel style to use that is appropriate for textured (metal) windows.

NSDisclosureBezelStyle supports the disclosure triangle like the one in NSOutlineView. You can create the disclosure triangle by setting the button bezel style to NSDisclosureBezelStyle and the button type to NSOnOffButton.

NSHelpButtonBezelStyle has been added to provide the standard help button look.


NSTextFieldCell

New API for NSTextFieldCell allows you to specify a string to draw if the string value of the text field cell is empty and the text field cell isn't editing. This string never appears as the cell's string value but is used at the drawing stages if the actual string value is nil or @"". The plain text string will be drawn in grey. This string is not archived in the old nib format. Setting the attributed string clears out the plain text string and vice versa.
@interface NSTextFieldCell
- (void)setPlaceholderString:(NSString*)string;
- (NSString*)placeholderString;
- (void)setPlaceholderAttributedString:(NSAttributedString*)string;
- (NSAttributedString*)placeholderAttributedString;
@end

NSScrollView

Beginning with Panther, an NSScrollView can be asked to automatically hide its scrollers when they are not needed. Off by default, this behavior can be controlled via the following new API:
- (BOOL)autohidesScrollers;
- (void)setAutohidesScrollers:(BOOL)flag;
Because showing and hiding of its scrollers causes an NSScrollView to retile, use of this feature in contexts where another mechanism competes for control of the document view's size is not recommended. In particular, when a document view's enclosing NSScrollView is set to automatically hide its scrollers, the document view should not be set to autoresize. AppKit will avoid potential recursions that might arise as a result, but this may prevent scroller autohiding from working properly for such views.

A previous empty implementation of -toggleRuler: has been removed from NSScrollView. The stub implementation, which was intended to help ensure compatibility for pre-Mac OS X apps that used a deprecated ruler view class, was removed to prevent it from blocking the responder chain for apps that wished to handle this message.

When using an NSClipView within an NSScrollView (the usual configuration for using an NSClipView), developers should issue messages that control background drawing state to the NSScrollView, rather than messaging the NSClipView directly. This recommendation applies to the following messages:
- (void)setBackgroundColor:(NSColor *)color;
- (NSColor *)backgroundColor;
- (void)setDrawsBackground:(BOOL)flag;
- (BOOL)drawsBackground;
Although NSClipView provides the same set of methods, they are intended primarily for when the NSClipView is used independently of a containing NSScrollView. In the usual case, NSScrollView should be allowed to manage the background-drawing properties of its associated NSClipView.

Previous documentation did not make this clear, but note that there is only one set of background-drawing state per NSScrollView/NSClipView pair. The two objects do not maintain independent and distinct drawsBackground and backgroundColor properties; rather, NSScrollView's accessors for these properties largely defer to the associated NSClipView and allow the NSClipView to maintain the state. In Jaguar and earlier system versions, it may have appeared that an NSScrollView and its NSClipView did maintain separate state for the drawsBackground property, since NSScrollView maintained a cache of the last state it set for its NSClipView that could become out of sync if the NSClipView was sent a setDrawsBackground: message directly. This caching of state has been removed in Panther. However, it remains important to note that sending a setDrawsBackground: message with a parameter of NO to an NSScrollView, rather than directly to its enclosed NSClipView, has the added effect of sending the NSClipView a setCopiesOnScroll: message with a parameter of NO (as documented). The side effect of omitting this step is the appearance of "trails" (vestiges of previous drawing) in the document view as it is scrolled.

Thus the general recommendation is to send requests pertaining to background drawing state to an NSClipView's enclosing NSScrollView (when present) and allow the NSScrollView to manage the NSClipView's state.


NSMovie

If you explicitly create an NSMovie using the -initWithMovie: method, DisposeMovie will no longer be called on the movie when the NSMovie is deallocated. Movies created via a URL or pasteboard will still be disposed. This change will only affect applications compiled in Panther or later.


NSStatusItem

For standard status bar items, you can now set an alternate image that is displayed when the item is highlighted on mouse tracking.
- (void)setAlternateImage:(NSImage*)image;
- (NSImage*)alternateImage;
For custom view status bar items, there are two new methods to help emulate standard items. The first method will draw the menu background pattern in the status item custom view in regular or highlight pattern.
- (void)drawStatusBarBackgroundInRect:(NSRect)rect withHighlight:(BOOL)highlight;
This will display a menu under the custom status item.
- (void)popUpStatusItemMenu:(NSMenu*)menu;

NSOpenGLContext, NSOpenGLPixelFormat

NSOpenGLContext and NSOpenGLPixelFormat have new accessors that you can invoke to obtain the underlying CGL objects. You can then use the CGL API to work with these objects directly.

NSOpenGLContext provides:
- (void *)CGLContextObj;        /* cast the return value to a CGLContextObj */
Similarly, NSOpenGLPixelFormat adds the accessor:
- (void *)CGLPixelFormatObj;    /* cast the return value to a CGLPixelFormatObj */

NSWorkspace

NSWorkspace now has API for opening files and launching applications with more LS launch options. The following API has been added:
- (BOOL)launchAppWithBundleIdentifier:(NSString *)bundleIdentifier
options:(NSWorkspaceLaunchOptions)options
additionalEventParamDescriptor:(NSAppleEventDescriptor *)descriptor
launchIdentifier:(NSNumber **)identifier;
- (BOOL)openURLs:(NSArray *)urls
withAppBundleIdentifier:(NSString *)bundleIdentifier
options:(NSWorkspaceLaunchOptions)options
additionalEventParamDescriptor:(NSAppleEventDescriptor *)descriptor
launchIdentifiers:(NSArray **)identifiers;
The NSWorkspaceLaunchOptions can be found in NSWorkspace.h. In addition, NSWorkspace now has API to get the absolute path from a bundle identifier:
- (NSString *)absolutePathForAppBundleWithIdentifier:(NSString *)bundleIdentifer;
In the NSWorkspaceDidLaunchApplicationNotification, a new constant NSApplicationBundleIdentifier has been added.

NSWorkspace now provides sleep notifications. NSWorkspaceWillSleepNotification and NSWorkspaceDidWakeNotification will be sent before the machine sleeps and after the machine wakes, respectively. An observer of NSWorkspaceWillSleepNotification can delay sleep for up to 30 seconds within the handling of the notification.

We added NSWorkspaceSessionDidBecomeActiveNotification and NSWorkspaceSessionDidResignActiveNotification notifications to NSWorkspace, for applications that need to be aware of session switching (aka "fast user switching"). For example, an application may decide to disable some processing when its user session is switched out, and reenable when that session gets switched back in. Such an application should register for these notifications.

Additionally, if an application is launched in an inactive session and registers for these notifications, NSWorkspace sends the NSWorkspaceSessionDidResignActiveNotification after sending NSApplicationWillFinishLaunching and before sending NSApplicationDidFinishLaunching.



NSProgressIndicator

We have added a new larger sized spinning progress indicator that corresponds to the NSRegularControlSize. The original smaller sized indicator now corresponds to NSSmallControlSize. If your application is linked against anything before Panther, we will always return the smaller size in order to ensure binary compatibility.


NSPasteboard

NSPasteboard has automatically made "NeXT plain ascii pasteboard type" data available when Carbon applications have put 'TEXT' on a pasteboard, despite the fact that use of this type has not been publicly supported since before Mac OS 10.0. NSPasteboard no longer ensures that this type is available on pasteboards. Use NSStringPboardType instead.

In Mac OS 10.2, NSPasteboard began to automatically provide Carbon kScrapFlavorTypeUnicode ('utxt') and kScrapFlavorTypeUnicodeStyle ('ustl') data when NSRTFPboardType items were put on the pasteboard. The 'utxt' that NSPasteboard provided always began with a Unicode byte order mark (BOM), which is valid. Unfortunately, many Carbon applications were not able to properly handle the BOM. Starting with 10.2.3, the 'utxt' that NSPasteboard automatically provides no longer begins with a BOM. However, because providing the BOM is ultimately the right thing to do, we do intend to bring it back in a future release.


NSPrintInfo

In Mac OS 10.2, -[NSPrintInfo setPaperSize:] began silently ignoring any paper size that didn't match any of the paper sizes supported by the current selected printer. This bug was fixed 10.2.3.

In Mac OS 10.2, -[NSPrintInfo setPaperSize:] began silently ignoring any paper size that was the rotated variant of a paper size supported by the current selected printer. This bug was fixed 10.2.3.

The string returned by -[NSPrintInfo paperName] is usually not suitable for presenting to the user. For example, "na-letter" is very often returned when the user has specified "Letter" in an NSPageLayout. Because some applications needs to present paper names to the user, a new method has been added to NSPrintInfo:
- (NSString *)localizedPaperName;

NSDocument

-[NSDocument lastComponentOfFileName] now returns the exact same value that -displayName would. A valid value for a document's "name" property is now always returned to scripts.

Name specifiers are now the default object specifier form for documents, instead of index specifiers. Index specifiers were not appropriate in many situations because the indices of documents in an application are so likely to change during the execution of a script that manipulates documents.

-[NSDocumentController openDocumentWithContentsOfFile:display:] is now invoked with a display: argument of YES instead of NO when a Print Documents Apple event is handled. For documents that present the print panel as a sheet (document-modally) there must be a visible document window to which the sheet can be attached. For documents that present the print panel as a dialog box (application-modally) the document window provides an indication of what will be printed when the user presses the OK button in the print panel.

In previous versions of Cocoa there was no easy public way to control which window of a multiwindow document should be used as the parent window of sheets presented by that document. Because there is a common need for this, a new method has been added to NSDocument:
- (NSWindow *)windowForSheet;
In previous versions of Cocoa the numbering of untitled documents was done in such a way that it was common for unnecessarily large numbers to appear in the display names of untitled documents, e.g. "Untitled 78." NSDocument now names untitled documents in such a way that each new untitled document is given a number that is one larger than the largest number used in any currently open, untitled, document.

In previous versions of Cocoa -[NSDocument writeWithBackupToFile:ofType:saveOperation:] would fail when passed a document path string that contained colons. Because colons in POSIX-style paths are by convention the result of the user typing a slash in the user interface (either that of the app itself or the Finder), this bug would appear to the user as a failure to save documents whose names contained slashes. This has been fixed.



NSWindow

A local autorelease pool will now be installed and released during live resize for applications built on Panther or later. This allows autoreleased objects to be released during live resize, which improves memory usage but also changes the lifetime of some objects. This change is limited to applications built on Panther or later for compatibility reasons.

We have introduced a delay for dragging from the document icon button. If you click and drag on the document icon button without pausing, the window will move. If you click and pause for 1/8 second, the document icon button will become a drag source. The document icon button will be highlighted to indicate when the drag delay has been satisfied. Additionally, the restriction preventing shift-drags from the document icon button has been lifted. The shift modifier is now ignored for document icon button drags.

Functionality of -setMiniWindowImage: has been reenabled for applications linked on Panther or later. Previously, for compatibility reasons, a special default was needed to enable this.

We now have a method to allow a window delegate to specify a custom sheet location. Most customization involves just the vertical offset , but some apps also want to control the horizontal location in the window. Some apps might want to control the width of the start of the sheet effect as well. For example it might make sense to make a sheet appear as if it was originating from a button or other widget. Note that this is typically a property of the parent window, but may also be dependent on the type of sheet being presented.
@interface NSObject(NSWindowDelegate)
- (NSRect)window:(NSWindow *)window willPositionSheet:(NSWindow *)sheet usingRect:(NSRect)rect;
...
@end
This method will be sent to the window's delegate before first animating the sheet, as well as any time window is resized while sheet is attached. The returned NSRect indicates the line at which the top edge of the sheet should be attached to the window, with the origin in window coordinates and the rect.size.width indicating the width of the initial animation. If rect.size.width is wider than the sheet, the sheet will slide out . If the rect.size.width is narrower than the sheet, the sheet will genie out from the given rect. The top of the sheet will be centered within the given rect. Note that rect.size.height will not currently impact that size of the animation, but will be used to determine the center of the rect.

NSWindow now has methods that do size computations in terms of content rather than frame metrics. This allows specification of window content size which is especially useful in windows which may have a toolbar visible.
- (NSRect)frameRectForContentRect:(NSRect)contentRect
- (NSRect)contentRectForFrameRect:(NSRect)frameRect
The following methods are preferred over the frame-based methods, but the frame-based methods will continue to work if the content-based methods are not used:
- (void)setContentMaxSize:(NSSize)aSize
The above method sets the maximum size to which the receiver's contentView frame can be sized to aSize. The maximum size constraint is enforced for resizing by the user as well as for the setFrame... methods other than setFrame:display:. Takes precedence over setMaxSize:.
- (NSSize)contentMaxSize
Returns the maximum size of the receiver's contentView frame.
- (void)setContentMinSize:(NSSize)aSize
Sets the minimum size to which the receiver's contentView frame can be sized to aSize. The minimum size constraint is enforced for resizing by the user as well as for the setFrame... methods other than setFrame:display:. Takes precedence over setMinSize:.
- (NSSize)contentMinSize
Returns the minimum size of the receiver's contentView frame.
- (void)setContentAspectRatio:(NSSize )ratio
Sets the receiver's content size aspect ratio to ratio, constraining the size of its content rectangle to integral multiples of this size when the user resizes it. You can set the NSWindow's size to any ratio programmatically. Takes precedence over -setAspectRatio:.
- (NSSize)contentAspectRatio
Returns the receiver's content size aspect ratio.
- (void)setContentResizeIncrements:(NSSize)increments
Sets the receiver's resize increments to increments, constraining the width and height of the content rectangle to change by integral multiples of increments.width and increments.height when the user resizes it. You can set the NSWindow's size to any width and height programmatically. Takes precedence over -setResizeIncrements:.
- (NSSize)contentResizeIncrements
The above method returns the receiver's content resize increments.

The default time for sheet and window resize animation has been reduced, so the effects will occur more quickly. If you need to customize this animation to be slower (or faster) in a window subclass, you can override -animationResizeTime: and tweak the value obtained from the super.

We fixed -setIgnoresMouseEvents: so that it works more reliably for opaque windows that want to be transparent to mouse events, and also works for transparent windows that want to receive mouse events. In Jaguar, this API only somewhat worked for ignoring events, and did not work at all for receiving mouse events in transparent windows. This fix applies only to applications built on Panther or later.

We no longer ignore NSMiniaturizableWindowMask for nonActivating utility windows. If this styleMask is set on a nonActivating utility window in an application built on Panther or later, that window will get a minimize button. We will continue to prohibit a minimize button on other types of utility windows.

On Jaguar and previous systems, -[NSPanel orderFront:] would behave like -orderFrontRegardless:, meaning that an NSPanel would be brought to the front of its window level whether or not its owning application was active. In Panther, we have removed this distinction for non-modal NSPanels. NSPanel and NSWindow now behave the same in that orderFront: will order the panel or window behind the active window if the active window belongs to another application. For compatibility, this change applies only to applications built on Panther or later.


NSEvent

NSEvent instance methods now check that instance methods are sent to valid event types, for applications built on Panther or later. This is as documented, but has not previously been enforced. A method sent to the wrong event type will cause an exception to be raised.

The delivery rule for NSScrollWheel events has been changed so that NSScrollWheel events are sent to the view under the mouse in a key or utility window. NSScrollWheel events are dropped if the mouse is not over a key or utility window. NSScrollWheel events may still be passed up the responder chain from the receiving view.In 10.2, the window server started setting an additional device-dependent modifier flag in user input events to indicate when event coalescing is disabled. Applications that check for modifierFlags using equality without masking off the device-dependent modifierFlags first can get unexpected behavior due to this change. In order to maintain compatibility for applications built on Jaguar and earlier systems, NSEvent by default strips this device-dependent modifier flag when creating the event from a windowServer event. For applications built on Panther or later systems, this will no longer be the default behavior. In order to override NSEvent's default behavior, an application can specify a value for the user default NSDeviceDependentModifierFlags. If this default is set to NO, the device-dependent modifier flags will be stripped.

NSApplication

We now ignore the user default NSSuppressReopenAppleEvent for applications built on Panther or later. This default was originally added as a workaround for applications that weren't ready to handle the 'rapp' event, but we would not expect any current applications to need this default.

New delegate methods have been added for opening or printing multiple files at once:
@interface NSObject(NSApplicationDelegate)
...
-(void)application:(NSApplication *)app openFiles:(NSArray *)fileList
-(void)application:(NSApplication *)app printFiles:(NSArray *)fileList
...
@end
If the application delegate implements application:openFiles:, this method will be called instead of application:openFile:. Similarly, application:printFiles: will be called instead of application:printFile:.

Note that the delegate may need to present one or more sheets while handling these methods. There may be error conditions as well. It is the delegate's responsibility to notify the user through an error panel or other means if appropriate. The delegate will also be responsible for indicating failure or user cancel to the sender of the AppleEvent which caused one of these methods to be sent. In order to make replying to the AppleEvent easy, we have provided a wrapper in NSApplication:
typedef enum NSApplicationDelegateReply {
NSApplicationDelegateReplySuccess = 0,
NSApplicationDelegateReplyCancel = 1,
NSApplicationDelegateReplyFailure = 2
} NSApplicationDelegateReply;
-(void)replyToOpenOrPrint:(NSApplicationDelegateReply)reply

The delegate must call this method in order to get the kit to manage error reporting in the reply AppleEvent. If this method is called with NSApplicationDelegateReplyCancel , userCanceledErr will be set in the reply AppleEvent. If this method is called with NSApplicationDelegateReplyFailure, errAEEventFailed is set in the reply AppleEvent. The delegate may also call this method to report success, although the current implementation does not do anything in response to this. Delegates that want to manage the Apple Event reply themselves should do so using NSAppleEventManager API, and should not call this method.

In 10.3, if you pass nil to -setApplicationIconImage:, we will now set the dock icon to the default image for the application. Previously this behavior was undefined.

The AppleEvent handler for the 'quit' event will now return userCanceledErr if there is an application modal panel open. -applicationShouldTerminate will not be invoked on the application delegate in this case. One consequence of this change is that an application with a modal panel open will now be reported as canceling logout. On previous versions of the system, such an application would block logout until the modal panel was dismissed.

System Preferences allows users to add applications to the Startup Items list, and to launch those applications hidden. In Panther, and since the WWDC seed, NSApplication now enforces the hidden-on-launch setting by adding windows ordered onscreen during application launch to a hidden list. This includes any non-modal windows ordered onscreen up to and including the time when -applicationDidFinishLaunching: is sent. Windows ordered onscreen after this time will cause the application to get unhidden. In order to maintain binary compatibility with applications that may not expect this behavior, the hidden-on-launch setting is only enforced for applications built on Panther or later. Applications built on earlier systems will probably see the old behavior, where a window shown during launch will temporarily flash onscreen, then get hidden with the app.

A new API -[NSApplication orderFrontCharacterPalette:] is added.

AppKit now adds "Special Characters..." menu item to the "Edit" menu if an item with -orderFrontCharacterPalette: action is not found in the menu. To prevent the behavior, you can set the NSDisabledCharacterPaletteMenuItem preference setting to YES.



NSBox

We no longer archive or unarchive the contentView for an NSBoxSeparator for keyed coding. The contentView has no purpose for an NSBoxSeparator.

In 10.3 we defer sizing the NSBox after unarchiving until it is first drawn. This means that subviews that resize based on the box size can get resized later than they did on Jaguar and previous systems.

10.3 provides a new appearance for NSBox. Box types of NSBoxPrimary and NSBoxSecondary will both draw with an indented look, enhanced but similar in some ways to how NSBoxSecondary boxes drew on Jaguar. If your application needs a simple outline look, you should use an NSBoxType of NSBoxOldStyle and an NSBorderType of NSLineBorder. It is recommended that you use this only for boxes without titles.


Dragging

A local autorelease pool is now installed and released around NSDraggingDestination method invocations, for applications built on Panther or later. This allows autoreleased objects to be released during dragging, which improves memory usage but also changes the lifetime of some objects. This change is limited to applications built on Panther or later for compatibility reasons.

A bug in generating the drag image would result in a flipped image (isFlipped: set) appearing unflipped if the source was cached (i.e. not a bitmap). The image will now appear in the correct orientation. This change will only affect applications compiled in Panther or later.


NSCursor

Applications built on Panther or later can now use cursor images of sizes other than 16x16. The cursor size will be defined by the size of the image passed to -initWithImage:hotSpot: or -initWithImage:foregroundColorHint:backgroundColorHint:hotSpot:. Applications can check for an NSAppKitVersionNumber greater than or equal to NSAppKitVersionNumberWithCursorSizeSupport to determine whether this support is available.

NSCursor now provides new cursors for alias and copy drags, as well as slightly modified cursors for vertical and horizontal resize. We've also added additional public cursors:
+ (NSCursor *)pointingHandCursor;
+ (NSCursor *)closedHandCursor;
+ (NSCursor *)openHandCursor;
+ (NSCursor *)resizeLeftCursor;
+ (NSCursor *)resizeRightCursor;
+ (NSCursor *)resizeLeftRightCursor;
+ (NSCursor *)resizeUpCursor;
+ (NSCursor *)resizeDownCursor;
+ (NSCursor *)resizeUpDownCursor;
+ (NSCursor *)crosshairCursor;
+ (NSCursor *)disappearingItemCursor;

NSGraphics

The following functions have been added to disable and reenable all drawing to the screen by the calling context:
void NSDisableScreenUpdates(void);
Prevents drawing for all windows belonging to the calling process from being flushed to the screen. This function permits operations on multiple windows to appear atomic to the user, and is particularly useful for parent and child windows. Note that this function should be used with care for short operations only as the system will only allow updates to be disabled for a short time (currently one second) before automatically reenabling updates.
void NSEnableScreenUpdates(void);
Reenables drawing for all windows belonging to the calling process. Calls to NSDisableScreenUpdates must be matched with calls to NSEnableScreenUpdates. Multiple calls stack.



NSHelpManager

We now have methods to support help lookup other than from the Help Menu. The following methods support navigation to a specific location in a help book, or querying a help book for a string when a Help button is pressed, for example.
- (void)openHelpAnchor:(NSString *)anchor inBook:(NSString *)book
Find and display the text at the given anchor location in the given book. The argument should be a localized help book name or nil --- if nil, all installed help books are searched. This is a wrapper for AHRegisterHelpBook (which is called only once to register the help book specified in the application's main bundle) and AHLookupAnchor.
- (void)findString:(NSString *)query inBook:(NSString *)book
Search for the given query in the given book. The argument should be a localized help book name or nil --- if nil, all installed help books are searched. This is a wrapper for AHRegisterHelpBook (which is called only once to register the help book specified in the application's main bundle) and AHSearch.


Accessibility

The AXWindows attribute of the application UI Element now returns the list of window in z-order, front-to-back.

AXWindows now support a raise action which simulates bringing a window forward by clicking on its title bar.
NSAccessibilityRaiseAction
AXWindows now support subroles to distinguish different types of windows.
NSAccessibilityStandardWindowSubrole
NSAccessibilityDialogSubrole
NSAccessibilitySystemDialogSubrole
NSAccessibilityUnknownSubrole
NSAccessibilityFloatingWindowSubrole
NSAccessibilitySystemFloatingWindowSubrole
AXWindow's title attribute used to include the path name for windows with represented files (as per [NSWindow title]). This has now been fixed so they only return the displayed title. You should access the represented file with the AXDocument attribute.

AXWindows now support attributes to identify their default and cancel buttons.
NSAccessibilityDefaultButtonAttribute
NSAccessibilityCancelButtonAttribute
Windows now emit notifications when AXDrawers and AXSheets are created.
NSAccessibilityDrawerCreatedNotification
NSAccessibilitySheetCreatedNotification
AXScrollBars now expose their arrows and page up/down areas as AXButtons with subroles.
NSAccessibilityIncrementArrowSubrole
NSAccessibilityDecrementArrowSubrole
NSAccessibilityIncrementPageSubrole
NSAccessibilityDecrementPageSubrole

10.3 provides more powerful text accessibility features. A number of new attributes were added for AXTextAreas and AXTextFields in order to return more detailed information about the text within. These additions are documented in the Accessibility APIs.


Two new methods were added to the Cocoa accessibility protocol in order to support parameterized attributes --- one to return a list of them and one to return their values.
- (NSArray *)accessibilityParameterizedAttributeNames;
- (id)accessibilityAttributeValue:(NSString *)attribute forParameter:(id)parameter;
A new function was added so you can raise an error if the parameter is the wrong type or has an illegal value. This function can also be used to raise an error if an attempt is made to set an attribute's value with the wrong type or an illegal value.
void NSAccessibilityRaiseBadArgumentException(id element, NSString *attribute, id value);
The following constants have been removed:
NSAccessibilityWindowTitleRole
NSAccessibilityWindowProxyRole
NSAccessibilityRelevanceIndicatorRole
The following constants have been added:
NSAccessibilityCancelAction


NSSound

NSSound uses CoreAudio to play most files in 10.3, but uses QuickTime to play some sound formats, like iTunes Music Store sounds and general URLs. In 10.2, NSSound primarily used QuickTime to play sounds.

Unfortunately, the underlying requirements and limitations of the underlying frameworks bleed through to NSSound, and affect developers trying to use NSSound to play sounds on multiple threads. If your app is single-threaded, or you only play sounds on the main thread, then you need not worry about these issues.

Since QuickTime requires the run loop to be run for sound (or movies) to continue playing, NSSound requires this as well. By "run loop", what is meant is the run loop on the thread which starts the sound playing. For Cocoa applications, this is not a big deal for sounds played on the main thread, as Cocoa apps normally let the AppKit handle running the run loop on the main thread. Also, since QuickTime is not particularly thread-safe, it is not recommended to play sounds (or movies) on multiple threads.

The delegate -sound:didFinishPlaying: is also sent on the main thread, when it is automatically triggered by the sound finishing. However, when -stop is called it is sent immediately on that thread calling -stop. So unless one does all sound playing and stopping on the main thread, one cannot assume that the delegate method is being called on the main thread.

Doing all sound playing on the main thread will also insulate you better from future changes in the multi-threaded behavior of NSSound and the underlying frameworks.


Playing an NSSound more than once simultaneously

A given NSSound instance can only be playing, or not. If a sound is playing, and -play is called, nothing will happen. This was true in 10.2, and is still true in 10.3, and will be true in the future. However, a different NSSound instance can play the same sound file. So if you want the same sound potentially played overlapping, make a copy of the NSSound and play the copy:
[[[mySound copy] autorelease] play];

NSBrowser

NSBrowser scrolling now provides immediate and continuous feedback. This of course provides a much better user experience, but also required some major changes. In particular, the internal view hierarchy had to change. So, if you have subclasses of NSBrowser or NSBrowserCell which depend on the internal view hierarchy, you should be on the look out for incompatibilities. In Panther, continuous scrolling is on by default for all applications. However, if necessary, you can revert to the old implementation by setting the NSBrowserSupportsContinuousScrolling default to NO. The old, non-continuous scrolling implementation remains for compatibility and will be removed in the next release.

The implementation of continuous scrolling has the following implications:

The internal view hierarchy has changed. However, the public API dealing in browser geometry still returns values in browser coordinates. For example, -titleFrameOfColumn:, and -frameOfColumn: return rectangles relative to the NSBrowser.

Overriding NSBrowser's -drawRect: method is no longer very useful (due to the new view hierarchy).

The -drawTitleOfColumn:inRect: method's 'inRect' parameter is in the coordinates of the view that draws the titles. You do not need to do any conversion in order to draw.

The size of a browser's columns may now vary by one pixel. This happens when the available space for column tilling cannot be evenly divided by the number of visible columns.

The usage of the delegate methods -browserWillScroll: and -browserDidScroll: require some explanation. The non-continuous implementation sent these delegate messages each time a new column became visible. However, with continuous scrolling, partial columns can now be visible during scrolling. The continuous scrolling implementation uses these methods before and after scrolling has completed. So, these methods are no longer visibility notifications.

The use of -scrollViaScroller: is deprecated. This method no longer does anything when using the continuous scrolling implementation

The use of -updateScroller is deprecated. This method no longer does anything when using the continuous scrolling implementation.

Note, one can check for the support of the continuous scrolling by comparing the appkit version number against NSAppKitVersionNumberWithContinuousScrollingBrowser.


NSBrowser now provides three different column resizing modes: NSBrowserNoColumnResizing, NSBrowserAutoColumnResizing, and NSBrowserUserColumnResizing. For many applications auto resizing will be sufficient. In auto resizing, each column is given the same width, which is calculated using a combinination of the minimum column width, and max visible columns setting. Some applicaitons may decide that they know how to size columns better than NSBrowser, or the user, and will choose to use no column resizing. In NSBrowserNoColumnResizing mode, the developer explicitly will determine the width of every column, and neither the user, nor NSBrowser will change the assigned width. Finally, NSBrowser allows a column resizing mode that allows developers to choose the initial column width, while allowing users the option to resize the columns much like they can in the Finder.

NSBrowsers user column resizing mode (NSBrowserUserColumnResizing), and no column resizing mode (NSBrowserNoColumnResizing) deserve a little further explanation since they are new. Essentially auto column resizing is the same as the old browser behavior. A number of new methods and delegate methods have been introduced to support the two new modes. First of all, there is new API to specify the type of column resizing:
typedef enum _NSBrowserColumnResizingType {
NSBrowserNoColumnResizing = 0, /* Column sizes are fixed and set by developer. */
NSBrowserAutoColumnResizing = 1, /* No user resizing. Columns grow as window grows. */
NSBrowserUserColumnResizing = 2 /* Columns fixed as window grows. User can resize. */
} NSBrowserColumnResizingType;
- (void)setColumnResizingType:(NSBrowserColumnResizingType)columnResizingType;
- (NSBrowserColumnResizingType)columnResizingType;
- (void)setPrefersAllColumnUserResizing:(BOOL)prefersAllColumnResizing;
- (BOOL)prefersAllColumnUserResizing;
Next, there is new API and delegate methods that allow you to declare the initial size for a newly visited browser column. There is also API that allows you to directly set the width of a column:
- (void)setWidth:(float)columnWidth ofColumn:(int)columnIndex;
- (float)widthOfColumn:(int)column;
@interface NSObject (NSBrowserDelegate)
- (float)browser:(NSBrowser *)browser
shouldSizeColumn:(int)columnIndex
forUserResize:(BOOL)forUserResize
toWidth:(float)suggestedWidth;
- (float)browser:(NSBrowser *)browser
sizeToFitWidthOfColumn:(int)columnIndex;
@end
Finally, there is new API to do simple column width persistence, and new notifications that allow you to do more sophisticated path based column width persistence:
- (void)setColumnsAutosaveName:(NSString *)name;
- (NSString *)columnsAutosaveName;
+ (void)removeSavedColumnsWithAutosaveName:(NSString *)name;
APPKIT_EXTERN NSString * NSBrowserColumnConfigurationDidChangeNotification AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER;
// Object : browser - the browser whose column sizes need to be persisted.
// UserInfo : No user info.
@interface NSObject (NSBrowserDelegate)
- (void)browserColumnConfigurationDidChange:(NSNotification *)notification;
@end

NSBrowser no longer loses focus during a reloadColumn:, or loadColumnZero.

Performing a selectAll: on a matrix in a browser now works. In the past, only "loaded" cells would be part of the selection when finished. This has been fixed. So, as part of a select all, cells are loaded if necessary.

NSBrowsers double and single click action are not sent until the browsers sliding animation has completed.

The existing -maxVisibleColumn/setMaxVisibleColumns: are ignored and not applicable for browser using NSBrowserNoColumnResizing, or NSBrowserUserColumnResizing types.

The use of -displayColumn: is deprecated. Use setNeedsDisplayInRect: with the appropriate rectangle instead.

The use of displayAllColumns is deprecated. Use setNeedsDisplay, or setNeedsDisplayInRect: with an appropriate rectangle instead.




NSBrowserCell

Leaf browser cells now draw their contents all the way to the end of their row's visible area. In Jaguar and prior releases, the contents stopped where the branch indicator would have been if the cell was not a leaf.

For applications linked on or after Panther, NSBrowserCell's -cellSize calculation will now include the width required for its image and arrow if necessary. Applications linked on earlier systems will still have the old buggy behavior. The old behavior returned a value that was too small because the image, arrow, and a spacing were not figured into the desired cell size.


NSComboBox

NSComboBox cell no longer allows users to click its button when disabled.

NSComboBox can now be displayed without the "border" around its button. It is often useful in NSTableView for instance to not display the button border. To configure this setting, use the new API:
- (void)setButtonBordered:(BOOL)flag;
- (BOOL)isButtonBordered;

NSOutlineVIew

NSOutlineView's disclosure triangle now animates.

-(void)collapseItem:(id)item collapseChildren:(BOOL)flag now actually will collapse children if asked to do so
-(id)outlineView:(NSOutlineView *)olv itemForPersistentObject:(id)object no longer raises an exception if a nil value is returned.

Sorting UI - see NSTableView's "Sorting UI" information.



NSTabView

For applications linked against Panther and later, -tabViewItems now returns an immutable array. It has always been declared to return an immutable array, but until now has always returned a mutable array.

When an NSTabViewItem is removed from a tab view, its state will now always be set to NSBackgroundTab.


NSTableView

NSTableView now implements the NSUserInterfaceValidations protocol, and specifically validates the selectAll: target/action method.

NSTableView and NSOutlineView draw a keyboard focus indication if there is enough room to display one. The focus indication is drawn either around the enclosing scroll view, or around the table and header (when not enclosed in a scroll view). If there is not enough room to display most of the focus ring, then none is shown.

In Jaguar and prior releases, -selectedCell would only returned a non-nil value when editing text via a double click. Now, in apps linked against Panther or later, selectedCell always returns the cell that was clicked, regardless of what type of cell was clicked. So, while the user clicks on a NSSliderCell and drags the mouse around, the table will return the slider cell that is being manipulated from -selectedCell. This will allow you to query the current slider value from your action method.

For applications linked against Panther or later, NSTableView now returns YES from -needsPanelToBecomeKey. This means that users can navigate to a table using the <tab> key. Previously, unless you subclassed NSTableView and overrode this method, the user would have to be in "Any Controls" keyboard navigation mode to be able to <tab> to a table. If the table is in a panel that returnes YES from becomesKeyOnlyIfNeeded, then this needsPanelToBecomeKey to become key returns YES only if the panel is currently key. By doing this, clicks in such panels will not force the panel to become key. Note that double clicking in a text cell to start editing will force the panel to become key.

NSTableHeaderView now waits until mouse up to select or deselect a column. If the user has clicked in an previously unselected header, the header will be drawn in a pressed (NSOnState) but not selected state until the user mouses up in the header cell. Among other things, this means that a column doesn't have to be selected in order to be moved by a user.

NSTableView supports autohiding its scrollers. However, using a customized corner view with autohiding scrollers on is currently not recommended because the corner view will disappear at the same time the vertical scroller disappears .

NSTableHeaderCell has fixed a bug with the positioning of its indicator image. Prior to Panther, indicator images set using NSTableView's -setIndicatorImage:inTableColumn: resulted in an image that was drawn too low, such that only the top half of the image was visible. NSTableHeaderCell now properly centers the image. The image was also allowed to be too close to the header text. This was fixed by decreasing the width available to the header text. Both fixes apply to applications linked on Panther and later only.

NSTableView's last table column now draws its column highlight all the way to the end. All other columns leave a small gap between column highlights (if there is an inter-cell spacing) by ending their column highlight short of the actual end of the column.

NSTableView now caches the results from numberOfRowsInTableView: when possible. In the past, NSTableView messaged the data source for this value an inordinate amount of times .


NSTableView now supports drawing its background using the standard alternating colors used by many applications, such as iTunes. The new flags are saved in old and new style keyed archiver. This feature can be adopted at IB design time, or at runtime using the following new API:
- (void)setUsesAlternatingRowBackgroundColors:(BOOL)useAlternatingRowColors;
- (BOOL)usesAlternatingRowBackgroundColors;
NSTableView now exposes an override point to allow complete background coloring customization. To customize background drawing, override the following new API:
- (void)drawBackgroundInClipRect:(NSRect)clipRect;

NSTableView now provides index set based selection API, using the new NSIndexSet class:
- (void)selectColumnIndexes:(NSIndexSet *)indexes byExtendingSelection:(BOOL)extend;
- (void)selectRowIndexes:(NSIndexSet *)indexes byExtendingSelection:(BOOL)extend;
- (NSIndexSet *)selectedColumnIndexes;
- (NSIndexSet *)selectedRowIndexes;

The following non-index set based APIs have been deprecated:
- (void)selectColumn:(int)column byExtendingSelection:(BOOL)extend;
- (void)selectRow:(int)row byExtendingSelection:(BOOL)extend;
- (NSEnumerator *)selectedColumnEnumerator;
- (NSEnumerator *)selectedRowEnumerator;

NSTableView now provides a general sorting API on NSTableView which will make sorting UI implementation easier. The API consists of methods that will allow NSTableView to automatically manage the sorting UI and to create sort descriptors to be used by the data source when the user clicks on a table header. The data will not be automatically sorted, but the data source will be told when it should resort its data.

A table column is considered sortable if it it has a sortDescriptorPrototype. A sort descriptor contains three pieces of information: a key, selector, and sort direction. When used as a column prototype, the sort descriptor defines several interesting things. First, the presence of a sort descriptor prototype indicates the column is sortable. Next the prototype's sort direction defines the initial sorting direction. Finally, the key and selector definition provide a convenient location to store information the data source will need when sorting. Note that it is not required that the key match the table columns identifier, however the key must be unique from the key used by other columns.
// NSTableColumn.h
- (void)setSortDescriptorPrototype:(NSSortDescriptor *)sortDescriptor;
- (NSSortDescriptor *)sortDescriptorPrototype;
Given a table with sortable columns, NSTableView will automatically manage the sorting UI. NSTableView automatically displays a sort indicator for the primary sort column. To accomplish this, NSTableView maintains a list of sort descriptors. The first sort descriptor in the list defines the primary sort key, selector, and direction. The array of sort descriptors is archived. Also, the array of sort descriptors will persist along with other column information if an autosave name is set.
// NSTableView.h
- (void)setSortDescriptors:(NSArray *)array;
- (NSArray *)sortDescriptors;
@end
Now, since NSTableView doesn't manage the data, it can't sort if for you. However, it does tell you when the data needs to be re-sorted.
@interface NSObject (NSTableDataSource)
- (void)tableView:(NSTableView *)tableView sortDescriptorsDidChange:(NSArray *)oldDescriptors;
@end
@interface NSObject (NSOutlineDataSource)
- (void)outlineView:(NSOutlineView *)outlineView sortDescriptorsDidChange:(NSArray *)oldDescriptors;
@end
NSTableHeaderCell provides override points for customizing the sorting UI look. -drawSortIndicatorWithFrame:inView:ascending:priority: is called for each column that participates in sorting. However, by default NSTableHeaderCell only draws an indicator if priority is 0, that is, if the column is the primary sort column.
@interface NSTableHeaderCell
- (void)drawSortIndicatorWithFrame:(NSRect)cellFrame inView:(NSView *)controlView ascending:(BOOL)ascending priority:(int)priority;
- (NSRect)sortIndicatorRectForBounds:(NSRect)theRect;
@end

NSTableView grid drawing now works properly. However, many nibs have been unknowingly saved with the "draws grid" flag checked in IB. To avoid having recompiled apps accidentally showing grids, the old flag is completely ignored. This is not a big deal since the flag was never used anyway. Proper archiving of the grid drawing flag are only supported by the keyed archiver.

NSTableView now respects the alpha in grid colors.

NSTableView now allows much finer grid drawing control. In addition to drawing a full grid, you may now choose to draw vertical or horizontal grid lines only using the -setGridStyleMask:(unsigned int)gridStyleMask API. Only nibs saved with the keyed archiver will save this information. Note that, with the addition of this API, the old grid drawing API becomes redundant, and has therefore been deprecated.

These methods have been deprecated:
- (void)setDrawsGrid:(BOOL)drawGrid;
- (BOOL)drawsGrid;

NSTableColumn

Although NSTableColumn has conformed to NSCoding for a long time, it now finally declares this conformance in its header.


NSToolbar

Toolbar items which have an NSBox as their view used to force the box to use NSNoBorder in the toolbar, and NSLineBorder in the customization palette. NSToolbarItem no longer does this.


NSToolbar now supports displaying the selected toolbar item in toolbars that are used as mode switchers (e.g. inspectors, color panel, etc...). The toolbar delegate must implement -toolbarSelectableItemIdentifiers to indicate which type of toolbar items can be used to indicate mode. Note that, since toolbars are very dynamic in their content, item selection is maintained by "item identifier", not by item. NSToolbar maintains selection automatically for image type items. However the selected item identifier can be explicitly set to anything by calling -setSelectedItemIdentifier:.


"Poof" Animation

A new function, NSShowAnimationEffect() has been added to allow developers to use the same item removal animation used by controls such as toolbar and the dock. Although the API is designed as a general mechanism for system animation effects, currently only one animation exists. To run an animation, you specify the type of animation you want, the size and location of the animation, and optional callback information. The NSAnimationEffectDisappearingItemDefault effect is meant to indicate removal from a list, without actually destroying the underlying item. For example, removal from the dock does not delete the file. The NSAnimationEffectPoof simply shows a disappearing cloud, poof effect. Currently NSAnimationEffectDisappearingItemDefault and NSAnimationEffectPoof are the same effect, but they are not guaranteed to be the same in the future.


ToolTips

Tooltips that are too large now automatically wrap. This can be disabled by setting the default NSToolTipAutoWrappingDisabled to YES.

Prior to Panther, if a user activated a window by clicking in an area with tooltips no tooltips would be displayed until the user moved the mouse out of the tooltip area and then back in that area. This bug has been fixed.


Prior to Mac OS X 10.3, tooltips only displayed in the key window of the active application. In Mac OS X 10.3, tooltips now always display in the active application. However, for performance reasons tooltips are not active if your application is inactive (or in the background). This is for performance reasons. If tooltips are enabled, moving the mouse over a background app's window will cause the app to do work, which may degrade the system performance. To allow your application to use tooltips even when it is the background application, use the following new API:


@interface NSWindow (NSToolTip)
- (void)setAllowsToolTipsWhenApplicationIsInactive:(BOOL)allowWhenInactive;
- (BOOL)allowsToolTipsWhenApplicationIsInactive;
@end

NSBezierPath

The bug causing -appendBezierPathWithGlyphs:count:inFont: and -appendBezierPathWithPackedGlyphs: mehods not to advance after each glyph was fixed. Also, -appendBezierPathWithGlyphs:count:inFont: no longer modifies the current graphics context (it doesn't call -[NSFont set]). This means it is the caller's responsibility to use fonts with matrix to flip when the target view is flipped.

Finally, these methods now move the current point to the last glyph's baseline position. In other words, successive calls to these methods correctly aligns glyphs on the baseline.



NSGraphicsContext

+saveGraphicsState and -saveGraphicsState no longer save the current path.


NSFormatter

The NSFormatter's partial validation methods are now correctly invoked at the end of a marked text session. If the formatter returns NO in this situation and consequently -[NSTextView shouldChangeTextInRange:replacementString:] returns NO, the field editor still removes the range of text in the current marked session.



Text Document Reading/Writing

A method has been added to NSMutableAttributedString:
- (BOOL)readFromData:(NSData *)data
options:(NSDictionary *)options
documentAttributes:(NSDictionary **)dict;
which parallels the existing readFromURL:options:documentAttributes:, but operates on the contents of the file as data rather than requiring a file to exist. The readFromURL:options:documentAttributes: method is usually preferable if a file already does exist, since it can make use of filesystem attributes such as extension and type to help determine the type of the file, but the new method is more convenient if a file does not already exist, or if for some reason one does not wish filesystem attributes to be taken into consideration. In Java, the constructor for NSAttributedString and NSMutableAttributedString that takes two arguments, an NSData and an NSMutableDictionary, will now use this method to construct an attributed string from data of any format the text system can read.

A new text document type is now supported,
NSString *NSDocFormatTextDocumentType;
corresponding to Microsoft Word documents. These documents may be read using any of the existing NSAttributedString/NSMutableAttributedString methods for reading text documents. They may be also be read and written using the new NSAttributedString methods
- (id)initWithDocFormat:(NSData *)data documentAttributes:(NSDictionary **)dict;
- (NSData *)docFormatFromRange:(NSRange)range documentAttributes:(NSDictionary *)dict;
Currently the two most recent major revisions of the format are supported for reading (corresponding roughly to Word 6 and later), but only the most recent major revision is supported for writing. Note that this does not imply support for all of the features expressible in such a document, any more than the existing RTF reading implies support for all features potentially expressible in RTF. In fact, Cocoa's feature support for doc format reading and writing is very nearly equivalent to its support for RTF reading and writing. This support has, however, been enhanced to include the features described in the sections on additional text attributes and additional paragraph style features.

The "Converted" key in the document properties dictionary has been reinterpreted, in a way that is consistent with its previous definition. Previously positive values specified that the document had been converted to the format specified by a filter service, and all other values specified that the file was originally in the format specified. That is still the case, but now there is a distinction between negative values and 0 (or not present). Now negative values imply that the file was originally in the format specified, but that the conversion from the format specified to NSAttributedString may have been lossy. In addition there are two new document property keys: "DefaultTabInterval", which specifies the document-wide default tab interval for the document. and "BackgroundColor", which specifies the document-wide background color for pages.


There is a new NSAttributedString HTML import method,
- (id)initWithHTML:(NSData *)data options:(NSDictionary *)options documentAttributes:(NSDictionary **)dict;
that takes an options dictionary like those used by other similar AppKit text import methods. In addition to the relevant existing options keys (BaseURL and CharacterEncoding) there are some new options keys intended specifically for HTML import, that may be used with this method and with the other methods that take an options dictionary:

@"UseWebKit" (NSNumber containing int; if present and positive, forces WebKit-based HTML importing be used; behavior if this is turned on may differ from that of HTML import in Mac OS X 10.2 and before, particularly for tables)
@"TextEncodingName" (NSString containing the name, IANA or otherwise, of a text encoding to be used if the encoding cannot be determined from the document; mutually exclusive with CharacterEncoding)
@"Timeout" (NSNumber containing float; time in seconds to wait for a document to finish loading; if not present or not positive, a default timeout will be used)
@"WebPreferences" (WebPreferences; if WebKit-based HTML importing is used, specifies a WebPreferences object; if not present, a default set of preferences will be used)
@"WebResourceLoadDelegate" (NSObject; if WebKit-based HTML importing is used, specifies an object to serve as the WebResourceLoadDelegate; if not present, a default delegate will be used that will permit the loading of subsidiary resources but will not respond to authentication challenges)


Images in SimpleText files are now centered, like they were in SimpleText. Also, images in Japanese SimpleText files are now displayed.

Methods to load files in NSAttributedString will now try to recognize XML files and use the character encoding specific in the header of the XML if they can. This is just a heuristic, not always applicable; it will not be used if the caller provides an explicit encoding.

Links (as represented by NSLinkAttributeName and stored as NSString, or more preferably as NSURL) in text are now read from and written to RTF files. The format used is compatible with one used by Word.



Text Attributes

The following attributes have been added to the text system:
NSString *NSStrokeWidthAttributeName; /* float, in % of font size, default 0: no stroke; pos for stroke alone; neg for stroke+fill */
NSString *NSStrokeColorAttributeName; /* NSColor, default nil: same as foreground color */
NSString *NSShadowAttributeName; /* NSShadow, default nil: no shadow */
NSString *NSObliquenessAttributeName; /* float; shear to be applied to glyphs, default 0 (no shear) */
NSString *NSExpansionAttributeName; /* float; log of expansion factor to be applied to glyphs, default 0 (no expansion) */
NSString *NSCursorAttributeName; /* NSCursor, default IBeamCursor */
NSString *NSToolTipAttributeName; /* NSString, default nil: no tooltip */
NSString *NSUnderlineColorAttributeName; /* NSColor, default nil: same as foreground color */
NSString *NSStrikethroughStyleAttributeName; /* int, default 0: no strikethrough */
NSString *NSStrikethroughColorAttributeName; /* NSColor, default nil: same as foreground color */
Quartz allows text to be drawn as outlines (stroke) or solids (fill), or both, potentially in different colors. Previously Cocoa text drawing has always used fill drawing. The new stroke width and stroke color attributes allow stroke drawing as well. The actual stroke width used is the absolute value of the attribute; stroke drawing alone is indicated by a positive value, stroke and fill by a negative value, and fill alone by a zero value or the lack of the attribute. The value is given as a percentage of font point size so that a single value can have a consistent meaning across multiple fonts. The foreground color continues to be used as the fill color. If a separate stroke color is specified, it will be used as the stroke color; otherwise the foreground color is used for both stroke and fill.

The previous values for NSUnderlineStyle, NSNoUnderlineStyle = 0 or NSSingleUnderlineStyle = 1, or'ed with NSUnderlineByWordMask for underlining by word and/or NSUnderlineStrikethroughMask for strikethroughs, are now deprecated (except for NSUnderlineByWordMask), although they are still defined and supported for compatibility. The new values for NSUnderlineStyle are
enum {
NSUnderlineStyleNone = 0x00,
NSUnderlineStyleSingle = 0x01,
NSUnderlineStyleThick = 0x02,
NSUnderlineStyleDouble = 0x09
};
or'ed with one of the following:
enum {
NSUnderlinePatternSolid = 0x0000,
NSUnderlinePatternDot = 0x0100,
NSUnderlinePatternDash = 0x0200,
NSUnderlinePatternDashDot = 0x0300,
NSUnderlinePatternDashDotDot = 0x0400
};
and with NSUnderlineByWordMask if underlining is to be by word. The color of the underline is specified by NSUnderlineColorAttributeName; if no color is specified, the foreground color is used.

Instead of an NSUnderlineStrikethroughMask in the underline style, there is now a separate NSStrikethroughStyleAttributeName attribute, with the same set of values as NSUnderlineStyleAttributeName. There is also an NSStrikethroughColorAttributeName to control the strikethrough color; if no color is specified, the foreground color is used. Correspondingly, there are now two additional NSLayoutManager methods to draw the strikethroughs, parallel to the two existing underline methods:
- (void)drawStrikethroughForGlyphRange:(NSRange)glyphRange
strikethroughType:(int)underlineVal
baselineOffset:(float)baselineOffset
lineFragmentRect:(NSRect)lineRect
lineFragmentGlyphRange:(NSRange)lineGlyphRange
containerOrigin:(NSPoint)containerOrigin;
- (void)strikethroughGlyphRange:(NSRange)glyphRange
strikethroughType:(int)underlineVal
lineFragmentRect:(NSRect)lineRect
lineFragmentGlyphRange:(NSRange)lineGlyphRange
containerOrigin:(NSPoint)containerOrigin;
There are three one-parameter subgroups of the affine group that are clearly useful as transformations of text laid out on baselines such as the Cocoa text system provides. Dilatation has always been available in the form of the font's point size. The two remaining subgroups are (a) a one-dimensional dilatation, corresponding to compression or expansion of the text along the x-axis; and (b) a shear transformation, specifically the one that leaves the baseline of the text unaltered, but makes the remainder of the text either more or less oblique. These are expressed by the attributes NSExpansionAttributeName and NSObliquenessAttributeName respectively. The values are chosen so that both appear as additive groups, in particular so that 0 represents the identity.

The new NSCursorAttributeName and NSToolTipAttributeName attributes support the ability to change the cursor and display tooltips over portions of text in a text view. Like NSLinkAttributeName, these attributes usually will be set programmatically rather than by user action. In addition, NSTextView now has a delegate method,
- (NSString *)textView:(NSTextView *)textView
willDisplayToolTip:(NSString *)tooltip
forCharacterAtIndex:(unsigned)charIndex;
which will be called if NSToolTipAttributeName attribute is actually set on the characters over which the mouse is hovering, and which allows the delegate to modify (by returning a different string) or suppress (by returning nil) the display of the tooltip at the time of display.

Note that cursors and tooltips are active only if the text view is selectable. Non-selectable text views do not process any mouse events. If for some reason it is necessary to disallow user selection change in a text view that handles mouse events, this can be achieved by making the text view selectable but implementing the delegate method textView:willChangeSelectionFromCharacterRange:toCharacterRange: to disallow selection changes.


Temporary and Link Text Attributes

Some text attributes affect glyph generation and/or layout, and some do not. The latter include color attributes of all types, underlines and strikethroughs, cursors, and tooltips. Only the latter are candidates for temporary attributes on the layout manager, or for selected or marked text attribute on the text view. Other attributes will be ignored if they are used as temporary, selected, or marked text attributes. In addition, there is a new set of attributes on the text view, the link text attributes. These will be applied--that is, to be added, overriding only existing values of the same attributes--to link text when drawing to the screen, just as the selected and marked text attributes are applied to selected and marked text. The following methods have been added to NSTextView:
- (void)setLinkTextAttributes:(NSDictionary *)attributeDictionary;
- (NSDictionary *)linkTextAttributes;
For pre-Panther applications the default value is an empty dictionary, while for Panther-linked applications the default is blue text with an underline, and an appropriate cursor. Note that linkTextAttributes is intended for those who wish all links to acquire certain attributes; applications wishing to decorate different links differently can use temporary attributes for this purpose, which will take precedence over the corresponding link text attributes.


Additional Text UI

The text ruler accessory has changed significantly, and several additional panels have been added to give users additional control over character and paragraph attributes. In support of this, a method has been added to NSTextView:
- (void)changeAttributes:(id)sender;
somewhat parallel to the existing changeFont:. When changeAttributes: is called, it invokes a new method
- (NSDictionary *)convertAttributes:(NSDictionary *)attributes;
on the sender of changeAttributes:, successively with each set of attributes used in the current selected range (or in the typing attributes). The sender then makes whatever attribute changes it desires and return a converted dictionary. The sender is expected to leave untouched attributes it is not interested in. This can also be used for custom controls that might be supplied for various text attributes. In addition, NSTextView now provides a notification and corresponding delegate method when typing attributes change, whether or not text has changed as a result--for example, when "Bold" is selected but there is a zero-length selection. This can be used to keep track of all changes to text attributes:
NSString *NSTextViewDidChangeTypingAttributesNotification;
- (void)textViewDidChangeTypingAttributes:(NSNotification *)notification;
There are also two new methods on NSFontManager:
- (void)orderFrontStylesPanel:(id)sender;
- (void)setSelectedAttributes:(NSDictionary *)attributes isMultiple:(BOOL)flag;
The latter is used by NSTextView to notify the new panels when attributes change. The former is an action method the main panel to be displayed, intended for use with menu items.


NSTextStorage

NSTextStorage was failing to unregister its delegate for notifications while being deallocated. It now sets its delegate to nil in dealloc, which deregisters the delegate as observer.


NSTextView

Several miscellaneous additional methods have also been added to NSTextView. To support an "Outline" font menu item, an action method has been added:
- (void)outline:(id)sender;
Like underline:, it will add the relevant attribute if absent, or remove it if not. Also like underline:, it uses a default value for the relevant attribute--in this case, the attribute is NSStrokeWidthAttributeName, and the default value is 3.0.

To support changing the base directionality of a paragraph--for example, for Hebrew or Arabic--an action method has been added:
- (void)toggleBaseWritingDirection:(id)sender;
An additional action method has been added
- (void)changeDocumentBackgroundColor:(id)sender;
to support user changes of the background color of the text view (and all of its sibling text views). The term "document" is added to the name to distinguish this background color from the text background color, as specified by NSBackgroundColorAttributeName, which applies only to particular ranges of text and not to the document as a whole. This background color is the view's backgroundColor, and it is the background color that would be expected to be used in connection with the "BackgroundColor" document property described above. Since not all text views will wish to allow users to change the document background color, there is a flag (default value NO) that determines whether this is allowed, and methods to set and get its value:
- (void)setAllowsDocumentBackgroundColorChange:(BOOL)flag;
- (BOOL)allowsDocumentBackgroundColorChange;
A new drawing method has been added,
- (void)drawViewBackgroundInRect:(NSRect)rect;
which is called when the text view intends to draw its background, and which subclasses can override to perform additional drawing behind the text of an NSTextView.

An NSTextView now has a default paragraph style, which clients may set, and which it will use when no paragraph style is explicitly specified, and which the user will be able to revert to using the ruler. If no client sets this, then [NSParagraphStyle defaultParagraphStyle] will be used.
- (NSParagraphStyle *)defaultParagraphStyle;
- (void)setDefaultParagraphStyle:(NSParagraphStyle *)paragraphStyle;
In combination with the new defaultTabStop property of the NSParagraphStyle, this provides a simple way of providing default tab stops throughout a document--for example, in a plain text document.


We now have a standard find panel, usable by NSTextView. The following two methods in NSTextView allow enabling/disabling the standard find panel:
- (void)setUsesFindPanel:(BOOL)flag;
- (BOOL)usesFindPanel;
By default newly created NSTextViews in IB have this attribute set, but for compatibility reasons programmatically created or already archived instances do not.

The following method is the generic action method for the find panel and find menu:
- (void)performFindPanelAction:(id)sender;
This is added to NSTextView, and can be overridden by views which want to provide their own find panel. The actual operation is determined by the tag values such as NSFindPanelActionNext, etc; see the enum NSFindPanelAction.

In 10.3 the find panel is meant for NSTextView use only, as there are no methods to provide the degree of reusability that would be needed for other clients to hook up to it.

When loading custom user-specific key binding dictionaries from ~/Library/KeyBindings, the text system no longer looks for a DefaultKeyBinding.plist file, just DefaultKeyBinding.dict. The former is not mentioned in the documentation, but some older user setups might have that file instead of the preferred DefaultKeyBinding.dict.


Text Completion

NSTextView now has a default implementation of the first responder method complete:, which is bound by default to option-Escape and also F5. The intent of complete: is to provide users with a choice of completions for the word currently being typed. By default the text system will not invoke complete: automatically, but rather only if the user presses a key to which it is bound; however, clients of the text system may obtain autocompletion by invoking complete: programmatically when desired. NSTextView will supply a default list of completions taken from a variety of sources, but clients may replace or modify this list via subclass or delegate methods.

The NSTextView implementation of
- (void)complete:(id)sender;
will in turn call the NSTextView methods (overridable by subclasses)
- (NSRange)rangeForUserCompletion;
- (NSArray *)completionsForPartialWordRange:(NSRange)charRange indexOfSelectedItem:(int *)index;
to get the range of the partial word to be completed, the list of potential completions, and optionally the index in that list of the item to be initially selected. This last method will in turn call the NSTextView delegate method (if implemented)
- (NSArray *)textView:(NSTextView *)text
completions:(NSArray *)words
forPartialWordRange:(NSRange)charRange
indexOfSelectedItem:(int *)index;
which will allow the delegate to modify, override, or suppress the list of completions. For text fields and other controls, we will define an NSControl delegate method
- (NSArray *)control:(NSControl *)control
textView:(NSTextView *)
completions:(NSArray *)words
forPartialWordRange:(NSRange)charRange
indexOfSelectedItem:(int *)index;
to allow the control's delegate the same freedom to control the list of completions used by the field editor. The actual means of presentation of the potential completions will be determined by the NSTextView complete: method; those who wish to modify it will need to override complete:.

The array used in all of these cases is an array of strings, in the order in which they should be presented, representing complete words that the user might be trying to type when starting by typing the partial word at the given range. The results are complete words rather than just the remainder of the word, in case completion requires some slight modification of what the user has already typed--for example, the addition of an accent, or a change in capitalization. Developers might also use this to support abbreviations that would complete into words that didn't necessarily start with the characters of the abbreviation. The index argument allows delegates or subclasses to return by reference an index specifying which of the completions should be selected initially (default is 0, and -1 means no initial selection).

As the user moves through the list of completions, the following NSTextView method will be called with the currently selected completion:
- (void)insertCompletion:(NSString *)word
forPartialWordRange:(NSRange)charRange
movement:(int)movement
isFinal:(BOOL)final;
for which the default implementation will insert the proposed completion into the text in the appropriate place. The final flag will be NO as long as the completion is still tentative, and YES when the user ultimately picks one completion definitively. The movement argument will describe the action the user took to change the current selected completion; it will take its values from the NSTextMovement enum defined in NSText.h, which already is used for a similar purpose in describing movements through tables, matrixes, and forms. An additional NSCancelTextMovement value has been added, to cover the case in which the user cancels completion and the original partial word is restored. In addition, the movement value 0 has been given the additional name NSOtherTextMovement, which more clearly reflects both its previous and current usage--namely, to cover any case not covered by the other values in this enum. Subclasses will be able to override insertCompletion:forPartialWordRange:movement:isFinal: either to modify the default behavior of the method, or else to perform some additional action, possibly depending on whether and by what means the user has exited the completion process.

One potential source of completions is the spellchecker. In support of this, an additional method has been added to NSSpellChecker:
- (NSArray *)completionsForPartialWordRange:(NSRange)range
inString:(NSString *)string
language:(NSString *)language
inSpellDocumentWithTag:(int)tag;
and the corresponding NSSpellServer delegate method to be implemented in the spellchecker itself:
- (NSArray *)spellServer:(NSSpellServer *)sender
suggestCompletionsForPartialWordRange:(NSRange)range
inString:(NSString *)string
language:(NSString *)language;

Before Panther, text undo/redo operations did not cause NSTextView to send its textView:shouldChangeTextInRange:replacementString: delegate method and its NSTextDidChange notification. On Panther, that delegate method and notification will be send for text undo and redo. However, for compatibility reasons, this will occur only for executables that have been linked on Panther or later system versions.


Bidirectional-savvy Movement

NSResponder methods containing "forward" and "backward" in their names are not the most appropriate choices for arrow key movement in bidirectional text. In Panther, there are some additional methods described by "right" and "left" that are used for binding arrow key movement, and that move in the appropriate visual direction whether it is actually forward or backward in the logical order of the text.
- (void)moveWordRight:(id)sender;
- (void)moveWordLeft:(id)sender;
- (void)moveRightAndModifySelection:(id)sender;
- (void)moveLeftAndModifySelection:(id)sender;
- (void)moveWordRightAndModifySelection:(id)sender;
- (void)moveWordLeftAndModifySelection:(id)sender;


Paragraph Range

We now clearly make a distinction between paragraph separators and line separators. Accordingly, Foundation has new methods on NSString to find paragraph boundaries:
- (void)getParagraphStart:(unsigned *)startPtr
end:(unsigned *)parEndPtr
contentsEnd:(unsigned *)contentsEndPtr
forRange:(NSRange)range;
- (NSRange)paragraphRangeForRange:(NSRange)range;
which parallel the existing line range equivalents, but which take into account only paragraph separators and not all line separators. In usages related to the Cocoa text system, one should decide whether a line range or a paragraph range is the appropriate quantity, and choose from these methods accordingly. The range of an NSParagraphStyle attribute, for example, will always be a paragraph range; likewise, triple-clicking will select a paragraph range.


NSGlyphGenerator

A new public class NSGlyphGenerator has been added to the Cocoa Text System. The class performs the initial nominal glyph generation phase in the layout process. The class communicates via the NSGlyphStorage protocol. An instance of classes conforming to the protocol is NSLayoutManager.

NSGlyphGenerator now generates NSControlGlyph for all characters in the Unicode General Category C* and U200B (ZERO WIDTH SPACE).


NSATSTypesetter

A new public NSTypesetter concrete subclass, NSATSTypesetter, is added in the Cocoa Text System. The class performs the actually layout (determines glyph positions) phase in the layout process.

The NSATSTypesetter API is categorized into 3 groups.

The first group of interfaces declared in the base @interface section itself is divided into 2 sections --- The layout primitives and NSLayoutManager interface.

The layout primitives are usually invoked by NSLayoutManager interface methods internally. In the meantime, the primitives can be called by 3rd party layout engines directly to perform typesetting without using NSLayoutManager.

The second group of API is declared in the NSLayoutPhaseInterface category. It lists all the override points for subclasses in order to tweak various aspects of typesetting behavior.

The third set is declared in the NSGlyphStorageInterface category. The methods are primitives for interfacing with the glyph storage such as NSLayoutManager.

You can override all the methods listed in here to interface with custom glyph storages. Then, calling -layoutParagraphAtPoint: drives each paragraph typesetting session.

The behavior for U00AD (SOFT HYPHEN) now conforms to the Unicode version 4.0 specification.


NSParagraphStyle

The following methods have been added to NSParagraphStyle:
- (float)lineHeightMultiple;
- (void)setLineHeightMultiple:(float)aFloat;
- (float)paragraphSpacingBefore;
- (void)setParagraphSpacingBefore:(float)aFloat;
- (float)defaultTabInterval;
- (void)setDefaultTabInterval:(float)aFloat;
The default values for the lineHeightMultiple, paragraphSpacingBefore, and defaultTabInterval will all be 0.0, which will give the previous behavior. If lineHeightMultiple is positive, then the natural line height will be multiplied by lineHeightMultiple, but still bounded by minimumLineHeight and maximumLineHeight as usual. This means that a lineHeightMultiple of 2.0 will give double spacing. The space between paragraphs will now be the previous paragraph's paragraphSpacing plus the following paragraph's paragraphSpacingBefore. If defaultTabInterval is positive, then tabs after the last explicitly specified tab stop will give effectively left tabs at integral multiples of defaultTabInterval from the left edge of the page.

The remaining three NSLineBreakMode settings, NSLineBreakByTruncatingHead, NSLineBreakByTruncatingTail, and NSLineBreakByTruncatingMiddle, are implemented in NSATSTypesetter (NSTypesetterBehavior > NSTypesetterOriginalBehavior). You can use these to draw truncated strings and text more efficiently that the usual multi-step process (compute size, truncate, then draw).

removeTabStop: used to remove all isEqual: tabstop instances, contrary to documentation. In Panther, for apps linked against Panther or later, it only removes the first isEqual: instance.


NSTextTab

NSTextTab concept is now further generalized. An NSTextTab instance now conceptually consists of two mandatory attributes (tab location and text alignment inside the tab column) and optional attributes represented by a dictionary. This generalization provides increased flexibility in tab settings.


NSResponder

Two new keybinding methods are defined in NSResponder. -deleteBackwardByDecomposingPreviousCharacter: is bound to control-Delete by default. -cancelOperation: is bound to Escape. Also, as described above, we've now added option-Escape as the main default binding for complete:.

NSFontDescriptor

The class NSFontDescriptor has been added, which provides a mechanism to describe a font, which can later be turned into an NSFont object. The main part of the font descriptor is a dictionary of attributes. All attributes are optional. You can currently create a font descriptor using the following methods.
- (id)initWithFontAttributes:(NSDictionary *)attributes;
+ (NSFontDescriptor *)fontDescriptorWithFontAttributes:(NSDictionary *)attributes;
+ fontDescriptorWithName:(NSString *)fontName size:(float)size;
The current attributes that can be defined are
NSFontFamilyAttribute
NSFontNameAttribute
NSFontFaceAttribute
NSFontSizeAttribute
NSFontVisibleNameAttribute
NSFontColorAttribute

NSFont

A new API +[NSFont systemFontSizeForControlSize:] is added.

The font fallback list now respects the user's language precedence list.

NSFont now always flips the text matrix regerdless of its own transformation matrix when set for the focused view that has flipped coordinate system. It used to do so only when the font's transformation matrix was identity. To restore the old behavior, you can set the NSOnlyFlipFontsWithIdentityMatrix preference value to YES.

The -screenFont method now consistently returns the screen font regardless of the receiver's size. The logic to instantiate screen fonts over their printer font counterparts is moved to -[NSLayoutManager substituteFontForFont:]. The new logic in NSLayoutManager now always chooses printer fonts for non-identity matrix fonts.

The default size for the palette font is changed from 10.0 to 11.0 to follow the Aqua specification.

The menu bar font may be different from the font used for menu items. This method returns the font. Passing in 0 for the fontSize returns the default menu bar font.
+ (NSFont *)menuBarFontOfSize:(float)fontSize;
You can get a font descriptor from an NSFont using the following method:
- (NSFontDescriptor *)fontDescriptor;

NSFontManager

The following methods have been added to NSFontManager to support font collection management. You can create and remove collections using the following two methods:
- (BOOL)addCollection:(NSString *)collectionName options:(int)collectionOptions;
- (BOOL)removeCollection:(NSString *)collectionName;
Currently, the only option available for font collections is the
NSFontCollectionApplicationOnlyMask
You can get an array of the current collection names using
- (NSArray *)collectionNames;
and you can get an array of the descriptors in a given collection using
- (NSArray *)fontDescriptorsInCollection:(NSString *)collectionNames;
To add and remove font descriptors from a collection, use the following methods.
- (void)addFontDescriptors:(NSArray *)descriptors  toCollection:(NSString *)collectionName;
- (void)removeFontDescriptor:(NSFontDescriptor *)descriptor fromCollection:(NSString *)collection;
You can get an array of NSFont objects matching a particular font descriptor using the following method. The current implementation only recognizes NSFontFamilyAttribute, NSFontNameAttribute, and NSFontFaceAttribute. All other attributes are ignored.
-(NSArray *) availableFontNamesMatchingFontDescriptor: (NSFontDescriptor *) descriptor;

NSFontPanel

The font collections have migrated to a format that uses the NSFontDescriptor class. The collections now live in ~/Library/FontCollections with the .collection extension. Changes made to the collections using previous versions of AppKit will affect the .fcache files and will not be synched with the new collections. If you want to re-sync them, you will have to remove all the .collection files in the font collections folder and re-launch the font panel.

Font Panel now has the ability to hide elements that are not applicable by having the target respond to a method validating the font panel modes. The following mode masks are defined:
enum {
NSFontPanelFaceModeMask = 1 << 0,
NSFontPanelSizeModeMask = 1 << 1,
NSFontPanelCollectionModeMask = 1 << 2,
...
NSFontPanelStandardModesMask = 0xFFFF, // standard modes, including those added in the future but expected to work by default
NSFontPanelAllModesMask = 0xFFFFFFFF // all modes, including some added in the future but are not enabled by default
};
If the target wants anything other than the standard mode mask, it must respond to this method.
- (unsigned int)validModesForFontPanel:(NSFontPanel *)fontPanel;

Handling of the "Saving" Parameter of the Quit Application Apple Event

In previous versions of Cocoa, the AppKit's default handling of the standard Quit Application Apple event (and the scripting Standard Suite's Quit command) ignored the "saving" parameter, behaving as if its value were always "ask." New behavior has been introduced so that the value of the "saving" parameter is correctly interpreted.

In applications that have an NSDocumentController:

If the value of the "saving" parameter is "yes," each open, modified, document will be sent a -saveDocumentWithDelegate:didSaveSelector:contextInfo: message. If the document is saved successfully, the NSDocument will then be sent a -close message, and the next open, modified, document will be processed. If any document cannot be saved because of an error or user cancellation, the application will not be quit.

For "no," the application will be sent a -terminate: message. The application will not send its delegate an -applicationShouldTerminate: message though.

For "ask," the NSDocumentController will be sent a -reviewUnsavedDocumentsWithAlertTitle:cancellable:delegate:didReviewAllSelector:contextInfo: message, as in previous versions of Cocoa.

In applications that have no NSDocumentController:

If the value of the "saving" parameter is "ask" or "yes," the delegate will be sent an -applicationShouldTerminate:, as in previous versions of Cocoa. Delegates that need to know the exact value of the "saving" parameter can use the the new -[NSAppleEventManager currentAppleEvent] method.

For "no," the application will be sent a -terminate: message. The application will not send its delegate an -applicationShouldTerminate: message though.


Forwarding of Close and Print Scripting Commands Sent to Windows

In previous versions of Cocoa Scripting, close and print commands sent to windows were mishandled. Now, -[NSWindow(NSScripting) handleCloseScriptCommand:] will forward the close command to the corresponding document, if there is a corresponding document and the window is the main window of the document. Otherwise, the window will send itself a -performClose message if it has a close box.

Likewise, [NSWindow(NSScripting) handlePrintScriptCommand:] now forwards the print command to the corresponding document if it is the main window of that document. Otherwise, the window will send itself a -print message.


Obsolete Symbols

NSAlphaEqualToData and NSAlphaAlwaysOne (with values of 1 and 2, respectively) have been removed from NSGraphics.h as they have not been used since before 10.0.





Notes specific to MacOS X 10.2.5

Jaguar update 10.2.5 contains a new AppKit which addresses a few bugs, including crashers with PNG files containing ColorSync data, corrupt GIF files, and a rare freed memory error in target applications when using accessibility APIs. In addition bug 3163914, causing new style nibs with custom subclasses to cause runtime problems, has also been fixed.

The version number for the AppKit in 10.2.5 is 663.10. A warning though, in very unlikely case you need to distinguish the 10.2.5 version of AppKit --- if treated as a floating point number, 663.10 ends up being less than 663.6.


Notes specific to MacOS X 10.2.3

A new AppKit is present in 10.2.3. Some of the changes in the 10.2.3 AppKit are listed below.

In case you need to differentiate the two AppKit versions at runtime: The version number for the 10.2.3 AppKit is 663.6. Version number for the 10.2 AppKit was 663. There are no API or header file changes in the AppKit between the 10.2 and 10.2.3.


NSBezierPath

10.2 bug with appendBezierPathWithGlyphs:count:inFont: putting all glyphs on top of each other has been fixed in 10.2.3.


NSColor

NSColor now preserves transparency when printing.


NSColorPanel

The color panel can now display arbitrary copyright information for a color list. To provide copyright information, simply add the NSColorListCopyrightInfo key to your color lists strings file (eg. MyColorList.clr/English.lproj/MyColorList.strings).

The list color picker was updated with several new user features, including a search field.


NSImage

An exception calling a non-existent method clearAvailableData during incremental image loading has been fixed.

JPEG 6 files saved with Graphic Converter could hang or crash applications; this bug has been fixed.

Animated GIF images now work better.


NSOutlineView

A possible crash in calling reloadItem:reloadChildren: during editing is fixed in 10.2.3.


NSTableView

A bug was introduced in 10.2 where calling abortEditing while a cell was being edited could cause a crash. 10.2.3 fixes this problem.

Performance problem with selecting multiple items in a tableview using the keyboard is fixed in 10.2.3.


NSToolbar

Disappearing-menu-items regression in toolbar items with menuFormRepresentations has been fixed in 10.2.3.


NSWindow

Appearance of the top-left corner buttons in metal window titles has changed in accordance with HI spec. Cocoa and Carbon applications which use the framework provided metallic window support will automatically get the new look.


Printing

10.2 regression with programmatically setting custom paper size has been fixed.


Text

Negative tail indents and large negative kerning values now work properly in the new (10.2) typesetter. These fixes make the new typesetter more compatible with the old one.

We have temporarily turned off the inclusion of the Unicode BOM character (0xFEFF) in the Carbon pasteboard type for Unicode text ('utxt') as this was causing problems in a few applications which failed to deal with this properly. It is our intent to reenable this in a future release.

When dragging text, the i-beam cursor will now properly change to an arrow when the drag starts.

A crash in saving as RTF text documents containing glyphs with no corresponding Unicode characters has been fixed in 10.2.3. Such glyphs are usually entered using the character palette.




Notes specific to MacOS X 10.2

Backward Compatibility

One backward compatibility mechanism that is occasionally used in the frameworks is to check for the version of the system an application was built against, and if an older system, modify the behavior to be more compatible. This is done in cases where bad incompatibility problems are predicted or discovered. Typically we detect where an application was built by looking at the version of Cocoa, AppKit, or Foundation frameworks the application was linked against. Thus, as a result of relinking your application on 10.2, you might notice different behaviors, some of which might cause incompatibilities. In these cases because the application is being rebuilt, we expect you to address these issues at the same time as well.

In some cases, we provide defaults (preferences) settings which can be used to get the old or new behavior, independent of what system an application was built against. Often these preferences are provided for debugging purposes only; in some cases the preferences can be used to globally modify the behavior of an application by registering the values (do it somewhere very early, with -[NSUserDefaults registerDefaults]).

These cases are described in these and in Foundation release notes.


Marking new APIs in headers

New APIs in headers are marked with the construct:
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_2
...
#endif
The basic definitions for these come from AvailabilityMacros.h, a new standard system header. This is included from Cocoa.h, AppKit.h, and Foundation.h imports.

If you do nothing, MAC_OS_X_VERSION_MAX_ALLOWED is assumed to be MAC_OS_X_VERSION_10_2. However, to see which post-10.1 symbols your app is referencing (for instance), you can build specifying the compiler flag:
-DMAC_OS_X_VERSION_MAX_ALLOWED=MAC_OS_X_VERSION_10_1
and watch for the warnings.


Runtime Version Check

There are several ways to check for new features provided by the Cocoa frameworks at runtime. One is to look for a given new class or method dynamically, and not use it if not there. Another is to use the global variable NSAppKitVersionNumber (or, in Foundation, NSFoundationVersionNumber):
APPKIT_EXTERN double NSAppKitVersionNumber;
#define NSAppKitVersionNumber10_0 577
#define NSAppKitVersionNumber10_1 620
One typical use of this is to floor() the value, and check against the values provided in NSApplication.h:
if (floor(NSAppKitVersionNumber) <= NSAppKitVersionNumber10_0) {
    /* On a 10.0.x or earlier system */
} else if (floor(NSAppKitVersionNumber) <= NSAppKitVersionNumber10_1) {
    /* On a 10.1 - 10.1.x system */
} else {
    /* 10.2 or later system */
}
Special cases or situations for version checking are also discussed in the release notes as appropriate. For instance some individual headers may also declare the versions numbers for NSAppKitVersionNumber where some bug fix or functionality is available in a given update, for example:
#define NSAppKitVersionWithSuchAndSuchBadBugFix 582.1

Accessibility

Cocoa's standard user interface elements (e.g. NSButton, NSView, ...) support the newly added Accessibility APIs which allow assistive applications, e.g. a screen reader, to examine and interact with the user interfaces of other applications.

If your application has custom user interface elements you will need to implement the NSAccessibility protocol in order from them to work with the Accessibility APIs. Documentation for this protocol can be found in /Developer/Documentation/Cocoa/TasksAndConcepts/ProgrammingTopics/Accessibility.


Cocoa in Carbon

It is now possible to show Cocoa windows in Carbon applications. When Cocoa is loaded into the Carbon application, NSApplicationLoad() should be called to initialize the Cocoa environment properly. Further documentation for this will be available on the Apple Developer Documentation site.

Font panel and color panel are also available to Carbon applications using Carbon APIs. Cocoa will be loaded dynamically into a Carbon app when needed.


Keyed Archiving

Cocoa now has support for keyed archiving, which allows saving object attributes with keys. This provides a lot more flexibility in the archives, allowing changing the list of attributes an object writes out while maintaining compatibility. Please see the Foundation release notes for details.

Some options you have are:

- If your application writes object archives, and you need those archives to be readable on 10.1, stick to the old format; otherwise it's better to switch over to the new format.
- If your objects implement archiving, and you want them to take advantage of the flexibility and compatibility features provided by keyed archiving, augment your initWithCoder: and encodeWithCoder: methods to implement keyed archiving. Note that objects which do not implement keyed archiving can still be written to keyed archives, but they won't take advantage of the new features.
- When saving nib files in Interface Builder, you can choose to use 10.1 format, 10.2 format, or both. The 10.1 format is compatible with pre-10.2 systems, however, due to compatibility concerns, 10.1 archives are not capable of storing many of the new features added in 10.2 and the future. Saving nib files using the "both" formats allows you to put both the new and old archives into the same .nib wrapper, choosing and opening the appropriate one at runtime. When editing such a nib file, both archives are edited and saved simultaneously.



Localized View of File System

10.2 supports localized view of the file system, which allows users to see names of file system elements (applications, bundles, document packages, and folders) in their primary language, assuming localizations have been provided. This is accomplished without actually localizing the file system names. This feature is discussed further in the System Overview document (near the end of the "How the File System Is Organized" section).

In a Cocoa application, there are several things to be aware of:

- Paths used for file system access are never localized; so the localized versions of file system entity names should only be used when being displayed to the user. For instance, don't use the localized display name when saving paths in preferences or elsewhere.

- Use -[NSFileManager displayNameAtPath:] or the new -[NSFileManager componentsToDisplayForPath:] methods to obtain human-readable names for file system entities, if you display any.

- If you wish your application name to be localizable, add CFBundleDisplayName to your Info.plist. The value of this should be the same as the file system name (without the file extension). This can then be localized via InfoPlist.strings. For performance reasons, it's best not to include this key in Info.plist if your app name is not going to be localized. Note that the existing CFBundleName key (and localization) is still used for the localized "short" application name displayed in the menu bar and about box.

- If you wish to create a folder which has localized names: (1) Provide your folder with the file extension ".localized", and mark the extension as hidden; (2) create a flat bundle called ".localized" in the folder (flat bundles are basically folders with no Contents or Resources subfolders); (3) supply strings files with names such as en.strings, containing "NonlocalizedName" = "Localized name". Example:
Release Notes For My App.localized/
    .localized/
        en.strings (contains "Release Notes For My App" = "Localized name"; )
        ja.strings

Text

Text documents which have a Mac OS type of 'TEXT' and which have no 'styl' resource fork information will be returned as "plain text" from various AppKit attributed string methods which open text files. These used to be identified as rich text. Note that 'TEXT' files with 'styl' info is considered rich text, even if the whole range of text is covered by a single style.

The heuristics for recognizing HTML files based on file contents have changed a bit; files which start with "<--" are no longer considered to be HTML.

With the new support for paragraph spacing, we've discovered some RTF files which had paragraph spacing values set, but of course never displayed up to now. It also turns out due to a Mail bug some text copy/pasted from Mail could have bogus paragraph spacing values. In order to fix these, paragraph spacing values in RTF files generated by Cocoa prior to 10.2 will be ignored by the RTF reader. However, you can use the NSIgnoreRTFParagraphSpacing default to force the behavior one way or the other (never ignore, always ignore). Note that as a part of this fix, the value of the CocoaRTFVersion document attribute was bumped up from 100 to 102.

We now read/write -[NSParagraphStyle lineSpacing] (the space between lines within a paragraph, aka leading) in RTF files.

The major text system objects (NSTextView, NSTextContainer, NSLayoutManager, and NSTextStorage) now support archiving using the new keyed archiving. This allows arbitrary configurations of the text system to be archived.

Menu items with the action paste: now automatically disable themselves when the first responder is an NSTextView and there is nothing in the pasteboard currently that can be pasted into the NSTextView.


NSParagraphStyle

NSParagraphStyle now has methods for the base writing direction setting in bi-directional text. -[NSParagraphStyle baseWritingDirection] and -[NSMutableParagraphStyle setBaseWritingDirection:] are the accessor methods for the attribute. You can use +[NSParagraphStyle defaultWritingDirectionForLanguage:] to query the default writing direction for a given localization name. Passing nil implies the user's default setting.

Tab stops other than left (right, centered, and decimal) are now implemented.


NSAttributedString

NSAttributedString's text break methods: -[NSAttributedString lineBreakBeforeIndex:withinRange:], -[NSAttributedString doubleClickAtIndex:], and -[NSAttributedString nextWordFromIndex:forward:], now have Unicode compliant implementations.

For backward compatibility, -lineBreakBeforeIndex:withinRange: still returns the index passed in the first argument when the index equals to the string length.


NSGlyphInfo

We now have a new class, NSGlyphInfo. Instances of this class are used to represent glyphs in attributed strings, allowing you to override the font specified Unicode -> glyph ID mapping. For example, you can specify a variant glyph for character 'a' if the font contains multiple variations for the character with this API. Or you can specify a certain ligature glyph that doesn't have a Unicode mapping. The following example assigns the small capital letter 'A' glyph often found in OpenType fonts.
NSMutableAttributedString *attrString; // Pre-initialized attributed string
NSRange rangeOfStringToBeOverriden;
NSString *baseString = [[attrString string] substringWithRange:rangeOfStringToBeOverriden];
NSFont *font = [attrString attribute:NSFontAttributeName
atIndex:rangeOfStringToBeOverriden.location
effectiveRange:NULL];
NSGlyphInfo *smallCapitalAGlyph = [NSGlyphInfo glyphInfoWithGlyphName:@"Asmall"
forFont:font
baseString:baseString];
[attrString addAttribute:NSGlyphInfoAttributeName
value:smallCapitalAGlyph
range:rangeOfStringToBeOverriden];

NSTextInput protocol

The InkWell text input service can ask you to return the content of your text input client that extends to your document range; so the implementation for the NSTextInputProtocol method, -attributedSubstringFromRange:, should be prepared to get out-of-bounds range. In that case, you should return the intersection of your document range and the range specified in the argument. If the location of the range is completely out-of-bounds of your document range, you can return nil.


NSTypesetter

We now have a new, currently private, NSTypesetter subclass which is enabled as the default system typesetter. It utilizes the Apple Type Service for Unicode Imaging functionality extensively, providing applications with advanced typography features such as smart-quoting and context-sensitive swashes, and broadening the support for languages in the AppKit framework.

In order to provide the reliable text layout compatibility between Mac OS X releases for applications, the AppKit text subsystem has new APIs to control various aspects of the text layout management in the framework.

NSLayoutManager now has the new methods:
- (NSTypesetterBehavior)typesetterBehavior;
- (void)setTypesetterBehavior:(NSTypesetterBehavior)behavior;
NSTypesetterBehavior is defined as:
typedef enum {
NSTypesetterLatestBehavior = -1,
NSTypesetterOriginalBehavior = 0,
NSTypesetterBehavior_10_2_WithCompatibility = 1,
NSTypesetterBehavior_10_2 = 2,
} NSTypesetterBehavior;
Setting the NSTypesetterLatestBehavior value causes the layout manager to use the latest (most-advanced) typesetter available on the system. This is the default value, and is appropriate for most usages. On 10.2, this corresponds to NSTypesetterBehavior_10_2. This enables all the new features in the new typesetter and fixes bugs in the NSSimpleHorizontalTypesetter implementation:

- It doesn't add the extra one pixel to the default ascender caused by a floating-point rounding error found in the previous typesetter implementation
- The values returned from -[NSParagraphStyle firstLineHeadIndent] and -[NSParagraphStyle headIndent] are interpreted as expected with all text alignment modes
- The value returned from -[NSParagraphStyle paragraphSpacing] is used by the typesetter
- It doesn't add the extra 20% leading to the ascender anymore except with Helvetica, Times, Courier that are already commonly used in the user interface.
- It interprets the value in NSBaselineOffsetAttributeName even if the attribute is set to the whole paragraph.

NSTypesetterBehavior_10_2_WithCompatibility behaves just as NSTypesetterBehavior_10_2 except the bugs listed above are preserved for applications that want to use the new typesetter and are relying on the behavior in the NSSimpleHorizontalTypesetter implementation.

NSTypesetterOriginalBehavior provides 100% compatibility by using the NSSimpleHorizontalTypesetter. You will not get the new features.

There are 2 default settings to control the default typesetter behavior: "NSTypesetterBehavior" takes integer values from 0 to 2 corresponding to the enumerated values in the NSTypesetterBehavior type. Other values are interpreted as NSTypesetterLatestBehavior. The default value for applications built on 10.2 is NSTypesetterBehavior_10_2, and the default value for applications built on prior versions is NSTypesetterOriginalBehavior. The value is accessible via the new NSTypesetter class method +defaultTypesetterBehavior.

"NSStringDrawingTypesetterBehavior" takes integer values from 0 to 2 corresponding to the enumerated values in the NSTypesetterBehavior type. Other values are interpreted as NSTypesetterLatestBehavior. This is the value used by the string drawing methods and NSCell subclasses. When this key is not present in the default database, it uses the value for NSTypesetterBehavior, assuming the value explicitly set and is smaller than the default value for NSStringDrawingTypesetterBehavior. The default value for NSStringDrawingTypesetterBehavior for applications built on 10.2 is NSTypesetterBehavior_10_2_WithCompatibility, and the default value for applications built on prior versions is NSTypesetterOriginalBehavior.

Using the new NSLayoutManager method, -defaultLineHeightForFont, applications can query the initial line height used by the typesetter subclasses depending on the current typesetter behavior in the receiver. It is no longer necessary to query the size of string containing a single space in order to get the line height for an empty string. This method returns the exact value used by the typesetters.

In NSTypesetterBehavior_10_2 and NSTypesetterBehavior_10_2_WithCompatibility, a new Unicode 3.2-based overstruck glyph inscription algorithm is used. It covers all the combining characters defined in the character standard, except the ones in Devanagari, Bengali, Gurmukhi, Gujarati, Oriya, Tamil, Telugu, Kannada, Malayalam, Sinhara, Thai, and Myanmar (U0900 - U0E7F and U1000 - U109F). The combining characters in these scripts require fonts with Apple Advanced Typography capabiliity. The new typesetter tries to precompose before falling back to the attachment placement algorithm based on the combining class, resulting in better glyph substitution with fonts that lacks the Apple Advanced Typography tables. There is now a threshold for the number of consecutive overstruck glyphs. A character sequence that has more combining characters than this threshold is not precomposed. The default value is 10 glyphs. The setting can be overriden via the "NSMaxNonBaseInscriptionGlyphs" default value.

Known issues with NSTypesetterBehavior_10_2 and NSTypesetterBehavior_10_2_WithCompatibility:

- The NSGlyphInscription values other than NSGlyphInscribeBase and NSGlyphInscribeOverstrike are ignored
- Two Apple Advanced Typography features, the context-senstive justification and left/right hangers, are explicitly disabled in this release.


NSInputManager

By default, NSInputManager no longer searches /Network/Library/InputManagers for input managers. You can override this behavior by setting the user preference NSSearchNetworkForInputManagers to YES in order to load input managers over the network.


NSFont

A new API, -coveredCharacterSet, is added to NSFont. It returns an NSCharacterSet that contains all the nominal characters renderable by the receiver. In other words, it returns all the entries mapped in the font's 'cmap' table. Note that the number of glyphs supported by a given font is often larger than the number of characters contained in the character set returned by this method. For example, a font may have a 'tt' ligature glyph, but it won't be in the character set since the glyph doesn't have the corresponding Unicode Value.


NSFontPanel

The font panel now has an optional preview pane, which can be shown by the user. It remembers its size on a per-app basis.


NSColorPanel

The standard color panel now has a "crayon" mode that offers the user a set of predefined colors to choose from. The crayon colors are also accessible in the "list" picker, by choosing "Crayons" in the "Palette" pop-up button. Two new constants have been added to NSColorPanel.h to accommodate this new color picking mode:
    NSCrayonModeColorPanel        = 7
NSColorPanelCrayonModeMask    = 0x00000080

The "Apply" button has been removed from the color panel. The NSColorPanel used to call the responder method 'changeColor:' whenever this button was clicked. Since the button is no longer there, 'changeColor:' will be sent to the first responder immediately on a color change. This responder method will be sent continuously only if the color panel is set to be continuous.


If you have written a custom color picker, you should check to make sure your picker fits into the area available at the new color panel's minimum size. If the view provided by your color picker is not resizable (this applies to width and height), then the color panel will automatically force itself to be at least big enough to accommodate your view in its full size.


In the past, the color panel used a matrix of buttons to present as a matrix of buttons. The color panel now uses a small icon only toolbar. So, you should make sure your icon looks good as a small toolbar icons (see NSToolbarItem relnotes for more information). Note that in the past, the button image and the tooltip could be supplied by overriding -provideNewButtonImage and/or -insertNewButtonImage:in:. This is still the case.


NSProgressIndicator

10.2 brings support for a spinning style in addition to the current bar style. The following API has been added to support this new style.
typedef enum {
NSProgressIndicatorBarStyle = 0,
NSProgressIndicatorSpinningStyle = 1
} NSProgressIndicatorStyle;
- (void) setStyle:(NSProgressIndicatorStyle)style;
- (NSProgressIndicatorStyle)style;
// For the spinning style, it will size the spinning arrows to their default size.
// For the bar style, the height will be set to the recommended height.
- (void) sizeToFit;
// True by default; for spinning style, might make sense to choose
// to have it not displayed when stopped.
- (BOOL) isDisplayedWhenStopped;
- (void) setDisplayedWhenStopped:(BOOL)isDisplayed;

NSDocumentController

NSDocumentController attempts to create a new document at application launch time using the first suitable document type declared in the application's Info.plist file, if there is one. In previous releases of Mac OS X, a document type was considered suitable if its Info.plist dictionary contained a CFBundleTypeRole entry whose value was "Editor" or "Viewer." Due to the widespread confusion this caused among developers who were using Cocoa's document architecture to write viewer-only applications, this behavior has been changed. Now, NSDocumentConroller will attempt to create a new document at launch time using the first type whose Info.plist dictionary's CFBundleTypeRole entry is "Editor," if there is one. Document types for which the application can only assume the "Viewer" role will not be considered.

For backwards binary compatibility, NSDocumentController will exhibit the same behavior in this regard as it did in Mac OS 10.1, when running in programs that were linked against the 10.1 or earlier versions of the AppKit or Cocoa frameworks.


In previous releases of Mac OS X, -[NSDocumentController typeFromFileExtension] compared passed-in file name extensions to the extensions declared in the application's Info.plist in a case-sensitive manner. As a result, NSDocument-based applications were often unable to open documents with file name extensions cased in a manner unanticipated by application developers. For example, documents with a file name extension of "PDF" could not be opened by an application whose Info.plist contained a CFBundleTypeExtensions array that contained only a "pdf" entry. This bug has been fixed. Some developers worked around it by redundantly listing file name extensions in their application's Info.plist, with the redundant entries varying only by character case. Such a workaround is no longer necessary for applications that are not required to run on releases of Mac OS X older than 10.2.


NSPrinter

Some NSPrinter methods have been deprecated. They are:
- (NSRect)imageRectForPaper:(NSString *)paperName;
+ (NSPrinter *)printerWithName:(NSString *)name domain:(NSString *)domain includeUnavailable:(BOOL)flag;
- (NSString *)domain;
- (NSString *)host;
- (NSString *)note;
- (BOOL)acceptsBinary;
- (BOOL)isColor;
- (BOOL)isFontAvailable:(NSString *)faceName;
- (BOOL)isOutputStackInReverseOrder;
See the comments in the <AppKit/NSPrinter.h> header file more more specific information.


In previous releases of Mac OS X, -[NSPrinter printerNames] returned the names of all NetInfo-registered printers, regardless of whether the printers had been added to the Print Center's Printer List. This behavior has been changed. -[NSPrinter printerNames] now returns the names of the same printers that appear in the printer list.

In previous releases of Mac OS X, -[NSPrinter printerTypes] always returned an array that contained exactly one string ("Xrn4525p"). It now returns strings that contain the makes and models of the printers that appear in the printer list.


NSPrintInfo

It is important in many applications to be able to reliably determine the maximum imageable area of a printed page. A new method has been added to NSPrintInfo:
- (NSRect)imageablePageBounds;
Returns the imageable area of a sheet of paper specified by this object, taking into account the current printer, paper size, and orientation settings, but not scaling. "Imageable area" is the maximum area that can possibly be marked on by the printer hardware, not the area defined by the current margin settings. The rectangle is in a coordinate space measured by points, with (0, 0) being the lower-left corner of the oriented sheet and (paperWidth, paperHeight) being the upper-right corner of the oriented sheet. The imageable bounds may extend past the edges of the sheet when, for example, a printer driver specifies it so that borderless printing can be done reliably.


Some NSPrintInfo methods have been deprecated. They are:
+ (void)setDefaultPrinter:(NSPrinter *)printer;
+ (NSPrinter *)defaultPrinter;
+ (NSSize)sizeForPaperName:(NSString *)name;
Also, some NSPrintInfo attributes have been deprecated. They are:
NSPrintFormName
NSPrintJobFeatures
NSPrintManualFeed
NSPrintPagesPerSheet
NSPrintPaperFeed
See the comments in the <AppKit/NSPrintInfo.h> header file more more specific information.


Printing Presets

New since WWDC update of 10.2, Mac OS X now has support for "printing presets". With this feature, printer drivers can specify names for commonly used sets of printing parameter values, so users can select such sets easily. For example, when this feature is enabled, and when a printer that supports this feature is selected, the user might see items like "Photo on Plain Paper" in the Presets menu of print panels. To enable this feature, applications must provide a hint about what kind of print job is being output. New methods have been added to Cocoa for this.

Right now, only one style of print job is supported. It is identified by a constant string that has been added to NSPrintPanel.h. It's declaration looks like this:
NSString *NSPrintPhotoJobStyleHint;
This is currently the only valid value for identifying a job style hint.

Two new methods have been added to NSPrintPanel.h:
- (void)setJobStyleHint:(NSString *)hint;
- (NSString *)jobStyleHint;
Sets or gets a string that provides a hint about the type of print job in which the print panel is being used. This controls the set of items that appear in the Presets menu. Currently, the string must be NSPrintPhotoJobStyleHint, or nil to provide no hint.

Matching methods have been added to NSPrintOperation.h:
- (void)setJobStyleHint:(NSString *)hint;
- (NSString *)jobStyleHint;
Sets or gets a string that provides a hint about the type of print job. This controls the set of items that appear in the Presets menu of the print panel presented by this operation, if it presents one. Currently, the string must be NSPrintPhotoJobStyleHint, or nil to provide no hint.


NSWindow

-[NSWindow setBackgroundColor:] will now take effect regardless of the window styleMask. In 10.1, -[NSWindow setBackgroundColor:] only modified the background color for borderless windows (that is, windows with styleMask equal to NSBorderlessWindowMask).

There is now a styleMask to specify that a window has a textured background, NSTexturedBackgroundWindowMask. Windows with this styleMask get a metal-textured background similar to the background in iApp windows. A window with this styleMask may be moved by clicking and dragging anywhere in the window background, as opposed to a window without this styleMask which may only be moved by clicking and dragging in the titlebar. A bordered window with this styleMask will also get rounded bottom corners. A borderless window may also be given this styleMask to specify that it should have the metal-textured background and be movable by the window background.

There is now a method to specify that a custom window should be movable by its background, and a method to query this setting. A window whose styleMask includes NSTexturedBackgroundWindowMask gets this setting by default, except that it is not allowed for sheets and drawers.
- (void)setMovableByWindowBackground:(BOOL)flag;
- (BOOL)isMovableByWindowBackground;
Also see discussion of -[NSView mouseDownCanMoveWindow] further below.


Keyed archiving for NSWindow is an illegal operation. An attempt to archive or unarchive NSWindow using a keyed coder will raise an NSInvalidArgumentException.


The following NSWindow changes are new since WWDC release of 10.2.

The -windowRef method has been modified to create a Carbon WindowRef if one does not already exist for the window. This method previously returned a WindowRef only for an NSWindow created using -initWithWindowRef:. -windowRef can now be used to create a WindowRef for a window containing a Carbon control. Subsequent calls to the method will return the existing WindowRef.


There is new API to create and access the buttons in the window titlebar:
typedef enum {
    NSWindowCloseButton,
    NSWindowMinimizeButton,
    NSWindowZoomButton,
    NSWindowToolbarButton,
    NSWindowDocumentIconButton
} NSWindowButton;
The following method returns an autoreleased new instance of the given standard button, sized appropriately for the styleMask. The caller is responsible for adding the button to the view hierarchy and for setting the target to be the window:
+ (NSButton *)standardWindowButton:(NSWindowButton)b forStyleMask:(unsigned int)styleMask
The following returns the given standard button if it is in the window view hierarchy:
- (NSButton *)standardWindowButton:(NSWindowButton)b

There is new API to attach one window to another for purposes of moving and ordering. childWin will be ordered either above (NSWindowAbove) or below (NSWindowBelow) the receiver, and maintained in that relative position for subsequent ordering operations involving either window. While this attachment is active, moving childWin will not cause the receiver to move (as in sliding a drawer in or out), but moving the receiver will cause childWin to move:
- (BOOL)addChildWindow:(NSWindow *)childWin ordered:(NSWindowOrderingMode)place
To query the array of attached child windows:
- (NSArray *)childWindows
To detach childWin from the receiver:
- (void)removeChildWindow:(NSWindow *)childWin
To get the parent window to which the receiver is attached as a child:
- (NSWindow *)parentWindow
Bottleneck for setting the parentWindow ivar in the receiver. May be overridden by subclasses; should call super:
- (void)setParentWindow:(NSWindow *)window
Note that ordering operations on the child will also effect the parent, so a child window should generally be removed from its parent before the childWindow is ordered out.


There is now API to make a window transparent to mouse events, allowing overlay windows. To set whether the window is transparent to mouse clicks and other mouse events, allowing overlay windows:
- (void)setIgnoresMouseEvents:(BOOL)flag;
Return whether the window is transparent to mouse events:
- (BOOL)ignoresMouseEvents;
If a custom-shaped window has a shadow, the shadow must be updated when the window changes shape. The following method will invalidate the window shadow so that it will be recomputed based on the current window shape:
- (void)invalidateShadow;

NSPanel

10.2 brings the concept of a non-activating panel. A non-activating panel can receive keyboard input without activating its owning application. To support this, a styleMask has been added to NSPanel.h:
enum {
    ...
NSNonactivatingPanelMask = 1 << 7
};
This styleMask can be passed to NSPanel's designated initializer:
- (id)initWithContentRect:(NSRect)contentRect styleMask:(unsigned int)aStyle backing:(NSBackingStoreType)bufferingType defer:(BOOL)flag;
Note that like NSUtilityWindowMask, NSNonactivatingPanelMask is only valid for an NSPanel or subclass, it is not valid for an NSWindow.

This type of panel inherits NSPanel's method for specifying whether the panel should become key when activated, or only if needed:
- (BOOL)setBecomesKeyOnlyIfNeeded:(BOOL)flag;
If this method is called with YES, then the non-activating panel becomes key only if the hit view returns YES for -needsPanelToBecomeKey. In this way, a non-activating panel can control whether it steals keyboard focus or not. Internally, we will allow keyboard events to be routed to a panel without requiring the owning application to be active. A non-activating panel with keyboard focus will have the appearance associated with key windows, including focus rings, cursor rects, and a blinking cursor if appropriate. A non-activating panel can be made key even if its owning application is not active.


NSView

NSView's autosizing machinery no longer adjusts the y origin to 0 when it becomes negative. In the prior releases, NSView used to adjust the y origin to 0 when it becomes negative, often resulting in inaccessible views pushed outside the window. The adjustment behavior is removed when the vertical autoresizingMask is NSViewMinYMargin.

The long-standing bug with drifting of autoresized views (usually set via springs in IB) has been fixed. Note that this fix applies to views whose frames do not overlap the edges of their superviews; in general autoresizing flags are not designed to work well otherwise.


New since the WWDC update of 10.2, NSView now has a new method which allows a view to specify whether or not it should be treated as blocking window moving for a mouseDown in its bounds. This only applies to views in windows that return YES for -isMovableByWindowBackground. The default implementation returns YES if the view is not opaque and NO otherwise. NSControl and other standard views that implement mouseDown: return NO for this method. A custom view should implement this method to return NO if it wants to disable window moving for a mouseDown: within the view bounds. This is an addition to NSView.h:
- (BOOL)mouseDownCanMoveWindow;

NSResponder

A method has been added to NSResponder in order to distinguish when a pen-down should start inking vs. when it should be treated as a mouse down event. This is needed to support a write-anywhere model for pen-based input.
- (BOOL)shouldBeTreatedAsInkEvent:(NSEvent *)event;
The event argument is the mouse down with tablet data. This method returns YES if the event should be treated as an ink event, NO if it should be treated as a mouse event.

A pen-down causes this method to be sent to NSApplication. The default implementation in NSApplication sends the method to the NSWindow under the pen. If the window is inactive, -shouldBeTreatedAsInkEvent: returns YES, unless the pen-down is in the window drag region.

If the window is active, -shouldBeTreatedAsInkEvent: will be sent to the NSView under the pen. The default implementation in NSView returns YES, and NSControl overrides to return NO. This allows write-anywhere over most NSViews, but also allows the pen to be used to track in controls and to move windows.

A custom view should override this method if needed to get the correct behavior for a pen-down in the view.


HFS Promises

Cocoa now supports dragging of HFS Promises for both the drag source and the drag destination. This has been added since WWDC release of 10.2.

An NSView that acts as a dragging source for HFS promises should call -[NSView dragPromisedFilesOfTypes:fromRect:source:slideBack:event:]. This method will write a new pasteboard type, NSFilePromisePboardType, with data consisting of the fileTypes array, and will also write a private type necessary to allow the destination to ask for the filenames when the drag is dropped. This is an addition to NSView.h:
- (BOOL)dragPromisedFilesOfTypes:(NSArray *)fileTypes fromRect:(NSRect)aRect source:(id)sourceObject slideBack:(BOOL)slideBack event:(NSEvent *)theEvent
fileTypes - an array of file type extensions, eg. [NSArray arrayWithObject:@"txt"] to promise one file with a .txt extension, or [NSArray arrayWithObjects:@"pdf", @"pdf", nil] to promise two files with the .pdf extension. It is also be possible to promise HFS types, using NSFileTypeForHFSTypeCode.
aRect - describes the position of the dragged image representing the file promise
sourceObject - the controller of the dragging operation, which must conform to the NSDraggingSource protocol
slideBack - whether or not the dragged image should slideback if the drag is rejected
theEvent - the mouse-down event object from which to initiate the drag operation

This method returns     YES if the drag operation is successfully initiated, NO otherwise.

When the drag is dropped on a destination that accepts HFS promises, -namesOfPromisedFilesDroppedAtDestination: will be invoked on the sourceObject. This is an addition to the NSDraggingSource informal protocol:
 -(NSArray *)namesOfPromisedFilesDroppedAtDestination:(NSURL *)dropDestination
dropDestination - a URL representing the drop location

This returns an array of filenames for the created files - note that this is filenames only, not full paths.

A dragging source will use the -[NSView dragPromisedFilesOfTypes:fromRect:source:slideBack:event:] to promise one or more files for dragging, but will defer creation of these files until after the drag has been dropped, so that the promised files can be created at their final destination. The actual contents of the files should not be written until after the drag has been released if the files are large, to prevent blocking the destination during a lengthy file operation. In addition, a source can promise a top-level directory, then fill in the directory contents after the drag has been released.

The destination may be either Carbon or Cocoa. If the destination is Cocoa, -performDragOperation: is called on the destination when the drag is dropped. At this point, the destination should call a new method on NSDraggingInfo to get the names for the promised files, passing the destination of the drop. This is an addition to the NSDraggingInfo protocol:
 -(NSArray *)namesOfPromisedFilesDroppedAtDestination:(NSURL *)dropDestination
dropDestination - a URL representing the drop location

Returns an array of filenames for the created files - note that this is filenames only, not full paths

This will cause an IPC to the source which will invoke -namesOfPromisedFilesDroppedAtDestination: on the dragging source if the source is Cocoa, or will ask for the HFS promise data if the dragging source is Carbon.


NSPasteboard

The -changeCount method now returns an integer which only changes when the entire set of data on the pasteboard changes. This aligns with the documented behavior. It used to return an integer which changed whenever anything on the pasteboard changed.

-declareTypes:owner: now properly returns the change count of the pasteboard. This aligns with the documented behavior. It used to return 0.

-addTypes:owner: now properly returns the change count of the pastebaord. This aligns with the documented behavior. It used to return -1 or 0.

The -dataForType: method now waits for a longer time for promises to be fulfilled, either the integer seconds given by the NSPasteboardPromiseTimeout default, or 120 seconds if the default does not exist.


AppKit has added a new constant, NSVCardPboardType, to represent VCards on the pasteboard. The AppKit doesn't do anything with data of this type, it is just exporting the type for clients.


Pasteboard Server Lookup Timeouts

The timeout for pbs server operations has been increased quite a bit, which may cause applications to hang longer in certain cases, and hopefully eventually get through, rather than simply fail.

There are three defaults that control the various timeouts. The values of the defaults should be integers, in units of seconds. Most of the time these defaults are sufficient, and apps need not worry about them

    NSPBSServerLookupTimeout    default: 10 seconds
    NSPBSServerSendTimeout        default: 20 seconds
    NSPBSServerReplyTimeout        default: 60 seconds


NSSound

NSSound now uses QuickTime to play most sound files/URLs, including streaming non-file URLs from the Internet. Since QuickTime requires the run loop to be run for sound (or movies) to continue playing, NSSound now requires this as well. The delegate -sound:didFinishPlaying: will also not be called unless the run loop is run. By "run loop", what is meant is the run loop on the thread which starts the sound playing. For Cocoa applications, this is not a big deal for sounds played by the main thread, as Cocoa apps normally let the AppKit handle running the run loop on the main thread. But in other situations you will need to be aware of this requirement.


NSEvent

In 10.2, and since the WWDC seed, the window server started setting an additional device-dependent modifier flag in user input events to indicate when event coalescing is disabled. Applications that check for modifierFlags using equality without masking off the device-dependent modifierFlags first can get unexpected behavior due to this change. In order to maintain compatibility for applications built on 10.2 and earlier systems, NSEvent by defaults strips this device-dependent modifier flag when creating the event from a windowServer event. For applications built on systems later than 10.2, this will no longer be the default behavior. In order to override NSEvent's default behavior, an application can specify a value for the user default NSDeviceDependentModifierFlags. If this default is set to YES, the device-dependent modifier flags will not be stripped.


NSWorkspace

NSWorkspace now contains two additional methods for dealing with the list of running applications. For the purpose of these methods, an application is specified by returning a dictionary with as many of the following keys as are available:

NSApplicationPath (the full path to the application, as a string)
NSApplicationName (the application's name, as a string)
NSApplicationProcessIdentifier (the application's process id, as an NSNumber)
NSApplicationProcessSerialNumberHigh (the high long of the PSN, as an NSNumber)
NSApplicationProcessSerialNumberLow (the low long of the PSN, as an NSNumber)

In addition, these keys have been added to the userInfo dictionary for the NSWorkspace application will launch, did launch, and did terminate notifications.

The new methods are:
- (NSArray *)launchedApplications;
- (NSDictionary *)activeApplication;
The first of these returns an array of these dictionaries for all running applications (those for which a will launch notification would have been sent), while the second returns a dictionary for the current frontmost application.


NSSavePanel

If -setTreatsFilePackagesAtDirectories: was sent to the save panel while it was on screen, the browser would get in an invalid state and not update properly to the new state of the panel. The user had to "click around" in the browser to get it updated. This has been fixed. This allows -setTreatsFilePackagesAtDirectories: to be called, for example, as the result of the user toggling a switch in the accessory view of the panel.


Accessory Views are now part of the keyboard loop (NSColorPanel, NSSavePanel, NSOpenPanel, spell checking panel)

Many system panels allow developers to specify a custom accessory view to be displayed as part of the panel. In previous version of Mac OS X, those accessory views did not become part of the panels keyboard loop. This has been fixed for a few system panels, including: NSSavePanel, NSOpenPanel, NSColorPanel, and the shared spell checking panel. You can specify your own keyboard loop within the accessory view. These system panels treat the accessory view's 'nextKeyView' much like an initialFirstResponder of an NSWindow (see notes in NSWindow on automatically generated keyboard loops). If the view's nextKeyView is not set, it will be assumed you have not specified your own keyboard loop, and one will be computed for you. If a 'nextKeyView' is set, then your loop will be used. Normally the automatically computed keyboard loop will do what you want.


NSTabView

NSTabView now has support for directional tabs - NSLeftTabsBezelBorder, NSBottomTabsBezelBorder, and NSRightTabsBezelBorder tab view types are now implemented. These styles can be chosen in InterfaceBuilder, or by calls to -setTabViewType:. One can check for support of this new feature by comparing against the constant:
    #define NSAppKitVersionNumberWithDirectionalTabs 631.0
No new API has been introduced to support directional tabs. However, there are issues with some existing API that require explanation.

First, define the normal axis to be the one given by the direction of the tab. So, for NSRightTabsBezelBorder tabs, the normal axis points east, or left to right across the screen. Next, define the label axis to be perpendicular to the normal axis. The width of the label is always measured along the label axis, and the height along the normal axis. Given these definitions, we clarify the effect on existing APIs:
    NSTabViewItem:
    - (void)drawLabel:(BOOL)shouldTruncateLabel inRect:(NSRect)labelRect;
     // This method draws the tab label in labelRect.
     // 'labelRect' is the area in between the curved end caps.
     // 'shouldTruncateLabel' is a hint that the label should be truncated.
    - (NSSize)sizeOfLabel:(BOOL)computeMin;
     // This method returns the minimum or nominal size of the tab label.
     // 'computeMin' indicates whether you should return the minimum or
     // nominal label size. The returned value is used to
     // compute the range of legal sizes for the tab label.
-drawLabel:inRect: assumes the label and normal axis are along the x and y axis respectively. This method is called by NSTabView after transforming the coordinate system to achieve this effect. So, by default developers can draw all tabs as if they were north facing (NSTopTabsBezelBorder).

-sizeOfLabel: also returns the width and height of the items label. The width of the label is measured along the label axis, and the height is measured along the normal axis.


NSBrowser

Mouse clicks in a browser that doesn't accept first responder no longer cause the current first responder to resign.

Browsers no longer enclose their titles within the focus ring rectangle. The focus ring will always enclose just the columns (and horizontal scroller if present).


NSTableColumn

A bug was discovered in 10.1 which could not be fixed in 10.2. Table columns created in IB have data cells with different properties than those created with alloc/init. NSTableColumns that come from IB (Either straight from the palette, or made via copy paste), will contain a NSTextFieldCell whose drawsBackground property is NO, and whose font is 13 pt. Lucida Grande. When a NSTableColumn is created using [[NSTableColumn alloc] initWithIdentifier:@"foo"], it will contain a NSTextFieldCell whose drawsBackground property is YES, and whose font is 12 pt. Lucida Grande. Until this is fixed, it may be necessary to verify / fix the font heights of your tables in code.


NSColor

isEqual: on pattern colors will now properly return NO with arguments which are not colors. This used to raise an exception.


colorWithPatternImage: used to return non-autoreleased colors. For apps linked post-10.1, this will correctly autorelease the return value. If you were not retaining the return value, your app will crash once it's linked on a post-10.1 system. The fix is to retain the color. If you need to dynamically check this fix, look for AppKit version >= NSAppKitVersionNumberWithPatternColorLeakFix (or if your use of pattern colors is small --- just a few instances allocated --- let the 10.1 version leak).


NSColor now has the following additional standard colors. These parallel the existing selectedControlColor and selectedControlTextColor:
+ (NSColor *)alternateSelectedControlColor;
+ (NSColor *)alternateSelectedControlTextColor;
These colors are meant to be used in tables and lists where Mail or iTunes like highlighting is desired. For inactive items in these situations, use the existing methods secondarySelectedControlColor and selectedControlTextColor. Note that in this context inactive does not mean disabled; it means non-key (aka secondary).

See below ("Alternate Selection Colors") for discussion on use of these colors in the AppKit.


Alternate Selection Colors

The highlight coloring scheme for lists and browsers has been changed. The goal is to make it easier to tell which control has keyboard focus. The new scheme, which applies to selections and their text, should be picked up automatically for most. However, some work may be required for adoption. Here's a summary of how the highlighting scheme works:

When a table/outline or browser is actively focused (the control receiving keyboard events, ie. it is first responder and in the key window), they will show selections using the new alternate highlight color, +[NSColor alternateSelectedControlColor]. For browsers, only the last column will use +[NSColor alternateSelectedControlColor] . In 10.1, +selectedControlColor was used.

If a table/outline or browser is not actively focused then it uses +[NSColor secondarySelectedControlColor]. For browsers, this color is used for every column except the last selected column. This process is the same as it was in 10.1; however, the color value has changed. It used to be a lighter version of +[NSColor selectedControlColor], now it is simply a light gray. (And clearly it could change in the future, so please, no assumptions.)

If a row is highlighted using +[NSColor alternateSelectedControlColor], NSCell will automatically use +[NSColor alternateSelectedControlTextColor] instead of +[NSColor controlTextColor] when drawing. Automatic use of the alternate text color will only happen if your cell's text color is set to +[NSColor controlTextColor], or your text color's RGB values are the same as +[NSColor controlTextColor]. Also, NSCell will not change your cell's stored text color. It simply will decide to draw with a different color if appropriate.

Adopting the new highlighting scheme:
- Most will not have to do anything for this to work.
- If you draw some of your own table/outline, browser, or cell highlights you should verify that they still look fine. If they do not, it is probably because you are hard-coding your use of colors. When drawing highlights, it is recommended that you ask NSCell what color to use by calling -highlightColorWithFrame:inView:.
- If you do your own text drawing (using string drawing routines), or set your own text colors, make sure the correct colors are being used as appropriate. Since it is common to subclass NSCells and do this, below is an example of how to do text highlighting.

If you can not use the alternate colors for some reason you can set the NSAlternateListHighlightCompatibility_10_1 default to YES.
    - (void)drawInteriorWithFrame:(NSRect)cellFrame inView:(NSView *)controlView {
NSColor *highlightColor = [self highlightColorWithFrame:cellFrame inView:controlView];
BOOL highlighted = [self isHighlighted];
        if (highlighted) {
    [highlightColor set];
NSRectFill(cellFrame);
}
        // Draw the icon
        if (myImage) {
            .....
        }
        // Draw the text (myTitle is an NSAttributedString)
        if (myTitle) {
            // If we are highlighted AND are drawing with the alternate color, then we want to draw our text with the alternate text color.
// For any other case, we should draw using our normal text color.
            if (highlighted && [highlightColor isEqual:[NSColor alternateSelectedControlColor]]) {
                // Make a copy of our title so that we can ....
NSMutableAttributedString *myTitleCopy = [[myTitle mutableCopy] autorelease];
                // ... add the alternate text color attribute...
[myTitleCopy addAttribute:NSForegroundColorAttributeName
                    value:[NSColor alternateSelectedControlTextColor]
range:NSMakeRange(0,[myTitle length])];
myTitle = myTitleCopy;
            }
            // Draw the text
            [myTitle drawInRect: .....];
        }
    }


NSTableView

Any API that changes the selection in a table view will now end editing if it is appropriate. For example deselectAll: will always end editing. In general if calling the API causes the edited row to no longer be selected, editing will be ended. Further, if calling the API causes multiple rows to be selected, editing will be ended. In all cases editing is ended gracefully, meaning the value will be applied if it is valid.

The image passed to setIndicatorImage: is now retained and released by the table view as appropriate.

The default sorting order indicators are now available as named NSImages. These images can be accessed with [NSImage imageNamed:] using the names NSAscendingSortIndicator (the "^" icon), and NSDescendingSortIndicator (the "v" icon).

NSTableView's encodeWithCoder: method now archives the autosaveName, but only if you are using keyed archiving. NSTableView's initWithCoder: method reads the autosaveName and then sets its columns to those found in user defaults.

In 10.1, the rowsInRect: method returned the range {0,0} whenever the inRect parameter contained a negative y component, even if the height was tall enough to intersect with some rows in the table. This has been fixed.

The following methods are now reflected in the Java API for NSTableView:
void setIndicatorImage(NSImage indicatorImage, NSTableColumn tableColumn);
NSImage indicatorImage(NSTableColumn tableColumn);
void setHighlightedTableColumn(NSTableColumn tableColumn);
NSTableColumn highlightedTableColumn();

In 10.2 and previous releases, NSTableView did not send its action to its target if the user changed the selection with the keyboard (up and down arrow keys). This issue can be easily handled by catching NSTableView's NSTableViewSelectionDidChangeNotification.


The following are a list of bugs in NSTableView that were discovered too late to be fixed.

Drags starting from a NSTableView no longer automatically support the trash as a destination. This applies to 10.2 and later applications. If you need to drag to the trash, you can do this by subclassing NSTableView and including NSDragOperationDelete in your return value from draggingSourceOperationMaskForLocal:. To determine if a drag ended in the trash, override draggedImage:endedAt:operation:. We hope to make this process easier in the future.


The "Show Grid" flag in IB is ignored. If you have not set the flag in IB, you can turn on grid drawing in code as expected. However, If you have set this flag in IB, you will need to do the following in code to get the grid to draw:
    [tableView setDrawsGrid:NO];
[tableView setDrawsGrid:YES];

NSTableView returns NO from needsPanelToBecomeKey. This means by default a user that navigates using the tab key will skip over tables and outline views. To workaround this, you can subclass NSTableView and return YES from needsPanelToBecomeKey.


Consider a table view containing one column of sliders. If the slider is continuous, you will be continuously sent your action message as the slider is tracking. If in response to this action, you ask for the selected, or edited cell, you will not get back the actual cell that is tracking. And because this cell is a temporary copy of your data cell, there is no way to get at the cell and obtain live values. This bug seems to have been around for quite some time. A simple workaround is to supply a custom subclass as your data cell. In this custom class you can override the tracking routines and mark the current tracking cell so that your other code can get at the cell that is tracking.


The following scenario can be problematic for tables that autosave their table columns. Autosaving table columns can be turned on in IB by setting the "Autosave Name" attribute, or in code by using setAutosaveTableColumns:/setAutosaveName:. This is useful if you want to allow users to customize the list of columns or their order.

Consider a table that autosaves columns, that is specified in IB with the columns (by column identifier): @"ColA", @"ColB". When the user runs your application, the present table column identifiers will written out to user defaults. When the user reruns the program, NSTableView will find a list of column identifiers in user defaults, representing the columns to be used in that table. NSTableView then searches itself for existing columns given those identifiers, keeping the columns it finds in the table and effectively removing the others. If you have removed or renamed (the identifier of) a column in IB you may run into problems because, NSTableView will stop it's searching whenever it hits a column that no longer exists. This can cause it to appear that all table columns after the missing column have disappeared. Worse, if the column that disappeared is the first column identifier found in user defaults, then your table will have NO columns (which will cause NSTableView to raise at a later time).

The workaround is fairly simple. If you need to remove a column, you should leave it around in IB, and remove it in code. If you need to rename a column you can apply a similar technique.


NSOutlineView

Any API that expands or collapses an item now considers the possibility that the outline view may be in the middle of editing a cell. If the edited cell is a child of an item that is about to be collapsed, editing will be ended. If expanding or collapsing an item causes a edited cell to move, the field editor will be repositioned and scrolled to visible if necessary.

In all cases editing is ended gracefully, meaning the value will be applied if it is valid.

See the NSTableView section concerning selections for the additional behavior NSOutlineView inherits.

The internal representation of indices in NSOutlineView has been fixed so that the number of children are no longer limited to 32K.

A significant leak has been fixed in NSOutlineView. Expandable items (those returned from data source API) would sometimes be retained but never released by NSOutlineView, resulting in leaks. Your application will get this fix only if it is linked against 10.2 or later. Applications linked against any previous version will maintain the old behavior for compatibility.


NSComboBox

In 10.1, disabled combo boxes returned YES from acceptsFirstResponder. When users clicked on a disabled combo box, this would cause focus to magically shift to the key view following the combo box. NSComboBox now returns NO from acceptsFirstResponder if it is disabled.


NSToolbarItem

If an image contains multiple representations, NSToolbarItem now chooses the most appropriately sized representation when displaying. For instance, if the image contains a representation which is the same size as a menu item image, that representation will be used in the menu form representation. Further if you find that your icon doesn't scale well in NSToolbar's small icon mode, you can add your own small image representation to the image, and it will be used instead of scaling.


NSToolbar

Toolbars now allow users to configure the displayed size. Toolbars that save their configuration to user defaults will also record the users chosen size. The following API has been added to support configurable toolbar sizes:
    typedef enum {
        NSToolbarSizeModeDefault,
        NSToolbarSizeModeRegular,
        NSToolbarSizeModeSmall
    } NSToolbarSizeMode;
    - (void)setSizeMode:(NSToolbarSizeMode)sizeMode;
    - (NSToolbarSizeMode)sizeMode;
Image items will automatically display a regular (32x32) or small sized (24x24) image as appropriate. If your image contains an image representation of the exact size of the current mode, that image will be used. Otherwise, the most appropriate representation will be scaled to the current modes size. Usually you should just supply the regular sized icon and let the toolbar use scaling when displaying the small version. When NSToolbar creates a scaled version it will add the scaled representation to your original image so that it won't have to create it again as users switch between modes or open multiple windows.

View items may require custom code to adjust their appearance based on the size mode. If your item's view implements setControlSize:, the view will be configured by sending it that method. If your view doesn't implement setControlSize:, NSToolbar will check to see if you view is really a control whose cell implements setControlSize:. In this case, your cell will receive the method. Notice this means most standard controls will automatically be configured for you. For example if you item's view is a NSPopUpButton, NSButton, NSTextField, etc... you won't have any work to do. If you need to customize or perform your own configuration, simply provide you item with a view that implements setControlSize:.


Any property set on a toolbar before it is handed to its window is considered to be the "initial" property of the toolbar. That is, if no values for the toolbar are found in user's preferences, then the initial value will be used. In 10.1 setVisible: NO was basically ignored. This has been fixed. Now, if you do a setVisible:NO, and no values are found in user defaults (this is the first time the user is seeing the toolbar), the toolbar will indeed show up initially hidden.


In Mac OS X 10.1, calling setConfigurationFromDictionary: only changed the state the messaged toolbar. Now, the toolbar properly updates other toolbars with that have the same identifier as the messaged toolbar.


In Puma changing a toolbar items label would sometimes cause all other items in the toolbar to disappear until the window was resized. This is fixed .


setConfigurationDictionary: now pays attention to the shown / hidden flag, and will show / hide the toolbar if the flag is different from the current configuration.


NSCell

In 10.1 using NSCell's -setStringValue:/-stringValue could cause a crash if used within nested autorelease pools. This bug is most commonly seen in Cocoa Java because of the use of autorelease pools in the Java bridge. This bug has been fixed now. You should be aware however, that an app that works in 10.2 may be susceptible to this crasher in 10.1.


If you are editing a cell (e.g. NSTextFieldCell) and ask for the cell's stringValue while the user is typing, you may interrupt multikey character input. You should check the edit field to see if is currently in this state via the following:

[[control currentEditor] hasMarkedText];

...and don't fetch the string value if this returns YES. This is not a problem if you use an NSFormatter. The NSFormatter method isPartialStringValid:... will not be called while in this partial character state.


NSMovieView

A call to -[NSMovieView setMovie:] will now call QuickTime PrePrerollMovie and PrerollMovie functions asynchronously. If you specified a streaming URL, this will initiate the connection but not actually begin playing when the preroll completes unless you have already called -[NSMovieView start:].

NSMovieView has been changed to use NSUndoManager for all undo operations. This enables multiple undo/redo. Note that the undo: method in NSMovieView has been removed since this is now handled by NSUndoManager.


NSImage

A change has been made to -[NSImage initByReferencingFile:]. If the image can be cached because the cached size is smaller than the actual expanded size, i.e an image that is more than 72 dpi, then the original data is flushed and the cached image is used. If you resize the image either larger or by less than 50%, the data will loaded in again from the file. If you expect the file to change or be deleted, you should use -[NSImage initWithContentsOfFile:] instead. This behavior only applies to applications built on 10.2 or later.


You can now set the whether the image caches its representation when drawing the image for the first time.
typedef enum {
NSImageCacheDefault,
NSImageCacheAlways,
NSImageCacheBySize,
NSImageCacheNever
} NSImageCacheMode;
-(void)setCacheMode:(NSImageCacheMode)mode;
-(NSImageCacheMode)cacheMode;
NSImageCacheDefault is the current behavior with bitmap and PICT cached by size and PDF cached when drawing to the screen. NSImageCacheAlways will always cache, NSImageCacheBySize will cache if the cached size is smaller than the data size. Use this when you have setDataRetained:YESto dispose of the image storage. NSImageCacheNeverwill try to never cache.

Note that depending on type of NSImageRep and the drawing composite operation and alpha (fraction), the image may still be cached. For example, PDF data can only be rendered using NSCompositeSourceOver with full alpha so NSImage will still need to cache the image in order to render with other composite operations.

Note that this setting is not encoded or decoded from a nib file if you are using the older encoding. It is saved and restored if you are using keyed coding.


NSBitmapImageRep

Support has been added for reading 1, 2, and 4 bits/sample palette based TIFF files. These images are converted to direct 8 bits/sample RGB or RGBA images when reading. Palette based TIFF files with alpha may have previously been drawn incorrectly.

Support has been added to read and write CMYK JPEG images. Additionally, gray scale JPEG image are now kept as single sample instead of converting to RGB.

Support has been added to read and write 16 bit/sample TIFF images.

Checking image files without type info for whether they are TIFF is now a little more strict. In theory this should be harmless; but, if the previous, looser behavior is desired, the preference NSLooseTIFFChecking can be set with value YES.

-[NSBitmapImageRep setProperty:withValue:] now accepts a value of nil which means you can clear out properties such as ColorSync data.


Animated GIFs

Support has been added to NSBitmapImageRep for animated GIFs. If an NSBitmapImageRep is created from a multi-frame animated GIF file or data, then the image rep will have 3 additional properties:
  NSImageFrameCount
NSImageCurrentFrame
NSImageCurrentFrameDuration
You check for an animated GIF by seeing if the property NSImageFrameCount exists. If it does, it will be an integer NSNumber containing the number of frames. NSImageCurrentFrame returns an integer NSNumber that contains the current frame starting with frame 0 and NSImageCurrentFrameDuration returns the duration of that frame as a floating point NSNumber in seconds. To change to a different frame, set the NSImageCurrentFrame property to the one you want and then check the NSImageCurrentFrameDuration property for the new frame's duration.

Note that there is overhead since the original data needs to be kept around so that each frame can be rendered and if you end up caching the image that contains the rep, changing the current frame wil have no effect on the cached image. Also note that rendering is most efficient when advancing frame by frame. Jumping to an arbitrary frame may take longer.

Here's are some methods on NSImage you can add that may simplify access:
@implementation NSImage(AnimatedImageExtension)
- (int)frameCount {
NSBitmapImageRep* imageRep = [[self representations] objectAtIndex:0];
id property = [imageRep valueForProperty:NSImageFrameCount];
return property != nil ? [property intValue] : 0;
}
- (int)currentFrame {
NSBitmapImageRep* imageRep = [[self representations] objectAtIndex:0];
id property = [imageRep valueForProperty:NSImageCurrentFrame];
return property != nil ? [property intValue] : 0;
}
- (void)setCurrentFrame:(int)frame {
NSBitmapImageRep* imageRep = [[self representations] objectAtIndex:0];
[imageRep setProperty:NSImageCurrentFrame withValue: [NSNumber numberWithInt:frame]];
}
- (float)frameDuration {
NSBitmapImageRep* imageRep = [[self representations] objectAtIndex:0];
id property = [imageRep valueForProperty:NSImageCurrentFrameDuration];
return property != nil ? [property floatValue] : 0.0;
}
@end

Incremental Image loading

API has been added to support incremental image loading. Currently, only JPEG images can be loaded this way but GIF and PNG will be added in the future. The API is in two parts. The NSImage API is meant for clients that either don't have their own data source or go can through NSURLHandle. The direct API is used for clients that can provide their own data directly. While simpler, the NSBitmapImageRep API is synchronous.

The following are a set of delegate methods for NSImage that are called as the image is loading. The are used when first drawing NSImages created via initByReferencingFile: and a new method initByReferencingURL:.
typedef enum {
NSImageLoadStatusCompleted,
NSImageLoadStatusCancelled,
NSImageLoadStatusInvalidData,
NSImageLoadStatusUnexpectedEOF,
NSImageLoadStatusReadError
} NSImageLoadStatus;
@interface NSObject(NSImageDelegate)
- (void)image:(NSImage*)image willLoadRepresentation:(NSImageRep*)rep;
- (void)image:(NSImage*)image didLoadRepresentationHeader:(NSImageRep*)rep;
- (void)image:(NSImage*)image didLoadPartOfRepresentation:(NSImageRep*)rep withValidRows:(int)rows;
- (void)image:(NSImage*)image didLoadRepresentation:(NSImageRep*)rep withStatus:(NSImageLoadStatus)status;
@end
The requirement for progressive image loading is that there be a delegate and the delegate implement the last method image:didLoadRepresentation:withStatus: so it can get a notification when the image is fully available. All the other delegate methods are optional.

If the user cancels the download or there is an error, image:didLoadRepresentation:withStatus: will still be called and the image will contain whatever part of the data is valid. If reading the header failed, the NSBitmapImageRep will remain zero sized.

If you draw the image while it is being downloaded, only the valid rows are drawn. The remainder is filled with white. You can use -[NSImage drawInRect:fromRect:operation:fraction] to trim out the picture using the validRows value.

When you first create the NSImage using a URL, it will contain a zero sized NSBitmapImageRep. When you first draw the image or otherwise require the bitmap data, image:willLoadRepresentation: is called and the image download begins. When enough data has been read to determine the size of the image, image:didLoadRepresentationHeader: is called. At this point, the NSBitmapImageRep is valid and has storage for the bitmap but the bitmap is filled with the image's background colour. As the image downloads, the delegate's image:didLoadPartOfRepresentation:withValidRows: method will be called repeatedly to inform the delegate that more of the image is available. Then when the image has been fully decompressed, the method image:didLoadRepresentation: is called.

There are two new NSImage methods. One to mirror initByReferencingFile:. Using this will archive just the URL and not the image data.
- (id)initByReferencingURL:(NSURL*)url;
This method and initByReferencingFile: allow the background download. initWithContentsOfFile: and initWithContentsOfURL: will both do synchronous downloads though initWithContentsOfURL: now supports more than just file URLs

The other method allows the immediate cancellation when downloading the image. This call has no effect if the image isn't loading.
- (void)cancelIncrementalLoad;
The following API allows a client to feed an NSBitmapImageRep data from a streaming source and have the data be decompressed. The API is intended to be minimal since only advanced clients will probably need to use it.
typedef enum {
NSImageRepLoadStatusUnknownType = -1, // not enough data to determine image format. please feed me more data
NSImageRepLoadStatusReadingHeader = -2, // image format known, reading header. not yet valid. more data needed
NSImageRepLoadStatusWillNeedAllData = -3, // can't read incrementally. will wait for complete data to become avail.
NSImageRepLoadStatusInvalidData = -4, // image decompression encountered error.
NSImageRepLoadStatusUnexpectedEOF = -5, // ran out of data before full image was decompressed.
NSImageRepLoadStatusCompleted = -6 // all is well, the full pixelsHigh image is valid.
} NSImageRepLoadStatus;
- (id)initForIncrementalLoad;
- (int)incrementalLoadFromData:(NSData*)data complete:(BOOL)complete;
First, the NSBitmapImageRep is created using -initForIncrementalLoad. This creates a 0 sized, empty, basically invalid NSBitmapImageRep with no buffer. Then the client will repeatedly call -incrementalLoadFromData:complete: with more and more data, finally passing in YES for complete: when the last chunk of data has become available. The data should be the full data, not just the new data since the decompressor may need to backtrack. This call is synchronous and will decompress as much of the image as possible based on the length of the data. The image rep does not retain the data but the data pointer should not change while inside the method.

If not enough data has been sent to determine the format, NSImageRepLoadStatusUnknownType is returned. The client should continue to call with more data.

Once enough data has been read, NSImageRepLoadStatusReadingHeader may be returned indicating that while the type is known, not enough data has been read to determine the size, depth, etc of the image. The client should continue to call with more data. If it turns out that the format does not support incremental loading, then the NSImageRepLoadStatusWillNeedAllData will be returned. Until you call -incrementalLoadFromData:complete: with YES, this status will be returned though you can continue to call it but no decompression will take place. Once you do call it with YES, then the image will be decompressed and one of the final three status messages will be returned.

If the format does support incremental loading, then once enough data has been read, the image is decompressed from the top down a row at a time. The image rep's information will be valid including pixelsHigh, pixelsWide, size, bitsPerSample, etc including the bitmap data. During this time, -incrementalLoadFromData:complete: will return the number of rows that have been decompressed from the top of the image. You can use this information to draw the part of the image that is valid. The rest of the image will be filled with opaque white. Note that if the image is progressive, you may quickly get the full pixelsHigh value but the image will still be loading so do not use this as an indication of how much of the image remains to be decompressed.

If an error occurred while decompressing, NSImageRepLoadStatusInvalidData is returned. If complete: is YES but not enough data was available for decompression, NSImageRepLoadStatusUnexpectedEOF is returned. If enough data has been provided (regardless of the complete: flag), then NSImageRepLoadStatusCompleted is returned. When any of these three status results are returned, the NSBitmapImageRep will have been adjusted so that pixelsHigh and size as well as the bitmap data will only contain the valid pixels.

To cancel decompression, just pass in the existing data or nil and YES for complete:. If data isn't nil, as much of the remaining data will be decompressed. If you pass in nil, then decompression stops immediately, the image size is adjusted and you get back an NSImageRepLoadStatusUnexpectedEOF status.

Calling -incrementalLoadFromData:complete: after any of the three results or on an image that was initialized from any other init call will result in a NSImageRepLoadStatusCompleted result.


Private images removed

The following private images were removed from the open panel nib. If any app used them out of the AppKit framework, these images will no longer be found:
NSSimpleSaveUpArrow.tiff
NSSimpleSaveDownArrow.tiff
NXSmallFloppyEjectIcon.tiff
NXSmallHomeIcon.tiff
NXSmallFloppyIcon.tiff


NSStatusBar

Removing an item via -[NSStatusBar removeItem:] now removes the item immediately from the menu bar. This change should not affect existing applications.

A problem with an application which put up a status bar item and then becomes active when clicking on the status bar item has been fixed.


NSStepper

A problem that caused stepper values to not change if the stepper was set to not autorepeat has been fixed.


Keyboard UI

A problem where the default keyboard loop in a flipped view was upside down has been fixed.


Popup Menus

Popup button menus and their submenus now match the button's font and font size.


NSPopUpButtonCell

In 10.1.x the text in a borderless popup button is positioned 3 pixels too high. This has been fixed for applications that link against 10.2 or later.

This is a note to point out a potential bug that is not fixed in 10.2. If your application leaks any NSPopUpButtonCell instances, use of command keys later on might cause your application to crash in -[NSApplication sendEvent:]. This crash will actually occur with any NSPopUpButtonCell which has an invalid (deallocated or otherwise) controlView (NSPopUpButton).


NSMenu

New class methods have been added to NSMenu to show and hide the menu bar and find out if it's currently visible.
+ (void)setMenuBarVisible:(BOOL)visible;
+ (BOOL)menuBarVisible;

Menu Item Key equivalents

Some menu item key equivalents are reserved by the system for screen and selection grabs. You can set these key equivalents in Interface Builder but they will not be shown when running. The currently reserved key equivalents are Command-Shift-3 (aka Command-#), Command-Shift-4 (aka Command-$) and Command-Control-Shift-3 and Command-Control-Shift-4.

Recommended command key equivalents for Copy/paste ruler and font (style) commands have been changed. These used to be cmd-1, cmd-2, cmd-3, and cmd-4 respectively; because we want to leave these command keys to applications, the new recommended guidelines for these commands are:

cmd-opt-c copy style
cmd-ctrl-c copy ruler

cmd-opt-v paste style
cmd-ctrl-v paste ruler

TextEdit and Mail follow these guidelines, as well as the menu entries in the Interface Builder palette. However, not all applications on the system have been converted.

cmd-opt-H is now the recommended command key equivalent for "Hide Others".


Delegation and Notification

With AppKit classes which provide delegation and notification (such as NSWindow), if you explicitly register for certain notifications which are also used to send delegate messages, and then when you stop being a delegate, you are unregistered for those notifications. It's not clear how this will be addressed in the future, but you should be aware of this potentially unexpected behavior.


NSTextField and NSMatrix obsolete methods

The following 4 methods from NSTextView and NSMatrix are obsolete and have been removed from the headers. They will continue to work but will emit a log message when used. Use the NSView methods setNextKeyView:, nextKeyView, and previousKeyView instead.
- (void)setPreviousText:(id)anObject;
- (void)setNextText:(id)anObject;
- (id)nextText;
- (id)previousText;

NSTextField, NSTextFieldCell

You can now change the text field bezel to be the rounded style. The text field must already have setBezeled:YES set.
typedef enum {
NSTextFieldSquareBezel,
NSTextFieldRoundedBezel
} NSTextFieldBezelStyle;
@interface NSTextField
-(void)setBezelStyle:(NSTextFieldBezelStyle)bezelStyle;
-(NSTextFieldBezelStyle)bezelStyle;
@end
@interface NSTextFieldCell
-(void)setBezelStyle:(NSTextFieldBezelStyle)bezelStyle;
-(NSTextFieldBezelStyle)bezelStyle;
@end

In Mac OS X 10.1, a NSTextFieldCell in a control would draw its focus ring if its control was being edited. For complex controls with multiple text fields this caused the focus ring to be drawn many times, resulting in a dark focus ring without the desired soft edges. This has been fixed. NSTextFieldCell now checks its 'showsFirstResponder' attribute to determine if it should draw the focus ring when the control is being edited. If you notice that your focus rings don't show up anymore, you can call cell's setShowsFirstResponder: with a value of YES.


Dock Menu

In 10.2, an action sent from a custom dock menu has the NSMenuItem as its sender. In 10.1, the sender was always NSApp.


NSApplication

There is now a better distinction made between document-modal sessions and application-modal sessions. This fixes problems where a sheet on an application-modal window would break the application modality. One result of this change is that -[NSApplication modalWindow] will no longer return a sheet window. If you need access to a sheet window, you may be able to use -[NSWindow attachedSheet].

If you need compatibility with 10.1 because you are relying on -[NSApplication modalWindow] to return a sheet, or because you call -[NSApplication endSheet:returnCode:] to terminate application-modal sessions, you can set the user default NSModalCompatibilityWithMacOS10.1 to YES.

-requestUserAttention: will now cause a spoken notification if spoken notifications are enabled. This is in addition to the existing dock animation behavior.


SEL Arguments

Foundation has been inconsistent in its handling of NULL SEL arguments in the past. In 10.2, for applications linked on 10.2 or later, Foundation raises exceptions in all functions and methods (such as NSObjects -respondsToSelector:) that take SEL arguments if the SEL argument is NULL.


NSOpenGL

Four new constants have been added to NSOpenGLPixelFormat:
NSOpenGLPFASampleBuffers      =  55
NSOpenGLPFASamples = 56
NSOpenGLPFAAuxDepthStencil = 57
NSOpenGLPFAVirtualScreenCount = 128
Two new constants have been added to NSOpenGLContextParameter:
NSOpenGLCPSurfaceOrder        = 235
NSOpenGLCPSurfaceOpacity = 236
The following methods allow the context to be shifted between virtual screens.
- (void)setCurrentVirtualScreen:(int)screen;
- (int)currentVirtualScreen;
This new method allows you to create a new texture with identifier target from the contents of an NSView associated with the NSOpenGLContext.
- (void)createTexture:(unsigned long/*GLenum*/)target fromView:(NSView*)view internalFormat:(unsigned long/*GLenum*/)format;

NSBezierPath

Performance note. If you have a bezier path with a lot of intersecting segments, the time to draw the path might be a lot more than the time to draw multiple paths which have less segments each but the same number total. The intersection comparisons and subsequent rasterization are the cause of the slowdown.

If you notice performance issues with NSBezierPaths that have a lot of segments, and you don't care too much about the absolute correctness of the rendering of intersections, you might want to use smaller segments.


NSGraphics function

The function declaration NSCopyBitmapFromGState is removed from NSGraphics.h. The function implementation was removed in the early stage of Mac OS X development.





Notes specific to MacOS X 10.1

Versioning

NSApplication.h now declares NSAppKitVersionNumber, which can be used to detect different versions of the AppKit framework (to per-build granularity; there are many builds between public releases). There's also a symbolic value for the Mac OS X 10.0 version of the AppKit:
/* The version of the AppKit framework */
APPKIT_EXTERN double NSAppKitVersionNumber;
#define NSAppKitVersionNumber10_0 577
Clients can compare against this to determine whether they are running on 10.0 or on a newer version. Note that some individual headers for other objects and components may also declare the versions numbers for NSAppKitVersionNumber where some bug fix or functionality is available in a given update, for example:
#define NSAppKitVersionWithSuchAndSuchBadBugFix 582.1
Although NSAppKitVersionNumber was not declared in the header files in 10.0, it is still available and can be accessed by applications at runtime. If you are compiling on 10.0, you can declare this variable yourself.

In general you should compare against a version number which you know fixes the problem you are checking for, rather than the exact version of the last external release. As an example, although 10.0 through 10.0.4 all have AppKit version 577, a 577.1 might get released to fix some bug in a future 10.0.x. This is just an example, but this has happened with other frameworks updated in the various 10.0.x software updates.


Keyboard UI

10.1 brings the keyboard navigation feature of Cocoa back to life. Users can now use tab, shift-tab, and various control keys (user settable; see Preferences) to navigate between user interface elements. For instance, using the default settings, ctrl-F2 takes focus to the menu bar and ctrl-F5 takes focus to the toolbar. Note that by default, full keyboard navigation is disabled, and users can only tab between text elements and lists. Hitting ctrl-F1 enables full navigation.

As was the case before, for windows which have an initialFirstResponder set, the kit assumes there is a valid keyboard navigation loop and uses the existing loop. If you have windows with an initialFirstResponder in which you have added or deleted UI elements, the navigation might be messed up.

In windows without an initialFirstResponder, the kit will create a keyboard UI loop for you.

We support a way that custom controls can add a keyboard focus ring around text, graphics, and images. For instance, see keyboard focus in toolbars. This function sets a 'style' in the current graphics context in the current locked focus view which affects all rendering until the graphics state is restored.
typedef enum {
NSFocusRingOnly = 0,
NSFocusRingBelow = 1,
NSFocusRingAbove = 2
} NSFocusRingPlacement;
void NSSetFocusRingStyle(NSFocusRingPlacement placement);
The placement indicates how the focus ring will be drawn. Use NSFocusRingAbove to draw over an image, use NSFocusRingBelow to draw the focus ring under text, and use NSFocusRingOnly if you don't have an image or text. For the NSFocusRingOnly case, fill a shape to add the focus ring around the shape.

Note that the focus ring may actually be drawn outside the view but will be clipped to any clipping superview or the window content view.

Because the focus ring may be drawn outside the view, use the following NSView method to invalidate the area around the focus ring.
-(void)setKeyboardFocusRingNeedsDisplayInRect:(NSRect)rect;
Pass in the rectangle of the control or cell and it will be expanded and invalidated.


NSDocument

In 10.1, NSDocument adds the following end-user features: Hidden file extensions, ability to track documents, folders, and volumes which are renamed, and ability to save documents in a way which preserves aliases to the documents and additional document info (such as icon locations). The recents menu also supports tracking of documents. These features and changes are discussed below. Note that most of these features can be supported in non-NSDocument based applications as well with varying degrees of work. TextEdit, which is not NSDocument based, has some (but not all) of these features; you can find its sources in /Developer/Examples/AppKit/TextEdit.


NSDocument now provides support for the concept of hidden file name extensions, which has been introduced in Mac OS X version 10.1. This feature allows file extensions to be hidden on a per-file basis, which provides cross-platform and web compatibility of files while freeing the users from having to deal with and see extensions. For instance, by default, the user-visible display name of RTF files saved by TextEdit do not have the ".rtf" extension.

There is additional API in NSSavePanel, NSFileManager, and NSDocument to support this feature. The NSSavePanel changes are described further below; NSFileManager changes are described in the Foundation release notes.

In NSDocument, two new methods have been added to support this feature:
- (BOOL)fileNameExtensionWasHiddenInLastRunSavePanel;
Returns YES if a save panel has been presented by this document, and the user chose to hide the name extension of the file that was selected in that save panel. Returns NO otherwise.
- (NSDictionary *)fileAttributesToWriteToFile:(NSString *)fullDocumentPath
ofType:(NSString *)documentTypeName
saveOperation:(NSSaveOperationType)saveOperationType;
Returns the file attributes that should be written to the named document file of the specified document type, as part of a particular type of save operation. The set of valid file attributes is a subset of those understood by the NSFileManager class. Invokers of this method should silently ignore invalid attributes. Of particular interest is the NSFileExtensionHidden attribute, which is documented in the Foundation release notes.

In addition, the behavior of one NSDocument method has changed to support hidden file extensions: -[NSDocument displayName] now returns a displayable document name that takes into account whether or not the document file's name extension should be hidden.

In version 10.1, the dictionary returned by the default implementation of this method will contain an NSFileExtensionHidden entry when that is appropriate. Your subclass of NSDocument can override this method to control the attributes that are set during a save operation. An override of this method should return a copy of the dictionary returned by its superclass' version of this method, with appropriate alterations.

An override of the -writeWithBackupToFile:ofType:saveOperation: method should invoke this method and set the returned attributes on the written document file, possibly using the -[NSFileManager changeFileAttributes:atPath:] method.

Implementers of overrides of this method should not assume that:
- The file pointed to by fullDocumentPath at the moment the method is invoked, if there is one, is related to the document itself. It may be an unrelated file that is about to be overwritten.
- -fileName or -fileType will return anything useful at the moment.


NSDocument now implements document saving in a way that preserves, when possible, various attributes of each document, including:
- Creation date.
- Permissions/privileges.
- The location of the document's icon in its parent folder's Icon View Finder window.
- The value of the document's Show Extension setting.

Care is also taken to save documents in a way that does not break any user-created aliases that may point to documents.

As a result, some methods in any subclass of NSDocument may now be invoked with parameters that are different from what would have been used in the past. For example, it is now more important than ever that overrides of -writeToFile:ofType:originalFile:saveOperation: and -writeToFile:ofType: make no assumptions about the file paths that are passed as parameters, including:
- The location to which the file is being written. Likely as not the file is being written to a hidden temporary directory.
- The name of the file being written. It is possible that the file name will have no obvious relation to the document name.
- The relation of any file path being passed, including originalFile, to the return value of [self fileName].

For backwards binary compatibility, NSDocument will exhibit nearly the exact same behavior as it did in Mac OS 10.0, when running in programs that were linked against the Mac OS 10.0 version of the AppKit or Cocoa framework.


Open documents now have the ability to track the files from which they were opened (or to which they were most recently saved) so that they withstand the sort of moving and renaming of documents, folders, and volumes that the user can do with the Finder. This feature manifests itself in the user interface in two ways:
- If the user uses the Finder to move or rename an open document, a containing folder, or the volume, the document window's title and document location menu (as seen when you command-click on the window title) will be updated automatically when the application is reactivated.
- When the users attempts to save a document after any of the above operations have been performed, an appropriate alert panel may be presented to let the user select an appropriate action.

As a result of this addition, instances of NSDocument will be sent several messages, -setFileName: in particular, more frequently than they have been in the past.


The -fileAttributesToWriteToFile:ofType:saveOperation: method mentioned above can be overridden to specify that a creator code and/or file type code should be written to a file as it is being saved. See the Foundation release notes for descriptions of the new NSFileHFSCreatorCode and NSFileHFSTypeCode file attributes. NSDocument's implementation of -fileAttributesToWriteToFile:ofType:saveOperation: returns zeroed-out creator and file type codes, effectively excluding creator code and file type code from the attribute preservation described above.

-[NSDocument runModalPageLayoutWithPrintInfo:delegate:didRunSelector:contextInfo:] will now present the page layout panel application-modally if there is no document window to which it can be presented document-modally.


There was a bug in which the value of the originalFile parameter was incorrect during invocations of -writeToFile:ofType:originalFile:saveOperation: that took place during Save As operations. It was always either nil or a path to a file being overwritten. Now it is the path to the document's current location on disk, or nil if the document has never been saved before.


NSDocumentController

At the time of the release of Mac OS X, version 10.0, the Mac OS X Cocoa AppKit Release Notes claimed that:

"NSDocumentController's -fileExtensionsFromType: now returns an array of file type strings that may contain encoded HFS file types as well as file name extensions. -runModalOpenPanel:forTypes: and -typeFromFileExtension: behave as they always have, but will now accept file type strings that contain encoded HFS file types as well as file name extensions. -openDocumentWithContentsOfFile:display: and -openDocumentWithContentsOfURL:display: now take the HFS file type of files into consideration when deciding what subclass of NSDocument should be instantiated."

That was not true, but it is true now. (The rest of the release note dealing with HFS file types was accurate.) None of the NSDocumentController methods named in that release note, except for -runModalOpenPanel:forTypes:, handled HFS file types correctly. Now, -fileExtensionsFromType:, -runModalOpenPanel:forTypes:, -typeFromFileExtension:, -openDocumentWithContentsOfFile:display:, and -openDocumentWithContentsOfURL:display: all handle HFS file types correctly.


NSDocumentController's implementation of the Open Recent menu now attempts to withstand the sort of moving and renaming of documents, folders, and volumes that the user can do with the Finder. If the user does any such operation involving the document, selection of the corresponding Open Recents menu item still results in the opening of the document.

Documents that cannot be located no longer appear in the Open Recent menu at all.

The name extensions of files shown in the Open Recent menu will also be hidden or shown as appropriate.


-[NSDocumentController reviewUnsavedDocumentsWithAlertTitle:cancellable:delegate:didReviewAllSelector:contextInfo:] now completely ignores the passed-in alert title string.


NSWindowController

There was a bug in NSWindowController in which the document name returned by an override of -[NSDocument displayName] would not be used for document window titles. That bug has been fixed.


NSSavePanel

In order to support the hidden file extension feature discussed above, a checkbox has been added to the save panel that allows the user to hide or show the extension. Existing non-NSDocument based applications will need to be modified to set the flag; by default, the checkbox is not visible. (In most cases this feature is automatically supported for NSDocument based apps.)

The new API consists of 3 methods in NSSavePanel.h:
- (void)setCanSelectHiddenExtension:(BOOL)flag;
- (BOOL)isExtensionHidden;
- (void)setExtensionHidden:(BOOL)flag;
setCanSelectHiddenExtension: shows the checkbox in the save panel. It needs to be called before runModal:, etc.

setExtensionHidden: allows the app to set the checkbox. should will rarely be used since the state is saved on a per app basis.

isExtensionHidden returns YES if the checkbox is visible and checked. This flag can be used to set the hidden extension bit in the saved files via NSFileManager API.


NSProgressIndicator

The height of the small progress indicator as generated was Interface Builder in nib files was wrong. It should be 12 instead of 10. Please open any nib files containing small progress indicators, switch the effected controls to large and back to small again, and save.


NSPDFImageRep

-[NSImage draw...] methods, when invoked on a PDF image during printing, very often created no output. This was a bug, and has been fixed.


NSPrintOperation

The NSPrintPreviewJob and NSPrintSaveJob job dispositions were not supported in Mac OS 10.0.x. They are in Mac OS 10.1.

The attribute that is accessed using -setShowPanels: and -showPanels now controls whether or not a printing progress panel is presented by -runOperation or -runOperationModalForWindow:delegate:didRunSelector:contextInfo:.


Scripting

The default value of of NSApplication's "version" scripting attribute is now the CFBundleShortVersionString entry in the application's Info property list, instead of the number zero. This value can still be overridden by the application delegate object.


NSButton

-[NSButton setKeyEquivalentModifierMask] now supports NSCommandKeyMask as an argument. When a commandKey modifier is present in a keyDown event, NSApplication now looks for a command-key equivalent in the key window before sending the event to the menu. A command-key equivalent in the key window will therefore have precedence over the same command-key equivalent in a menu. It is preferable to avoid such collisions, however.


Command-d key equivalent

NSRunAlertPanel and NSBeginAlertSheet now provide a command-d key equivalent for the "Don't save" button in the panel, if one is found. The button titles are searched for the localized value for "Don't save". If a match is found, that button is assigned a command-d key equivalent, provided it is not already the default button. (It does not work to assign both command-d and return as key equivalents for the same button, so return takes priority).

If you create a modal panel using -[NSApplication runModalForWindow:] or -[NSApplication beginSheet:modalForWindow:modalDelegate:didEndSelector:contextInfo:], you can assign the key equivalent yourself, using -[NSButton setKeyEquivalent] and -[NSButton setKeyEquivalentModifierMask:].


NSWindow

In 10.1, on multiple monitor machines, windows whose locations are being restored from saved frames will be shown on the screen where they were before being closed, assuming that there is such a screen in the current display configuration. If there is no screen approximating the location of the screen saved with the window frame, the window will be placed on the screen containing the menu bar.

-isSheet has been added to indicate when a window is a "sheet", or document modal panel. There is also a method to ask for the sheet attached to a window, -attachedSheet. If such a sheet exists, this indicates that the window is in a document modal state. If the window does not have an attached sheet, this method returns nil.

A notification is sent before a sheet is presented on a window, NSWindowWillBeginSheetNotification, and after it is dismissed, NSWindowDidEndSheetNotification.
- (BOOL)isSheet;
- (NSWindow *)attachedSheet;
A window delegate should implement the following to receive the sheet notifications:
- (void)windowWillBeginSheet:(NSNotification *)notification;
- (void)windowDidEndSheet:(NSNotification *)notification;
There was a bug in 10.0 where calling setAspectRatio: on a window would cause it to resize to the zero frame the moment you tried to resize it. As of Puma5G21 -setAspectRatio: now enforces the aspect ratio correctly for resize operations.

In 10.1, the string passed into -[NSWindow setTitle:] will be copied rather than retained by the window. This provides the correct behavior for titles set using mutable strings. However, if you depend on NSWindow to retain this string in order for your application to later modify it, you will need to retain the string yourself. Also note that modifications made after the string is passed into setTitle: will not be reflected in the title of the window.

There are known issues with window positioning and the dock. New windows frequently do not respect the dock position - especially if the dock is on the left side of the screen rather than the bottom. This can result in windows being partially obscured by the dock.

There is also a less common problem where collapsing the save panel can cause the document window to move to an unexpected location. This is a problem that is caused by failure to initialize the window position properly in some cases. You can workaround this problem in your application by positioning the document window with -[NSWindow setFrame:display:] rather than passing the positioned frame into -[NSWindow initWithContentRect:styleMask:backing:defer:].


NSScreen

We now have support for dynamic screen reconfiguration. This will allow certain models of PowerBooks to discover displays added or removed on waking from sleep. When a display is added or removed, the contents of +[NSScreen screens] will change, so applications should not cache the screens array.


NSEvent

Event types have been added for "other" mouse events. These events can be generated by an input device with more than two buttons:
NSOtherMouseDown      = 25,
NSOtherMouseUp = 26,
NSOtherMouseDragged = 27
The corresponding event masks are also defined:
NSOtherMouseDownMask      = 1 << NSOtherMouseDown,
NSOtherMouseUpMask = 1 << NSOtherMouseUp,
NSOtherMouseDraggedMask = 1 << NSOtherMouseDragged
A method has been added to get the buttonNumber for the mouse button that generated the OtherMouse event. The -buttonNumber method is intended for use with the OtherMouse events, but will return constant values for LeftMouse and RightMouse events as well:
- (int)buttonNumber;
NSResponder methods have been added for handling these events. An NSResponder subclass can implement these methods to get called when an OtherMouse event is received:
- (void)otherMouseDown:(NSEvent *)theEvent;
- (void)otherMouseUp:(NSEvent *)theEvent;
- (void)otherMouseDragged:(NSEvent *)theEvent;
-[NSEvent deltaX] and -[NSEvent deltaY] now return mouse delta for mouse move and mouse dragged events.


-[NSEvent locationInWindow] may now return NSPoints with non-integral coordinates to represent sub-pixel precision generated by some input devices, for instance tablets. -[NSDraggingInfo draggingLocation] and -[NSDraggingInfo draggedImageLocation] may also return non-integral locations. Applications should not assume that these locations will be on pixel boundaries.


NSApplication

If your application uses NSStatusItems and implements - (BOOL)applicationShouldHandleReopen:(NSApplication *)theApplication hasVisibleWindows:(BOOL)flag, there is a known problem where the hasVisibleWindows flag will always be YES even if there are no visible windows aside from the NSStatusItems.

If your application uses NSStatusItems and needs to accurately distinguish between having visible windows and not, you should add your own check in -applicationShouldHandleReopen:hasVisibleWindows:. For example, it might make sense to ask if -[NSApp mainWindow] is nil as a way to check for visible document windows.


NSApplication Dock Interaction

NSApplication has added support for applications to specify the contents of the application dock menu. This allows an application to add menu items below the list of windows in the dock menu.

An application can either specify an NSMenu in a nib, or return an NSMenu from a delegate method.

To specify an NSMenu in a nib, add the nib name to the info.plist, using the key AppleDockMenu. The nib name should be specified without an extension. There will be an IB outlet from NSApplication named dockMenu, which should be connected to the NSMenu in the nib. This menu should be in its own nib file so that it can be loaded lazily when the dockMenu is requested, rather than at launch time.

There is also an application delegate method to allow a delegate to specify the menu dynamically. If the delegate returns non-nil for this menu, it takes precedence over the dockMenu in the nib. Because this method is invoked whenever the dockMenu is to be shown, efficiency is important. The delegate should keep its own internal representation of the dock menu up to date rather than updating when this method is invoked.
- (NSMenu *)applicationDockMenu:(NSApplication *)sender;
The target and action for each menu item is passed to the dock. On selection of the menu item, the dock messages the application, which invokes [NSApp sendAction:selector to:target from:nil].

The current implementation does not yet support adding an image to a menuItem or changing the menu title based on modifier keys, which are both features desired in the dockMenu.


We now have support for "Dock Notifications", basically user notifications to allow an application that is not frontmost to request user attention. The dock supplies a new kind of app tile animation to indicate this notification.

To start a notification, an application would call:
- (int)requestUserAttention:(NSRequestUserAttentionType)requestType
requestType is either NSInformationalRequest or NSCriticalRequest. We bounce the dock icon for one second (usually one bounce) for an informational request, and until the app becomes active for a critical request. Activating the app cancels the user notification request. Making this call in an app that is already active has no effect.

The return value is a request tag that can be passed to:
- (void)cancelUserAttentionRequest:(int)request
cancelUserAttentionRequest: allows an application to cancel a previous request. request is the return value from a previous call to requestUserAttention:. In the common case, a request will be cancelled automatically by user activation of the application. This method provides the less frequently needed facility for cancelling a request without explicit activation.

The additions to NSApplication.h are:
enum {
NSInformationalRequest = 0,
NSCriticalRequest = 1
} NSRequestUserAttentionType;
- (int)requestUserAttention:(NSRequestUserAttentionType)requestType
- (void)cancelUserAttentionRequest:(int)request
If an inactive app presents a modal panel, we call -[NSApp requestUserAttention:NSCriticalRequest] automatically for the application. The modal panel is no longer brought to the front (using NSModalPanelWindowLevel) for an inactive application.


Standard About Panel

The standard about panel now supports links in the Credits area; clicking on a link causes it to be opened in the default application prepared to handle the link. You can specify the links in the attributed string you provide (as the value of the "Credits" key in the dictionary), or in a Credits.html file, which will be looked for before Credits.rtf. Note that Credits.html is not looked for in 10.0, so if you do provide one, you might also want to provide a Credits.rtf file. There is also support now for Credits.rtfd.


Alerts

In 10.1 the alert panel presented by NSRunCriticalAlertPanel and the sheet presented by NSBeginCriticalAlertSheet will badge the application icon with a caution icon. These functions should be used only as specified by the Human Interface Guidelines.


NSFileWrapper

Bug Fixes
- Improved error handling. Under some circumstances errors were being ignored during initialization (rather than returning nil) and the resulting file wrapper could cause a segfault when it was used.
- Broken, absolute links are now copied into the file wrapper instead of being treated as an error.

Known Problems
- File wrappers ignore resource forks.
- File wrappers resolve relative links - i.e. they copy the links destination rather than reproducing the link. This is especially problematic if the link is broken or if following the link results in a cycle.


NSWorkspace

A bug has been fixed in which NSWorkspace did not deliver its NSWorkspaceDidUnmountNotification if a volume was forcibly and immediately made unavailable, for example by simply unplugging a firewire drive. In this case the NSWorkspaceDidUnmountNotification will now be delivered, but the NSWorkspaceWillUnmountNotification still will not be, because there is no chance to deliver it before the volume is unmounted.


Text

The NSAttributedString methods
- (id)initWithPath:(NSString *)path documentAttributes:(NSDictionary **)dict;
- (id)initWithURL:(NSURL *)url documentAttributes:(NSDictionary **)dict;
and the NSMutableAttributedString method
- (BOOL)readFromURL:(NSURL *)url options:(NSDictionary *)options documentAttributes:(NSDictionary **)dict;
can now use filter services to convert the specified file into a format recognized by the Cocoa text system (plain text, rtf, rtfd, or html). In addition to the existing pasteboard types for plain text, rtf, and rtfd, there is now an NSHTMLPasteboardType that can be used for this purpose, and can also be read (but not written) by NSTextView. In addition to these pasteboard types, text filter services can also convert to typed filenames pasteboard types (again, of the types txt, rtf, rtfd, or html). To support the use of filter services, a @"Converted" key is supplied in the returned document attributes to indicate whether the file was converted by a filter service or not (if it was, then a text editor, for example, would probably not wish to write the file back in the same location). In addition, the following methods
+ (NSArray *)textUnfilteredFileTypes;
+ (NSArray *)textUnfilteredPasteboardTypes;
+ (NSArray *)textFileTypes;
+ (NSArray *)textPasteboardTypes;
are available to determine what types can be loaded as text.


TextView will now attempt to open links if there is no delegate or the delegate method for handling links returns NO. Note that the textview might not be able to open some links as it does not have the proper base URL in many cases.


We now handle the following new key in the documentAttributes dictionary when reading/writing files:

@"ReadOnly": NSNumber containing an int; 0 or less: editable, 1 or more: readonly. If not present, implies a value of 0, that is, editable. Note that readonly state has nothing to do with file system protection; it simply indicates how the document should be presented to the user. TextEdit has a new menu item to take advantage of this setting.


There are now first responder action methods for speaking user-visible text in Cocoa,
- (void)startSpeaking:(id)sender;
- (void)stopSpeaking:(id)sender;
implemented on NSTextView, and which can be implemented as appropriate on other responders. The NSTextView default context menu contains items to invoke these methods.


The NSTextView method
- (BOOL)shouldChangeTextInRange:(NSRange)affectedCharRange
replacementString:(NSString *)replacementString;
will now automatically return NO if the textview is not editable. This prevents some instances in which a textview could be changed by user actions even though it had been set to be non-editable. The general rule followed here is that NSTextView, as the view layer in the text system's model-view-controller structure, enforces any restrictions on interaction with the user, and is appropriately used for actions that are directly occasioned by user actions. Programmatic changes to the text which should not need those restrictions should be made at the model layer, i.e., in NSTextStorage.

One thing to keep in mind in this connection is that actions recorded on the undo stack by the text system take place at the model layer. Therefore, if a textview at any point changes from being editable to not being editable, any actions related to it still on the undo stack will still be able to be undone. If the change in editability is intended to be irreversible (for example, if it corresponds to a change being irrevocably committed to a database) then steps should be taken to remove any such undo actions at the time of the change. On the other hand, if the change in editability is reversible, then that change should itself be made undoable, so that it would be undone in the process of passing down the undo stack before reaching any items that would alter the text.


NSLayoutManager now provides a threshold for text antialiasing. It looks at default value set by Preferences. If the font size is smaller than or equal to this threshold size, the text is rendered aliased by NSLayoutManager. You can change the threshold value from System Preferences application's General pane.


NSDrawer

Several problems in NSDrawer have now been fixed. First, there was a problem that caused drawers with a maximum content size not to be able to be manually resized to that maximum size. That has been fixed. Second, there was a problem with setContentSize:, which was not interpreting its argument correctly. That has been fixed, but applications that linked against previous versions of Cocoa or AppKit will continue to use the old behavior. Third, the delegate method drawerWillResizeContents:toSize: was not being sent; now it is. For comparison with NSAppKitVersionNumber, the version number in which these changes occurred was 592.


NSColorPanel

NSColorPanel can now toggle between visible / hidden.

Any menu item that matches the default "Show Colors" menu item in IB will exhibit new behaviour. Instead of simply showing the color panel, the menu item will now toggle the visibility of the color panel. If the color panel is hidden already, it will order it front. If the color panel is already ordered front, selecting the menu item will hide the color panel.

Your "Show Colors" menu item will only exhibit this new behavior if it's target is FirstResponder and it's action is orderFrontColorPanel:. Further if your menu item's title matches the default in IB (localized comparison), "Show Colors", then menu validation will title your menu appropriately to indicate whether selecting the menu item will hide or show the color panel. If your title is not toggling appropriately, it either because the menu items title doesn't match the default from IB, or you have a custom subclass of NSApplication that overrides validateMenuItem: and does not call [super validateMenuItem:].


NSFontPanel

NSFontPanel can now toggle between visible / hidden.

Any menu item that matches the default "Show Fonts" menu item in IB will exhibit new behaviour. Instead of simply showing the font panel, the menu item will now toggle the visibility of the font panel. If the font panel is hidden already, it will order it front. If the font panel is already ordered front, selecting the menu item will hide the font panel.

Your "Show Fonts" menu item will only exhibit this new behavior if it's target is the shared NSFontManager object (The "A", or "Font Manager" icon in your IB document) and it's action is orderFrontFontPanel:. Further if your menu item's title matches the default in IB (localized comparison), "Show Fonts", then menu validation will title your menu appropriately to indicate whether selecting the menu item will hide or show the font panel. If your title is not toggling appropriately, it probably because the menu items title doesn't match the default from IB.


NSTabView

NSTabView's controlSize method was incorrectly declared as: -(NSControlTint)controlSize. It is now correctly declared as: -(NSControlSize)controlSize. This change will not break compatability as NSControlTint and NSControlSize are both the same size.


Users can now navigate a tab view and it's items using the keyboard. Using the tab key, users can place keyboard focus on an NSTabView and switch between tab items by pressing the arrow keys. With focus on the tab view itself, hitting tab will take the user to the selected item's initialFirstResponder. Continuing to tab will take users through the keyloop you have defined, eventually leading a user out of the NSTabView (usually the view connected as the tab view's nextKeyView in IB).

There are a couple of details that should be mentioned:

- The initially provided nextKeyView of a NSTabView is remembered as the "original next key view".

- Each NSTabViewItem should provide an initialFirstResponder and a valid keyboard loop. If you do not prvide one, it is assumed you have in fact not provided any keyboard loop. Therefore, a keyboard loop will automatically be created.

- The last key view in a NSTabViewItem's loop will be given the "original next key view" as its next key view. If there is no original next key view, the last key view's will be wired to the tab view itself.

- The keyboard loop you provide should not contain cycles. If found, the cycle may be broken, so that tabbing past the last key view will take users out of the tab view. The location the cycle is broken will be considered the item's last key view.

- The keyboard loop you define should not lead outside of a NSTabViewItems view. If this is detected, the link causing keyboard focus to leave the view may be broken. This location will be considered the item's last key view.

Summary: Each NSTabView should have an original next key view (usually provided in IB). Each NSTabView items should be given an initialFirstResponder, and a valid keyboard loop. Typically using the tab key will take user to the tab, through the selected items keyboard loop, and then out the other side.


NSCell

NSCell has support for drawing the proper highlight color in non-key windows. This method return the color to use when drawing a selection highlight:
- (NSColor *)highlightColorWithFrame:(NSRect)cellFrame inView:(NSView *)controlView;
In the past developers typically assumed that the color use was [NSColor selectedControlColor]. However, now some controls want to draw with different selection highlight colors depending on things such as key state of the controlView in which the cell is displayed. In order to be sure you are using the correct selection highlight color, you should search your existing code for places that assume the use of [NSColor selectedControlColor].


NSBrowser

The setPath: contains a bug fix, which causes a slight, yet desirable change in behavior. The method should, and now does, return YES whenever path is valid, and NO otherwise (previously it return NO if a leaf was matched).

While parsing the string, NSBrowser tries to locate matching entries in its columns. If an exact match is found, the match will be selected and the next entry will be processed. The algorithm proceeds until finished with the string, or until an entry can't be matched.


NSTableView

Table views and outline views now allow you to drag entries without the application being active. This change only affects clients using the row/item based dragging APIs. Dragging from such a table now acts more like NSTextViews implementation of dragging. If you app is not active, and the users can now drag from your table. If they simply click, the selection will not be affected. In this situation you app will become active, but the selection will not change.

To facilitate this feature, NSTableView now implements:
- (void)shouldDelayWindowOrderingForEvent:(NSEvent *)theEvent;
- (BOOL)acceptsFirstMouse:(NSEvent *)theEvent;

NSPDFImageRep

The size of the image rep is now set from the PDF's crop box instead of the media box. If they didn't match, you may find the image appears larger.


NSMovie

-[NSMovie initWithURL:byReference:] will now accept and play network based URLs (http:, rtsp:, etc.). When starting to play the movie, the NSMovieView will not is not resized. You will need to register with the movieController to receive a callback when the size changes dynamically and update the NSMovieView to match.


NSView

NSView now has live resizing API:
- (void)viewWillStartLiveResize
- (void)viewDidEndLiveResize
These methods will be sent to a view before live resize starts, and after it ends. In the simple case, a view will be sent viewWillStartLiveResize before the first resize operation on the containing window, and viewDidEndLiveResize after the last resize operation. A view that is repeatedly added and removed from a window during live resize will receive only one viewDidStartLiveResize message (on the first time it is added to the window) and one viewDidEndLiveResize message (when the window has completed the live resize operation). This allows a superview such as NSBrowser to add and remove its NSMatrix subviews during live resize without NSMatrix receiving multiple calls to these methods.

A view might allocate data structures to cache drawing information in viewWillStartLiveResize, and should clean up these data structures in viewDidEndLiveResize. In addition, a view that does optimized drawing during live resize might want to do full drawing after viewDidEndLiveResize, although a view should not assume that it has a drawing context in viewDidEndLiveResize (since it may have been removed from the window during live resize). A view that wants to redraw itself after live resize should call [self setNeedsDisplay:YES] in viewDidEndLiveResize.

A view subclass should call super from these methods.
- (BOOL)inLiveResize
This is a convenience method, expected to be called from -drawRect: to make decisions about optimized drawing.

NSView's unlockFocus method now raises NSInvalidArgumentException exception if the method is invoked on a wrong view.

Also see elsewhere in this document for discussion of the new method setKeyboardFocusRingNeedsDisplayInRect:.


NSOpenGLPixelFormat

initWithAttributes: will now return nil if the format attributes provided aren't supported or conflict. It previously returned a valid format but created with no attributes which mean no depth buffer.

Please note that the NSOpenGLPixelFormat methods -initWithData:, -setAttribute:, and -attributes are deprecated and will be removed in a future release. It is also not recommended that you archive an NSOpenGLPixelFormat.

There are two new NSOpenGLPixelFormatAttribute enum values which are not listed in the headers but available in Mac OS X 10.1:
NSOpenGLPFASampleBuffers = 55
NSOpenGLPFASamples = 56
These are for GL_ARB_multisample support.


NSFont

Although NSFonts are long-living instances which never go away, they should be retained and released just like any other autoreleased return --- for instance, NSColors. If this is done properly, at some point we will be able to make NSFonts truly autoreleased, allowing them to go away when no longer needed.

-[NSFont descender] method used to return the value with the line gap (leading) added for Japanese Hiragino font family in 10.0. In 10.1 the method returns the correct descender value specified in the font. In order to get the default line height that should include the ascender, descender, and leading, use -[NSFont defaultLineHeightForFont] method.


NSColor

NSColor now has a secondarySelectedControlColor method, providing somewhat dimmed color used to display selections in tableview, browser, etc when inactive. In addition, NSColor's disabledControlTextColor method now correctly archives itself. These colors can be unarchived on all systems, back to 10.0.


NSStatusBar

NSStatusBar allows you to place persistent UI elements in the menu bar. There are a few important things to note.

1. Just like with Apple's status bar items, you should allow provide a user preference for any status bar items you intend to display. This way, even if the user installs many applications with status bar items, they can choose the ones they want to see.

2. Space in the menu bar is a precious commodity. Depending on the size of the menu of the active application and the user's display size, your status bar items might get clipped and not get displayed. In addition, other factors might cause status bar items to stop displaying permanently in a future release. Because of these reasons, don't count on the status bar item as the sole way to inform the user of status. This is reasonable, considering #1 above.

3. The location and size of status bar items might change in a future release. Don't make too many assumptions about the location and size of these items.



NSScroller

NSScrollArrowPosition enum has been changed in order to accomodate the additional style introduced in 10.1 (arrows together). Note that NSScrollerArrowsMaxEnd and NSScrollerArrowsMinEnd values are now deprecated. You can only access NSScrollerArrowsNone or NSScrollerArrowsDefaultSetting. NSScrollerArrowsDefaultSetting gets the configuration from user's preferences.


NSSplitView

NSSplitView now tiles its subviews and splitters correctly. -[NSSplitView drawDividerInRect:] used to receive the height that is 2 pixel higher than the value returned from -dividerThickness.


String Drawing

In releases prior to 10.1, there were cases in which -[NSString drawAtPoint:withAttributes:] and -[NSAttributedString drawAtPoint:] would shift the point at which the string was drawn, or clip the string incorrectly, if the point was specified so as to place the string partly or wholly outside of the bounds of the current focused view. This has been fixed in 10.1.

One caution is that the behavior of NSRightTextAlignment and NSCenterTextAlignment paragraph styles with the drawAtPoint: calls is not well-defined. If you wish to use these alignment styles with string drawing, we strongly recommend the use of the drawInRect: string drawing calls rather than the drawAtPoint: variants. For backward compatibility, the string drawing implementation in 10.1 attempts to mimic the behavior of previous releases when right or center justification is used with drawAtPoint: calls, but this behavior is not guaranteed and may change from release to release.



Notes specific to MacOS X 10.0


NSToolbar

NSToolbar and NSToolbarItem are new classes which provide a mechanism for creating standard toolbars you can attach to titled windows.

To create a NSToolbar you will need to provide a delegate that can provide NSToolbarItems on demand, and answer a number of important questions. First, a toolbar's delegate provides, by identifier, the list of default toolbar items. This list is used when reverting to default, and constructing the initial toolbar. Next, the delegate provides the list of allowed item identifiers. The allowed item list is used to construct the customization palette, if the toolbar is customizable. Finally, the delegate must implement the method that returns NSToolbarItems for a given item identifier.

When you create an NSToolbar you give it an identifier. NSToolbar assumes all toolbars with the same identifier are the same, and automatically synchronizes changes. For instance, consider writing a Mail application. Your applications compose window toolbar would have the same identifier string. So, when you re-order items in one toolbar, the changes automatically propagate to any other compose windows currently open.

Most toolbars will contain simple clickable items. The simplest NSToolbarItem is defined by its icon, label, palette label (used in the customize sheet), target, action, tooltip and other attributes. Most toolbars can sufficiently be represented using these simple button-like items. However, if you need something custom in your toolbar, it is possible. Custom views are provided by calling setView: on NSToolbarItem. For instance, if you want your development tool to have a pop for selecting build styles, you can provide your toolbar item with a NSPopupButton.

There are a couple of standard item identifiers that NSToolbar knows about. NSToolbarSeparatorItemIdentifier is the identifier for the standard vertical line separator. NSToolbarSpaceItemIdentifier represents a fixed width space that can be dragged into the toolbar. NSFlexibleSeparatorItemIdentifier represents a variable width space. There is al