From 8c1f6f30142c0ebe80b6a2bef99b7a9782651df6 Mon Sep 17 00:00:00 2001 From: Francisco Tolmasky Date: Fri, 15 May 2009 21:40:11 -0700 Subject: [PATCH 1/6] CPButton cleanup from residual pre-theme code. Reviewed by me. --- AppKit/CPButton.j | 116 +++++++++++++--------------------------------- AppKit/CPView.j | 31 ++++++++++++- 2 files changed, 63 insertions(+), 84 deletions(-) diff --git a/AppKit/CPButton.j b/AppKit/CPButton.j index 9317a2992..e9ec683df 100644 --- a/AppKit/CPButton.j +++ b/AppKit/CPButton.j @@ -84,11 +84,6 @@ CPMomentaryLight = 7; var CPHUDBezelStyleTextColor = nil; -var _CPButtonClassName = nil, - _CPButtonBezelStyleSizes = {}, - _CPButtonBezelStyleIdentifiers = {}, - _CPButtonBezelStyleHighlightedIdentifier = @"Highlighted"; - /*! @class CPButton CPButton is a subclass of CPControl that @@ -97,8 +92,6 @@ var _CPButtonClassName = nil, */ @implementation CPButton : CPControl { - int _tag; - int _state; BOOL _allowsMixedState; CPString _title; @@ -107,10 +100,6 @@ var _CPButtonClassName = nil, CPImage _image; CPImage _alternateImage; - // Layout Views - CPView _bezelView; - _CPImageAndTextView _contentView; - // NS-style Display Properties CPBezelStyle _bezelStyle; BOOL _isBordered; @@ -179,21 +168,44 @@ var _CPButtonClassName = nil, _allowsMixedState = aFlag; } -/*! - Sets the button to its next state. -*/ +- (void)setObjectValue:(id)anObjectValue +{ + if (!anObjectValue || anObjectValue === @"") + anObjectValue = CPOffState; + + else if (![anObjectValue isKindOfClass:[CPNumber class]]) + anObjectValue = CPOnState; + + else if (aState > CPOnState) + anObjectValue = CPOnState + + else if (anObjectValue < CPOffState) + if ([self allowsMixedState]) + anObjectValue = CPMixedState; + + else + anObjectValue = CPOnState; + + [super setObjectValue:anObjectValue]; +} + - (int)nextState { - if (_state == CPOffState) - return CPOnState; - else - return (_state >= CPOnState && _allowsMixedState) ? CPMixedState : CPOffState; + if ([self allowsMixedState]) + { + var value = [self state]; + + return value - ((value === -1) ? -2 : 1); + } + + return 1 - [self state]; } - (void)setNextState { [self setState:[self nextState]]; } + /*! Sets the button's state to aState. @param aState Possible states are any of the CPButton globals: @@ -201,7 +213,7 @@ var _CPButtonClassName = nil, */ - (void)setState:(int)aState { - _state = aState; + [self setIntValue:aState]; } /*! @@ -209,7 +221,7 @@ var _CPButtonClassName = nil, */ - (int)state { - return _state; + return [self intValue]; } - (void)setTitle:(CPString)aTitle @@ -283,34 +295,6 @@ var _CPButtonClassName = nil, return _alternateImage; } -/*! - Highlights the receiver based on aFlag. - @param If YES the button will highlight, NO the button will unhighlight. -*/ -- (void)highlight:(BOOL)aFlag -{ - [super highlight:aFlag]; - - [self drawBezelWithHighlight:aFlag]; -} - -/*! - Sets button's tag. - @param aTag the button's new tag -*/ -- (void)setTag:(int)aTag -{ - _tag = aTag; -} - -/*! - Returns the button's tag. -*/ -- (int)tag -{ - return _tag; -} - - (BOOL)startTrackingAt:(CGPoint)aPoint { [self highlight:YES]; @@ -325,33 +309,6 @@ var _CPButtonClassName = nil, [super stopTracking:lastPoint at:aPoint mouseIsUp:mouseIsUp]; } -/* @ignore */ -- (void)drawBezelWithHighlight:(BOOL)shouldHighlight -{ return; - _bezelBorderNeedsUpdate = ![self window]; - - if (_bezelBorderNeedsUpdate) - return; - - [self setBackgroundColorWithName:shouldHighlight ? CPControlHighlightedBackgroundColor : CPControlNormalBackgroundColor]; -} - -- (CPView)createBezelView -{ - var view = [[CPView alloc] initWithFrame:_CGRectMakeZero()]; - - [view setHitTests:NO]; - - return view; -} - -- (CPView)createContentView -{ - var view = [[_CPImageAndTextView alloc] initWithFrame:_CGRectMakeZero()]; - - return view; -} - - (CGRect)contentRectForBounds:(CGRect)bounds { var contentInset = [self currentValueForThemeAttribute:@"content-inset"]; @@ -494,15 +451,8 @@ var CPButtonImageKey = @"CPButtonImageKey", CPButtonAlternateImageKey = @"CPButtonAlternateImageKey", CPButtonTitleKey = @"CPButtonTitleKey", CPButtonAlternateTitleKey = @"CPButtonAlternateTitleKey", - CPButtonContentInsetKey = @"CPButtonContentInsetKey", - CPButtonBezelInsetKey = @"CPButtonBezelInsetKey", - CPButtonBezelColorKey = @"CPButtonBezelColorKey", - CPButtonImageAndTitleViewKey = @"CPButtonImageAndTitleViewKey", - CPButtonImagePositionKey = @"CPButtonImagePositionKey", - CPButtonImageScalingKey = @"CPButtonImageScalingKey", CPButtonIsBorderedKey = @"CPButtonIsBorderedKey", - CPButtonBezelStyleKey = @"CPButtonBezelStyleKey", - CPButtonImageAndTitleViewKey = @"CPButtonImageAndTitleViewKey"; + CPButtonBezelStyleKey = @"CPButtonBezelStyleKey"; @implementation CPButton (CPCoding) diff --git a/AppKit/CPView.j b/AppKit/CPView.j index 6db16de7c..7bb4aa19c 100644 --- a/AppKit/CPView.j +++ b/AppKit/CPView.j @@ -552,11 +552,35 @@ var DOMElementPrototype = nil, return enclosingMenuItem;*/ } -- (int)tag +- (void)setTag:(CPInteger)aTag +{ + _tag = aTag; +} + +- (CPInteger)tag { return _tag; } +- (void)viewWithTag:(CPInteger)aTag +{ + if ([self tag] === aTag) + return self; + + var index = 0, + count = _subviews.length; + + for (; index < count; ++index) + { + var view = [_subviews[index] viewWithTag:aTag]; + + if (view) + return view; + } + + return nil; +} + /*! Returns whether the view is flipped. @return YES if the view is flipped. NO, otherwise. @@ -1930,6 +1954,11 @@ setBoundsOrigin: @implementation CPView (Theming) #pragma mark Theme States +- (unsigned)themeState +{ + return _themeState; +} + - (BOOL)hasThemeState:(CPThemeState)aState { return !!(_themeState & ((typeof aState === "string") ? CPThemeState(aState) : aState)); From 4588d1db0860682a7a4b8e097dac924f7d56bf17 Mon Sep 17 00:00:00 2001 From: Francisco Tolmasky Date: Fri, 15 May 2009 22:16:15 -0700 Subject: [PATCH 2/6] Further CPView/CPMenuItem cleanup. Reviewed by me. --- AppKit/CPMenuItem.j | 70 +++++++++++++++++++++++---------------------- AppKit/CPView.j | 18 ++++++++---- 2 files changed, 49 insertions(+), 39 deletions(-) diff --git a/AppKit/CPMenuItem.j b/AppKit/CPMenuItem.j index e0d163690..cf32d3241 100644 --- a/AppKit/CPMenuItem.j +++ b/AppKit/CPMenuItem.j @@ -113,11 +113,11 @@ { if ([_menu autoenablesItems]) return; - + _isEnabled = isEnabled; - + [_menuItemView setDirty]; - + [_menu itemChanged:self]; } @@ -686,7 +686,7 @@ CPControlKeyMask */ - (void)setView:(CPView)aView { - if (_view == aView) + if (_view === aView) return; _view = aView; @@ -754,19 +754,23 @@ CPControlKeyMask var CPMenuItemTitleKey = @"CPMenuItemTitleKey", CPMenuItemTargetKey = @"CPMenuItemTargetKey", CPMenuItemActionKey = @"CPMenuItemActionKey", - + CPMenuItemIsEnabledKey = @"CPMenuItemIsEnabledKey", CPMenuItemIsHiddenKey = @"CPMenuItemIsHiddenKey", - + CPMenuItemTagKey = @"CPMenuItemTagKey", - + CPMenuItemImageKey = @"CPMenuItemImageKey", CPMenuItemAlternateImageKey = @"CPMenuItemAlternateImageKey", - + CPMenuItemSubmenuKey = @"CPMenuItemSubmenuKey", CPMenuItemMenuKey = @"CPMenuItemMenuKey", - - CPMenuItemRepresentedObjectKey = @"CPMenuItemRepresentedObjectKey"; + + CPMenuItemRepresentedObjectKey = @"CPMenuItemRepresentedObjectKey", + CPMenuItemViewKey = @"CPMenuItemViewKey"; + +#define DEFAULT_VALUE(aKey, aDefaultValue) [aCoder containsValueForKey:(aKey)] ? [aCoder decodeObjectForKey:(aKey)] : (aDefaultValue) +#define ENCODE_IFNOT(aKey, aValue, aDefaultValue) if ((aValue) !== (aDefaultValue)) [aCoder encodeObject:(aValue) forKey:(aKey)]; @implementation CPMenuItem (CPCoding) /*! @@ -787,22 +791,21 @@ var CPMenuItemTitleKey = @"CPMenuItemTitleKey", _target = [aCoder decodeObjectForKey:CPMenuItemTargetKey]; _action = [aCoder decodeObjectForKey:CPMenuItemActionKey]; - _isEnabled = [aCoder decodeObjectForKey:CPMenuItemIsEnabledKey]; - _isHidden = [aCoder decodeObjectForKey:CPMenuItemIsHiddenKey]; - - _tag = [aCoder containsValueForKey:CPMenuItemTagKey] ? [aCoder decodeObjectForKey:CPMenuItemTagKey] : 0; + _isEnabled = DEFAULT_VALUE(CPMenuItemIsEnabledKey, YES); + _isHidden = DEFAULT_VALUE(CPMenuItemIsHiddenKey, NO); + _tag = DEFAULT_VALUE(CPMenuItemTagKey, 0); // int _state; - - _image = [aCoder decodeObjectForKey:CPMenuItemImageKey]; - _alternateImage = [aCoder decodeObjectForKey:CPMenuItemAlternateImageKey]; + + _image = DEFAULT_VALUE(CPMenuItemImageKey, nil); + _alternateImage = DEFAULT_VALUE(CPMenuItemAlternateImageKey, nil); // CPImage _onStateImage; // CPImage _offStateImage; // CPImage _mixedStateImage; - _submenu = [aCoder decodeObjectForKey:CPMenuItemSubmenuKey]; - _menu = [aCoder decodeObjectForKey:CPMenuItemMenuKey]; - + _submenu = DEFAULT_VALUE(CPMenuItemSubmenuKey, nil); + _menu = DEFAULT_VALUE(CPMenuItemMenuKey, nil); + // CPString _keyEquivalent; // unsigned _keyEquivalentModifierMask; @@ -810,12 +813,11 @@ var CPMenuItemTitleKey = @"CPMenuItemTitleKey", // BOOL _isAlternate; // int _indentationLevel; - + // CPString _toolTip; - _representedObject = [aCoder decodeObjectForKey:CPMenuItemRepresentedObjectKey]; -// id _representedObject; -// CPView _view; + _representedObject = DEFAULT_VALUE(CPMenuItemRepresentedObjectKey, nil); + _view = DEFAULT_VALUE(CPMenuItemViewKey, nil); } return self; @@ -832,19 +834,19 @@ var CPMenuItemTitleKey = @"CPMenuItemTitleKey", [aCoder encodeObject:_target forKey:CPMenuItemTargetKey]; [aCoder encodeObject:_action forKey:CPMenuItemActionKey]; - [aCoder encodeObject:_isEnabled forKey:CPMenuItemIsEnabledKey]; - [aCoder encodeObject:_isHidden forKey:CPMenuItemIsHiddenKey]; + ENCODE_IFNOT(CPMenuItemIsEnabledKey, _isEnabled, YES); + ENCODE_IFNOT(CPMenuItemIsHiddenKey, _isHidden, NO); - if (_tag !== 0) - [aCoder encodeObject:_tag forKey:CPMenuItemTagKey]; + ENCODE_IFNOT(CPMenuItemTagKey, _tag, 0); - [aCoder encodeObject:_image forKey:CPMenuItemImageKey]; - [aCoder encodeObject:_alternateImage forKey:CPMenuItemAlternateImageKey]; + ENCODE_IFNOT(CPMenuItemImageKey, _image, nil); + ENCODE_IFNOT(CPMenuItemAlternateImageKey, _alternateImage, nil); - [aCoder encodeObject:_submenu forKey:CPMenuItemSubmenuKey]; - [aCoder encodeObject:_menu forKey:CPMenuItemMenuKey]; - - [aCoder encodeObject:_representedObject forKey:CPMenuItemRepresentedObjectKey]; + ENCODE_IFNOT(CPMenuItemSubmenuKey, _submenu, nil); + ENCODE_IFNOT(CPMenuItemMenuKey, _menu, nil); + + ENCODE_IFNOT(CPMenuItemRepresentedObjectKey, _representedObject, nil); + ENCODE_IFNOT(CPMenuItemViewKey, _view, nil) } @end diff --git a/AppKit/CPView.j b/AppKit/CPView.j index 7bb4aa19c..b3230a4e6 100644 --- a/AppKit/CPView.j +++ b/AppKit/CPView.j @@ -2221,7 +2221,12 @@ var CPViewAutoresizingMaskKey = @"CPViewAutoresizingMask", _tag = [aCoder decodeIntForKey:CPViewTagKey]; _window = [aCoder decodeObjectForKey:CPViewWindowKey]; - _subviews = [aCoder decodeObjectForKey:CPViewSubviewsKey]; + + if ([aCoder containsValueForKey:CPViewSubviewsKey]) + _subviews = [aCoder decodeObjectForKey:CPViewSubviewsKey]; + else + _subviews = []; + _superview = [aCoder decodeObjectForKey:CPViewSuperviewKey]; _autoresizingMask = [aCoder decodeIntForKey:CPViewAutoresizingMaskKey] || 0; @@ -2252,7 +2257,7 @@ var CPViewAutoresizingMaskKey = @"CPViewAutoresizingMask", [self setBackgroundColor:[aCoder decodeObjectForKey:CPViewBackgroundColorKey]]; _theme = [CPTheme defaultTheme]; - _themeState = [aCoder decodeIntForKey:CPViewThemeStateKey]; + _themeState = CPThemeState([aCoder decodeIntForKey:CPViewThemeStateKey]); _themeAttributes = {}; var theClass = [self class], @@ -2286,14 +2291,17 @@ var CPViewAutoresizingMaskKey = @"CPViewAutoresizingMask", { [super encodeWithCoder:aCoder]; - if (_tag != -1) + if (_tag !== -1) [aCoder encodeInt:_tag forKey:CPViewTagKey]; [aCoder encodeRect:_frame forKey:CPViewFrameKey]; [aCoder encodeRect:_bounds forKey:CPViewBoundsKey]; [aCoder encodeConditionalObject:_window forKey:CPViewWindowKey]; - [aCoder encodeObject:_subviews forKey:CPViewSubviewsKey]; + + if (_subviews.length > 0) + [aCoder encodeObject:_subviews forKey:CPViewSubviewsKey]; + [aCoder encodeConditionalObject:_superview forKey:CPViewSuperviewKey]; [aCoder encodeInt:_autoresizingMask forKey:CPViewAutoresizingMaskKey]; @@ -2310,7 +2318,7 @@ var CPViewAutoresizingMaskKey = @"CPViewAutoresizingMask", [aCoder encodeConditionalObject:[self nextKeyView] forKey:CPViewNextKeyViewKey]; [aCoder encodeConditionalObject:[self previousKeyView] forKey:CPViewPreviousKeyViewKey]; - [aCoder encodeInt:_themeState forKey:CPViewThemeStateKey]; + [aCoder encodeInt:CPThemeStateName(_themeState) forKey:CPViewThemeStateKey]; for (var attributeName in _themeAttributes) if (_themeAttributes.hasOwnProperty(attributeName)) From 1b494389a6af1fc19c530323b819088f0f7d1a6f Mon Sep 17 00:00:00 2001 From: Francisco Tolmasky Date: Fri, 15 May 2009 22:33:39 -0700 Subject: [PATCH 3/6] Fixed crash when selecting "About New Application..." in nib app. About panel still not implemented, but at least it no longer crashes. Reviewed by me. --- AppKit/CPApplication.j | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/AppKit/CPApplication.j b/AppKit/CPApplication.j index 26b1089d8..c68941af1 100644 --- a/AppKit/CPApplication.j +++ b/AppKit/CPApplication.j @@ -474,6 +474,16 @@ CPRunContinuesResponse = -1002; _mainMenu = aMenu; } +- (void)orderFrontStandardAboutPanel:(id)aSender +{ + [self orderFrontStandardAboutPanelWithOptions:nil]; +} + +- (void)orderFrontStandardAboutPanelWithOptions:(CPDictionary)aDictionary +{ + // FIXME: Implement. +} + // Posting Actions /*! Tries to perform the action with an argument. Performs From 94f83a92b7d356552f8c7ba484f3a1928160481c Mon Sep 17 00:00:00 2001 From: Francisco Tolmasky Date: Sat, 16 May 2009 15:53:49 -0700 Subject: [PATCH 4/6] Added Radio and checkbox classes. Remaining works: - Fix artwork issue - nib2cib support Closes #77. Reviewed by me. --- AppKit/CPButton.j | 186 +++++++++++++++--- .../Resources/check-box-bezel-selected.png | Bin 0 -> 646 bytes .../Aristo/Resources/check-box-bezel.png | Bin 0 -> 2961 bytes .../Aristo/Resources/radio-bezel-selected.png | Bin 0 -> 855 bytes .../Themes/Aristo/Resources/radio-bezel.png | Bin 0 -> 666 bytes AppKit/Themes/Aristo/ThemeDescriptors.j | 37 ++++ 6 files changed, 200 insertions(+), 23 deletions(-) create mode 100644 AppKit/Themes/Aristo/Resources/check-box-bezel-selected.png create mode 100644 AppKit/Themes/Aristo/Resources/check-box-bezel.png create mode 100644 AppKit/Themes/Aristo/Resources/radio-bezel-selected.png create mode 100644 AppKit/Themes/Aristo/Resources/radio-bezel.png diff --git a/AppKit/CPButton.j b/AppKit/CPButton.j index e9ec683df..626ac1e3c 100644 --- a/AppKit/CPButton.j +++ b/AppKit/CPButton.j @@ -46,9 +46,9 @@ CPImageOverlaps = 6; /* @group CPButtonState */ -CPOnState = 1; -CPOffState = 0; -CPMixedState = -1; +CPOnState = 1; +CPOffState = 0; +CPMixedState = -1; /* @group CPBezelStyle */ @@ -70,19 +70,30 @@ CPHUDBezelStyle = -1; /* @group CPButtonType */ -CPMomentaryLightButton = 0; -CPPushOnPushOffButton = 1; -CPToggleButton = 2; -CPSwitchButton = 3; -CPRadioButton = 4; -CPMomentaryChangeButton = 5; -CPOnOffButton = 6; -CPMomentaryPushInButton = 7; -CPMomentaryPushButton = 0; -CPMomentaryLight = 7; +CPMomentaryLightButton = 0; +CPPushOnPushOffButton = 1; +CPToggleButton = 2; +CPSwitchButton = 3; // Deprecated, use CPCheckBox instead. +CPRadioButton = 4; // Deprecated, use CPRadio instead. +CPMomentaryChangeButton = 5; +CPOnOffButton = 6; +CPMomentaryPushInButton = 7; +CPMomentaryPushButton = 0; +CPMomentaryLight = 7; +CPNoButtonMask = 0; +CPContentsButtonMask = 1; +CPPushInButtonMask = 2; +CPGrayButtonMask = 4; +CPBackgroundButtonMask = 8; -var CPHUDBezelStyleTextColor = nil; +CPNoCellMask = CPNoButtonMask; +CPContentsCellMask = CPContentsButtonMask; +CPPushInCellMask = CPPushInButtonMask; +CPChangeGrayCellMask = CPGrayButtonMask; +CPChangeBackgroundCellMask = CPBackgroundButtonMask; + +CPButtonStateMixed = CPThemeState("mixed"); /*! @class CPButton @@ -100,22 +111,32 @@ var CPHUDBezelStyleTextColor = nil; CPImage _image; CPImage _alternateImage; + CPInteger _showsStateBy; + CPInteger _highlightsBy; + BOOL _imageDimsWhenDisabled; + // NS-style Display Properties CPBezelStyle _bezelStyle; - BOOL _isBordered; CPControlSize _controlSize; } + (id)standardButtonWithTitle:(CPString)aTitle { + var button = [[CPButton alloc] init]; + + [button setTitle:aTitle]; + + return button; } -+ (id)standardCheckboxWithTitle:(CPString)aTitle ++ (id)standardCheckBoxWithTitle:(CPString)aTitle { + return [CPCheckBox standardButtonWithTitle:aTitle]; } -- (id)standardRadioButtonWithTitle:(CPString)aTitle +- (id)standardRadioWithTitle:(CPString)aTitle { + return [CPRadio standardButtonWithTitle:aTitle]; } + (CPString)themeClass @@ -165,18 +186,26 @@ var CPHUDBezelStyleTextColor = nil; */ - (void)setAllowsMixedState:(BOOL)aFlag { + aFlag = !!aFlag; + + if (_allowsMixedState === aFlag) + return; + _allowsMixedState = aFlag; + + if (!_allowsMixedState) + [self unsetThemeState:CPButtonStateMixed]; } - (void)setObjectValue:(id)anObjectValue { - if (!anObjectValue || anObjectValue === @"") + if (!anObjectValue || anObjectValue === @"" || ([anObjectValue intValue] === 0)) anObjectValue = CPOffState; else if (![anObjectValue isKindOfClass:[CPNumber class]]) anObjectValue = CPOnState; - else if (aState > CPOnState) + else if (anObjectValue > CPOnState) anObjectValue = CPOnState else if (anObjectValue < CPOffState) @@ -187,9 +216,22 @@ var CPHUDBezelStyleTextColor = nil; anObjectValue = CPOnState; [super setObjectValue:anObjectValue]; + + switch ([self objectValue]) + { + case CPMixedState: [self unsetThemeState:CPThemeStateSelected]; + [self setThemeState:CPButtonStateMixed]; + break; + + case CPOnState: [self unsetThemeState:CPButtonStateMixed]; + [self setThemeState:CPThemeStateSelected]; + break; + + case CPOffState: [self unsetThemeState:CPThemeStateSelected | CPButtonStateMixed]; + } } -- (int)nextState +- (CPInteger)nextState { if ([self allowsMixedState]) { @@ -211,7 +253,7 @@ var CPHUDBezelStyleTextColor = nil; @param aState Possible states are any of the CPButton globals: CPOffState, CPOnState, CPMixedState */ -- (void)setState:(int)aState +- (void)setState:(CPInteger)aState { [self setIntValue:aState]; } @@ -219,7 +261,7 @@ var CPHUDBezelStyleTextColor = nil; /*! Returns the button's current state */ -- (int)state +- (CPInteger)state { return [self intValue]; } @@ -295,6 +337,98 @@ var CPHUDBezelStyleTextColor = nil; return _alternateImage; } +- (void)setShowsStateBy:(CPInteger)aMask +{ + if (_showsStateBy === aMask) + return; + + _showsStateBy = aMask; + + [self setNeedsDisplay:YES]; + [self setNeedsLayout]; +} + +- (CPInteger)showsStateBy +{ + return _showsStateBy; +} + +- (void)setHighlightsBy:(CPInteger)aMask +{ + if (_highlightsBy === aMask) + return; + + _highlightsBy = aMask; + + if ([self hasThemeState:CPThemeStateHighlighted]) + { + [self setNeedsDisplay:YES]; + [self setNeedsLayout]; + } +} + +- (void)setButtonType:(CPButtonType)aButtonType +{ + switch (buttonType) + { + case CPMomentaryLightButton: [self setHighlightsBy:CPChangeBackgroundCellMask]; + [self setShowsStateBy:CPNoCellMask]; + break; + + case CPMomentaryPushInButton: [self setHighlightsBy:CPPushInCellMask | CPChangeGrayCellMask]; + [self setShowsStateBy:CPNoCellMask]; + break; + + case CPMomentaryChangeButton: [self setHighlightsBy:CPContentsCellMask]; + [self setShowsStateBy:CPNoCellMask]; + break; + + case CPPushOnPushOffButton: [self setHighlightsBy:CPPushInCellMask | CPChangeGrayCellMask]; + [self setShowsStateBy:CPChangeBackgroundCellMask]; + break; + + case CPOnOffButton: [self setHighlightsBy:CPChangeBackgroundCellMask]; + [self setShowsStateBy:CPChangeBackgroundCellMask]; + break; + + case CPToggleButton: [self setHighlightsBy:CPPushInCellMask | NSContentsCellMask]; + [self setShowsStateBy:CPContentsCellMask]; + break; + + case CPSwitchButton: [CPException raise:CPInvalidArgumentException + reason:"The CPSwitchButton type is not supported in Cappuccino, use the CPCheckBox class instead."]; + + case CPRadioButton: [CPException raise:CPInvalidArgumentException + reason:"The CPRadioButton type is not supported in Cappuccino, use the CPRadio class instead."]; + + default: [CPException raise:CPInvalidArgumentException + reason:"Unknown button type."]; + } + + [self setImageDimsWhenDisabled:YES]; +} + +- (void)setImageDimsWhenDisabled:(BOOL)imageShouldDimWhenDisabled +{ + imageShouldDimWhenDisabled = !!imageShouldDimWhenDisabled; + + if (_imageDimsWhenDisabled === imageShouldDimWhenDisabled) + return; + + _imageDimsWhenDisabled = imageShouldDimWhenDisabled; + + if (_imageDimsWhenDisabled) + { + [self setNeedsDisplay:YES]; + [self setNeedsLayout]; + } +} + +- (BOOL)imageDimsWhenDisabled +{ + return _imageDimsWhenDisabled; +} + - (BOOL)startTrackingAt:(CGPoint)aPoint { [self highlight:YES]; @@ -305,8 +439,11 @@ var CPHUDBezelStyleTextColor = nil; - (void)stopTracking:(CGPoint)lastPoint at:(CGPoint)aPoint mouseIsUp:(BOOL)mouseIsUp { [self highlight:NO]; - + [super stopTracking:lastPoint at:aPoint mouseIsUp:mouseIsUp]; + + if (mouseIsUp && CGRectContainsPoint([self bounds], aPoint)) + [self setNextState]; } - (CGRect)contentRectForBounds:(CGRect)bounds @@ -499,3 +636,6 @@ var CPButtonImageKey = @"CPButtonImageKey", } @end + +@import "CPCheckBox.j" +@import "CPRadio.j" diff --git a/AppKit/Themes/Aristo/Resources/check-box-bezel-selected.png b/AppKit/Themes/Aristo/Resources/check-box-bezel-selected.png new file mode 100644 index 0000000000000000000000000000000000000000..7d4ee29835fbaf4f9f254fee1312c8c3df4e78dd GIT binary patch literal 646 zcmV;10(t$3P)f5L?*y0d~p5Cm<(4^Z5Q2x7sFNU94r7OG-Xs$y$n zqu8|MV>0i}_}+|ZEu=v&oW^ol-;9bUKX+h_o#jg{riwgfVue!{@_N z8K6aNOX8c%3p{)I8cJsb-Ju}jeTg0iC#wa`gjS_sl-0%J=TCTe?+#=&0NLxs@na{z zH&zMdJ_NR^YE{F;^{XJtP7qfsjvg9?tSA=8!6=3P2RE-=!fK(g{w?re{03Ha6Hf1T z^v7d}M59(;@Enw{rRxmKOF6uonZfwA%g{94>Sdl!;{C^2cy_4hP}^}}C}s5p1do$# zg`Yo`;q`}+FRbCw-COuFpT*?UCy?7a;dHq%Ix+%-XQH-|;1No>3P&Ik#lgczkeQmo zhuJK$b8~RF`M6IHhEqfE$g(w8E5Rd{vTi@vp1m=Y$`!nwo(6dE94#%_y{j8tp~(8o z2H8@!_peo7B8gI|jQOt%P&_X54-9TP-yky(5jo-E?@A8rN4Zo)ES|7@8kE+Js#rU( zX%)4ZkWGh!sbO28P6n9$V0n?SiQM7>D%@+$LL-PdG0%Co2{YJ*{P%AX$4P#v{~!L! g9LIf*bH4=`0P1mAgWl^vE&u=k07*qoM6N<$g3v%J4FCWD literal 0 HcmV?d00001 diff --git a/AppKit/Themes/Aristo/Resources/check-box-bezel.png b/AppKit/Themes/Aristo/Resources/check-box-bezel.png new file mode 100644 index 0000000000000000000000000000000000000000..d25d8c9d10fcafdf3e5c367ba16f7ebbf20acd88 GIT binary patch literal 2961 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 literal 0 HcmV?d00001 diff --git a/AppKit/Themes/Aristo/Resources/radio-bezel.png b/AppKit/Themes/Aristo/Resources/radio-bezel.png new file mode 100644 index 0000000000000000000000000000000000000000..d9b61ad3882c8c736c159edd2b1950f2e2f69808 GIT binary patch literal 666 zcmV;L0%iS)P)0pV}#)m z0umczqDEsVx1*7WS{e-v*+}>a)cyvH1q}sO>_*hiL@j7daFY!-1dvxC%PKE<&UijD zBnz80?3bKLZtnfgobSxJ!?BCS<@5Q7AP8ZNM)QE@`8&(y@>rJT@ALWmQzR0}(P;FA)9JitHk%nXS523J_H8yBbGck$sDDXQkPC2x|jH{W1cmrqrJ1 za=C*_rSc2sC%k%@qjjM1{tJU78QmG@HIVEo?6(oY&@{5ett7JxCk8(if z0aIY4Hvd%#F8&I(R0%2pr;bcSa}^u^lYasX04lySz!kbAv;Y7A07*qoM6N<$f}tre ASpWb4 literal 0 HcmV?d00001 diff --git a/AppKit/Themes/Aristo/ThemeDescriptors.j b/AppKit/Themes/Aristo/ThemeDescriptors.j index 213a59704..4e00f026b 100644 --- a/AppKit/Themes/Aristo/ThemeDescriptors.j +++ b/AppKit/Themes/Aristo/ThemeDescriptors.j @@ -7,6 +7,7 @@ */ @import +@import @implementation AristoThemeDescriptor : CPObject @@ -252,6 +253,42 @@ return button; } ++ (CPRadioButton)themedRadioButton +{ + var button = [[CPRadio alloc] initWithFrame:CGRectMake(0.0, 0.0, 120.0, 17.0)]; + + [button setTitle:@"Hello Friend!"]; + + var bezelColor = PatternColor([_CPCibCustomResource imageResourceWithName:"radio-bezel.png" size:CGSizeMake(17.0, 17.0)]), + bezelColorSelected = PatternColor([_CPCibCustomResource imageResourceWithName:"radio-bezel-selected.png" size:CGSizeMake(17.0, 17.0)]); + + [button setValue:CPLeftTextAlignment forThemeAttribute:@"alignment" inState:CPThemeStateBordered]; + [button setValue:[CPFont boldSystemFontOfSize:12.0] forThemeAttribute:@"font" inState:CPThemeStateBordered]; + [button setValue:CGInsetMake(0.0, 0.0, 0.0, 20.0) forThemeAttribute:@"content-inset" inState:CPThemeStateBordered]; + [button setValue:bezelColor forThemeAttribute:@"bezel-color" inState:CPThemeStateBordered]; + [button setValue:bezelColorSelected forThemeAttribute:@"bezel-color" inState:CPThemeStateBordered | CPThemeStateSelected]; + + return button; +} + ++ (CPRadioButton)themedCheckBoxButton +{ + var button = [[CPCheckBox alloc] initWithFrame:CGRectMake(0.0, 0.0, 120.0, 17.0)]; + + [button setTitle:@"Another option"]; + + var bezelColor = PatternColor([_CPCibCustomResource imageResourceWithName:"check-box-bezel.png" size:CGSizeMake(15.0, 15.0)]), + bezelColorSelected = PatternColor([_CPCibCustomResource imageResourceWithName:"check-box-bezel-selected.png" size:CGSizeMake(15.0, 16.0)]); + + [button setValue:CPLeftTextAlignment forThemeAttribute:@"alignment" inState:CPThemeStateBordered]; + [button setValue:[CPFont boldSystemFontOfSize:12.0] forThemeAttribute:@"font" inState:CPThemeStateBordered]; + [button setValue:CGInsetMake(0.0, 0.0, 0.0, 20.0) forThemeAttribute:@"content-inset" inState:CPThemeStateBordered]; + [button setValue:bezelColor forThemeAttribute:@"bezel-color" inState:CPThemeStateBordered]; + [button setValue:bezelColorSelected forThemeAttribute:@"bezel-color" inState:CPThemeStateBordered | CPThemeStateSelected]; + + return button; +} + + (CPPopUpButton)themedPopUpButton { var button = [[CPPopUpButton alloc] initWithFrame:CGRectMake(0.0, 0.0, 100.0, 24.0) pullsDown:NO], From 67cfe69f3895986123683a7a14f21ec3da58b6e3 Mon Sep 17 00:00:00 2001 From: Francisco Tolmasky Date: Sat, 16 May 2009 15:55:07 -0700 Subject: [PATCH 5/6] Forgot to include these files in the last commit. Reviewed by me. --- AppKit/CPCheckBox.j | 63 ++++++++++++++++++ AppKit/CPRadio.j | 159 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 222 insertions(+) create mode 100644 AppKit/CPCheckBox.j create mode 100644 AppKit/CPRadio.j diff --git a/AppKit/CPCheckBox.j b/AppKit/CPCheckBox.j new file mode 100644 index 000000000..487c51813 --- /dev/null +++ b/AppKit/CPCheckBox.j @@ -0,0 +1,63 @@ +/* + * CPCheckBox.j + * AppKit + * + * Created by Francisco Tolmasky. + * Copyright 2009, 280 North, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +@import "CPButton.j" + + +@implementation CPCheckBox : CPButton +{ +} + ++ (CPButton)standardButtonWithTitle:(CPString)aTitle +{ + var button = [[CPCheckBox alloc] init]; + + [button setTitle:aTitle]; + + return button; +} + ++ (CPString)themeClass +{ + return @"check-box"; +} + +- (id)initWithFrame:(CGRect)aFrame +{ + self = [super initWithFrame:aFrame]; + + if (self) + { + [self setHighlightsBy:CPContentsCellMask]; + [self setShowsStateBy:CPContentsCellMask]; + + // Defaults? + [self setImagePosition:CPImageLeft]; + [self setAlignment:CPLeftTextAlignment]; + + [self setBordered:YES]; + } + + return self; +} + +@end diff --git a/AppKit/CPRadio.j b/AppKit/CPRadio.j new file mode 100644 index 000000000..a19df54f0 --- /dev/null +++ b/AppKit/CPRadio.j @@ -0,0 +1,159 @@ +/* + * CPRadio.j + * AppKit + * + * Created by Francisco Tolmasky. + * Copyright 2009, 280 North, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +@import +@import + +@import "CPButton.j" + + +@implementation CPRadio : CPButton +{ + CPRadioGroup _radioGroup; +} + ++ (CPButton)standardButtonWithTitle:(CPString)aTitle +{ + var button = [[CPRadio alloc] init]; + + [button setTitle:aTitle]; + + return button; +} + ++ (CPString)themeClass +{ + return @"radio"; +} + +// Designated Initializer +- (id)initWithFrame:(CGRect)aFrame radioGroup:(CPRadioGroup)aRadioGroup +{ + self = [super initWithFrame:aFrame]; + + if (self) + { + _radioGroup = aRadioGroup || [CPRadioGroup new]; + + [self setHighlightsBy:CPContentsCellMask]; + [self setShowsStateBy:CPContentsCellMask]; + + // Defaults? + [self setImagePosition:CPImageLeft]; + [self setAlignment:CPLeftTextAlignment]; + + [self setBordered:YES]; + } + + return self; +} + +- (id)initWithFrame:(CGRect)aFrame +{ + return [self initWithFrame:aFrame radioGroup:nil]; +} + +- (CPInteger)nextState +{ + return CPOnState; +} + +- (void)setRadioGroup:(CPRadioGroup)aRadioGroup +{ + if (_radioGroup === aRadioGroup) + return; + + [_radioGroup _removeRadio:self]; + _radioGroup = aRadioGroup; + [_radioGroup _addRadio:self]; +} + +- (CPRadioGroup)radioGroup +{ + return _radioGroup; +} + +- (void)setObjectValue:(id)aValue +{ + [super setObjectValue:aValue]; + + if ([self state] === CPOnState) + [_radioGroup _setSelectedRadio:self]; +} + +@end + +@implementation CPRadioGroup : CPObject +{ + CPSet _radios; + CPRadio _selectedRadio; +} + +- (id)init +{ + self = [super init]; + + if (self) + { + _radios = [CPSet set]; + _selectedRadio = nil; + } + + return self; +} + +- (void)_addRadio:(CPRadio)aRadio +{ + [_radios addObject:aRadio]; + + if ([aRadio state] === CPOnState) + [self _setSelectedRadio:aRadio]; +} + +- (void)_removeRadio:(CPRadio)aRadio +{ + if (_selectedRadio === aRadio) + _selectedRadio = nil; + + [_radios removeObject:aRadio]; +} + +- (void)_setSelectedRadio:(CPRadio)aRadio +{ + if (_selectedRadio === aRadio) + return; + + [_selectedRadio setState:CPOffState]; + _selectedRadio = aRadio; +} + +- (CPRadio)selectedRadio +{ + return _selectedRadio; +} + +- (CPArray)radios +{ + return [_radios allObjects]; +} + +@end From 9f237c2d1a0adec2c5cfe823997cbd5f4660894f Mon Sep 17 00:00:00 2001 From: Francisco Tolmasky Date: Sat, 16 May 2009 16:21:48 -0700 Subject: [PATCH 6/6] Automatically update submodules when building. Reviewed by me. --- External/Rakefile | 11 ++++++++++- Rakefile | 24 ++++++++++++------------ 2 files changed, 22 insertions(+), 13 deletions(-) diff --git a/External/Rakefile b/External/Rakefile index 5b31563f4..d976681e0 100644 --- a/External/Rakefile +++ b/External/Rakefile @@ -29,6 +29,15 @@ file_d $ENVIRONMENT_JACK_PRODUCT => [$ENVIRONMENT_NARWHAL_PRODUCT] do cp_r('jack', $ENVIRONMENT_JACK_PRODUCT) end -task :build => [$ENVIRONMENT_NARWHAL_PRODUCT, $ENVIRONMENT_BROWSERJS_PRODUCT, $ENVIRONMENT_JACK_PRODUCT, $ENVIRONMENT_NARWHAL_EXECUTABLE] +task :update_submodules do + if executable_exists? "git" + system %{cd .. && git submodule update --init} + else + puts "Git not installed" + rake abort + end +end + +task :build => [:update_submodules, $ENVIRONMENT_NARWHAL_PRODUCT, $ENVIRONMENT_BROWSERJS_PRODUCT, $ENVIRONMENT_JACK_PRODUCT, $ENVIRONMENT_NARWHAL_EXECUTABLE] CLOBBER.include($ENVIRONMENT_NARWHAL_PRODUCT, $ENVIRONMENT_BROWSERJS_PRODUCT, $ENVIRONMENT_JACK_PRODUCT, $ENVIRONMENT_NARWHAL_EXECUTABLE) diff --git a/Rakefile b/Rakefile index 299f83a79..2ae19fb41 100644 --- a/Rakefile +++ b/Rakefile @@ -72,12 +72,12 @@ file_d $STARTER_DOWNLOAD_README => [$STARTER_README] do end task :install => [:downloads] do - if ENV['prefix'] - prefix = "--prefix #{ENV['prefix']}" - else - prefix = '' - end - system %{cd #{$TOOLS_DOWNLOAD} && sudo sh ./install-tools #{prefix} } + if ENV['prefix'] + prefix = "--prefix #{ENV['prefix']}" + else + prefix = '' + end + system %{cd #{$TOOLS_DOWNLOAD} && sudo sh ./install-tools #{prefix} } end task :test => [:build] do @@ -101,12 +101,12 @@ task :docs do end task :submodules do - if executable_exists? "git" - system %{git submodule init} - system %{git submodule update} - else - puts "Git not installed" - end + if executable_exists? "git" + system %{cd .. && git submodule update --init} + else + puts "Git not installed" + rake abort + end end =begin