Merge pull request #10 from gunyarakun/fix-invalid-return
[cocotron.git] / AppKit / NSToolbar.subproj / NSToolbarItem.m
blobb9a13a9136fb5508dc155e832dc289caf0e64340
1 /* Copyright (c) 2006-2009 Christopher J. W. Lloyd <cjwl@objc.net>
3 Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
5 The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
7 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
8 #import <AppKit/NSToolbarItem.h>
9 #import <AppKit/NSToolbar.h>
10 #import <AppKit/NSToolbarItemView.h>
11 #import <AppKit/NSMenuItem.h>
12 #import <AppKit/NSImage.h>
13 #import <AppKit/NSColor.h>
14 #import <AppKit/NSDocument.h>
15 #import <AppKit/NSStringDrawing.h>
16 #import <AppKit/NSStringDrawer.h>
17 #import <AppKit/NSApplication.h>
18 #import <AppKit/NSFontManager.h>
19 #import <AppKit/NSAttributedString.h>
20 #import <AppKit/NSRaise.h>
21 #import <AppKit/NSGraphicsContext.h>
23 NSString * const NSToolbarCustomizeToolbarItemIdentifier=@"NSToolbarCustomizeToolbarItem";
24 NSString * const NSToolbarFlexibleSpaceItemIdentifier=@"NSToolbarFlexibleSpaceItem";
25 NSString * const NSToolbarPrintItemIdentifier=@"NSToolbarPrintItem";
26 NSString * const NSToolbarSeparatorItemIdentifier=@"NSToolbarSeparatorItem";
27 NSString * const NSToolbarShowColorsItemIdentifier=@"NSToolbarShowColorsItem";
28 NSString * const NSToolbarShowFontsItemIdentifier=@"NSToolbarShowFontsItem";
29 NSString * const NSToolbarSpaceItemIdentifier=@"NSToolbarSpaceItem";
31 extern NSSize _NSToolbarSizeRegular;
32 extern NSSize _NSToolbarSizeSmall;
33 extern NSSize _NSToolbarIconSizeRegular;
34 extern NSSize _NSToolbarIconSizeSmall;
36 @interface NSToolbar(private)
37 -(NSView *)_view;
38 -(void)itemSizeDidChange;
39 -(NSDictionary *)_labelAttributes;
40 -(NSDictionary *)_labelAttributesForSizeMode:(NSToolbarSizeMode)sizeMode;
41 @end
43 @implementation NSToolbarItem
45 extern NSSize _NSToolbarIconSizeRegular;
46 extern NSSize _NSToolbarIconSizeSmall;
48 -(void)_configureAsStandardItemIfNeeded {
49    if ([_itemIdentifier isEqualToString:NSToolbarSeparatorItemIdentifier]){
50     NSSize size;
51     
52     [self setLabel:@""];
53         [self setPaletteLabel: NSLocalizedStringFromTableInBundle(@"Separator", nil, [NSBundle bundleForClass: [NSToolbarItem class]], @"Describes a toolbar separator item")];
54     [self setEnabled:NO];
55     
56     size = [self minSize];
57     size.width = floor(size.width/2);
58     [self setMinSize:size];
59     size = [self maxSize];
60     size.width = floor(size.width/2);
61     [self setMaxSize:size];
62     
63    }
64    else if ([_itemIdentifier isEqualToString:NSToolbarSpaceItemIdentifier]){
65     NSSize size;
66     
67     [self setLabel:@""];
68     [self setPaletteLabel: NSLocalizedStringFromTableInBundle(@"Space", nil, [NSBundle bundleForClass: [NSToolbarItem class]], @"Describes a toolbar space item")];
69     [self setEnabled:NO];
71     size = [self minSize];
72     size.width /= 2;
73     [self setMinSize:size];
74     size = [self maxSize];
75     size.width /= 2;
76     [self setMaxSize:size];
77     
78    }
79    else if ([_itemIdentifier isEqualToString:NSToolbarFlexibleSpaceItemIdentifier]){
80     NSSize size;
81     
82     [self setLabel:@""];
83     [self setPaletteLabel: NSLocalizedStringFromTableInBundle(@"Flexible Space", nil, [NSBundle bundleForClass: [NSToolbarItem class]], @"Describes a toolbar flexible space item")];
84     [self setEnabled:NO];
85     
86     size = [self minSize];
87     size.width /= 2;
88     [self setMinSize:size];
89     [self setMaxSize:NSMakeSize(-1, [self maxSize].height)];
90     
91    
92    }
93    else if ([_itemIdentifier isEqualToString:NSToolbarShowColorsItemIdentifier]){
94     [self setLabel: NSLocalizedStringFromTableInBundle(@"Colors", nil, [NSBundle bundleForClass: [NSToolbarItem class]], @"Reveals a color picker")];
95     [self setPaletteLabel: NSLocalizedStringFromTableInBundle(@"Show Colors", nil, [NSBundle bundleForClass: [NSToolbarItem class]], @"Reveals a color picker")];
96     [self setTarget:[NSApplication sharedApplication]];
97     [self setAction:@selector(orderFrontColorPanel:)];
98     [self setImage:[NSImage imageNamed:NSToolbarShowColorsItemIdentifier]];
99     [self setToolTip: NSLocalizedStringFromTableInBundle(@"Show the Colors panel.", nil, [NSBundle bundleForClass: [NSToolbarItem class]], @"Reveals a color picker")];
100    }
101    else if ([_itemIdentifier isEqualToString:NSToolbarShowFontsItemIdentifier]){
102     [self setLabel: NSLocalizedStringFromTableInBundle(@"Fonts", nil, [NSBundle bundleForClass: [NSToolbarItem class]], @"Reveals a font picker")];
103     [self setPaletteLabel: NSLocalizedStringFromTableInBundle(@"Show Fonts", nil, [NSBundle bundleForClass: [NSToolbarItem class]], @"Reveals a font picker")];
104     [self setTarget:[NSFontManager sharedFontManager]];
105     [self setAction:@selector(orderFrontFontPanel:)];
106     [self setImage:[NSImage imageNamed:NSToolbarShowFontsItemIdentifier]];
107     [self setToolTip: NSLocalizedStringFromTableInBundle(@"Show the Fonts panel.", nil, [NSBundle bundleForClass: [NSToolbarItem class]], @"Reveals a font picker")];
108    }
109    else if ([_itemIdentifier isEqualToString:NSToolbarCustomizeToolbarItemIdentifier]){
110     [self setLabel: NSLocalizedStringFromTableInBundle(@"Customize", nil, [NSBundle bundleForClass: [NSToolbarItem class]], @"Reveals a toolbar customization dialog")];
111     [self setPaletteLabel: NSLocalizedStringFromTableInBundle(@"Customize", nil, [NSBundle bundleForClass: [NSToolbarItem class]], @"Reveals a toolbar customization dialog")];
112     [self setTarget:nil];
113     [self setAction:@selector(runToolbarCustomizationPalette:)];
114     [self setImage:[NSImage imageNamed:NSToolbarCustomizeToolbarItemIdentifier]];
115     [self setToolTip: NSLocalizedStringFromTableInBundle(@"Customize this toolbar.", nil, [NSBundle bundleForClass: [NSToolbarItem class]], @"Reveals a toolbar customization dialog")];
116    }
117    else if ([_itemIdentifier isEqualToString:NSToolbarPrintItemIdentifier]){
118         [self setLabel: NSLocalizedStringFromTableInBundle(@"Print", nil, [NSBundle bundleForClass: [NSToolbarItem class]], @"")];
119         [self setPaletteLabel: NSLocalizedStringFromTableInBundle(@"Print Document", nil, [NSBundle bundleForClass: [NSToolbarItem class]], @"")];
120     [self setTarget:nil];
121     [self setAction:@selector(printDocument:)];
122     [self setImage:[NSImage imageNamed:NSToolbarPrintItemIdentifier]];
123     [self setToolTip: NSLocalizedStringFromTableInBundle(@"Print this document.", nil, [NSBundle bundleForClass: [NSToolbarItem class]], @"")];
124    }
127 -initWithItemIdentifier:(NSString *)identifier {
128    _itemIdentifier=[identifier retain];
129    _toolbar=nil;
130    _enclosingView=[[NSToolbarItemView alloc] init];
131    [_enclosingView setToolbarItem:self];
132    _image=nil;
133    _label=@"";
134    _paletteLabel=@"";
135    _target=nil;
136    _action=NULL;
137    _menuFormRepresentation=nil;
138    _view=nil;
139    _minSize=NSZeroSize;
140    _maxSize=NSZeroSize;
141    _visibilityPriority=NSToolbarItemVisibilityPriorityStandard;
142    _autovalidates=NO;
143    _isEnabled=YES;
144    [self _configureAsStandardItemIfNeeded];
145    
146    return self;
149 -(void)dealloc {
150    [_itemIdentifier release];
151    _toolbar=nil;   
152    [_image release];
153    [_label release];
154    [_paletteLabel release];
155    [_menuFormRepresentation release];    
156    [_view release];
157    [super dealloc];
160 -copyWithZone:(NSZone *)zone {
161 // FIXME: copying views, ugh
162    NSToolbarItem *copy=NSCopyObject(self, 0, zone);
164    copy->_itemIdentifier=[_itemIdentifier copy];
165    copy->_toolbar=nil;
166    copy->_image=[_image copy];
167    copy->_label=[_label copy];
168    copy->_paletteLabel=[_paletteLabel copy];
169    copy->_menuFormRepresentation=[_menuFormRepresentation copy];
170    copy->_view=[_view copy]; 
171     
172    return copy;
175 -(NSView *)_enclosingView {
176    return _enclosingView;
179 -(void)_setToolbar:(NSToolbar *)toolbar {
180    _toolbar = toolbar;
183 -(NSString *)itemIdentifier {
184    return _itemIdentifier;
187 -(NSToolbar *)toolbar {
188    return _toolbar;
191 -(NSString *)label {
192    return _label;
195 -(NSString *)paletteLabel {
196    return _paletteLabel;
199 // By default, this method returns a singleton menu item with item label as the title.  For standard items, the target, action is set.
200 - (NSMenuItem *)menuFormRepresentation
202     // FIX should update standard item for action/target/label changes?
203     if (_menuFormRepresentation == nil && [self label] != nil) {
204         _menuFormRepresentation = [[NSMenuItem alloc] initWithTitle:[self label] action:[self action] keyEquivalent:@""];
205         [_menuFormRepresentation setImage:[self image]];
206         [_menuFormRepresentation setTarget:[self target]];
207         [_menuFormRepresentation setRepresentedObject:self];
208     }
209     
210     return _menuFormRepresentation;
213 -(NSView *)view {
214    return _view;
217 -(NSSize)minSize {
218    return _minSize;
221 -(NSSize)maxSize {
222    return _maxSize;
225 -(NSInteger)visibilityPriority {
226    return _visibilityPriority;
229 -(BOOL)autovalidates {
230    return _autovalidates;
233 -(BOOL)allowsDuplicatesInToolbar {
234    return NO;
237 -(void)_didChange {
238         // Changing a toolbar item doesn't change the height of the toolbar - so this call is not helping
239         // [_toolbar itemSizeDidChange];
240         
241    [_enclosingView setNeedsDisplay:YES];
244 -(void)setLabel:(NSString *)label {
245 // does not forward to view
246    label=[label copy];
247    [_label release];
248    _label=label;
249    [self _didChange];
252 -(void)setPaletteLabel:(NSString *)label {
253 // does not forward to view
254     [_paletteLabel release];
255     _paletteLabel = [label retain];
256    [self _didChange];
259 -(void)setMenuFormRepresentation:(NSMenuItem *)menuItem {
260 // does not forward to view
261    menuItem=[menuItem retain];
262    [_menuFormRepresentation release];
263    _menuFormRepresentation=menuItem;
266 -(void)setView:(NSView *)view {
267    view=[view retain];
268    [_view release];
269    _view=view;
270    if(view!=nil){
271     _minSize=[_view frame].size;
272     _maxSize=[_view frame].size;
273    }
274    [_enclosingView setSubview:_view];
275    [self _didChange];
278 -(void)setMinSize:(NSSize)size {
279    _minSize = size;
280    [self _didChange];
283 -(void)setMaxSize:(NSSize)size {
284    _maxSize = size;
285    [self _didChange];
288 -(void)setVisibilityPriority:(NSInteger)value {
289     _visibilityPriority=value;
290    [self _didChange];
293 -(void)setAutovalidates:(BOOL)value {
294    _autovalidates=value;
298 /* The understanding is that NSToolbarItem only forwards enabled/tag/action/target/image setters and getters to the publicly settable view. The rest are managed internally.
299  */
301 -(NSImage *)image {
302    if([_view respondsToSelector:@selector(image)])
303     return [(id)_view image];
305    return _image;
308 -target {
309    if ([_view respondsToSelector:@selector(target)])
310     return [(id)_view target];
311     
312    return _target;
315 -(SEL)action {
316    if ([_view respondsToSelector:@selector(action)])
317     return [(id)_view action];
318     
319    return _action;
322 -(NSInteger)tag {
323    if ([_view respondsToSelector:@selector(tag)])
324     return [(id)_view tag];
326    return _tag;
329 -(BOOL)isEnabled {
330    if([_view respondsToSelector:@selector(isEnabled)])
331     return [(id)_view isEnabled];
332     
333    return _isEnabled;
336 -(NSString *)toolTip  {
337    return _toolTip;
340 -(void)setImage:(NSImage *)image {
341    image=[image retain];
342    [_image release];
343    _image=image;
344     
345         if([_view respondsToSelector:@selector(setImage:)]) {
346                 [(id)_view setImage:image];
347         }
348         [self _didChange];
351 -(void)setTarget:target {
352    _target=target;
354    if([_view respondsToSelector:@selector(setTarget:)])
355     [(id)_view setTarget:target];
358 -(void)setAction:(SEL)action {
359    _action=action;
361    if([_view respondsToSelector:@selector(setAction:)])
362     [(id)_view setAction:action];
365 -(void)setTag:(NSInteger)tag {
366    _tag=tag;
367    if ([_view respondsToSelector:@selector(setTag:)])
368     [(id)_view setTag:tag];
371 -(void)setEnabled:(BOOL)enabled {
372    _isEnabled=enabled;
373    if([_view respondsToSelector:@selector(setEnabled:)])
374     [(id)_view setEnabled:enabled];
375     [self _didChange];
378 -(void)setToolTip:(NSString *)tip {
379    tip=[tip copy];
380    [_toolTip release];
381    _toolTip=tip;
384 -(void)validate
386     BOOL enabled = NO;
387     
388     id target=[NSApp targetForAction:[self action] to:[self target] from:nil];
389     
390     if ([self action] == nil && [self view] != nil) {
391         // Views can be arbitrarily complex - so let's not try to figure out what they
392         // want. Apple docs say use a subclass to do more sophisticated validation in this case.
393         enabled = YES;
394     } else if ((target == nil) || ![target respondsToSelector:[self action]]) {
395         enabled = NO;
396     } else if ([target respondsToSelector:@selector(validateToolbarItem:)]) {
397         enabled = [target validateToolbarItem:self];
398     } else if ([target respondsToSelector:@selector(validateUserInterfaceItem:)]) { // New validation scheme
399         enabled = [target validateUserInterfaceItem:self];
400     } else {
401         enabled = YES;
402     }
403     if (enabled != [self isEnabled]) {
404         [self setEnabled:enabled];
405     }
408 -(NSSize)_labelSize {
409    switch ([_toolbar displayMode]) {
410     case NSToolbarDisplayModeIconOnly:
411      return NSZeroSize;
412             
413     case NSToolbarDisplayModeLabelOnly:
414     case NSToolbarDisplayModeIconAndLabel: 
415     case NSToolbarDisplayModeDefault:
416     default:
417      return [_label sizeWithAttributes:[_toolbar _labelAttributesForSizeMode:[_toolbar sizeMode]]];
418    }
422 -(NSSize)sizeForSizeMode:(NSToolbarSizeMode)sizeMode displayMode:(NSToolbarDisplayMode)displayMode minSize:(NSSize)minSize maxSize:(NSSize)maxSize {
423    NSSize result;
424    
425    switch (sizeMode) {
426     case NSToolbarSizeModeSmall:
427      result = _NSToolbarSizeSmall;
428      break;
429             
430     case NSToolbarSizeModeRegular:
431     case NSToolbarSizeModeDefault:
432     default:
433      result = _NSToolbarSizeRegular;
434      break;
435    }        
437    if (minSize.width > 0 && result.width < minSize.width)
438     result.width = minSize.width;
439    if (minSize.height > 0 && result.height < minSize.height)
440     result.height = minSize.height;
441    if (maxSize.width > 0 && result.width > maxSize.width)
442     result.width = maxSize.width;
443    if (maxSize.height > 0 && result.height > maxSize.height)
444     result.height = maxSize.height;
446    NSSize labelSize=[_label sizeWithAttributes:[_toolbar _labelAttributesForSizeMode:sizeMode]];
447    labelSize.width+=8; // label margins
448    
449    switch (displayMode) {
450     case NSToolbarDisplayModeIconOnly:
451      break;
452             
453     case NSToolbarDisplayModeLabelOnly:
454      result.height=labelSize.height;
455      if(result.width<labelSize.width)
456       result.width=labelSize.width;
457      break;
459     case NSToolbarDisplayModeIconAndLabel: 
460     case NSToolbarDisplayModeDefault:
461     default:
462      result.height+=labelSize.height;
463      if(result.width<labelSize.width)
464       result.width=labelSize.width;
465      break;
466    }
468    return result;
471 -(NSSize)sizeForSizeMode:(NSToolbarSizeMode)sizeMode displayMode:(NSToolbarDisplayMode)displayMode  {
472    return [self sizeForSizeMode:sizeMode displayMode:displayMode minSize:_minSize maxSize:_maxSize];
475 -(NSSize)constrainedSize {
476    return [self sizeForSizeMode:[_toolbar sizeMode] displayMode:[_toolbar displayMode] minSize:_minSize maxSize:_maxSize];
479 -(void)_setItemViewFrame:(NSRect)rect {
480    [_enclosingView setFrame:rect];
483 -(CGFloat)_expandWidth:(CGFloat)width {
484    if([self view]!=nil){
485     return MIN(width,_maxSize.width);
486    }
487     
488    if([_itemIdentifier isEqualToString:NSToolbarFlexibleSpaceItemIdentifier])
489     return width;
490    
491    return [self constrainedSize].width;
494 -(void)drawInRect:(NSRect)bounds highlighted:(BOOL)highlighted {
495       
496    if([_itemIdentifier isEqualToString:NSToolbarSeparatorItemIdentifier]){
497     bounds.origin.x = floor(bounds.origin.x + (bounds.size.width/2));
498     bounds.size.width = 1;
499     [[NSColor blackColor] set];
500     NSDottedFrameRect(bounds);
501     
502     return;
503    }
504    CGFloat labelHeight=0;
505    CGFloat padding=4;
506    
508    if([_toolbar displayMode]!=NSToolbarDisplayModeIconOnly){  
509     NSMutableDictionary *attributes=[NSMutableDictionary dictionaryWithDictionary:[_toolbar _labelAttributes]];
510     NSColor             *color=[self isEnabled]?[NSColor controlTextColor]:[NSColor disabledControlTextColor];
511    
512     [attributes setObject:color forKey:NSForegroundColorAttributeName];
513    
514     NSRect labelRect;
515     labelRect.size=[_label sizeWithAttributes:attributes];
516     labelRect.origin.x=floor((bounds.size.width-labelRect.size.width)/2);
517     labelRect.origin.y=bounds.origin.y;
519     if(!highlighted){
520      NSMutableDictionary *shadowAttributes=[[attributes mutableCopy] autorelease];
521      NSRect shadowRect=labelRect;
522      
523      [shadowAttributes setObject:[NSColor whiteColor] forKey:NSForegroundColorAttributeName];
524      
525      shadowRect.origin.y--;
526      
527      [_label _clipAndDrawInRect:shadowRect withAttributes:shadowAttributes];
528     }
529     
530     [_label _clipAndDrawInRect:labelRect withAttributes:attributes];
531     labelHeight=labelRect.size.height;
532     labelHeight+=padding;
533    }
535    if([_toolbar displayMode]!=NSToolbarDisplayModeLabelOnly){
536     if([self view]==nil){
537      NSImage *image=[self image];
538      NSRect   imageRect;
540      if([_toolbar sizeMode]==NSToolbarSizeModeSmall)
541       imageRect.size=_NSToolbarIconSizeSmall;
542      else
543       imageRect.size=_NSToolbarIconSizeRegular;
544           
545         imageRect.origin.y=bounds.origin.y+labelHeight;
546         imageRect.origin.x=bounds.origin.x+floor((bounds.size.width-imageRect.size.width)/2);
547         CGContextRef ctx = NULL;
548         if ([self isEnabled] == NO) {
549             ctx = [[NSGraphicsContext currentContext] graphicsPort];
550             CGContextClipToRect(ctx, imageRect);
551             CGContextBeginTransparencyLayer(ctx, NULL);
552         }
553         [image drawInRect:imageRect fromRect:NSZeroRect operation:NSCompositeSourceOver fraction:highlighted?0.5:1.0];
554         if ([self isEnabled] == NO) {
555             [[NSColor colorWithCalibratedWhite:0.0 alpha:0.33] set];
556             NSRectFillUsingOperation(imageRect, NSCompositeSourceAtop);
557         }
558         CGContextEndTransparencyLayer(ctx);
559     }
560    }
563 -(NSString *)description {
564    return [NSString stringWithFormat:@"<%@[0x%lx] %@ label: \"%@\" image: %@ view: %@>",
565         [self class], self, _itemIdentifier, _label, [self image], _view];
568 -initWithCoder:(NSCoder *)coder {
569    if(![coder allowsKeyedCoding])
570     NSUnimplementedMethod();
571    else {
572     _itemIdentifier=[[coder decodeObjectForKey:@"NSToolbarItemIdentifier"] retain];
573       
574     _enclosingView=[[NSToolbarItemView alloc] init];
575     [_enclosingView setToolbarItem:self];
576     [self setView:[coder decodeObjectForKey:@"NSToolbarItemView"]];      
577     [self setTarget:[coder decodeObjectForKey:@"NSToolbarItemTarget"]];
578     [self setAction:NSSelectorFromString([coder decodeObjectForKey:@"NSToolbarItemAction"])];
580     [self setImage:[coder decodeObjectForKey:@"NSToolbarItemImage"]];
581     [self setLabel:[coder decodeObjectForKey:@"NSToolbarItemLabel"]];
582     [self setPaletteLabel:[coder decodeObjectForKey:@"NSToolbarItemPaletteLabel"]];
584     _maxSize=[coder decodeSizeForKey:@"NSToolbarItemMaxSize"];
585     _minSize=[coder decodeSizeForKey:@"NSToolbarItemMinSize"];
586     [self setEnabled:[coder decodeBoolForKey:@"NSToolbarItemEnabled"]];
587     [self setTag:[coder decodeIntForKey:@"NSToolbarItemTag"]];
588       
589     [self setAutovalidates:[coder decodeBoolForKey:@"NSToolbarItemAutovalidates"]];
590     [self setToolTip:[coder decodeObjectForKey:@"NSToolbarItemToolTip"]];
591     [self setVisibilityPriority:[coder decodeIntForKey:@"NSToolbarItemVisibilityPriority"]];
592       
593       /*
594        NSToolbarIsUserRemovable = 1;
595        */      
596     [self _configureAsStandardItemIfNeeded];
597    }
599    return self;
601 @end
603 @interface NSToolbarSpaceItem : NSToolbarItem
604 @end
606 @implementation NSToolbarSpaceItem
607 @end
610 @interface NSToolbarFlexibleSpaceItem : NSToolbarItem
611 @end
613 @implementation NSToolbarFlexibleSpaceItem
614 @end
616 @interface NSToolbarSeparatorItem : NSToolbarItem
617 @end
619 @implementation NSToolbarSeparatorItem
620 @end