API  1.0.0
CPToolbar.j
Go to the documentation of this file.
1 /*
2  * CPToolbar.j
3  * AppKit
4  *
5  * Portions based on NSToolbar.m (11/10/2008) in Cocotron (http://www.cocotron.org/)
6  * Copyright (c) 2006-2007 Christopher J. W. Lloyd
7  *
8  * Created by Francisco Tolmasky.
9  * Copyright 2008, 280 North, Inc.
10  *
11  * This library is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU Lesser General Public
13  * License as published by the Free Software Foundation; either
14  * version 2.1 of the License, or (at your option) any later version.
15  *
16  * This library is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19  * Lesser General Public License for more details.
20  *
21  * You should have received a copy of the GNU Lesser General Public
22  * License along with this library; if not, write to the Free Software
23  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
24  */
25 
26 
27 
28 @global CPApp
29 
36 
37 
38 @typedef CPToolbarDisplayMode
39 /*
40  @global
41  @group CPToolbarDisplayMode
42 */
44 /*
45  @global
46  @group CPToolbarDisplayMode
47 */
49 /*
50  @global
51  @group CPToolbarDisplayMode
52 */
54 /*
55  @global
56  @group CPToolbarDisplayMode
57 */
59 
60 @typedef CPToolbarSizeMode
64 
67 
68 
69 @protocol CPToolbarDelegate <CPObject>
70 
71 @optional
72 - (CPToolbarItem)toolbar:(CPToolbar)toolbar itemForItemIdentifier:(CPString)itemIdentifier willBeInsertedIntoToolbar:(BOOL)flag;
73 - (CPArray)toolbarAllowedItemIdentifiers:(CPToolbar)toolbar;
74 - (CPArray)toolbarDefaultItemIdentifiers:(CPToolbar)toolbar;
75 - (void)toolbarDidRemoveItem:(CPNotification)notification;
76 - (CPArray)toolbarSelectableItemIdentifiers:(CPToolbar)toolbar;
77 - (void)toolbarWillAddItem:(CPNotification)notification;
78 
79 @end
80 
81 
108 @implementation CPToolbar : CPObject
109 {
110  CPString _identifier;
111  CPToolbarDisplayMode _displayMode;
112  BOOL _showsBaselineSeparator;
113  BOOL _allowsUserCustomization;
114  BOOL _isVisible;
115  CPToolbarSizeMode _sizeMode;
116  int _desiredHeight;
117 
118  id <CPToolbarDelegate> _delegate;
119  unsigned _implementedDelegateMethods;
120 
121  CPArray _itemIdentifiers;
122 
123  CPDictionary _identifiedItems;
124  CPArray _defaultItems;
125  CPArray _allowedItems;
126  CPArray _selectableItems;
127 
128  CPArray _items;
129  CPArray _itemsSortedByVisibilityPriority;
130 
131  CPView _toolbarView;
132  CPWindow _window;
133 }
134 
135 /* @ignore */
136 + (void)initialize
137 {
138  if (self !== [CPToolbar class])
139  return;
140 
143 }
144 
145 /* @ignore */
146 + (void)_addToolbar:(CPToolbar)toolbar forIdentifier:(CPString)identifier
147 {
148  var toolbarsSharingIdentifier = [CPToolbarsByIdentifier objectForKey:identifier];
149 
150  if (!toolbarsSharingIdentifier)
151  {
152  toolbarsSharingIdentifier = [];
153  [CPToolbarsByIdentifier setObject:toolbarsSharingIdentifier forKey:identifier];
154  }
155 
156  [toolbarsSharingIdentifier addObject:toolbar];
157 }
158 
159 - (id)init
160 {
161  return [self initWithIdentifier:@""];
162 }
163 
169 - (id)initWithIdentifier:(CPString)anIdentifier
170 {
171  self = [super init];
172 
173  if (self)
174  {
175  _items = [];
176 
177  _identifier = anIdentifier;
178  _isVisible = YES;
179  _sizeMode = CPToolbarSizeModeDefault;
180  _desiredHeight = 0;
181 
182  [CPToolbar _addToolbar:self forIdentifier:_identifier];
183  }
184 
185  return self;
186 }
187 
192 {
193  return _identifier;
194 }
195 
199 - (id)delegate
200 {
201  return _delegate;
202 }
203 
207 - (BOOL)isVisible
208 {
209  return _isVisible;
210 }
211 
216 - (void)setVisible:(BOOL)aFlag
217 {
218  if (_isVisible === aFlag)
219  return;
220 
221  _isVisible = aFlag;
222 
223  [_window _noteToolbarChanged];
224 }
225 
226 - (void)setSizeMode:(CPToolbarSizeMode)aSize
227 {
228  if (aSize === _sizeMode)
229  return;
230  _sizeMode = aSize;
231 
232  [[self _toolbarView] setFrame:[self _toolbarViewFrame]];
233  [_window _noteToolbarChanged];
234 }
235 
236 - (CPWindow)_window
237 {
238  return _window;
239 }
240 
241 - (void)_setWindow:(CPWindow)aWindow
242 {
243  if (_window)
244  [[CPNotificationCenter defaultCenter] removeObserver:self name:_CPWindowDidChangeFirstResponderNotification object:_window];
245 
246  _window = aWindow;
247 
248  if (_window)
249  [[CPNotificationCenter defaultCenter] addObserver:self selector:@selector(_autoValidateVisibleItems) name:_CPWindowDidChangeFirstResponderNotification object:aWindow];
250 }
251 
256 - (void)setDelegate:(id)aDelegate
257 {
258  if (_delegate === aDelegate)
259  return;
260 
261  _delegate = aDelegate;
262  _implementedDelegateMethods = 0;
263 
264  if ([_delegate respondsToSelector:@selector(toolbar:itemForItemIdentifier:willBeInsertedIntoToolbar:)])
266 
267  if ([_delegate respondsToSelector:@selector(toolbarAllowedItemIdentifiers:)])
268  _implementedDelegateMethods |= CPToolbarDelegate_toolbarAllowedItemIdentifiers_;
269 
270  if ([_delegate respondsToSelector:@selector(toolbarDefaultItemIdentifiers:)])
271  _implementedDelegateMethods |= CPToolbarDelegate_toolbarDefaultItemIdentifiers_;
272 
273  if ([_delegate respondsToSelector:@selector(toolbarDidRemoveItem:)])
274  _implementedDelegateMethods |= CPToolbarDelegate_toolbarDidRemoveItem_;
275 
276  if ([_delegate respondsToSelector:@selector(toolbarSelectableItemIdentifiers:)])
277  _implementedDelegateMethods |= CPToolbarDelegate_toolbarSelectableItemIdentifiers_;
278 
279  if ([_delegate respondsToSelector:@selector(toolbarWillAddItem:)])
280  _implementedDelegateMethods |= CPToolbarDelegate_toolbarWillAddItem_;
281 
282  [self _reloadToolbarItems];
283 }
284 
285 - (void)setDisplayMode:(CPToolbarDisplayMode)aDisplayMode
286 {
287  if (_displayMode === aDisplayMode)
288  return;
289  _displayMode = aDisplayMode;
290 
291  [self _reloadToolbarItems];
292 }
293 
294 /* @ignore */
295 - (void)_loadConfiguration
296 {
297 
298 }
299 
300 - (CGRect)_toolbarViewFrame
301 {
302  var height = _desiredHeight || (_sizeMode != CPToolbarSizeModeSmall ? [_toolbarView valueForThemeAttribute:@"regular-size-height"] : [_toolbarView valueForThemeAttribute:@"small-size-height"]);
303  return CGRectMake(0.0, 0.0, 1200.0, height);
304 }
305 
306 /* @ignore */
307 - (CPView)_toolbarView
308 {
309  if (!_toolbarView)
310  {
311  _toolbarView = [[_CPToolbarView alloc] initWithFrame:[self _toolbarViewFrame]];
312 
313  [_toolbarView setToolbar:self];
314  [_toolbarView setAutoresizingMask:CPViewWidthSizable];
315  [_toolbarView reloadToolbarItems];
316  }
317 
318  return _toolbarView;
319 }
320 
321 /* @ignore */
322 - (void)_reloadToolbarItems
323 {
324  // As of OS X 10.5 (Leopard), toolbar items can be set in IB and a
325  // toolbar delegate is optional. Toolbar items can be combined from
326  // both IB and a delegate (see Apple's NSToolbar guide for IB, for more details).
327 
328  // _defaultItems may have been loaded from Cib
329  _itemIdentifiers = [_defaultItems valueForKey:@"itemIdentifier"] || [];
330 
331  if ([self _delegateRespondsToToolbarDefaultItemIdentifiers])
332  {
333  var itemIdentifiersFromDelegate = [self _sendDelegateToolbarDefaultItemIdentifiers];
334 
335  // If we get items both from the Cib and from the delegate method, put the delegate items before the
336  // Cib ones.
337  if (itemIdentifiersFromDelegate)
338  _itemIdentifiers = [itemIdentifiersFromDelegate arrayByAddingObjectsFromArray:_itemIdentifiers];
339  }
340  // If we didn't load from a cib and the delegate hasn't been set yet, we'll just work with an empty list
341  // at this point.
342 
343  var index = 0,
344  count = [_itemIdentifiers count];
345 
346  _items = [];
347 
348  for (; index < count; ++index)
349  {
350  var identifier = _itemIdentifiers[index],
351  item = [CPToolbarItem _standardItemWithItemIdentifier:identifier];
352 
353  // May come from a Cib.
354  if (!item)
355  item = [_identifiedItems objectForKey:identifier];
356 
357  if (!item && _delegate)
358  item = [self _sendDelegateItemForItemIdentifier:identifier willBeInsertedIntoToolbar:YES];
359 
360  item = [item copy];
361 
362  if (item === nil)
364  reason:@"Toolbar delegate " + _delegate + " returned nil toolbar item for identifier \"" + identifier + "\""];
365 
366  item._toolbar = self;
367 
368  [_items addObject:item];
369  }
370 
371 // _items = [[self _defaultToolbarItems] mutableCopy];
372 
373  // Store items sorted by priority. We want items to be removed first at the end of the array,
374  // items to be removed last at the front.
375 
376  _itemsSortedByVisibilityPriority = [_items sortedArrayUsingFunction:_CPToolbarItemVisibilityPriorityCompare context:NULL];
377 
378  [_toolbarView reloadToolbarItems];
379 }
380 
384 - (CPArray)items
385 {
386  return _items;
387 }
388 
392 - (CPArray)visibleItems
393 {
394  return [_toolbarView visibleItems];
395 }
396 
400 - (CPArray)itemsSortedByVisibilityPriority
401 {
402  return _itemsSortedByVisibilityPriority;
403 }
404 
409 - (void)validateVisibleItems
410 {
411  [self _validateVisibleItems:NO]
412 }
413 
414 - (void)_autoValidateVisibleItems
415 {
416  [self _validateVisibleItems:YES]
417 }
418 
419 - (void)_validateVisibleItems:(BOOL)isAutovalidation
420 {
421  var toolbarItems = [self visibleItems],
422  count = [toolbarItems count];
423 
424  while (count--)
425  {
426  var item = [toolbarItems objectAtIndex:count];
427  if (!isAutovalidation || [item autovalidates])
428  [item validate];
429  }
430 }
431 
432 /* @ignore */
433 - (id)_itemForItemIdentifier:(CPString)identifier willBeInsertedIntoToolbar:(BOOL)toolbar
434 {
435  var item = [_identifiedItems objectForKey:identifier];
436 
437  if (!item)
438  {
439  item = [CPToolbarItem _standardItemWithItemIdentifier:identifier];
440 
441  if (_delegate && !item)
442  {
443  item = [[self _sendDelegateItemForItemIdentifier:identifier willBeInsertedIntoToolbar:toolbar] copy];
444  if (!item)
446  reason:@"Toolbar delegate " + _delegate + " returned nil toolbar item for identifier " + identifier];
447  }
448 
449  [_identifiedItems setObject:item forKey:identifier];
450  }
451 
452  return item;
453 }
454 
455 /* @ignore */
456 - (id)_itemsWithIdentifiers:(CPArray)identifiers
457 {
458  return [identifiers arrayByApplyingBlock:function(identifier)
459  {
460  return [self _itemForItemIdentifier:identifier willBeInsertedIntoToolbar:NO];
461  }];
462 }
463 
464 /* @ignore */
465 - (id)_defaultToolbarItems
466 {
467  if (!_defaultItems && [self _delegateRespondsToToolbarDefaultItemIdentifiers])
468  {
469  _defaultItems = [];
470 
471  var identifiers = [self _sendDelegateToolbarDefaultItemIdentifiers],
472  index = 0,
473  count = [identifiers count];
474 
475  for (; index < count; ++index)
476  [_defaultItems addObject:[self _itemForItemIdentifier:identifiers[index] willBeInsertedIntoToolbar:NO]];
477  }
478 
479  return _defaultItems;
480 }
481 
486 - (void)toolbarItemDidChange:(CPToolbarItem)anItem
487 {
488  if ([_identifiedItems objectForKey:[anItem itemIdentifier]])
489  [_identifiedItems setObject:anItem forKey:[anItem itemIdentifier]];
490 
491  var index = 0,
492  count = [_items count];
493 
494  for (; index <= count; ++index)
495  {
496  var item = _items[index];
497 
498  if ([item itemIdentifier] === [anItem itemIdentifier])
499  {
500  _items[index] = anItem;
501  _itemsSortedByVisibilityPriority = [_items sortedArrayUsingFunction:_CPToolbarItemVisibilityPriorityCompare context:NULL];
502 
503  [_toolbarView reloadToolbarItems];
504  }
505  }
506 }
507 
508 @end
509 
510 
511 var CPToolbarIdentifierKey = @"CPToolbarIdentifierKey",
512  CPToolbarDisplayModeKey = @"CPToolbarDisplayModeKey",
513  CPToolbarShowsBaselineSeparatorKey = @"CPToolbarShowsBaselineSeparatorKey",
514  CPToolbarAllowsUserCustomizationKey = @"CPToolbarAllowsUserCustomizationKey",
515  CPToolbarIsVisibleKey = @"CPToolbarIsVisibleKey",
516  CPToolbarDelegateKey = @"CPToolbarDelegateKey",
517  CPToolbarIdentifiedItemsKey = @"CPToolbarIdentifiedItemsKey",
518  CPToolbarDefaultItemsKey = @"CPToolbarDefaultItemsKey",
519  CPToolbarAllowedItemsKey = @"CPToolbarAllowedItemsKey",
520  CPToolbarSelectableItemsKey = @"CPToolbarSelectableItemsKey",
521  CPToolbarSizeModeKey = @"CPToolbarSizeModeKey";
522 
523 @implementation CPToolbar (CPCoding)
524 
525 /*
526  Initializes the toolbar by unarchiving data from \c aCoder.
527  @param aCoder the coder containing the archived CPToolbar.
528 */
529 - (id)initWithCoder:(CPCoder)aCoder
530 {
531  self = [super init];
532 
533  if (self)
534  {
535  _identifier = [aCoder decodeObjectForKey:CPToolbarIdentifierKey];
536  _displayMode = [aCoder decodeIntForKey:CPToolbarDisplayModeKey];
537  _showsBaselineSeparator = [aCoder decodeBoolForKey:CPToolbarShowsBaselineSeparatorKey];
538  _allowsUserCustomization = [aCoder decodeBoolForKey:CPToolbarAllowsUserCustomizationKey];
539  _isVisible = [aCoder decodeBoolForKey:CPToolbarIsVisibleKey];
540  _sizeMode = [aCoder decodeIntForKey:CPToolbarSizeModeKey];
541 
542  _identifiedItems = [aCoder decodeObjectForKey:CPToolbarIdentifiedItemsKey];
543  _defaultItems = [aCoder decodeObjectForKey:CPToolbarDefaultItemsKey];
544  _allowedItems = [aCoder decodeObjectForKey:CPToolbarAllowedItemsKey];
545  _selectableItems = [aCoder decodeObjectForKey:CPToolbarSelectableItemsKey];
546 
547  [[_identifiedItems allValues] makeObjectsPerformSelector:@selector(_setToolbar:) withObject:self];
548 
549  _items = [];
550 
551  [CPToolbar _addToolbar:self forIdentifier:_identifier];
552 
553  // This won't come from a Cib, but can come from manual encoding.
554  [self setDelegate:[aCoder decodeObjectForKey:CPToolbarDelegateKey]];
555 
556  // Because we don't know if a delegate will be set later (it is optional
557  // as of OS X 10.5), we need to call -_reloadToolbarItems here.
558  // In order to load any toolbar items that may have been configured in the
559  // Cib. Unfortunately this means that if there is a delegate
560  // specified, it will be read later and the resulting call to -setDelegate:
561  // will cause -_reloadToolbarItems] to run again :-(
562  // FIXME: Can we make this better?
563 
564  // Do this at the end of the run loop to allow all the cib-stuff to
565  // finish (establishing connections, etc.).
567  performSelector:@selector(_reloadToolbarItems)
568  target:self
569  argument:nil
570  order:0 modes:[CPDefaultRunLoopMode]];
571  }
572 
573  return self;
574 }
575 
576 /*
577  Archives this toolbar into the provided coder.
578  @param aCoder the coder to which the toolbar's instance data will be written.
579 */
580 - (void)encodeWithCoder:(CPCoder)aCoder
581 {
582  [aCoder encodeObject:_identifier forKey:CPToolbarIdentifierKey];
583  [aCoder encodeInt:_displayMode forKey:CPToolbarDisplayModeKey];
584  [aCoder encodeBool:_showsBaselineSeparator forKey:CPToolbarShowsBaselineSeparatorKey];
585  [aCoder encodeBool:_allowsUserCustomization forKey:CPToolbarAllowsUserCustomizationKey];
586  [aCoder encodeBool:_isVisible forKey:CPToolbarIsVisibleKey];
587  [aCoder encodeInt:_sizeMode forKey:CPToolbarSizeModeKey];
588 
589  [aCoder encodeObject:_identifiedItems forKey:CPToolbarIdentifiedItemsKey];
590  [aCoder encodeObject:_defaultItems forKey:CPToolbarDefaultItemsKey];
591  [aCoder encodeObject:_allowedItems forKey:CPToolbarAllowedItemsKey];
592  [aCoder encodeObject:_selectableItems forKey:CPToolbarSelectableItemsKey];
593 
594  [aCoder encodeConditionalObject:_delegate forKey:CPToolbarDelegateKey];
595 }
596 
597 @end
598 
599 
600 var _CPToolbarViewBackgroundColor = nil,
601  _CPToolbarViewExtraItemsImage = nil,
602  _CPToolbarViewExtraItemsAlternateImage = nil;
603 
604 var _CPToolbarItemInfoMake = function(anIndex, aView, aLabel, aMinWidth)
605 {
606  return { index:anIndex, view:aView, label:aLabel, minWidth:aMinWidth };
607 };
608 
609 /* @ignore */
610 @implementation _CPToolbarView : CPView
611 {
612  CPToolbar _toolbar;
613 
614  CPIndexSet _flexibleWidthIndexes;
615  CPIndexSet _visibleFlexibleWidthIndexes;
616 
617  CPDictionary _itemInfos;
618  JSObject _viewsForToolbarItems;
619 
620  CPArray _visibleItems;
621  CPArray _invisibleItems;
622 
623  CPPopUpButton _additionalItemsButton;
624  CPColor _labelColor;
625  CPColor _labelShadowColor;
626 
627  float _minWidth;
628 
629  BOOL _FIXME_isHUD;
630 }
631 
632 + (CPString)defaultThemeClass
633 {
634  return @"toolbar-view";
635 }
636 
637 + (CPDictionary)themeAttributes
638 {
639  return @{
640  @"item-margin": 10.0,
641  @"extra-item-width": 20.0,
642  @"extra-item-extra-image": [CPNull null],
643  @"extra-item-extra-alternate-image": [CPNull null],
644  @"content-inset": CGInsetMake(4.0, 4.0, 4.0, 10),
645  @"regular-size-height": 59.0,
646  @"small-size-height": 46.0,
647  @"image-item-separator-color": [CPNull null],
648  @"image-item-separator-size": CGRectMake(0.0, 0.0, 2.0, 32.0),
649  };
650 }
651 
652 - (id)initWithFrame:(CGRect)aFrame
653 {
654  self = [super initWithFrame:aFrame];
655 
656  if (self)
657  {
658  _minWidth = 0;
659 
660  _labelColor = [CPColor blackColor];
661  _labelShadowColor = [CPColor colorWithWhite:1.0 alpha:0.75];
662 
663  _additionalItemsButton = [[CPPopUpButton alloc] initWithFrame:CGRectMake(0.0, 0.0, 10.0, 15.0) pullsDown:YES];
664  [_additionalItemsButton setBordered:NO];
665 
666  [_additionalItemsButton setImagePosition:CPImageOnly];
667  [[_additionalItemsButton menu] setShowsStateColumn:NO];
668  [[_additionalItemsButton menu] setAutoenablesItems:NO];
669  }
670 
671  return self;
672 }
673 
674 - (void)setToolbar:(CPToolbar)aToolbar
675 {
676  _toolbar = aToolbar;
677 }
678 
679 - (CPToolbar)toolbar
680 {
681  return _toolbar;
682 }
683 
684 - (void)FIXME_setIsHUD:(BOOL)shouldBeHUD
685 {
686  if (_FIXME_isHUD === shouldBeHUD)
687  return;
688 
689  _FIXME_isHUD = shouldBeHUD;
690 
691  var items = [_toolbar items],
692  count = [items count];
693 
694  while (count--)
695  [[self viewForItem:items[count]] FIXME_setIsHUD:shouldBeHUD];
696 }
697 
698 // This *should* be roughly O(3N) = O(N)
699 - (void)resizeSubviewsWithOldSize:(CGSize)aSize
700 {
701  [self tile];
702 }
703 
704 - (_CPToolbarItemView)viewForItem:(CPToolbarItem)anItem
705 {
706  return _viewsForToolbarItems[[anItem UID]] || nil;
707 }
708 
709 - (void)tile
710 {
711  // We begin by recalculating the visible items.
712  var items = [_toolbar items],
713  itemsWidth = CGRectGetWidth([self bounds]),
714  minWidth = _minWidth,
715  // FIXME: This should be a CPSet.
716  invisibleItemsSortedByPriority = [];
717 
718  _visibleItems = items;
719 
720  // We only have hidden items if our actual width is smaller than our
721  // minimum width for hiding items.
722  if (itemsWidth < minWidth)
723  {
724  itemsWidth -= [self valueForThemeAttribute:@"extra-item-width"];
725 
726  _visibleItems = [_visibleItems copy];
727 
728  var itemsSortedByVisibilityPriority = [_toolbar itemsSortedByVisibilityPriority],
729  count = itemsSortedByVisibilityPriority.length;
730 
731  // Remove items until we fit:
732  // The assumption here is that there are more visible items than there are
733  // invisible items, if not it would be faster to add items until we *no
734  // longer fit*.
735  while (minWidth > itemsWidth && count)
736  {
737  var item = itemsSortedByVisibilityPriority[--count],
738  view = [self viewForItem:item];
739 
740  minWidth -= [view minSize].width + [self valueForThemeAttribute:@"item-margin"];
741 
742  [_visibleItems removeObjectIdenticalTo:item];
743  [invisibleItemsSortedByPriority addObject:item];
744 
745  [view setHidden:YES];
746  [view FIXME_setIsHUD:_FIXME_isHUD];
747  }
748  }
749 
750  // FIXME: minHeight?
751  var count = [items count],
752  height = 0.0;
753 
754  while (count--)
755  {
756  var view = [self viewForItem:items[count]],
757  minSize = [view minSize];
758 
759  if (height < minSize.height)
760  height = minSize.height;
761  }
762 
763  // We'll figure out the proper height for the toolbar depending on its items.
764  // If nothing has a minimum size we'll use the standard toolbar size for the
765  // sizeMode, indicated by a 0 _desiredHeight.
766  var contentInset = [self valueForThemeAttribute:@"content-inset"],
767  newDesiredHeight = height ? height + contentInset.top + contentInset.bottom : 0;
768 
769  if (newDesiredHeight != _toolbar._desiredHeight)
770  {
771  // FIXME Probably the toolbar view shouldn't be telling the toolbar which height it should be. Maybe refactor
772  // to just have the toolbar scan the toolbar items whenever the items change.
773  _toolbar._desiredHeight = newDesiredHeight;
774 
775  [self setFrame:[_toolbar _toolbarViewFrame]];
776  [_toolbar._window _noteToolbarChanged];
777  // The above will cause tile to be called again.
778  return;
779  }
780 
781  // Determine all the items that have flexible width.
782  // Also determine the height of the toolbar.
783  var count = _visibleItems.length,
784  flexibleItemIndexes = [CPIndexSet indexSet];
785 
786  while (count--)
787  {
788  var item = _visibleItems[count],
789  view = [self viewForItem:item],
790  minSize = [view minSize];
791 
792  if (minSize.width !== [view maxSize].width)
793  [flexibleItemIndexes addIndex:count];
794 
795  // FIXME: Is this still necessary? (probably not since we iterate them all below).
796  // If the item doesn't have flexible width, then make sure it's set to the
797  // static width (min==max). This handles the case where the user did setView:
798  // with a view of a different size than minSize/maxSize
799  else
800  [view setFrameSize:CGSizeMake(minSize.width, height)];
801 
802  [view setHidden:NO];
803  }
804 
805  var remainingSpace = itemsWidth - minWidth,
806  proportionate = 0.0;
807 
808  // Continue to distribute space proportionately while we have it,
809  // and there are flexible items left that want it. (Those with max
810  // widths may eventually not want it anymore).
811  while (remainingSpace && [flexibleItemIndexes count])
812  {
813  // Divy out the space.
814  proportionate += remainingSpace / [flexibleItemIndexes count];
815 
816  // Reset the remaining space to 0
817  remainingSpace = 0.0;
818 
819  var index = CPNotFound;
820 
821  while ((index = [flexibleItemIndexes indexGreaterThanIndex:index]) !== CPNotFound)
822  {
823  var item = _visibleItems[index],
824  view = [self viewForItem:item],
825  proposedWidth = [view minSize].width + proportionate,
826  constrainedWidth = MIN(proposedWidth, [view maxSize].width);
827 
828  if (constrainedWidth < proposedWidth)
829  {
830  [flexibleItemIndexes removeIndex:index];
831 
832  remainingSpace += proposedWidth - constrainedWidth;
833  }
834 
835  [view setFrameSize:CGSizeMake(constrainedWidth, height)];
836  }
837  }
838 
839  // Now that all the visible items are the correct width, give them their final frames.
840  var index = 0,
841  count = _visibleItems.length,
842  x = contentInset.left,
843  y = contentInset.top;
844 
845  for (; index < count; ++index)
846  {
847  var view = [self viewForItem:_visibleItems[index]],
848  viewWidth = CGRectGetWidth([view frame]);
849 
850  [view setFrame:CGRectMake(x, y, viewWidth, height)];
851 
852  x += viewWidth + [self valueForThemeAttribute:@"item-margin"];
853  }
854 
855  var needsAdditionalItemsButton = NO;
856 
857  if ([invisibleItemsSortedByPriority count])
858  {
859  var index = 0,
860  count = [items count];
861 
862  _invisibleItems = [];
863 
864  for (; index < count; ++index)
865  {
866  var item = items[index];
867 
868  if ([invisibleItemsSortedByPriority indexOfObjectIdenticalTo:item] !== CPNotFound)
869  {
870  [_invisibleItems addObject:item];
871 
872  var identifier = [item itemIdentifier];
873 
874  if (identifier !== CPToolbarSpaceItemIdentifier &&
875  identifier !== CPToolbarFlexibleSpaceItemIdentifier &&
876  identifier !== CPToolbarSeparatorItemIdentifier)
877  needsAdditionalItemsButton = YES;
878  }
879  }
880  }
881 
882  if (needsAdditionalItemsButton)
883  {
884  [_additionalItemsButton setFrameOrigin:CGPointMake(itemsWidth + 5.0, (CGRectGetHeight([self bounds]) - CGRectGetHeight([_additionalItemsButton frame])) / 2.0)];
885 
886  [self addSubview:_additionalItemsButton];
887 
888  [_additionalItemsButton removeAllItems];
889 
890  [_additionalItemsButton addItemWithTitle:@"Additional Items"];
891  [[_additionalItemsButton itemArray][0] setImage:[self valueForThemeAttribute:@"extra-item-extra-image"]];
892 
893  var index = 0,
894  count = [_invisibleItems count],
895  hasNonSeparatorItem = NO;
896 
897  for (; index < count; ++index)
898  {
899  var item = _invisibleItems[index],
900  identifier = [item itemIdentifier];
901 
902  if (identifier === CPToolbarSpaceItemIdentifier ||
903  identifier === CPToolbarFlexibleSpaceItemIdentifier)
904  continue;
905 
906  if (identifier === CPToolbarSeparatorItemIdentifier)
907  {
908  if (hasNonSeparatorItem)
909  [_additionalItemsButton addItem:[CPMenuItem separatorItem]];
910 
911  continue;
912  }
913 
914  hasNonSeparatorItem = YES;
915 
916  var menuItem = [[CPMenuItem alloc] initWithTitle:[item label] action:@selector(didSelectMenuItem:) keyEquivalent:nil];
917 
918  [menuItem setRepresentedObject:item];
919  [menuItem setImage:[item image]];
920  [menuItem setTarget:self];
921  [menuItem setEnabled:[item isEnabled]];
922 
923  [_additionalItemsButton addItem:menuItem];
924  }
925  }
926  else
927  [_additionalItemsButton removeFromSuperview];
928 }
929 
930 /*
931  Used privately.
932  @ignore
933 */
934 
935 - (void)didSelectMenuItem:(id)aSender
936 {
937  var toolbarItem = [aSender representedObject];
938 
939  [CPApp sendAction:[toolbarItem action] to:[toolbarItem target] from:toolbarItem];
940 }
941 
942 - (void)reloadToolbarItems
943 {
944  // Get rid of all our current subviews.
945  var subviews = [self subviews],
946  count = subviews.length;
947 
948  while (count--)
949  [subviews[count] removeFromSuperview];
950 
951  // Populate with new subviews.
952  var items = [_toolbar items],
953  index = 0;
954 
955  count = items.length;
956 
957  _minWidth = [self valueForThemeAttribute:@"item-margin"];
958  _viewsForToolbarItems = { };
959 
960  for (; index < count; ++index)
961  {
962  var item = items[index],
963  view = [[_CPToolbarItemView alloc] initWithToolbarItem:item toolbar:self];
964 
965  _viewsForToolbarItems[[item UID]] = view;
966 
967  if ([item toolTip] && [view respondsToSelector:@selector(setToolTip:)])
968  [view setToolTip:[item toolTip]];
969 
970  [self addSubview:view];
971 
972  _minWidth += [view minSize].width + [self valueForThemeAttribute:@"item-margin"];
973  }
974 
975  [self tile];
976 }
977 
978 - (void)layoutSubviews
979 {
980  [_additionalItemsButton setAlternateImage:[self valueForThemeAttribute:@"extra-item-extra-alternate-image"]];
981 }
982 
983 @end
984 
985 /* @ignore */
986 var _CPToolbarItemVisibilityPriorityCompare = function(lhs, rhs)
987 {
988  var lhsVisibilityPriority = [lhs visibilityPriority],
989  rhsVisibilityPriority = [rhs visibilityPriority];
990 
991  if (lhsVisibilityPriority == rhsVisibilityPriority)
992  return CPOrderedSame;
993 
994  if (lhsVisibilityPriority > rhsVisibilityPriority)
995  return CPOrderedAscending;
996 
997  return CPOrderedDescending;
998 };
999 
1000 var LABEL_MARGIN = 2.0;
1001 
1002 @implementation _CPToolbarItemView : CPControl
1003 {
1004  CGSize _minSize;
1005  CGSize _maxSize;
1006  CGSize _labelSize;
1007 
1008  CPToolbarItem _toolbarItem;
1009  CPToolbar _toolbar;
1010 
1011  CPImageView _imageView;
1012  CPView _view;
1013 
1014  CPTextField _labelField;
1015 
1016  BOOL _FIXME_isHUD;
1017 }
1018 
1019 - (id)initWithToolbarItem:(CPToolbarItem)aToolbarItem toolbar:(CPToolbar)aToolbar
1020 {
1021  self = [super init];
1022 
1023  if (self)
1024  {
1025  _toolbarItem = aToolbarItem;
1026 
1027  _labelField = [[CPTextField alloc] initWithFrame:CGRectMakeZero()];
1028 
1029  [_labelField setFont:[CPFont systemFontOfSize:11.0]];
1030  [_labelField setTextColor:[self FIXME_labelColor]];
1031  [_labelField setTextShadowColor:[self FIXME_labelShadowColor]];
1032  [_labelField setTextShadowOffset:CGSizeMake(0.0, 1.0)];
1033  [_labelField setAutoresizingMask:CPViewWidthSizable | CPViewMinXMargin];
1034 
1035  [self addSubview:_labelField];
1036 
1037  [self updateFromItem];
1038 
1039  _toolbar = aToolbar;
1040 
1041  var keyPaths = [@"label", @"image", @"alternateImage", @"minSize", @"maxSize", @"target", @"action", @"enabled"],
1042  index = 0,
1043  count = [keyPaths count];
1044 
1045  for (; index < count; ++index)
1046  [_toolbarItem
1047  addObserver:self
1048  forKeyPath:keyPaths[index]
1049  options:0
1050  context:NULL];
1051  }
1052 
1053  return self;
1054 }
1055 
1056 - (void)FIXME_setIsHUD:(BOOL)shouldBeHUD
1057 {
1058  _FIXME_isHUD = shouldBeHUD;
1059  [_labelField setTextColor:[self FIXME_labelColor]];
1060  [_labelField setTextShadowColor:[self FIXME_labelShadowColor]];
1061 }
1062 
1063 - (void)updateFromItem
1064 {
1065  var identifier = [_toolbarItem itemIdentifier];
1066 
1067  if (identifier === CPToolbarSpaceItemIdentifier ||
1068  identifier === CPToolbarFlexibleSpaceItemIdentifier ||
1069  identifier === CPToolbarSeparatorItemIdentifier)
1070  {
1071  [_view removeFromSuperview];
1072  [_imageView removeFromSuperview];
1073 
1074  _minSize = [_toolbarItem minSize];
1075  _maxSize = [_toolbarItem maxSize];
1076 
1077  if (identifier === CPToolbarSeparatorItemIdentifier)
1078  {
1079  _view = [[CPView alloc] initWithFrame:CGRectMakeZero()];
1080  [self addSubview:_view];
1081  }
1082 
1083  return;
1084  }
1085 
1086  [self setTarget:[_toolbarItem target]];
1087  [self setAction:[_toolbarItem action]];
1088 
1089  var view = [_toolbarItem view] || nil;
1090 
1091  if (view !== _view)
1092  {
1093  if (!view)
1094  [_view removeFromSuperview];
1095 
1096  else
1097  {
1098  [self addSubview:view];
1099  [_imageView removeFromSuperview];
1100  }
1101 
1102  _view = view;
1103  }
1104 
1105  if (!_view)
1106  {
1107  if (!_imageView)
1108  {
1109  _imageView = [[CPImageView alloc] initWithFrame:[self bounds]];
1110 
1111  [_imageView setImageScaling:CPImageScaleProportionallyDown];
1112 
1113  [self addSubview:_imageView];
1114  }
1115 
1116  [_imageView setImage:[_toolbarItem image]];
1117  }
1118 
1119  var minSize = [_toolbarItem minSize],
1120  maxSize = [_toolbarItem maxSize];
1121 
1122  [_labelField setStringValue:[_toolbarItem label]];
1123  [_labelField sizeToFit]; // FIXME
1124 
1125  [self setEnabled:[_toolbarItem isEnabled]];
1126 
1127  _labelSize = [_labelField frame].size;
1128 
1129  var iconOnly = [[_toolbarItem toolbar] displayMode] === CPToolbarDisplayModeIconOnly,
1130  labelOnly = [[_toolbarItem toolbar] displayMode] === CPToolbarDisplayModeLabelOnly;
1131  [_labelField setHidden:iconOnly];
1132  [_view setHidden:labelOnly];
1133 
1134  _minSize = CGSizeMake(MAX(_labelSize.width, minSize.width), (labelOnly ? 0 : minSize.height) + (iconOnly ? 0 : _labelSize.height + LABEL_MARGIN));
1135  _maxSize = CGSizeMake(MAX(_labelSize.width, maxSize.width), 100000000.0);
1136 
1137  [_toolbar tile];
1138 }
1139 
1140 - (void)layoutSubviews
1141 {
1142  var identifier = [_toolbarItem itemIdentifier];
1143 
1144  if (identifier === CPToolbarSpaceItemIdentifier ||
1145  identifier === CPToolbarFlexibleSpaceItemIdentifier)
1146  return;
1147 
1148  var bounds = [self bounds],
1149  width = CGRectGetWidth(bounds);
1150 
1151  if (identifier === CPToolbarSeparatorItemIdentifier)
1152  {
1153  var itemSeparatorColor = [_toolbar valueForThemeAttribute:@"image-item-separator-color"],
1154  itemSeparatorSize = [_toolbar valueForThemeAttribute:@"image-item-separator-size"];
1155 
1156  [_view setFrame:CGRectMake(ROUND((width - itemSeparatorSize.size.width) / 2.0), 0.0, itemSeparatorSize.size.width, CGRectGetHeight(bounds))];
1157  [_view setBackgroundColor:itemSeparatorColor];
1158 
1159  return;
1160  }
1161 
1162  // The view is centred in the available space above the label.
1163  var view = _view || _imageView,
1164  itemMaxSize = [_toolbarItem maxSize],
1165  iconOnly = [[_toolbarItem toolbar] displayMode] === CPToolbarDisplayModeIconOnly,
1166  height = CGRectGetHeight(bounds) - (iconOnly ? 0 : _labelSize.height),
1167  viewWidth = MIN(itemMaxSize.width, width),
1168  viewHeight = MIN(itemMaxSize.height, height);
1169 
1170  [view setFrame:CGRectMake(ROUND((width - viewWidth) / 2.0),
1171  ROUND((height - viewHeight) / 2.0),
1172  viewWidth,
1173  viewHeight)];
1174 
1175  // Label is always drawn at the bottom of the view. So if the view is really tall but the icon is tiny, the icon is centred above the label while the label remains on the bottom.
1176  [_labelField setFrameOrigin:CGPointMake(ROUND((width - _labelSize.width) / 2.0), CGRectGetHeight(bounds) - _labelSize.height)];
1177 }
1178 
1179 - (void)mouseDown:(CPEvent)anEvent
1180 {
1181  if ([_toolbarItem view])
1182  return [[self nextResponder] mouseDown:anEvent];
1183 
1184  var identifier = [_toolbarItem itemIdentifier];
1185 
1186  if (identifier === CPToolbarSpaceItemIdentifier ||
1187  identifier === CPToolbarFlexibleSpaceItemIdentifier ||
1188  identifier === CPToolbarSeparatorItemIdentifier)
1189  return [[self nextResponder] mouseDown:anEvent];
1190 
1191  [super mouseDown:anEvent];
1192 }
1193 
1194 - (void)setEnabled:(BOOL)shouldBeEnabled
1195 {
1196  // Tiling is very expensive so try to avoid it. The CPToolbarItem should already be careful to not notifying about its enabled state needlessly.
1197  if ([self isEnabled] === shouldBeEnabled)
1198  return;
1199 
1200  [super setEnabled:shouldBeEnabled];
1201 
1202  if (shouldBeEnabled)
1203  {
1204  [_imageView setAlphaValue:1.0];
1205  [_labelField setAlphaValue:1.0];
1206  }
1207  else
1208  {
1209  [_imageView setAlphaValue:0.5];
1210  [_labelField setAlphaValue:0.5];
1211  }
1212 
1213  [_toolbar tile];
1214 }
1215 
1216 - (CPColor)FIXME_labelColor
1217 {
1218  if (_FIXME_isHUD)
1219  return [CPColor whiteColor];
1220 
1221  return [CPColor blackColor];
1222 }
1223 
1224 - (CPColor)FIXME_labelShadowColor
1225 {
1226  if (_FIXME_isHUD)
1227  return [self isHighlighted] ? [CPColor colorWithWhite:1.0 alpha:0.5] : [CPColor clearColor];
1228 
1229  return [self isHighlighted] ? [CPColor colorWithWhite:0.0 alpha:0.3] : [CPColor colorWithWhite:1.0 alpha:0.75];
1230 }
1231 
1232 - (void)setHighlighted:(BOOL)shouldBeHighlighted
1233 {
1234  [super setHighlighted:shouldBeHighlighted];
1235 
1236  if (shouldBeHighlighted)
1237  {
1238  var alternateImage = [_toolbarItem alternateImage];
1239 
1240  if (alternateImage)
1241  [_imageView setImage:alternateImage];
1242 
1243  [_labelField setTextShadowOffset:CGSizeMakeZero()];
1244  }
1245  else
1246  {
1247  var image = [_toolbarItem image];
1248 
1249  if (image)
1250  [_imageView setImage:image];
1251 
1252  [_labelField setTextShadowOffset:CGSizeMake(0.0, 1.0)];
1253  }
1254 
1255  [_labelField setTextShadowColor:[self FIXME_labelShadowColor]];
1256 }
1257 
1258 - (BOOL)sendAction:(SEL)anAction to:(id)aSender
1259 {
1260  [CPApp sendAction:anAction to:aSender from:_toolbarItem];
1261 }
1262 
1263 - (void)observeValueForKeyPath:(CPString)aKeyPath
1264  ofObject:(id)anObject
1265  change:(CPDictionary)aChange
1266  context:(id)aContext
1267 {
1268  if (aKeyPath === "enabled")
1269  [self setEnabled:[anObject isEnabled]];
1270 
1271  else if (aKeyPath === @"target")
1272  [self setTarget:[anObject target]];
1273 
1274  else if (aKeyPath === @"action")
1275  [self setAction:[anObject action]];
1276 
1277  else
1278  [self updateFromItem];
1279 }
1280 
1281 @end
1282 
1283 
1285 
1286 /*
1287  @ignore
1288  Return YES if the delegate implements toolbarDefaultItemIdentifiers:
1289 */
1290 - (BOOL)_delegateRespondsToToolbarDefaultItemIdentifiers
1291 {
1292  return _implementedDelegateMethods & CPToolbarDelegate_toolbarDefaultItemIdentifiers_;
1293 }
1294 
1299 - (CPToolbarItem)_sendDelegateItemForItemIdentifier:(CPString)itemIdentifier willBeInsertedIntoToolbar:(BOOL)flag
1300 {
1302  return nil;
1303 
1304  return [_delegate toolbar:self itemForItemIdentifier:itemIdentifier willBeInsertedIntoToolbar:flag];
1305 }
1306 
1311 - (CPArray)_sendDelegateToolbarAllowedItemIdentifiers
1312 {
1313  if (!(_implementedDelegateMethods & CPToolbarDelegate_toolbarAllowedItemIdentifiers_))
1314  return [];
1315 
1316  return [_delegate toolbarAllowedItemIdentifiers:self];
1317 }
1318 
1323 - (CPArray)_sendDelegateToolbarDefaultItemIdentifiers
1324 {
1325  if (!(_implementedDelegateMethods & CPToolbarDelegate_toolbarDefaultItemIdentifiers_))
1326  return [];
1327 
1328  return [_delegate toolbarDefaultItemIdentifiers:self];
1329 }
1330 
1335 - (void)_sendDelegateToolbarDidRemoveItem:(CPNotification)notification
1336 {
1337  if (!(_delegate & CPToolbarDelegate_toolbarDidRemoveItem_))
1338  return;
1339 
1340  [_delegate toolbarDidRemoveItem:notification];
1341 }
1342 
1347 - (CPArray)_sendDelegateToolbarSelectableItemIdentifiers
1348 {
1349  if (!(_implementedDelegateMethods & CPToolbarDelegate_toolbarSelectableItemIdentifiers_))
1350  return [];
1351 
1352  return [_delegate toolbarSelectableItemIdentifiers:self];
1353 }
1354 
1359 - (void)_sendDelegateToolbarWillAddItem:(CPNotification)notification
1360 {
1361  if (!(_delegate & CPToolbarDelegate_toolbarWillAddItem_))
1362  return;
1363 
1364  [_delegate toolbarWillAddItem:notification];
1365 }
1366 
1367 @end
1368 
1370 
1374 - (CPToolbarDisplayMode)displayMode
1375 {
1376  return _displayMode;
1377 }
1378 
1382 - (void)setDisplayMode:(CPToolbarDisplayMode)aValue
1383 {
1384  _displayMode = aValue;
1385 }
1386 
1390 - (CPToolbarSizeMode)sizeMode
1391 {
1392  return _sizeMode;
1393 }
1394 
1398 - (void)setSizeMode:(CPToolbarSizeMode)aValue
1399 {
1400  _sizeMode = aValue;
1401 }
1402 
1403 @end
Used to implement exception handling (creating & raising).
Definition: CPException.h:2
Definition: CPFont.h:2
CPOrderedAscending
Definition: CPObjJRuntime.j:48
id init()
Definition: CALayer.j:126
FrameUpdater prototype identifier
CGRect frame
global CPApp var CPToolbarDelegate_toolbarWillAddItem_
Definition: CPToolbar.j:35
An object representation of nil.
Definition: CPNull.h:2
CPOrderedSame
Definition: CPObjJRuntime.j:54
CPFont systemFontOfSize:(CGSize aSize)
Definition: CPFont.j:282
CPToolbarSizeModeSmall
Definition: CPToolbar.j:63
CPToolbarDisplayModeIconOnly
Definition: CPToolbar.j:53
CPToolbarDisplayMode CPToolbarDisplayModeDefault
Definition: CPToolbar.j:43
CPColor clearColor()
Definition: CPColor.j:451
The main run loop for the application.
Definition: CPRunLoop.h:2
var CPToolbarConfigurationsByIdentifier
Definition: CPToolbar.j:66
void addObserver:selector:name:object:(id anObserver, [selector] SEL aSelector, [name] CPString aNotificationName, [object] id anObject)
CPToolbarSizeMode CPToolbarSizeModeDefault
Definition: CPToolbar.j:61
void performSelector:target:argument:order:modes:(SEL aSelector, [target] id aTarget, [argument] id anArgument, [order] int anOrder, [modes] CPArray modes)
Definition: CPRunLoop.j:253
var LABEL_MARGIN
Definition: CPToolbar.j:1000
CPToolbarDisplayModeLabelOnly
Definition: CPToolbar.j:58
CPColor whiteColor()
Definition: CPColor.j:361
id delegate()
Definition: CALayer.j:965
CPString label
int width
A collection of unique integers.
Definition: CPIndexSet.h:2
var CPToolbarShowsBaselineSeparatorKey
Definition: CPToolbar.j:513
var CPToolbarDefaultItemsKey
Definition: CPToolbar.j:518
CPNotificationCenter defaultCenter()
CPInvalidArgumentException
Definition: CPException.j:25
A mutable key-value pair collection.
Definition: CPDictionary.h:2
global CPApp var CPToolbarDelegate_toolbar_itemForItemIdentifier_willBeInsertedIntoToolbar_
Definition: CPToolbar.j:30
CPRunLoop currentRunLoop()
Definition: CPRunLoop.j:232
var CPToolbarDelegateKey
Definition: CPToolbar.j:516
CGRect bounds()
Definition: CALayer.j:203
CPColor blackColor()
Definition: CPColor.j:284
var CPToolbarDisplayModeKey
Definition: CPToolbar.j:512
var CPToolbarSelectableItemsKey
Definition: CPToolbar.j:520
An immutable string (collection of characters).
Definition: CPString.h:2
CPNull null()
Definition: CPNull.j:51
var CPToolbarIdentifierKey
Definition: CPToolbar.j:511
CPOrderedDescending
Definition: CPObjJRuntime.j:60
global CPApp var CPToolbarDelegate_toolbarAllowedItemIdentifiers_
Definition: CPToolbar.j:31
var CPToolbarIdentifiedItemsKey
Definition: CPToolbar.j:517
var CPToolbarIsVisibleKey
Definition: CPToolbar.j:515
A notification that can be posted to a CPNotificationCenter.
Definition: CPNotification.h:2
CPColor colorWithWhite:alpha:(float white, [alpha] float alpha)
Definition: CPColor.j:157
global CPApp var CPToolbarDelegate_toolbarSelectableItemIdentifiers_
Definition: CPToolbar.j:34
var CPToolbarSizeModeKey
Definition: CPToolbar.j:521
var CPToolbarAllowsUserCustomizationKey
Definition: CPToolbar.j:514
Defines methods for use when archiving & restoring (enc/decoding).
Definition: CPCoder.h:2
CPNotFound
Definition: CPObjJRuntime.j:62
id init()
Definition: CPObject.j:145
Sends messages (CPNotification) between objects.
CPToolbarSizeModeRegular
Definition: CPToolbar.j:62
id initWithTitle:action:keyEquivalent:(CPString aTitle, [action] SEL anAction, [keyEquivalent] CPString aKeyEquivalent)
Definition: CPMenuItem.j:121
CPToolbarDisplayModeIconAndLabel
Definition: CPToolbar.j:48
var CPToolbarAllowedItemsKey
Definition: CPToolbar.j:519
global CPApp var CPToolbarDelegate_toolbarDidRemoveItem_
Definition: CPToolbar.j:33
void removeObserver:name:object:(id anObserver, [name] CPString aNotificationName, [object] id anObject)
Definition: CPEvent.h:2
var CPToolbarsByIdentifier
Definition: CPToolbar.j:65
id indexSet()
Definition: CPIndexSet.j:43
void setDelegate:(id aDelegate)
Definition: CPToolbar.j:256
id alloc()
Definition: CPObject.j:130
id initWithIdentifier:(CPString anIdentifier)
Definition: CPToolbar.j:169
Definition: CPView.j:137
global CPApp var CPToolbarDelegate_toolbarDefaultItemIdentifiers_
Definition: CPToolbar.j:32