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