Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[ASDisplayNode] Allow setting stretchable contents on nodes; add bridged properties. #trivial #429

Merged
merged 1 commit into from
Jul 9, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 27 additions & 19 deletions Source/ASDisplayNode.h
Original file line number Diff line number Diff line change
Expand Up @@ -621,29 +621,32 @@ extern NSInteger const ASDefaultDrawingPriority;
*/
- (void)layoutIfNeeded;

@property (nonatomic, strong, nullable) id contents; // default=nil
@property (nonatomic, assign) CGRect frame; // default=CGRectZero
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should definitely do additional cleanup in this header. However, I made a few improvements (no breaking changes of course) so that the most commonly used properties are more towards the top and more logically grouped.

Because this is still pretty far from ideal, let's not worry too much about optimizing it in this patch - but at least it will be slightly better until we get around to it.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

@property (nonatomic, assign) CGRect bounds; // default=CGRectZero
@property (nonatomic, assign) CGPoint position; // default=CGPointZero
@property (nonatomic, assign) CGFloat alpha; // default=1.0f

@property (nonatomic, assign) BOOL clipsToBounds; // default==NO
@property (nonatomic, getter=isHidden) BOOL hidden; // default==NO
@property (nonatomic, getter=isOpaque) BOOL opaque; // default==YES

@property (nonatomic, assign) BOOL allowsGroupOpacity;
@property (nonatomic, assign) BOOL allowsEdgeAntialiasing;
@property (nonatomic, assign) unsigned int edgeAntialiasingMask; // default==all values from CAEdgeAntialiasingMask
@property (nonatomic, strong, nullable) id contents; // default=nil
@property (nonatomic, assign) CGRect contentsRect; // default={0,0,1,1}. @see CALayer.h for details.
@property (nonatomic, assign) CGRect contentsCenter; // default={0,0,1,1}. @see CALayer.h for details.
@property (nonatomic, assign) CGFloat contentsScale; // default=1.0f. See @contentsScaleForDisplay for details.
@property (nonatomic, assign) CGFloat rasterizationScale; // default=1.0f.

@property (nonatomic, getter=isHidden) BOOL hidden; // default==NO
@property (nonatomic, assign) BOOL needsDisplayOnBoundsChange; // default==NO
@property (nonatomic, assign) BOOL autoresizesSubviews; // default==YES (undefined for layer-backed nodes)
@property (nonatomic, assign) UIViewAutoresizing autoresizingMask; // default==UIViewAutoresizingNone (undefined for layer-backed nodes)
@property (nonatomic, assign) CGFloat alpha; // default=1.0f
@property (nonatomic, assign) CGRect bounds; // default=CGRectZero
@property (nonatomic, assign) CGRect frame; // default=CGRectZero
@property (nonatomic, assign) CGPoint anchorPoint; // default={0.5, 0.5}
@property (nonatomic, assign) CGFloat zPosition; // default=0.0
@property (nonatomic, assign) CGPoint position; // default=CGPointZero
@property (nonatomic, assign) CGFloat cornerRadius; // default=0.0
@property (nonatomic, assign) CGFloat contentsScale; // default=1.0f. See @contentsScaleForDisplay for more info
@property (nonatomic, assign) CATransform3D transform; // default=CATransform3DIdentity
@property (nonatomic, assign) CATransform3D subnodeTransform; // default=CATransform3DIdentity

@property (nonatomic, assign, getter=isUserInteractionEnabled) BOOL userInteractionEnabled; // default=YES (NO for layer-backed nodes)
#if TARGET_OS_IOS
@property (nonatomic, assign, getter=isExclusiveTouch) BOOL exclusiveTouch; // default=NO
#endif

/**
* @abstract The node view's background color.
*
Expand All @@ -652,8 +655,8 @@ extern NSInteger const ASDefaultDrawingPriority;
*/
@property (nonatomic, strong, nullable) UIColor *backgroundColor; // default=nil

@property (nonatomic, strong, null_resettable) UIColor *tintColor; // default=Blue
- (void)tintColorDidChange; // Notifies the node when the tintColor has changed.
@property (nonatomic, strong, null_resettable) UIColor *tintColor; // default=Blue
- (void)tintColorDidChange; // Notifies the node when the tintColor has changed.

