Merge pull request #2371 from primalmotion/CPVisualEffectView

CPVisualEffectView & CPAppearance
This commit is contained in:
Alexandre Wilhelm
2015-08-18 15:15:03 -07:00
25 changed files with 1649 additions and 11 deletions
+3 -1
View File
@@ -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"
@@ -106,7 +107,8 @@
@import "CPView.j"
@import "CPViewAnimation.j"
@import "CPViewController.j"
@import "CPVisualEffectView.j"
@import "CPWebView.j"
@import "CPWindow.j"
@import "CPWindowController.j"
@import "CPWorkspace.j"
@import "CPWorkspace.j"
+162
View File
@@ -0,0 +1,162 @@
/*
* 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 <Foundation/Foundation.j>
@import "CPTheme.j"
CPAppearanceNameAqua = @"CPAppearanceNameAqua";
CPAppearanceNameLightContent = @"CPAppearanceNameLightContent";
CPAppearanceNameVibrantDark = @"CPAppearanceNameVibrantDark";
CPAppearanceNameVibrantLight = @"CPAppearanceNameVibrantLight";
var _CPAppearanceCurrent = nil,
_CPAppearancesRegistry = @{};
@protocol CPAppearanceCustomization <CPObject>
@required
- (CPAppearance)appearance;
- (void)setAppearance:(CPAppearance)appearance;
- (CPAppearance)effectiveAppearance;
- (void)setEffectiveAppearance:(CPAppearance)appearance;
@end
CPThemeStateAppearanceAqua = CPThemeState("appearance-aqua");
CPThemeStateAppearanceLightContent = CPThemeState("appearance-light-content");
CPThemeStateAppearanceVibrantLight = CPThemeState("appearance-vibrant-light");
CPThemeStateAppearanceVibrantDark = CPThemeState("appearance-vibrant-dark");
/*!
@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
*/
- (id)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
- (BOOL)isEqual:(id)anObject
{
if (![anObject isKindOfClass:CPAppearance])
return NO;
return self._name == anObject._name;
}
- (CPString)description
{
return @"<CPAppearance @" + [self UID] + @" name: " + _name + ">";
}
#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
+2
View File
@@ -112,6 +112,8 @@
- (void)awakeFromCib
{
[super awakeFromCib];
var view = [self superview],
subview = self;
+2
View File
@@ -1582,6 +1582,8 @@ var CPScrollViewContentViewKey = @"CPScrollViewContentView",
*/
- (void)awakeFromCib
{
[super awakeFromCib];
[self _updateScrollerStyle];
[self _updateCornerAndHeaderView];
}
+2
View File
@@ -529,6 +529,8 @@ var CPTabViewItemsKey = "CPTabViewItemsKey",
- (void)awakeFromCib
{
[super awakeFromCib];
// This cannot be run in initWithCoder because it might call selectTabViewItem:, which is
// not safe to call before the views of the tab views items are fully decoded.
[self _updateItems];
+1
View File
@@ -6394,6 +6394,7 @@ var CPTableViewDataSourceKey = @"CPTableViewDataSourceKey",
- (void)awakeFromCib
{
[super awakeFromCib];
[self setThemeState:CPThemeStateTableDataView];
}
+98 -4
View File
@@ -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,10 @@ var CPViewHighDPIDrawingEnabled = YES;
BOOL _toolTipInstalled;
BOOL _isObserving;
BOOL _allowsVibrancy @accessors(property=allowsVibrancy);
CPAppearance _appearance @accessors(getter=appearance);
CPAppearance _effectiveAppearance;
}
/*
@@ -327,6 +331,13 @@ var CPViewHighDPIDrawingEnabled = YES;
return nil;
}
- (void)awakeFromCib
{
[super awakeFromCib];
[self _recomputeAppearance];
}
- (id)init
{
return [self initWithFrame:CGRectMakeZero()];
@@ -839,9 +850,9 @@ var CPViewHighDPIDrawingEnabled = YES;
*/
- (void)viewDidMoveToSuperview
{
// if (_graphicsContext)
[self setNeedsDisplay:YES];
[self _recomputeAppearance];
[self setNeedsDisplay:YES];
}
/*!
@@ -3509,6 +3520,85 @@ setBoundsOrigin:
return (_ephemeralSubviewsForNames[aViewName] || nil);
}
@end
@implementation CPView (Appearance)
/*! Returns the receiver's appearance if any, or ask the superview and returns it.
*/
- (CPAppearance)effectiveAppearance
{
if (_appearance)
return _appearance;
return [_superview effectiveAppearance];
}
- (void)setAppearance:(CPAppearance)anAppearance
{
if ([_appearance isEqual:anAppearance])
return;
[self willChangeValueForKey:@"appearance"];
_appearance = anAppearance;
[self didChangeValueForKey:@"appearance"];
[self _recomputeAppearance];
}
/*! @ignore
*/
- (void)_recomputeAppearance
{
// if we don't have a themeState, it means
// the view is not decoding from a cib, so we just return.
// this method will be called again in awakeFromCib
if (!_themeState)
return;
var effectiveAppearance = [self effectiveAppearance];
if ([effectiveAppearance isEqual:[CPAppearance appearanceNamed:CPAppearanceNameAqua]])
{
[self setThemeState:CPThemeStateAppearanceAqua];
[self unsetThemeState:CPThemeStateAppearanceLightContent];
[self unsetThemeState:CPThemeStateAppearanceVibrantLight];
[self unsetThemeState:CPThemeStateAppearanceVibrantDark];
}
else if ([effectiveAppearance isEqual:[CPAppearance appearanceNamed:CPAppearanceNameLightContent]])
{
[self unsetThemeState:CPThemeStateAppearanceAqua];
[self setThemeState:CPThemeStateAppearanceLightContent];
[self unsetThemeState:CPThemeStateAppearanceVibrantLight];
[self unsetThemeState:CPThemeStateAppearanceVibrantDark];
}
else if ([effectiveAppearance isEqual:[CPAppearance appearanceNamed:CPAppearanceNameVibrantLight]])
{
[self unsetThemeState:CPThemeStateAppearanceAqua];
[self unsetThemeState:CPThemeStateAppearanceLightContent];
[self setThemeState:CPThemeStateAppearanceVibrantLight];
[self unsetThemeState:CPThemeStateAppearanceVibrantDark];
}
else if ([effectiveAppearance isEqual:[CPAppearance appearanceNamed:CPAppearanceNameVibrantDark]])
{
[self unsetThemeState:CPThemeStateAppearanceAqua];
[self unsetThemeState:CPThemeStateAppearanceLightContent];
[self unsetThemeState:CPThemeStateAppearanceVibrantLight];
[self setThemeState:CPThemeStateAppearanceVibrantDark];
}
else
{
[self unsetThemeState:CPThemeStateAppearanceAqua];
[self unsetThemeState:CPThemeStateAppearanceLightContent];
[self unsetThemeState:CPThemeStateAppearanceVibrantLight];
[self unsetThemeState:CPThemeStateAppearanceVibrantDark];
}
[_subviews makeObjectsPerformSelector:@selector(_recomputeAppearance)];
}
@end
var CPViewAutoresizingMaskKey = @"CPViewAutoresizingMask",
@@ -3531,7 +3621,8 @@ var CPViewAutoresizingMaskKey = @"CPViewAutoresizingMask",
CPReuseIdentifierKey = @"CPReuseIdentifierKey",
CPViewScaleKey = @"CPViewScaleKey",
CPViewSizeScaleKey = @"CPViewSizeScaleKey",
CPViewIsScaledKey = @"CPViewIsScaledKey";
CPViewIsScaledKey = @"CPViewIsScaledKey",
CPViewAppearanceKey = @"CPViewAppearanceKey";
@implementation CPView (CPCoding)
@@ -3646,6 +3737,8 @@ var CPViewAutoresizingMaskKey = @"CPViewAutoresizingMask",
_themeAttributes[attributeName] = CPThemeAttributeDecode(aCoder, attributeName, attributes[count], _theme, themeClass);
}
[self setAppearance:[aCoder decodeObjectForKey:CPViewAppearanceKey]];
[self setNeedsDisplay:YES];
[self setNeedsLayout];
}
@@ -3734,6 +3827,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
+231
View File
@@ -0,0 +1,231 @@
/*
* CPVisualEffectView.j
* AppKit
*
* Created by Antoine Mercadal.
* Copyright 2015, 280 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 <Foundation/Foundation.j>
@import "CPAppearance.j"
@import "CPView.j"
@typedef CPVisualEffectMaterial
CPVisualEffectMaterialAppearanceBased = 0;
CPVisualEffectMaterialLight = 1;
CPVisualEffectMaterialDark = 2;
CPVisualEffectMaterialTitlebar = 3;
@typedef CPVisualEffectBlendingMode
CPVisualEffectBlendingModeBehindWindow = 0;
CPVisualEffectBlendingModeWithinWindow = 1;
@typedef CPVisualEffectState
CPVisualEffectStateFollowsWindowActiveState = 0;
CPVisualEffectStateActive = 1;
CPVisualEffectStateInactive = 2;
/*! @ingroup appkit
Very naive implementation of CPVisualEffectView. This view allows
to use vibrancy effect. This is only working with Safari 9+ and the
support in Chrome/ium should come quite soon.
Using this class with a browser that doesn't support backdrop-filter
While still work, but you will not get the blurry effect.
*/
@implementation CPVisualEffectView : CPView
{
CPImage _maskImage @accessors(property=maskImage);
CPVisualEffectBlendingMode _blendingMode @accessors(property=blendingMode);
CPVisualEffectMaterial _material @accessors(property=material);
CPVisualEffectState _state @accessors(property=state);
}
#pragma mark -
#pragma mark Initialization
- (id)initWithFrame:(CGRect)aFrame
{
if (self = [super initWithFrame:aFrame])
{
_material = CPVisualEffectMaterialAppearanceBased;
_blendingMode = CPVisualEffectBlendingModeWithinWindow;
_state = CPVisualEffectStateFollowsWindowActiveState;
_appearance = [CPAppearance appearanceNamed:CPAppearanceNameVibrantDark];
}
return self;
}
#pragma mark -
#pragma mark CPVisualEffectView API
/*! Sets the appearance of the CPVisualEffectView.
Only CPAppearance named CPAppearanceNameVibrantDark or CPAppearanceNameVibrantLight are valid
@param anAppearance the CPAppearance.
*/
- (void)setAppearance:(CPAppearance)anAppearance
{
if (![self _validAppearance:anAppearance])
[CPException raise:CPInvalidArgumentException reason:"Appearance can only be CPAppearanceNameVibrantDark or CPAppearanceNameVibrantLight in CPVisualEffectView, but is " + anAppearance];
[super setAppearance:anAppearance];
[self _applyVibrancyState];
}
/*! Sets the received effect state.
Possible values:
<pre>
CPVisualEffectStateFollowsWindowActiveState (default)
CPVisualEffectStateActive
CPVisualEffectStateInactive
</pre>
*/
- (void)setState:(CPVisualEffectState)aState
{
if (_state == aState)
return;
[self willChangeValueForKey:"state"];
_state = aState;
[self didChangeValueForKey:"state"];
[self _applyVibrancyState];
}
#pragma mark -
#pragma mark Utilities
- (void)_setEffectEnabled:(BOOL)shouldEnable
{
var dark = [[self appearance] isEqual:[CPAppearance appearanceNamed:CPAppearanceNameVibrantDark]],
prop = CPBrowserStyleProperty("backdrop-filter"),
color = (dark ? [CPColor colorWithHexString:@"1e1e1e"] : [CPColor whiteColor]),
finalColor = shouldEnable ? [color colorWithAlphaComponent:0.6] : color;
[self setBackgroundColor:finalColor];
#if PLATFORM(DOM)
self._DOMElement.style[prop] = shouldEnable ? "blur(30px)" : nil;
#endif
}
- (void)_applyVibrancyState
{
switch (_state)
{
case CPVisualEffectStateFollowsWindowActiveState:
[self _setEffectEnabled:[self hasThemeState:CPThemeStateKeyWindow]];
break;
case CPVisualEffectStateActive:
[self _setEffectEnabled:YES];
break;
case CPVisualEffectStateInactive:
[self _setEffectEnabled:NO];
break;
}
}
- (BOOL)_validAppearance:(CPAppearance)anAppearance
{
return [anAppearance isEqual:[CPAppearance appearanceNamed:CPAppearanceNameVibrantDark]] || [anAppearance isEqual:[CPAppearance appearanceNamed:CPAppearanceNameVibrantLight]];
}
#pragma mark -
#pragma mark Overrides
- (BOOL)setThemeState:(ThemeState)aState
{
if (aState.isa && [aState isKindOfClass:CPArray])
aState = CPThemeState.apply(null, aState);
var r = [super setThemeState:aState];
if (r)
[self _applyVibrancyState];
return r;
}
- (BOOL)unsetThemeState:(ThemeState)aState
{
if (aState.isa && [aState isKindOfClass:CPArray])
aState = CPThemeState.apply(null, aState);
var r = [super unsetThemeState:aState];
if (r)
[self _applyVibrancyState];
return r;
}
- (void)viewDidMoveToSuperview
{
[super viewDidMoveToSuperview];
if (_superview)
[self _applyVibrancyState];
}
- (void)viewDidMoveToWindow
{
[super viewDidMoveToWindow];
if (_window)
[self _applyVibrancyState];
}
#pragma mark -
#pragma mark CPCoding
- (id)initWithCoder:(CPCoder)aCoder
{
if (self = [super initWithCoder:aCoder])
{
_blendingMode = [aCoder decodeIntForKey:@"_blendingMode"] || CPVisualEffectBlendingModeWithinWindow;
_maskImage = [aCoder decodeObjectForKey:@"_maskImage"];
_material = [aCoder decodeIntForKey:@"_material"] || CPVisualEffectMaterialAppearanceBased;
_state = [aCoder decodeIntForKey:@"_state"] || CPVisualEffectStateFollowsWindowActiveState;
}
return self;
}
- (void)encodeWithCoder:(CPCoder)aCoder
{
[super encodeWithCoder:aCoder];
[aCoder encodeObject:_maskImage forKey:@"_maskImage"];
[aCoder encodeInt:_blendingMode forKey:@"_blendingMode"];
[aCoder encodeInt:_material forKey:@"_material"];
[aCoder encodeInt:_state forKey:@"_state"];
}
@end
+2 -4
View File
@@ -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"];
+6 -1
View File
@@ -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
+106
View File
@@ -771,6 +771,112 @@ var methodCalled;
[self assert:nil equals:view._toolTipFunctionOut];
}
- (void)testAppearanceDefaultvalue
{
[self assert:nil equals:[view appearance]];
[self assertFalse:[view hasThemeState:CPThemeStateAppearanceVibrantDark]];
[self assertFalse:[view hasThemeState:CPThemeStateAppearanceVibrantLight]];
[self assert:nil equals:[view effectiveAppearance]];
}
- (void)testAppearanceWithVibrantDark
{
[view setAppearance:[CPAppearance appearanceNamed:CPAppearanceNameVibrantDark]];
[self assert:[CPAppearance appearanceNamed:CPAppearanceNameVibrantDark] equals:[view appearance]];
[self assert:[CPAppearance appearanceNamed:CPAppearanceNameVibrantDark] equals:[view effectiveAppearance]];
[self assertTrue:[view hasThemeState:CPThemeStateAppearanceVibrantDark]];
[self assertFalse:[view hasThemeState:CPThemeStateAppearanceVibrantLight]];
}
- (void)testAppearanceWithVibrantLight
{
[view setAppearance:[CPAppearance appearanceNamed:CPAppearanceNameVibrantLight]];
[self assert:[CPAppearance appearanceNamed:CPAppearanceNameVibrantLight] equals:[view appearance]];
[self assert:[CPAppearance appearanceNamed:CPAppearanceNameVibrantLight] equals:[view effectiveAppearance]];
[self assertTrue:[view hasThemeState:CPThemeStateAppearanceVibrantLight]];
[self assertFalse:[view hasThemeState:CPThemeStateAppearanceVibrantDark]];
}
- (void)testAppearanceReset
{
[view setAppearance:[CPAppearance appearanceNamed:CPAppearanceNameVibrantLight]];
[view setAppearance:nil];
[self assert:nil equals:[view appearance]];
[self assert:nil equals:[view effectiveAppearance]];
[self assertFalse:[view hasThemeState:CPThemeStateAppearanceVibrantLight]];
[self assertFalse:[view hasThemeState:CPThemeStateAppearanceVibrantDark]];
}
- (void)testEffectiveAppearance
{
var secondView = [[CPView alloc] initWithFrame:CGRectMakeZero()];
[view addSubview:secondView];
[self assert:nil equals:[secondView appearance]];
[view setAppearance:[CPAppearance appearanceNamed:CPAppearanceNameVibrantLight]];
[self assert:[CPAppearance appearanceNamed:CPAppearanceNameVibrantLight] equals:[secondView effectiveAppearance]];
}
- (void)testEffectiveAppearanceWithMovingViews
{
var viewA = [[CPView alloc] initWithFrame:CGRectMakeZero()],
viewB = [[CPView alloc] initWithFrame:CGRectMakeZero()];
[viewA setAppearance:[CPAppearance appearanceNamed:CPAppearanceNameVibrantLight]];
[viewB setAppearance:[CPAppearance appearanceNamed:CPAppearanceNameVibrantDark]];
[viewA addSubview:view];
[self assert:[CPAppearance appearanceNamed:CPAppearanceNameVibrantLight] equals:[view effectiveAppearance]];
[self assertTrue:[view hasThemeState:CPThemeStateAppearanceVibrantLight]];
[self assertFalse:[view hasThemeState:CPThemeStateAppearanceVibrantDark]];
[viewB addSubview:view];
[self assert:[CPAppearance appearanceNamed:CPAppearanceNameVibrantDark] equals:[view effectiveAppearance]];
[self assertFalse:[view hasThemeState:CPThemeStateAppearanceVibrantLight]];
[self assertTrue:[view hasThemeState:CPThemeStateAppearanceVibrantDark]];
}
- (void)testEffectiveAppearanceWithMovingViewHierarchy
{
var viewC = [[CPView alloc] initWithFrame:CGRectMakeZero()],
viewA = [[CPView alloc] initWithFrame:CGRectMakeZero()],
viewB = [[CPView alloc] initWithFrame:CGRectMakeZero()];
[view setAppearance:[CPAppearance appearanceNamed:CPAppearanceNameVibrantLight]];
[viewC setAppearance:[CPAppearance appearanceNamed:CPAppearanceNameVibrantDark]];
[viewA addSubview:viewB];
[view addSubview:viewA];
[self assert:[CPAppearance appearanceNamed:CPAppearanceNameVibrantLight] equals:[viewB effectiveAppearance]];
[viewC addSubview:viewA];
[self assert:[CPAppearance appearanceNamed:CPAppearanceNameVibrantDark] equals:[viewB effectiveAppearance]];
}
- (void)testEffectiveAppearanceReset
{
var viewA = [[CPView alloc] initWithFrame:CGRectMakeZero()],
viewB = [[CPView alloc] initWithFrame:CGRectMakeZero()];
[viewA setAppearance:[CPAppearance appearanceNamed:CPAppearanceNameVibrantLight]];
[viewB setAppearance:[CPAppearance appearanceNamed:CPAppearanceNameVibrantDark]];
[viewA addSubview:view];
[self assert:[CPAppearance appearanceNamed:CPAppearanceNameVibrantLight] equals:[view effectiveAppearance]];
[view removeFromSuperview];
[self assert:nil equals:[view effectiveAppearance]];
}
@end
@implementation CPLayoutView : CPView
@@ -0,0 +1,73 @@
/*
* AppController.j
* CPVisualEffectViewTest
*
* Created by You on August 13, 2015.
* Copyright 2015, Your Company All rights reserved.
*/
@import <Foundation/Foundation.j>
@import <AppKit/AppKit.j>
@implementation AppController : CPObject
{
@outlet CPWindow window;
@outlet CPVisualEffectView FXView1;
@outlet CPVisualEffectView FXView2;
@outlet CPVisualEffectView FXView3;
@outlet CPVisualEffectView FXView4;
@outlet CPVisualEffectView FXView5;
@outlet CPVisualEffectView FXView6;
@outlet CPTextField field1;
@outlet CPTextField field2;
@outlet CPTextField field3;
@outlet CPTextField field4;
@outlet CPTextField field5;
@outlet CPTextField field6;
@outlet CPButton button1;
@outlet CPButton button2;
@outlet CPButton button3;
@outlet CPButton button4;
@outlet CPButton button5;
@outlet CPButton button6;
}
- (void)applicationDidFinishLaunching:(CPNotification)aNotification
{
}
- (void)awakeFromCib
{
var fields = [field1, field2, field3, field4, field5, field6];
for (var i = [fields count] - 1; i >= 0; i--)
[fields[i] setValue:[CPColor whiteColor] forThemeAttribute:@"text-color" inState:CPThemeStateAppearanceVibrantDark];
var buttons = [button1, button2, button3, button4, button5, button6];
for (var i = [buttons count] - 1; i >= 0; i--)
{
[buttons[i] setValue:[CPColor colorWithHexString:@"f3f3f3"] forThemeAttribute:@"bezel-color" inState:CPThemeStateAppearanceVibrantLight];
[buttons[i] setValue:[CPColor colorWithHexString:@"333333"] forThemeAttribute:@"text-color" inState:CPThemeStateAppearanceVibrantLight];
[buttons[i] setValue:[CPColor clearColor] forThemeAttribute:@"text-shadow-color" inState:CPThemeStateAppearanceVibrantLight];
[buttons[i] setValue:[CPColor colorWithHexString:@"333333"] forThemeAttribute:@"bezel-color" inState:CPThemeStateAppearanceVibrantDark];
[buttons[i] setValue:[CPColor colorWithHexString:@"999"] forThemeAttribute:@"text-color" inState:CPThemeStateAppearanceVibrantDark];
[buttons[i] setValue:[CPColor clearColor] forThemeAttribute:@"text-shadow-color" inState:CPThemeStateAppearanceVibrantDark];
}
}
- (IBAction)switch:(id)aSender
{
var dark = [CPAppearance appearanceNamed:CPAppearanceNameVibrantDark],
light = [CPAppearance appearanceNamed:CPAppearanceNameVibrantLight],
appearance = ([[aSender effectiveAppearance] isEqual:dark]) ? light : dark;
[[aSender superview] setAppearance:appearance];
}
@end
@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Main cib file base name</key>
<string>MainMenu.cib</string>
<key>CPBundleName</key>
<string>CPVisualEffectViewTest</string>
<key>CPBundleVersion</key>
<string>1.0</string>
<key>CPHumanReadableCopyright</key>
<string>Copyright © 2015, Your Company All rights reserved.</string>
</dict>
</plist>
@@ -0,0 +1,184 @@
/*
* Jakefile
* CPVisualEffectViewTest
*
* Created by You on August 13, 2015.
* Copyright 2015, Your Company All rights reserved.
*/
var ENV = require("system").env,
FILE = require("file"),
JAKE = require("jake"),
task = JAKE.task,
FileList = JAKE.FileList,
app = require("cappuccino/jake").app,
configuration = ENV["CONFIG"] || ENV["CONFIGURATION"] || ENV["c"] || "Debug",
OS = require("os"),
projectName = "CPVisualEffectViewTest";
app (projectName, function(task)
{
ENV["OBJJ_INCLUDE_PATHS"] = "Frameworks";
if (configuration === "Debug")
ENV["OBJJ_INCLUDE_PATHS"] = FILE.join(ENV["OBJJ_INCLUDE_PATHS"], configuration);
task.setBuildIntermediatesPath(FILE.join("Build", "CPVisualEffectViewTest.build", configuration));
task.setBuildPath(FILE.join("Build", configuration));
task.setProductName("CPVisualEffectViewTest");
task.setIdentifier("com.yourcompany.CPVisualEffectViewTest");
task.setVersion("1.0");
task.setAuthor("Your Company");
task.setEmail("feedback @nospam@ yourcompany.com");
task.setSummary("CPVisualEffectViewTest");
task.setSources(new FileList("**/*.j").exclude(FILE.join("Build", "**")).exclude(FILE.join("Frameworks", "Source", "**")));
task.setResources(new FileList("Resources/**"));
task.setIndexFilePath("index.html");
task.setInfoPlistPath("Info.plist");
if (configuration === "Debug")
task.setCompilerFlags("-DDEBUG -g");
else
task.setCompilerFlags("-O");
});
task ("default", [projectName], function()
{
printResults(configuration);
});
task ("build", ["default"], function()
{
updateApplicationSize();
});
task ("debug", function()
{
configuration = ENV["CONFIGURATION"] = "Debug";
JAKE.subjake(["."], "build", ENV);
});
task ("release", function()
{
configuration = ENV["CONFIGURATION"] = "Release";
JAKE.subjake(["."], "build", ENV);
});
task ("run", ["debug"], function()
{
OS.system(["open", FILE.join("Build", "Debug", projectName, "index.html")]);
});
task ("run-release", ["release"], function()
{
OS.system(["open", FILE.join("Build", "Release", projectName, "index.html")]);
});
task ("deploy", ["release"], function()
{
FILE.mkdirs(FILE.join("Build", "Deployment", projectName));
OS.system(["press", "-f", FILE.join("Build", "Release", projectName), FILE.join("Build", "Deployment", projectName)]);
printResults("Deployment")
});
task ("desktop", ["release"], function()
{
FILE.mkdirs(FILE.join("Build", "Desktop", projectName));
require("cappuccino/nativehost").buildNativeHost(FILE.join("Build", "Release", projectName), FILE.join("Build", "Desktop", projectName, "CPVisualEffectViewTest.app"));
printResults("Desktop")
});
task ("run-desktop", ["desktop"], function()
{
OS.system([FILE.join("Build", "Desktop", projectName, "CPVisualEffectViewTest.app", "Contents", "MacOS", "NativeHost"), "-i"]);
});
function printResults(configuration)
{
print("----------------------------");
print(configuration+" app built at path: "+FILE.join("Build", configuration, projectName));
print("----------------------------");
}
function updateApplicationSize()
{
print("Calculating application file sizes...");
var contents = FILE.read(FILE.join("Build", configuration, projectName, "Info.plist"), { charset:"UTF-8" }),
format = CFPropertyList.sniffedFormatOfString(contents),
plist = CFPropertyList.propertyListFromString(contents),
totalBytes = {executable:0, data:0, mhtml:0};
// Get the size of all framework executables and sprite data
var frameworksDir = "Frameworks";
if (configuration === "Debug")
frameworksDir = FILE.join(frameworksDir, "Debug");
var frameworks = FILE.list(frameworksDir);
frameworks.forEach(function(framework)
{
if (framework !== "Source")
addBundleFileSizes(FILE.join(frameworksDir, framework), totalBytes);
});
// Read in the default theme name, and attempt to get its size
var themeName = plist.valueForKey("CPDefaultTheme") || "Aristo2",
themePath = nil;
if (themeName === "Aristo" || themeName === "Aristo2")
themePath = FILE.join(frameworksDir, "AppKit", "Resources", themeName + ".blend");
else
themePath = FILE.join("Frameworks", "Resources", themeName + ".blend");
if (FILE.isDirectory(themePath))
addBundleFileSizes(themePath, totalBytes);
// Add sizes for the app
addBundleFileSizes(FILE.join("Build", configuration, projectName), totalBytes);
print("Executables: " + totalBytes.executable + ", sprite data: " + totalBytes.data + ", total: " + (totalBytes.executable + totalBytes.data));
var dict = new CFMutableDictionary();
dict.setValueForKey("executable", totalBytes.executable);
dict.setValueForKey("data", totalBytes.data);
dict.setValueForKey("mhtml", totalBytes.mhtml);
plist.setValueForKey("CPApplicationSize", dict);
FILE.write(FILE.join("Build", configuration, projectName, "Info.plist"), CFPropertyList.stringFromPropertyList(plist, format), { charset:"UTF-8" });
}
function addBundleFileSizes(bundlePath, totalBytes)
{
var bundleName = FILE.basename(bundlePath),
environment = bundleName === "Foundation" ? "Objj" : "Browser",
bundlePath = FILE.join(bundlePath, environment + ".environment");
if (FILE.isDirectory(bundlePath))
{
var filename = bundleName + ".sj",
filePath = new FILE.Path(FILE.join(bundlePath, filename));
if (filePath.exists())
totalBytes.executable += filePath.size();
filePath = new FILE.Path(FILE.join(bundlePath, "dataURLs.txt"));
if (filePath.exists())
totalBytes.data += filePath.size();
filePath = new FILE.Path(FILE.join(bundlePath, "MHTMLData.txt"));
if (filePath.exists())
totalBytes.mhtml += filePath.size();
filePath = new FILE.Path(FILE.join(bundlePath, "MHTMLPaths.txt"));
if (filePath.exists())
totalBytes.mhtml += filePath.size();
}
}
File diff suppressed because one or more lines are too long
@@ -0,0 +1,271 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="8173.3" systemVersion="15A244d" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none">
<dependencies>
<deployment version="1050" identifier="macosx"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="8173.3"/>
</dependencies>
<objects>
<customObject id="-2" userLabel="File's Owner" customClass="NSApplication">
<connections>
<outlet property="delegate" destination="450" id="451"/>
</connections>
</customObject>
<customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
<customObject id="-3" userLabel="Application" customClass="NSObject"/>
<customObject id="450" customClass="AppController">
<connections>
<outlet property="FXView1" destination="ESw-Mt-ZuS" id="9sp-kM-oA6"/>
<outlet property="FXView2" destination="ofy-S7-rCf" id="B5s-ei-PSM"/>
<outlet property="FXView3" destination="GcT-Xr-eCB" id="xb2-nI-t3Q"/>
<outlet property="FXView4" destination="xEz-ym-SoC" id="65y-hT-xuH"/>
<outlet property="FXView5" destination="X1I-rR-BOD" id="xRm-BO-MOM"/>
<outlet property="FXView6" destination="kpQ-qE-hkl" id="7gx-CZ-I5a"/>
<outlet property="button1" destination="8UZ-6M-ugH" id="HW6-M8-eVe"/>
<outlet property="button2" destination="rsT-2n-bIX" id="2te-bR-PMa"/>
<outlet property="button3" destination="22y-1h-QPQ" id="7ba-up-1UD"/>
<outlet property="button4" destination="lT3-jQ-tgV" id="fW4-Gk-FbR"/>
<outlet property="button5" destination="PbX-4k-5V8" id="Snb-TO-Hda"/>
<outlet property="button6" destination="xCh-Ei-U1y" id="GR3-p9-foJ"/>
<outlet property="field1" destination="drG-ES-sje" id="NGY-iR-BAD"/>
<outlet property="field2" destination="YjR-CK-WeJ" id="e1I-sz-QB1"/>
<outlet property="field3" destination="V0w-c6-mp4" id="jcP-xb-IVG"/>
<outlet property="field4" destination="oRu-hV-Fpl" id="Ifr-Ft-x2d"/>
<outlet property="field5" destination="eA4-la-pyn" id="O1i-2s-6tS"/>
<outlet property="field6" destination="x9a-RT-bcS" id="YrX-y5-Fqc"/>
<outlet property="window" destination="371" id="7nV-eB-gc9"/>
</connections>
</customObject>
<window title="Window" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" oneShot="NO" releasedWhenClosed="NO" showsToolbarButton="NO" frameAutosaveName="" animationBehavior="default" id="Knp-iN-1Ch">
<windowStyleMask key="styleMask" titled="YES" closable="YES" miniaturizable="YES" resizable="YES"/>
<windowPositionMask key="initialPositionMask" leftStrut="YES" rightStrut="YES" topStrut="YES" bottomStrut="YES"/>
<rect key="contentRect" x="100" y="722" width="181" height="67"/>
<rect key="screenRect" x="0.0" y="0.0" width="1440" height="877"/>
<view key="contentView" id="KQ2-1g-9W7">
<rect key="frame" x="0.0" y="0.0" width="181" height="67"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" id="d7y-fN-bjP">
<rect key="frame" x="18" y="25" width="145" height="17"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<animations/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Click me to loose focus" id="eKf-xB-TJp">
<font key="font" metaFont="system"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
</subviews>
<animations/>
</view>
<point key="canvasLocation" x="146.5" y="111.5"/>
</window>
<window title="Window" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" releasedWhenClosed="NO" animationBehavior="default" id="371">
<windowStyleMask key="styleMask" titled="YES" closable="YES" miniaturizable="YES"/>
<rect key="contentRect" x="335" y="178" width="834" height="545"/>
<rect key="screenRect" x="0.0" y="0.0" width="1440" height="877"/>
<view key="contentView" id="372">
<rect key="frame" x="0.0" y="0.0" width="834" height="545"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<imageView horizontalHuggingPriority="251" verticalHuggingPriority="251" id="WJS-cx-TuA">
<rect key="frame" x="0.0" y="0.0" width="834" height="545"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<animations/>
<imageCell key="cell" refusesFirstResponder="YES" alignment="left" imageScaling="proportionallyUpOrDown" image="background" id="asL-vN-HqR"/>
</imageView>
<visualEffectView appearanceType="vibrantLight" blendingMode="behindWindow" state="followsWindowActiveState" id="ESw-Mt-ZuS">
<rect key="frame" x="87" y="276" width="215" height="254"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<subviews>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" id="drG-ES-sje">
<rect key="frame" x="18" y="110" width="179" height="34"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<animations/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="center" id="f01-C4-Fhw">
<font key="font" metaFont="systemBold"/>
<string key="title">Vibrant Light
Follows Key Window</string>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<button verticalHuggingPriority="750" id="8UZ-6M-ugH">
<rect key="frame" x="67" y="13" width="81" height="32"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<animations/>
<buttonCell key="cell" type="push" title="Switch" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="71z-vZ-VTZ">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<action selector="switch:" target="450" id="gIr-5T-Rzf"/>
</connections>
</button>
</subviews>
<animations/>
</visualEffectView>
<visualEffectView appearanceType="vibrantLight" blendingMode="behindWindow" state="active" id="ofy-S7-rCf">
<rect key="frame" x="310" y="276" width="215" height="254"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<subviews>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" id="YjR-CK-WeJ">
<rect key="frame" x="18" y="110" width="179" height="34"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<animations/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="center" id="0ce-BE-k8L">
<font key="font" metaFont="systemBold"/>
<string key="title">Vibrant Light
Active</string>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<button verticalHuggingPriority="750" id="rsT-2n-bIX">
<rect key="frame" x="67" y="13" width="81" height="32"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<animations/>
<buttonCell key="cell" type="push" title="Switch" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="W6T-T4-5FW">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<action selector="switch:" target="450" id="Uaa-H7-ZYy"/>
</connections>
</button>
</subviews>
<animations/>
</visualEffectView>
<visualEffectView appearanceType="vibrantDark" blendingMode="behindWindow" state="active" id="X1I-rR-BOD">
<rect key="frame" x="310" y="14" width="215" height="254"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<subviews>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" id="eA4-la-pyn">
<rect key="frame" x="18" y="110" width="179" height="34"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<animations/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="center" id="16n-7u-pbb">
<font key="font" metaFont="systemBold"/>
<string key="title">Vibrant Dark
Active</string>
<color key="textColor" name="textColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<button verticalHuggingPriority="750" id="PbX-4k-5V8">
<rect key="frame" x="67" y="13" width="81" height="32"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<animations/>
<buttonCell key="cell" type="push" title="Switch" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="2is-6O-MxB">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<action selector="switch:" target="450" id="tSS-p5-usa"/>
</connections>
</button>
</subviews>
<animations/>
</visualEffectView>
<visualEffectView appearanceType="vibrantLight" blendingMode="behindWindow" state="inactive" id="GcT-Xr-eCB">
<rect key="frame" x="533" y="276" width="215" height="254"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<subviews>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" id="V0w-c6-mp4">
<rect key="frame" x="18" y="110" width="179" height="34"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<animations/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="center" id="Apx-Ho-9sT">
<font key="font" metaFont="systemBold"/>
<string key="title">Vibrant Light
Inactive</string>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<button verticalHuggingPriority="750" id="22y-1h-QPQ">
<rect key="frame" x="67" y="13" width="81" height="32"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<animations/>
<buttonCell key="cell" type="push" title="Switch" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="skm-xt-1Tf">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<action selector="switch:" target="450" id="h8T-E1-iI8"/>
</connections>
</button>
</subviews>
<animations/>
</visualEffectView>
<visualEffectView appearanceType="vibrantDark" blendingMode="behindWindow" state="inactive" id="kpQ-qE-hkl">
<rect key="frame" x="533" y="14" width="215" height="254"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<subviews>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" id="x9a-RT-bcS">
<rect key="frame" x="18" y="110" width="179" height="34"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<animations/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="center" id="b25-G9-HOg">
<font key="font" metaFont="systemBold"/>
<string key="title">Vibrant Dark
Inactive</string>
<color key="textColor" name="textColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<button verticalHuggingPriority="750" id="xCh-Ei-U1y">
<rect key="frame" x="67" y="13" width="81" height="32"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<animations/>
<buttonCell key="cell" type="push" title="Switch" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="GUB-yD-5Mr">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<action selector="switch:" target="450" id="SEg-XC-jHs"/>
</connections>
</button>
</subviews>
<animations/>
</visualEffectView>
<visualEffectView appearanceType="vibrantDark" blendingMode="behindWindow" state="followsWindowActiveState" id="xEz-ym-SoC">
<rect key="frame" x="87" y="14" width="215" height="254"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<subviews>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" id="oRu-hV-Fpl">
<rect key="frame" x="18" y="110" width="179" height="34"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<animations/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="center" id="ff0-As-8T5">
<font key="font" metaFont="systemBold"/>
<string key="title">Vibrant Dark
Follows Key Window</string>
<color key="textColor" name="textColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<button verticalHuggingPriority="750" id="lT3-jQ-tgV">
<rect key="frame" x="67" y="13" width="81" height="32"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<animations/>
<buttonCell key="cell" type="push" title="Switch" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="sNu-BP-dFg">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<action selector="switch:" target="450" id="nyO-Ie-Hgv"/>
</connections>
</button>
</subviews>
<animations/>
</visualEffectView>
</subviews>
<animations/>
</view>
<point key="canvasLocation" x="713" y="374.5"/>
</window>
</objects>
<resources>
<image name="background" width="245.75999450683594" height="160.32000732421875"/>
</resources>
</document>
Binary file not shown.

