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 CPString _title;
00042
00043
00044 CPFont _font;
00045
00046 id _target;
00047 SEL _action;
00048
00049 BOOL _isEnabled;
00050 BOOL _isHidden;
00051
00052 int _tag;
00053 int _state;
00054
00055 CPImage _image;
00056 CPImage _alternateImage;
00057 CPImage _onStateImage;
00058 CPImage _offStateImage;
00059 CPImage _mixedStateImage;
00060
00061 CPMenu _submenu;
00062 CPMenu _menu;
00063
00064 CPString _keyEquivalent;
00065 unsigned _keyEquivalentModifierMask;
00066
00067 int _mnemonicLocation;
00068
00069 BOOL _isAlternate;
00070 int _indentationLevel;
00071
00072 CPString _toolTip;
00073 id _representedObject;
00074 CPView _view;
00075
00076 _CPMenuItemView _menuItemView;
00077 }
00078
00086 - (id)initWithTitle:(CPString)aTitle action:(SEL)anAction keyEquivalent:(CPString)aKeyEquivalent
00087 {
00088 self = [super init];
00089
00090 if (self)
00091 {
00092 _title = aTitle;
00093 _action = anAction;
00094
00095 _isEnabled = YES;
00096
00097 _tag = 0;
00098 _state = CPOffState;
00099
00100 _keyEquivalent = aKeyEquivalent || @"";
00101 _keyEquivalentModifierMask = CPPlatformActionKeyMask;
00102
00103 _mnemonicLocation = CPNotFound;
00104 }
00105
00106 return self;
00107 }
00108
00109
00114 - (void)setEnabled:(BOOL)isEnabled
00115 {
00116 if ([_menu autoenablesItems])
00117 return;
00118
00119 _isEnabled = isEnabled;
00120
00121 [_menuItemView setDirty];
00122
00123 [_menu itemChanged:self];
00124 }
00125
00129 - (BOOL)isEnabled
00130 {
00131 return _isEnabled;
00132 }
00133
00134
00139 - (void)setHidden:(BOOL)isHidden
00140 {
00141 if (_isHidden == isHidden)
00142 return;
00143
00144 _isHidden = isHidden;
00145
00146 [_menu itemChanged:self];
00147 }
00148
00152 - (BOOL)isHidden
00153 {
00154 return _isHidden;
00155 }
00156
00160 - (BOOL)isHiddenOrHasHiddenAncestor
00161 {
00162 if (_isHidden)
00163 return YES;
00164
00165 var supermenu = [_menu supermenu];
00166
00167 if ([[supermenu itemAtIndex:[supermenu indexOfItemWithSubmenu:_menu]] isHiddenOrHasHiddenAncestor])
00168 return YES;
00169
00170 return NO;
00171 }
00172
00173
00178 - (void)setTarget:(id)aTarget
00179 {
00180 _target = aTarget;
00181 }
00182
00186 - (id)target
00187 {
00188 return _target;
00189 }
00190
00195 - (void)setAction:(SEL)anAction
00196 {
00197 _action = anAction;
00198 }
00199
00203 - (SEL)action
00204 {
00205 return _action;
00206 }
00207
00208
00213 - (void)setTitle:(CPString)aTitle
00214 {
00215 _mnemonicLocation = CPNotFound;
00216
00217 if (_title == aTitle)
00218 return;
00219
00220 _title = aTitle;
00221
00222 [_menuItemView setDirty];
00223
00224 [_menu itemChanged:self];
00225 }
00226
00230 - (CPString)title
00231 {
00232 return _title;
00233 }
00234
00238 - (void)setTextColor:(CPString)aColor
00239 {
00240
00241 }
00242
00247 - (void)setFont:(CPFont)aFont
00248 {
00249 if (_font == aFont)
00250 return;
00251
00252 _font = aFont;
00253
00254 [_menu itemChanged:self];
00255
00256 [_menuItemView setDirty];
00257 }
00258
00262 - (CPFont)font
00263 {
00264 return _font;
00265 }
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00282 - (void)setTag:(int)aTag
00283 {
00284 _tag = aTag;
00285 }
00286
00290 - (int)tag
00291 {
00292 return _tag;
00293 }
00294
00303 - (void)setState:(int)aState
00304 {
00305 if (_state == aState)
00306 return;
00307
00308 _state = aState;
00309
00310 [_menu itemChanged:self];
00311
00312 [_menuItemView setDirty];
00313 }
00314
00323 - (int)state
00324 {
00325 return _state;
00326 }
00327
00328
00333 - (void)setImage:(CPImage)anImage
00334 {
00335 if (_image == anImage)
00336 return;
00337
00338 _image = anImage;
00339
00340 [_menuItemView setDirty];
00341
00342 [_menu itemChanged:self];
00343 }
00344
00348 - (CPImage)image
00349 {
00350 return _image;
00351 }
00352
00357 - (void)setAlternateImage:(CPImage)anImage
00358 {
00359 _alternateImage = anImage;
00360 }
00361
00365 - (CPImage)alternateImage
00366 {
00367 return _alternateImage;
00368 }
00369
00375 - (void)setOnStateImage:(CPImage)anImage
00376 {
00377 if (_onStateImage == anImage)
00378 return;
00379
00380 _onStateImage = anImage;
00381 [_menu itemChanged:self];
00382 }
00383
00387 - (CPImage)onStateImage
00388 {
00389 return _onStateImage;
00390 }
00391
00396 - (void)setOffStateImage:(CPImage)anImage
00397 {
00398 if (_offStateImage == anImage)
00399 return;
00400
00401 _offStateImage = anImage;
00402 [_menu itemChanged:self];
00403 }
00404
00408 - (CPImage)offStateImage
00409 {
00410 return _offStateImage;
00411 }
00412
00417 - (void)setMixedStateImage:(CPImage)anImage
00418 {
00419 if (_mixedStateImage == anImage)
00420 return;
00421
00422 _mixedStateImage = anImage;
00423 [_menu itemChanged:self];
00424 }
00425
00430 - (CPImage)mixedStateImage
00431 {
00432 return _mixedStateImage;
00433 }
00434
00435
00440 - (void)setSubmenu:(CPMenu)aMenu
00441 {
00442 var supermenu = [_submenu supermenu];
00443
00444 if (supermenu == self)
00445 return;
00446
00447 if (supermenu)
00448 return alert("bad");
00449
00450 [_submenu setSupermenu:_menu];
00451
00452 _submenu = aMenu;
00453
00454 [_menuItemView setDirty];
00455
00456 [_menu itemChanged:self];
00457 }
00458
00462 - (CPMenu)submenu
00463 {
00464 return _submenu;
00465 }
00466
00470 - (BOOL)hasSubmenu
00471 {
00472 return _submenu ? YES : NO;
00473 }
00474
00475
00476
00480 + (CPMenuItem)separatorItem
00481 {
00482 return [[_CPMenuItemSeparator alloc] init];
00483 }
00484
00488 - (BOOL)isSeparatorItem
00489 {
00490 return NO;
00491 }
00492
00493
00498 - (void)setMenu:(CPMenu)aMenu
00499 {
00500 _menu = aMenu;
00501 }
00502
00506 - (CPMenu)menu
00507 {
00508 return _menu;
00509 }
00510
00511
00512
00517 - (void)setKeyEquivalent:(CPString)aString
00518 {
00519 _keyEquivalent = aString || @"";
00520 }
00521
00525 - (CPString)keyEquivalent
00526 {
00527 return _keyEquivalent;
00528 }
00529
00540 - (void)setKeyEquivalentModifierMask:(unsigned)aMask
00541 {
00542 _keyEquivalentModifierMask = aMask;
00543 }
00544
00555 - (unsigned)keyEquivalentModifierMask
00556 {
00557 return _keyEquivalentModifierMask;
00558 }
00559
00560
00566 - (void)setMnemonicLocation:(unsigned)aLocation
00567 {
00568 _mnemonicLocation = aLocation;
00569 }
00570
00574 - (unsigned)mnemonicLocation
00575 {
00576 return _mnemonicLocation;
00577 }
00578
00583 - (void)setTitleWithMnemonicLocation:(CPString)aTitle
00584 {
00585 var location = [aTitle rangeOfString:@"&"].location;
00586
00587 if (location == CPNotFound)
00588 [self setTitle:aTitle];
00589 else
00590 {
00591 [self setTitle:[aTitle substringToIndex:location] + [aTitle substringFromIndex:location + 1]];
00592 [self setMnemonicLocation:location];
00593 }
00594 }
00595
00599 - (CPString)mnemonic
00600 {
00601 return _mnemonicLocation == CPNotFound ? @"" : [_title characterAtIndex:_mnemonicLocation];
00602 }
00603
00604
00605
00610 - (void)setAlternate:(BOOL)isAlternate
00611 {
00612 _isAlternate = isAlternate;
00613 }
00614
00618 - (BOOL)isAlternate
00619 {
00620 return _isAlternate;
00621 }
00622
00623
00624
00630 - (void)setIndentationLevel:(unsigned)aLevel
00631 {
00632 if (aLevel < 0)
00633 [CPException raise:CPInvalidArgumentException reason:"setIndentationLevel: argument must be greater than 0."];
00634
00635 _indentationLevel = MIN(15, aLevel);
00636 }
00637
00641 - (unsigned)indentationLevel
00642 {
00643 return _indentationLevel;
00644 }
00645
00646
00651 - (void)setToolTip:(CPString)aToolTip
00652 {
00653 _toolTip = aToolTip;
00654 }
00655
00659 - (CPString)toolTip
00660 {
00661 return _toolTip;
00662 }
00663
00664
00665
00670 - (void)setRepresentedObject:(id)anObject
00671 {
00672 _representedObject = anObject;
00673 }
00674
00678 - (id)representedObject
00679 {
00680 return _representedObject;
00681 }
00682
00683
00684
00689 - (void)setView:(CPView)aView
00690 {
00691 if (_view === aView)
00692 return;
00693
00694 _view = aView;
00695
00696 [_menuItemView setDirty];
00697
00698 [_menu itemChanged:self];
00699 }
00700
00704 - (CPView)view
00705 {
00706 return _view;
00707 }
00708
00709
00710
00714 - (BOOL)isHighlighted
00715 {
00716 return [[self menu] highlightedItem] == self;
00717 }
00718
00719
00720
00721
00722
00723
00724 - (id)_menuItemView
00725 {
00726 if (!_menuItemView)
00727 _menuItemView = [[_CPMenuItemView alloc] initWithFrame:CGRectMakeZero() forMenuItem:self];
00728
00729 return _menuItemView;
00730 }
00731
00732 @end
00733
00734
00735 @implementation _CPMenuItemSeparator : CPMenuItem
00736 {
00737 }
00738
00739 - (id)init
00740 {
00741 self = [super initWithTitle:@"" action:nil keyEquivalent:nil];
00742
00743 if (self)
00744 [self setEnabled:NO];
00745
00746 return self;
00747 }
00748
00749 - (BOOL)isSeparatorItem
00750 {
00751 return YES;
00752 }
00753
00754 @end
00755
00756 var CPMenuItemTitleKey = @"CPMenuItemTitleKey",
00757 CPMenuItemTargetKey = @"CPMenuItemTargetKey",
00758 CPMenuItemActionKey = @"CPMenuItemActionKey",
00759
00760 CPMenuItemIsEnabledKey = @"CPMenuItemIsEnabledKey",
00761 CPMenuItemIsHiddenKey = @"CPMenuItemIsHiddenKey",
00762
00763 CPMenuItemTagKey = @"CPMenuItemTagKey",
00764 CPMenuItemStateKey = @"CPMenuItemStateKey",
00765
00766 CPMenuItemImageKey = @"CPMenuItemImageKey",
00767 CPMenuItemAlternateImageKey = @"CPMenuItemAlternateImageKey",
00768
00769 CPMenuItemSubmenuKey = @"CPMenuItemSubmenuKey",
00770 CPMenuItemMenuKey = @"CPMenuItemMenuKey",
00771
00772 CPMenuItemRepresentedObjectKey = @"CPMenuItemRepresentedObjectKey",
00773 CPMenuItemViewKey = @"CPMenuItemViewKey";
00774
00775 #define DEFAULT_VALUE(aKey, aDefaultValue) [aCoder containsValueForKey:(aKey)] ? [aCoder decodeObjectForKey:(aKey)] : (aDefaultValue)
00776 #define ENCODE_IFNOT(aKey, aValue, aDefaultValue) if ((aValue) !== (aDefaultValue)) [aCoder encodeObject:(aValue) forKey:(aKey)];
00777
00778 @implementation CPMenuItem (CPCoding)
00784 - (id)initWithCoder:(CPCoder)aCoder
00785 {
00786 self = [super init];
00787
00788 if (self)
00789 {
00790 _title = [aCoder decodeObjectForKey:CPMenuItemTitleKey];
00791
00792
00793
00794 _target = [aCoder decodeObjectForKey:CPMenuItemTargetKey];
00795 _action = [aCoder decodeObjectForKey:CPMenuItemActionKey];
00796
00797 _isEnabled = DEFAULT_VALUE(CPMenuItemIsEnabledKey, YES);
00798 _isHidden = DEFAULT_VALUE(CPMenuItemIsHiddenKey, NO);
00799 _tag = DEFAULT_VALUE(CPMenuItemTagKey, 0);
00800 _state = DEFAULT_VALUE(CPMenuItemStateKey, CPOffState);
00801
00802
00803 _image = DEFAULT_VALUE(CPMenuItemImageKey, nil);
00804 _alternateImage = DEFAULT_VALUE(CPMenuItemAlternateImageKey, nil);
00805
00806
00807
00808
00809 _submenu = DEFAULT_VALUE(CPMenuItemSubmenuKey, nil);
00810 _menu = DEFAULT_VALUE(CPMenuItemMenuKey, nil);
00811
00812
00813
00814
00815
00816
00817
00818
00819
00820
00821
00822 _representedObject = DEFAULT_VALUE(CPMenuItemRepresentedObjectKey, nil);
00823 _view = DEFAULT_VALUE(CPMenuItemViewKey, nil);
00824 }
00825
00826 return self;
00827 }
00828
00833 - (void)encodeWithCoder:(CPCoder)aCoder
00834 {
00835 [aCoder encodeObject:_title forKey:CPMenuItemTitleKey];
00836
00837 [aCoder encodeObject:_target forKey:CPMenuItemTargetKey];
00838 [aCoder encodeObject:_action forKey:CPMenuItemActionKey];
00839
00840 ENCODE_IFNOT(CPMenuItemIsEnabledKey, _isEnabled, YES);
00841 ENCODE_IFNOT(CPMenuItemIsHiddenKey, _isHidden, NO);
00842
00843 ENCODE_IFNOT(CPMenuItemTagKey, _tag, 0);
00844 ENCODE_IFNOT(CPMenuItemStateKey, _state, CPOffState);
00845
00846 ENCODE_IFNOT(CPMenuItemImageKey, _image, nil);
00847 ENCODE_IFNOT(CPMenuItemAlternateImageKey, _alternateImage, nil);
00848
00849 ENCODE_IFNOT(CPMenuItemSubmenuKey, _submenu, nil);
00850 ENCODE_IFNOT(CPMenuItemMenuKey, _menu, nil);
00851
00852 ENCODE_IFNOT(CPMenuItemRepresentedObjectKey, _representedObject, nil);
00853 ENCODE_IFNOT(CPMenuItemViewKey, _view, nil);
00854 }
00855
00856 @end
00857
00858 var LEFT_MARGIN = 3.0,
00859 RIGHT_MARGIN = 16.0,
00860 STATE_COLUMN_WIDTH = 14.0,
00861 INDENTATION_WIDTH = 17.0,
00862 VERTICAL_MARGIN = 4.0;
00863
00864 var _CPMenuItemSelectionColor = nil,
00865 _CPMenuItemTextShadowColor = nil,
00866
00867 _CPMenuItemDefaultStateImages = [],
00868 _CPMenuItemDefaultStateHighlightedImages = [];
00869
00870
00871
00872
00873 @implementation _CPMenuItemView : CPView
00874 {
00875 CPMenuItem _menuItem;
00876
00877 CPFont _font;
00878 CPColor _textColor;
00879 CPColor _textShadowColor;
00880 CPColor _activateColor;
00881 CPColor _activateShadowColor;
00882
00883 CGSize _minSize;
00884 BOOL _isDirty;
00885 BOOL _showsStateColumn;
00886 BOOL _belongsToMenuBar;
00887
00888 CPImageView _stateView;
00889 _CPImageAndTextView _imageAndTextView;
00890 CPView _submenuView;
00891 }
00892
00893 + (void)initialize
00894 {
00895 if (self != [_CPMenuItemView class])
00896 return;
00897
00898 _CPMenuItemSelectionColor = [CPColor colorWithCalibratedRed:95.0 / 255.0 green:131.0 / 255.0 blue:185.0 / 255.0 alpha:1.0];
00899 _CPMenuItemTextShadowColor = [CPColor colorWithCalibratedRed:26.0 / 255.0 green: 73.0 / 255.0 blue:109.0 / 255.0 alpha:1.0]
00900
00901 var bundle = [CPBundle bundleForClass:self];
00902
00903 _CPMenuItemDefaultStateImages[CPOffState] = nil;
00904 _CPMenuItemDefaultStateHighlightedImages[CPOffState] = nil;
00905
00906 _CPMenuItemDefaultStateImages[CPOnState] = [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPMenuItem/CPMenuItemOnState.png"] size:CGSizeMake(14.0, 14.0)];
00907 _CPMenuItemDefaultStateHighlightedImages[CPOnState] = [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPMenuItem/CPMenuItemOnStateHighlighted.png"] size:CGSizeMake(14.0, 14.0)];
00908
00909 _CPMenuItemDefaultStateImages[CPMixedState] = nil;
00910 _CPMenuItemDefaultStateHighlightedImages[CPMixedState] = nil;
00911 }
00912
00913 + (float)leftMargin
00914 {
00915 return LEFT_MARGIN + STATE_COLUMN_WIDTH;
00916 }
00917
00918 - (id)initWithFrame:(CGRect)aFrame forMenuItem:(CPMenuItem)aMenuItem
00919 {
00920 self = [super initWithFrame:aFrame];
00921
00922 if (self)
00923 {
00924 _menuItem = aMenuItem;
00925 _showsStateColumn = YES;
00926 _isDirty = YES;
00927
00928 [self setAutoresizingMask:CPViewWidthSizable];
00929
00930 [self synchronizeWithMenuItem];
00931 }
00932
00933 return self;
00934 }
00935
00936 - (CGSize)minSize
00937 {
00938 return _minSize;
00939 }
00940
00941 - (void)setDirty
00942 {
00943 _isDirty = YES;
00944 }
00945
00946 - (void)synchronizeWithMenuItem
00947 {
00948 if (!_isDirty)
00949 return;
00950
00951 _isDirty = NO;
00952
00953 var view = [_menuItem view];
00954
00955 if ([_menuItem isSeparatorItem])
00956 {
00957 var line = [[CPView alloc] initWithFrame:CGRectMake(0.0, 5.0, 10.0, 1.0)];
00958
00959 view = [[CPView alloc] initWithFrame:CGRectMake(0.0, 0.0, 0.0, 10.0)];
00960
00961 [view setAutoresizingMask:CPViewWidthSizable];
00962 [line setAutoresizingMask:CPViewWidthSizable];
00963
00964 [line setBackgroundColor:[CPColor lightGrayColor]];
00965
00966 [view addSubview:line];
00967 }
00968
00969 if (view)
00970 {
00971 [_imageAndTextView removeFromSuperview];
00972 _imageAndTextView = nil;
00973
00974 [_stateView removeFromSuperview];
00975 _stateView = nil;
00976
00977 [_submenuView removeFromSuperview];
00978 _submenuView = nil;
00979
00980 _minSize = [view frame].size;
00981
00982 [self setFrameSize:_minSize];
00983
00984 [self addSubview:view];
00985
00986 return;
00987 }
00988
00989
00990 var x = _belongsToMenuBar ? 0.0 : (LEFT_MARGIN + [_menuItem indentationLevel] * INDENTATION_WIDTH);
00991
00992 if (_showsStateColumn)
00993 {
00994 if (!_stateView)
00995 {
00996 _stateView = [[CPImageView alloc] initWithFrame:CGRectMake(x, (CGRectGetHeight([self frame]) - STATE_COLUMN_WIDTH) / 2.0, STATE_COLUMN_WIDTH, STATE_COLUMN_WIDTH)];
00997
00998 [_stateView setAutoresizingMask:CPViewMinYMargin | CPViewMaxYMargin];
00999
01000 [self addSubview:_stateView];
01001 }
01002
01003 var state = [_menuItem state];
01004
01005 switch (state)
01006 {
01007 case CPOffState:
01008 case CPOnState:
01009 case CPMixedState: [_stateView setImage:_CPMenuItemDefaultStateImages[state]];
01010 break;
01011
01012 default: [_stateView setImage:nil];
01013 }
01014
01015 x += STATE_COLUMN_WIDTH;
01016 }
01017 else
01018 {
01019 [_stateView removeFromSuperview];
01020
01021 _stateView = nil;
01022 }
01023
01024
01025
01026 if (!_imageAndTextView)
01027 {
01028 _imageAndTextView = [[_CPImageAndTextView alloc] initWithFrame:CGRectMake(0.0, 0.0, 0.0, 0.0)];
01029
01030 [_imageAndTextView setImagePosition:CPImageLeft];
01031 [_imageAndTextView setTextShadowOffset:CGSizeMake(0.0, 1.0)];
01032
01033 [self addSubview:_imageAndTextView];
01034 }
01035
01036 var font = [_menuItem font];
01037
01038 if (!font)
01039 font = _font;
01040
01041 [_imageAndTextView setFont:font];
01042 [_imageAndTextView setVerticalAlignment:CPCenterVerticalTextAlignment];
01043 [_imageAndTextView setImage:[_menuItem image]];
01044 [_imageAndTextView setText:[_menuItem title]];
01045 [_imageAndTextView setTextColor:[self textColor]];
01046 [_imageAndTextView setTextShadowColor:[self textShadowColor]];
01047 [_imageAndTextView setTextShadowOffset:CGSizeMake(0, 1)];
01048 [_imageAndTextView setFrameOrigin:CGPointMake(x, VERTICAL_MARGIN)];
01049 [_imageAndTextView sizeToFit];
01050
01051 var frame = [_imageAndTextView frame];
01052
01053
01054
01055
01056 frame.size.height += 2 * VERTICAL_MARGIN;
01057
01058 x += CGRectGetWidth(frame);
01059
01060
01061 if ([_menuItem hasSubmenu])
01062 {
01063 x += 3.0;
01064
01065 if (!_submenuView)
01066 {
01067 _submenuView = [[_CPMenuItemArrowView alloc] initWithFrame:CGRectMake(0.0, 0.0, 10.0, 10.0)];
01068
01069 [self addSubview:_submenuView];
01070 }
01071
01072 [_submenuView setHidden:NO];
01073 [_submenuView setColor:_belongsToMenuBar ? [self textColor] : nil];
01074 [_submenuView setFrameOrigin:CGPointMake(x, (CGRectGetHeight(frame) - 10.0) / 2.0)];
01075
01076 x += 10.0;
01077 }
01078 else
01079 [_submenuView setHidden:YES];
01080
01081 _minSize = CGSizeMake(x + (_belongsToMenuBar ? 0.0 : RIGHT_MARGIN) + 3.0, CGRectGetHeight(frame));
01082
01083 [self setFrameSize:_minSize];
01084 }
01085
01086 - (CGFloat)overlapOffsetWidth
01087 {
01088 return LEFT_MARGIN + ([[_menuItem menu] showsStateColumn] ? STATE_COLUMN_WIDTH : 0.0);
01089 }
01090
01091 - (void)setShowsStateColumn:(BOOL)shouldShowStateColumn
01092 {
01093 _showsStateColumn = shouldShowStateColumn;
01094 }
01095
01096 - (void)setBelongsToMenuBar:(BOOL)shouldBelongToMenuBar
01097 {
01098 _belongsToMenuBar = shouldBelongToMenuBar;
01099 }
01100
01101 - (void)highlight:(BOOL)shouldHighlight
01102 {
01103
01104
01105 if (_belongsToMenuBar)
01106 [_imageAndTextView setImage:shouldHighlight ? [_menuItem alternateImage] : [_menuItem image]];
01107
01108 else if ([_menuItem isEnabled])
01109 {
01110 if (shouldHighlight)
01111 {
01112 [self setBackgroundColor:_CPMenuItemSelectionColor];
01113
01114 [_imageAndTextView setTextColor:[CPColor whiteColor]];
01115 [_imageAndTextView setTextShadowColor:_CPMenuItemTextShadowColor];
01116 }
01117 else
01118 {
01119 [self setBackgroundColor:nil];
01120
01121 [_imageAndTextView setTextColor:[self textColor]];
01122 [_imageAndTextView setTextShadowColor:[self textShadowColor]];
01123 }
01124
01125 var state = [_menuItem state];
01126
01127 switch (state)
01128 {
01129 case CPOffState:
01130 case CPOnState:
01131 case CPMixedState: [_stateView setImage:shouldHighlight ? _CPMenuItemDefaultStateHighlightedImages[state] : _CPMenuItemDefaultStateImages[state]];
01132 break;
01133
01134 default: [_stateView setImage:nil];
01135 }
01136 }
01137 }
01138
01139 - (void)activate:(BOOL)shouldActivate
01140 {
01141 [_imageAndTextView setImage:[_menuItem image]];
01142
01143 if (shouldActivate)
01144 {
01145 [_imageAndTextView setTextColor:[self activateColor] || [CPColor whiteColor]];
01146 [_imageAndTextView setTextShadowColor:[self activateShadowColor] || [CPColor blackColor]];
01147 [_submenuView setColor:[self activateColor] || [CPColor whiteColor]];
01148 }
01149 else
01150 {
01151 [_imageAndTextView setTextColor:[self textColor]];
01152 [_imageAndTextView setTextShadowColor:[self textShadowColor]];
01153 [_submenuView setColor:[self textColor]];
01154 }
01155 }
01156
01157 - (BOOL)eventOnSubmenu:(CPEvent)anEvent
01158 {
01159 if (![_menuItem hasSubmenu])
01160 return NO;
01161
01162 return CGRectContainsPoint([_submenuView frame], [self convertPoint:[anEvent locationInWindow] fromView:nil]);
01163 }
01164
01165 - (BOOL)isHidden
01166 {
01167 return [_menuItem isHidden];
01168 }
01169
01170 - (CPMenuItem)menuItem
01171 {
01172 return _menuItem;
01173 }
01174
01175 - (void)setFont:(CPFont)aFont
01176 {
01177 if (_font == aFont)
01178 return;
01179
01180 _font = aFont;
01181
01182 [self setDirty];
01183 }
01184
01185 - (void)setTextColor:(CPColor)aColor
01186 {
01187 if (_textColor == aColor)
01188 return;
01189
01190 _textColor = aColor;
01191
01192 [_imageAndTextView setTextColor:[self textColor]];
01193 [_submenuView setColor:[self textColor]];
01194 }
01195
01196 - (CPColor)textColor
01197 {
01198 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];
01199 }
01200
01201 - (void)setTextShadowColor:(CPColor)aColor
01202 {
01203 if (_textShadowColor == aColor)
01204 return;
01205
01206 _textShadowColor = aColor;
01207
01208 [_imageAndTextView setTextShadowColor:[self textShadowColor]];
01209
01210 }
01211
01212 - (CPColor)textShadowColor
01213 {
01214 return [_menuItem isEnabled] ? (_textShadowColor ? _textShadowColor : [CPColor colorWithWhite:1.0 alpha:0.8]) : [CPColor colorWithWhite:0.8 alpha:0.8];
01215 }
01216
01217 - (void)setActivateColor:(CPColor)aColor
01218 {
01219 _activateColor = aColor;
01220 }
01221
01222 - (CPColor)activateColor
01223 {
01224 return _activateColor;
01225 }
01226
01227 - (void)setActivateShadowColor:(CPColor)aColor
01228 {
01229 _activateShadowColor = aColor;
01230 }
01231
01232 - (CPColor)activateShadowColor
01233 {
01234 return _activateShadowColor;
01235 }
01236
01237 @end
01238
01239 @implementation _CPMenuItemArrowView : CPView
01240 {
01241 CPColor _color;
01242 }
01243
01244 - (void)setColor:(CPColor)aColor
01245 {
01246 if (_color == aColor)
01247 return;
01248
01249 _color = aColor;
01250
01251 [self setNeedsDisplay:YES];
01252 }
01253
01254 - (void)drawRect:(CGRect)aRect
01255 {
01256 var context = [[CPGraphicsContext currentContext] graphicsPort];
01257
01258 CGContextBeginPath(context);
01259
01260 CGContextMoveToPoint(context, 1.0, 4.0);
01261 CGContextAddLineToPoint(context, 9.0, 4.0);
01262 CGContextAddLineToPoint(context, 5.0, 8.0);
01263 CGContextAddLineToPoint(context, 1.0, 4.0);
01264
01265 CGContextClosePath(context);
01266
01267 CGContextSetFillColor(context, _color);
01268 CGContextFillPath(context);
01269 }
01270
01271 @end