| OLD | NEW |
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #import "ios/chrome/browser/ui/toolbar/toolbar_tools_menu_button.h" | 5 #import "ios/chrome/browser/ui/toolbar/toolbar_tools_menu_button.h" |
| 6 | 6 |
| 7 #import <QuartzCore/CAAnimation.h> | 7 #import <QuartzCore/CAAnimation.h> |
| 8 #import <QuartzCore/CAMediaTimingFunction.h> | 8 #import <QuartzCore/CAMediaTimingFunction.h> |
| 9 | 9 |
| 10 #include "ios/chrome/browser/ui/toolbar/toolbar_button_tints.h" | 10 #include "ios/chrome/browser/ui/toolbar/toolbar_button_tints.h" |
| 11 | 11 |
| 12 #if !defined(__has_feature) || !__has_feature(objc_arc) |
| 13 #error "This file requires ARC support." |
| 14 #endif |
| 15 |
| 12 namespace { | 16 namespace { |
| 13 // The number of dots drawn. | 17 // The number of dots drawn. |
| 14 const int kNumberOfDots = 3; | 18 const int kNumberOfDots = 3; |
| 15 // Position of the topmost dot. | 19 // Position of the topmost dot. |
| 16 const CGFloat kDotOffsetX = 22; | 20 const CGFloat kDotOffsetX = 22; |
| 17 const CGFloat kDotOffsetY = 18; | 21 const CGFloat kDotOffsetY = 18; |
| 18 // Vertical space between dots. | 22 // Vertical space between dots. |
| 19 const CGFloat kVerticalSpaceBetweenDots = 6; | 23 const CGFloat kVerticalSpaceBetweenDots = 6; |
| 20 // The duration of the animation, in seconds. | 24 // The duration of the animation, in seconds. |
| 21 const CFTimeInterval kAnimationDuration = 1; | 25 const CFTimeInterval kAnimationDuration = 1; |
| (...skipping 19 matching lines...) Expand all Loading... |
| 41 } // namespace | 45 } // namespace |
| 42 | 46 |
| 43 @interface ToolbarToolsMenuButton ()<CAAnimationDelegate> { | 47 @interface ToolbarToolsMenuButton ()<CAAnimationDelegate> { |
| 44 // The style of the toolbar the button is in. | 48 // The style of the toolbar the button is in. |
| 45 ToolbarControllerStyle style_; | 49 ToolbarControllerStyle style_; |
| 46 // Whether the tools menu is visible. | 50 // Whether the tools menu is visible. |
| 47 BOOL toolsMenuVisible_; | 51 BOOL toolsMenuVisible_; |
| 48 // Whether the reading list contains unseen items. | 52 // Whether the reading list contains unseen items. |
| 49 BOOL readingListContainsUnseenItems_; | 53 BOOL readingListContainsUnseenItems_; |
| 50 // The CALayers containing the drawn dots. | 54 // The CALayers containing the drawn dots. |
| 51 base::scoped_nsobject<CAShapeLayer> pathLayers_[kNumberOfDots]; | 55 NSMutableArray<CAShapeLayer*>* pathLayers_; |
| 52 // Whether the CALayers are being animated. | 56 // Whether the CALayers are being animated. |
| 53 BOOL animationOnGoing_; | 57 BOOL animationOnGoing_; |
| 54 } | 58 } |
| 55 // Updates the tint configuration based on the button's situation, e.g. whether | 59 // Updates the tint configuration based on the button's situation, e.g. whether |
| 56 // the tools menu is visible or not. | 60 // the tools menu is visible or not. |
| 57 - (void)updateTintOfButton; | 61 - (void)updateTintOfButton; |
| 58 // Initializes the pathLayers. | 62 // Initializes the pathLayers. |
| 59 - (void)initializeShapeLayers; | 63 - (void)initializeShapeLayers; |
| 60 // Returns a keyframe-based animation of the property identified by |keyPath|. | 64 // Returns a keyframe-based animation of the property identified by |keyPath|. |
| 61 // The animation immidiately sets the property's value to |initialValue|. | 65 // The animation immidiately sets the property's value to |initialValue|. |
| (...skipping 12 matching lines...) Expand all Loading... |
| 74 | 78 |
| 75 - (instancetype)initWithFrame:(CGRect)frame | 79 - (instancetype)initWithFrame:(CGRect)frame |
| 76 style:(ToolbarControllerStyle)style { | 80 style:(ToolbarControllerStyle)style { |
| 77 if (self = [super initWithFrame:frame]) { | 81 if (self = [super initWithFrame:frame]) { |
| 78 style_ = style; | 82 style_ = style; |
| 79 | 83 |
| 80 [self setTintColor:toolbar::NormalButtonTint(style_) | 84 [self setTintColor:toolbar::NormalButtonTint(style_) |
| 81 forState:UIControlStateNormal]; | 85 forState:UIControlStateNormal]; |
| 82 [self setTintColor:toolbar::HighlighButtonTint(style_) | 86 [self setTintColor:toolbar::HighlighButtonTint(style_) |
| 83 forState:UIControlStateHighlighted]; | 87 forState:UIControlStateHighlighted]; |
| 88 pathLayers_ = [[NSMutableArray alloc] initWithCapacity:kNumberOfDots]; |
| 84 } | 89 } |
| 85 return self; | 90 return self; |
| 86 } | 91 } |
| 87 | 92 |
| 88 - (void)setToolsMenuIsVisible:(BOOL)toolsMenuVisible { | 93 - (void)setToolsMenuIsVisible:(BOOL)toolsMenuVisible { |
| 89 toolsMenuVisible_ = toolsMenuVisible; | 94 toolsMenuVisible_ = toolsMenuVisible; |
| 90 [self updateTintOfButton]; | 95 [self updateTintOfButton]; |
| 91 } | 96 } |
| 92 | 97 |
| 93 - (void)setReadingListContainsUnseenItems:(BOOL)readingListContainsUnseenItems { | 98 - (void)setReadingListContainsUnseenItems:(BOOL)readingListContainsUnseenItems { |
| (...skipping 12 matching lines...) Expand all Loading... |
| 106 [self setTintColor:toolbar::HighlighButtonTint(style_) | 111 [self setTintColor:toolbar::HighlighButtonTint(style_) |
| 107 forState:UIControlStateNormal]; | 112 forState:UIControlStateNormal]; |
| 108 } else { | 113 } else { |
| 109 [self setTintColor:toolbar::NormalButtonTint(style_) | 114 [self setTintColor:toolbar::NormalButtonTint(style_) |
| 110 forState:UIControlStateNormal]; | 115 forState:UIControlStateNormal]; |
| 111 } | 116 } |
| 112 } | 117 } |
| 113 | 118 |
| 114 - (void)initializeShapeLayers { | 119 - (void)initializeShapeLayers { |
| 115 for (int i = 0; i < kNumberOfDots; i++) { | 120 for (int i = 0; i < kNumberOfDots; i++) { |
| 116 base::scoped_nsobject<CAShapeLayer>& pathLayer = pathLayers_[i]; | 121 CAShapeLayer* pathLayer = pathLayers_[i]; |
| 117 if (pathLayer) { | 122 if (pathLayer) { |
| 118 [pathLayer removeFromSuperlayer]; | 123 [pathLayer removeFromSuperlayer]; |
| 119 } | 124 } |
| 120 | 125 |
| 121 const CGFloat x = kDotOffsetX; | 126 const CGFloat x = kDotOffsetX; |
| 122 const CGFloat y = kDotOffsetY + kVerticalSpaceBetweenDots * i; | 127 const CGFloat y = kDotOffsetY + kVerticalSpaceBetweenDots * i; |
| 123 | 128 |
| 124 UIBezierPath* path = [UIBezierPath bezierPath]; | 129 UIBezierPath* path = [UIBezierPath bezierPath]; |
| 125 [path moveToPoint:CGPointMake(x - kMaxWidthOfSegment * 0.5, y)]; | 130 [path moveToPoint:CGPointMake(x - kMaxWidthOfSegment * 0.5, y)]; |
| 126 [path addLineToPoint:CGPointMake(x + kMaxWidthOfSegment * 0.5, y)]; | 131 [path addLineToPoint:CGPointMake(x + kMaxWidthOfSegment * 0.5, y)]; |
| 127 | 132 |
| 128 pathLayer.reset([[CAShapeLayer layer] retain]); | 133 pathLayer = [CAShapeLayer layer]; |
| 129 [pathLayer setFrame:self.bounds]; | 134 [pathLayer setFrame:self.bounds]; |
| 130 [pathLayer setPath:path.CGPath]; | 135 [pathLayer setPath:path.CGPath]; |
| 131 [pathLayer setStrokeColor:[self.tintColor CGColor]]; | 136 [pathLayer setStrokeColor:[self.tintColor CGColor]]; |
| 132 [pathLayer setFillColor:nil]; | 137 [pathLayer setFillColor:nil]; |
| 133 [pathLayer setLineWidth:kLineWidthAtRest]; | 138 [pathLayer setLineWidth:kLineWidthAtRest]; |
| 134 [pathLayer setLineCap:kCALineCapRound]; | 139 [pathLayer setLineCap:kCALineCapRound]; |
| 135 [pathLayer setStrokeStart:kStrokeStartAtRest]; | 140 [pathLayer setStrokeStart:kStrokeStartAtRest]; |
| 136 [pathLayer setStrokeEnd:kStrokeEndAtRest]; | 141 [pathLayer setStrokeEnd:kStrokeEndAtRest]; |
| 137 [self.layer addSublayer:pathLayer.get()]; | 142 [self.layer addSublayer:pathLayer]; |
| 143 pathLayers_[i] = pathLayer; |
| 138 } | 144 } |
| 139 } | 145 } |
| 140 | 146 |
| 141 - (CAAnimation*)animationWithInitialValue:(id)initialValue | 147 - (CAAnimation*)animationWithInitialValue:(id)initialValue |
| 142 intermediaryValue:(id)intermediaryValue | 148 intermediaryValue:(id)intermediaryValue |
| 143 finalValue:(id)finalValue | 149 finalValue:(id)finalValue |
| 144 frameStart:(int)frameStart | 150 frameStart:(int)frameStart |
| 145 forKeyPath:(NSString*)keyPath { | 151 forKeyPath:(NSString*)keyPath { |
| 146 // The property is animated the following way: | 152 // The property is animated the following way: |
| 147 // | 153 // |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 199 #endif | 205 #endif |
| 200 | 206 |
| 201 return animation; | 207 return animation; |
| 202 } | 208 } |
| 203 | 209 |
| 204 - (void)animateToColor:(UIColor*)targetColor { | 210 - (void)animateToColor:(UIColor*)targetColor { |
| 205 animationOnGoing_ = YES; | 211 animationOnGoing_ = YES; |
| 206 | 212 |
| 207 // Add four animations for each stroke. | 213 // Add four animations for each stroke. |
| 208 for (int i = 0; i < kNumberOfDots; i++) { | 214 for (int i = 0; i < kNumberOfDots; i++) { |
| 209 base::scoped_nsobject<CAShapeLayer>& pathLayer = pathLayers_[i]; | 215 CAShapeLayer* pathLayer = pathLayers_[i]; |
| 210 DCHECK(pathLayer.get()); | |
| 211 const int frameStart = | 216 const int frameStart = |
| 212 (kNumberOfDots - i) * kFramesBetweenAnimationOfEachDot; | 217 (kNumberOfDots - i) * kFramesBetweenAnimationOfEachDot; |
| 213 | 218 |
| 214 // Start of the stroke animation. | 219 // Start of the stroke animation. |
| 215 CAAnimation* strokeStartAnimation = | 220 CAAnimation* strokeStartAnimation = |
| 216 [self animationWithInitialValue:@(kStrokeStartAtRest) | 221 [self animationWithInitialValue:@(kStrokeStartAtRest) |
| 217 intermediaryValue:@(kStrokeStartAtApogee) | 222 intermediaryValue:@(kStrokeStartAtApogee) |
| 218 finalValue:@(kStrokeStartAtRest) | 223 finalValue:@(kStrokeStartAtRest) |
| 219 frameStart:frameStart | 224 frameStart:frameStart |
| 220 forKeyPath:@"strokeStart"]; | 225 forKeyPath:@"strokeStart"]; |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 280 #pragma mark - CAAnimationDelegate | 285 #pragma mark - CAAnimationDelegate |
| 281 | 286 |
| 282 - (void)animationDidStop:(CAAnimation*)animation finished:(BOOL)flag { | 287 - (void)animationDidStop:(CAAnimation*)animation finished:(BOOL)flag { |
| 283 animationOnGoing_ = NO; | 288 animationOnGoing_ = NO; |
| 284 // Recreate the CAShapeLayers in case the tint code changed while the | 289 // Recreate the CAShapeLayers in case the tint code changed while the |
| 285 // animation was going on. | 290 // animation was going on. |
| 286 [self initializeShapeLayers]; | 291 [self initializeShapeLayers]; |
| 287 } | 292 } |
| 288 | 293 |
| 289 @end | 294 @end |
| OLD | NEW |