After

Width:  |  Height:  |  Size: 187 KiB

@@ -0,0 +1,191 @@
<!DOCTYPE html>
<html lang="en">
<!--
index-debug.html
CPVisualEffectViewTest
Created by You on August 13, 2015.
Copyright 2015, Your Company All rights reserved.
-->
<head>
<meta charset="utf-8">
<!--[if lte IE 8]>
<meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7, chrome=1">
<![endif]-->
<!--[if gte IE 9]>
<meta http-equiv="X-UA-Compatible" content="IE=edge, chrome=1">
<![endif]-->
<meta name="viewport" content="initial-scale=1.0, user-scalable=no">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black">
<link rel="apple-touch-icon" href="Resources/icon.png">
<link rel="apple-touch-startup-image" href="Resources/default.png">
<title>CPVisualEffectViewTest</title>
<!-- Custom javascript goes here -->
<!-- End custom javascript -->
<script type="text/javascript">
OBJJ_MAIN_FILE = "main.j";
OBJJ_INCLUDE_PATHS = ["Frameworks/Debug", "Frameworks"];
var progressBar = null;
OBJJ_PROGRESS_CALLBACK = function(percent, appSize, path)
{
percent = percent * 100;
if (!progressBar)
progressBar = document.getElementById("progress-bar");
if (progressBar)
progressBar.style.width = Math.min(percent, 100) + "%";
}
var loadingHTML =
'<div id="loading">' +
' <div id="loading-text">Loading...</div>' +
' <div id="progress-indicator">' +
' <span id="progress-bar" style="width:0%"></span>' +
' </div>' +
'</div>';
</script>
<script type="text/javascript" src="Frameworks/Debug/Objective-J/Objective-J.js" charset="UTF-8"></script>
<script type="text/javascript">
objj_msgSend_reset();
// DEBUG OPTIONS:
// Uncomment to enable printing of backtraces on exceptions:
//objj_msgSend_decorate(objj_backtrace_decorator);
// Uncomment to supress exceptions that take place inside a message
//objj_msgSend_decorate(objj_supress_exceptions_decorator)
// Uncomment to enable runtime type checking:
//objj_msgSend_decorate(objj_typecheck_decorator);
// Uncomment (along with both above) to print backtraces on type check errors:
//objj_typecheck_prints_backtrace = true;
// Uncomment to disable the default logger (CPLogConsole if window.console exists, CPLogPopup otherwise):
//CPLogUnregister(CPLogDefault);
// Uncomment to enable a specific logger:
//CPLogRegister(CPLogConsole);
//CPLogRegister(CPLogPopup);
// Tag view DOM elements with a "data-cappuccino-view" attribute that contains
// the class name of the view that created them. Comment this or set to false to disable.
appkit_tag_dom_elements = true;
</script>
<style type="text/css">
html, body, h1, p {
margin: 0;
padding: 0;
}
/* We need a body wrapper because Cappuccino is unhappy if we change the body element */
#cappuccino-body {
/* Position it absolutely so it will fill the height without content */
position: absolute;
top: 0;
bottom: 0;
width: 100%;
/* Put it at the bottom of the stack so it doesn't interfere with UI */
z-index: 0;
}
#cappuccino-body .container {
display: table;
margin: 0 auto;
height: 100%;
}
#cappuccino-body .content {
display: table-cell;
height: 100%;
vertical-align: top;
}
#loading {
position: relative;
top: 35%;
}
#loading-text {
height: 1.5em;
color: #555;
font: normal bold 36px/36px Arial, sans-serif;
}
#progress-indicator {
padding: 0px;
height: 16px;
border: 5px solid #555;
border-radius: 18px;
background-color: white;
}
#progress-bar {
position: relative;
top: -1px;
left: -1px;
display: block;
height: 18px;
/* Compensate for moving the bar left 1px to overlap the indicator border */
border-right: 1px solid #555;
background-color: #555;
}
#noscript {
position: relative;
top: 35%;
padding: 1em 1.5em;
border: 5px solid #555;
border-radius: 16px;
background-color: white;
color: #555;
text-align: center;
font: bold 24px Arial, sans-serif;
}
#noscript a {
color: #98c0ff;
text-decoration: none;
}
</style>
</head>
<body>
<div id="cappuccino-body">
<div class="container">
<div class="content">
<script type="text/javascript">
document.write(loadingHTML);
</script>
</div>
</div>
<noscript style="position:absolute; top:0; left:0; width:100%; height:100%">
<div class="container">
<div class="content">
<div id="noscript">
<p style="font-size:120%; margin-bottom:.75em">JavaScript is required for this site.</p>
<p><a href="http://www.enable-javascript.com" target="_blank">Enable JavaScript</a></p>
</div>
</div>
</div>
</noscript>
</div>
</body>
</html>
@@ -0,0 +1,161 @@
<!DOCTYPE html>
<html lang="en">
<!--
index.html
CPVisualEffectViewTest
Created by You on August 13, 2015.
Copyright 2015, Your Company All rights reserved.
-->
<head>
<meta charset="utf-8">
<!--[if lte IE 8]>
<meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7, chrome=1">
<![endif]-->
<!--[if gte IE 9]>
<meta http-equiv="X-UA-Compatible" content="IE=edge, chrome=1">
<![endif]-->
<meta name="viewport" content="initial-scale=1.0, user-scalable=no">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black">
<link rel="apple-touch-icon" href="Resources/icon.png">
<link rel="apple-touch-startup-image" href="Resources/default.png">
<title>CPVisualEffectViewTest</title>
<!-- Custom javascript goes here -->
<!-- End custom javascript -->
<script type="text/javascript">
OBJJ_MAIN_FILE = "main.j";
var progressBar = null;
OBJJ_PROGRESS_CALLBACK = function(percent, appSize, path)
{
percent = percent * 100;
if (!progressBar)
progressBar = document.getElementById("progress-bar");
if (progressBar)
progressBar.style.width = Math.min(percent, 100) + "%";
}
var loadingHTML =
'<div id="loading">' +
' <div id="loading-text">Loading...</div>' +
' <div id="progress-indicator">' +
' <span id="progress-bar" style="width:0%"></span>' +
' </div>' +
'</div>';
</script>
<script type="text/javascript" src="Frameworks/Objective-J/Objective-J.js" charset="UTF-8"></script>
<style type="text/css">
html, body, h1, p {
margin: 0;
padding: 0;
}
/* We need a body wrapper because Cappuccino is unhappy if we change the body element */
#cappuccino-body {
/* Position it absolutely so it will fill the height without content */
position: absolute;
top: 0;
bottom: 0;
width: 100%;
/* Put it at the bottom of the stack so it doesn't interfere with UI */
z-index: 0;
}
#cappuccino-body .container {
display: table;
margin: 0 auto;
height: 100%;
}
#cappuccino-body .content {
display: table-cell;
height: 100%;
vertical-align: top;
}
#loading {
position: relative;
top: 35%;
}
#loading-text {
height: 1.5em;
color: #555;
font: normal bold 36px/36px Arial, sans-serif;
}
#progress-indicator {
padding: 0px;
height: 16px;
border: 5px solid #555;
border-radius: 18px;
background-color: white;
}
#progress-bar {
position: relative;
top: -1px;
left: -1px;
display: block;
height: 18px;
/* Compensate for moving the bar left 1px to overlap the indicator border */
border-right: 1px solid #555;
background-color: #555;
}
#noscript {
position: relative;
top: 35%;
padding: 1em 1.5em;
border: 5px solid #555;
border-radius: 16px;
background-color: white;
color: #555;
text-align: center;
font: bold 24px Arial, sans-serif;
}
#noscript a {
color: #98c0ff;
text-decoration: none;
}
</style>
</head>
<body>
<div id="cappuccino-body">
<div class="container">
<div class="content">
<script type="text/javascript">
document.write(loadingHTML);
</script>
</div>
</div>
<noscript style="position:absolute; top:0; left:0; width:100%; height:100%">
<div class="container">
<div class="content">
<div id="noscript">
<p style="font-size:120%; margin-bottom:.75em">JavaScript is required for this site.</p>
<p><a href="http://www.enable-javascript.com" target="_blank">Enable JavaScript</a></p>
</div>
</div>
</div>
</noscript>
</div>
</body>
</html>
@@ -0,0 +1,18 @@
/*
* AppController.j
* CPVisualEffectViewTest
*
* Created by You on August 13, 2015.
* Copyright 2015, Your Company All rights reserved.
*/
@import <Foundation/Foundation.j>
@import <AppKit/AppKit.j>
@import "AppController.j"
function main(args, namedArgs)
{
CPApplicationMain(args, namedArgs);
}
+2
View File
@@ -88,6 +88,8 @@
@import "NSSortDescriptor.j"
@import "NSPopover.j"
@import "NSProgressIndicator.j"
@import "NSAppearance.j"
@import "NSVisualEffectView.j"
function CP_NSMapClassName(aClassName)
+52
View File
@@ -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 <AppKit/CPAppearance.j>
@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
+1
View File
@@ -52,6 +52,7 @@ var NSViewAutoresizingMask = 0x3F,
_window = [aCoder decodeObjectForKey:@"NSWindow"];
_superview = [aCoder decodeObjectForKey:@"NSSuperview"];
_subviews = [aCoder decodeObjectForKey:@"NSSubviews"];
_appearance = [aCoder decodeObjectForKey:@"NSAppearance"];
_hierarchyScaleSize = CGSizeMake(1.0 , 1.0);
_scaleSize = CGSizeMake(1.0, 1.0);
+57
View File
@@ -0,0 +1,57 @@
/*
* NSVisualEffectView.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 <AppKit/CPVisualEffectView.j>
@implementation CPVisualEffectView (NSCoding)
- (id)NS_initWithCoder:(CPCoder)aCoder
{
if (self = [super NS_initWithCoder:aCoder])
{
_material = [aCoder decodeObjectForKey:@"NSVisualEffectViewMaterial"];
_state = [aCoder decodeObjectForKey:@"NSVisualEffectViewState"];
// this is not supported
// _blendingMode = [aCoder decodeObjectForKey:@"NSVisualEffectViewBlendingMode"];
_blendingMode = CPVisualEffectBlendingModeWithinWindow;
}
return self;
}
@end
@implementation NSVisualEffectView : CPVisualEffectView
- (id)initWithCoder:(CPCoder)aCoder
{
return [self NS_initWithCoder:aCoder];
}
- (Class)classForKeyedArchiver
{
return [CPVisualEffectView class];
}
@end
+3 -1
View File
@@ -604,5 +604,7 @@ var NSClasses = {
"NSWindow" : YES,
"NSWindowController" : YES,
"NSWorkspace" : YES,
"NSPopover": YES
"NSPopover": YES,
"NSAppearance" : YES,
"NSVisualEffectView" : YES,
};