From 482bd56d46cb51e1e01e1b4359850d04a0b04a13 Mon Sep 17 00:00:00 2001 From: Yarden Eitan Date: Wed, 11 Apr 2018 17:14:22 +0300 Subject: [PATCH] [Buttons] Implement a color themer for an MDCFlatButton (#3308) Addition of a unit test, and updated example to use the new themer. Pivotal: https://www.pivotaltracker.com/story/show/156640819 --- .../Buttons/examples/ButtonsTypicalUse.m | 7 +- .../src/ColorThemer/MDCButtonColorThemer.h | 19 +++-- .../src/ColorThemer/MDCButtonColorThemer.m | 25 +++++- .../tests/unit/ButtonsColorThemerTests.m | 82 +++++++++++++++---- 4 files changed, 103 insertions(+), 30 deletions(-) diff --git a/components/Buttons/examples/ButtonsTypicalUse.m b/components/Buttons/examples/ButtonsTypicalUse.m index 5b9d5b4d1e7..1ec7f0b1012 100644 --- a/components/Buttons/examples/ButtonsTypicalUse.m +++ b/components/Buttons/examples/ButtonsTypicalUse.m @@ -35,7 +35,7 @@ - (MDCButton *)buildCustomStrokedButton { [button setBorderWidth:1.0 forState:UIControlStateNormal]; [button setBorderColor:[UIColor colorWithWhite:0.1f alpha:1] forState:UIControlStateNormal]; - id colorScheme = [[MDCSemanticColorScheme alloc] init]; + MDCSemanticColorScheme *colorScheme = [[MDCSemanticColorScheme alloc] init]; [MDCButtonColorThemer applySemanticColorScheme:colorScheme toButton:button]; MDCTypographyScheme *typographyScheme = [[MDCTypographyScheme alloc] init]; [MDCButtonTypographyThemer applyTypographyScheme:typographyScheme toButton:button]; @@ -45,6 +45,7 @@ - (MDCButton *)buildCustomStrokedButton { - (void)viewDidLoad { [super viewDidLoad]; + MDCSemanticColorScheme *colorScheme = [[MDCSemanticColorScheme alloc] init]; MDCTypographyScheme *typographyScheme = [[MDCTypographyScheme alloc] init]; self.view.backgroundColor = [UIColor colorWithWhite:0.9f alpha:1]; @@ -79,8 +80,8 @@ - (void)viewDidLoad { MDCFlatButton *flatButton = [[MDCFlatButton alloc] init]; [flatButton setTitle:@"Button" forState:UIControlStateNormal]; - [flatButton setTitleColor:[UIColor grayColor] forState:UIControlStateNormal]; [MDCButtonTypographyThemer applyTypographyScheme:typographyScheme toButton:flatButton]; + [MDCButtonColorThemer applySemanticColorScheme:colorScheme toFlatButton:flatButton]; [flatButton sizeToFit]; [flatButton addTarget:self action:@selector(didTap:) @@ -91,8 +92,8 @@ - (void)viewDidLoad { MDCFlatButton *disabledFlatButton = [[MDCFlatButton alloc] init]; [disabledFlatButton setTitle:@"Button" forState:UIControlStateNormal]; - [disabledFlatButton setTitleColor:[UIColor grayColor] forState:UIControlStateNormal]; [MDCButtonTypographyThemer applyTypographyScheme:typographyScheme toButton:disabledFlatButton]; + [MDCButtonColorThemer applySemanticColorScheme:colorScheme toFlatButton:disabledFlatButton]; [disabledFlatButton sizeToFit]; [disabledFlatButton addTarget:self action:@selector(didTap:) diff --git a/components/Buttons/src/ColorThemer/MDCButtonColorThemer.h b/components/Buttons/src/ColorThemer/MDCButtonColorThemer.h index 21df2e83185..7065eee6b9f 100644 --- a/components/Buttons/src/ColorThemer/MDCButtonColorThemer.h +++ b/components/Buttons/src/ColorThemer/MDCButtonColorThemer.h @@ -23,21 +23,30 @@ @interface MDCButtonColorThemer : NSObject /** - Applies a color scheme to theme to a MDCButton. + Applies a color scheme to theme to an MDCButton. - @param colorScheme The color scheme to apply to MDCButton. + @param colorScheme The color scheme to apply to @c button. */ + (void)applySemanticColorScheme:(nonnull id)colorScheme toButton:(nonnull MDCButton *)button; /** - Applies a color scheme to theme a MDCButton. Use a UIAppearance proxy to apply a color scheme to + Applies a color scheme to theme to an MDCFlatButton. + + @param colorScheme The color scheme to apply to @c flatButton. + @param flatButton An MDCFlatButton instance to apply a color scheme. + */ ++ (void)applySemanticColorScheme:(nonnull id)colorScheme + toFlatButton:(nonnull MDCFlatButton *)flatButton; + +/** + Applies a color scheme to theme an MDCButton. Use a UIAppearance proxy to apply a color scheme to all instances of MDCButton. This method will soon be deprecated. Consider using applySemanticColorScheme:colorScheme. - @param colorScheme The color scheme to apply to MDCButton. - @param button A MDCButton instance to apply a color scheme. + @param colorScheme The color scheme to apply to @c button. + @param button An MDCButton instance to apply a color scheme. */ + (void)applyColorScheme:(nonnull id)colorScheme toButton:(nonnull MDCButton *)button; diff --git a/components/Buttons/src/ColorThemer/MDCButtonColorThemer.m b/components/Buttons/src/ColorThemer/MDCButtonColorThemer.m index a093a44540d..759ce0df579 100644 --- a/components/Buttons/src/ColorThemer/MDCButtonColorThemer.m +++ b/components/Buttons/src/ColorThemer/MDCButtonColorThemer.m @@ -20,19 +20,36 @@ @implementation MDCButtonColorThemer + (void)applySemanticColorScheme:(nonnull id)colorScheme toButton:(nonnull MDCButton *)button { + [self resetUIControlStatesForButtonTheming:button]; [button setBackgroundColor:colorScheme.primaryColor forState:UIControlStateNormal]; - [button setBackgroundColor:colorScheme.primaryColor forState:UIControlStateHighlighted]; - [button setBackgroundColor:colorScheme.primaryColor forState:UIControlStateSelected]; [button setBackgroundColor:[colorScheme.onSurfaceColor colorWithAlphaComponent:0.12f] forState:UIControlStateDisabled]; [button setTitleColor:colorScheme.onPrimaryColor forState:UIControlStateNormal]; - [button setTitleColor:colorScheme.onPrimaryColor forState:UIControlStateHighlighted]; - [button setTitleColor:colorScheme.onPrimaryColor forState:UIControlStateSelected]; [button setTitleColor:[colorScheme.onSurfaceColor colorWithAlphaComponent:0.26f] forState:UIControlStateDisabled]; button.disabledAlpha = 1.f; } ++ (void)applySemanticColorScheme:(nonnull id)colorScheme + toFlatButton:(nonnull MDCFlatButton *)flatButton { + [self resetUIControlStatesForButtonTheming:flatButton]; + [flatButton setBackgroundColor:UIColor.clearColor forState:UIControlStateNormal]; + [flatButton setBackgroundColor:UIColor.clearColor forState:UIControlStateDisabled]; + [flatButton setTitleColor:colorScheme.primaryColor forState:UIControlStateNormal]; + [flatButton setTitleColor:[colorScheme.onSurfaceColor colorWithAlphaComponent:0.26f] + forState:UIControlStateDisabled]; + flatButton.disabledAlpha = 1.f; +} + ++ (void)resetUIControlStatesForButtonTheming:(nonnull MDCButton *)button { + NSUInteger maximumStateValue = UIControlStateNormal | UIControlStateSelected | + UIControlStateHighlighted | UIControlStateDisabled; + for (NSUInteger state = 0; state <= maximumStateValue; ++state) { + [button setBackgroundColor:nil forState:state]; + [button setTitleColor:nil forState:state]; + } +} + + (void)applyColorScheme:(id)colorScheme toButton:(MDCButton *)button { [button setBackgroundColor:colorScheme.primaryColor forState:UIControlStateNormal]; diff --git a/components/Buttons/tests/unit/ButtonsColorThemerTests.m b/components/Buttons/tests/unit/ButtonsColorThemerTests.m index 0e91cc614e7..3c9d9f2daa5 100644 --- a/components/Buttons/tests/unit/ButtonsColorThemerTests.m +++ b/components/Buttons/tests/unit/ButtonsColorThemerTests.m @@ -34,32 +34,78 @@ - (void)testMDCButtonColorThemer { colorScheme.onPrimaryColor = UIColor.greenColor; colorScheme.onSurfaceColor = UIColor.blueColor; [button setTitleColor:UIColor.whiteColor forState:UIControlStateNormal]; - [button setTitleColor:UIColor.greenColor forState:UIControlStateHighlighted]; - [button setTitleColor:UIColor.blueColor forState:UIControlStateSelected]; + [button setTitleColor:UIColor.whiteColor forState:UIControlStateHighlighted]; + [button setTitleColor:UIColor.whiteColor forState:UIControlStateSelected]; [button setTitleColor:UIColor.grayColor forState:UIControlStateDisabled]; [button setBackgroundColor:UIColor.purpleColor forState:UIControlStateNormal]; - [button setBackgroundColor:UIColor.redColor forState:UIControlStateHighlighted]; - [button setBackgroundColor:UIColor.blueColor forState:UIControlStateSelected]; + [button setBackgroundColor:UIColor.purpleColor forState:UIControlStateHighlighted]; + [button setBackgroundColor:UIColor.purpleColor forState:UIControlStateSelected]; [button setBackgroundColor:UIColor.darkGrayColor forState:UIControlStateDisabled]; // Where [MDCButtonColorThemer applySemanticColorScheme:colorScheme toButton:button]; // Then - XCTAssertEqual([button titleColorForState:UIControlStateNormal], colorScheme.onPrimaryColor); - XCTAssertEqual([button titleColorForState:UIControlStateHighlighted], colorScheme.onPrimaryColor); - XCTAssertEqual([button titleColorForState:UIControlStateSelected], colorScheme.onPrimaryColor); - XCTAssert( - CGColorEqualToColor([button titleColorForState:UIControlStateDisabled].CGColor, - [colorScheme.onSurfaceColor colorWithAlphaComponent:0.26f].CGColor)); - XCTAssertEqual([button backgroundColorForState:UIControlStateNormal], colorScheme.primaryColor); - XCTAssertEqual([button backgroundColorForState:UIControlStateHighlighted], - colorScheme.primaryColor); - XCTAssertEqual([button backgroundColorForState:UIControlStateSelected], colorScheme.primaryColor); - XCTAssert( - CGColorEqualToColor([button backgroundColorForState:UIControlStateDisabled].CGColor, - [colorScheme.onSurfaceColor colorWithAlphaComponent:0.12f].CGColor)); - XCTAssertEqual(button.disabledAlpha, 1.f); + NSUInteger maximumStateValue = UIControlStateNormal | UIControlStateSelected | + UIControlStateHighlighted | UIControlStateDisabled; + for (NSUInteger state = 0; state <= maximumStateValue; ++state) { + if (state != UIControlStateDisabled) { + if ([button titleColorForState:state] != nil) { + XCTAssertEqual([button titleColorForState:state], colorScheme.onPrimaryColor); + } + if ([button backgroundColorForState:state] != nil) { + XCTAssertEqual([button backgroundColorForState:state], colorScheme.primaryColor); + } + } else { + XCTAssert( + CGColorEqualToColor([button titleColorForState:state].CGColor, + [colorScheme.onSurfaceColor colorWithAlphaComponent:0.26f].CGColor)); + XCTAssert( + CGColorEqualToColor([button backgroundColorForState:state].CGColor, + [colorScheme.onSurfaceColor colorWithAlphaComponent:0.12f].CGColor)); + } + } + XCTAssertEqualWithAccuracy(button.disabledAlpha, 1.f, 0.001f); +} + +- (void)testMDCFlatButtonColorThemer { + // Given + MDCSemanticColorScheme *colorScheme = [[MDCSemanticColorScheme alloc] init]; + MDCFlatButton *button = [[MDCFlatButton alloc] init]; + [button setTitle:@"Hello World" forState:UIControlStateNormal]; + colorScheme.primaryColor = UIColor.redColor; + colorScheme.onSurfaceColor = UIColor.blueColor; + [button setTitleColor:UIColor.whiteColor forState:UIControlStateNormal]; + [button setTitleColor:UIColor.whiteColor forState:UIControlStateHighlighted]; + [button setTitleColor:UIColor.whiteColor forState:UIControlStateSelected]; + [button setTitleColor:UIColor.grayColor forState:UIControlStateDisabled]; + [button setBackgroundColor:UIColor.purpleColor forState:UIControlStateNormal]; + [button setBackgroundColor:UIColor.purpleColor forState:UIControlStateHighlighted]; + [button setBackgroundColor:UIColor.purpleColor forState:UIControlStateSelected]; + [button setBackgroundColor:UIColor.darkGrayColor forState:UIControlStateDisabled]; + + // Where + [MDCButtonColorThemer applySemanticColorScheme:colorScheme toFlatButton:button]; + + // Then + NSUInteger maximumStateValue = UIControlStateNormal | UIControlStateSelected | + UIControlStateHighlighted | UIControlStateDisabled; + for (NSUInteger state = 0; state <= maximumStateValue; ++state) { + if (state != UIControlStateDisabled) { + if ([button titleColorForState:state] != nil) { + XCTAssertEqual([button titleColorForState:state], colorScheme.primaryColor); + } + if ([button backgroundColorForState:state] != nil) { + XCTAssertEqual([button backgroundColorForState:state], UIColor.clearColor); + } + } else { + XCTAssert( + CGColorEqualToColor([button titleColorForState:state].CGColor, + [colorScheme.onSurfaceColor colorWithAlphaComponent:0.26f].CGColor)); + XCTAssertEqual([button backgroundColorForState:state], UIColor.clearColor); + } + } + XCTAssertEqualWithAccuracy(button.disabledAlpha, 1.f, 0.001f); } @end