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,10 +47,12 @@ - (instancetype)init
4147
4248 _titleNode = [[ASTextNode alloc ] init ];
4349 _imageNode = [[ASImageNode alloc ] init ];
50+ _backgroundImageNode = [[ASImageNode alloc ] init ];
4451
4552 _contentHorizontalAlignment = ASAlignmentMiddle;
4653 _contentVerticalAlignment = ASAlignmentCenter;
4754
55+ [self addSubnode: _backgroundImageNode];
4856 [self addSubnode: _titleNode];
4957 [self addSubnode: _imageNode];
5058 }
@@ -54,20 +62,24 @@ - (instancetype)init
5462- (void )setEnabled : (BOOL )enabled
5563{
5664 [super setEnabled: enabled];
57- [self updateImage ];
58- [self updateTitle ];
65+ [self updateButtonContent ];
5966}
6067
6168- (void )setHighlighted : (BOOL )highlighted
6269{
6370 [super setHighlighted: highlighted];
64- [self updateImage ];
65- [self updateTitle ];
71+ [self updateButtonContent ];
6672}
6773
6874- (void )setSelected : (BOOL )selected
6975{
7076 [super setSelected: selected];
77+ [self updateButtonContent ];
78+ }
79+
80+ - (void )updateButtonContent
81+ {
82+ [self updateBackgroundImage ];
7183 [self updateImage ];
7284 [self updateTitle ];
7385}
@@ -113,6 +125,27 @@ - (void)updateTitle
113125 }
114126}
115127
128+ - (void )updateBackgroundImage
129+ {
130+ ASDN::MutexLocker l (_propertyLock);
131+
132+ UIImage *newImage;
133+ if (self.enabled == NO && _disabledBackgroundImage) {
134+ newImage = _disabledBackgroundImage;
135+ } else if (self.highlighted && _highlightedBackgroundImage) {
136+ newImage = _highlightedBackgroundImage;
137+ } else if (self.selected && _selectedBackgroundImage) {
138+ newImage = _selectedBackgroundImage;
139+ } else {
140+ newImage = _normalBackgroundImage;
141+ }
142+
143+ if (newImage != self.backgroundImageNode .image ) {
144+ self.backgroundImageNode .image = newImage;
145+ [self setNeedsLayout ];
146+ }
147+ }
148+
116149- (CGFloat)contentSpacing
117150{
118151 ASDN::MutexLocker l (_propertyLock);
@@ -145,6 +178,18 @@ - (void)setLaysOutHorizontally:(BOOL)laysOutHorizontally
145178 [self setNeedsLayout ];
146179}
147180
181+ - (void )setTitle : (NSString *)title withFont : (UIFont *)font withColor : (UIColor *)color forState : (ASControlState)state
182+ {
183+ NSDictionary *attributes = @{
184+ NSFontAttributeName : font ? font :[UIFont systemFontOfSize: [UIFont buttonFontSize ]],
185+ NSForegroundColorAttributeName : color ? color : [UIColor blackColor ]
186+ };
187+
188+ NSAttributedString *string = [[NSAttributedString alloc ] initWithString: title
189+ attributes: attributes];
190+ [self setAttributedTitle: string forState: state];
191+ }
192+
148193- (NSAttributedString *)attributedTitleForState : (ASControlState)state
149194{
150195 ASDN::MutexLocker l (_propertyLock);
@@ -239,6 +284,54 @@ - (void)setImage:(UIImage *)image forState:(ASControlState)state
239284 [self updateImage ];
240285}
241286
287+ - (void )setBackgroundImage : (UIImage *)image forState : (ASControlState)state
288+ {
289+ ASDN::MutexLocker l (_propertyLock);
290+ switch (state) {
291+ case ASControlStateNormal:
292+ _normalBackgroundImage = image;
293+ break ;
294+
295+ case ASControlStateHighlighted:
296+ _highlightedBackgroundImage = image;
297+ break ;
298+
299+ case ASControlStateSelected:
300+ _selectedBackgroundImage = image;
301+ break ;
302+
303+ case ASControlStateDisabled:
304+ _disabledBackgroundImage = image;
305+ break ;
306+
307+ default :
308+ break ;
309+ }
310+ [self updateBackgroundImage ];
311+ }
312+
313+ - (UIImage *)backgroundImageForState : (ASControlState)state
314+ {
315+ ASDN::MutexLocker l (_propertyLock);
316+ switch (state) {
317+ case ASControlStateNormal:
318+ return _normalBackgroundImage;
319+
320+ case ASControlStateHighlighted:
321+ return _highlightedBackgroundImage;
322+
323+ case ASControlStateSelected:
324+ return _selectedBackgroundImage;
325+
326+ case ASControlStateDisabled:
327+ return _disabledBackgroundImage;
328+
329+ default :
330+ return _normalBackgroundImage;
331+ }
332+
333+ }
334+
242335- (ASLayoutSpec *)layoutSpecThatFits : (ASSizeRange)constrainedSize
243336{
244337 ASStackLayoutSpec *stack = [[ASStackLayoutSpec alloc ] init ];
@@ -258,12 +351,18 @@ - (ASLayoutSpec *)layoutSpecThatFits:(ASSizeRange)constrainedSize
258351
259352 stack.children = children;
260353
261- return stack;
354+ if (self.backgroundImageNode .image ) {
355+ return [ASBackgroundLayoutSpec backgroundLayoutSpecWithChild: stack
356+ background: self .backgroundImageNode];
357+ } else {
358+ return stack;
359+ }
262360}
263361
264362- (void )layout
265363{
266364 [super layout ];
365+ self.backgroundImageNode .hidden = self.backgroundImageNode .image == nil ;
267366 self.imageNode .hidden = self.imageNode .image == nil ;
268367 self.titleNode .hidden = self.titleNode .attributedString .length > 0 == NO ;
269368}
0 commit comments