00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 @import <Foundation/CPCoder.j>
00024 @import <Foundation/CPObject.j>
00025 @import <Foundation/CPString.j>
00026
00027 @import <AppKit/CPImage.j>
00028 @import <AppKit/CPMenu.j>
00029 @import <AppKit/CPView.j>
00030
00039 @implementation CPMenuItem : CPObject
00040 {
00041 BOOL _isSeparator;
00042
00043 CPString _title;
00044
00045
00046 CPFont _font;
00047
00048 id _target;
00049 SEL _action;
00050
00051 BOOL _isEnabled;
00052 BOOL _isHidden;
00053
00054 int _tag;
00055 int _state;
00056
00057 CPImage _image;
00058 CPImage _alternateImage;
00059 CPImage _onStateImage;
00060 CPImage _offStateImage;
00061 CPImage _mixedStateImage;
00062
00063 CPMenu _submenu;
00064 CPMenu _menu;
00065
00066 CPString _keyEquivalent;
00067 unsigned _keyEquivalentModifierMask;
00068
00069 int _mnemonicLocation;
00070
00071 BOOL _isAlternate;
00072 int _indentationLevel;
00073
00074 CPString _toolTip;
00075 id _representedObject;
00076 CPView _view;
00077
00078 _CPMenuItemView _menuItemView;
00079 }
00080
00088 - (id)initWithTitle:(CPString)aTitle action:(SEL)anAction keyEquivalent:(CPString)aKeyEquivalent
00089 {
00090 self = [super init];
00091
00092 if (self)
00093 {
00094 _isSeparator = NO;
00095
00096 _title = aTitle;
00097 _action = anAction;
00098
00099 _isEnabled = YES;
00100
00101 _tag = 0;
00102 _state = CPOffState;
00103
00104 _keyEquivalent = aKeyEquivalent || @"";
00105 _keyEquivalentModifierMask = CPPlatformActionKeyMask;
00106
00107 _mnemonicLocation = CPNotFound;
00108 }
00109
00110 return self;
00111 }
00112
00113
00118 - (void)setEnabled:(BOOL)isEnabled
00119 {
00120 if ([_menu autoenablesItems])
00121 return;
00122
00123 _isEnabled = isEnabled;
00124
00125 [_menuItemView setDirty];
00126
00127 [_menu itemChanged:self];
00128 }
00129
00133 - (BOOL)isEnabled
00134 {
00135 return _isEnabled;
00136 }
00137
00138
00143 - (void)setHidden:(BOOL)isHidden
00144 {
00145 if (_isHidden == isHidden)
00146 return;
00147
00148 _isHidden = isHidden;
00149
00150 [_menu itemChanged:self];
00151 }
00152
00156 - (BOOL)isHidden
00157 {
00158 return _isHidden;
00159 }
00160
00164 - (BOOL)isHiddenOrHasHiddenAncestor
00165 {
00166 if (_isHidden)
00167 return YES;
00168
00169 var supermenu = [_menu supermenu];
00170
00171 if ([[supermenu itemAtIndex:[supermenu indexOfItemWithSubmenu:_menu]] isHiddenOrHasHiddenAncestor])
00172 return YES;
00173
00174 return NO;
00175 }
00176
00177
00182 - (void)setTarget:(id)aTarget
00183 {
00184 _target = aTarget;
00185 }
00186
00190 - (id)target
00191 {
00192 return _target;
00193 }
00194
00199 - (void)setAction:(SEL)anAction
00200 {
00201 _action = anAction;
00202 }
00203
00207 - (SEL)action
00208 {
00209 return _action;
00210 }
00211
00212
00217 - (void)setTitle:(CPString)aTitle
00218 {
00219 _mnemonicLocation = CPNotFound;
00220
00221 if (_title == aTitle)
00222 return;
00223
00224 _title = aTitle;
00225
00226 [_menuItemView setDirty];
00227
00228 [_menu itemChanged:self];
00229 }
00230
00234 - (CPString)title
00235 {
00236 return _title;
00237 }
00238
00242 - (void)setTextColor:(CPString)aColor
00243 {
00244
00245 }
00246
00251 - (void)setFont:(CPFont)aFont
00252 {
00253 if (_font == aFont)
00254 return;
00255
00256 _font = aFont;
00257
00258 [_menu itemChanged:self];
00259
00260 [_menuItemView setDirty];
00261 }
00262
00266 - (CPFont)font
00267 {
00268 return _font;
00269 }
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00286 - (void)setTag:(int)aTag
00287 {
00288 _tag = aTag;
00289 }
00290
00294 - (int)tag
00295 {
00296 return _tag;
00297 }
00298
00307 - (void)setState:(int)aState
00308 {
00309 if (_state == aState)
00310 return;
00311
00312 _state = aState;
00313
00314 [_menu itemChanged:self];
00315
00316 [_menuItemView setDirty];
00317 }
00318
00327 - (int)state
00328 {
00329 return _state;
00330 }
00331
00332
00337 - (void)setImage:(CPImage)anImage
00338 {
00339 if (_image == anImage)
00340 return;
00341
00342 _image = anImage;
00343
00344 [_menuItemView setDirty];
00345
00346 [_menu itemChanged:self];
00347 }
00348
00352 - (CPImage)image
00353 {
00354 return _image;
00355 }
00356
00361 - (void)setAlternateImage:(CPImage)anImage
00362 {
00363 _alternateImage = anImage;
00364 }
00365
00369 - (CPImage)alternateImage
00370 {
00371 return _alternateImage;
00372 }
00373
00379 - (void)setOnStateImage:(CPImage)anImage
00380 {
00381 if (_onStateImage == anImage)
00382 return;
00383
00384 _onStateImage = anImage;
00385 [_menu itemChanged:self];
00386 }
00387
00391 - (CPImage)onStateImage
00392 {
00393 return _onStateImage;
00394 }
00395
00400 - (void)setOffStateImage:(CPImage)anImage
00401 {
00402 if (_offStateImage == anImage)
00403 return;
00404
00405 _offStateImage = anImage;
00406 [_menu itemChanged:self];
00407 }
00408
00412 - (CPImage)offStateImage
00413 {
00414 return _offStateImage;
00415 }
00416
00421 - (void)setMixedStateImage:(CPImage)anImage
00422 {
00423 if (_mixedStateImage == anImage)
00424 return;
00425
00426 _mixedStateImage = anImage;
00427 [_menu itemChanged:self];
00428 }
00429
00434 - (CPImage)mixedStateImage
00435 {
00436 return _mixedStateImage;
00437 }
00438
00439
00444 - (void)setSubmenu:(CPMenu)aMenu
00445 {
00446 var supermenu = [_submenu supermenu];
00447
00448 if (supermenu == self)
00449 return;
00450
00451 if (supermenu)
00452 return alert("bad");
00453
00454 [_submenu setSupermenu:_menu];
00455
00456 _submenu = aMenu;
00457
00458 [_menuItemView setDirty];
00459
00460 [_menu itemChanged:self];
00461 }
00462
00466 - (CPMenu)submenu
00467 {
00468 return _submenu;
00469 }
00470
00474 - (BOOL)hasSubmenu
00475 {
00476 return _submenu ? YES : NO;
00477 }
00478
00479
00480
00484 + (CPMenuItem)separatorItem
00485 {
00486 var separatorItem = [[self alloc] initWithTitle:@"" action:nil keyEquivalent:nil];
00487
00488 separatorItem._isSeparator = YES;
00489
00490 return separatorItem;
00491 }
00492
00496 - (BOOL)isSeparatorItem
00497 {
00498 return _isSeparator;
00499 }
00500
00501
00506 - (void)setMenu:(CPMenu)aMenu
00507 {
00508 _menu = aMenu;
00509 }
00510
00514 - (CPMenu)menu
00515 {
00516 return _menu;
00517 }
00518
00519
00520
00525 - (void)setKeyEquivalent:(CPString)aString
00526 {
00527 _keyEquivalent = aString || @"";
00528 }
00529
00533 - (CPString)keyEquivalent
00534 {
00535 return _keyEquivalent;
00536 }
00537
00548 - (void)setKeyEquivalentModifierMask:(unsigned)aMask
00549 {
00550 _keyEquivalentModifierMask = aMask;
00551 }
00552
00563 - (unsigned)keyEquivalentModifierMask
00564 {
00565 return _keyEquivalentModifierMask;
00566 }
00567
00568
00574 - (void)setMnemonicLocation:(unsigned)aLocation
00575 {
00576 _mnemonicLocation = aLocation;
00577 }
00578
00582 - (unsigned)mnemonicLocation
00583 {
00584 return _mnemonicLocation;
00585 }
00586
00591 - (void)setTitleWithMnemonicLocation:(CPString)aTitle
00592 {
00593 var location = [aTitle rangeOfString:@"&"].location;
00594
00595 if (location == CPNotFound)
00596 [self setTitle:aTitle];
00597 else
00598 {
00599 [self setTitle:[aTitle substringToIndex:location] + [aTitle substringFromIndex:location + 1]];
00600 [self setMnemonicLocation:location];
00601 }
00602 }
00603
00607 - (CPString)mnemonic
00608 {
00609 return _mnemonicLocation == CPNotFound ? @"" : [_title characterAtIndex:_mnemonicLocation];
00610 }
00611
00612
00613
00618 - (void)setAlternate:(BOOL)isAlternate
00619 {
00620 _isAlternate = isAlternate;
00621 }
00622
00626 - (BOOL)isAlternate
00627 {
00628 return _isAlternate;
00629 }
00630
00631
00632
00638 - (void)setIndentationLevel:(unsigned)aLevel
00639 {
00640 if (aLevel < 0)
00641 [CPException raise:CPInvalidArgumentException reason:"setIndentationLevel: argument must be greater than 0."];
00642
00643 _indentationLevel = MIN(15, aLevel);
00644 }
00645
00649 - (unsigned)indentationLevel
00650 {
00651 return _indentationLevel;
00652 }
00653
00654
00659 - (void)setToolTip:(CPString)aToolTip
00660 {
00661 _toolTip = aToolTip;
00662 }
00663
00667 - (CPString)toolTip
00668 {
00669 return _toolTip;
00670 }
00671
00672
00673
00678 - (void)setRepresentedObject:(id)anObject
00679 {
00680 _representedObject = anObject;
00681 }
00682
00686 - (id)representedObject
00687 {
00688 return _representedObject;
00689 }
00690
00691
00692
00697 - (void)setView:(CPView)aView
00698 {
00699 if (_view === aView)
00700 return;
00701
00702 _view = aView;
00703
00704 [_menuItemView setDirty];
00705
00706 [_menu itemChanged:self];
00707 }
00708
00712 - (CPView)view
00713 {
00714 return _view;
00715 }
00716
00717
00718
00722 - (BOOL)isHighlighted
00723 {
00724 return [[self menu] highlightedItem] == self;
00725 }
00726
00727
00728
00729
00730
00731
00732 - (id)_menuItemView
00733 {
00734 if (!_menuItemView)
00735 _menuItemView = [[_CPMenuItemView alloc] initWithFrame:CGRectMakeZero() forMenuItem:self];
00736
00737 return _menuItemView;
00738 }
00739
00740 @end
00741
00742 var CPMenuItemIsSeparatorKey = @"CPMenuItemIsSeparatorKey",
00743
00744 CPMenuItemTitleKey = @"CPMenuItemTitleKey",
00745 CPMenuItemTargetKey = @"CPMenuItemTargetKey",
00746 CPMenuItemActionKey = @"CPMenuItemActionKey",
00747
00748 CPMenuItemIsEnabledKey = @"CPMenuItemIsEnabledKey",
00749 CPMenuItemIsHiddenKey = @"CPMenuItemIsHiddenKey",
00750
00751 CPMenuItemTagKey = @"CPMenuItemTagKey",
00752 CPMenuItemStateKey = @"CPMenuItemStateKey",
00753
00754 CPMenuItemImageKey = @"CPMenuItemImageKey",
00755 CPMenuItemAlternateImageKey = @"CPMenuItemAlternateImageKey",
00756
00757 CPMenuItemSubmenuKey = @"CPMenuItemSubmenuKey",
00758 CPMenuItemMenuKey = @"CPMenuItemMenuKey",
00759
00760 CPMenuItemRepresentedObjectKey = @"CPMenuItemRepresentedObjectKey",
00761 CPMenuItemViewKey = @"CPMenuItemViewKey";
00762
00763 #define DEFAULT_VALUE(aKey, aDefaultValue) [aCoder containsValueForKey:(aKey)] ? [aCoder decodeObjectForKey:(aKey)] : (aDefaultValue)
00764 #define ENCODE_IFNOT(aKey, aValue, aDefaultValue) if ((aValue) !== (aDefaultValue)) [aCoder encodeObject:(aValue) forKey:(aKey)];
00765
00766 @implementation CPMenuItem (CPCoding)
00772 - (id)initWithCoder:(CPCoder)aCoder
00773 {
00774 self = [super init];
00775
00776 if (self)
00777 {
00778 _isSeparator = [aCoder containsValueForKey:CPMenuItemIsSeparatorKey] && [aCoder decodeBoolForKey:CPMenuItemIsSeparatorKey];
00779
00780 _title = [aCoder decodeObjectForKey:CPMenuItemTitleKey];
00781
00782
00783
00784 _target = [aCoder decodeObjectForKey:CPMenuItemTargetKey];
00785 _action = [aCoder decodeObjectForKey:CPMenuItemActionKey];
00786
00787 _isEnabled = DEFAULT_VALUE(CPMenuItemIsEnabledKey, YES);
00788 _isHidden = DEFAULT_VALUE(CPMenuItemIsHiddenKey, NO);
00789 _tag = DEFAULT_VALUE(CPMenuItemTagKey, 0);
00790 _state = DEFAULT_VALUE(CPMenuItemStateKey, CPOffState);
00791
00792
00793 _image = DEFAULT_VALUE(CPMenuItemImageKey, nil);
00794 _alternateImage = DEFAULT_VALUE(CPMenuItemAlternateImageKey, nil);
00795
00796
00797
00798
00799 _submenu = DEFAULT_VALUE(CPMenuItemSubmenuKey, nil);
00800 _menu = DEFAULT_VALUE(CPMenuItemMenuKey, nil);
00801
00802
00803
00804
00805
00806
00807
00808
00809
00810
00811
00812 _representedObject = DEFAULT_VALUE(CPMenuItemRepresentedObjectKey, nil);
00813 _view = DEFAULT_VALUE(CPMenuItemViewKey, nil);
00814 }
00815
00816 return self;
00817 }
00818
00823 - (void)encodeWithCoder:(CPCoder)aCoder
00824 {
00825 if (_isSeparator)
00826 [aCoder encodeBool:_isSeparator forKey:CPMenuItemIsSeparatorKey];
00827
00828 [aCoder encodeObject:_title forKey:CPMenuItemTitleKey];
00829
00830 [aCoder encodeObject:_target forKey:CPMenuItemTargetKey];
00831 [aCoder encodeObject:_action forKey:CPMenuItemActionKey];
00832
00833 ENCODE_IFNOT(CPMenuItemIsEnabledKey, _isEnabled, YES);
00834 ENCODE_IFNOT(CPMenuItemIsHiddenKey, _isHidden, NO);
00835
00836 ENCODE_IFNOT(CPMenuItemTagKey, _tag, 0);
00837 ENCODE_IFNOT(CPMenuItemStateKey, _state, CPOffState);
00838
00839 ENCODE_IFNOT(CPMenuItemImageKey, _image, nil);
00840 ENCODE_IFNOT(CPMenuItemAlternateImageKey, _alternateImage, nil);
00841
00842 ENCODE_IFNOT(CPMenuItemSubmenuKey, _submenu, nil);
00843 ENCODE_IFNOT(CPMenuItemMenuKey, _menu, nil);
00844
00845 ENCODE_IFNOT(CPMenuItemRepresentedObjectKey, _representedObject, nil);
00846 ENCODE_IFNOT(CPMenuItemViewKey, _view, nil);
00847 }
00848
00849 @end
00850
00851 var LEFT_MARGIN = 3.0,
00852 RIGHT_MARGIN = 16.0,
00853 STATE_COLUMN_WIDTH = 14.0,
00854 INDENTATION_WIDTH = 17.0,
00855 VERTICAL_MARGIN = 4.0;
00856
00857 var _CPMenuItemSelectionColor = nil,
00858 _CPMenuItemTextShadowColor = nil,
00859
00860 _CPMenuItemDefaultStateImages = [],
00861 _CPMenuItemDefaultStateHighlightedImages = [];
00862
00863
00864
00865
00866 @implementation _CPMenuItemView : CPView
00867 {
00868 CPMenuItem _menuItem;
00869
00870 CPFont _font;
00871 CPColor _textColor;
00872 CPColor _textShadowColor;
00873 CPColor _activateColor;
00874 CPColor _activateShadowColor;
00875
00876 CGSize _minSize;
00877 BOOL _isDirty;
00878 BOOL _showsStateColumn;
00879 BOOL _belongsToMenuBar;
00880
00881 CPImageView _stateView;
00882 _CPImageAndTextView _imageAndTextView;
00883 CPView _submenuView;
00884 }
00885
00886 + (void)initialize
00887 {
00888 if (self != [_CPMenuItemView class])
00889 return;
00890
00891 _CPMenuItemSelectionColor = [CPColor colorWithCalibratedRed:95.0 / 255.0 green:131.0 / 255.0 blue:185.0 / 255.0 alpha:1.0];
00892 _CPMenuItemTextShadowColor = [CPColor colorWithCalibratedRed:26.0 / 255.0 green: 73.0 / 255.0 blue:109.0 / 255.0 alpha:1.0]
00893
00894 var bundle = [CPBundle bundleForClass:self];
00895
00896 _CPMenuItemDefaultStateImages[CPOffState] = nil;
00897 _CPMenuItemDefaultStateHighlightedImages[CPOffState] = nil;
00898
00899 _CPMenuItemDefaultStateImages[CPOnState] = [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPMenuItem/CPMenuItemOnState.png"] size:CGSizeMake(14.0, 14.0)];
00900 _CPMenuItemDefaultStateHighlightedImages[CPOnState] = [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPMenuItem/CPMenuItemOnStateHighlighted.png"] size:CGSizeMake(14.0, 14.0)];
00901
00902 _CPMenuItemDefaultStateImages[CPMixedState] = nil;
00903 _CPMenuItemDefaultStateHighlightedImages[CPMixedState] = nil;
00904 }
00905
00906 + (float)leftMargin
00907 {
00908 return LEFT_MARGIN + STATE_COLUMN_WIDTH;
00909 }
00910
00911 - (id)initWithFrame:(CGRect)aFrame forMenuItem:(CPMenuItem)aMenuItem
00912 {
00913 self = [super initWithFrame:aFrame];
00914
00915 if (self)
00916 {
00917 _menuItem = aMenuItem;
00918 _showsStateColumn = YES;
00919 _isDirty = YES;
00920
00921 [self setAutoresizingMask:CPViewWidthSizable];
00922
00923 [self synchronizeWithMenuItem];
00924 }
00925
00926 return self;
00927 }
00928
00929 - (CGSize)minSize
00930 {
00931 return _minSize;
00932 }
00933
00934 - (void)setDirty
00935 {
00936 _isDirty = YES;
00937 }
00938
00939 - (void)synchronizeWithMenuItem
00940 {
00941 if (!_isDirty)
00942 return;
00943
00944 _isDirty = NO;
00945
00946 var view = [_menuItem view];
00947
00948 if ([_menuItem isSeparatorItem])
00949 {
00950 var line = [[CPView alloc] initWithFrame:CGRectMake(0.0, 5.0, 10.0, 1.0)];
00951
00952 view = [[CPView alloc] initWithFrame:CGRectMake(0.0, 0.0, 0.0, 10.0)];
00953
00954 [view setAutoresizingMask:CPViewWidthSizable];
00955 [line setAutoresizingMask:CPViewWidthSizable];
00956
00957 [line setBackgroundColor:[CPColor lightGrayColor]];
00958
00959 [view addSubview:line];
00960 }
00961
00962 if (view)
00963 {
00964 [_imageAndTextView removeFromSuperview];
00965 _imageAndTextView = nil;
00966
00967 [_stateView removeFromSuperview];
00968 _stateView = nil;
00969
00970 [_submenuView removeFromSuperview];
00971 _submenuView = nil;
00972
00973 _minSize = [view frame].size;
00974
00975 [self setFrameSize:_minSize];
00976
00977 [self addSubview:view];
00978
00979 return;
00980 }
00981
00982
00983 var x = _belongsToMenuBar ? 0.0 : (LEFT_MARGIN + [_menuItem indentationLevel] * INDENTATION_WIDTH);
00984
00985 if (_showsStateColumn)
00986 {
00987 if (!_stateView)
00988 {
00989 _stateView = [[CPImageView alloc] initWithFrame:CGRectMake(x, (CGRectGetHeight([self frame]) - STATE_COLUMN_WIDTH) / 2.0, STATE_COLUMN_WIDTH, STATE_COLUMN_WIDTH)];
00990
00991 [_stateView setAutoresizingMask:CPViewMinYMargin | CPViewMaxYMargin];
00992
00993 [self addSubview:_stateView];
00994 }
00995
00996 var state = [_menuItem state];
00997
00998 switch (state)
00999 {
01000 case CPOffState:
01001 case CPOnState:
01002 case CPMixedState: [_stateView setImage:_CPMenuItemDefaultStateImages[state]];
01003 break;
01004
01005 default: [_stateView setImage:nil];
01006 }
01007
01008 x += STATE_COLUMN_WIDTH;
01009 }
01010 else
01011 {
01012 [_stateView removeFromSuperview];
01013
01014 _stateView = nil;
01015 }
01016
01017
01018
01019 if (!_imageAndTextView)
01020 {
01021 _imageAndTextView = [[_CPImageAndTextView alloc] initWithFrame:CGRectMake(0.0, 0.0, 0.0, 0.0)];
01022
01023 [_imageAndTextView setImagePosition:CPImageLeft];
01024 [_imageAndTextView setTextShadowOffset:CGSizeMake(0.0, 1.0)];
01025
01026 [self addSubview:_imageAndTextView];
01027 }
01028
01029 var font = [_menuItem font];
01030
01031 if (!font)
01032 font = _font;
01033
01034 [_imageAndTextView setFont:font];
01035 [_imageAndTextView setVerticalAlignment:CPCenterVerticalTextAlignment];
01036 [_imageAndTextView setImage:[_menuItem image]];
01037 [_imageAndTextView setText:[_menuItem title]];
01038 [_imageAndTextView setTextColor:[self textColor]];
01039 [_imageAndTextView setTextShadowColor:[self textShadowColor]];
01040 [_imageAndTextView setTextShadowOffset:CGSizeMake(0, 1)];
01041 [_imageAndTextView setFrameOrigin:CGPointMake(x, VERTICAL_MARGIN)];
01042 [_imageAndTextView sizeToFit];
01043
01044 var frame = [_imageAndTextView frame];
01045
01046
01047
01048
01049 frame.size.height += 2 * VERTICAL_MARGIN;
01050
01051 x += CGRectGetWidth(frame);
01052
01053
01054 if ([_menuItem hasSubmenu])
01055 {
01056 x += 3.0;
01057
01058 if (!_submenuView)
01059 {
01060 _submenuView = [[_CPMenuItemArrowView alloc] initWithFrame:CGRectMake(0.0, 0.0, 10.0, 10.0)];
01061
01062 [self addSubview:_submenuView];
01063 }
01064
01065 [_submenuView setHidden:NO];
01066 [_submenuView setColor:_belongsToMenuBar ? [self textColor] : nil];
01067 [_submenuView setFrameOrigin:CGPointMake(x, (CGRectGetHeight(frame) - 10.0) / 2.0)];
01068
01069 x += 10.0;
01070 }
01071 else
01072 [_submenuView setHidden:YES];
01073
01074 _minSize = CGSizeMake(x + (_belongsToMenuBar ? 0.0 : RIGHT_MARGIN) + 3.0, CGRectGetHeight(frame));
01075
01076 [self setFrameSize:_minSize];
01077 }
01078
01079 - (CGFloat)overlapOffsetWidth
01080 {
01081 return LEFT_MARGIN + ([[_menuItem menu] showsStateColumn] ? STATE_COLUMN_WIDTH : 0.0);
01082 }
01083
01084 - (void)setShowsStateColumn:(BOOL)shouldShowStateColumn
01085 {
01086 _showsStateColumn = shouldShowStateColumn;
01087 }
01088
01089 - (void)setBelongsToMenuBar:(BOOL)shouldBelongToMenuBar
01090 {
01091 _belongsToMenuBar = shouldBelongToMenuBar;
01092 }
01093
01094 - (void)highlight:(BOOL)shouldHighlight
01095 {
01096
01097
01098 if (_belongsToMenuBar)
01099 [_imageAndTextView setImage:shouldHighlight ? [_menuItem alternateImage] : [_menuItem image]];
01100
01101 else if ([_menuItem isEnabled])
01102 {
01103 if (shouldHighlight)
01104 {
01105 [self setBackgroundColor:_CPMenuItemSelectionColor];
01106
01107 [_imageAndTextView setTextColor:[CPColor whiteColor]];
01108 [_imageAndTextView setTextShadowColor:_CPMenuItemTextShadowColor];
01109 }
01110 else
01111 {
01112 [self setBackgroundColor:nil];
01113
01114 [_imageAndTextView setTextColor:[self textColor]];
01115 [_imageAndTextView setTextShadowColor:[self textShadowColor]];
01116 }
01117
01118 var state = [_menuItem state];
01119
01120 switch (state)
01121 {
01122 case CPOffState:
01123 case CPOnState:
01124 case CPMixedState: [_stateView setImage:shouldHighlight ? _CPMenuItemDefaultStateHighlightedImages[state] : _CPMenuItemDefaultStateImages[state]];
01125 break;
01126
01127 default: [_stateView setImage:nil];
01128 }
01129 }
01130 }
01131
01132 - (void)activate:(BOOL)shouldActivate
01133 {
01134 [_imageAndTextView setImage:[_menuItem image]];
01135
01136 if (shouldActivate)
01137 {
01138 [_imageAndTextView setTextColor:[self activateColor] || [CPColor whiteColor]];
01139 [_imageAndTextView setTextShadowColor:[self activateShadowColor] || [CPColor blackColor]];
01140 [_submenuView setColor:[self activateColor] || [CPColor whiteColor]];
01141 }
01142 else
01143 {
01144 [_imageAndTextView setTextColor:[self textColor]];
01145 [_imageAndTextView setTextShadowColor:[self textShadowColor]];
01146 [_submenuView setColor:[self textColor]];
01147 }
01148 }
01149
01150 - (BOOL)eventOnSubmenu:(CPEvent)anEvent
01151 {
01152 if (![_menuItem hasSubmenu])
01153 return NO;
01154
01155 return CGRectContainsPoint([_submenuView frame], [self convertPoint:[anEvent locationInWindow] fromView:nil]);
01156 }
01157
01158 - (BOOL)isHidden
01159 {
01160 return [_menuItem isHidden];
01161 }
01162
01163 - (CPMenuItem)menuItem
01164 {
01165 return _menuItem;
01166 }
01167
01168 - (void)setFont:(CPFont)aFont
01169 {
01170 if (_font == aFont)
01171 return;
01172
01173 _font = aFont;
01174
01175 [self setDirty];
01176 }
01177
01178 - (void)setTextColor:(CPColor)aColor
01179 {
01180 if (_textColor == aColor)
01181 return;
01182
01183 _textColor = aColor;
01184
01185 [_imageAndTextView setTextColor:[self textColor]];
01186 [_submenuView setColor:[self textColor]];
01187 }
01188
01189 - (CPColor)textColor
01190 {
01191 return [_menuItem isEnabled] ? (_textColor ? _textColor : [CPColor colorWithCalibratedRed:70.0 / 255.0 green:69.0 / 255.0 blue:69.0 / 255.0 alpha:1.0]) : [CPColor darkGrayColor];
01192 }
01193
01194 - (void)setTextShadowColor:(CPColor)aColor
01195 {
01196 if (_textShadowColor == aColor)
01197 return;
01198
01199 _textShadowColor = aColor;
01200
01201 [_imageAndTextView setTextShadowColor:[self textShadowColor]];
01202
01203 }
01204
01205 - (CPColor)textShadowColor
01206 {
01207 return [_menuItem isEnabled] ? (_textShadowColor ? _textShadowColor : [CPColor colorWithWhite:1.0 alpha:0.8]) : [CPColor colorWithWhite:0.8 alpha:0.8];
01208 }
01209
01210 - (void)setActivateColor:(CPColor)aColor
01211 {
01212 _activateColor = aColor;
01213 }
01214
01215 - (CPColor)activateColor
01216 {
01217 return _activateColor;
01218 }
01219
01220 - (void)setActivateShadowColor:(CPColor)aColor
01221 {
01222 _activateShadowColor = aColor;
01223 }
01224
01225 - (CPColor)activateShadowColor
01226 {
01227 return _activateShadowColor;
01228 }
01229
01230 @end
01231
01232 @implementation _CPMenuItemArrowView : CPView
01233 {
01234 CPColor _color;
01235 }
01236
01237 - (void)setColor:(CPColor)aColor
01238 {
01239 if (_color == aColor)
01240 return;
01241
01242 _color = aColor;
01243
01244 [self setNeedsDisplay:YES];
01245 }
01246
01247 - (void)drawRect:(CGRect)aRect
01248 {
01249 var context = [[CPGraphicsContext currentContext] graphicsPort];
01250
01251 CGContextBeginPath(context);
01252
01253 CGContextMoveToPoint(context, 1.0, 4.0);
01254 CGContextAddLineToPoint(context, 9.0, 4.0);
01255 CGContextAddLineToPoint(context, 5.0, 8.0);
01256 CGContextAddLineToPoint(context, 1.0, 4.0);
01257
01258 CGContextClosePath(context);
01259
01260 CGContextSetFillColor(context, _color);
01261 CGContextFillPath(context);
01262 }
01263
01264 @end