Skip to content
This repository was archived by the owner on Feb 2, 2023. It is now read-only.
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
81 changes: 54 additions & 27 deletions AsyncDisplayKit.xcodeproj/project.pbxproj

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0700"
LastUpgradeVersion = "0710"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0700"
LastUpgradeVersion = "0710"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
Expand Down
40 changes: 40 additions & 0 deletions AsyncDisplayKit/ASButtonNode.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/* Copyright (c) 2014-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/

#import <AsyncDisplayKit/AsyncDisplayKit.h>

typedef enum : NSUInteger {
ASButtonStateNormal,
ASButtonStateHighlighted,
ASButtonStateDisabled,
} ASButtonState;

@interface ASButtonNode : ASControlNode

@property (nonatomic, readonly) ASTextNode *titleNode;
@property (nonatomic, readonly) ASImageNode *imageNode;

/**
Spacing between image and title. Defaults to 8.0.
*/
@property (nonatomic, assign) CGFloat contentSpacing;

/**
Whether button should be laid out vertically (image on top of text) or horizontally (image to the left of text).
ASButton node does not yet support RTL but it should be fairly easy to implement.
Defaults to YES.
*/
@property (nonatomic, assign) BOOL laysOutHorizontally;

- (NSAttributedString *)attributedTitleForState:(ASButtonState)state;
- (void)setAttributedTitle:(NSAttributedString *)title forState:(ASButtonState)state;

- (UIImage *)imageForState:(ASButtonState)state;
- (void)setImage:(UIImage *)image forState:(ASButtonState)state;

