1010#import " ASStackLayoutSpec.h"
1111#import " ASThread.h"
1212#import " ASDisplayNode+Subclasses.h"
13+ #import " ASBackgroundLayoutSpec.h"
1314
1415@interface ASButtonNode ()
1516{
@@ -24,6 +25,11 @@ @interface ASButtonNode ()
2425 UIImage *_highlightedImage;
2526 UIImage *_selectedImage;
2627 UIImage *_disabledImage;
28+
29+ UIImage *_normalBackgroundImage;
30+ UIImage *_highlightedBackgroundImage;
31+ UIImage *_selectedBackgroundImage;
32+ UIImage *_disabledBackgroundImage;
2733}
2834
2935@end
@@ -41,33 +47,50 @@ - (instancetype)init
4147
4248 _titleNode = [[ASTextNode alloc ] init ];
4349 _imageNode = [[ASImageNode alloc ] init ];
50+ _backgroundImageNode = [[ASImageNode alloc ] init ];
51+ [_backgroundImageNode setContentMode: UIViewContentModeScaleToFill];
4452
53+ [_titleNode setLayerBacked: YES ];
54+ [_imageNode setLayerBacked: YES ];
55+ [_backgroundImageNode setLayerBacked: YES ];
56+
4557 _contentHorizontalAlignment = ASAlignmentMiddle;
4658 _contentVerticalAlignment = ASAlignmentCenter;
4759
60+ [self addSubnode: _backgroundImageNode];
4861 [self addSubnode: _titleNode];
4962 [self addSubnode: _imageNode];
5063 }
5164 return self;
5265}
5366
67+ - (void )setLayerBacked : (BOOL )layerBacked
68+ {
69+ ASDisplayNodeAssert (!layerBacked, @" ASButtonNode must not be layer backed!" );
70+ [super setLayerBacked: layerBacked];
71+ }
72+
5473- (void )setEnabled : (BOOL )enabled
5574{
5675 [super setEnabled: enabled];
57- [self updateImage ];
58- [self updateTitle ];
76+ [self updateButtonContent ];
5977}
6078
6179- (void )setHighlighted : (BOOL )highlighted
6280{
6381 [super setHighlighted: highlighted];
64- [self updateImage ];
65- [self updateTitle ];
82+ [self updateButtonContent ];
6683}
6784
6885- (void )setSelected : (BOOL )selected
6986{
7087 [super setSelected: selected];
88+ [self updateButtonContent ];
89+ }
90+
91+ - (void )updateButtonContent
92+ {
93+ [self updateBackgroundImage ];
7194 [self updateImage ];
7295 [self updateTitle ];
7396}
@@ -120,6 +143,27 @@ - (void)updateTitle
120143 }
121144}
122145
146+ - (void )updateBackgroundImage
147+ {
148+ ASDN::MutexLocker l (_propertyLock);
149+
150+ UIImage *newImage;
151+ if (self.enabled == NO && _disabledBackgroundImage) {
152+ newImage = _disabledBackgroundImage;
153+ } else if (self.highlighted && _highlightedBackgroundImage) {
154+ newImage = _highlightedBackgroundImage;
155+ } else if (self.selected && _selectedBackgroundImage) {
156+ newImage = _selectedBackgroundImage;
157+ } else {
158+ newImage = _normalBackgroundImage;
159+ }
160+
161+ if (newImage != self.backgroundImageNode .image ) {
162+ self.backgroundImageNode .image = newImage;
163+ [self setNeedsLayout ];
164+ }
165+ }
166+
123167- (CGFloat)contentSpacing
124168{
125169 ASDN::MutexLocker l (_propertyLock);
@@ -152,6 +196,18 @@ - (void)setLaysOutHorizontally:(BOOL)laysOutHorizontally
152196 [self setNeedsLayout ];
153197}
154198
199+ - (void )setTitle : (NSString *)title withFont : (UIFont *)font withColor : (UIColor *)color forState : (ASControlState)state
200+ {
201+ NSDictionary *attributes = @{
202+ NSFontAttributeName : font ? font :[UIFont systemFontOfSize: [UIFont buttonFontSize ]],
203+ NSForegroundColorAttributeName : color ? color : [UIColor blackColor ]
204+ };
205+
206+ NSAttributedString *string = [[NSAttributedString alloc ] initWithString: title
207+ attributes: attributes];
208+ [self setAttributedTitle: string forState: state];
209+ }
210+
155211- (NSAttributedString *)attributedTitleForState : (ASControlState)state
156212{
157213 ASDN::MutexLocker l (_propertyLock);
@@ -246,6 +302,54 @@ - (void)setImage:(UIImage *)image forState:(ASControlState)state
246302 [self updateImage ];
247303}
248304
305+ - (void )setBackgroundImage : (UIImage *)image forState : (ASControlState)state
306+ {
307+ ASDN::MutexLocker l (_propertyLock);
308+ switch (state) {
309+ case ASControlStateNormal:
310+ _normalBackgroundImage = image;
311+ break ;
312+
313+ case ASControlStateHighlighted:
314+ _highlightedBackgroundImage = image;
315+ break ;
316+
317+ case ASControlStateSelected:
318+ _selectedBackgroundImage = image;
319+ break ;
320+
321+ case ASControlStateDisabled:
322+ _disabledBackgroundImage = image;
323+ break ;
324+
325+ default :
326+ break ;
327+ }
328+ [self updateBackgroundImage ];
329+ }
330+
331+ - (UIImage *)backgroundImageForState : (ASControlState)state
332+ {
333+ ASDN::MutexLocker l (_propertyLock);
334+ switch (state) {
335+ case ASControlStateNormal:
336+ return _normalBackgroundImage;
337+
338+ case ASControlStateHighlighted:
339+ return _highlightedBackgroundImage;
340+
341+ case ASControlStateSelected:
342+ return _selectedBackgroundImage;
343+
344+ case ASControlStateDisabled:
345+ return _disabledBackgroundImage;
346+
347+ default :
348+ return _normalBackgroundImage;
349+ }
350+
351+ }
352+
249353- (ASLayoutSpec *)layoutSpecThatFits : (ASSizeRange)constrainedSize
250354{
251355 ASStackLayoutSpec *stack = [[ASStackLayoutSpec alloc ] init ];
@@ -265,12 +369,18 @@ - (ASLayoutSpec *)layoutSpecThatFits:(ASSizeRange)constrainedSize
265369
266370 stack.children = children;
267371
268- return stack;
372+ if (self.backgroundImageNode .image ) {
373+ return [ASBackgroundLayoutSpec backgroundLayoutSpecWithChild: stack
374+ background: self .backgroundImageNode];
375+ } else {
376+ return stack;
377+ }
269378}
270379
271380- (void )layout
272381{
273382 [super layout ];
383+ self.backgroundImageNode .hidden = self.backgroundImageNode .image == nil ;
274384 self.imageNode .hidden = self.imageNode .image == nil ;
275385 self.titleNode .hidden = self.titleNode .attributedString .length > 0 == NO ;
276386}
0 commit comments