From 862af9cbae6c1e89b474eda3c7728c27d5cc0f96 Mon Sep 17 00:00:00 2001 From: Francisco Tolmasky Date: Sun, 10 May 2009 13:04:02 -0700 Subject: [PATCH] First stab at fixing Themeing API. Reviewed by me. --- AppKit/CPApplication.j | 3 +- AppKit/CPButton.j | 91 ++- AppKit/CPButtonBar.j | 4 +- AppKit/CPColorPicker.j | 4 +- AppKit/CPControl.j | 44 +- AppKit/CPImageView.j | 4 +- AppKit/CPPopUpButton.j | 29 +- AppKit/CPScroller.j | 35 +- AppKit/CPSegmentedControl.j | 59 +- AppKit/CPSlider.j | 68 +- AppKit/CPTableColumn.j | 2 +- AppKit/CPTextField.j | 106 ++- AppKit/CPTheme.j | 639 +++++++++++------- AppKit/CPThemeBlend.j | 82 +++ AppKit/CPThemedAttribute.j | 267 -------- AppKit/CPView.j | 254 ++++--- .../Resources/popup-bezel-right-pullsdown.png | Bin 32722 -> 474 bytes .../scroller-horizontal-knob-left.png | Bin 23854 -> 3077 bytes .../Aristo/Resources/scroller-right-arrow.png | Bin 25008 -> 718 bytes AppKit/Themes/Aristo/ThemeDescriptors.j | 338 ++++----- AppKit/Tools/BlendKit/BKShowcaseController.j | 4 + AppKit/Tools/blend/main.j | 18 +- Foundation/CPDictionary.j | 17 +- Foundation/CPKeyedUnarchiver.j | 2 +- Tools/nib2cib/NSControl.j | 2 - Tools/nib2cib/NSTableColumn.j | 2 +- Tools/nib2cib/NSView.j | 5 +- 27 files changed, 1067 insertions(+), 1012 deletions(-) create mode 100644 AppKit/CPThemeBlend.j delete mode 100644 AppKit/CPThemedAttribute.j diff --git a/AppKit/CPApplication.j b/AppKit/CPApplication.j index d11e0d8f7..26b1089d8 100644 --- a/AppKit/CPApplication.j +++ b/AppKit/CPApplication.j @@ -27,6 +27,7 @@ @import "CPMenu.j" @import "CPResponder.j" @import "CPDocumentController.j" +@import "CPThemeBlend.j" var CPMainCibFile = @"CPMainCibFile", CPMainCibFileHumanFriendly = @"Main cib file base name"; @@ -807,7 +808,7 @@ var _CPAppBootstrapperActions = nil; + (BOOL)loadDefaultTheme { - var blend = [[CPBlend alloc] initWithContentsOfURL:[[CPBundle bundleForClass:[CPApplication class]] pathForResource:@"Aristo.blend"]]; + var blend = [[CPThemeBlend alloc] initWithContentsOfURL:[[CPBundle bundleForClass:[CPApplication class]] pathForResource:@"Aristo.blend"]]; [blend loadWithDelegate:self]; diff --git a/AppKit/CPButton.j b/AppKit/CPButton.j index 0c3d8a36b..9317a2992 100644 --- a/AppKit/CPButton.j +++ b/AppKit/CPButton.j @@ -107,12 +107,6 @@ var _CPButtonClassName = nil, CPImage _image; CPImage _alternateImage; - // Display Properties - CPThemedValue _bezelInset; - CPThemedValue _contentInset; - - CPThemedValue _bezelColor; - // Layout Views CPView _bezelView; _CPImageAndTextView _contentView; @@ -123,7 +117,24 @@ var _CPButtonClassName = nil, CPControlSize _controlSize; } -+ (id)themedAttributes ++ (id)standardButtonWithTitle:(CPString)aTitle +{ +} + ++ (id)standardCheckboxWithTitle:(CPString)aTitle +{ +} + +- (id)standardRadioButtonWithTitle:(CPString)aTitle +{ +} + ++ (CPString)themeClass +{ + return @"button"; +} + ++ (id)themeAttributes { return [CPDictionary dictionaryWithObjects:[_CGInsetMakeZero(), _CGInsetMakeZero(), nil, 24.0] forKeys:[@"bezel-inset", @"content-inset", @"bezel-color", @"default-height"]]; @@ -136,10 +147,10 @@ var _CPButtonClassName = nil, if (self) { // Should we instead override the defaults? - [self setValue:CPCenterTextAlignment forThemedAttributeName:@"alignment"]; - [self setValue:CPCenterVerticalTextAlignment forThemedAttributeName:@"vertical-alignment"]; - [self setValue:CPImageLeft forThemedAttributeName:@"image-position"]; - [self setValue:CPScaleNone forThemedAttributeName:@"image-scaling"]; + [self setValue:CPCenterTextAlignment forThemeAttribute:@"alignment"]; + [self setValue:CPCenterVerticalTextAlignment forThemeAttribute:@"vertical-alignment"]; + [self setValue:CPImageLeft forThemeAttribute:@"image-position"]; + [self setValue:CPScaleNone forThemeAttribute:@"image-scaling"]; _controlSize = CPRegularControlSize; @@ -343,7 +354,7 @@ var _CPButtonClassName = nil, - (CGRect)contentRectForBounds:(CGRect)bounds { - var contentInset = [self currentValueForThemedAttributeName:@"content-inset"]; + var contentInset = [self currentValueForThemeAttribute:@"content-inset"]; if (_CGInsetIsEmpty(contentInset)) return bounds; @@ -361,7 +372,7 @@ var _CPButtonClassName = nil, if (![self isBordered]) return _CGRectMakeZero(); - var bezelInset = [self currentValueForThemedAttributeName:@"bezel-inset"]; + var bezelInset = [self currentValueForThemeAttribute:@"bezel-inset"]; if (_CGInsetIsEmpty(bezelInset)) return bounds; @@ -380,8 +391,8 @@ var _CPButtonClassName = nil, - (void)sizeToFit { var size = [([self title] || " ") sizeWithFont:[self font]], - contentInset = [self currentValueForThemedAttributeName:@"content-inset"], - defaultHeight = [self currentValueForThemedAttributeName:@"default-height"]; + contentInset = [self currentValueForThemeAttribute:@"content-inset"], + defaultHeight = [self currentValueForThemeAttribute:@"default-height"]; [self setFrameSize:CGSizeMake(size.width + contentInset.left + contentInset.right, defaultHeight)]; } @@ -420,41 +431,35 @@ var _CPButtonClassName = nil, relativeToEphemeralSubviewNamed:@"content-view"]; if (bezelView) - [bezelView setBackgroundColor:[self currentValueForThemedAttributeName:@"bezel-color"]]; - + [bezelView setBackgroundColor:[self currentValueForThemeAttribute:@"bezel-color"]]; + var contentView = [self layoutEphemeralSubviewNamed:@"content-view" positioned:CPWindowAbove relativeToEphemeralSubviewNamed:@"bezel-view"]; if (contentView) { - [contentView setText:((_controlState & CPControlStateHighlighted) && _alternateTitle) ? _alternateTitle : _title]; - [contentView setImage:((_controlState & CPControlStateHighlighted) && _alternateImage) ? _alternateImage : _image]; - - [contentView setFont:[self currentValueForThemedAttributeName:@"font"]]; - [contentView setTextColor:[self currentValueForThemedAttributeName:@"text-color"]]; - [contentView setAlignment:[self currentValueForThemedAttributeName:@"alignment"]]; - [contentView setVerticalAlignment:[self currentValueForThemedAttributeName:@"vertical-alignment"]]; - [contentView setLineBreakMode:[self currentValueForThemedAttributeName:@"line-break-mode"]]; - [contentView setTextShadowColor:[self currentValueForThemedAttributeName:@"text-shadow-color"]]; - [contentView setTextShadowOffset:[self currentValueForThemedAttributeName:@"text-shadow-offset"]]; - [contentView setImagePosition:[self currentValueForThemedAttributeName:@"image-position"]]; - [contentView setImageScaling:[self currentValueForThemedAttributeName:@"image-scaling"]]; + [contentView setText:([self hasThemeState:CPThemeStateHighlighted] && _alternateTitle) ? _alternateTitle : _title]; + [contentView setImage:([self hasThemeState:CPThemeStateHighlighted] && _alternateImage) ? _alternateImage : _image]; + + [contentView setFont:[self currentValueForThemeAttribute:@"font"]]; + [contentView setTextColor:[self currentValueForThemeAttribute:@"text-color"]]; + [contentView setAlignment:[self currentValueForThemeAttribute:@"alignment"]]; + [contentView setVerticalAlignment:[self currentValueForThemeAttribute:@"vertical-alignment"]]; + [contentView setLineBreakMode:[self currentValueForThemeAttribute:@"line-break-mode"]]; + [contentView setTextShadowColor:[self currentValueForThemeAttribute:@"text-shadow-color"]]; + [contentView setTextShadowOffset:[self currentValueForThemeAttribute:@"text-shadow-offset"]]; + [contentView setImagePosition:[self currentValueForThemeAttribute:@"image-position"]]; + [contentView setImageScaling:[self currentValueForThemeAttribute:@"image-scaling"]]; } } - (void)setDefaultButton:(BOOL)shouldBeDefaultButton { - if ((!!(_controlState & CPControlStateDefault)) === shouldBeDefaultButton) - return; - if (shouldBeDefaultButton) - _controlState |= CPControlStateDefault; + [self setThemeState:CPThemeStateDefault]; else - _controlState &= ~CPControlStateDefault; - - [self setNeedsLayout]; - [self setNeedsDisplay:YES]; + [self unsetThemeState:CPThemeStateDefault]; } @end @@ -471,21 +476,15 @@ var _CPButtonClassName = nil, - (void)setBordered:(BOOL)shouldBeBordered { - if ((!!(_controlState & CPControlStateBordered)) === shouldBeBordered) - return; - if (shouldBeBordered) - _controlState |= CPControlStateBordered; + [self setThemeState:CPThemeStateBordered]; else - _controlState &= ~CPControlStateBordered; - - [self setNeedsLayout]; - [self setNeedsDisplay:YES]; + [self unsetThemeState:CPThemeStateBordered]; } - (BOOL)isBordered { - return !!(_controlState & CPControlStateBordered); + return [self hasThemeState:CPThemeStateBordered]; } @end diff --git a/AppKit/CPButtonBar.j b/AppKit/CPButtonBar.j index 75658bcca..5bf1b00f3 100644 --- a/AppKit/CPButtonBar.j +++ b/AppKit/CPButtonBar.j @@ -8,7 +8,7 @@ { } -+ (id)themedAttributes ++ (id)themeAttributes { return [CPDictionary dictionaryWithObjects:[nil] forKeys:[@"bezel-color"]]; @@ -43,7 +43,7 @@ relativeToEphemeralSubviewNamed:@""]; if (bezelView) - [bezelView setBackgroundColor:[self currentValueForThemedAttributeName:@"bezel-color"]]; + [bezelView setBackgroundColor:[self currentValueForThemeAttribute:@"bezel-color"]]; } - (void)addSubview:(CPView)aSubview diff --git a/AppKit/CPColorPicker.j b/AppKit/CPColorPicker.j index 8e52553f4..5fafd56e3 100644 --- a/AppKit/CPColorPicker.j +++ b/AppKit/CPColorPicker.j @@ -113,8 +113,8 @@ _brightnessSlider = [[CPSlider alloc] initWithFrame:CGRectMake(0, (aFrame.size.height - 34), aFrame.size.width, 15)]; - [_brightnessSlider setValue:15.0 forThemedAttributeName:@"track-width"]; - [_brightnessSlider setValue:[CPColor colorWithPatternImage:[[CPImage alloc] initWithContentsOfFile:[[CPBundle bundleForClass:[CPColorPicker class]] pathForResource:@"brightness_bar.png"]]] forThemedAttributeName:@"track-color"]; + [_brightnessSlider setValue:15.0 forThemeAttribute:@"track-width"]; + [_brightnessSlider setValue:[CPColor colorWithPatternImage:[[CPImage alloc] initWithContentsOfFile:[[CPBundle bundleForClass:[CPColorPicker class]] pathForResource:@"brightness_bar.png"]]] forThemeAttribute:@"track-color"]; [_brightnessSlider setMinValue:0.0]; [_brightnessSlider setMaxValue:100.0]; diff --git a/AppKit/CPControl.j b/AppKit/CPControl.j index 058071110..611919cb0 100644 --- a/AppKit/CPControl.j +++ b/AppKit/CPControl.j @@ -99,18 +99,16 @@ var CPControlBlackColor = [CPColor blackColor]; unsigned _trackingMouseDownFlags; CGPoint _previousTrackingLocation; - CPControlState _controlState; - JSObject _ephemeralSubviewsForNames; CPSet _ephereralSubviews; - CPString _toolTip; + CPString _toolTip; // FIXME: Who uses this? BOOL _isBezeled; } -+ (CPDictionary)themedAttributes ++ (CPDictionary)themeAttributes { return [CPDictionary dictionaryWithObjects:[ CPLeftTextAlignment, CPTopVerticalTextAlignment, CPLineBreakByClipping, [CPColor blackColor], [CPFont systemFontOfSize:12.0], nil, _CGSizeMakeZero(), CPImageLeft, CPScaleToFit] @@ -123,8 +121,6 @@ var CPControlBlackColor = [CPColor blackColor]; if (self) { - _controlState = CPControlStateNormal; - _sendActionOn = CPLeftMouseUpMask; _trackingMouseDownFlags = 0; } @@ -493,11 +489,11 @@ var CPControlBlackColor = [CPColor blackColor]; #define BRIDGE(UPPERCASE, LOWERCASE, ATTRIBUTENAME) \ - (void)set##UPPERCASE:(id)aValue\ {\ -[self setValue:aValue forThemedAttributeName:ATTRIBUTENAME];\ +[self setValue:aValue forThemeAttribute:ATTRIBUTENAME];\ }\ - (id)LOWERCASE\ {\ -return [self valueForThemedAttributeName:ATTRIBUTENAME];\ +return [self valueForThemeAttribute:ATTRIBUTENAME];\ } BRIDGE(Alignment, alignment, "alignment") @@ -510,28 +506,17 @@ BRIDGE(TextShadowOffset, textShadowOffset, "text-shadow-offset") BRIDGE(ImagePosition, imagePosition, "image-position") BRIDGE(ImageScaling, imageScaling, "image-scaling") -- (int)controlState -{ - return _controlState; -} - - (void)setEnabled:(BOOL)isEnabled { - if ((!(_controlState & CPControlStateDisabled)) === isEnabled) - return; - if (isEnabled) - _controlState &= ~CPControlStateDisabled; + [self unsetThemeState:CPThemeStateDisabled]; else - _controlState |= CPControlStateDisabled; - - [self setNeedsLayout]; - [self setNeedsDisplay:YES]; + [self setThemeState:CPThemeStateDisabled]; } - (BOOL)isEnabled { - return !(_controlState & CPControlStateDisabled); + return ![self hasThemeState:CPThemeStateDisabled]; } - (void)highlight:(BOOL)shouldHighlight @@ -541,21 +526,15 @@ BRIDGE(ImageScaling, imageScaling, "image-scaling") - (void)setHighlighted:(BOOL)isHighlighted { - if ((!!(_controlState & CPControlStateHighlighted)) === isHighlighted) - return; - if (isHighlighted) - _controlState |= CPControlStateHighlighted; + [self setThemeState:CPThemeStateHighlighted]; else - _controlState &= ~CPControlStateHighlighted; - - [self setNeedsLayout]; - [self setNeedsDisplay:YES]; + [self unsetThemeState:CPThemeStateHighlighted]; } - (BOOL)isHighlighted { - return !!(_controlState & CPControlStateHighlighted); + return [self hasThemeState:CPThemeStateHighlighted]; } - (CPView)createEphemeralSubviewNamed:(CPString)aViewName @@ -631,8 +610,6 @@ var __Deprecated__CPImageViewImageKey = @"CPImageViewImageKey"; if (self) { - _controlState = [aCoder decodeObjectForKey:CPControlControlStateKey]; - [self setObjectValue:[aCoder decodeObjectForKey:CPControlValueKey]]; [self setTarget:[aCoder decodeObjectForKey:CPControlTargetKey]]; @@ -668,7 +645,6 @@ var __Deprecated__CPImageViewImageKey = @"CPImageViewImageKey"; if (subviews) _subviews = subviews; - [aCoder encodeObject:_controlState forKey:CPControlControlStateKey]; [aCoder encodeObject:_value forKey:CPControlValueKey]; /*[aCoder encodeBool:_isEnabled forKey:CPControlIsEnabledKey]; diff --git a/AppKit/CPImageView.j b/AppKit/CPImageView.j index a80a30d82..aa9d12332 100644 --- a/AppKit/CPImageView.j +++ b/AppKit/CPImageView.j @@ -205,7 +205,7 @@ var LEFT_SHADOW_INSET = 3.0, [super setImageScaling:anImageScaling]; #if PLATFORM(DOM) - if ([self currentValueForThemedAttributeName:@"image-scaling"] === CPScaleToFit) + if ([self currentValueForThemeAttribute:@"image-scaling"] === CPScaleToFit) { CPDOMDisplayServerSetStyleLeftTop(_DOMImageElement, NULL, 0.0, 0.0); } @@ -254,7 +254,7 @@ var LEFT_SHADOW_INSET = 3.0, var bounds = [self bounds], image = [self image], - imageScaling = [self currentValueForThemedAttributeName:@"image-scaling"], + imageScaling = [self currentValueForThemeAttribute:@"image-scaling"], x = 0.0, y = 0.0, insetWidth = (_hasShadow ? HORIZONTAL_SHADOW_INSET : 0.0), diff --git a/AppKit/CPPopUpButton.j b/AppKit/CPPopUpButton.j index bc68954dc..7ac5901f5 100644 --- a/AppKit/CPPopUpButton.j +++ b/AppKit/CPPopUpButton.j @@ -30,7 +30,7 @@ var VISIBLE_MARGIN = 7.0; -CPPopUpButtonStatePullsDown = 1 << 12; +CPPopUpButtonStatePullsDown = CPThemeState("pulls-down"); /*! @class CPPopUpButton @@ -44,6 +44,11 @@ CPPopUpButtonStatePullsDown = 1 << 12; CPMenu _menu; } ++ (CPString)themeClass +{ + return "popup-button"; +} + /*! Initializes the pop-up button to the specified size. @param aFrame the size for the button @@ -59,9 +64,9 @@ CPPopUpButtonStatePullsDown = 1 << 12; _selectedIndex = CPNotFound; _preferredEdge = CPMaxYEdge; - [self setValue:CPImageLeft forThemedAttributeName:@"image-position"]; - [self setValue:CPLeftTextAlignment forThemedAttributeName:@"alignment"]; - [self setValue:CPLineBreakByTruncatingTail forThemedAttributeName:@"line-break-mode"]; + [self setValue:CPImageLeft forThemeAttribute:@"image-position"]; + [self setValue:CPLeftTextAlignment forThemeAttribute:@"alignment"]; + [self setValue:CPLineBreakByTruncatingTail forThemeAttribute:@"line-break-mode"]; [self setMenu:[[CPMenu alloc] initWithTitle:@""]]; @@ -85,21 +90,21 @@ CPPopUpButtonStatePullsDown = 1 << 12; */ - (void)setPullsDown:(BOOL)shouldPullDown { - if ((!!(_controlState & CPPopUpButtonStatePullsDown)) === shouldPullDown) - return; - if (shouldPullDown) - _controlState |= CPPopUpButtonStatePullsDown; + var changed = [self setThemeState:CPPopUpButtonStatePullsDown]; else - _controlState &= ~CPPopUpButtonStatePullsDown; + var changed = [self unsetThemeState:CPPopUpButtonStatePullsDown]; + + if (!changed) + return; var items = [_menu itemArray]; - + if ([items count] <= 0) return; [items[0] setHidden:[self pullsDown]]; - + [self synchronizeTitleAndSelectedItem]; } @@ -108,7 +113,7 @@ CPPopUpButtonStatePullsDown = 1 << 12; */ - (BOOL)pullsDown { - return _controlState & CPPopUpButtonStatePullsDown; + return [self hasThemeState:CPPopUpButtonStatePullsDown]; } // Inserting and Deleting Items diff --git a/AppKit/CPScroller.j b/AppKit/CPScroller.j index cecfec70d..f4721f7e5 100644 --- a/AppKit/CPScroller.j +++ b/AppKit/CPScroller.j @@ -71,7 +71,12 @@ NAMES_FOR_PARTS[CPScrollerKnob] = @"knob"; CGPoint _trackingStartPoint; } -+ (id)themedAttributes ++ (CPString)themeClass +{ + return "scroller"; +} + ++ (id)themeAttributes { return [CPDictionary dictionaryWithObjects:[ _CGInsetMakeZero(), nil, nil, nil, nil, @@ -181,14 +186,14 @@ NAMES_FOR_PARTS[CPScrollerKnob] = @"knob"; return _knobProportion; } -- (id)currentValueForThemedAttributeName:(CPString)anAttributeName +- (id)currentValueForThemeAttribute:(CPString)anAttributeName { - var controlState = _controlState; + var themeState = _themeState; if (NAMES_FOR_PARTS[_hitPart] + "-color" !== anAttributeName) - controlState &= ~CPControlStateHighlighted; + themeState &= ~CPThemeStateHighlighted; - return [self valueForThemedAttributeName:anAttributeName inControlState:controlState]; + return [self valueForThemeAttribute:anAttributeName inState:themeState]; } // Calculating Layout @@ -261,18 +266,18 @@ NAMES_FOR_PARTS[CPScrollerKnob] = @"knob"; // At this point we know we're going to need arrows. _usableParts = CPAllScrollerParts; - var trackOverlapInset = [self currentValueForThemedAttributeName:@"track-overlap-inset"], + var trackOverlapInset = [self currentValueForThemeAttribute:@"track-overlap-inset"], width = _CGRectGetWidth(bounds), height = _CGRectGetHeight(bounds); if ([self isVertical]) { - var decrementLineSize = [self currentValueForThemedAttributeName:"decrement-line-size"], - incrementLineSize = [self currentValueForThemedAttributeName:"increment-line-size"], + var decrementLineSize = [self currentValueForThemeAttribute:"decrement-line-size"], + incrementLineSize = [self currentValueForThemeAttribute:"increment-line-size"], effectiveDecrementLineHeight = decrementLineSize.height - trackOverlapInset.top, effectiveIncrementLineHeight = incrementLineSize.height - trackOverlapInset.bottom, slotHeight = height - effectiveDecrementLineHeight - effectiveIncrementLineHeight, - minimumKnobSize = [self currentValueForThemedAttributeName:"minimum-knob-size"], + minimumKnobSize = [self currentValueForThemeAttribute:"minimum-knob-size"], knobHeight = MAX(minimumKnobSize.height, (slotHeight * _knobProportion)), knobLocation = effectiveDecrementLineHeight + (slotHeight - knobHeight) * [self floatValue]; @@ -286,12 +291,12 @@ NAMES_FOR_PARTS[CPScrollerKnob] = @"knob"; else { - var decrementLineSize = [self currentValueForThemedAttributeName:"decrement-line-size"], - incrementLineSize = [self currentValueForThemedAttributeName:"increment-line-size"], + var decrementLineSize = [self currentValueForThemeAttribute:"decrement-line-size"], + incrementLineSize = [self currentValueForThemeAttribute:"increment-line-size"], effectiveDecrementLineWidth = decrementLineSize.width - trackOverlapInset.left, effectiveIncrementLineWidth = incrementLineSize.width - trackOverlapInset.right; slotWidth = width - effectiveDecrementLineWidth - effectiveIncrementLineWidth, - minimumKnobSize = [self currentValueForThemedAttributeName:"minimum-knob-size"], + minimumKnobSize = [self currentValueForThemeAttribute:"minimum-knob-size"], knobWidth = MAX(minimumKnobSize.width, (slotWidth * _knobProportion)), knobLocation = effectiveDecrementLineWidth + (slotWidth - knobWidth) * [self floatValue]; @@ -377,7 +382,7 @@ NAMES_FOR_PARTS[CPScrollerKnob] = @"knob"; view = [self layoutEphemeralSubviewNamed:part positioned:CPWindowAbove relativeToEphemeralSubviewNamed:PARTS_ARRANGEMENT[index - 1]]; if (view) - [view setBackgroundColor:[self currentValueForThemedAttributeName:NAMES_FOR_PARTS[part] + "-color"]]; + [view setBackgroundColor:[self currentValueForThemeAttribute:NAMES_FOR_PARTS[part] + "-color"]]; } } @@ -534,9 +539,9 @@ NAMES_FOR_PARTS[CPScrollerKnob] = @"knob"; _isVertical = width < height ? 1 : (width > height ? 0 : -1); if (_isVertical === 1) - _controlState |= CPControlStateVertical; + [self setThemeState:CPThemeStateVertical]; else if (_isVertical === 0) - _controlState &= ~CPControlStateVertical; + [self unsetThemeState:CPThemeStateVertical]; } - (void)setFrameSize:(CGSize)aSize diff --git a/AppKit/CPSegmentedControl.j b/AppKit/CPSegmentedControl.j index bfe81764f..74c4c870f 100644 --- a/AppKit/CPSegmentedControl.j +++ b/AppKit/CPSegmentedControl.j @@ -49,7 +49,7 @@ CPSegmentSwitchTrackingMomentary = 2; @implementation CPSegmentedControl : CPControl { CPArray _segments; - CPArray _controlStates; + CPArray _themeStates; int _selectedSegment; int _segmentStyle; @@ -59,7 +59,12 @@ CPSegmentSwitchTrackingMomentary = 2; BOOL _trackingHighlighted; } -+ (id)themedAttributes ++ (CPString)themeClass +{ + return "segmented-control"; +} + ++ (id)themeAttributes { return [CPDictionary dictionaryWithObjects:[_CGInsetMakeZero(), _CGInsetMakeZero(), nil, nil, nil, nil, 1.0, 24.0] forKeys:[@"bezel-inset", @"content-inset", @"left-segment-bezel-color", @"right-segment-bezel-color", @"center-segment-bezel-color", @"divider-bezel-color", @"divider-thickness", @"default-height"]]; @@ -68,7 +73,7 @@ CPSegmentSwitchTrackingMomentary = 2; - (id)initWithFrame:(CGRect)aRect { _segments = []; - _controlStates = []; + _themeStates = []; self = [super initWithFrame:aRect]; @@ -111,7 +116,7 @@ CPSegmentSwitchTrackingMomentary = 2; _segments[index] = [[_CPSegmentItem alloc] init]; _segments[index].frame.size.height = height; - _controlStates[index] = CPControlStateNormal; + _themeStates[index] = CPThemeStateNormal; } } else if (aCount < _segments.length) @@ -384,7 +389,7 @@ CPSegmentSwitchTrackingMomentary = 2; segment.selected = isSelected; - _controlStates[aSegment] = isSelected ? CPControlStateSelected : CPControlStateNormal; + _themeStates[aSegment] = isSelected ? CPThemeStateSelected : CPThemeStateNormal; // We need to do some cleanup if we only allow one selection. if (isSelected) @@ -396,7 +401,7 @@ CPSegmentSwitchTrackingMomentary = 2; if (_trackingMode == CPSegmentSwitchTrackingSelectOne && oldSelectedSegment != aSegment && oldSelectedSegment != -1) { _segments[oldSelectedSegment].selected = NO; - _controlStates[oldSelectedSegment] = CPControlStateNormal; + _themeStates[oldSelectedSegment] = CPThemeStateNormal; [self drawSegmentBezel:oldSelectedSegment highlight:NO]; } @@ -467,30 +472,30 @@ CPSegmentSwitchTrackingMomentary = 2; - (void)drawSegmentBezel:(int)aSegment highlight:(BOOL)shouldHighlight { if (shouldHighlight) - _controlStates[aSegment] |= CPControlStateHighlighted; + _themeStates[aSegment] |= CPThemeStateHighlighted; else - _controlStates[aSegment] &= ~CPControlStateHighlighted; + _themeStates[aSegment] &= ~CPThemeStateHighlighted; [self setNeedsLayout]; } - (float)_leftOffsetForSegment:(unsigned)segment { - var bezelInset = [self currentValueForThemedAttributeName:@"bezel-inset"]; + var bezelInset = [self currentValueForThemeAttribute:@"bezel-inset"]; if (segment == 0) return bezelInset.left; - var thickness = [self currentValueForThemedAttributeName:@"divider-thickness"]; + var thickness = [self currentValueForThemeAttribute:@"divider-thickness"]; return [self _leftOffsetForSegment:segment - 1] + [self widthForSegment:segment - 1] + thickness; } - (CGRect)rectForEphemeralSubviewNamed:(CPString)aName { - var height = [self currentValueForThemedAttributeName:@"default-height"], - contentInset = [self currentValueForThemedAttributeName:@"content-inset"], - bezelInset = [self currentValueForThemedAttributeName:@"bezel-inset"], + var height = [self currentValueForThemeAttribute:@"default-height"], + contentInset = [self currentValueForThemeAttribute:@"content-inset"], + bezelInset = [self currentValueForThemeAttribute:@"bezel-inset"], bounds = [self bounds]; if (aName === "left-segment-bezel") @@ -521,7 +526,7 @@ CPSegmentSwitchTrackingMomentary = 2; var segment = parseInt(aName.substring("divider-bezel-".length), 10), width = [self widthForSegment:segment], left = [self _leftOffsetForSegment:segment], - thickness = [self currentValueForThemedAttributeName:@"divider-thickness"]; + thickness = [self currentValueForThemeAttribute:@"divider-thickness"]; return CGRectMake(left + width, bezelInset.top, thickness, height); } @@ -536,8 +541,8 @@ CPSegmentSwitchTrackingMomentary = 2; - (void)layoutSubviews { - var leftCapColor = [self valueForThemedAttributeName:@"left-segment-bezel-color" - inControlState:_controlStates[0]]; + var leftCapColor = [self valueForThemeAttribute:@"left-segment-bezel-color" + inState:_themeStates[0]]; var leftBezelView = [self layoutEphemeralSubviewNamed:@"left-segment-bezel" positioned:CPWindowBelow @@ -545,8 +550,8 @@ CPSegmentSwitchTrackingMomentary = 2; [leftBezelView setBackgroundColor:leftCapColor]; - var rightCapColor = [self valueForThemedAttributeName:@"right-segment-bezel-color" - inControlState:_controlStates[_controlStates.length - 1]]; + var rightCapColor = [self valueForThemeAttribute:@"right-segment-bezel-color" + inState:_themeStates[_themeStates.length - 1]]; var rightBezelView = [self layoutEphemeralSubviewNamed:@"right-segment-bezel" positioned:CPWindowBelow @@ -554,10 +559,10 @@ CPSegmentSwitchTrackingMomentary = 2; [rightBezelView setBackgroundColor:rightCapColor]; - for (var i=0, count = _controlStates.length; i height ? 0 : -1); if (_isVertical === 1) - _controlState |= CPControlStateVertical; + [self setThemeState:CPThemeStateVertical]; else if (_isVertical === 0) - _controlState &= ~CPControlStateVertical; + [self unsetThemeState:CPThemeStateVertical]; } - (int)isVertical @@ -263,14 +265,14 @@ CPCircularSlider = 1; relativeToEphemeralSubviewNamed:@"knob-view"]; if (trackView) - [trackView setBackgroundColor:[self currentValueForThemedAttributeName:@"track-color"]]; + [trackView setBackgroundColor:[self currentValueForThemeAttribute:@"track-color"]]; var knobView = [self layoutEphemeralSubviewNamed:@"knob-view" positioned:CPWindowAbove relativeToEphemeralSubviewNamed:@"track-view"]; if (knobView) - [knobView setBackgroundColor:[self currentValueForThemedAttributeName:"knob-color"]]; + [knobView setBackgroundColor:[self currentValueForThemeAttribute:"knob-color"]]; } - (BOOL)tracksMouseOutsideOfFrame @@ -284,7 +286,7 @@ CPCircularSlider = 1; knobRect = [self knobRectForBounds:bounds], trackRect = [self trackRectForBounds:bounds]; - if (_controlState & CPControlStateCircular) + if ([self hasThemeState:CPThemeStateCircular]) { var knobWidth = _CGRectGetWidth(knobRect); @@ -295,7 +297,7 @@ CPCircularSlider = 1; dx = aPoint.x - _CGRectGetMidX(trackRect), dy = aPoint.y - _CGRectGetMidY(trackRect); - return MAX(0.0, MIN(1.0, 1.0 - (3*PI_2 - ATAN2(dy, dx))%PI2 / PI2)) * ([self maxValue] - minValue) + minValue; + return MAX(0.0, MIN(1.0, 1.0 - (3 * PI_2 - ATAN2(dy, dx)) % PI2 / PI2)) * ([self maxValue] - minValue) + minValue; } else if ([self isVertical]) { diff --git a/AppKit/CPTableColumn.j b/AppKit/CPTableColumn.j index 897f27145..3cdc65e8f 100644 --- a/AppKit/CPTableColumn.j +++ b/AppKit/CPTableColumn.j @@ -95,7 +95,7 @@ CPTableColumnUserResizingMask = 2; _maxWidth = 1000.0; var dataView = [[CPTextField alloc] initWithFrame:CPRectMakeZero()]; - [dataView setValue:[CPColor whiteColor] forThemedAttributeName:"text-color" inControlState:CPControlStateHighlighted]; + [dataView setValue:[CPColor whiteColor] forThemeAttribute:"text-color" inState:CPThemeStateHighlighted]; [self setDataView:dataView]; diff --git a/AppKit/CPTextField.j b/AppKit/CPTextField.j index 21dd731e5..d8b9ebe14 100644 --- a/AppKit/CPTextField.j +++ b/AppKit/CPTextField.j @@ -25,7 +25,7 @@ @import "CPStringDrawing.j" @import "CPCompatibility.j" -#include "CoreGraphics/CGGeometry.j" +#include "CoreGraphics/CGGeometry.h" #include "Platform/Platform.h" #include "Platform/DOM/CPDOMDisplayServer.h" @@ -109,8 +109,8 @@ var CPSecureTextFieldCharacter = "\u2022"; @end -CPTextFieldStateRounded = 1 << 12; -CPTextFieldStatePlaceholder = 1 << 13; +CPTextFieldStateRounded = CPThemeState("rounded"); +CPTextFieldStatePlaceholder = CPThemeState("placeholder"); /*! This control displays editable text in a Cappuccino application. @@ -137,10 +137,15 @@ CPTextFieldStatePlaceholder = 1 << 13; CPControlSize _controlSize; } -+ (id)themedAttributes ++ (CPString)themeClass { - return [CPDictionary dictionaryWithObjects:[_CGInsetMakeZero(), _CGInsetMake(2.0, 2.0, 2.0, 2.0), _CGInsetMake(2.0, 2.0, 2.0, 2.0), nil] - forKeys:[@"bezel-inset", @"content-inset", @"bezeled-content-inset", @"bezel-color"]]; + return "textfield"; +} + ++ (id)themeAttributes +{ + return [CPDictionary dictionaryWithObjects:[_CGInsetMakeZero(), _CGInsetMake(2.0, 2.0, 2.0, 2.0), nil] + forKeys:[@"bezel-inset", @"content-inset", @"bezel-color"]]; } /* @ignore */ @@ -308,7 +313,7 @@ CPTextFieldStatePlaceholder = 1 << 13; _sendActionOn = CPKeyUpMask | CPKeyDownMask; - [self setValue:CPLeftTextAlignment forThemedAttributeName:@"alignment"]; + [self setValue:CPLeftTextAlignment forThemeAttribute:@"alignment"]; } return self; @@ -373,16 +378,10 @@ CPTextFieldStatePlaceholder = 1 << 13; */ - (void)setBezeled:(BOOL)shouldBeBezeled { - if ((!!(_controlState & CPControlStateBezeled)) === shouldBeBezeled) - return; - if (shouldBeBezeled) - _controlState |= CPControlStateBezeled; + [self setThemeState:CPThemeStateBezeled]; else - _controlState &= ~CPControlStateBezeled; - - [self setNeedsLayout]; - [self setNeedsDisplay:YES]; + [self unsetThemeState:CPThemeStateBezeled]; } /*! @@ -390,7 +389,7 @@ CPTextFieldStatePlaceholder = 1 << 13; */ - (BOOL)isBezeled { - return !!(_controlState & CPControlStateBezeled); + return [self hasThemeState:CPThemeStateBezeled]; } /*! @@ -401,16 +400,10 @@ CPTextFieldStatePlaceholder = 1 << 13; { var shouldBeRounded = aBezelStyle === CPTextFieldRoundedBezel; - if ((!!(_controlState & CPTextFieldStateRounded)) === shouldBeRounded) - return; - if (shouldBeRounded) - _controlState |= CPTextFieldStateRounded; + [self setThemeState:CPTextFieldStateRounded]; else - _controlState &= ~CPTextFieldStateRounded; - - [self setNeedsLayout]; - [self setNeedsDisplay:YES]; + [self unsetThemeState:CPTextFieldStateRounded]; } /*! @@ -418,7 +411,7 @@ CPTextFieldStatePlaceholder = 1 << 13; */ - (CPTextFieldBezelStyle)bezelStyle { - if (_controlState & CPTextFieldStateRounded) + if ([self hasThemeState:CPTextFieldStateRounded]) return CPTextFieldRoundedBezel; return CPTextFieldSquareBezel; @@ -430,16 +423,10 @@ CPTextFieldStatePlaceholder = 1 << 13; */ - (void)setBordered:(BOOL)shouldBeBordered { - if ((!!(_controlState & CPControlStateBordered)) === shouldBeBordered) - return; - if (shouldBeBordered) - _controlState |= CPControlStateBordered; + [self setThemeState:CPThemeStateBordered]; else - _controlState &= ~CPControlStateBordered; - - [self setNeedsLayout]; - [self setNeedsDisplay:YES]; + [self unsetThemeState:CPThemeStateBordered]; } /*! @@ -447,7 +434,7 @@ CPTextFieldStatePlaceholder = 1 << 13; */ - (BOOL)isBordered { - return !!(_controlState & CPControlStateBordered); + return [self hasThemeState:CPThemeStateBordered]; } /*! @@ -508,7 +495,7 @@ CPTextFieldStatePlaceholder = 1 << 13; if (CPTextFieldInputOwner && [CPTextFieldInputOwner window] !== [self window]) [[CPTextFieldInputOwner window] makeFirstResponder:nil]; - _controlState |= CPControlStateEditing; + [self setThemeState:CPThemeStateEditing]; [self _updatePlaceholderState]; @@ -520,8 +507,8 @@ CPTextFieldStatePlaceholder = 1 << 13; element = [self _inputElement]; element.value = string; - element.style.color = [[self currentValueForThemedAttributeName:@"text-color"] cssString]; - element.style.font = [[self currentValueForThemedAttributeName:@"font"] cssString]; + element.style.color = [[self currentValueForThemeAttribute:@"text-color"] cssString]; + element.style.font = [[self currentValueForThemeAttribute:@"font"] cssString]; element.style.zIndex = 1000; var contentRect = [self contentRectForBounds:[self bounds]]; @@ -563,7 +550,7 @@ CPTextFieldStatePlaceholder = 1 << 13; /* @ignore */ - (BOOL)resignFirstResponder { - _controlState &= ~CPControlStateEditing; + [self unsetThemeState:CPThemeStateEditing]; [self _updatePlaceholderState]; @@ -635,19 +622,12 @@ CPTextFieldStatePlaceholder = 1 << 13; - (void)_updatePlaceholderState { - var string = [self stringValue], - controlState = _controlState; + var string = [self stringValue]; - if ((!string || [string length] === 0) && !(_controlState & CPControlStateEditing)) - _controlState |= CPTextFieldStatePlaceholder; + if ((!string || [string length] === 0) && ![self hasThemeState:CPThemeStateEditing]) + [self setThemeState:CPTextFieldStatePlaceholder]; else - _controlState &= ~CPTextFieldStatePlaceholder; - - if (_controlState !== controlState) - { - [self setNeedsLayout]; - [self setNeedsDisplay:YES]; - } + [self unsetThemeState:CPTextFieldStatePlaceholder]; } /*! @@ -662,7 +642,7 @@ CPTextFieldStatePlaceholder = 1 << 13; _placeholderString = aStringValue; // Only update things if we need to show the placeholder - if (_controlState & CPTextFieldStatePlaceholder) + if ([self hasThemeState:CPTextFieldStatePlaceholder]) { [self setNeedsLayout]; [self setNeedsDisplay:YES]; @@ -684,7 +664,7 @@ CPTextFieldStatePlaceholder = 1 << 13; - (void)sizeToFit { var size = [([self stringValue] || " ") sizeWithFont:[self font]], - contentInset = [self currentValueForThemedAttributeName:@"content-inset"]; + contentInset = [self currentValueForThemeAttribute:@"content-inset"]; [self setFrameSize:CGSizeMake(size.width + contentInset.left + contentInset.right, size.height + contentInset.top + contentInset.bottom)]; } @@ -749,7 +729,7 @@ CPTextFieldStatePlaceholder = 1 << 13; - (CGRect)contentRectForBounds:(CGRect)bounds { - var contentInset = [self currentValueForThemedAttributeName:@"content-inset"]; + var contentInset = [self currentValueForThemeAttribute:@"content-inset"]; if (!contentInset) return bounds; @@ -764,7 +744,7 @@ CPTextFieldStatePlaceholder = 1 << 13; - (CGRect)bezelRectForBounds:(CFRect)bounds { - var bezelInset = [self currentValueForThemedAttributeName:@"bezel-inset"]; + var bezelInset = [self currentValueForThemeAttribute:@"bezel-inset"]; if (_CGInsetIsEmpty(bezelInset)) return bounds; @@ -816,7 +796,7 @@ CPTextFieldStatePlaceholder = 1 << 13; relativeToEphemeralSubviewNamed:@"content-view"]; if (bezelView) - [bezelView setBackgroundColor:[self currentValueForThemedAttributeName:@"bezel-color"]]; + [bezelView setBackgroundColor:[self currentValueForThemeAttribute:@"bezel-color"]]; var contentView = [self layoutEphemeralSubviewNamed:@"content-view" positioned:CPWindowAbove @@ -824,11 +804,11 @@ CPTextFieldStatePlaceholder = 1 << 13; if (contentView) { - [contentView setHidden:_controlState & CPControlStateEditing]; + [contentView setHidden:[self hasThemeState:CPThemeStateEditing]]; var string = ""; - if (_controlState & CPTextFieldStatePlaceholder) + if ([self hasThemeState:CPTextFieldStatePlaceholder]) string = [self placeholderString]; else { @@ -840,13 +820,13 @@ CPTextFieldStatePlaceholder = 1 << 13; [contentView setText:string]; - [contentView setTextColor:[self currentValueForThemedAttributeName:@"text-color"]]; - [contentView setFont:[self currentValueForThemedAttributeName:@"font"]]; - [contentView setAlignment:[self currentValueForThemedAttributeName:@"alignment"]]; - [contentView setVerticalAlignment:[self currentValueForThemedAttributeName:@"vertical-alignment"]]; - [contentView setLineBreakMode:[self currentValueForThemedAttributeName:@"line-break-mode"]]; - [contentView setTextShadowColor:[self currentValueForThemedAttributeName:@"text-shadow-color"]]; - [contentView setTextShadowOffset:[self currentValueForThemedAttributeName:@"text-shadow-offset"]]; + [contentView setTextColor:[self currentValueForThemeAttribute:@"text-color"]]; + [contentView setFont:[self currentValueForThemeAttribute:@"font"]]; + [contentView setAlignment:[self currentValueForThemeAttribute:@"alignment"]]; + [contentView setVerticalAlignment:[self currentValueForThemeAttribute:@"vertical-alignment"]]; + [contentView setLineBreakMode:[self currentValueForThemeAttribute:@"line-break-mode"]]; + [contentView setTextShadowColor:[self currentValueForThemeAttribute:@"text-shadow-color"]]; + [contentView setTextShadowOffset:[self currentValueForThemeAttribute:@"text-shadow-offset"]]; } } diff --git a/AppKit/CPTheme.j b/AppKit/CPTheme.j index e4c39a17f..d1a6750ad 100644 --- a/AppKit/CPTheme.j +++ b/AppKit/CPTheme.j @@ -21,123 +21,16 @@ */ @import -@import -@import - -@import "CPThemedAttribute.j" +@import -@implementation CPBlend : CPObject -{ - CPBundle _bundle; - CPArray _themes @accessors(readonly); - id _loadDelegate; -} - -- (id)initWithContentsOfURL:(CPURL)aURL -{ - self = [super init]; - - if (self) - { - _bundle = [[CPBundle alloc] initWithPath:aURL + "/Info.plist"]; - } - - return self; -} - -- (void)loadWithDelegate:(id)aDelegate -{ - _loadDelegate = aDelegate; - - [_bundle loadWithDelegate:self]; -} - -- (void)bundleDidFinishLoading:(CPBundle)aBundle -{ - var paths = [_bundle objectForInfoDictionaryKey:@"CPBundleReplacedFiles"], - index = 0, - count = paths.length, - bundlePath = [_bundle bundlePath]; - - while (count--) - { - var path = paths[count]; - - if ([path pathExtension] === "keyedtheme") - { - var unarchiver = [[_CPThemeKeyedUnarchiver alloc] - initForReadingWithData:[CPData dataWithString:objj_files[bundlePath + '/' + path].contents] - bundle:_bundle]; - - [unarchiver decodeObjectForKey:@"root"]; - - [unarchiver finishDecoding]; - } - } - - [_loadDelegate blendDidFinishLoading:self]; -} - -@end - -var CPThemesByName = nil, - CPThemeDefaultTheme = nil, - - CPThemeViewClass = Nil, - CPThemeWindowClass = Nil; +var CPThemesByName = { }, + CPThemeDefaultTheme = nil; @implementation CPTheme : CPObject { - CPString _name; - Class _activeClass; - JSObject _classTable; -} - -+ (void)initialize -{ - if (self !== [CPTheme class]) - return; - - CPThemesByName = {}; - - CPThemeViewClass = [CPView class]; - CPThemeWindowClass = [CPWindow class]; - - var bundle = [CPBundle bundleForClass:self]; - defaultThemePath = [bundle objectForInfoDictionaryKey:@"Default Themes Path"], - defaultThemeName = [bundle objectForInfoDictionaryKey:@"Default Theme Name"]; - - if (!defaultThemePath) - return; - - defaultThemePath = [bundle pathForResource:defaultThemePath]; - - var file = objj_files[defaultThemePath + "/Info.plist"]; - - if (!file) - return; - - // Oh boy are we tricky. - var infoDictionary = CPPropertyListCreateFromData([CPData dataWithString:objj_files[defaultThemePath + "/Info.plist"].contents]); - - themes = [infoDictionary objectForKey:@"CPBundleReplacedFiles"], - - themeIndex = 0, - themeCount = [themes count]; - - for (; themeIndex < themeCount; ++themeIndex) - { - var unarchiver = [[_CPThemeKeyedUnarchiver alloc] - initForReadingWithData:[CPData dataWithString:objj_files[defaultThemePath + '/' + themes[themeIndex]].contents] - bundle:file.bundle]; - - [unarchiver decodeObjectForKey:@"root"]; - - [unarchiver finishDecoding]; - } - - [self setDefaultTheme:[CPTheme themeNamed:defaultThemeName]]; + CPString _name; + CPDictionary _attributes; } + (void)setDefaultTheme:(CPTheme)aTheme @@ -155,24 +48,18 @@ var CPThemesByName = nil, return CPThemesByName[aName]; } -+ (void)loadThemesAtURL:(CPURL)aURL delegate:(id)aLoadDelegate -{ - -} - - (id)initWithName:(CPString)aName { self = [super init]; - + if (self) { _name = aName; - _classTable = {}; - _classTable[[[self class] className]] = {}; - - CPThemesByName[_name] = aName; + _attributes = [CPDictionary dictionary]; + + CPThemesByName[_name] = self; } - + return self; } @@ -181,160 +68,124 @@ var CPThemesByName = nil, return _name; } -- (void)setActiveClass:(Class)aClass +- (_CPThemeAttribute)_attributeWithName:(CPString)aName forClass:(CPString)aClass { - _activeClass = aClass; -} + var attributes = [_attributes objectForKey:aClass]; -- (Class)activeClass -{ - return _activeClass; -} + if (!attributes) + return nil; -- (id)valueForAttributeName:(CPString)anAttributeName inClass:(CPClass)aClass -{ - if (!aClass) - return nil; - - var className = [aClass className], - table = _classTable[className]; - - if (!table) - return nil; - - var value = table[anAttributeName]; - - if (!value) - return nil; - - return value; + return [attributes objectForKey:aName]; } - (void)takeThemeFromObject:(id)anObject { - var attributes = [anObject _themedAttributes], + var attributes = [anObject _themeAttributeDictionary], attributeName = nil, attributeNames = [attributes keyEnumerator], - objectClass = [anObject class]; - + objectThemeClass = [[anObject class] themeClass]; + while (attributeName = [attributeNames nextObject]) - [self addValue:[attributes objectForKey:attributeName] forAttributeName:attributeName inClass:objectClass]; + [self _recordAttribute:[attributes objectForKey:attributeName] forClass:objectThemeClass]; } -- (void)setDefaultValue:(id)aValue forAttributeName:(CPString)anAttributeName +- (void)_recordAttribute:(_CPThemeAttribute)anAttribute forClass:(CPString)aClass { - [self addValue:aValue forAttributeName:anAttributeName inClass:[self class]]; -} + var attributes = [_attributes objectForKey:aClass]; -- (void)addValue:(id)aValue forAttributeName:(CPString)anAttributeName inClass:(Class)aClass -{ - if (!aValue) - return; - - var className = [aClass className], - table = _classTable[className]; - - if (!table) + if (!attributes) { - var classNames = []; - - while (!table && (aClass !== CPThemeViewClass) && (aClass !== CPThemeWindowClass)) - { - classNames.push(className); - - aClass = [aClass superclass]; - className = [aClass className]; - table = _classTable[className]; - } - - if (!table) - table = _classTable[[[self class] className]]; - - var count = [classNames count]; - - while (count--) - { - className = classNames[count]; - - _classTable[className] = {}; - _classTable[className].prototype = table; - - table = _classTable[className]; - } + attributes = [CPDictionary dictionary]; + + [_attributes setObject:attributes forKey:aClass]; } - var existingAttribute = table[anAttributeName]; + var name = [anAttribute name], + existingAttribute = [attributes objectForKey:name]; if (existingAttribute) - table[anAttributeName] = [existingAttribute themedAttributeMergedWithThemedAttribute:aValue]; + [attributes setObject:[existingAttribute attributeMergedWithAttribute:anAttribute] forKey:name]; else - table[anAttributeName] = aValue; + [attributes setObject:anAttribute forKey:name]; } @end -var CPThemeNameKey = @"CPThemeNameKey", - CPThemeClassNamesArrayKey = @"CPThemeClassNamesArrayKey"; +var CPThemeNameKey = @"CPThemeNameKey", + CPThemeAttributesKey = @"CPThemeAttributesKey"; @implementation CPTheme (CPCoding) - (id)initWithCoder:(CPCoder)aCoder { self = [super init]; - - _name = [aCoder decodeObjectForKey:CPThemeNameKey]; - _classTable = {}; - - CPThemesByName[_name] = self; - + if (self) { - var classNamesArray = [aCoder decodeObjectForKey:CPThemeClassNamesArrayKey], - count = classNamesArray.length; + _name = [aCoder decodeObjectForKey:CPThemeNameKey]; + /* + var themeClasses = [aCoder decodeObjectForKey:CPThemeClassesKey], + count = themeClasses.length; + while (count--) { - var className = classNamesArray[count], - theClass = objj_getClass(className), - values = [aCoder decodeObjectForKey:className], - keys = [values allKeys], - keyCount = keys.length; - - while (keyCount--) + var themeClass = themeClasses[count], + attributes = [CPDictionary dictionary], + encodedAttributeNames = [aCoder decodeObjectForKey:@"$c" + themeClass], + encodedCount = encodedAttributeNames.length; + + while (encodedCount--) { - var key = keys[keyCount]; + var attributeName = encodedAttributeNames[encodedCount]; - [self addValue:[values objectForKey:key] forAttributeName:key inClass:theClass]; + [attributes setObject:CPThemeAttributeDecode(aCoder, attributeName, nil, nil, nil) forKey:attributeName]; } + + [_attributes setObject:attributes forKey:themeClass]; } + + */ + + _attributes = [aCoder decodeObjectForKey:CPThemeAttributesKey]; + + CPThemesByName[_name] = self; } - + return self; } - (void)encodeWithCoder:(CPCoder)aCoder { - var classNamesArray = []; + [aCoder encodeObject:_name forKey:CPThemeNameKey]; + /* - for (var className in _classTable) + var themeClasses = [], + classNames = [_attributes keyEnumerator], + className = nil; + + while (className = [classNames nextObject]) { - if (_classTable.hasOwnProperty(className)) + var attributeNames = [], + attributes = [_attributes objectForKey:className], + attribute = nil; + + while (attribute = [attributes nextObject]) + if (CPThemeAttributeEncode(aCoder, attribute)) + attributeNames.push([attribute name]); + + if (attributeNames.length > 0) { - var values = _classTable[className], - valuesDictionary = [CPDictionary dictionary]; + [aCoder encodeObject:attributeNames forKey:"$c" + themeClass]; - for (var key in values) - if (key !== "prototype" && values.hasOwnProperty(key)) - [valuesDictionary setObject:values[key] forKey:key]; - - [aCoder encodeObject:valuesDictionary forKey:className]; - - classNamesArray.push(className); + themeClasses.push(themeClass); } } - [aCoder encodeObject:_name forKey:CPThemeNameKey]; - [aCoder encodeObject:classNamesArray forKey:CPThemeClassNamesArrayKey]; + [aCoder encodeObject:themeClasses forKey:CPThemeClassesKey]; + */ + + [aCoder encodeObject:_attributes forKey:CPThemeAttributesKey]; } @end @@ -347,10 +198,10 @@ var CPThemeNameKey = @"CPThemeNameKey", - (id)initForReadingWithData:(CPData)data bundle:(CPBundle)aBundle { self = [super initForReadingWithData:data]; - + if (self) _bundle = aBundle; - + return self; } @@ -365,3 +216,337 @@ var CPThemeNameKey = @"CPThemeNameKey", } @end + +var CPThemeStates = {}, + CPThemeStateNames = {}, + CPThemeStateCount = 0; + +function CPThemeState(aStateName) +{ + var state = CPThemeStates[aStateName]; + + if (state === undefined) + { + if (aStateName.indexOf('+') === -1) + state = 1 << CPThemeStateCount++; + else + { + var state = 0, + states = aStateName.split('+'), + count = states.length; + + while (count--) + { + var stateName = states[count], + individualState = CPThemeStates[stateName]; + + if (individualState === undefined) + { + individualState = 1 << CPThemeStateCount++; + CPThemeStates[stateName] = individualState; + CPThemeStateNames[individualState] = stateName; + } + + state |= individualState; + } + } + + CPThemeStates[aStateName] = state; + CPThemeStateNames[state] = aStateName; + } + + return state; +} + +function CPThemeStateName(aState) +{ + var name = CPThemeStateNames[aState]; + + if (name !== undefined) + return name; + + if (!(aState & (aState - 1))) + return ""; + + var state = 1, + name = ""; + + for (; state < aState; state <<= 1) + if (aState & state) + name += (name.length === 0 ? '' : '+') + CPThemeStateNames[state]; + + CPThemeStateNames[aState] = name; + + return name; +} + +CPThemeStateNames[0] = "normal"; +CPThemeStateNormal = CPThemeStates["normal"] = 0; +CPThemeStateDisabled = CPThemeState("disabled"); +CPThemeStateHighlighted = CPThemeState("highlighted"); +CPThemeStateSelected = CPThemeState("selected"); +CPThemeStateBezeled = CPThemeState("bezeled"); +CPThemeStateBordered = CPThemeState("bordered"); +CPThemeStateEditable = CPThemeState("editable"); +CPThemeStateEditing = CPThemeState("editing"); +CPThemeStateVertical = CPThemeState("vertical"); +CPThemeStateDefault = CPThemeState("default"); +CPThemeStateCircular = CPThemeState("circular"); + +@implementation _CPThemeAttribute : CPObject +{ + CPString _name; + id _defaultValue; + CPDictionary _values; + + JSObject _cache; + CPThemeAttribute _parentAttribute; +} + +- (id)initWithName:(CPString)aName defaultValue:(id)aDefaultValue +{ + self = [super init]; + + if (self) + { + _cache = { }; + _name = aName; + _defaultValue = aDefaultValue; + _values = [CPDictionary dictionary]; + } + + return self; +} + +- (CPString)name +{ + return _name; +} + +- (id)defaultValue +{ + return _defaultValue; +} + +- (void)setValue:(id)aValue +{ + _cache = {}; + + if (aValue === undefined || aValue === nil) + _values = [CPDictionary dictionary]; + else + _values = [CPDictionary dictionaryWithObject:aValue forKey:String(CPThemeStateNormal)]; +} + +- (void)setValue:(id)aValue forState:(CPThemeState)aState +{ + _cache = { }; + + if ((aValue === undefined) || (aValue === nil)) + [_values removeObjectForKey:String(aState)]; + else + [_values setObject:aValue forKey:String(aState)]; +} + +- (id)value +{ + return [self valueForState:CPThemeStateNormal]; +} + +- (id)valueForState:(CPThemeState)aState +{ + var value = _cache[aState]; + + // This can be nil. + if (value !== undefined) + return value; + + value = [_values objectForKey:String(aState)]; + + // If we don't have a value, and we have a non-normal state... + if ((value === undefined || value === nil) && aState !== CPThemeStateNormal) + { + // If this is a composite state (not a power of 2), find the closest partial subset match. + if (aState & (aState - 1)) + { + var highestOneCount = 0, + states = [_values allKeys], + count = states.length; + + while (count--) + { + // states[count] is a string! + var state = Number(states[count]); + + // A & B = A iff A < B + if ((state & aState) === state) + { + var oneCount = cachedNumberOfOnes[state]; + + if (oneCount === undefined) + oneCount = numberOfOnes(state); + + if (oneCount > highestOneCount) + { + highestOneCount = oneCount; + value = [_values objectForKey:String(state)]; + } + } + } + } + + // Still don't have a value? OK, let's use the normal value. + if (value === undefined || value === nil) + value = [_values objectForKey:String(CPThemeStateNormal)]; + } + + if (value === undefined || value === nil) + value = [_parentAttribute valueForState:aState]; + + if (value === undefined || value === nil) + value = _defaultValue; + + _cache[aState] = value; + + return value; +} + +- (void)setParentAttribute:(CPThemeAttribute)anAttribute +{ + if (_parentAttribute === anAttribute) + return; + + _cache = { }; + _parentAttribute = anAttribute; +} + +- (CPThemeAttribute)attributeMergedWithAttribute:(_CPThemeAttribute)anAttribute +{ + var mergedAttribute = [[_CPThemeAttribute alloc] initWithName:_name defaultValue:_defaultValue]; + + mergedAttribute._values = [_values copy]; + [mergedAttribute._values addEntriesFromDictionary:anAttribute._values]; + + return mergedAttribute; +} + +@end + +@implementation _CPThemeAttribute (CPCoding) + +- (id)initWithCoder:(CPCoder)aCoder +{ + self = [super init]; + + if (self) + { + _cache = {}; + + _name = [aCoder decodeObjectForKey:@"name"]; + _values = [CPDictionary dictionary]; + + var encodedValues = [aCoder decodeObjectForKey:@"values"], + keys = [encodedValues allKeys], + count = keys.length; + + while (count--) + { + var key = keys[count]; + + [_values setObject:[encodedValues objectForKey:key] forKey:CPThemeState(key)]; + } + } + + return self; +} + +- (void)encodeWithCoder:(CPCoder)aCoder +{ + var encodedValues = [CPDictionary dictionary], + keys = [_values allKeys], + count = keys.length; + + while (count--) + { + var key = keys[count]; + + [encodedValues setObject:[_values objectForKey:key] forKey:CPThemeStateName(Number(key))]; + } + + [aCoder encodeObject:_name forKey:@"name"]; + [aCoder encodeObject:encodedValues forKey:@"values"]; +} + +@end + +var cachedNumberOfOnes = [ 0 /*000000*/, 1 /*000001*/, 1 /*000010*/, 2 /*000011*/, 1 /*000100*/, 2 /*000101*/, 2 /*000110*/, + 3 /*000111*/, 1 /*001000*/, 2 /*001001*/, 2 /*001010*/, 3 /*001011*/, 2 /*001100*/, 3 /*001101*/, + 3 /*001110*/, 4 /*001111*/, 1 /*010000*/, 2 /*010001*/, 2 /*010010*/, 3 /*010011*/, 2 /*010100*/, + 3 /*010101*/, 3 /*010110*/, 4 /*010111*/, 2 /*011000*/, 3 /*011001*/, 3 /*011010*/, 4 /*011011*/, + 3 /*011100*/, 4 /*011101*/, 4 /*011110*/, 5 /*011111*/, 1 /*100000*/, 2 /*100001*/, 2 /*100010*/, + 3 /*100011*/, 2 /*100100*/, 3 /*100101*/, 3 /*100110*/, 4 /*100111*/, 2 /*101000*/, 3 /*101001*/, + 3 /*101010*/, 4 /*101011*/, 3 /*101100*/, 4 /*101101*/, 4 /*101110*/, 5 /*101111*/, 2 /*110000*/, + 3 /*110001*/, 3 /*110010*/, 4 /*110011*/, 3 /*110100*/, 4 /*110101*/, 4 /*110110*/, 5 /*110111*/, + 3 /*111000*/, 4 /*111001*/, 4 /*111010*/, 5 /*111011*/, 4 /*111100*/, 5 /*111101*/, 5 /*111110*/, + 6 /*111111*/ ]; + +var numberOfOnes = function(aNumber) +{ + var count = 0, + slot = aNumber; + + while (aNumber) + { + ++count; + aNumber &= (aNumber - 1); + } + + cachedNumberOfOnes[slot] = count; + + return count; +} + +numberOfOnes.displayName = "numberOfOnes"; + +function CPThemeAttributeEncode(aCoder, aThemeAttribute) +{ + var values = aThemeAttribute._values, + count = [values count]; + + if (count === 1) + { + var key = [values allKeys][0]; + + if (Number(key) === 0) + return [aCoder encodeObject:[values objectForKey:key] forKey:"$a" + [aThemeAttribute name]]; + } + + if (count >= 1) + [aCoder encodeObject:aThemeAttribute forKey:"$a" + [aThemeAttribute name]]; +} + +function CPThemeAttributeDecode(aCoder, anAttributeName, aDefaultValue, aTheme, aClass) +{ + var key = "$a" + anAttributeName; + + if (![aCoder containsValueForKey:key]) + var attribute = [[_CPThemeAttribute alloc] initWithName:anAttributeName defaultValue:aDefaultValue]; + + else + { + var attribute = [aCoder decodeObjectForKey:key]; + + if (!attribute.isa || ![attribute isKindOfClass:[_CPThemeAttribute class]]) + { + var themeAttribute = [[_CPThemeAttribute alloc] initWithName:anAttributeName defaultValue:aDefaultValue]; + + [themeAttribute setValue:attribute]; + + attribute = themeAttribute; + } + } + + [attribute setParentAttribute:[aTheme _attributeWithName:anAttributeName forClass:aClass]]; + + return attribute; +} diff --git a/AppKit/CPThemeBlend.j b/AppKit/CPThemeBlend.j new file mode 100644 index 000000000..b6f981e46 --- /dev/null +++ b/AppKit/CPThemeBlend.j @@ -0,0 +1,82 @@ +/* + * CPThemeBlend.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 +@import + + +@implementation CPThemeBlend : CPObject +{ + CPBundle _bundle; + CPArray _themes @accessors(readonly); + id _loadDelegate; +} + +- (id)initWithContentsOfURL:(CPURL)aURL +{ + self = [super init]; + + if (self) + { + _bundle = [[CPBundle alloc] initWithPath:aURL + "/Info.plist"]; + } + + return self; +} + +- (void)loadWithDelegate:(id)aDelegate +{ + _loadDelegate = aDelegate; + + [_bundle loadWithDelegate:self]; +} + +- (void)bundleDidFinishLoading:(CPBundle)aBundle +{ + var paths = [_bundle objectForInfoDictionaryKey:@"CPBundleReplacedFiles"], + index = 0, + count = paths.length, + bundlePath = [_bundle bundlePath]; + + while (count--) + { + var path = paths[count]; + + if ([path pathExtension] === "keyedtheme") + { + var unarchiver = [[_CPThemeKeyedUnarchiver alloc] + initForReadingWithData:[CPData dataWithString:objj_files[bundlePath + '/' + path].contents] + bundle:_bundle]; + + [unarchiver decodeObjectForKey:@"root"]; + + [unarchiver finishDecoding]; + } + } + + [_loadDelegate blendDidFinishLoading:self]; +} + +@end diff --git a/AppKit/CPThemedAttribute.j b/AppKit/CPThemedAttribute.j deleted file mode 100644 index e25590412..000000000 --- a/AppKit/CPThemedAttribute.j +++ /dev/null @@ -1,267 +0,0 @@ - -@import - - -CPControlStateNormal = 0, -CPControlStateHighlighted = 1 << 0, -CPControlStateDisabled = 1 << 1, -CPControlStateSelected = 1 << 2, -CPControlStateDefault = 1 << 3, -CPControlStateBordered = 1 << 4, -CPControlStateBezeled = 1 << 5, -CPControlStateVertical = 1 << 6, -CPControlStateEditable = 1 << 7, -CPControlStateEditing = 1 << 8; -CPControlStateHorizontal = 1 << 9; -CPControlStateCircular = 1 << 10; - -var BIT_COUNT = [ 0 /*00000*/, 1 /*00001*/, 1 /*00010*/, 2 /*00011*/, 1 /*00100*/, 2 /*00101*/, 2 /*00110*/, 3 /*00111*/, - 1 /*01000*/, 2 /*01001*/, 2 /*01010*/, 3 /*01011*/, 2 /*01100*/, 3 /*01101*/, 3 /*01110*/, 4 /*01111*/, - 1 /*10000*/, 2 /*10001*/, 2 /*10010*/, 3 /*10011*/, 2 /*10100*/, 3 /*10101*/, 3 /*10110*/, 4 /*10111*/, - 2 /*11000*/, 3 /*11001*/, 3 /*11010*/, 4 /*11011*/, 3 /*11100*/, 4 /*11101*/, 4 /*11110*/, 5 /*11111*/], - bit_count = function(bits) - { - var count = 0; - - while (bits) - { - ++count; - bits &= (bits - 1); - } - - return count ; - } - -@implementation CPThemedAttribute : CPObject -{ - JSObject _cache; - - CPString _name; - id _defaultValue; - - CPTheme _theme; - Class _themedClass; - - CPDictionary _values; - CPThemedAttribute _attributeFromTheme; -} - -- (id)initWithName:(CPString)aName defaultValue:(id)aDefaultValue theme:(CPTheme)aTheme class:(Class)aClass -{ - self = [super init]; - - if (self) - { - _cache = {}; - - _name = aName; - - _defaultValue = aDefaultValue; - - _theme = aTheme; - _themedClass = aClass; - - _values = [CPDictionary dictionary]; - _attributeFromTheme = [_theme valueForAttributeName:_name inClass:_themedClass]; - } - - return self; -} - -- (void)setName:(CPString)aName -{ - _name = aName; -} - -- (CPString)name -{ - return _name; -} - -- (void)setDefaultValue:(id)aValue -{ - _cache = {}; - _defaultValue = aValue; -} - -- (void)setTheme:(CPTheme)aTheme -{ - if (_theme === aTheme) - return; - - _cache = {}; - _theme = aTheme; - _attributeFromTheme = [_theme valueForAttributeName:_name inClass:_themedClass]; -} - -- (void)setThemedClass:(Class)aClass -{ - if (_themedClass === aClass) - return; - - _cache = {}; - _themedClass = aClass; - _attributeFromTheme = [_theme valueForAttributeName:_name inClass:_themedClass]; -} - -- (void)setValue:(id)aValue -{ - _cache = {}; - - if (aValue === undefined || aValue === nil) - _values = [CPDictionary dictionary]; - else - _values = [CPDictionary dictionaryWithObject:aValue forKey:String(CPControlStateNormal)]; -} - -- (id)value -{ - return [self valueForControlState:CPControlStateNormal]; -} - -- (void)setValue:(id)aValue forControlState:(CPControlState)aState -{ - //delete _cache[aState]; - _cache = {}; - - if ((aValue === undefined) || (aValue === nil)) - [_values removeObjectForKey:String(aState)]; - else - [_values setObject:aValue forKey:String(aState)]; -} - -- (id)valueForControlState:(CPControlState)aState -{ - var value = _cache[aState]; - - // This can be nil. - if (value !== undefined) - return value; - - value = [_values objectForKey:String(aState)]; - - // If we don't have a value, and we have a non-normal state... - if ((value === undefined || value === nil) && aState > 0) - { - // If this is a composite state, find the closest partial subset match. - if (aState & (aState - 1)) - { - var highestBitCount = 0, - states = [_values allKeys], - count = states.length; - - while (count--) - { - // state is a string! - state = Number(states[count]); - - // A & B = A iff A < B - if ((state & aState) === state) - { - var bitCount = (state < BIT_COUNT.length) ? BIT_COUNT[state] : bit_count(state); - - if (bitCount > highestBitCount) - { - highestBitCount = bitCount; - value = [_values objectForKey:String(state)]; - } - } - } - } - - // Still don't have a value? OK, let's use the normal value. - if (value === undefined || value === nil) - value = [_values objectForKey:String(CPControlStateNormal)]; - } - - if (value === undefined || value === nil) - value = [_attributeFromTheme valueForControlState:aState]; - - if (value === undefined || value === nil) - value = _defaultValue; - - _cache[aState] = value; - - return value; -} - -- (CPThemedAttribute)themedAttributeMergedWithThemedAttribute:(CPThemedAttribute)aThemedAttribute -{ - var mergedAttribute = CPThemedAttributeMake(_name, _defaultValue, _theme, _themedClass); - - mergedAttribute._values = [_values copy]; - [mergedAttribute._values addEntriesFromDictionary:aThemedAttribute._values]; - - return mergedAttribute; -} - -- (id)initWithCoder:(CPCoder)aCoder -{ - self = [super init]; - - if (self) - { - _cache = {}; - _values = [aCoder decodeObjectForKey:@"values"]; - } - - return self; -} - -- (void)encodeWithCoder:(CPCoder)aCoder -{ - [aCoder encodeObject:_values forKey:@"values"]; -} - -@end - -function CPThemedAttributeMake(aName, aDefaultValue, aTheme, aClass) -{ - return [[CPThemedAttribute alloc] initWithName:aName defaultValue:aDefaultValue theme:aTheme class:aClass]; -} - -function CPThemedAttributeEncode(aCoder, aThemedAttribute) -{ - var values = aThemedAttribute._values, - count = [values count]; - - if (count === 1) - { - var key = [values allKeys][0]; - - if (Number(key) === 0) - return [aCoder encodeObject:[values objectForKey:key] forKey:"$a" + [aThemedAttribute name]]; - } - - if (count >= 1) - [aCoder encodeObject:aThemedAttribute forKey:"$a" + [aThemedAttribute name]]; -} - -function CPThemedAttributeDecode(aCoder, anAttributeName, aDefaultValue, aTheme, aClass) -{ - var key = "$a" + anAttributeName; - - if (![aCoder containsValueForKey:key]) - return CPThemedAttributeMake(anAttributeName, aDefaultValue, aTheme, aClass); - - var attribute = [aCoder decodeObjectForKey:key]; - - if (!attribute.isa || ![attribute isKindOfClass:[CPThemedAttribute class]]) - { - var themedAttribute = CPThemedAttributeMake(anAttributeName, aDefaultValue, aTheme, aClass); - - [themedAttribute setValue:attribute]; - - attribute = themedAttribute; - } - - else - { - [attribute setName:anAttributeName]; - [attribute setDefaultValue:aDefaultValue]; - [attribute setTheme:aTheme]; - [attribute setThemedClass:aClass]; - } - - return attribute; -} diff --git a/AppKit/CPView.j b/AppKit/CPView.j index 894cb547b..71237bacd 100644 --- a/AppKit/CPView.j +++ b/AppKit/CPView.j @@ -85,11 +85,8 @@ CPViewMaxYMargin = 32; CPViewBoundsDidChangeNotification = @"CPViewBoundsDidChangeNotification"; CPViewFrameDidChangeNotification = @"CPViewFrameDidChangeNotification"; -var _DOMOriginUpdateMask = 1 << 0, - _DOMSizeUpdateMask = 1 << 1; - -var _CPViewNotificationCenter = nil, - _CachedThemedAttributes = nil; +var CachedNotificationCenter = nil, + CachedThemeAttributes = nil; #if PLATFORM(DOM) var DOMElementPrototype = nil, @@ -178,7 +175,8 @@ var DOMElementPrototype = nil, // Theming Support CPTheme _theme; - JSObject _themedAttributes; + JSObject _themeAttributes; + unsigned _themeState; // Key View Support CPView _nextKeyView; @@ -191,7 +189,7 @@ var DOMElementPrototype = nil, */ + (void)initialize { - if (self != [CPView class]) + if (self !== [CPView class]) return; #if PLATFORM(DOM) @@ -205,7 +203,7 @@ var DOMElementPrototype = nil, style.zIndex = 0; #endif - _CPViewNotificationCenter = [CPNotificationCenter defaultCenter]; + CachedNotificationCenter = [CPNotificationCenter defaultCenter]; } - (id)init @@ -255,9 +253,9 @@ var DOMElementPrototype = nil, #endif _theme = [CPTheme defaultTheme]; - _themedAttributes = {}; - - [self _loadThemedAttributes]; + _themeState = CPThemeStateNormal; + + [self _loadThemeAttributes]; } return self; @@ -588,7 +586,7 @@ var DOMElementPrototype = nil, _inhibitFrameAndBoundsChangedNotifications = NO; if (_postsFrameChangedNotifications) - [_CPViewNotificationCenter postNotificationName:CPViewFrameDidChangeNotification object:self]; + [CachedNotificationCenter postNotificationName:CPViewFrameDidChangeNotification object:self]; } /*! @@ -639,7 +637,7 @@ var DOMElementPrototype = nil, origin.y = aPoint.y; if (_postsFrameChangedNotifications && !_inhibitFrameAndBoundsChangedNotifications) - [_CPViewNotificationCenter postNotificationName:CPViewFrameDidChangeNotification object:self]; + [CachedNotificationCenter postNotificationName:CPViewFrameDidChangeNotification object:self]; #if PLATFORM(DOM) CPDOMDisplayServerSetStyleLeftTop(_DOMElement, _superview ? _superview._boundsTransform : NULL, origin.x, origin.y); @@ -717,7 +715,7 @@ var DOMElementPrototype = nil, #endif if (_postsFrameChangedNotifications && !_inhibitFrameAndBoundsChangedNotifications) - [_CPViewNotificationCenter postNotificationName:CPViewFrameDidChangeNotification object:self]; + [CachedNotificationCenter postNotificationName:CPViewFrameDidChangeNotification object:self]; } /*! @@ -738,7 +736,7 @@ var DOMElementPrototype = nil, _inhibitFrameAndBoundsChangedNotifications = NO; if (_postsBoundsChangedNotifications) - [_CPViewNotificationCenter postNotificationName:CPViewBoundsDidChangeNotification object:self]; + [CachedNotificationCenter postNotificationName:CPViewBoundsDidChangeNotification object:self]; } /*! @@ -790,7 +788,7 @@ var DOMElementPrototype = nil, #endif if (_postsBoundsChangedNotifications && !_inhibitFrameAndBoundsChangedNotifications) - [_CPViewNotificationCenter postNotificationName:CPViewBoundsDidChangeNotification object:self]; + [CachedNotificationCenter postNotificationName:CPViewBoundsDidChangeNotification object:self]; } /*! @@ -828,7 +826,7 @@ var DOMElementPrototype = nil, } if (_postsBoundsChangedNotifications && !_inhibitFrameAndBoundsChangedNotifications) - [_CPViewNotificationCenter postNotificationName:CPViewBoundsDidChangeNotification object:self]; + [CachedNotificationCenter postNotificationName:CPViewBoundsDidChangeNotification object:self]; } @@ -1358,7 +1356,7 @@ setFrameOrigin: _postsFrameChangedNotifications = shouldPostFrameChangedNotifications; if (_postsFrameChangedNotifications) - [_CPViewNotificationCenter postNotificationName:CPViewFrameDidChangeNotification object:self]; + [CachedNotificationCenter postNotificationName:CPViewFrameDidChangeNotification object:self]; } /*! @@ -1389,7 +1387,7 @@ setBoundsOrigin: _postsBoundsChangedNotifications = shouldPostBoundsChangedNotifications; if (_postsBoundsChangedNotifications) - [_CPViewNotificationCenter postNotificationName:CPViewBoundsDidChangeNotification object:self]; + [CachedNotificationCenter postNotificationName:CPViewBoundsDidChangeNotification object:self]; } /*! @@ -1930,67 +1928,118 @@ setBoundsOrigin: @end @implementation CPView (Theming) +#pragma mark Theme States -+ (CPDictionary)themedAttributes +- (BOOL)hasThemeState:(CPThemeState)aState +{ + return !!(_themeState & ((typeof aState === "string") ? CPThemeState(aState) : aState)); +} + +- (BOOL)setThemeState:(CPThemeState)aState +{ + var newState = (typeof aState === "string") ? CPThemeState(aState) : aState; + + if (_themeState & newState) + return NO; + + _themeState |= newState; + + [self setNeedsLayout]; + [self setNeedsDisplay:YES]; + + return YES; +} + +- (BOOL)unsetThemeState:(CPThemeState)aState +{ + var newState = ((typeof aState === "string") ? CPThemeState(aState) : aState); + + if (!(_themeState & newState)) + return NO; + + _themeState &= ~newState; + + [self setNeedsLayout]; + [self setNeedsDisplay:YES]; + + return YES; +} + +#pragma mark Theme Attributes + ++ (CPString)themeClass { return nil; } -+ (CPArray)_themedAttributes ++ (CPDictionary)themeAttributes { - if (!_CachedThemedAttributes) - _CachedThemedAttributes = {}; + return nil; +} + ++ (CPArray)_themeAttributes +{ + if (!CachedThemeAttributes) + CachedThemeAttributes = {}; var theClass = [self class], CPViewClass = [CPView class], attributes = []; - - while (theClass && theClass !== CPViewClass) + + for (; theClass && theClass !== CPViewClass; theClass = [theClass superclass]) { - var cachedAttributes = _CachedThemedAttributes[class_getName(theClass)]; - + var cachedAttributes = CachedThemeAttributes[class_getName(theClass)]; + if (cachedAttributes) { attributes = attributes.length ? attributes.concat(cachedAttributes) : attributes; - _CachedThemedAttributes[[self className]] = attributes; - + CachedThemeAttributes[[self className]] = attributes; + break; } + + var attributeDictionary = [theClass themeAttributes]; - var attributeDictionary = [theClass themedAttributes]; - - if (attributeDictionary) + if (!attributeDictionary) + continue; + + var attributeKeys = [attributeDictionary allKeys], + attributeCount = attributeKeys.length; + + while (attributeCount--) { - var attributeKeys = [attributeDictionary allKeys], - attributeCount = attributeKeys.length; - - while (attributeCount--) - { - var attributeName = attributeKeys[attributeCount]; - - attributes.push([attributeDictionary objectForKey:attributeName]); - attributes.push(attributeName); - } + var attributeName = attributeKeys[attributeCount]; + + attributes.push([attributeDictionary objectForKey:attributeName]); + attributes.push(attributeName); } - - theClass = [theClass superclass]; } - + return attributes; } -- (void)_loadThemedAttributes +- (void)_loadThemeAttributes { - var theme = [self theme], - theClass = [self class], - attributes = [theClass _themedAttributes]; + var theClass = [self class], + attributes = [theClass _themeAttributes], count = attributes.length; + + if (!count) + return; + + var theme = [self theme], + themeClass = [theClass themeClass]; + + _themeAttributes = {}; while (count--) { - var attributeName = attributes[count--]; + var attributeName = attributes[count--], + attribute = [[_CPThemeAttribute alloc] initWithName:attributeName defaultValue:attributes[count]]; + + [attribute setParentAttribute:[theme _attributeWithName:attributeName forClass:themeClass]]; - _themedAttributes[attributeName] = CPThemedAttributeMake(attributeName, attributes[count], theme, theClass); + _themeAttributes[attributeName] = attribute; } } @@ -2011,73 +2060,87 @@ setBoundsOrigin: - (void)viewDidChangeTheme { - var theme = [self theme]; - - for (var attributeName in _themedAttributes) - if (_themedAttributes.hasOwnProperty(attributeName)) - [_themedAttributes[attributeName] setTheme:theme]; + if (!_themeAttributes) + return; + + var theme = [self theme], + themeClass = [[self class] themeClass]; + + for (var attributeName in _themeAttributes) + if (_themeAttributes.hasOwnProperty(attributeName)) + [_themeAttributes[attributeName] setParentAttribute:[theme _attributeWithName:attributeName forClass:themeClass]]; } -- (CPDictionary)_themedAttributes +- (CPDictionary)_themeAttributeDictionary { var dictionary = [CPDictionary dictionary]; - - for (var attributeName in _themedAttributes) - if (_themedAttributes.hasOwnProperty(attributeName)) - [dictionary setObject:_themedAttributes[attributeName] forKey:attributeName]; - + + if (_themeAttributes) + { + var theme = [self theme]; + + for (var attributeName in _themeAttributes) + if (_themeAttributes.hasOwnProperty(attributeName)) + [dictionary setObject:_themeAttributes[attributeName] forKey:attributeName]; + } + return dictionary; } -- (void)setValue:(id)aValue forThemedAttributeName:(CPString)aName inControlState:(CPControlState)aControlState +- (void)setValue:(id)aValue forThemeAttribute:(CPString)aName inState:(CPThemeState)aState { - var attribute = _themedAttributes[aName]; + if (!_themeAttributes || !_themeAttributes[aName]) + [CPException raise:CPInvalidArgumentException reason:[self className] + " does not contain theme attribute '" + aName + "'"]; - if (!attribute) - return; + var currentValue = [self currentValueForThemeAttribute:aName]; - var currentValue = [self currentValueForThemedAttributeName:aName]; + [_themeAttributes[aName] setValue:aValue forState:aState]; - [attribute setValue:aValue forControlState:aControlState]; - - if ([self currentValueForThemedAttributeName:aName] === currentValue) + if ([self currentValueForThemeAttribute:aName] === currentValue) return; [self setNeedsDisplay:YES]; [self setNeedsLayout]; } -- (void)setValue:(id)aValue forThemedAttributeName:(CPString)aName +- (void)setValue:(id)aValue forThemeAttribute:(CPString)aName { - var attribute = _themedAttributes[aName]; + if (!_themeAttributes || !_themeAttributes[aName]) + [CPException raise:CPInvalidArgumentException reason:[self className] + " does not contain theme attribute '" + aName + "'"]; - if (!attribute) - return; + var currentValue = [self currentValueForThemeAttribute:aName]; - var currentValue = [self currentValueForThemedAttributeName:aName]; + [_themeAttributes[aName] setValue:aValue]; - [attribute setValue:aValue]; - - if ([self currentValueForThemedAttributeName:aName] === currentValue) + if ([self currentValueForThemeAttribute:aName] === currentValue) return; [self setNeedsDisplay:YES]; [self setNeedsLayout]; } -- (id)valueForThemedAttributeName:(CPString)aName inControlState:(CPControlState)aControlState +- (id)valueForThemeAttribute:(CPString)aName inState:(CPThemeState)aState { - return [_themedAttributes[aName] valueForControlState:aControlState]; + if (!_themeAttributes || !_themeAttributes[aName]) + [CPException raise:CPInvalidArgumentException reason:[self className] + " does not contain theme attribute '" + aName + "'"]; + + return [_themeAttributes[aName] valueForState:aState]; } -- (id)valueForThemedAttributeName:(CPString)aName +- (id)valueForThemeAttribute:(CPString)aName { - return [_themedAttributes[aName] value]; + if (!_themeAttributes || !_themeAttributes[aName]) + [CPException raise:CPInvalidArgumentException reason:[self className] + " does not contain theme attribute '" + aName + "'"]; + + return [_themeAttributes[aName] value]; } -- (void)currentValueForThemedAttributeName:(CPString)aName +- (void)currentValueForThemeAttribute:(CPString)aName { - return [_themedAttributes[aName] valueForControlState:_controlState];//[self controlStateForThemedAttributeName:aName]]; + if (!_themeAttributes || !_themeAttributes[aName]) + [CPException raise:CPInvalidArgumentException reason:[self className] + " does not contain theme attribute '" + aName + "'"]; + + return [_themeAttributes[aName] valueForState:_themeState]; } @end @@ -2093,6 +2156,7 @@ var CPViewAutoresizingMaskKey = @"CPViewAutoresizingMask", CPViewSubviewsKey = @"CPViewSubviewsKey", CPViewSuperviewKey = @"CPViewSuperviewKey", CPViewTagKey = @"CPViewTagKey", + CPViewThemeStateKey = @"CPViewThemeStateKey", CPViewWindowKey = @"CPViewWindowKey", CPViewNextKeyViewKey = @"CPViewNextKeyViewKey", CPViewPreviousKeyViewKey = @"CPViewPreviousKeyViewKey"; @@ -2160,17 +2224,19 @@ var CPViewAutoresizingMaskKey = @"CPViewAutoresizingMask", [self setBackgroundColor:[aCoder decodeObjectForKey:CPViewBackgroundColorKey]]; _theme = [CPTheme defaultTheme]; - _themedAttributes = {}; - + _themeState = [aCoder decodeIntForKey:CPViewThemeStateKey]; + _themeAttributes = {}; + var theClass = [self class], - attributes = [theClass _themedAttributes], + themeClass = [theClass themeClass], + attributes = [theClass _themeAttributes], count = attributes.length; - + while (count--) { var attributeName = attributes[count--]; - - _themedAttributes[attributeName] = CPThemedAttributeDecode(aCoder, attributeName, attributes[count], _theme, theClass); + + _themeAttributes[attributeName] = CPThemeAttributeDecode(aCoder, attributeName, attributes[count], _theme, themeClass); } [self setNeedsDisplay:YES]; @@ -2209,9 +2275,11 @@ var CPViewAutoresizingMaskKey = @"CPViewAutoresizingMask", [aCoder encodeConditionalObject:[self nextKeyView] forKey:CPViewNextKeyViewKey]; [aCoder encodeConditionalObject:[self previousKeyView] forKey:CPViewPreviousKeyViewKey]; - for (var attributeName in _themedAttributes) - if (_themedAttributes.hasOwnProperty(attributeName)) - CPThemedAttributeEncode(aCoder, _themedAttributes[attributeName]); + [aCoder encodeInt:_themeState forKey:CPViewThemeStateKey]; + + for (var attributeName in _themeAttributes) + if (_themeAttributes.hasOwnProperty(attributeName)) + CPThemeAttributeEncode(aCoder, _themeAttributes[attributeName]); } @end diff --git a/AppKit/Themes/Aristo/Resources/popup-bezel-right-pullsdown.png b/AppKit/Themes/Aristo/Resources/popup-bezel-right-pullsdown.png index a17bed227dc078f8a89d92200292d267015e80d6..6694b670a1ca76fca9c466bd08fac3838a2773ca 100644 GIT binary patch literal 474 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 diff --git a/AppKit/Themes/Aristo/Resources/scroller-horizontal-knob-left.png b/AppKit/Themes/Aristo/Resources/scroller-horizontal-knob-left.png index 8b417a826cbb3b8f66d81c60b5569a411983d2fb..48b0753a6777a0dc38033ce1f41e8b9dd021de1c 100644 GIT binary patch literal 3077 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 Tm*sX200000NkvXXu0mjfjw-$= literal 23854 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 AV*mgE literal 25008 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 Gc -@import + @implementation AristoThemeDescriptor : CPObject { @@ -21,34 +21,34 @@ + (CPScroller)themedVerticalScroller { var scroller = [[CPScroller alloc] initWithFrame:CGRectMake(0.0, 0.0, 17.0, 170.0)], - trackColor = PatterColor([_CPCibCustomResource imageResourceWithName:"scroller-vertical-track.png" size:CGSizeMake(17.0, 1.0)]), - disabledTrackColor = PatterColor([_CPCibCustomResource imageResourceWithName:"scroller-vertical-track-disabled.png" size:CGSizeMake(17.0, 1.0)]); + trackColor = PatternColor([_CPCibCustomResource imageResourceWithName:"scroller-vertical-track.png" size:CGSizeMake(17.0, 1.0)]), + disabledTrackColor = PatternColor([_CPCibCustomResource imageResourceWithName:"scroller-vertical-track-disabled.png" size:CGSizeMake(17.0, 1.0)]); - [scroller setValue:CGSizeMake(15.0, 19.0) forThemedAttributeName:@"minimum-knob-size" inControlState:CPControlStateVertical]; + [scroller setValue:CGSizeMake(15.0, 19.0) forThemeAttribute:@"minimum-knob-size" inState:CPThemeStateVertical]; - [scroller setValue:CGInsetMake(9.0, 9.0, 9.0, 9.0) forThemedAttributeName:@"track-overlap-inset" inControlState:CPControlStateVertical]; - [scroller setValue:trackColor forThemedAttributeName:@"knob-slot-color" inControlState:CPControlStateVertical]; - [scroller setValue:disabledTrackColor forThemedAttributeName:@"knob-slot-color" inControlState:CPControlStateVertical | CPControlStateDisabled]; + [scroller setValue:CGInsetMake(9.0, 9.0, 9.0, 9.0) forThemeAttribute:@"track-overlap-inset" inState:CPThemeStateVertical]; + [scroller setValue:trackColor forThemeAttribute:@"knob-slot-color" inState:CPThemeStateVertical]; + [scroller setValue:disabledTrackColor forThemeAttribute:@"knob-slot-color" inState:CPThemeStateVertical | CPThemeStateDisabled]; - var arrowColor = PatterColor([_CPCibCustomResource imageResourceWithName:"scroller-up-arrow.png" size:CGSizeMake(17.0, 30.0)]), - highlightedArrowColor = PatterColor([_CPCibCustomResource imageResourceWithName:"scroller-up-arrow-highlighted.png" size:CGSizeMake(17.0, 30.0)]), - disabledArrowColor = PatterColor([_CPCibCustomResource imageResourceWithName:"scroller-up-arrow-disabled.png" size:CGSizeMake(17.0, 30.0)]); + var arrowColor = PatternColor([_CPCibCustomResource imageResourceWithName:"scroller-up-arrow.png" size:CGSizeMake(17.0, 30.0)]), + highlightedArrowColor = PatternColor([_CPCibCustomResource imageResourceWithName:"scroller-up-arrow-highlighted.png" size:CGSizeMake(17.0, 30.0)]), + disabledArrowColor = PatternColor([_CPCibCustomResource imageResourceWithName:"scroller-up-arrow-disabled.png" size:CGSizeMake(17.0, 30.0)]); - [scroller setValue:CGSizeMake(17.0, 30.0) forThemedAttributeName:@"decrement-line-size" inControlState:CPControlStateVertical]; - [scroller setValue:arrowColor forThemedAttributeName:@"decrement-line-color" inControlState:CPControlStateVertical]; - [scroller setValue:highlightedArrowColor forThemedAttributeName:@"decrement-line-color" inControlState:CPControlStateVertical | CPControlStateHighlighted], - [scroller setValue:disabledArrowColor forThemedAttributeName:@"decrement-line-color" inControlState:CPControlStateVertical | CPControlStateDisabled]; + [scroller setValue:CGSizeMake(17.0, 30.0) forThemeAttribute:@"decrement-line-size" inState:CPThemeStateVertical]; + [scroller setValue:arrowColor forThemeAttribute:@"decrement-line-color" inState:CPThemeStateVertical]; + [scroller setValue:highlightedArrowColor forThemeAttribute:@"decrement-line-color" inState:CPThemeStateVertical | CPThemeStateHighlighted], + [scroller setValue:disabledArrowColor forThemeAttribute:@"decrement-line-color" inState:CPThemeStateVertical | CPThemeStateDisabled]; - var arrowColor = PatterColor([_CPCibCustomResource imageResourceWithName:"scroller-down-arrow.png" size:CGSizeMake(17.0, 30.0)]), - highlightedArrowColor = PatterColor([_CPCibCustomResource imageResourceWithName:"scroller-down-arrow-highlighted.png" size:CGSizeMake(17.0, 30.0)]), - disabledArrowColor = PatterColor([_CPCibCustomResource imageResourceWithName:"scroller-down-arrow-disabled.png" size:CGSizeMake(17.0, 30.0)]); + var arrowColor = PatternColor([_CPCibCustomResource imageResourceWithName:"scroller-down-arrow.png" size:CGSizeMake(17.0, 30.0)]), + highlightedArrowColor = PatternColor([_CPCibCustomResource imageResourceWithName:"scroller-down-arrow-highlighted.png" size:CGSizeMake(17.0, 30.0)]), + disabledArrowColor = PatternColor([_CPCibCustomResource imageResourceWithName:"scroller-down-arrow-disabled.png" size:CGSizeMake(17.0, 30.0)]); - [scroller setValue:CGSizeMake(17.0, 30.0) forThemedAttributeName:@"increment-line-size"]; - [scroller setValue:arrowColor forThemedAttributeName:@"increment-line-color" inControlState:CPControlStateVertical]; - [scroller setValue:highlightedArrowColor forThemedAttributeName:@"increment-line-color" inControlState:CPControlStateVertical | CPControlStateHighlighted]; - [scroller setValue:disabledArrowColor forThemedAttributeName:@"increment-line-color" inControlState:CPControlStateVertical | CPControlStateDisabled]; + [scroller setValue:CGSizeMake(17.0, 30.0) forThemeAttribute:@"increment-line-size"]; + [scroller setValue:arrowColor forThemeAttribute:@"increment-line-color" inState:CPThemeStateVertical]; + [scroller setValue:highlightedArrowColor forThemeAttribute:@"increment-line-color" inState:CPThemeStateVertical | CPThemeStateHighlighted]; + [scroller setValue:disabledArrowColor forThemeAttribute:@"increment-line-color" inState:CPThemeStateVertical | CPThemeStateDisabled]; - var knobColor = PatterColor([[CPThreePartImage alloc] initWithImageSlices: + var knobColor = PatternColor([[CPThreePartImage alloc] initWithImageSlices: [ [_CPCibCustomResource imageResourceWithName:"scroller-vertical-knob-top.png" size:CGSizeMake(15.0, 8.0)], [_CPCibCustomResource imageResourceWithName:"scroller-vertical-knob-center.png" size:CGSizeMake(15.0, 1.0)], @@ -56,7 +56,7 @@ ] isVertical:YES]); - [scroller setValue:knobColor forThemedAttributeName:@"knob-color" inControlState:CPControlStateVertical]; + [scroller setValue:knobColor forThemeAttribute:@"knob-color" inState:CPThemeStateVertical]; [scroller setFloatValue:0.1 knobProportion:0.5]; @@ -64,36 +64,36 @@ } + (CPScroller)themedHorizontalScroller -{CPControlStateHorizontal = 0; +{ var scroller = [[CPScroller alloc] initWithFrame:CGRectMake(0.0, 0.0, 170.0, 17.0)], - trackColor = PatterColor([_CPCibCustomResource imageResourceWithName:"scroller-horizontal-track.png" size:CGSizeMake(1.0, 17.0)]), - disabledTrackColor = PatterColor([_CPCibCustomResource imageResourceWithName:"scroller-vertical-track-disabled.png" size:CGSizeMake(17.0, 1.0)]); + trackColor = PatternColor([_CPCibCustomResource imageResourceWithName:"scroller-horizontal-track.png" size:CGSizeMake(1.0, 17.0)]), + disabledTrackColor = PatternColor([_CPCibCustomResource imageResourceWithName:"scroller-vertical-track-disabled.png" size:CGSizeMake(17.0, 1.0)]); [scroller setBackgroundColor:[CPColor blueColor]]; - [scroller setValue:CGSizeMake(19.0, 15.0) forThemedAttributeName:@"minimum-knob-size" inControlState:CPControlStateHorizontal]; + [scroller setValue:CGSizeMake(19.0, 15.0) forThemeAttribute:@"minimum-knob-size"]; - [scroller setValue:CGInsetMake(9.0, 9.0, 9.0, 9.0) forThemedAttributeName:@"track-overlap-inset" inControlState:CPControlStateHorizontal]; - [scroller setValue:trackColor forThemedAttributeName:@"knob-slot-color" inControlState:CPControlStateHorizontal]; - [scroller setValue:disabledTrackColor forThemedAttributeName:@"knob-slot-color" inControlState:CPControlStateHorizontal | CPControlStateDisabled]; + [scroller setValue:CGInsetMake(9.0, 9.0, 9.0, 9.0) forThemeAttribute:@"track-overlap-inset" ]; + [scroller setValue:trackColor forThemeAttribute:@"knob-slot-color"]; + [scroller setValue:disabledTrackColor forThemeAttribute:@"knob-slot-color" inState:CPThemeStateDisabled]; - var arrowColor = PatterColor([_CPCibCustomResource imageResourceWithName:"scroller-left-arrow.png" size:CGSizeMake(32.0, 17.0)]), - highlightedArrowColor = PatterColor([_CPCibCustomResource imageResourceWithName:"scroller-up-arrow-highlighted.png" size:CGSizeMake(17.0, 30.0)]), - disabledArrowColor = PatterColor([_CPCibCustomResource imageResourceWithName:"scroller-up-arrow-disabled.png" size:CGSizeMake(17.0, 30.0)]); + var arrowColor = PatternColor([_CPCibCustomResource imageResourceWithName:"scroller-left-arrow.png" size:CGSizeMake(32.0, 17.0)]), + highlightedArrowColor = PatternColor([_CPCibCustomResource imageResourceWithName:"scroller-left-arrow-highlighted.png" size:CGSizeMake(17.0, 30.0)]), + disabledArrowColor = PatternColor([_CPCibCustomResource imageResourceWithName:"scroller-left-arrow-disabled.png" size:CGSizeMake(17.0, 30.0)]); - [scroller setValue:CGSizeMake(32.0, 17.0) forThemedAttributeName:@"decrement-line-size" inControlState:CPControlStateHorizontal]; - [scroller setValue:arrowColor forThemedAttributeName:@"decrement-line-color" inControlState:CPControlStateHorizontal]; - [scroller setValue:highlightedArrowColor forThemedAttributeName:@"decrement-line-color" inControlState:CPControlStateHorizontal | CPControlStateHighlighted], - [scroller setValue:disabledArrowColor forThemedAttributeName:@"decrement-line-color" inControlState:CPControlStateHorizontal | CPControlStateDisabled]; + [scroller setValue:CGSizeMake(32.0, 17.0) forThemeAttribute:@"decrement-line-size"]; + [scroller setValue:arrowColor forThemeAttribute:@"decrement-line-color"]; + [scroller setValue:highlightedArrowColor forThemeAttribute:@"decrement-line-color" inState:CPThemeStateHighlighted], + [scroller setValue:disabledArrowColor forThemeAttribute:@"decrement-line-color" inState:CPThemeStateDisabled]; - var arrowColor = PatterColor([_CPCibCustomResource imageResourceWithName:"scroller-right-arrow.png" size:CGSizeMake(31.0, 17.0)]), - highlightedArrowColor = PatterColor([_CPCibCustomResource imageResourceWithName:"scroller-down-arrow-highlighted.png" size:CGSizeMake(17.0, 30.0)]), - disabledArrowColor = PatterColor([_CPCibCustomResource imageResourceWithName:"scroller-down-arrow-disabled.png" size:CGSizeMake(17.0, 30.0)]); + var arrowColor = PatternColor([_CPCibCustomResource imageResourceWithName:"scroller-right-arrow.png" size:CGSizeMake(31.0, 17.0)]), + highlightedArrowColor = PatternColor([_CPCibCustomResource imageResourceWithName:"scroller-right-arrow-highlighted.png" size:CGSizeMake(17.0, 30.0)]), + disabledArrowColor = PatternColor([_CPCibCustomResource imageResourceWithName:"scroller-right-arrow-disabled.png" size:CGSizeMake(17.0, 30.0)]); - [scroller setValue:CGSizeMake(31.0, 17.0) forThemedAttributeName:@"increment-line-size"]; - [scroller setValue:arrowColor forThemedAttributeName:@"increment-line-color" inControlState:CPControlStateHorizontal]; - [scroller setValue:highlightedArrowColor forThemedAttributeName:@"increment-line-color" inControlState:CPControlStateHorizontal | CPControlStateHighlighted]; - [scroller setValue:disabledArrowColor forThemedAttributeName:@"increment-line-color" inControlState:CPControlStateHorizontal | CPControlStateDisabled]; + [scroller setValue:CGSizeMake(31.0, 17.0) forThemeAttribute:@"increment-line-size"]; + [scroller setValue:arrowColor forThemeAttribute:@"increment-line-color"]; + [scroller setValue:highlightedArrowColor forThemeAttribute:@"increment-line-color" inState:CPThemeStateHighlighted]; + [scroller setValue:disabledArrowColor forThemeAttribute:@"increment-line-color" inState:CPThemeStateDisabled]; - var knobColor = PatterColor([[CPThreePartImage alloc] initWithImageSlices: + var knobColor = PatternColor([[CPThreePartImage alloc] initWithImageSlices: [ [_CPCibCustomResource imageResourceWithName:"scroller-horizontal-knob-left.png" size:CGSizeMake(11.0, 15.0)], [_CPCibCustomResource imageResourceWithName:"scroller-horizontal-knob-center.png" size:CGSizeMake(1.0, 15.0)], @@ -101,7 +101,7 @@ ] isVertical:NO]); - [scroller setValue:knobColor forThemedAttributeName:@"knob-color" inControlState:CPControlStateHorizontal]; + [scroller setValue:knobColor forThemeAttribute:@"knob-color"]; [scroller setFloatValue:0.1 knobProportion:0.5]; @@ -139,17 +139,15 @@ [textfield setBezeled:YES]; - [textfield setValue:bezelColor forThemedAttributeName:@"bezel-color" inControlState:CPControlStateBezeled]; - [textfield setValue:bezelFocusedColor forThemedAttributeName:@"bezel-color" inControlState:CPControlStateBezeled|CPControlStateEditing]; + [textfield setValue:bezelColor forThemeAttribute:@"bezel-color" inState:CPThemeStateBezeled]; + [textfield setValue:bezelFocusedColor forThemeAttribute:@"bezel-color" inState:CPThemeStateBezeled|CPThemeStateEditing]; + [textfield setValue:[CPFont systemFontOfSize:12.0] forThemeAttribute:@"font" inState:CPThemeStateBezeled]; + [textfield setValue:CGInsetMake(9.0, 8.0, 5.0, 7.0) forThemeAttribute:@"content-inset" inState:CPThemeStateBezeled]; - [textfield setValue:[CPFont systemFontOfSize:12.0] forThemedAttributeName:@"font"]; + [textfield setValue:CGInsetMake(4.0, 4.0, 3.0, 4.0) forThemeAttribute:@"bezel-inset" inState:CPThemeStateBezeled]; + [textfield setValue:CGInsetMake(0.0, 0.0, 0.0, 0.0) forThemeAttribute:@"bezel-inset" inState:CPThemeStateBezeled|CPThemeStateEditing]; - [textfield setValue:CGInsetMake(9.0, 8.0, 5.0, 7.0) forThemedAttributeName:@"content-inset" inControlState:CPControlStateBezeled]; - - [textfield setValue:CGInsetMake(4.0, 4.0, 3.0, 4.0) forThemedAttributeName:@"bezel-inset" inControlState:CPControlStateBezeled]; - [textfield setValue:CGInsetMake(0.0, 0.0, 0.0, 0.0) forThemedAttributeName:@"bezel-inset" inControlState:CPControlStateBezeled|CPControlStateEditing]; - - [textfield setValue:[CPColor colorWithCalibratedRed:189.0 / 255.0 green:199.0 / 255.0 blue:211.0 / 255.0 alpha:1.0] forThemedAttributeName:@"text-color" inControlState:CPTextFieldStatePlaceholder]; + [textfield setValue:[CPColor colorWithCalibratedRed:189.0 / 255.0 green:199.0 / 255.0 blue:211.0 / 255.0 alpha:1.0] forThemeAttribute:@"text-color" inState:CPTextFieldStatePlaceholder]; [textfield setPlaceholderString:"cheese cheese"]; [textfield setStringValue:""]; @@ -178,16 +176,16 @@ [textfield setBezeled:YES]; [textfield setBezelStyle:CPTextFieldRoundedBezel]; - [textfield setValue:bezelColor forThemedAttributeName:@"bezel-color" inControlState:CPControlStateBezeled | CPTextFieldStateRounded]; - [textfield setValue:bezelFocusedColor forThemedAttributeName:@"bezel-color" inControlState:CPControlStateBezeled | CPTextFieldStateRounded | CPControlStateEditing]; + [textfield setValue:bezelColor forThemeAttribute:@"bezel-color" inState:CPThemeStateBezeled | CPTextFieldStateRounded]; + [textfield setValue:bezelFocusedColor forThemeAttribute:@"bezel-color" inState:CPThemeStateBezeled | CPTextFieldStateRounded | CPThemeStateEditing]; - [textfield setValue:[CPFont systemFontOfSize:12.0] forThemedAttributeName:@"font"]; - [textfield setValue:CGInsetMake(9.0, 14.0, 6.0, 14.0) forThemedAttributeName:@"content-inset" inControlState:CPControlStateBezeled | CPTextFieldStateRounded]; + [textfield setValue:[CPFont systemFontOfSize:12.0] forThemeAttribute:@"font"]; + [textfield setValue:CGInsetMake(9.0, 14.0, 6.0, 14.0) forThemeAttribute:@"content-inset" inState:CPThemeStateBezeled | CPTextFieldStateRounded]; - [textfield setValue:CGInsetMake(4.0, 4.0, 4.0, 4.0) forThemedAttributeName:@"bezel-inset" inControlState:CPControlStateBezeled|CPTextFieldStateRounded]; - [textfield setValue:CGInsetMake(0.0, 0.0, 0.0, 0.0) forThemedAttributeName:@"bezel-inset" inControlState:CPControlStateBezeled|CPTextFieldStateRounded|CPControlStateEditing]; + [textfield setValue:CGInsetMake(4.0, 4.0, 4.0, 4.0) forThemeAttribute:@"bezel-inset" inState:CPThemeStateBezeled|CPTextFieldStateRounded]; + [textfield setValue:CGInsetMake(0.0, 0.0, 0.0, 0.0) forThemeAttribute:@"bezel-inset" inState:CPThemeStateBezeled|CPTextFieldStateRounded|CPThemeStateEditing]; - [textfield setValue:[CPColor colorWithCalibratedRed:189.0 / 255.0 green:199.0 / 255.0 blue:211.0 / 255.0 alpha:1.0] forThemedAttributeName:@"text-color" inControlState:CPTextFieldStatePlaceholder]; + [textfield setValue:[CPColor colorWithCalibratedRed:189.0 / 255.0 green:199.0 / 255.0 blue:211.0 / 255.0 alpha:1.0] forThemeAttribute:@"text-color" inState:CPTextFieldStatePlaceholder]; [textfield setPlaceholderString:"cheese cheese"]; [textfield setStringValue:""]; @@ -235,28 +233,29 @@ [button setTitle:@"Cancel"]; - [button setValue:[CPFont boldSystemFontOfSize:12.0] forThemedAttributeName:@"font" inControlState:CPControlStateBordered]; - [button setValue:[CPColor colorWithCalibratedWhite:79.0 / 255.0 alpha:1.0] forThemedAttributeName:@"text-color"]; - [button setValue:[CPColor colorWithCalibratedWhite:240.0 / 255.0 alpha:1.0] forThemedAttributeName:@"text-shadow-color" inControlState:CPControlStateBordered]; - [button setValue:CGSizeMake(0.0, 1.0) forThemedAttributeName:@"text-shadow-offset" inControlState:CPControlStateBordered]; - [button setValue:CPLineBreakByTruncatingTail forThemedAttributeName:@"line-break-mode"]; + [button setValue:[CPFont boldSystemFontOfSize:12.0] forThemeAttribute:@"font" inState:CPThemeStateBordered]; + [button setValue:[CPColor colorWithCalibratedWhite:79.0 / 255.0 alpha:1.0] forThemeAttribute:@"text-color"]; + [button setValue:[CPColor colorWithCalibratedWhite:240.0 / 255.0 alpha:1.0] forThemeAttribute:@"text-shadow-color" inState:CPThemeStateBordered]; + [button setValue:CGSizeMake(0.0, 1.0) forThemeAttribute:@"text-shadow-offset" inState:CPThemeStateBordered]; + [button setValue:CPLineBreakByTruncatingTail forThemeAttribute:@"line-break-mode"]; - [button setValue:bezelColor forThemedAttributeName:@"bezel-color" inControlState:CPControlStateBordered]; - [button setValue:highlightedBezelColor forThemedAttributeName:@"bezel-color" inControlState:CPControlStateBordered|CPControlStateHighlighted]; - [button setValue:CGInsetMake(0.0, 5.0, 0.0, 5.0) forThemedAttributeName:@"content-inset" inControlState:CPControlStateBordered]; + [button setValue:bezelColor forThemeAttribute:@"bezel-color" inState:CPThemeStateBordered]; + [button setValue:highlightedBezelColor forThemeAttribute:@"bezel-color" inState:CPThemeStateBordered|CPThemeStateHighlighted]; + [button setValue:CGInsetMake(0.0, 5.0, 0.0, 5.0) forThemeAttribute:@"content-inset" inState:CPThemeStateBordered]; - [button setValue:defaultBezelColor forThemedAttributeName:@"bezel-color" inControlState:CPControlStateBordered|CPControlStateDefault]; - [button setValue:defaultHighlightedBezelColor forThemedAttributeName:@"bezel-color" inControlState:CPControlStateBordered|CPControlStateHighlighted|CPControlStateDefault]; - [button setValue:[CPColor colorWithCalibratedRed:13.0/255.0 green:51.0/255.0 blue:70.0/255.0 alpha:1.0] forThemedAttributeName:@"text-color" inControlState:CPControlStateDefault]; + [button setValue:defaultBezelColor forThemeAttribute:@"bezel-color" inState:CPThemeStateBordered|CPThemeStateDefault]; + [button setValue:defaultHighlightedBezelColor forThemeAttribute:@"bezel-color" inState:CPThemeStateBordered|CPThemeStateHighlighted|CPThemeStateDefault]; + [button setValue:[CPColor colorWithCalibratedRed:13.0/255.0 green:51.0/255.0 blue:70.0/255.0 alpha:1.0] forThemeAttribute:@"text-color" inState:CPThemeStateDefault]; - [button setValue:24.0 forThemedAttributeName:@"default-height"]; + [button setValue:24.0 forThemeAttribute:@"default-height"]; return button; } + (CPPopUpButton)themedPopUpButton { - var button = [[CPPopUpButton alloc] initWithFrame:CGRectMake(0.0, 0.0, 100.0, 24.0) pullsDown:NO],color = [CPColor colorWithPatternImage:[[CPThreePartImage alloc] initWithImageSlices: + var button = [[CPPopUpButton alloc] initWithFrame:CGRectMake(0.0, 0.0, 100.0, 24.0) pullsDown:NO], + color = [CPColor colorWithPatternImage:[[CPThreePartImage alloc] initWithImageSlices: [ [_CPCibCustomResource imageResourceWithName:"button-bezel-left.png" size:CGSizeMake(4.0, 24.0)], [_CPCibCustomResource imageResourceWithName:"button-bezel-center.png" size:CGSizeMake(1.0, 24.0)], @@ -266,18 +265,43 @@ [button setTitle:@"Pop Up"]; - [button setValue:color forThemedAttributeName:@"bezel-color" inControlState:CPControlStateBordered]; - [button setValue:CGInsetMake(0, 5, 0, 27.0 + 5.0) forThemedAttributeName:@"content-inset" inControlState:CPControlStateBordered]; - [button setValue:[CPFont boldSystemFontOfSize:12.0] forThemedAttributeName:@"font"]; - [button setValue:[CPColor colorWithCalibratedWhite:79.0 / 255.0 alpha:1.0] forThemedAttributeName:@"text-color"]; - [button setValue:[CPColor colorWithCalibratedWhite:240.0 / 255.0 alpha:1.0] forThemedAttributeName:@"text-shadow-color"]; - [button setValue:CGSizeMake(0.0, 1.0) forThemedAttributeName:@"text-shadow-offset"]; + [button setValue:color forThemeAttribute:@"bezel-color" inState:CPThemeStateBordered]; + [button setValue:CGInsetMake(0, 5, 0, 27.0 + 5.0) forThemeAttribute:@"content-inset" inState:CPThemeStateBordered]; + [button setValue:[CPFont boldSystemFontOfSize:12.0] forThemeAttribute:@"font"]; + [button setValue:[CPColor colorWithCalibratedWhite:79.0 / 255.0 alpha:1.0] forThemeAttribute:@"text-color"]; + [button setValue:[CPColor colorWithCalibratedWhite:240.0 / 255.0 alpha:1.0] forThemeAttribute:@"text-shadow-color"]; + [button setValue:CGSizeMake(0.0, 1.0) forThemeAttribute:@"text-shadow-offset"]; [button addItemWithTitle:@"item"]; return button; } ++ (CPPopUpButton)themedPullDownMenu +{ + var button = [[CPPopUpButton alloc] initWithFrame:CGRectMake(0.0, 0.0, 100.0, 24.0) pullsDown:YES], + color = [CPColor colorWithPatternImage:[[CPThreePartImage alloc] initWithImageSlices: + [ + [_CPCibCustomResource imageResourceWithName:"button-bezel-left.png" size:CGSizeMake(4.0, 24.0)], + [_CPCibCustomResource imageResourceWithName:"button-bezel-center.png" size:CGSizeMake(1.0, 24.0)], + [_CPCibCustomResource imageResourceWithName:"popup-bezel-right-pullsdown.png" size:CGSizeMake(27.0, 24.0)] + ] + isVertical:NO]]; + + [button setTitle:@"Pop Up"]; + + [button setValue:color forThemeAttribute:@"bezel-color" inState:CPPopUpButtonStatePullsDown|CPThemeStateBordered]; + [button setValue:CGInsetMake(0, 5, 0, 27.0 + 5.0) forThemeAttribute:@"content-inset" inState:CPThemeStateBordered]; + [button setValue:[CPFont boldSystemFontOfSize:12.0] forThemeAttribute:@"font"]; + [button setValue:[CPColor colorWithCalibratedWhite:79.0 / 255.0 alpha:1.0] forThemeAttribute:@"text-color"]; + [button setValue:[CPColor colorWithCalibratedWhite:240.0 / 255.0 alpha:1.0] forThemeAttribute:@"text-shadow-color"]; + [button setValue:CGSizeMake(0.0, 1.0) forThemeAttribute:@"text-shadow-offset"]; + + [button addItemWithTitle:@"item"]; + + return button; +} + + (CPPopUpButton)themedSegmentedControl { var segmentedControl = [[CPSegmentedControl alloc] initWithFrame:CGRectMake(0.0, 0.0, 0.0, 24.0)]; @@ -298,87 +322,64 @@ [segmentedControl setTag:3 forSegment:2]; //various colors - var centerBezelColor = [CPColor colorWithPatternImage:[_CPCibCustomResource imageResourceWithName:@"segmented-control-bezel-center.png" size:CGSizeMake(1.0, 24.0)]], - dividerBezelColor = [CPColor colorWithPatternImage:[_CPCibCustomResource imageResourceWithName:@"segmented-control-bezel-divider.png" size:CGSizeMake(1.0, 24.0)]], - centerHighlightedBezelColor = [CPColor colorWithPatternImage:[_CPCibCustomResource imageResourceWithName:@"segmented-control-bezel-highlighted-center.png" size:CGSizeMake(1.0, 24.0)]], - dividerHighlightedBezelColor = [CPColor colorWithPatternImage:[_CPCibCustomResource imageResourceWithName:@"segmented-control-bezel-highlighted-divider.png" size:CGSizeMake(1.0, 24.0)]], - leftHighlightedBezelColor = [CPColor colorWithPatternImage:[_CPCibCustomResource imageResourceWithName:@"segmented-control-bezel-highlighted-left.png" size:CGSizeMake(4.0, 24.0)]], - rightHighlightedBezelColor = [CPColor colorWithPatternImage:[_CPCibCustomResource imageResourceWithName:@"segmented-control-bezel-highlighted-right.png" size:CGSizeMake(4.0, 24.0)]], - inactiveCenterBezelColor = [CPColor colorWithPatternImage:[_CPCibCustomResource imageResourceWithName:@"segmented-control-bezel-inactive-center.png" size:CGSizeMake(1.0, 24.0)]], - inactiveDividerBezelColor = [CPColor colorWithPatternImage:[_CPCibCustomResource imageResourceWithName:@"segmented-control-bezel-inactive-divider.png" size:CGSizeMake(1.0, 24.0)]], - inactiveLeftBezelColor = [CPColor colorWithPatternImage:[_CPCibCustomResource imageResourceWithName:@"segmented-control-bezel-inactive-left.png" size:CGSizeMake(4.0, 24.0)]], - inactiveRightBezelColor = [CPColor colorWithPatternImage:[_CPCibCustomResource imageResourceWithName:@"segmented-control-bezel-inactive-right.png" size:CGSizeMake(4.0, 24.0)]], - leftBezelColor = [CPColor colorWithPatternImage:[_CPCibCustomResource imageResourceWithName:@"segmented-control-bezel-left.png" size:CGSizeMake(4.0, 24.0)]], - rightBezelColor = [CPColor colorWithPatternImage:[_CPCibCustomResource imageResourceWithName:@"segmented-control-bezel-right.png" size:CGSizeMake(4.0, 24.0)]], - pushedCenterBezelColor = [CPColor colorWithPatternImage:[_CPCibCustomResource imageResourceWithName:@"segmented-control-bezel-pushed-center.png" size:CGSizeMake(1.0, 24.0)]], - pushedLeftBezelColor = [CPColor colorWithPatternImage:[_CPCibCustomResource imageResourceWithName:@"segmented-control-bezel-pushed-left.png" size:CGSizeMake(4.0, 24.0)]], - pushedRightBezelColor = [CPColor colorWithPatternImage:[_CPCibCustomResource imageResourceWithName:@"segmented-control-bezel-pushed-right.png" size:CGSizeMake(4.0, 24.0)]]; - pushedHighlightedCenterBezelColor = [CPColor colorWithPatternImage:[_CPCibCustomResource imageResourceWithName:@"segmented-control-bezel-pushed-highlighted-center.png" size:CGSizeMake(1.0, 24.0)]], - pushedHighlightedLeftBezelColor = [CPColor colorWithPatternImage:[_CPCibCustomResource imageResourceWithName:@"segmented-control-bezel-pushed-highlighted-left.png" size:CGSizeMake(4.0, 24.0)]], - pushedHighlightedRightBezelColor = [CPColor colorWithPatternImage:[_CPCibCustomResource imageResourceWithName:@"segmented-control-bezel-pushed-highlighted-right.png" size:CGSizeMake(4.0, 24.0)]]; + var centerBezelColor = PatternColor([_CPCibCustomResource imageResourceWithName:@"segmented-control-bezel-center.png" size:CGSizeMake(1.0, 24.0)]), + dividerBezelColor = PatternColor([_CPCibCustomResource imageResourceWithName:@"segmented-control-bezel-divider.png" size:CGSizeMake(1.0, 24.0)]), + centerHighlightedBezelColor = PatternColor([_CPCibCustomResource imageResourceWithName:@"segmented-control-bezel-highlighted-center.png" size:CGSizeMake(1.0, 24.0)]), + dividerHighlightedBezelColor = PatternColor([_CPCibCustomResource imageResourceWithName:@"segmented-control-bezel-highlighted-divider.png" size:CGSizeMake(1.0, 24.0)]), + leftHighlightedBezelColor = PatternColor([_CPCibCustomResource imageResourceWithName:@"segmented-control-bezel-highlighted-left.png" size:CGSizeMake(4.0, 24.0)]), + rightHighlightedBezelColor = PatternColor([_CPCibCustomResource imageResourceWithName:@"segmented-control-bezel-highlighted-right.png" size:CGSizeMake(4.0, 24.0)]), + inactiveCenterBezelColor = PatternColor([_CPCibCustomResource imageResourceWithName:@"segmented-control-bezel-inactive-center.png" size:CGSizeMake(1.0, 24.0)]), + inactiveDividerBezelColor = PatternColor([_CPCibCustomResource imageResourceWithName:@"segmented-control-bezel-inactive-divider.png" size:CGSizeMake(1.0, 24.0)]), + inactiveLeftBezelColor = PatternColor([_CPCibCustomResource imageResourceWithName:@"segmented-control-bezel-inactive-left.png" size:CGSizeMake(4.0, 24.0)]), + inactiveRightBezelColor = PatternColor([_CPCibCustomResource imageResourceWithName:@"segmented-control-bezel-inactive-right.png" size:CGSizeMake(4.0, 24.0)]), + leftBezelColor = PatternColor([_CPCibCustomResource imageResourceWithName:@"segmented-control-bezel-left.png" size:CGSizeMake(4.0, 24.0)]), + rightBezelColor = PatternColor([_CPCibCustomResource imageResourceWithName:@"segmented-control-bezel-right.png" size:CGSizeMake(4.0, 24.0)]), + pushedCenterBezelColor = PatternColor([_CPCibCustomResource imageResourceWithName:@"segmented-control-bezel-pushed-center.png" size:CGSizeMake(1.0, 24.0)]), + pushedLeftBezelColor = PatternColor([_CPCibCustomResource imageResourceWithName:@"segmented-control-bezel-pushed-left.png" size:CGSizeMake(4.0, 24.0)]), + pushedRightBezelColor = PatternColor([_CPCibCustomResource imageResourceWithName:@"segmented-control-bezel-pushed-right.png" size:CGSizeMake(4.0, 24.0)]); + pushedHighlightedCenterBezelColor = PatternColor([_CPCibCustomResource imageResourceWithName:@"segmented-control-bezel-pushed-highlighted-center.png" size:CGSizeMake(1.0, 24.0)]), + pushedHighlightedLeftBezelColor = PatternColor([_CPCibCustomResource imageResourceWithName:@"segmented-control-bezel-pushed-highlighted-left.png" size:CGSizeMake(4.0, 24.0)]), + pushedHighlightedRightBezelColor = PatternColor([_CPCibCustomResource imageResourceWithName:@"segmented-control-bezel-pushed-highlighted-right.png" size:CGSizeMake(4.0, 24.0)]); - [segmentedControl setValue:centerBezelColor forThemedAttributeName:@"center-segment-bezel-color" inControlState:CPControlStateNormal]; - [segmentedControl setValue:inactiveCenterBezelColor forThemedAttributeName:@"center-segment-bezel-color" inControlState:CPControlStateDisabled]; - [segmentedControl setValue:centerHighlightedBezelColor forThemedAttributeName:@"center-segment-bezel-color" inControlState:CPControlStateSelected]; - [segmentedControl setValue:pushedCenterBezelColor forThemedAttributeName:@"center-segment-bezel-color" inControlState:CPControlStateHighlighted]; - [segmentedControl setValue:pushedHighlightedCenterBezelColor forThemedAttributeName:@"center-segment-bezel-color" inControlState:CPControlStateHighlighted|CPControlStateSelected]; + [segmentedControl setValue:centerBezelColor forThemeAttribute:@"center-segment-bezel-color" inState:CPThemeStateNormal]; + [segmentedControl setValue:inactiveCenterBezelColor forThemeAttribute:@"center-segment-bezel-color" inState:CPThemeStateDisabled]; + [segmentedControl setValue:centerHighlightedBezelColor forThemeAttribute:@"center-segment-bezel-color" inState:CPThemeStateSelected]; + [segmentedControl setValue:pushedCenterBezelColor forThemeAttribute:@"center-segment-bezel-color" inState:CPThemeStateHighlighted]; + [segmentedControl setValue:pushedHighlightedCenterBezelColor forThemeAttribute:@"center-segment-bezel-color" inState:CPThemeStateHighlighted|CPThemeStateSelected]; - [segmentedControl setValue:dividerBezelColor forThemedAttributeName:@"divider-bezel-color" inControlState:CPControlStateNormal]; - [segmentedControl setValue:inactiveDividerBezelColor forThemedAttributeName:@"divider-bezel-color" inControlState:CPControlStateDisabled]; - [segmentedControl setValue:dividerHighlightedBezelColor forThemedAttributeName:@"divider-bezel-color" inControlState:CPControlStateSelected]; - [segmentedControl setValue:dividerBezelColor forThemedAttributeName:@"divider-bezel-color" inControlState:CPControlStateHighlighted]; + [segmentedControl setValue:dividerBezelColor forThemeAttribute:@"divider-bezel-color" inState:CPThemeStateNormal]; + [segmentedControl setValue:inactiveDividerBezelColor forThemeAttribute:@"divider-bezel-color" inState:CPThemeStateDisabled]; + [segmentedControl setValue:dividerHighlightedBezelColor forThemeAttribute:@"divider-bezel-color" inState:CPThemeStateSelected]; + [segmentedControl setValue:dividerBezelColor forThemeAttribute:@"divider-bezel-color" inState:CPThemeStateHighlighted]; - [segmentedControl setValue:rightBezelColor forThemedAttributeName:@"right-segment-bezel-color" inControlState:CPControlStateNormal]; - [segmentedControl setValue:inactiveRightBezelColor forThemedAttributeName:@"right-segment-bezel-color" inControlState:CPControlStateDisabled]; - [segmentedControl setValue:rightHighlightedBezelColor forThemedAttributeName:@"right-segment-bezel-color" inControlState:CPControlStateSelected]; - [segmentedControl setValue:pushedRightBezelColor forThemedAttributeName:@"right-segment-bezel-color" inControlState:CPControlStateHighlighted]; - [segmentedControl setValue:pushedHighlightedRightBezelColor forThemedAttributeName:@"right-segment-bezel-color" inControlState:CPControlStateHighlighted|CPControlStateSelected]; + [segmentedControl setValue:rightBezelColor forThemeAttribute:@"right-segment-bezel-color" inState:CPThemeStateNormal]; + [segmentedControl setValue:inactiveRightBezelColor forThemeAttribute:@"right-segment-bezel-color" inState:CPThemeStateDisabled]; + [segmentedControl setValue:rightHighlightedBezelColor forThemeAttribute:@"right-segment-bezel-color" inState:CPThemeStateSelected]; + [segmentedControl setValue:pushedRightBezelColor forThemeAttribute:@"right-segment-bezel-color" inState:CPThemeStateHighlighted]; + [segmentedControl setValue:pushedHighlightedRightBezelColor forThemeAttribute:@"right-segment-bezel-color" inState:CPThemeStateHighlighted|CPThemeStateSelected]; - [segmentedControl setValue:leftBezelColor forThemedAttributeName:@"left-segment-bezel-color" inControlState:CPControlStateNormal]; - [segmentedControl setValue:inactiveLeftBezelColor forThemedAttributeName:@"left-segment-bezel-color" inControlState:CPControlStateDisabled]; - [segmentedControl setValue:leftHighlightedBezelColor forThemedAttributeName:@"left-segment-bezel-color" inControlState:CPControlStateSelected]; - [segmentedControl setValue:pushedLeftBezelColor forThemedAttributeName:@"left-segment-bezel-color" inControlState:CPControlStateHighlighted]; - [segmentedControl setValue:pushedHighlightedLeftBezelColor forThemedAttributeName:@"left-segment-bezel-color" inControlState:CPControlStateHighlighted|CPControlStateSelected]; + [segmentedControl setValue:leftBezelColor forThemeAttribute:@"left-segment-bezel-color" inState:CPThemeStateNormal]; + [segmentedControl setValue:inactiveLeftBezelColor forThemeAttribute:@"left-segment-bezel-color" inState:CPThemeStateDisabled]; + [segmentedControl setValue:leftHighlightedBezelColor forThemeAttribute:@"left-segment-bezel-color" inState:CPThemeStateSelected]; + [segmentedControl setValue:pushedLeftBezelColor forThemeAttribute:@"left-segment-bezel-color" inState:CPThemeStateHighlighted]; + [segmentedControl setValue:pushedHighlightedLeftBezelColor forThemeAttribute:@"left-segment-bezel-color" inState:CPThemeStateHighlighted|CPThemeStateSelected]; - [segmentedControl setValue:CGInsetMake(0.0, 4.0, 0.0, 4.0) forThemedAttributeName:@"content-inset" inControlState:CPControlStateNormal]; + [segmentedControl setValue:CGInsetMake(0.0, 4.0, 0.0, 4.0) forThemeAttribute:@"content-inset" inState:CPThemeStateNormal]; - [segmentedControl setValue:CGInsetMake(0.0, 0.0, 0.0, 0.0) forThemedAttributeName:@"bezel-inset" inControlState:CPControlStateNormal]; + [segmentedControl setValue:CGInsetMake(0.0, 0.0, 0.0, 0.0) forThemeAttribute:@"bezel-inset" inState:CPThemeStateNormal]; - [segmentedControl setValue:[CPFont boldSystemFontOfSize:12.0] forThemedAttributeName:@"font"]; - [segmentedControl setValue:[CPColor colorWithCalibratedWhite:79.0 / 255.0 alpha:1.0] forThemedAttributeName:@"text-color"]; - [segmentedControl setValue:[CPColor colorWithCalibratedWhite:240.0 / 255.0 alpha:1.0] forThemedAttributeName:@"text-shadow-color"]; + [segmentedControl setValue:[CPFont boldSystemFontOfSize:12.0] forThemeAttribute:@"font"]; + [segmentedControl setValue:[CPColor colorWithCalibratedWhite:79.0 / 255.0 alpha:1.0] forThemeAttribute:@"text-color"]; + [segmentedControl setValue:[CPColor colorWithCalibratedWhite:240.0 / 255.0 alpha:1.0] forThemeAttribute:@"text-shadow-color"]; + [segmentedControl setValue:CGSizeMake(0.0, 1.0) forThemeAttribute:@"text-shadow-offset"]; + [segmentedControl setValue:CPLineBreakByTruncatingTail forThemeAttribute:@"line-break-mode"]; + + [segmentedControl setValue:1.0 forThemeAttribute:@"divider-thickness"]; + [segmentedControl setValue:24.0 forThemeAttribute:@"default-height"]; - [segmentedControl setValue:1.0 forThemedAttributeName:@"divider-thickness"]; - [segmentedControl setValue:24.0 forThemedAttributeName:@"default-height"]; - return segmentedControl; } -+ (CPPopUpButton)themedPullDownMenu -{ - var button = [[CPPopUpButton alloc] initWithFrame:CGRectMake(0.0, 0.0, 100.0, 24.0) pullsDown:YES], - color = [CPColor colorWithPatternImage:[[CPThreePartImage alloc] initWithImageSlices: - [ - [_CPCibCustomResource imageResourceWithName:"button-bezel-left.png" size:CGSizeMake(4.0, 24.0)], - [_CPCibCustomResource imageResourceWithName:"button-bezel-center.png" size:CGSizeMake(1.0, 24.0)], - [_CPCibCustomResource imageResourceWithName:"popup-bezel-right-pullsdown.png" size:CGSizeMake(27.0, 24.0)] - ] - isVertical:NO]]; - - [button setTitle:@"Pop Up"]; - - [button setValue:color forThemedAttributeName:@"bezel-color" inControlState:CPPopUpButtonStatePullsDown|CPControlStateBordered]; - [button setValue:CGInsetMake(0, 5, 0, 27.0 + 5.0) forThemedAttributeName:@"content-inset" inControlState:CPControlStateBordered]; - [button setValue:[CPFont boldSystemFontOfSize:12.0] forThemedAttributeName:@"font"]; - [button setValue:[CPColor colorWithCalibratedWhite:79.0 / 255.0 alpha:1.0] forThemedAttributeName:@"text-color"]; - [button setValue:[CPColor colorWithCalibratedWhite:240.0 / 255.0 alpha:1.0] forThemedAttributeName:@"text-shadow-color"]; - [button setValue:CGSizeMake(0.0, 1.0) forThemedAttributeName:@"text-shadow-offset"]; - - [button addItemWithTitle:@"item"]; - - return button; -} - + (CPSlider)themedHorizontalSlider { var slider = [[CPSlider alloc] initWithFrame:CGRectMake(0.0, 0.0, 50.0, 24.0)], @@ -390,15 +391,15 @@ ] isVertical:NO]]; - [slider setValue:5.0 forThemedAttributeName:@"track-width"]; - [slider setValue:trackColor forThemedAttributeName:@"track-color"]; + [slider setValue:5.0 forThemeAttribute:@"track-width"]; + [slider setValue:trackColor forThemeAttribute:@"track-color"]; var knobColor = [CPColor colorWithPatternImage:[_CPCibCustomResource imageResourceWithName:"knob.png" size:CGSizeMake(23.0, 24.0)]]; knobHighlightedColor = [CPColor colorWithPatternImage:[_CPCibCustomResource imageResourceWithName:"knob-highlighted.png" size:CGSizeMake(23.0, 24.0)]]; - [slider setValue:CGSizeMake(23.0, 24.0) forThemedAttributeName:@"knob-size"]; - [slider setValue:knobColor forThemedAttributeName:@"knob-color"]; - [slider setValue:knobHighlightedColor forThemedAttributeName:@"knob-color" inControlState:CPControlStateHighlighted]; + [slider setValue:CGSizeMake(23.0, 24.0) forThemeAttribute:@"knob-size"]; + [slider setValue:knobColor forThemeAttribute:@"knob-color"]; + [slider setValue:knobHighlightedColor forThemeAttribute:@"knob-color" inState:CPThemeStateHighlighted]; return slider; } @@ -414,15 +415,15 @@ ] isVertical:YES]]; - [slider setValue:5.0 forThemedAttributeName:@"track-width"]; - [slider setValue:trackColor forThemedAttributeName:@"track-color" inControlState:CPControlStateVertical]; + [slider setValue:5.0 forThemeAttribute:@"track-width"]; + [slider setValue:trackColor forThemeAttribute:@"track-color" inState:CPThemeStateVertical]; var knobColor = [CPColor colorWithPatternImage:[_CPCibCustomResource imageResourceWithName:"knob.png" size:CGSizeMake(23.0, 24.0)]]; knobHighlightedColor = [CPColor colorWithPatternImage:[_CPCibCustomResource imageResourceWithName:"knob-highlighted.png" size:CGSizeMake(23.0, 24.0)]]; - [slider setValue:CGSizeMake(23.0, 24.0) forThemedAttributeName:@"knob-size"]; - [slider setValue:knobColor forThemedAttributeName:@"knob-color"]; - [slider setValue:knobHighlightedColor forThemedAttributeName:@"knob-color" inControlState:CPControlStateHighlighted]; + [slider setValue:CGSizeMake(23.0, 24.0) forThemeAttribute:@"knob-size"]; + [slider setValue:knobColor forThemeAttribute:@"knob-color"]; + [slider setValue:knobHighlightedColor forThemeAttribute:@"knob-color" inState:CPThemeStateHighlighted]; return slider; } @@ -430,18 +431,17 @@ + (CPSlider)themedCircularSlider { var slider = [[CPSlider alloc] initWithFrame:CGRectMake(0.0, 0.0, 32.0, 32.0)], - trackColor = [CPColor colorWithPatternImage:[_CPCibCustomResource imageResourceWithName:"circularSliderBezel.png" size:CGSizeMake(32.0, 32.0)]]; + trackColor = PatternColor([_CPCibCustomResource imageResourceWithName:"circularSliderBezel.png" size:CGSizeMake(32.0, 32.0)]); [slider setSliderType:CPCircularSlider]; - [slider setValue:trackColor forThemedAttributeName:@"track-color" inControlState:CPControlStateCircular]; - [slider setValue:trackColor forThemedAttributeName:@"track-color" inControlState:CPControlStateCircular|CPControlStateVertical]; + [slider setValue:trackColor forThemeAttribute:@"track-color" inState:CPThemeStateCircular]; var knobColor = [CPColor colorWithPatternImage:[_CPCibCustomResource imageResourceWithName:"circularSliderKnob.png" size:CGSizeMake(5.0, 5.0)]], knobHighlightedColor = knobColor; - [slider setValue:CGSizeMake(5.0, 5.0) forThemedAttributeName:@"knob-size" inControlState:CPControlStateCircular]; - [slider setValue:knobColor forThemedAttributeName:@"knob-color" inControlState:CPControlStateCircular]; - [slider setValue:knobHighlightedColor forThemedAttributeName:@"knob-color" inControlState:CPControlStateCircular|CPControlStateHighlighted]; + [slider setValue:CGSizeMake(5.0, 5.0) forThemeAttribute:@"knob-size" inState:CPThemeStateCircular]; + [slider setValue:knobColor forThemeAttribute:@"knob-color" inState:CPThemeStateCircular]; + [slider setValue:knobHighlightedColor forThemeAttribute:@"knob-color" inState:CPThemeStateCircular|CPThemeStateHighlighted]; return slider; } @@ -456,7 +456,7 @@ ] isVertical:NO]]; - [buttonBar setValue:color forThemedAttributeName:@"bezel-color"]; + [buttonBar setValue:color forThemeAttribute:@"bezel-color"]; [buttonBar setNeedsLayout]; views.push(buttonBar); @@ -465,7 +465,7 @@ */ @end -function PatterColor(anImage) +function PatternColor(anImage) { return [CPColor colorWithPatternImage:anImage]; } diff --git a/AppKit/Tools/BlendKit/BKShowcaseController.j b/AppKit/Tools/BlendKit/BKShowcaseController.j index 885417f3e..23f198315 100644 --- a/AppKit/Tools/BlendKit/BKShowcaseController.j +++ b/AppKit/Tools/BlendKit/BKShowcaseController.j @@ -87,6 +87,10 @@ CPTextField _label; } +- (void)setSelected:(BOOL)isSelected +{ +} + - (void)setRepresentedObject:(id)anObject { if (!_label) diff --git a/AppKit/Tools/blend/main.j b/AppKit/Tools/blend/main.j index 4b6faf9cb..46556f71b 100644 --- a/AppKit/Tools/blend/main.j +++ b/AppKit/Tools/blend/main.j @@ -49,7 +49,7 @@ function main() cibFiles.push(argument); } } - + if (descriptorFiles.length === 0) return buildBlendFromCibFiles(cibFiles); @@ -57,26 +57,26 @@ function main() { var themeDescriptorClasses = BKThemeDescriptorClasses(), count = [themeDescriptorClasses count]; - + while (count--) { var theClass = themeDescriptorClasses[count], themeTemplate = [[AKThemeTemplate alloc] init]; - + [themeTemplate setValue:[theClass themeName] forKey:@"name"]; - - var objectTemplates = BKThemeObjectTemplatesForClass(theClass); + + var objectTemplates = BKThemeObjectTemplatesForClass(theClass), data = cibDataFromTopLevelObjects(objectTemplates.concat([themeTemplate])), temporaryCibFile = File.createTempFile("temp", ".cib"), temporaryCibFilePath = temporaryCibFile.getAbsolutePath(), writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(temporaryCibFilePath), "UTF-8")); - + writer.write([data string]); writer.close(); cibFiles.push(temporaryCibFilePath); } - + buildBlendFromCibFiles(cibFiles, outputFilePath, resourcesPath); }); } @@ -131,7 +131,7 @@ function buildBlendFromCibFiles(cibFiles, outputFilePath, resourcesPath) fileContents = [[CPKeyedArchiver archivedDataWithRootObject:theme] string]; replacedFiles.push(filePath); - + staticContent += MARKER_PATH + ';' + filePath.length + ';' + filePath + MARKER_TEXT + ';' + fileContents.length + ';' + fileContents; } @@ -182,7 +182,7 @@ function themeFromCibFile(aFile) var object = topLevelObjects[count]; templates = templates.concat([object blendThemeObjectTemplates]); - + if ([object isKindOfClass:[AKThemeTemplate class]]) theme = [[CPTheme alloc] initWithName:[object valueForKey:@"name"]]; } diff --git a/Foundation/CPDictionary.j b/Foundation/CPDictionary.j index a8fa19611..016759bca 100755 --- a/Foundation/CPDictionary.j +++ b/Foundation/CPDictionary.j @@ -547,10 +547,21 @@ var i = _keys.length; while (i--) - description += _keys[i] +":"+[_buckets[_keys[i]] description]+"\n"; - + { + description += _keys[i] + ":"; + + var object = _buckets[_keys[i]]; + + if (object && object.isa) + description += [object description]; + else + description += object; + + description += "\n"; + } + description += "}"; - + return description; } diff --git a/Foundation/CPKeyedUnarchiver.j b/Foundation/CPKeyedUnarchiver.j index d7c13930b..d646302b9 100644 --- a/Foundation/CPKeyedUnarchiver.j +++ b/Foundation/CPKeyedUnarchiver.j @@ -111,7 +111,7 @@ var _CPKeyedUnarchiverArrayClass = Ni */ + (void)initialize { - if (self != [CPKeyedUnarchiver class]) + if (self !== [CPKeyedUnarchiver class]) return; _CPKeyedUnarchiverArrayClass = [CPArray class]; diff --git a/Tools/nib2cib/NSControl.j b/Tools/nib2cib/NSControl.j index 2d86d9597..c6749b7b7 100644 --- a/Tools/nib2cib/NSControl.j +++ b/Tools/nib2cib/NSControl.j @@ -34,8 +34,6 @@ if (self) { - _controlState = CPControlStateNormal; - [self sendActionOn:CPLeftMouseUpMask]; var cell = [aCoder decodeObjectForKey:@"NSCell"]; diff --git a/Tools/nib2cib/NSTableColumn.j b/Tools/nib2cib/NSTableColumn.j index b92d90ef6..0fb2055d7 100644 --- a/Tools/nib2cib/NSTableColumn.j +++ b/Tools/nib2cib/NSTableColumn.j @@ -38,7 +38,7 @@ //var dataViewCell = [aCoder decodeObjectForKey:@"NSDataCell"]; _dataView = [[CPTextField alloc] initWithFrame:CPRectMakeZero()]; - [_dataView setValue:[CPColor whiteColor] forThemedAttributeName:"text-color" inControlState:CPControlStateHighlighted]; + [_dataView setValue:[CPColor whiteColor] forThemedAttributeName:"text-color" inControlState:CPThemeStateHighlighted]; //_headerView = [aCoder decodeObjectForKey:@"NSHeaderCell"]; _headerView = [[CPTextField alloc] initWithFrame:CPRectMakeZero()]; diff --git a/Tools/nib2cib/NSView.j b/Tools/nib2cib/NSView.j index c3717102a..1b5b5676c 100644 --- a/Tools/nib2cib/NSView.j +++ b/Tools/nib2cib/NSView.j @@ -93,8 +93,9 @@ } } - _themedAttributes = {}; - [self _loadThemedAttributes]; + _themeAttributes = {}; + _themeState = CPThemeStateNormal; + [self _loadThemeAttributes]; } return self;