@end
222 changes: 222 additions & 0 deletions AsyncDisplayKit/ASButtonNode.mm
Original file line number Diff line number Diff line change
@@ -0,0 +1,222 @@
/* Copyright (c) 2014-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/

#import "ASButtonNode.h"

#import <AsyncDisplayKit/ASThread.h>

@interface ASButtonNode ()
{
ASDN::RecursiveMutex _propertyLock;

NSAttributedString *_normalAttributedTitle;
NSAttributedString *_highlightedAttributedTitle;
NSAttributedString *_disabledAttributedTitle;

UIImage *_normalImage;
UIImage *_highlightedImage;
UIImage *_disabledImage;
}

@end

@implementation ASButtonNode

@synthesize contentSpacing = _contentSpacing;
@synthesize laysOutHorizontally = _laysOutHorizontally;

- (instancetype)init
{
if (self = [super init]) {
_contentSpacing = 8.0;
_laysOutHorizontally = YES;

_titleNode = [[ASTextNode alloc] init];
_imageNode = [[ASImageNode alloc] init];

[self addSubnode:_titleNode];
[self addSubnode:_imageNode];

[self addTarget:self action:@selector(controlEventUpdated:) forControlEvents:ASControlNodeEventAllEvents];
}
return self;
}

- (void)controlEventUpdated:(ASControlNode *)node
{
[self updateImage];
[self updateTitle];
}

- (void)updateImage
{
ASDN::MutexLocker l(_propertyLock);

UIImage *newImage;
if (self.enabled == NO && _disabledImage) {
newImage = _disabledImage;
} else if (self.highlighted && _highlightedImage) {
newImage = _highlightedImage;
} else {
newImage = _normalImage;
}

if (newImage != self.imageNode.image) {
self.imageNode.image = newImage;
[self setNeedsLayout];
}
}

- (void)updateTitle
{
ASDN::MutexLocker l(_propertyLock);
NSAttributedString *newTitle;
if (self.enabled == NO && _disabledAttributedTitle) {
newTitle = _disabledAttributedTitle;
} else if (self.highlighted && _highlightedAttributedTitle) {
newTitle = _highlightedAttributedTitle;
} else {
newTitle = _normalAttributedTitle;
}

if (newTitle != self.titleNode.attributedString) {
self.titleNode.attributedString = newTitle;
[self setNeedsLayout];
}
}

- (CGFloat)contentSpacing
{
ASDN::MutexLocker l(_propertyLock);
return _contentSpacing;
}

- (void)setContentSpacing:(CGFloat)contentSpacing
{
ASDN::MutexLocker l(_propertyLock);
if (contentSpacing == _contentSpacing)
return;

_contentSpacing = contentSpacing;
[self setNeedsLayout];
}

- (BOOL)laysOutHorizontally
{
ASDN::MutexLocker l(_propertyLock);
return _laysOutHorizontally;
}

- (void)setLaysOutHorizontally:(BOOL)laysOutHorizontally
{
ASDN::MutexLocker l(_propertyLock);
if (laysOutHorizontally == _laysOutHorizontally)
return;

_laysOutHorizontally = laysOutHorizontally;
[self setNeedsLayout];
}

- (NSAttributedString *)attributedTitleForState:(ASButtonState)state
{
ASDN::MutexLocker l(_propertyLock);
switch (state) {
case ASButtonStateNormal:
return _normalAttributedTitle;

case ASButtonStateHighlighted:
return _highlightedAttributedTitle;

case ASButtonStateDisabled:
return _disabledAttributedTitle;
}
}

- (void)setAttributedTitle:(NSAttributedString *)title forState:(ASButtonState)state
{
ASDN::MutexLocker l(_propertyLock);
switch (state) {
case ASButtonStateNormal:
_normalAttributedTitle = [title copy];
break;

case ASButtonStateHighlighted:
_highlightedAttributedTitle = [title copy];
break;

case ASButtonStateDisabled:
_disabledAttributedTitle = [title copy];
break;
}
[self updateTitle];
}

- (UIImage *)imageForState:(ASButtonState)state
{
ASDN::MutexLocker l(_propertyLock);
switch (state) {
case ASButtonStateNormal:
return _normalImage;

case ASButtonStateHighlighted:
return _highlightedImage;

case ASButtonStateDisabled:
return _disabledImage;
}
}

- (void)setImage:(UIImage *)image forState:(ASButtonState)state
{
ASDN::MutexLocker l(_propertyLock);
switch (state) {
case ASButtonStateNormal:
_normalImage = image;
break;

case ASButtonStateHighlighted:
_highlightedImage = image;
break;

case ASButtonStateDisabled:
_disabledImage = image;
break;
}
[self updateImage];
}

- (ASLayoutSpec *)layoutSpecThatFits:(ASSizeRange)constrainedSize
{
ASStackLayoutSpec *stack = [[ASStackLayoutSpec alloc] init];
stack.direction = self.laysOutHorizontally ? ASStackLayoutDirectionHorizontal : ASStackLayoutDirectionVertical;
stack.spacing = self.contentSpacing;
stack.justifyContent = ASStackLayoutJustifyContentCenter;
stack.alignItems = ASStackLayoutAlignItemsCenter;

NSMutableArray *children = [[NSMutableArray alloc] initWithCapacity:2];
if (self.imageNode.image) {
[children addObject:self.imageNode];
}

if (self.titleNode.attributedString.length > 0) {
[children addObject:self.titleNode];
}

stack.children = children;

return stack;
}

- (void)layout
{
[super layout];
self.imageNode.hidden = self.imageNode.image == nil;
self.titleNode.hidden = self.titleNode.attributedString.length > 0 == NO;
}

@end
1 change: 1 addition & 0 deletions AsyncDisplayKit/ASTextNode.mm
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ @implementation ASTextNode {

UILongPressGestureRecognizer *_longPressGestureRecognizer;
}
@dynamic placeholderEnabled;

#pragma mark - NSObject

Expand Down
1 change: 1 addition & 0 deletions AsyncDisplayKit/AsyncDisplayKit.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#import <AsyncDisplayKit/ASControlNode.h>
#import <AsyncDisplayKit/ASImageNode.h>
#import <AsyncDisplayKit/ASTextNode.h>
#import <AsyncDisplayKit/ASButtonNode.h>

#import <AsyncDisplayKit/ASEditableTextNode.h>

Expand Down
16 changes: 16 additions & 0 deletions examples/Multiplex/Sample.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@
05E2127E19D4DB510098F589 /* Frameworks */,
05E2127F19D4DB510098F589 /* Resources */,
F012A6F39E0149F18F564F50 /* Copy Pods Resources */,
93B7780A33739EF25F20366B /* Embed Pods Frameworks */,
);
buildRules = (
);
Expand Down Expand Up @@ -179,6 +180,21 @@
/* End PBXResourcesBuildPhase section */

/* Begin PBXShellScriptBuildPhase section */
93B7780A33739EF25F20366B /* Embed Pods Frameworks */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
);
name = "Embed Pods Frameworks";
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods/Pods-frameworks.sh\"\n";
showEnvVarsInLog = 0;
};
E080B80F89C34A25B3488E26 /* Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
Expand Down
2 changes: 1 addition & 1 deletion examples/Multiplex/Sample/ScreenNode.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
@interface ScreenNode : ASDisplayNode

@property (nonatomic, strong) ASMultiplexImageNode *imageNode;
@property (nonatomic, strong) ASTextNode *textNode;
@property (nonatomic, strong) ASButtonNode *buttonNode;

- (void)start;
- (void)reload;
Expand Down
Loading