/**
* @abstract A flag used to determine how a node lays out its content when its bounds change.
Expand All @@ -664,19 +667,24 @@ extern NSInteger const ASDefaultDrawingPriority;
* contentMode for your content while it's being re-rendered.
*/
@property (nonatomic, assign) UIViewContentMode contentMode; // default=UIViewContentModeScaleToFill
@property (nonatomic, copy) NSString *contentsGravity; // Use .contentMode in preference when possible.
@property (nonatomic, assign) UISemanticContentAttribute semanticContentAttribute; // default=Unspecified

@property (nonatomic, assign, getter=isUserInteractionEnabled) BOOL userInteractionEnabled; // default=YES (NO for layer-backed nodes)
#if TARGET_OS_IOS
@property (nonatomic, assign, getter=isExclusiveTouch) BOOL exclusiveTouch; // default=NO
#endif
@property (nonatomic, nullable) CGColorRef shadowColor; // default=opaque rgb black
@property (nonatomic, assign) CGFloat shadowOpacity; // default=0.0
@property (nonatomic, assign) CGSize shadowOffset; // default=(0, -3)
@property (nonatomic, assign) CGFloat shadowRadius; // default=3
@property (nonatomic, assign) CGFloat borderWidth; // default=0
@property (nonatomic, nullable) CGColorRef borderColor; // default=opaque rgb black

@property (nonatomic, assign) BOOL allowsGroupOpacity;
@property (nonatomic, assign) BOOL allowsEdgeAntialiasing;
@property (nonatomic, assign) unsigned int edgeAntialiasingMask; // default==all values from CAEdgeAntialiasingMask

@property (nonatomic, assign) BOOL needsDisplayOnBoundsChange; // default==NO
@property (nonatomic, assign) BOOL autoresizesSubviews; // default==YES (undefined for layer-backed nodes)
@property (nonatomic, assign) UIViewAutoresizing autoresizingMask; // default==UIViewAutoresizingNone (undefined for layer-backed nodes)

