diff --git a/AppKit/AppKit.j b/AppKit/AppKit.j index bada5344d..e73d58c53 100644 --- a/AppKit/AppKit.j +++ b/AppKit/AppKit.j @@ -26,6 +26,7 @@ @import "CPAccordionView.j" @import "CPAlert.j" @import "CPAnimation.j" +@import "CPAppearance.j" @import "CPApplication.j" @import "CPArrayController.j" @import "CPBezierPath.j" @@ -109,4 +110,4 @@ @import "CPWebView.j" @import "CPWindow.j" @import "CPWindowController.j" -@import "CPWorkspace.j" +@import "CPWorkspace.j" \ No newline at end of file diff --git a/AppKit/CPAppearance.j b/AppKit/CPAppearance.j new file mode 100644 index 000000000..6c57a8d7d --- /dev/null +++ b/AppKit/CPAppearance.j @@ -0,0 +1,148 @@ +/* + * CPAppearance.j + * AppKit + * + * Created by Antoine Mercadal. + * Copyright 2015, Cappuccino Project. + * + * 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 + +CPAppearanceNameAqua = @"CPAppearanceNameAqua"; +CPAppearanceNameLightContent = @"CPAppearanceNameLightContent"; +CPAppearanceNameVibrantDark = @"CPAppearanceNameVibrantDark"; +CPAppearanceNameVibrantLight = @"CPAppearanceNameVibrantLight"; + +var _CPAppearanceCurrent = nil, + _CPAppearancesRegistry = @{}; + + +@protocol CPAppearanceCustomization + +@required +- (CPAppearance)appearance; +- (void)setAppearance:(CPAppearance)appearance; +- (CPAppearance)effectiveAppearance; +- (void)setEffectiveAppearance:(CPAppearance)appearance; + +@end + + +/*! + @ingroup appkit + + A CPAppareance represents the appearance of an to a subset of UI elements. + This is a very lightweight implementation of the NSAppearance system, but + We are using it for compliance, and especially for the CPVisualEffectView +*/ +@implementation CPAppearance : CPObject +{ + BOOL _allowsVibrancy @accessors(property=allowsVibrancy); + + CPString _name; +} + + +#pragma mark - +#pragma mark Class Methods + +/*! Returns the current default CPAppearance +*/ ++ (CPAppearance)currentAppearance +{ + if (!_CPAppearanceCurrent) + _CPAppearanceCurrent = [CPAppearance appearanceNamed:CPAppearanceNameAqua]; + + return _CPAppearanceCurrent; +} + +/*! Sets the current default CPAppearance + @param appearance the new current appearance +*/ ++ (void)setCurrentAppearance:(CPAppearance)anAppearance +{ + _CPAppearanceCurrent = anAppearance; +} + +/*! Returns the CPAppearance object with the given name + @param name the name of the appearance +*/ ++ (CPAppearance)appearanceNamed:(CPString)aName +{ + if (![_CPAppearancesRegistry containsKey:aName]) + { + [_CPAppearancesRegistry setObject:[[CPAppearance alloc] initWithAppearanceNamed:aName bundle:nil] + forKey:aName]; + } + + return [_CPAppearancesRegistry objectForKey:aName]; +} + + +#pragma mark - +#pragma mark Initialization + +/*! Creates a CPAppearance object initialized to the specified appearance file in the specified bundle + This method does actually nothing special. It just creates a default appearance object +*/ +- initWithAppearanceNamed:(CPString)aName bundle:(CPBundle)bundle +{ + if (self = [super init]) + { + _name = aName; + _allowsVibrancy = YES; + + if ([_CPAppearancesRegistry containsKey:aName]) + [CPException raise:CPInternalInconsistencyException reason:"Appearance with name '" + aName + "' is already declared."]; + + [_CPAppearancesRegistry setObject:self forKey:aName]; + } + + return self; +} + + +#pragma mark - +#pragma mark Implementation + +- (CPString)description +{ + return @""; +} + + +#pragma mark - +#pragma mark CPCoding + +- (id)initWithCoder:(CPCoder)aCoder +{ + if (self = [super init]) + { + _name = [aCoder decodeObjectForKey:@"_name"]; + _allowsVibrancy = [aCoder decodeBoolForKey:@"_allowsVibrancy"]; + } + + return self; +} + +- (void)encodeWithCoder:(CPCoder)aCoder +{ + [aCoder encodeObject:_name forKey:@"_name"]; + [aCoder encodeBool:_allowsVibrancy forKey:@"_allowsVibrancy"]; +} + +@end \ No newline at end of file diff --git a/AppKit/CPView.j b/AppKit/CPView.j index 36ed408bb..250291471 100644 --- a/AppKit/CPView.j +++ b/AppKit/CPView.j @@ -26,6 +26,7 @@ @import "CGAffineTransform.j" @import "CGGeometry.j" +@import "CPAppearance.j" @import "CPColor.j" @import "CPGraphicsContext.j" @import "CPResponder.j" @@ -131,7 +132,6 @@ var CPViewFlags = { }, var CPViewHighDPIDrawingEnabled = YES; - /*! @ingroup appkit @class CPView @@ -240,6 +240,9 @@ var CPViewHighDPIDrawingEnabled = YES; BOOL _toolTipInstalled; BOOL _isObserving; + + BOOL _allowsVibrancy @accessors(property=allowsVibrancy); + CPAppearance _appearance @accessors(property=appearance); } /* @@ -3511,6 +3514,24 @@ setBoundsOrigin: @end + +@implementation CPView (Appeatance) + +/*! Returns the received appearance if any, or ask the superview and returns it. +*/ +- (CPAppearance)effectiveAppearance +{ + if (_appearance) + return _appearance; + + if (_superview) + return [_superview appearance]; + + return nil; +} + +@end + var CPViewAutoresizingMaskKey = @"CPViewAutoresizingMask", CPViewAutoresizesSubviewsKey = @"CPViewAutoresizesSubviews", CPViewBackgroundColorKey = @"CPViewBackgroundColor", @@ -3531,7 +3552,8 @@ var CPViewAutoresizingMaskKey = @"CPViewAutoresizingMask", CPReuseIdentifierKey = @"CPReuseIdentifierKey", CPViewScaleKey = @"CPViewScaleKey", CPViewSizeScaleKey = @"CPViewSizeScaleKey", - CPViewIsScaledKey = @"CPViewIsScaledKey"; + CPViewIsScaledKey = @"CPViewIsScaledKey", + CPViewAppearanceKey = @"CPViewAppearanceKey"; @implementation CPView (CPCoding) @@ -3646,6 +3668,8 @@ var CPViewAutoresizingMaskKey = @"CPViewAutoresizingMask", _themeAttributes[attributeName] = CPThemeAttributeDecode(aCoder, attributeName, attributes[count], _theme, themeClass); } + _appearance = [aCoder decodeObjectForKey:CPViewAppearanceKey]; + [self setNeedsDisplay:YES]; [self setNeedsLayout]; } @@ -3734,6 +3758,7 @@ var CPViewAutoresizingMaskKey = @"CPViewAutoresizingMask", [aCoder encodeSize:[self scaleSize] forKey:CPViewScaleKey]; [aCoder encodeSize:[self _hierarchyScaleSize] forKey:CPViewSizeScaleKey]; [aCoder encodeBool:_isScaled forKey:CPViewIsScaledKey]; + [aCoder encodeObject:_appearance forKey:CPViewAppearanceKey]; } @end diff --git a/AppKit/CPWindow/_CPPopoverWindowView.j b/AppKit/CPWindow/_CPPopoverWindowView.j index b337be625..aeba11f8a 100644 --- a/AppKit/CPWindow/_CPPopoverWindowView.j +++ b/AppKit/CPWindow/_CPPopoverWindowView.j @@ -26,7 +26,6 @@ @import "CGGradient.j" @import "_CPWindowView.j" -@global CPPopoverAppearanceMinimal var _CPPopoverWindowViewDefaultCursorSize = CGSizeMake(16, 10); @@ -39,7 +38,6 @@ var _CPPopoverWindowViewDefaultCursorSize = CGSizeMake(16, 10); { float _arrowOffsetX @accessors(property=arrowOffsetX); float _arrowOffsetY @accessors(property=arrowOffsetY); - int _appearance @accessors(property=appearance); unsigned _preferredEdge @accessors(property=preferredEdge); CGSize _cursorSize; @@ -123,7 +121,7 @@ var _CPPopoverWindowViewDefaultCursorSize = CGSizeMake(16, 10); { _arrowOffsetX = 0.0; _arrowOffsetY = 0.0; - _appearance = CPPopoverAppearanceMinimal; + _appearance = [CPAppearance appearanceNamed:CPAppearanceNameVibrantLight]; _cursorSize = CGSizeMakeCopy(_CPPopoverWindowViewDefaultCursorSize); } @@ -168,7 +166,7 @@ var _CPPopoverWindowViewDefaultCursorSize = CGSizeMake(16, 10); gradient, frame = [self bounds]; - if (_appearance == CPPopoverAppearanceMinimal) + if ([_appearance isEqual:[CPAppearance appearanceNamed:CPAppearanceNameVibrantLight]]) { gradient = [self valueForThemeAttribute:@"background-gradient"]; strokeColor = [self valueForThemeAttribute:@"stroke-color"]; diff --git a/AppKit/_CPPopoverWindow.j b/AppKit/_CPPopoverWindow.j index 4aa1f4c0e..443109c18 100644 --- a/AppKit/_CPPopoverWindow.j +++ b/AppKit/_CPPopoverWindow.j @@ -141,7 +141,12 @@ var _CPPopoverWindow_shouldClose_ = 1 << 4, if (_appearance === anAppearance) return; - [_windowView setAppearance:anAppearance]; + _appearance = anAppearance; + + var appearanceName = _appearance == CPPopoverAppearanceMinimal ? CPAppearanceNameVibrantLight : CPAppearanceNameVibrantDark, + viewAppearance = [CPAppearance appearanceNamed:appearanceName]; + + [_windowView setAppearance:viewAppearance]; } - (void)setStyleMask:(unsigned)aStyleMask diff --git a/Tools/nib2cib/NSAppKit.j b/Tools/nib2cib/NSAppKit.j index 8dbc498ee..691872013 100644 --- a/Tools/nib2cib/NSAppKit.j +++ b/Tools/nib2cib/NSAppKit.j @@ -88,6 +88,7 @@ @import "NSSortDescriptor.j" @import "NSPopover.j" @import "NSProgressIndicator.j" +@import "NSAppearance.j" function CP_NSMapClassName(aClassName) diff --git a/Tools/nib2cib/NSAppearance.j b/Tools/nib2cib/NSAppearance.j new file mode 100644 index 000000000..fc5f62b4d --- /dev/null +++ b/Tools/nib2cib/NSAppearance.j @@ -0,0 +1,52 @@ +/* + * NSAppearance.j + * nib2cib + * + * Created by Antoine Mercadal. + * Copyright 2015, Cappuccino Project + * + * 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 + + +@implementation CPAppearance (NSCoding) + +- (id)NS_initWithCoder:(CPCoder)aCoder +{ + if (self = [super init]) + { + _name = [aCoder decodeObjectForKey:@"NSAppearanceName"].replace(/^NS/, "CP"); + } + + return self; +} + +@end + +@implementation NSAppearance : CPAppearance + +- (id)initWithCoder:(CPCoder)aCoder +{ + return [self NS_initWithCoder:aCoder]; +} + +- (Class)classForKeyedArchiver +{ + return [CPAppearance class]; +} + +@end diff --git a/Tools/objj2objcskeleton/objj2objcskeleton b/Tools/objj2objcskeleton/objj2objcskeleton index c855c5c54..7ddcfa419 100644 --- a/Tools/objj2objcskeleton/objj2objcskeleton +++ b/Tools/objj2objcskeleton/objj2objcskeleton @@ -604,5 +604,6 @@ var NSClasses = { "NSWindow" : YES, "NSWindowController" : YES, "NSWorkspace" : YES, - "NSPopover": YES + "NSPopover": YES, + "NSAppearance" : YES };