30 - (void)menuWillOpen:(
CPMenu)aMenu;
31 - (void)menuDidClose:(
CPMenu)aMenu;
44 var _CPMenuBarVisible = NO,
45 _CPMenuBarTitle =
@"",
46 _CPMenuBarAttributes = nil,
47 _CPMenuBarSharedWindow = nil;
68 BOOL _autoenablesItems;
69 BOOL _showsStateColumn;
71 id <CPMenuDelegate> _delegate;
72 unsigned _implementedDelegateMethods;
74 int _highlightedIndex;
75 _CPMenuWindow _menuWindow;
84 if (
self !== [
CPMenu class])
87 [[
self class] setMenuBarAttributes:@{}];
90 + (BOOL)menuBarVisible
92 return _CPMenuBarVisible;
95 + (void)setMenuBarVisible:(BOOL)menuBarShouldBeVisible
97 if (_CPMenuBarVisible === menuBarShouldBeVisible)
100 _CPMenuBarVisible = menuBarShouldBeVisible;
105 if (menuBarShouldBeVisible)
107 if (!_CPMenuBarSharedWindow)
108 _CPMenuBarSharedWindow = [[_CPMenuBarWindow alloc] init];
110 [_CPMenuBarSharedWindow setMenu:[CPApp mainMenu]];
112 [_CPMenuBarSharedWindow setTitle:_CPMenuBarTitle];
116 [_CPMenuBarSharedWindow setColor:[_CPMenuBarAttributes objectForKey:@"CPMenuBarBackgroundColor"]];
117 [_CPMenuBarSharedWindow setTextColor:[_CPMenuBarAttributes objectForKey:@"CPMenuBarTextColor"]];
118 [_CPMenuBarSharedWindow setTitleColor:[_CPMenuBarAttributes objectForKey:@"CPMenuBarTitleColor"]];
119 [_CPMenuBarSharedWindow setTextShadowColor:[_CPMenuBarAttributes objectForKey:@"CPMenuBarTextShadowColor"]];
120 [_CPMenuBarSharedWindow setTitleShadowColor:[_CPMenuBarAttributes objectForKey:@"CPMenuBarTitleShadowColor"]];
121 [_CPMenuBarSharedWindow setHighlightColor:[_CPMenuBarAttributes objectForKey:@"CPMenuBarHighlightColor"]];
122 [_CPMenuBarSharedWindow setHighlightTextColor:[_CPMenuBarAttributes objectForKey:@"CPMenuBarHighlightTextColor"]];
123 [_CPMenuBarSharedWindow setHighlightTextShadowColor:[_CPMenuBarAttributes objectForKey:@"CPMenuBarHighlightTextShadowColor"]];
125 [_CPMenuBarSharedWindow orderFront:self];
128 [_CPMenuBarSharedWindow orderOut:self];
138 _CPMenuBarTitle = aTitle;
139 [_CPMenuBarSharedWindow setTitle:_CPMenuBarTitle];
144 return _CPMenuBarTitle;
149 _CPMenuBarImage = anImage;
150 [_CPMenuBarSharedWindow setIconImage:anImage];
155 return _CPMenuBarImage;
158 + (void)_setOrRemoveMenuBarAttribute:(
id)aValue forKey:(
id)aKey
161 [_CPMenuBarAttributes removeObjectForKey:aKey];
163 [_CPMenuBarAttributes setObject:aValue forKey:aKey];
168 if (_CPMenuBarAttributes == attributes)
171 _CPMenuBarAttributes = [attributes
copy];
173 var textColor = [attributes
objectForKey:@"CPMenuBarTextColor"],
174 titleColor = [attributes
objectForKey:@"CPMenuBarTitleColor"],
175 textShadowColor = [attributes
objectForKey:@"CPMenuBarTextShadowColor"],
176 titleShadowColor = [attributes
objectForKey:@"CPMenuBarTitleShadowColor"],
177 highlightColor = [attributes
objectForKey:@"CPMenuBarHighlightColor"],
178 highlightTextColor = [attributes
objectForKey:@"CPMenuBarHighlightTextColor"],
179 highlightTextShadowColor = [attributes
objectForKey:@"CPMenuBarHighlightTextShadowColor"];
181 if (!textColor && titleColor)
182 [_CPMenuBarAttributes setObject:titleColor forKey:@"CPMenuBarTextColor"];
184 else if (textColor && !titleColor)
185 [_CPMenuBarAttributes setObject:textColor forKey:@"CPMenuBarTitleColor"];
187 else if (!textColor && !titleColor)
193 if (!textShadowColor && titleShadowColor)
194 [_CPMenuBarAttributes setObject:titleShadowColor forKey:@"CPMenuBarTextShadowColor"];
196 else if (textShadowColor && !titleShadowColor)
197 [_CPMenuBarAttributes setObject:textShadowColor forKey:@"CPMenuBarTitleShadowColor"];
199 else if (!textShadowColor && !titleShadowColor)
208 if (!highlightTextColor)
211 if (!highlightTextShadowColor)
214 if (_CPMenuBarSharedWindow)
216 [_CPMenuBarSharedWindow setColor:[_CPMenuBarAttributes objectForKey:@"CPMenuBarBackgroundColor"]];
217 [_CPMenuBarSharedWindow setTextColor:[_CPMenuBarAttributes objectForKey:@"CPMenuBarTextColor"]];
218 [_CPMenuBarSharedWindow setTitleColor:[_CPMenuBarAttributes objectForKey:@"CPMenuBarTitleColor"]];
219 [_CPMenuBarSharedWindow setTextShadowColor:[_CPMenuBarAttributes objectForKey:@"CPMenuBarTextShadowColor"]];
220 [_CPMenuBarSharedWindow setTitleShadowColor:[_CPMenuBarAttributes objectForKey:@"CPMenuBarTitleShadowColor"]];
221 [_CPMenuBarSharedWindow setHighlightColor:[_CPMenuBarAttributes objectForKey:@"CPMenuBarHighlightColor"]];
222 [_CPMenuBarSharedWindow setHighlightTextColor:[_CPMenuBarAttributes objectForKey:@"CPMenuBarHighlightTextColor"]];
223 [_CPMenuBarSharedWindow setHighlightTextShadowColor:[_CPMenuBarAttributes objectForKey:@"CPMenuBarHighlightTextShadowColor"]];
229 return _CPMenuBarAttributes;
232 + (void)_setMenuBarIconImageAlphaValue:(
float)anAlphaValue
234 _CPMenuBarIconImageAlphaValue = anAlphaValue;
235 [_CPMenuBarSharedWindow setIconImageAlphaValue:anAlphaValue];
238 - (float)menuBarHeight
240 if (
self === [
CPApp mainMenu])
246 + (float)menuBarHeight
266 _autoenablesItems = YES;
267 _showsStateColumn = YES;
286 - (void)insertItem:(
CPMenuItem)aMenuItem atIndex:(CPUInteger)anIndex
343 - (void)removeItemAtIndex:(CPUInteger)anIndex
354 - (void)removeAllItems
356 var count = [_items count];
361 [_items[count] setMenu:nil];
363 [
self _highlightItemAtIndex:CPNotFound];
382 if ([aMenuItem
menu] !==
self || !_items)
390 userInfo:@{ @"CPMenuItemIndex": [_items indexOfObjectIdenticalTo:aMenuItem] }];
406 return _items[index];
421 return _items[index];
430 return [_items objectAtIndex:anIndex];
436 - (unsigned)numberOfItems
438 return [_items count];
457 if ([aMenuItem
menu] !==
self)
460 return [_items indexOfObjectIdenticalTo:aMenuItem];
471 count = _items.length;
473 for (; index < count; ++index)
474 if ([_items[index] title] === aTitle)
485 - (int)indexOfItemWithTag:(
int)aTag
488 count = _items.length;
490 for (; index < count; ++index)
491 if ([_items[index]
tag] == aTag)
503 - (int)indexOfItemWithTarget:(
id)aTarget andAction:(
SEL)anAction
506 count = _items.length;
508 for (; index < count; ++index)
510 var item = _items[index];
512 if ([item target] == aTarget && (!anAction || [item action] == anAction))
524 - (int)indexOfItemWithRepresentedObject:(
id)anObject
527 count = _items.length;
529 for (; index < count; ++index)
530 if ([[_items[index] representedObject]
isEqual:anObject])
541 - (int)indexOfItemWithSubmenu:(
CPMenu)aMenu
544 count = _items.length;
546 for (; index < count; ++index)
547 if ([_items[index] submenu] == aMenu)
573 - (void)submenuAction:(
id)aSender
600 return !_supermenu ||
self == [CPApp mainMenu];
608 - (void)setAutoenablesItems:(BOOL)aFlag
610 _autoenablesItems = aFlag;
616 - (BOOL)autoenablesItems
618 return _autoenablesItems;
629 if (!_autoenablesItems)
634 for (var i = 0; i < [items count]; i++)
636 var item = [items objectAtIndex:i];
638 if ([item hasSubmenu])
646 [binder setValueFor:CPEnabledBinding];
647 [[_menuWindow _menuView] tile];
651 var validator = [CPApp targetForAction:[item action] to:[item target] from:item],
652 shouldBeEnabled = YES;
658 if ([item action] || [item target])
659 shouldBeEnabled = NO;
667 var
object = [info objectForKey:CPObservedObjectKey],
668 keyPath = [info objectForKey:CPObservedKeyPathKey],
669 options = [info objectForKey:CPOptionsKey],
670 target = [object valueForKeyPath:keyPath],
671 selector = [options valueForKey:CPSelectorNameBindingOption];
674 shouldBeEnabled = NO;
678 else if (![validator respondsToSelector:[item action]])
679 shouldBeEnabled = NO;
680 else if ([validator respondsToSelector:
@selector(validateMenuItem:)])
681 shouldBeEnabled = [validator validateMenuItem:item];
682 else if ([validator respondsToSelector:
@selector(validateUserInterfaceItem:)])
683 shouldBeEnabled = [validator validateUserInterfaceItem:item];
685 [item setEnabled:shouldBeEnabled];
688 [[_menuWindow _menuView] tile];
709 - (void)setMinimumWidth:(
float)aMinimumWidth
711 _minimumWidth = aMinimumWidth;
714 - (float)minimumWidth
716 return _minimumWidth;
719 - (void)_performActionOfHighlightedItemChain
721 var highlightedItem = [
self highlightedItem];
723 while ([highlightedItem submenu] && [highlightedItem action] ===
@selector(submenuAction:))
724 highlightedItem = [[highlightedItem submenu] highlightedItem];
729 if (highlightedItem && [highlightedItem isEnabled])
733 [binding invokeAction];
735 [CPApp sendAction:[highlightedItem action] to:[highlightedItem target] from:highlightedItem];
740 + (CGRect)_constraintRectForView:(
CPView)aView
743 return CGRectInset([[[aView window] platformWindow] contentBounds], 5.0, 5.0);
745 return CGRectInset([[[aView window] screen] visibleFrame], 5.0, 5.0);
748 - (void)popUpMenuPositioningItem:(
CPMenuItem)anItem atLocation:(CGPoint)aLocation inView:(
CPView)aView callback:(Function)aCallback
750 [
self _popUpMenuPositioningItem:anItem
758 - (void)_popUpMenuPositioningItem:(
CPMenuItem)anItem atLocation:(CGPoint)aLocation topY:(
float)aTopY bottomY:(
float)aBottomY inView:(
CPView)aView callback:(Function)aCallback
764 itemIndex = [
self indexOfItem:anItem];
767 throw "In call to popUpMenuPositioningItem:atLocation:inView:callback:, menu item " +
768 anItem + " is not present in
menu " + self;
771 var theWindow = [aView
window];
773 if (aView && !theWindow)
774 throw "In call to popUpMenuPositioningItem:atLocation:inView:callback:, view is not in any window.";
776 [
self _menuWillOpen];
780 aLocation = [theWindow convertBaseToGlobal:[aView
convertPoint:aLocation
toView:nil]];
783 var menuWindow = [_CPMenuWindow menuWindowWithMenu:self font:[
self font]];
785 [menuWindow setBackgroundStyle:_CPMenuWindowPopUpBackgroundStyle];
790 aLocation.y -= [menuWindow deltaYForItemAtIndex:itemIndex];
793 var constraintRect = [
CPMenu _constraintRectForView:aView];
795 [menuWindow setFrameOrigin:aLocation];
796 [menuWindow setConstraintRect:constraintRect];
799 if (![menuWindow hasMinimumNumberOfVisibleItems])
801 var unconstrainedFrame = [menuWindow unconstrainedFrame],
802 unconstrainedY = CGRectGetMinY(unconstrainedFrame);
805 if (unconstrainedY >= CGRectGetMaxY(constraintRect) || [menuWindow canScrollDown])
809 aTopY = [theWindow convertBaseToGlobal:[aView
convertPoint:CGPointMake(0.0, aTopY)
toView:nil]].y;
811 unconstrainedFrame.origin.y = MIN(CGRectGetMaxY(constraintRect), aTopY) - CGRectGetHeight(unconstrainedFrame);
815 else if (unconstrainedY < CGRectGetMinY(constraintRect) || [menuWindow canScrollUp])
819 aBottomY = [theWindow convertBaseToGlobal:[aView
convertPoint:CGPointMake(0.0, aBottomY)
toView:nil]].y;
821 unconstrainedFrame.origin.y = MAX(CGRectGetMinY(constraintRect), aBottomY);
824 [menuWindow setFrameOrigin:CGRectIntersection(unconstrainedFrame, constraintRect).origin];
831 [menuWindow orderFront:self];
834 [[_CPMenuManager sharedMenuManager]
835 beginTracking:[CPApp currentEvent]
836 menuContainer:menuWindow
837 constraintRect:constraintRect
841 + (Function)trackingCallbackWithCallback:(Function)aCallback
843 return function(aMenuWindow, aMenu)
845 [aMenuWindow setMenu:nil];
846 [aMenuWindow orderOut:self];
848 [_CPMenuWindow poolMenuWindow:aMenuWindow];
853 [aMenu _performActionOfHighlightedItemChain];
865 [[_CPMenuManager sharedMenuManager] cancelActiveMenu];
867 [aMenu _menuWillOpen];
872 var theWindow = [aView
window],
873 menuWindow = [_CPMenuWindow menuWindowWithMenu:aMenu font:aFont];
875 [menuWindow setBackgroundStyle:_CPMenuWindowPopUpBackgroundStyle];
877 var constraintRect = [
CPMenu _constraintRectForView:aView],
880 [menuWindow setConstraintRect:constraintRect];
881 [menuWindow setFrameOrigin:aLocation];
884 if (![menuWindow hasMinimumNumberOfVisibleItems])
886 var unconstrainedFrame = [menuWindow unconstrainedFrame],
887 unconstrainedY = CGRectGetMinY(unconstrainedFrame);
890 if (unconstrainedY >= CGRectGetMaxY(constraintRect) || [menuWindow canScrollDown])
891 unconstrainedFrame.origin.y = MIN(CGRectGetMaxY(constraintRect), aLocation.y) - CGRectGetHeight(unconstrainedFrame);
894 else if (unconstrainedY < CGRectGetMinY(constraintRect) || [menuWindow canScrollUp])
895 unconstrainedFrame.origin.y = MAX(CGRectGetMinY(constraintRect), aLocation.y);
897 [menuWindow setFrameOrigin:CGRectIntersection(unconstrainedFrame, constraintRect).origin];
903 [menuWindow orderFront:self];
905 [[_CPMenuManager sharedMenuManager]
906 beginTracking:anEvent
907 menuContainer:menuWindow
908 constraintRect:[
CPMenu _constraintRectForView:aView]
917 - (void)setShowsStateColumn:(BOOL)shouldShowStateColumn
919 _showsStateColumn = shouldShowStateColumn;
925 - (BOOL)showsStateColumn
927 return _showsStateColumn;
937 if (_highlightedIndex < 0)
940 var highlightedItem = _items[_highlightedIndex];
942 if ([highlightedItem isSeparatorItem])
945 return highlightedItem;
950 - (void)setDelegate:(
id <CPMenuDelegate>)aDelegate
952 if (_delegate === aDelegate)
955 _delegate = aDelegate;
956 _implementedDelegateMethods = 0;
958 if ([_delegate respondsToSelector:
@selector(menuWillOpen:)])
961 if ([_delegate respondsToSelector:
@selector(menuDidClose:)])
970 - (void)_menuWillOpen
972 [
self _sendDelegateMenuWillOpen];
975 - (void)_menuDidClose
979 _lastCloseEvent = [CPApp currentEvent];
981 [
self _sendDelegateMenuDidClose];
988 - (void)cancelTracking
993 - (void)_fireCancelTrackingEvent
1011 [_CPDisplayServer run];
1015 - (void)_setMenuWindow:(_CPMenuWindow)aMenuWindow
1017 _menuWindow = aMenuWindow;
1038 if (_autoenablesItems)
1042 count = _items.length,
1046 for (; index < count; ++index)
1048 var item = _items[index];
1050 if ([anEvent _triggersKeyEquivalent:[item keyEquivalent] withModifierMask:[item keyEquivalentModifierMask]])
1052 if ([item isEnabled])
1062 if ([[item submenu] performKeyEquivalent:anEvent])
1074 - (void)performActionForItemAtIndex:(CPUInteger)anIndex
1076 var item = _items[anIndex];
1078 [CPApp sendAction:[item action] to:[item target] from:item];
1085 - (void)_highlightItemAtIndex:(
int)anIndex
1087 if (_highlightedIndex === anIndex)
1091 [[_items[_highlightedIndex] _menuItemView] highlight:NO];
1093 _highlightedIndex = anIndex;
1096 [[_items[_highlightedIndex] _menuItemView] highlight:YES];
1098 if (_highlightedIndex !==
CPNotFound && _menuWindow)
1099 [_menuWindow._menuView scrollRectToVisible:[[_items[_highlightedIndex] _menuItemView] frame]];
1102 - (void)_setMenuName:(
CPString)aName
1104 if (_name === aName)
1109 if (_name ===
@"CPMainMenu")
1110 [CPApp setMainMenu:self];
1118 - (void)awakeFromCib
1120 if (_name ===
@"_CPMainMenu")
1122 [
self _setMenuName:@"CPMainMenu"];
1127 - (void)_menuWithName:(
CPString)aName
1129 if (aName === _name)
1132 for (var i = 0, count = [_items count]; i < count; i++)
1134 var
menu = [[_items[i] submenu] _menuWithName:aName];
1152 - (void)_sendDelegateMenuWillOpen
1157 [_delegate menuWillOpen:self];
1164 - (void)_sendDelegateMenuDidClose
1169 [_delegate menuDidClose:self];
1177 - (CPUInteger)countOfItems
1179 return [_items count];
1184 return [_items objectAtIndex:anIndex];
1189 return [_items objectsAtIndexes:indexes];
1196 - (void)insertObject:(
CPMenuItem)aMenuItem inItemsAtIndex:(CPUInteger)anIndex
1207 [
self _highlightItemAtIndex:CPNotFound];
1208 [_items insertObject:aMenuItem atIndex:anIndex];
1213 userInfo:@{ @"CPMenuItemIndex": anIndex }];
1216 - (void)removeObjectFromItemsAtIndex:(CPUInteger)anIndex
1218 if (anIndex < 0 || anIndex >= [_items count])
1221 [[_items objectAtIndex:anIndex] setMenu:nil];
1222 [
self _highlightItemAtIndex:CPNotFound];
1223 [_items removeObjectAtIndex:anIndex];
1228 userInfo:@{ @"CPMenuItemIndex": anIndex }];
1248 self = [
super init];
1252 _title = [aCoder decodeObjectForKey:CPMenuTitleKey];
1253 _items = [aCoder decodeObjectForKey:CPMenuItemsKey];
1255 [
self _setMenuName:[aCoder decodeObjectForKey:CPMenuNameKey]];
1257 _showsStateColumn = ![aCoder containsValueForKey:CPMenuShowsStateColumnKey] || [aCoder decodeBoolForKey:CPMenuShowsStateColumnKey];
1259 _autoenablesItems = ![aCoder containsValueForKey:CPMenuAutoEnablesItemsKey] || [aCoder decodeBoolForKey:CPMenuAutoEnablesItemsKey];
1273 [aCoder encodeObject:_title forKey:CPMenuTitleKey];
1278 [aCoder encodeObject:_items forKey:CPMenuItemsKey];
1280 if (!_showsStateColumn)
1283 if (!_autoenablesItems)
Used to implement exception handling (creating & raising).
void willChangeValueForKey:(CPString aKey)
CPDictionary infoForBinding:forObject:(CPString aBinding, [forObject] id anObject)
void postNotificationName:object:userInfo:(CPString aNotificationName, [object] id anObject, [userInfo] CPDictionary aUserInfo)
CPFont systemFontOfSize:(CGSize aSize)
The main run loop for the application.
void performSelector:target:argument:order:modes:(SEL aSelector, [target] id aTarget, [argument] id anArgument, [order] int anOrder, [modes] CPArray modes)
CGPoint locationInWindow()
A collection of unique integers.
CPString charactersIgnoringModifiers()
function CPSelectorFromString(aSelectorName)
CPNotificationCenter defaultCenter()
A mutable key-value pair collection.
CPRunLoop currentRunLoop()
An immutable string (collection of characters).
id objectForKey:(id aKey)
CGPoint convertBaseToGlobal:(CGPoint aPoint)
id valueForKey:(CPString aKey)
CPBinder getBinding:forObject:(CPString aBinding, [forObject] id anObject)
CGPoint convertPoint:toView:(CGPoint aPoint, [toView] CPView aView)
void didChangeValueForKey:(CPString aKey)
CPEvent otherEventWithType:location:modifierFlags:timestamp:windowNumber:context:subtype:data1:data2:(CPEventType anEventType, [location] CGPoint aLocation, [modifierFlags] unsigned modifierFlags, [timestamp] CPTimeInterval aTimestamp, [windowNumber] int aWindowNumber, [context] CPGraphicsContext aGraphicsContext, [subtype] short aSubtype, [data1] int aData1, [data2] int aData2)
CPInternalInconsistencyException
Defines methods for use when archiving & restoring (enc/decoding).
void setValue:forKey:(id aValue, [forKey] CPString aKey)
Sends messages (CPNotification) between objects.
CPPlatformWindow platformWindow()
id valueForAttributeWithName:forClass:(CPString aName, [forClass] id aClass)