// UIResponder methods
// By default these fall through to the underlying view, but can be overridden.
- (BOOL)canBecomeFirstResponder; // default==NO
Expand Down
2 changes: 1 addition & 1 deletion Source/ASDisplayNode.mm
Original file line number Diff line number Diff line change
Expand Up @@ -2442,7 +2442,7 @@ - (void)_locked_setupPlaceholderLayerIfNeeded
if (_placeholderImage) {
BOOL stretchable = !UIEdgeInsetsEqualToEdgeInsets(_placeholderImage.capInsets, UIEdgeInsetsZero);
if (stretchable) {
ASDisplayNodeSetupLayerContentsWithResizableImage(_placeholderLayer, _placeholderImage);
ASDisplayNodeSetResizableContents(_placeholderLayer, _placeholderImage);
} else {
_placeholderLayer.contentsScale = self.contentsScale;
_placeholderLayer.contents = (id)_placeholderImage.CGImage;
Expand Down
6 changes: 5 additions & 1 deletion Source/Details/UIView+ASConvenience.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,13 @@ NS_ASSUME_NONNULL_BEGIN
@property (nonatomic, assign) CGPoint position;
@property (nonatomic, assign) CGFloat zPosition;
@property (nonatomic, assign) CGPoint anchorPoint;
@property (nullable, nonatomic, strong) id contents;
@property (nonatomic, assign) CGFloat cornerRadius;
@property (nullable, nonatomic, strong) id contents;
@property (nonatomic, copy) NSString *contentsGravity;
@property (nonatomic, assign) CGRect contentsRect;
@property (nonatomic, assign) CGRect contentsCenter;
@property (nonatomic, assign) CGFloat contentsScale;
@property (nonatomic, assign) CGFloat rasterizationScale;
@property (nonatomic, assign) CATransform3D transform;
@property (nonatomic, assign) CATransform3D sublayerTransform;
@property (nonatomic, assign) BOOL needsDisplayOnBoundsChange;
Expand Down
2 changes: 1 addition & 1 deletion Source/Private/ASDisplayNode+AsyncDisplay.mm
Original file line number Diff line number Diff line change
Expand Up @@ -341,7 +341,7 @@ - (void)displayAsyncLayer:(_ASDisplayLayer *)asyncLayer asynchronously:(BOOL)asy
UIImage *image = (UIImage *)value;
BOOL stretchable = (NO == UIEdgeInsetsEqualToEdgeInsets(image.capInsets, UIEdgeInsetsZero));
if (stretchable) {
ASDisplayNodeSetupLayerContentsWithResizableImage(layer, image);
ASDisplayNodeSetResizableContents(layer, image);
} else {
layer.contentsScale = self.contentsScale;
layer.contents = (id)image.CGImage;
Expand Down
48 changes: 48 additions & 0 deletions Source/Private/ASDisplayNode+UIViewBridge.mm
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,42 @@ - (void)setCornerRadius:(CGFloat)newCornerRadius
_setToLayer(cornerRadius, newCornerRadius);
}

- (NSString *)contentsGravity
{
_bridge_prologue_read;
return _getFromLayer(contentsGravity);
}

- (void)setContentsGravity:(NSString *)newContentsGravity
{
_bridge_prologue_write;
_setToLayer(contentsGravity, newContentsGravity);
}

- (CGRect)contentsRect
{
_bridge_prologue_read;
return _getFromLayer(contentsRect);
}

- (void)setContentsRect:(CGRect)newContentsRect
{
_bridge_prologue_write;
_setToLayer(contentsRect, newContentsRect);
}

- (CGRect)contentsCenter
{
_bridge_prologue_read;
return _getFromLayer(contentsCenter);
}

- (void)setContentsCenter:(CGRect)newContentsCenter
{
_bridge_prologue_write;
_setToLayer(contentsCenter, newContentsCenter);
}

- (CGFloat)contentsScale
{
_bridge_prologue_read;
Expand All @@ -207,6 +243,18 @@ - (void)setContentsScale:(CGFloat)newContentsScale
_setToLayer(contentsScale, newContentsScale);
}

- (CGFloat)rasterizationScale
{
_bridge_prologue_read;
return _getFromLayer(rasterizationScale);
}

- (void)setRasterizationScale:(CGFloat)newRasterizationScale
{
_bridge_prologue_write;
_setToLayer(rasterizationScale, newRasterizationScale);
}

- (CGRect)bounds
{
_bridge_prologue_read;
Expand Down
23 changes: 22 additions & 1 deletion Source/Private/_ASCoreAnimationExtras.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,28 @@
#import <UIKit/UIKit.h>

#import <AsyncDisplayKit/ASBaseDefines.h>
#import <AsyncDisplayKit/ASDisplayNode.h>

ASDISPLAYNODE_EXTERN_C_BEGIN

extern void ASDisplayNodeSetupLayerContentsWithResizableImage(CALayer *layer, UIImage *image);
// This protocol defines the core properties that ASDisplayNode and CALayer share, for managing contents.
@protocol ASResizableContents
@required
@property id contents;
@property CGRect contentsRect;
@property CGRect contentsCenter;
@property CGFloat contentsScale;
@property CGFloat rasterizationScale;
@property NSString *contentsGravity;
@end

@interface CALayer (ASResizableContents) <ASResizableContents>
@end
@interface ASDisplayNode (ASResizableContents) <ASResizableContents>
@end

// This function can operate on either an ASDisplayNode (including un-loaded) or CALayer directly.
extern void ASDisplayNodeSetResizableContents(id<ASResizableContents> obj, UIImage *image);

/**
Turns a value of UIViewContentMode to a string for debugging or serialization
Expand Down Expand Up @@ -67,4 +85,7 @@ extern UIImage *ASDisplayNodeStretchableBoxContentsWithColor(UIColor *color, CGS
*/
extern BOOL ASDisplayNodeLayerHasAnimations(CALayer *layer);

// This function is a less generalized version of ASDisplayNodeSetResizableContents.
extern void ASDisplayNodeSetupLayerContentsWithResizableImage(CALayer *layer, UIImage *image) ASDISPLAYNODE_DEPRECATED;

ASDISPLAYNODE_EXTERN_C_END
18 changes: 11 additions & 7 deletions Source/Private/_ASCoreAnimationExtras.mm
Original file line number Diff line number Diff line change
Expand Up @@ -20,17 +20,21 @@
#import <AsyncDisplayKit/ASAssert.h>

extern void ASDisplayNodeSetupLayerContentsWithResizableImage(CALayer *layer, UIImage *image)
{
ASDisplayNodeSetResizableContents(layer, image);
}

extern void ASDisplayNodeSetResizableContents(id<ASResizableContents> obj, UIImage *image)
{
// FIXME: This method does not currently handle UIImageResizingModeTile, which is the default on iOS 6.
// I'm not sure of a way to use CALayer directly to perform such tiling on the GPU, though the stretch is handled by the GPU,
// and CALayer.h documents the fact that contentsCenter is used to stretch the pixels.

if (image) {

// Image may not actually be stretchable in one or both dimensions; this is handled
layer.contents = (id)[image CGImage];
layer.contentsScale = [image scale];
layer.rasterizationScale = [image scale];
obj.contents = (id)[image CGImage];
obj.contentsScale = [image scale];
obj.rasterizationScale = [image scale];
CGSize imageSize = [image size];

ASDisplayNodeCAssert(image.resizingMode == UIImageResizingModeStretch || UIEdgeInsetsEqualToEdgeInsets(image.capInsets, UIEdgeInsetsZero),
Expand All @@ -51,11 +55,11 @@ extern void ASDisplayNodeSetupLayerContentsWithResizableImage(CALayer *layer, UI
contentsCenter.origin.y = ((insets.top + halfPixelFudge) / imageSize.height);
contentsCenter.size.height = (imageSize.height - (insets.top + insets.bottom + 1.f) + otherPixelFudge) / imageSize.height;
}
layer.contentsGravity = kCAGravityResize;
layer.contentsCenter = contentsCenter;
obj.contentsGravity = kCAGravityResize;
obj.contentsCenter = contentsCenter;

} else {
layer.contents = nil;
obj.contents = nil;
}
}

Expand Down
36 changes: 32 additions & 4 deletions Source/Private/_ASPendingState.mm
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,11 @@
int setAnchorPoint:1;
int setPosition:1;
int setZPosition:1;
int setContentsGravity:1;
int setContentsRect:1;
int setContentsCenter:1;
int setContentsScale:1;
int setRasterizationScale:1;
int setTransform:1;
int setSublayerTransform:1;
int setUserInteractionEnabled:1;
Expand Down Expand Up @@ -101,7 +105,11 @@ @implementation _ASPendingState
CGPoint anchorPoint;
CGPoint position;
CGFloat zPosition;
NSString *contentsGravity;
CGRect contentsRect;
CGRect contentsCenter;
CGFloat contentsScale;
CGFloat rasterizationScale;
CATransform3D transform;
CATransform3D sublayerTransform;
CGColorRef shadowColor;
Expand Down Expand Up @@ -176,7 +184,11 @@ ASDISPLAYNODE_INLINE void ASPendingStateApplyMetricsToLayer(_ASPendingState *sta
@synthesize anchorPoint=anchorPoint;
@synthesize position=position;
@synthesize zPosition=zPosition;
@synthesize contentsGravity=contentsGravity;
@synthesize contentsRect=contentsRect;
@synthesize contentsCenter=contentsCenter;
@synthesize contentsScale=contentsScale;
@synthesize rasterizationScale=rasterizationScale;
@synthesize transform=transform;
@synthesize sublayerTransform=sublayerTransform;
@synthesize userInteractionEnabled=userInteractionEnabled;
Expand Down Expand Up @@ -827,9 +839,6 @@ - (void)applyToView:(UIView *)view withSpecialPropertiesHandling:(BOOL)specialPr
if (flags.setBounds)
view.bounds = bounds;

if (flags.setContentsScale)
layer.contentsScale = contentsScale;

if (flags.setTransform)
layer.transform = transform;

Expand All @@ -839,6 +848,21 @@ - (void)applyToView:(UIView *)view withSpecialPropertiesHandling:(BOOL)specialPr
if (flags.setContents)
layer.contents = contents;

if (flags.setContentsGravity)
layer.contentsGravity = contentsGravity;

if (flags.setContentsRect)
layer.contentsRect = contentsRect;

if (flags.setContentsCenter)
layer.contentsCenter = contentsCenter;

if (flags.setContentsScale)
layer.contentsScale = contentsScale;

if (flags.setRasterizationScale)
layer.rasterizationScale = rasterizationScale;

if (flags.setClipsToBounds)
view.clipsToBounds = clipsToBounds;

Expand Down Expand Up @@ -1037,10 +1061,14 @@ + (_ASPendingState *)pendingViewStateFromView:(UIView *)view
pendingState.position = layer.position;
pendingState.zPosition = layer.zPosition;
pendingState.bounds = view.bounds;
pendingState.contentsScale = layer.contentsScale;
pendingState.transform = layer.transform;
pendingState.sublayerTransform = layer.sublayerTransform;
pendingState.contents = layer.contents;
pendingState.contentsGravity = layer.contentsGravity;
pendingState.contentsRect = layer.contentsRect;
pendingState.contentsCenter = layer.contentsCenter;
pendingState.contentsScale = layer.contentsScale;
pendingState.rasterizationScale = layer.rasterizationScale;
pendingState.clipsToBounds = view.clipsToBounds;
pendingState.backgroundColor = layer.backgroundColor;
pendingState.tintColor = view.tintColor;
Expand Down