/AppKit/NSToolbar.subproj/NSToolbarItem.m

https://code.google.com/p/cocotron/ · Objective C · 594 lines · 458 code · 118 blank · 18 comment · 55 complexity · 64d35325bc0a06fc606c2d00eea6bd6e MD5 · raw file

  1. /* Copyright (c) 2006-2009 Christopher J. W. Lloyd <cjwl@objc.net>
  2. 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:
  3. The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
  4. 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. */
  5. #import <AppKit/NSToolbarItem.h>
  6. #import <AppKit/NSToolbar.h>
  7. #import <AppKit/NSToolbarItemView.h>
  8. #import <AppKit/NSMenuItem.h>
  9. #import <AppKit/NSImage.h>
  10. #import <AppKit/NSColor.h>
  11. #import <AppKit/NSStringDrawing.h>
  12. #import <AppKit/NSStringDrawer.h>
  13. #import <AppKit/NSApplication.h>
  14. #import <AppKit/NSFontManager.h>
  15. #import <AppKit/NSAttributedString.h>
  16. #import <AppKit/NSRaise.h>
  17. NSString * const NSToolbarCustomizeToolbarItemIdentifier=@"NSToolbarCustomizeToolbarItem";
  18. NSString * const NSToolbarFlexibleSpaceItemIdentifier=@"NSToolbarFlexibleSpaceItem";
  19. NSString * const NSToolbarPrintItemIdentifier=@"NSToolbarPrintItem";
  20. NSString * const NSToolbarSeparatorItemIdentifier=@"NSToolbarSeparatorItem";
  21. NSString * const NSToolbarShowColorsItemIdentifier=@"NSToolbarShowColorsItem";
  22. NSString * const NSToolbarShowFontsItemIdentifier=@"NSToolbarShowFontsItem";
  23. NSString * const NSToolbarSpaceItemIdentifier=@"NSToolbarSpaceItem";
  24. extern NSSize _NSToolbarSizeRegular;
  25. extern NSSize _NSToolbarSizeSmall;
  26. extern NSSize _NSToolbarIconSizeRegular;
  27. extern NSSize _NSToolbarIconSizeSmall;
  28. @interface NSToolbar(private)
  29. -(NSView *)_view;
  30. -(void)itemSizeDidChange;
  31. -(NSDictionary *)_labelAttributes;
  32. -(NSDictionary *)_labelAttributesForSizeMode:(NSToolbarSizeMode)sizeMode;
  33. @end
  34. @implementation NSToolbarItem
  35. extern NSSize _NSToolbarIconSizeRegular;
  36. extern NSSize _NSToolbarIconSizeSmall;
  37. -(void)_configureAsStandardItemIfNeeded {
  38. if ([_itemIdentifier isEqualToString:NSToolbarSeparatorItemIdentifier]){
  39. NSSize size;
  40. [self setLabel:@""];
  41. [self setPaletteLabel: NSLocalizedStringFromTableInBundle(@"Separator", nil, [NSBundle bundleForClass: [NSToolbarItem class]], @"Describes a toolbar separator item")];
  42. [self setEnabled:NO];
  43. size = [self minSize];
  44. size.width = floor(size.width/2);
  45. [self setMinSize:size];
  46. size = [self maxSize];
  47. size.width = floor(size.width/2);
  48. [self setMaxSize:size];
  49. }
  50. else if ([_itemIdentifier isEqualToString:NSToolbarSpaceItemIdentifier]){
  51. NSSize size;
  52. [self setLabel:@""];
  53. [self setPaletteLabel: NSLocalizedStringFromTableInBundle(@"Space", nil, [NSBundle bundleForClass: [NSToolbarItem class]], @"Describes a toolbar space item")];
  54. [self setEnabled:NO];
  55. size = [self minSize];
  56. size.width /= 2;
  57. [self setMinSize:size];
  58. size = [self maxSize];
  59. size.width /= 2;
  60. [self setMaxSize:size];
  61. }
  62. else if ([_itemIdentifier isEqualToString:NSToolbarFlexibleSpaceItemIdentifier]){
  63. NSSize size;
  64. [self setLabel:@""];
  65. [self setPaletteLabel: NSLocalizedStringFromTableInBundle(@"Flexible Space", nil, [NSBundle bundleForClass: [NSToolbarItem class]], @"Describes a toolbar flexible space item")];
  66. [self setEnabled:NO];
  67. size = [self minSize];
  68. size.width /= 2;
  69. [self setMinSize:size];
  70. [self setMaxSize:NSMakeSize(-1, [self maxSize].height)];
  71. }
  72. else if ([_itemIdentifier isEqualToString:NSToolbarShowColorsItemIdentifier]){
  73. [self setLabel: NSLocalizedStringFromTableInBundle(@"Colors", nil, [NSBundle bundleForClass: [NSToolbarItem class]], @"Reveals a color picker")];
  74. [self setPaletteLabel: NSLocalizedStringFromTableInBundle(@"Show Colors", nil, [NSBundle bundleForClass: [NSToolbarItem class]], @"Reveals a color picker")];
  75. [self setTarget:[NSApplication sharedApplication]];
  76. [self setAction:@selector(orderFrontColorPanel:)];
  77. [self setImage:[NSImage imageNamed:NSToolbarShowColorsItemIdentifier]];
  78. [self setToolTip: NSLocalizedStringFromTableInBundle(@"Show the Colors panel.", nil, [NSBundle bundleForClass: [NSToolbarItem class]], @"Reveals a color picker")];
  79. }
  80. else if ([_itemIdentifier isEqualToString:NSToolbarShowFontsItemIdentifier]){
  81. [self setLabel: NSLocalizedStringFromTableInBundle(@"Fonts", nil, [NSBundle bundleForClass: [NSToolbarItem class]], @"Reveals a font picker")];
  82. [self setPaletteLabel: NSLocalizedStringFromTableInBundle(@"Show Fonts", nil, [NSBundle bundleForClass: [NSToolbarItem class]], @"Reveals a font picker")];
  83. [self setTarget:[NSFontManager sharedFontManager]];
  84. [self setAction:@selector(orderFrontFontPanel:)];
  85. [self setImage:[NSImage imageNamed:NSToolbarShowFontsItemIdentifier]];
  86. [self setToolTip: NSLocalizedStringFromTableInBundle(@"Show the Fonts panel.", nil, [NSBundle bundleForClass: [NSToolbarItem class]], @"Reveals a font picker")];
  87. }
  88. else if ([_itemIdentifier isEqualToString:NSToolbarCustomizeToolbarItemIdentifier]){
  89. [self setLabel: NSLocalizedStringFromTableInBundle(@"Customize", nil, [NSBundle bundleForClass: [NSToolbarItem class]], @"Reveals a toolbar customization dialog")];
  90. [self setPaletteLabel: NSLocalizedStringFromTableInBundle(@"Customize", nil, [NSBundle bundleForClass: [NSToolbarItem class]], @"Reveals a toolbar customization dialog")];
  91. [self setTarget:nil];
  92. [self setAction:@selector(runToolbarCustomizationPalette:)];
  93. [self setImage:[NSImage imageNamed:NSToolbarCustomizeToolbarItemIdentifier]];
  94. [self setToolTip: NSLocalizedStringFromTableInBundle(@"Customize this toolbar.", nil, [NSBundle bundleForClass: [NSToolbarItem class]], @"Reveals a toolbar customization dialog")];
  95. }
  96. else if ([_itemIdentifier isEqualToString:NSToolbarPrintItemIdentifier]){
  97. [self setLabel: NSLocalizedStringFromTableInBundle(@"Print", nil, [NSBundle bundleForClass: [NSToolbarItem class]], @"")];
  98. [self setPaletteLabel: NSLocalizedStringFromTableInBundle(@"Print Document", nil, [NSBundle bundleForClass: [NSToolbarItem class]], @"")];
  99. [self setTarget:nil];
  100. [self setAction:@selector(printDocument:)];
  101. [self setImage:[NSImage imageNamed:NSToolbarPrintItemIdentifier]];
  102. [self setToolTip: NSLocalizedStringFromTableInBundle(@"Print this document.", nil, [NSBundle bundleForClass: [NSToolbarItem class]], @"")];
  103. }
  104. }
  105. -initWithItemIdentifier:(NSString *)identifier {
  106. _itemIdentifier=[identifier retain];
  107. _toolbar=nil;
  108. _enclosingView=[[NSToolbarItemView alloc] init];
  109. [_enclosingView setToolbarItem:self];
  110. _image=nil;
  111. _label=@"";
  112. _paletteLabel=@"";
  113. _target=nil;
  114. _action=NULL;
  115. _menuFormRepresentation=nil;
  116. _view=nil;
  117. _minSize=NSZeroSize;
  118. _maxSize=NSZeroSize;
  119. _visibilityPriority=NSToolbarItemVisibilityPriorityStandard;
  120. _autovalidates=NO;
  121. _isEnabled=YES;
  122. [self _configureAsStandardItemIfNeeded];
  123. return self;
  124. }
  125. -(void)dealloc {
  126. [_itemIdentifier release];
  127. _toolbar=nil;
  128. [_image release];
  129. [_label release];
  130. [_paletteLabel release];
  131. [_menuFormRepresentation release];
  132. [_view release];
  133. [super dealloc];
  134. }
  135. -copyWithZone:(NSZone *)zone {
  136. // FIXME: copying views, ugh
  137. NSToolbarItem *copy=NSCopyObject(self, 0, zone);
  138. copy->_itemIdentifier=[_itemIdentifier copy];
  139. copy->_toolbar=nil;
  140. copy->_image=[_image copy];
  141. copy->_label=[_label copy];
  142. copy->_paletteLabel=[_paletteLabel copy];
  143. copy->_menuFormRepresentation=[_menuFormRepresentation copy];
  144. copy->_view=[_view copy];
  145. return copy;
  146. }
  147. -(NSView *)_enclosingView {
  148. return _enclosingView;
  149. }
  150. -(void)_setToolbar:(NSToolbar *)toolbar {
  151. _toolbar = toolbar;
  152. }
  153. -(NSString *)itemIdentifier {
  154. return _itemIdentifier;
  155. }
  156. -(NSToolbar *)toolbar {
  157. return _toolbar;
  158. }
  159. -(NSString *)label {
  160. return _label;
  161. }
  162. -(NSString *)paletteLabel {
  163. return _paletteLabel;
  164. }
  165. // By default, this method returns a singleton menu item with item label as the title. For standard items, the target, action is set.
  166. - (NSMenuItem *)menuFormRepresentation
  167. {
  168. // FIX should update standard item for action/target/label changes?
  169. if (_menuFormRepresentation == nil && [self label] != nil) {
  170. _menuFormRepresentation = [[NSMenuItem alloc] initWithTitle:[self label] action:[self action] keyEquivalent:@""];
  171. [_menuFormRepresentation setImage:[self image]];
  172. [_menuFormRepresentation setTarget:[self target]];
  173. [_menuFormRepresentation setRepresentedObject:self];
  174. }
  175. return _menuFormRepresentation;
  176. }
  177. -(NSView *)view {
  178. return _view;
  179. }
  180. -(NSSize)minSize {
  181. return _minSize;
  182. }
  183. -(NSSize)maxSize {
  184. return _maxSize;
  185. }
  186. -(NSInteger)visibilityPriority {
  187. return _visibilityPriority;
  188. }
  189. -(BOOL)autovalidates {
  190. return _autovalidates;
  191. }
  192. -(BOOL)allowsDuplicatesInToolbar {
  193. return NO;
  194. }
  195. -(void)_didChange {
  196. [_toolbar itemSizeDidChange];
  197. [_enclosingView setNeedsDisplay:YES];
  198. }
  199. -(void)setLabel:(NSString *)label {
  200. // does not forward to view
  201. label=[label copy];
  202. [_label release];
  203. _label=label;
  204. [self _didChange];
  205. }
  206. -(void)setPaletteLabel:(NSString *)label {
  207. // does not forward to view
  208. [_paletteLabel release];
  209. _paletteLabel = [label retain];
  210. [self _didChange];
  211. }
  212. -(void)setMenuFormRepresentation:(NSMenuItem *)menuItem {
  213. // does not forward to view
  214. menuItem=[menuItem retain];
  215. [_menuFormRepresentation release];
  216. _menuFormRepresentation=menuItem;
  217. }
  218. -(void)setView:(NSView *)view {
  219. view=[view retain];
  220. [_view release];
  221. _view=view;
  222. if(view!=nil){
  223. _minSize=[_view frame].size;
  224. _maxSize=[_view frame].size;
  225. }
  226. [_enclosingView setSubview:_view];
  227. [self _didChange];
  228. }
  229. -(void)setMinSize:(NSSize)size {
  230. _minSize = size;
  231. [self _didChange];
  232. }
  233. -(void)setMaxSize:(NSSize)size {
  234. _maxSize = size;
  235. [self _didChange];
  236. }
  237. -(void)setVisibilityPriority:(NSInteger)value {
  238. _visibilityPriority=value;
  239. [self _didChange];
  240. }
  241. -(void)setAutovalidates:(BOOL)value {
  242. _autovalidates=value;
  243. }
  244. /* 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.
  245. */
  246. -(NSImage *)image {
  247. if([_view respondsToSelector:@selector(image)])
  248. return [(id)_view image];
  249. return _image;
  250. }
  251. -target {
  252. if ([_view respondsToSelector:@selector(target)])
  253. return [(id)_view target];
  254. return _target;
  255. }
  256. -(SEL)action {
  257. if ([_view respondsToSelector:@selector(action)])
  258. return [(id)_view action];
  259. return _action;
  260. }
  261. -(NSInteger)tag {
  262. if ([_view respondsToSelector:@selector(tag)])
  263. return [(id)_view tag];
  264. return _tag;
  265. }
  266. -(BOOL)isEnabled {
  267. if([_view respondsToSelector:@selector(isEnabled)])
  268. return [(id)_view isEnabled];
  269. return _isEnabled;
  270. }
  271. -(NSString *)toolTip {
  272. return _toolTip;
  273. }
  274. -(void)setImage:(NSImage *)image {
  275. image=[image retain];
  276. [_image release];
  277. _image=image;
  278. if([_view respondsToSelector:@selector(setImage:)]) {
  279. [(id)_view setImage:image];
  280. }
  281. [self _didChange];
  282. }
  283. -(void)setTarget:target {
  284. _target=target;
  285. if([_view respondsToSelector:@selector(setTarget:)])
  286. [(id)_view setTarget:target];
  287. }
  288. -(void)setAction:(SEL)action {
  289. _action=action;
  290. if([_view respondsToSelector:@selector(setAction:)])
  291. [(id)_view setAction:action];
  292. }
  293. -(void)setTag:(NSInteger)tag {
  294. _tag=tag;
  295. if ([_view respondsToSelector:@selector(setTag:)])
  296. [(id)_view setTag:tag];
  297. }
  298. -(void)setEnabled:(BOOL)enabled {
  299. _isEnabled=YES;
  300. if([_view respondsToSelector:@selector(setEnabled:)])
  301. [(id)_view setEnabled:enabled];
  302. }
  303. -(void)setToolTip:(NSString *)tip {
  304. tip=[tip copy];
  305. [_toolTip release];
  306. _toolTip=tip;
  307. }
  308. -(void)validate
  309. {
  310. if ([[self target] respondsToSelector: @selector(validateToolbarItem:)]) {
  311. BOOL valid = [[self target] validateToolbarItem: [self action]];
  312. [self setEnabled: valid];
  313. } else if ([[self target] respondsToSelector:[self action]]) {
  314. [self setEnabled:YES];
  315. } else {
  316. [self setEnabled:NO];
  317. }
  318. }
  319. -(NSSize)_labelSize {
  320. switch ([_toolbar displayMode]) {
  321. case NSToolbarDisplayModeIconOnly:
  322. return NSZeroSize;
  323. case NSToolbarDisplayModeLabelOnly:
  324. case NSToolbarDisplayModeIconAndLabel:
  325. case NSToolbarDisplayModeDefault:
  326. default:
  327. return [_label sizeWithAttributes:[_toolbar _labelAttributesForSizeMode:[_toolbar sizeMode]]];
  328. }
  329. }
  330. -(NSSize)sizeForSizeMode:(NSToolbarSizeMode)sizeMode displayMode:(NSToolbarDisplayMode)displayMode minSize:(NSSize)minSize maxSize:(NSSize)maxSize {
  331. NSSize result;
  332. switch (sizeMode) {
  333. case NSToolbarSizeModeSmall:
  334. result = _NSToolbarSizeSmall;
  335. break;
  336. case NSToolbarSizeModeRegular:
  337. case NSToolbarSizeModeDefault:
  338. default:
  339. result = _NSToolbarSizeRegular;
  340. break;
  341. }
  342. if (minSize.width > 0 && result.width < minSize.width)
  343. result.width = minSize.width;
  344. if (minSize.height > 0 && result.height < minSize.height)
  345. result.height = minSize.height;
  346. if (maxSize.width > 0 && result.width > maxSize.width)
  347. result.width = maxSize.width;
  348. if (maxSize.height > 0 && result.height > maxSize.height)
  349. result.height = maxSize.height;
  350. NSSize labelSize=[_label sizeWithAttributes:[_toolbar _labelAttributesForSizeMode:sizeMode]];
  351. labelSize.width+=8; // label margins
  352. switch (displayMode) {
  353. case NSToolbarDisplayModeIconOnly:
  354. break;
  355. case NSToolbarDisplayModeLabelOnly:
  356. result.height=labelSize.height;
  357. if(result.width<labelSize.width)
  358. result.width=labelSize.width;
  359. break;
  360. case NSToolbarDisplayModeIconAndLabel:
  361. case NSToolbarDisplayModeDefault:
  362. default:
  363. result.height+=labelSize.height;
  364. if(result.width<labelSize.width)
  365. result.width=labelSize.width;
  366. break;
  367. }
  368. return result;
  369. }
  370. -(NSSize)sizeForSizeMode:(NSToolbarSizeMode)sizeMode displayMode:(NSToolbarDisplayMode)displayMode {
  371. return [self sizeForSizeMode:sizeMode displayMode:displayMode minSize:_minSize maxSize:_maxSize];
  372. }
  373. -(NSSize)constrainedSize {
  374. return [self sizeForSizeMode:[_toolbar sizeMode] displayMode:[_toolbar displayMode] minSize:_minSize maxSize:_maxSize];
  375. }
  376. -(void)_setItemViewFrame:(NSRect)rect {
  377. [_enclosingView setFrame:rect];
  378. }
  379. -(CGFloat)_expandWidth:(CGFloat)width {
  380. if([self view]!=nil){
  381. return MIN(width,_maxSize.width);
  382. }
  383. if([_itemIdentifier isEqualToString:NSToolbarFlexibleSpaceItemIdentifier])
  384. return width;
  385. return [self constrainedSize].width;
  386. }
  387. -(void)drawInRect:(NSRect)bounds highlighted:(BOOL)highlighted {
  388. if([_itemIdentifier isEqualToString:NSToolbarSeparatorItemIdentifier]){
  389. bounds.origin.x = floor(bounds.origin.x + (bounds.size.width/2));
  390. bounds.size.width = 1;
  391. [[NSColor blackColor] set];
  392. NSDottedFrameRect(bounds);
  393. return;
  394. }
  395. CGFloat labelHeight=0;
  396. CGFloat padding=4;
  397. if([_toolbar displayMode]!=NSToolbarDisplayModeIconOnly){
  398. NSMutableDictionary *attributes=[NSMutableDictionary dictionaryWithDictionary:[_toolbar _labelAttributes]];
  399. NSColor *color=[self isEnabled]?[NSColor controlTextColor]:[NSColor disabledControlTextColor];
  400. [attributes setObject:color forKey:NSForegroundColorAttributeName];
  401. NSRect labelRect;
  402. labelRect.size=[_label sizeWithAttributes:attributes];
  403. labelRect.origin.x=floor((bounds.size.width-labelRect.size.width)/2);
  404. labelRect.origin.y=bounds.origin.y;
  405. if(!highlighted){
  406. NSMutableDictionary *shadowAttributes=[[attributes mutableCopy] autorelease];
  407. NSRect shadowRect=labelRect;
  408. [shadowAttributes setObject:[NSColor whiteColor] forKey:NSForegroundColorAttributeName];
  409. shadowRect.origin.y--;
  410. [_label _clipAndDrawInRect:shadowRect withAttributes:shadowAttributes];
  411. }
  412. [_label _clipAndDrawInRect:labelRect withAttributes:attributes];
  413. labelHeight=labelRect.size.height;
  414. labelHeight+=padding;
  415. }
  416. if([_toolbar displayMode]!=NSToolbarDisplayModeLabelOnly){
  417. if([self view]==nil){
  418. NSImage *image=[self image];
  419. NSRect imageRect;
  420. if([_toolbar sizeMode]==NSToolbarSizeModeSmall)
  421. imageRect.size=_NSToolbarIconSizeSmall;
  422. else
  423. imageRect.size=_NSToolbarIconSizeRegular;
  424. imageRect.origin.y=bounds.origin.y+labelHeight;
  425. imageRect.origin.x=bounds.origin.x+floor((bounds.size.width-imageRect.size.width)/2);
  426. [image drawInRect:imageRect fromRect:NSZeroRect operation:NSCompositeSourceOver fraction:highlighted?0.5:1.0];
  427. }
  428. }
  429. }
  430. -(NSString *)description {
  431. return [NSString stringWithFormat:@"<%@[0x%lx] %@ label: \"%@\" image: %@ view: %@>",
  432. [self class], self, _itemIdentifier, _label, [self image], _view];
  433. }
  434. -initWithCoder:(NSCoder *)coder {
  435. if(![coder allowsKeyedCoding])
  436. NSUnimplementedMethod();
  437. else {
  438. _itemIdentifier=[[coder decodeObjectForKey:@"NSToolbarItemIdentifier"] retain];
  439. _enclosingView=[[NSToolbarItemView alloc] init];
  440. [_enclosingView setToolbarItem:self];
  441. [self setView:[coder decodeObjectForKey:@"NSToolbarItemView"]];
  442. [self setTarget:[coder decodeObjectForKey:@"NSToolbarItemTarget"]];
  443. [self setAction:NSSelectorFromString([coder decodeObjectForKey:@"NSToolbarItemAction"])];
  444. [self setImage:[coder decodeObjectForKey:@"NSToolbarItemImage"]];
  445. [self setLabel:[coder decodeObjectForKey:@"NSToolbarItemLabel"]];
  446. [self setPaletteLabel:[coder decodeObjectForKey:@"NSToolbarItemPaletteLabel"]];
  447. _maxSize=[coder decodeSizeForKey:@"NSToolbarItemMaxSize"];
  448. _minSize=[coder decodeSizeForKey:@"NSToolbarItemMinSize"];
  449. [self setEnabled:[coder decodeBoolForKey:@"NSToolbarItemEnabled"]];
  450. [self setTag:[coder decodeIntForKey:@"NSToolbarItemTag"]];
  451. [self setAutovalidates:[coder decodeBoolForKey:@"NSToolbarItemAutovalidates"]];
  452. [self setToolTip:[coder decodeObjectForKey:@"NSToolbarItemToolTip"]];
  453. [self setVisibilityPriority:[coder decodeIntForKey:@"NSToolbarItemVisibilityPriority"]];
  454. /*
  455. NSToolbarIsUserRemovable = 1;
  456. */
  457. [self _configureAsStandardItemIfNeeded];
  458. }
  459. return self;
  460. }
  461. @end
  462. @interface NSToolbarSpaceItem : NSToolbarItem
  463. @end
  464. @implementation NSToolbarSpaceItem
  465. @end
  466. @interface NSToolbarFlexibleSpaceItem : NSToolbarItem
  467. @end
  468. @implementation NSToolbarFlexibleSpaceItem
  469. @end
  470. @interface NSToolbarSeparatorItem : NSToolbarItem
  471. @end
  472. @implementation NSToolbarSeparatorItem
  473. @end