34 var _CPMenuBarVisible = NO,
35 _CPMenuBarTitle =
@"",
36 _CPMenuBarIconImage = nil,
37 _CPMenuBarIconImageAlphaValue = 1.0,
38 _CPMenuBarAttributes = nil,
39 _CPMenuBarSharedWindow = nil;
61 BOOL _autoenablesItems;
62 BOOL _showsStateColumn;
66 int _highlightedIndex;
67 _CPMenuWindow _menuWindow;
74 if (
self !== [
CPMenu class])
80 + (BOOL)menuBarVisible
82 return _CPMenuBarVisible;
85 + (void)setMenuBarVisible:(BOOL)menuBarShouldBeVisible
87 if (_CPMenuBarVisible === menuBarShouldBeVisible)
90 _CPMenuBarVisible = menuBarShouldBeVisible;
95 if (menuBarShouldBeVisible)
97 if (!_CPMenuBarSharedWindow)
98 _CPMenuBarSharedWindow = [[_CPMenuBarWindow alloc] init];
100 [_CPMenuBarSharedWindow setMenu:[CPApp mainMenu]];
102 [_CPMenuBarSharedWindow setTitle:_CPMenuBarTitle];
103 [_CPMenuBarSharedWindow setIconImage:_CPMenuBarIconImage];
104 [_CPMenuBarSharedWindow setIconImageAlphaValue:_CPMenuBarIconImageAlphaValue];
106 [_CPMenuBarSharedWindow setColor:[_CPMenuBarAttributes objectForKey:@"CPMenuBarBackgroundColor"]];
107 [_CPMenuBarSharedWindow setTextColor:[_CPMenuBarAttributes objectForKey:@"CPMenuBarTextColor"]];
108 [_CPMenuBarSharedWindow setTitleColor:[_CPMenuBarAttributes objectForKey:@"CPMenuBarTitleColor"]];
109 [_CPMenuBarSharedWindow setTextShadowColor:[_CPMenuBarAttributes objectForKey:@"CPMenuBarTextShadowColor"]];
110 [_CPMenuBarSharedWindow setTitleShadowColor:[_CPMenuBarAttributes objectForKey:@"CPMenuBarTitleShadowColor"]];
111 [_CPMenuBarSharedWindow setHighlightColor:[_CPMenuBarAttributes objectForKey:@"CPMenuBarHighlightColor"]];
112 [_CPMenuBarSharedWindow setHighlightTextColor:[_CPMenuBarAttributes objectForKey:@"CPMenuBarHighlightTextColor"]];
113 [_CPMenuBarSharedWindow setHighlightTextShadowColor:[_CPMenuBarAttributes objectForKey:@"CPMenuBarHighlightTextShadowColor"]];
115 [_CPMenuBarSharedWindow orderFront:self];
118 [_CPMenuBarSharedWindow orderOut:self];
128 _CPMenuBarTitle = aTitle;
129 [_CPMenuBarSharedWindow setTitle:_CPMenuBarTitle];
134 return _CPMenuBarTitle;
139 _CPMenuBarImage = anImage;
140 [_CPMenuBarSharedWindow setIconImage:anImage];
145 return _CPMenuBarImage;
151 if (_CPMenuBarAttributes == attributes)
154 _CPMenuBarAttributes = [attributes
copy];
156 var textColor = [attributes
objectForKey:@"CPMenuBarTextColor"],
157 titleColor = [attributes
objectForKey:@"CPMenuBarTitleColor"],
158 textShadowColor = [attributes
objectForKey:@"CPMenuBarTextShadowColor"],
159 titleShadowColor = [attributes
objectForKey:@"CPMenuBarTitleShadowColor"],
160 highlightColor = [attributes
objectForKey:@"CPMenuBarHighlightColor"],
161 highlightTextColor = [attributes
objectForKey:@"CPMenuBarHighlightTextColor"],
162 highlightTextShadowColor = [attributes
objectForKey:@"CPMenuBarHighlightTextShadowColor"];
164 if (!textColor && titleColor)
165 [_CPMenuBarAttributes setObject:titleColor forKey:@"CPMenuBarTextColor"];
167 else if (textColor && !titleColor)
168 [_CPMenuBarAttributes setObject:textColor forKey:@"CPMenuBarTitleColor"];
170 else if (!textColor && !titleColor)
176 if (!textShadowColor && titleShadowColor)
177 [_CPMenuBarAttributes setObject:titleShadowColor forKey:@"CPMenuBarTextShadowColor"];
179 else if (textShadowColor && !titleShadowColor)
180 [_CPMenuBarAttributes setObject:textShadowColor forKey:@"CPMenuBarTitleShadowColor"];
182 else if (!textShadowColor && !titleShadowColor)
184 [_CPMenuBarAttributes setObject:[
CPColor whiteColor] forKey:@"CPMenuBarTextShadowColor"];
185 [_CPMenuBarAttributes setObject:[
CPColor whiteColor] forKey:@"CPMenuBarTitleShadowColor"];
191 if (!highlightTextColor)
192 [_CPMenuBarAttributes setObject:[
CPColor whiteColor] forKey:@"CPMenuBarHighlightTextColor"];
194 if (!highlightTextShadowColor)
195 [_CPMenuBarAttributes setObject:[
CPColor blackColor] forKey:@"CPMenuBarHighlightTextShadowColor"];
197 if (_CPMenuBarSharedWindow)
199 [_CPMenuBarSharedWindow setColor:[_CPMenuBarAttributes objectForKey:@"CPMenuBarBackgroundColor"]];
200 [_CPMenuBarSharedWindow setTextColor:[_CPMenuBarAttributes objectForKey:@"CPMenuBarTextColor"]];
201 [_CPMenuBarSharedWindow setTitleColor:[_CPMenuBarAttributes objectForKey:@"CPMenuBarTitleColor"]];
202 [_CPMenuBarSharedWindow setTextShadowColor:[_CPMenuBarAttributes objectForKey:@"CPMenuBarTextShadowColor"]];
203 [_CPMenuBarSharedWindow setTitleShadowColor:[_CPMenuBarAttributes objectForKey:@"CPMenuBarTitleShadowColor"]];
204 [_CPMenuBarSharedWindow setHighlightColor:[_CPMenuBarAttributes objectForKey:@"CPMenuBarHighlightColor"]];
205 [_CPMenuBarSharedWindow setHighlightTextColor:[_CPMenuBarAttributes objectForKey:@"CPMenuBarHighlightTextColor"]];
206 [_CPMenuBarSharedWindow setHighlightTextShadowColor:[_CPMenuBarAttributes objectForKey:@"CPMenuBarHighlightTextShadowColor"]];
212 return _CPMenuBarAttributes;
215 + (void)_setMenuBarIconImageAlphaValue:(
float)anAlphaValue
217 _CPMenuBarIconImageAlphaValue = anAlphaValue;
218 [_CPMenuBarSharedWindow setIconImageAlphaValue:anAlphaValue];
221 - (float)menuBarHeight
223 if (
self === [
CPApp mainMenu])
229 + (float)menuBarHeight
249 _autoenablesItems = YES;
250 _showsStateColumn = YES;
269 - (void)insertItem:(
CPMenuItem)aMenuItem atIndex:(
unsigned)anIndex
326 - (void)removeItemAtIndex:(
unsigned)anIndex
337 - (void)removeAllItems
339 var count = [_items count];
344 [_items[count] setMenu:nil];
360 if ([aMenuItem
menu] !==
self)
384 return _items[index];
399 return _items[index];
408 return [_items objectAtIndex:anIndex];
414 - (unsigned)numberOfItems
416 return [_items count];
435 if ([aMenuItem
menu] !==
self)
438 return [_items indexOfObjectIdenticalTo:aMenuItem];
449 count = _items.length;
451 for (; index < count; ++index)
452 if ([_items[index] title] === aTitle)
463 - (int)indexOfItemWithTag:(
int)aTag
466 count = _items.length;
468 for (; index < count; ++index)
469 if ([_items[index]
tag] == aTag)
481 - (int)indexOfItemWithTarget:(
id)aTarget andAction:(
SEL)anAction
484 count = _items.length;
486 for (; index < count; ++index)
488 var item = _items[index];
490 if ([item target] == aTarget && (!anAction || [item action] == anAction))
502 - (int)indexOfItemWithRepresentedObject:(
id)anObject
505 count = _items.length;
507 for (; index < count; ++index)
508 if ([[_items[index] representedObject]
isEqual:anObject])
519 - (int)indexOfItemWithSubmenu:(
CPMenu)aMenu
522 count = _items.length;
524 for (; index < count; ++index)
525 if ([_items[index] submenu] == aMenu)
551 - (void)submenuAction:(
id)aSender
578 return !_supermenu ||
self == [CPApp mainMenu];
586 - (void)setAutoenablesItems:(BOOL)aFlag
588 _autoenablesItems = aFlag;
594 - (BOOL)autoenablesItems
596 return _autoenablesItems;
606 if (![
self autoenablesItems])
610 for (var i = 0; i < [items count]; i++)
612 var item = [items objectAtIndex:i];
614 if ([item hasSubmenu])
617 var validator = [CPApp targetForAction:[item action] to:[item target] from:item];
619 if (!validator || ![validator respondsToSelector:[item action]])
620 [item setEnabled:NO];
621 else if ([validator respondsToSelector:
@selector(validateMenuItem:)])
622 [item setEnabled:[validator validateMenuItem:item]];
623 else if ([validator respondsToSelector:
@selector(validateUserInterfaceItem:)])
624 [item setEnabled:[validator validateUserInterfaceItem:item]];
627 [[_menuWindow _menuView] tile];
648 - (void)setMinimumWidth:(
float)aMinimumWidth
650 _minimumWidth = aMinimumWidth;
653 - (float)minimumWidth
655 return _minimumWidth;
658 - (void)_performActionOfHighlightedItemChain
660 var highlightedItem = [
self highlightedItem];
662 while ([highlightedItem submenu] && [highlightedItem action] ===
@selector(submenuAction:))
663 highlightedItem = [[highlightedItem submenu] highlightedItem];
668 if (highlightedItem && [highlightedItem isEnabled])
669 [CPApp sendAction:[highlightedItem action] to:[highlightedItem target] from:highlightedItem];
673 + (CGRect)_constraintRectForView:(
CPView)aView
676 return CGRectInset([[[aView window] platformWindow] contentBounds], 5.0, 5.0);
678 return CGRectInset([[[aView window] screen] visibleFrame], 5.0, 5.0);
681 - (void)popUpMenuPositioningItem:(
CPMenuItem)anItem atLocation:(CGPoint)aLocation inView:(
CPView)aView callback:(Function)aCallback
683 [
self _popUpMenuPositioningItem:anItem
691 - (void)_popUpMenuPositioningItem:(
CPMenuItem)anItem atLocation:(CGPoint)aLocation topY:(
float)aTopY bottomY:(
float)aBottomY inView:(
CPView)aView callback:(Function)aCallback
697 itemIndex = [
self indexOfItem:anItem];
700 throw "In call to popUpMenuPositioningItem:atLocation:inView:callback:, menu item " +
701 anItem + " is not present in
menu " + self;
704 var theWindow = [aView
window];
706 if (aView && !theWindow)
707 throw "In call to popUpMenuPositioningItem:atLocation:inView:callback:, view is not in any window.";
709 [
self _menuWillOpen];
713 aLocation = [theWindow convertBaseToGlobal:[aView
convertPoint:aLocation
toView:nil]];
716 var menuWindow = [_CPMenuWindow menuWindowWithMenu:self font:[
self font]];
718 [menuWindow setBackgroundStyle:_CPMenuWindowPopUpBackgroundStyle];
723 aLocation.y -= [menuWindow deltaYForItemAtIndex:itemIndex];
726 var constraintRect = [
CPMenu _constraintRectForView:aView];
728 [menuWindow setFrameOrigin:aLocation];
729 [menuWindow setConstraintRect:constraintRect];
732 if (![menuWindow hasMinimumNumberOfVisibleItems])
734 var unconstrainedFrame = [menuWindow unconstrainedFrame],
735 unconstrainedY = CGRectGetMinY(unconstrainedFrame);
738 if (unconstrainedY >= CGRectGetMaxY(constraintRect) || [menuWindow canScrollDown])
742 aTopY = [theWindow convertBaseToGlobal:[aView
convertPoint:CGPointMake(0.0, aTopY)
toView:nil]].y;
744 unconstrainedFrame.origin.y = MIN(CGRectGetMaxY(constraintRect), aTopY) - CGRectGetHeight(unconstrainedFrame);
748 else if (unconstrainedY < CGRectGetMinY(constraintRect) || [menuWindow canScrollUp])
752 aBottomY = [theWindow convertBaseToGlobal:[aView
convertPoint:CGPointMake(0.0, aBottomY)
toView:nil]].y;
754 unconstrainedFrame.origin.y = MAX(CGRectGetMinY(constraintRect), aBottomY);
757 [menuWindow setFrameOrigin:CGRectIntersection(unconstrainedFrame, constraintRect).origin];
764 [menuWindow orderFront:self];
767 [[_CPMenuManager sharedMenuManager]
768 beginTracking:[CPApp currentEvent]
769 menuContainer:menuWindow
770 constraintRect:constraintRect
774 + (Function)trackingCallbackWithCallback:(Function)aCallback
776 return function(aMenuWindow, aMenu)
778 [aMenuWindow setMenu:nil];
779 [aMenuWindow orderOut:self];
781 [_CPMenuWindow poolMenuWindow:aMenuWindow];
786 [aMenu _performActionOfHighlightedItemChain];
797 [aMenu _menuWillOpen];
802 var theWindow = [aView
window],
803 menuWindow = [_CPMenuWindow menuWindowWithMenu:aMenu font:aFont];
805 [menuWindow setBackgroundStyle:_CPMenuWindowPopUpBackgroundStyle];
807 var constraintRect = [
CPMenu _constraintRectForView:aView],
810 [menuWindow setConstraintRect:constraintRect];
811 [menuWindow setFrameOrigin:aLocation];
814 if (![menuWindow hasMinimumNumberOfVisibleItems])
816 var unconstrainedFrame = [menuWindow unconstrainedFrame],
817 unconstrainedY = CGRectGetMinY(unconstrainedFrame);
820 if (unconstrainedY >= CGRectGetMaxY(constraintRect) || [menuWindow canScrollDown])
821 unconstrainedFrame.origin.y = MIN(CGRectGetMaxY(constraintRect), aLocation.y) - CGRectGetHeight(unconstrainedFrame);
824 else if (unconstrainedY < CGRectGetMinY(constraintRect) || [menuWindow canScrollUp])
825 unconstrainedFrame.origin.y = MAX(CGRectGetMinY(constraintRect), aLocation.y);
827 [menuWindow setFrameOrigin:CGRectIntersection(unconstrainedFrame, constraintRect).origin];
833 [menuWindow orderFront:self];
835 [[_CPMenuManager sharedMenuManager]
836 beginTracking:anEvent
837 menuContainer:menuWindow
838 constraintRect:[
CPMenu _constraintRectForView:aView]
847 - (void)setShowsStateColumn:(BOOL)shouldShowStateColumn
849 _showsStateColumn = shouldShowStateColumn;
855 - (BOOL)showsStateColumn
857 return _showsStateColumn;
867 if (_highlightedIndex < 0)
870 var highlightedItem = _items[_highlightedIndex];
872 if ([highlightedItem isSeparatorItem])
875 return highlightedItem;
880 - (void)setDelegate:(
id)aDelegate
882 _delegate = aDelegate;
890 - (void)_menuWillOpen
892 var delegate = [
self delegate];
894 if ([delegate respondsToSelector:
@selector(menuWillOpen:)])
895 [delegate menuWillOpen:self];
898 - (void)_menuDidClose
900 var delegate = [
self delegate];
902 if ([delegate respondsToSelector:
@selector(menuDidClose:)])
903 [delegate menuDidClose:self];
910 - (void)cancelTracking
915 - (void)_fireCancelTrackingEvent
933 [_CPDisplayServer run];
937 - (void)_setMenuWindow:(_CPMenuWindow)aMenuWindow
939 _menuWindow = aMenuWindow;
960 if (_autoenablesItems)
964 count = _items.length,
968 for (; index < count; ++index)
970 var item = _items[index];
972 if ([anEvent _triggersKeyEquivalent:[item keyEquivalent] withModifierMask:[item keyEquivalentModifierMask]])
974 if ([item isEnabled])
984 if ([[item submenu] performKeyEquivalent:anEvent])
996 - (void)performActionForItemAtIndex:(
unsigned)anIndex
998 var item = _items[anIndex];
1000 [CPApp sendAction:[item action] to:[item target] from:item];
1007 - (void)_highlightItemAtIndex:(
int)anIndex
1009 if (_highlightedIndex === anIndex)
1013 [[_items[_highlightedIndex] _menuItemView] highlight:NO];
1015 _highlightedIndex = anIndex;
1018 [[_items[_highlightedIndex] _menuItemView] highlight:YES];
1020 if (_highlightedIndex !==
CPNotFound && _menuWindow)
1021 [_menuWindow._menuView scrollRectToVisible:[[_items[_highlightedIndex] _menuItemView] frame]];
1024 - (void)_setMenuName:(
CPString)aName
1026 if (_name === aName)
1031 if (_name ===
@"CPMainMenu")
1032 [CPApp setMainMenu:self];
1040 - (void)awakeFromCib
1042 if (_name ===
@"_CPMainMenu")
1044 [
self _setMenuName:@"CPMainMenu"];
1049 - (void)_menuWithName:(
CPString)aName
1051 if (aName === _name)
1054 for (var i = 0, count = [_items count]; i < count; i++)
1056 var
menu = [[_items[i] submenu] _menuWithName:aName];
1069 - (CPUInteger)countOfItems
1071 return [_items count];
1076 return [_items objectAtIndex:anIndex];
1081 return [_items objectsAtIndexes:indexes];
1088 - (void)insertObject:(
CPMenuItem)aMenuItem inItemsAtIndex:(CPUInteger)anIndex
1099 [_items insertObject:aMenuItem atIndex:anIndex];
1107 - (void)removeObjectFromItemsAtIndex:(CPUInteger)anIndex
1109 if (anIndex < 0 || anIndex >= [_items count])
1112 [[_items objectAtIndex:anIndex] setMenu:nil];
1113 [_items removeObjectAtIndex:anIndex];
1137 self = [
super init];
1141 _title = [aCoder decodeObjectForKey:CPMenuTitleKey];
1142 _items = [aCoder decodeObjectForKey:CPMenuItemsKey];
1144 [
self _setMenuName:[aCoder decodeObjectForKey:CPMenuNameKey]];
1146 _showsStateColumn = ![aCoder containsValueForKey:CPMenuShowsStateColumnKey] || [aCoder decodeBoolForKey:CPMenuShowsStateColumnKey];
1148 _autoenablesItems = YES;
1162 [aCoder encodeObject:_title forKey:CPMenuTitleKey];
1167 [aCoder encodeObject:_items forKey:CPMenuItemsKey];
1169 if (!_showsStateColumn)