| OLD | NEW |
| 1 // Copyright 2012 The Chromium Authors. All rights reserved. | 1 // Copyright 2012 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 // For performance reasons, the composition of the card frame is broken up into | 5 // For performance reasons, the composition of the card frame is broken up into |
| 6 // four pieces. The overall structure of the CardView is: | 6 // four pieces. The overall structure of the CardView is: |
| 7 // - CardView | 7 // - CardView |
| 8 // - Snapshot (UIImageView) | 8 // - Snapshot (UIImageView) |
| 9 // - FrameTop (UIImageView) | 9 // - FrameTop (UIImageView) |
| 10 // - FrameLeft (UIImageView) | 10 // - FrameLeft (UIImageView) |
| 11 // - FrameRight (UIImageView) | 11 // - FrameRight (UIImageView) |
| 12 // - FrameBottom (UIImageView) | 12 // - FrameBottom (UIImageView) |
| 13 // - CardTabView (UIView::DrawRect) | 13 // - CardTabView (UIView::DrawRect) |
| 14 // | 14 // |
| 15 // While it would be simpler to put the frame in one transparent UIImageView, | 15 // While it would be simpler to put the frame in one transparent UIImageView, |
| 16 // that would make the entire snapshot area needlessly color-blended. Instead | 16 // that would make the entire snapshot area needlessly color-blended. Instead |
| 17 // the frame is broken up into four pieces, top, left, bottom, right. | 17 // the frame is broken up into four pieces, top, left, bottom, right. |
| 18 // | 18 // |
| 19 // The frame's tab gets its own view above everything else (CardTabView) so that | 19 // The frame's tab gets its own view above everything else (CardTabView) so that |
| 20 // it can be animated out. It's also transparent since the tab has a curve and | 20 // it can be animated out. It's also transparent since the tab has a curve and |
| 21 // a shadow. | 21 // a shadow. |
| 22 | 22 |
| 23 #import "ios/chrome/browser/ui/stack_view/card_view.h" | 23 #import "ios/chrome/browser/ui/stack_view/card_view.h" |
| 24 | 24 |
| 25 #import <QuartzCore/QuartzCore.h> | 25 #import <QuartzCore/QuartzCore.h> |
| 26 #include <algorithm> | 26 #include <algorithm> |
| 27 | 27 |
| 28 #import "base/mac/foundation_util.h" | 28 #import "base/mac/foundation_util.h" |
| 29 | 29 #import "base/mac/objc_property_releaser.h" |
| 30 #import "base/mac/scoped_nsobject.h" |
| 30 #include "components/strings/grit/components_strings.h" | 31 #include "components/strings/grit/components_strings.h" |
| 31 #import "ios/chrome/browser/ui/animation_util.h" | 32 #import "ios/chrome/browser/ui/animation_util.h" |
| 32 #import "ios/chrome/browser/ui/reversed_animation.h" | 33 #import "ios/chrome/browser/ui/reversed_animation.h" |
| 33 #import "ios/chrome/browser/ui/rtl_geometry.h" | 34 #import "ios/chrome/browser/ui/rtl_geometry.h" |
| 34 #import "ios/chrome/browser/ui/stack_view/close_button.h" | 35 #import "ios/chrome/browser/ui/stack_view/close_button.h" |
| 35 #import "ios/chrome/browser/ui/stack_view/title_label.h" | 36 #import "ios/chrome/browser/ui/stack_view/title_label.h" |
| 36 #import "ios/chrome/browser/ui/ui_util.h" | 37 #import "ios/chrome/browser/ui/ui_util.h" |
| 37 #import "ios/chrome/common/material_timing.h" | 38 #import "ios/chrome/common/material_timing.h" |
| 38 #import "ios/third_party/material_components_ios/src/components/Typography/src/M
aterialTypography.h" | 39 #import "ios/third_party/material_components_ios/src/components/Typography/src/M
aterialTypography.h" |
| 39 #include "ui/base/l10n/l10n_util.h" | 40 #include "ui/base/l10n/l10n_util.h" |
| 40 #include "ui/base/resource/resource_bundle.h" | 41 #include "ui/base/resource/resource_bundle.h" |
| 41 #include "ui/gfx/favicon_size.h" | 42 #include "ui/gfx/favicon_size.h" |
| 42 #include "ui/gfx/image/image.h" | 43 #include "ui/gfx/image/image.h" |
| 43 #import "ui/gfx/ios/uikit_util.h" | 44 #import "ui/gfx/ios/uikit_util.h" |
| 44 | 45 |
| 45 #if !defined(__has_feature) || !__has_feature(objc_arc) | |
| 46 #error "This file requires ARC support." | |
| 47 #endif | |
| 48 | |
| 49 using ios::material::TimingFunction; | 46 using ios::material::TimingFunction; |
| 50 | 47 |
| 51 const UIEdgeInsets kCardImageInsets = {48.0, 4.0, 4.0, 4.0}; | 48 const UIEdgeInsets kCardImageInsets = {48.0, 4.0, 4.0, 4.0}; |
| 52 const CGFloat kCardFrameInset = 1.0; | 49 const CGFloat kCardFrameInset = 1.0; |
| 53 const CGFloat kCardShadowThickness = 16.0; | 50 const CGFloat kCardShadowThickness = 16.0; |
| 54 const CGFloat kCardFrameCornerRadius = 4.0; | 51 const CGFloat kCardFrameCornerRadius = 4.0; |
| 55 const CGFloat kCardTabTopInset = 4; | 52 const CGFloat kCardTabTopInset = 4; |
| 56 const CGFloat kCardFrameBackgroundBrightness = 242.0 / 255.0; | 53 const CGFloat kCardFrameBackgroundBrightness = 242.0 / 255.0; |
| 57 const CGFloat kCardFrameBackgroundBrightnessIncognito = 80.0 / 255.0; | 54 const CGFloat kCardFrameBackgroundBrightnessIncognito = 80.0 / 255.0; |
| 58 const CGFloat kCardFrameImageSnapshotOverlap = 1.0; | 55 const CGFloat kCardFrameImageSnapshotOverlap = 1.0; |
| (...skipping 22 matching lines...) Expand all Loading... |
| 81 return [UIImage imageNamed:name]; | 78 return [UIImage imageNamed:name]; |
| 82 } | 79 } |
| 83 | 80 |
| 84 } // namespace | 81 } // namespace |
| 85 | 82 |
| 86 #pragma mark - | 83 #pragma mark - |
| 87 | 84 |
| 88 @interface CardTabView : UIView | 85 @interface CardTabView : UIView |
| 89 | 86 |
| 90 @property(nonatomic, assign) CardCloseButtonSide closeButtonSide; | 87 @property(nonatomic, assign) CardCloseButtonSide closeButtonSide; |
| 91 @property(nonatomic, strong) UIImageView* favIconView; | 88 @property(nonatomic, retain) UIImageView* favIconView; |
| 92 @property(nonatomic, strong) UIImage* favicon; | 89 @property(nonatomic, retain) UIImage* favicon; |
| 93 @property(nonatomic, strong) CloseButton* closeButton; | 90 @property(nonatomic, retain) CloseButton* closeButton; |
| 94 @property(nonatomic, strong) TitleLabel* titleLabel; | 91 @property(nonatomic, retain) TitleLabel* titleLabel; |
| 95 @property(nonatomic, assign) BOOL isIncognito; | 92 @property(nonatomic, assign) BOOL isIncognito; |
| 96 | 93 |
| 97 // Layout helper selectors that calculate the frames for subviews given the | 94 // Layout helper selectors that calculate the frames for subviews given the |
| 98 // bounds of the card tab. Note that the frames returned by these selectors | 95 // bounds of the card tab. Note that the frames returned by these selectors |
| 99 // will be different depending on the value of the |displaySide| property. | 96 // will be different depending on the value of the |displaySide| property. |
| 100 - (LayoutRect)faviconLayoutForBounds:(CGRect)bounds; | 97 - (LayoutRect)faviconLayoutForBounds:(CGRect)bounds; |
| 101 - (CGRect)faviconFrameForBounds:(CGRect)bounds; | 98 - (CGRect)faviconFrameForBounds:(CGRect)bounds; |
| 102 - (LayoutRect)titleLabelLayoutForBounds:(CGRect)bounds; | 99 - (LayoutRect)titleLabelLayoutForBounds:(CGRect)bounds; |
| 103 - (CGRect)titleLabelFrameForBounds:(CGRect)bounds; | 100 - (CGRect)titleLabelFrameForBounds:(CGRect)bounds; |
| 104 - (LayoutRect)closeButtonLayoutForBounds:(CGRect)bounds; | 101 - (LayoutRect)closeButtonLayoutForBounds:(CGRect)bounds; |
| (...skipping 15 matching lines...) Expand all Loading... |
| 120 - (void)cleanUpAnimations; | 117 - (void)cleanUpAnimations; |
| 121 | 118 |
| 122 // Initialize a CardTabView with |frame| and |isIncognito| state. | 119 // Initialize a CardTabView with |frame| and |isIncognito| state. |
| 123 - (instancetype)initWithFrame:(CGRect)frame | 120 - (instancetype)initWithFrame:(CGRect)frame |
| 124 isIncognito:(BOOL)isIncognito NS_DESIGNATED_INITIALIZER; | 121 isIncognito:(BOOL)isIncognito NS_DESIGNATED_INITIALIZER; |
| 125 | 122 |
| 126 - (instancetype)initWithCoder:(NSCoder*)aDecoder NS_UNAVAILABLE; | 123 - (instancetype)initWithCoder:(NSCoder*)aDecoder NS_UNAVAILABLE; |
| 127 | 124 |
| 128 @end | 125 @end |
| 129 | 126 |
| 130 @implementation CardTabView | 127 @implementation CardTabView { |
| 128 base::mac::ObjCPropertyReleaser _propertyReleaser_CardTabView; |
| 129 } |
| 131 | 130 |
| 132 #pragma mark - Property Implementation | 131 #pragma mark - Property Implementation |
| 133 | 132 |
| 134 @synthesize closeButtonSide = _closeButtonSide; | 133 @synthesize closeButtonSide = _closeButtonSide; |
| 135 @synthesize favIconView = _faviconView; | 134 @synthesize favIconView = _faviconView; |
| 136 @synthesize favicon = _favicon; | 135 @synthesize favicon = _favicon; |
| 137 @synthesize closeButton = _closeButton; | 136 @synthesize closeButton = _closeButton; |
| 138 @synthesize titleLabel = _titleLabel; | 137 @synthesize titleLabel = _titleLabel; |
| 139 @synthesize isIncognito = _isIncognito; | 138 @synthesize isIncognito = _isIncognito; |
| 140 | 139 |
| 141 - (instancetype)initWithFrame:(CGRect)frame { | 140 - (instancetype)initWithFrame:(CGRect)frame { |
| 142 return [self initWithFrame:frame isIncognito:NO]; | 141 return [self initWithFrame:frame isIncognito:NO]; |
| 143 } | 142 } |
| 144 | 143 |
| 145 - (instancetype)initWithFrame:(CGRect)frame isIncognito:(BOOL)isIncognito { | 144 - (instancetype)initWithFrame:(CGRect)frame isIncognito:(BOOL)isIncognito { |
| 146 self = [super initWithFrame:frame]; | 145 self = [super initWithFrame:frame]; |
| 147 if (!self) | 146 if (!self) |
| 148 return self; | 147 return self; |
| 149 | 148 |
| 149 _propertyReleaser_CardTabView.Init(self, [CardTabView class]); |
| 150 _isIncognito = isIncognito; | 150 _isIncognito = isIncognito; |
| 151 | 151 |
| 152 UIImage* image = ImageWithName(@"default_favicon", _isIncognito); | 152 UIImage* image = ImageWithName(@"default_favicon", _isIncognito); |
| 153 _faviconView = [[UIImageView alloc] initWithImage:image]; | 153 _faviconView = [[UIImageView alloc] initWithImage:image]; |
| 154 [self addSubview:_faviconView]; | 154 [self addSubview:_faviconView]; |
| 155 | 155 |
| 156 UIImage* normal = ImageWithName(@"card_close_button", _isIncognito); | 156 UIImage* normal = ImageWithName(@"card_close_button", _isIncognito); |
| 157 UIImage* pressed = ImageWithName(@"card_close_button_pressed", _isIncognito); | 157 UIImage* pressed = ImageWithName(@"card_close_button_pressed", _isIncognito); |
| 158 | 158 |
| 159 _closeButton = [[CloseButton alloc] initWithFrame:CGRectZero]; | 159 _closeButton = [[CloseButton alloc] initWithFrame:CGRectZero]; |
| (...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 265 | 265 |
| 266 - (void)setTitle:(NSString*)title { | 266 - (void)setTitle:(NSString*)title { |
| 267 [_titleLabel setText:title]; | 267 [_titleLabel setText:title]; |
| 268 [_closeButton setAccessibilityValue:title]; | 268 [_closeButton setAccessibilityValue:title]; |
| 269 | 269 |
| 270 [self setNeedsUpdateConstraints]; | 270 [self setNeedsUpdateConstraints]; |
| 271 } | 271 } |
| 272 | 272 |
| 273 - (void)setFavicon:(UIImage*)favicon { | 273 - (void)setFavicon:(UIImage*)favicon { |
| 274 if (favicon != _favicon) { | 274 if (favicon != _favicon) { |
| 275 [favicon retain]; |
| 276 [_favicon release]; |
| 275 _favicon = favicon; | 277 _favicon = favicon; |
| 276 [self updateFaviconImage]; | 278 [self updateFaviconImage]; |
| 277 } | 279 } |
| 278 } | 280 } |
| 279 | 281 |
| 280 - (void)updateTitleColors { | 282 - (void)updateTitleColors { |
| 281 UIColor* titleColor = [UIColor blackColor]; | 283 UIColor* titleColor = [UIColor blackColor]; |
| 282 if (_isIncognito) | 284 if (_isIncognito) |
| 283 titleColor = [UIColor whiteColor]; | 285 titleColor = [UIColor whiteColor]; |
| 284 | 286 |
| (...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 428 else if (element == _titleLabel) | 430 else if (element == _titleLabel) |
| 429 index = closeButtonLeading ? 1 : 0; | 431 index = closeButtonLeading ? 1 : 0; |
| 430 return index; | 432 return index; |
| 431 } | 433 } |
| 432 | 434 |
| 433 @end | 435 @end |
| 434 | 436 |
| 435 #pragma mark - | 437 #pragma mark - |
| 436 | 438 |
| 437 @interface CardView () { | 439 @interface CardView () { |
| 438 UIImageView* _contents; | 440 base::scoped_nsobject<UIImageView> _contents; |
| 439 CardTabView* _tab; | 441 base::scoped_nsobject<CardTabView> _tab; |
| 440 id _cardCloseTarget; // weak | 442 id _cardCloseTarget; // weak |
| 441 SEL _cardCloseAction; | 443 SEL _cardCloseAction; |
| 442 id _accessibilityTarget; // weak | 444 id _accessibilityTarget; // weak |
| 443 SEL _accessibilityAction; | 445 SEL _accessibilityAction; |
| 444 | 446 |
| 445 BOOL _isIncognito; // YES if the card should use the incognito styling. | 447 BOOL _isIncognito; // YES if the card should use the incognito styling. |
| 446 | 448 |
| 447 // Pieces of the card frame, split into four UIViews. | 449 // Pieces of the card frame, split into four UIViews. |
| 448 UIImageView* _frameLeft; | 450 base::scoped_nsobject<UIImageView> _frameLeft; |
| 449 UIImageView* _frameRight; | 451 base::scoped_nsobject<UIImageView> _frameRight; |
| 450 UIImageView* _frameTop; | 452 base::scoped_nsobject<UIImageView> _frameTop; |
| 451 UIImageView* _frameBottom; | 453 base::scoped_nsobject<UIImageView> _frameBottom; |
| 452 UIImageView* _frameShadowImageView; | 454 base::scoped_nsobject<UIImageView> _frameShadowImageView; |
| 453 CALayer* _shadowMask; | 455 base::scoped_nsobject<CALayer> _shadowMask; |
| 454 } | 456 } |
| 455 | 457 |
| 456 // The LayoutRect for the CardTabView. | 458 // The LayoutRect for the CardTabView. |
| 457 - (LayoutRect)tabLayout; | 459 - (LayoutRect)tabLayout; |
| 458 | 460 |
| 459 // Sends |_cardCloseAction| to |_cardCloseTarget| with |self| as the sender. | 461 // Sends |_cardCloseAction| to |_cardCloseTarget| with |self| as the sender. |
| 460 - (void)closeButtonWasTapped:(id)sender; | 462 - (void)closeButtonWasTapped:(id)sender; |
| 461 | 463 |
| 462 // Resizes/zooms the snapshot to avoid stretching given the card's current | 464 // Resizes/zooms the snapshot to avoid stretching given the card's current |
| 463 // bounds. | 465 // bounds. |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 502 if (!self) | 504 if (!self) |
| 503 return self; | 505 return self; |
| 504 | 506 |
| 505 _isIncognito = isIncognito; | 507 _isIncognito = isIncognito; |
| 506 CGRect bounds = self.bounds; | 508 CGRect bounds = self.bounds; |
| 507 | 509 |
| 508 self.opaque = NO; | 510 self.opaque = NO; |
| 509 self.contentMode = UIViewContentModeRedraw; | 511 self.contentMode = UIViewContentModeRedraw; |
| 510 | 512 |
| 511 CGRect shadowFrame = UIEdgeInsetsInsetRect(bounds, kCardShadowLayoutOutsets); | 513 CGRect shadowFrame = UIEdgeInsetsInsetRect(bounds, kCardShadowLayoutOutsets); |
| 512 _frameShadowImageView = [[UIImageView alloc] initWithFrame:shadowFrame]; | 514 _frameShadowImageView.reset([[UIImageView alloc] initWithFrame:shadowFrame]); |
| 513 [_frameShadowImageView | 515 [_frameShadowImageView |
| 514 setAutoresizingMask:(UIViewAutoresizingFlexibleWidth | | 516 setAutoresizingMask:(UIViewAutoresizingFlexibleWidth | |
| 515 UIViewAutoresizingFlexibleHeight)]; | 517 UIViewAutoresizingFlexibleHeight)]; |
| 516 [self addSubview:_frameShadowImageView]; | 518 [self addSubview:_frameShadowImageView]; |
| 517 | 519 |
| 518 // Calling properties for side-effects. | 520 // Calling properties for side-effects. |
| 519 self.shouldShowShadow = YES; | 521 self.shouldShowShadow = YES; |
| 520 self.shouldMaskShadow = YES; | 522 self.shouldMaskShadow = YES; |
| 521 | 523 |
| 522 UIImage* image = [UIImage imageNamed:kCardShadowImageName]; | 524 UIImage* image = [UIImage imageNamed:kCardShadowImageName]; |
| 523 image = [image resizableImageWithCapInsets:kShadowStretchInsets]; | 525 image = [image resizableImageWithCapInsets:kShadowStretchInsets]; |
| 524 [_frameShadowImageView setImage:image]; | 526 [_frameShadowImageView setImage:image]; |
| 525 | 527 |
| 526 CGRect snapshotFrame = UIEdgeInsetsInsetRect(bounds, kCardImageInsets); | 528 CGRect snapshotFrame = UIEdgeInsetsInsetRect(bounds, kCardImageInsets); |
| 527 _contents = [[UIImageView alloc] initWithFrame:snapshotFrame]; | 529 _contents.reset([[UIImageView alloc] initWithFrame:snapshotFrame]); |
| 528 [_contents setClipsToBounds:YES]; | 530 [_contents setClipsToBounds:YES]; |
| 529 [_contents setContentMode:UIViewContentModeScaleAspectFill]; | 531 [_contents setContentMode:UIViewContentModeScaleAspectFill]; |
| 530 [_contents setFrame:snapshotFrame]; | 532 [_contents setFrame:snapshotFrame]; |
| 531 [_contents setAutoresizingMask:UIViewAutoresizingFlexibleWidth | | 533 [_contents setAutoresizingMask:UIViewAutoresizingFlexibleWidth | |
| 532 UIViewAutoresizingFlexibleHeight]; | 534 UIViewAutoresizingFlexibleHeight]; |
| 533 [self addSubview:_contents]; | 535 [self addSubview:_contents]; |
| 534 | 536 |
| 535 image = [UIImage imageNamed:isIncognito ? @"border_frame_incognito_left" | 537 image = [UIImage imageNamed:isIncognito ? @"border_frame_incognito_left" |
| 536 : @"border_frame_left"]; | 538 : @"border_frame_left"]; |
| 537 UIEdgeInsets imageStretchInsets = UIEdgeInsetsMake( | 539 UIEdgeInsets imageStretchInsets = UIEdgeInsetsMake( |
| 538 0.5 * image.size.height, 0.0, 0.5 * image.size.height, 0.0); | 540 0.5 * image.size.height, 0.0, 0.5 * image.size.height, 0.0); |
| 539 image = [image resizableImageWithCapInsets:imageStretchInsets]; | 541 image = [image resizableImageWithCapInsets:imageStretchInsets]; |
| 540 _frameLeft = [[UIImageView alloc] initWithImage:image]; | 542 _frameLeft.reset([[UIImageView alloc] initWithImage:image]); |
| 541 [self addSubview:_frameLeft]; | 543 [self addSubview:_frameLeft]; |
| 542 | 544 |
| 543 image = [UIImage imageNamed:isIncognito ? @"border_frame_incognito_right" | 545 image = [UIImage imageNamed:isIncognito ? @"border_frame_incognito_right" |
| 544 : @"border_frame_right"]; | 546 : @"border_frame_right"]; |
| 545 imageStretchInsets = UIEdgeInsetsMake(0.5 * image.size.height, 0.0, | 547 imageStretchInsets = UIEdgeInsetsMake(0.5 * image.size.height, 0.0, |
| 546 0.5 * image.size.height, 0.0); | 548 0.5 * image.size.height, 0.0); |
| 547 image = [image resizableImageWithCapInsets:imageStretchInsets]; | 549 image = [image resizableImageWithCapInsets:imageStretchInsets]; |
| 548 _frameRight = [[UIImageView alloc] initWithImage:image]; | 550 _frameRight.reset([[UIImageView alloc] initWithImage:image]); |
| 549 [self addSubview:_frameRight]; | 551 [self addSubview:_frameRight]; |
| 550 | 552 |
| 551 image = [UIImage imageNamed:isIncognito ? @"border_frame_incognito_top" | 553 image = [UIImage imageNamed:isIncognito ? @"border_frame_incognito_top" |
| 552 : @"border_frame_top"]; | 554 : @"border_frame_top"]; |
| 553 imageStretchInsets = UIEdgeInsetsMake(0.0, 0.5 * image.size.width, 0.0, | 555 imageStretchInsets = UIEdgeInsetsMake(0.0, 0.5 * image.size.width, 0.0, |
| 554 0.5 * image.size.width); | 556 0.5 * image.size.width); |
| 555 image = [image resizableImageWithCapInsets:imageStretchInsets]; | 557 image = [image resizableImageWithCapInsets:imageStretchInsets]; |
| 556 _frameTop = [[UIImageView alloc] initWithImage:image]; | 558 _frameTop.reset([[UIImageView alloc] initWithImage:image]); |
| 557 [self addSubview:_frameTop]; | 559 [self addSubview:_frameTop]; |
| 558 | 560 |
| 559 image = [UIImage imageNamed:isIncognito ? @"border_frame_incognito_bottom" | 561 image = [UIImage imageNamed:isIncognito ? @"border_frame_incognito_bottom" |
| 560 : @"border_frame_bottom"]; | 562 : @"border_frame_bottom"]; |
| 561 imageStretchInsets = UIEdgeInsetsMake(0.0, 0.5 * image.size.width, 0.0, | 563 imageStretchInsets = UIEdgeInsetsMake(0.0, 0.5 * image.size.width, 0.0, |
| 562 0.5 * image.size.width); | 564 0.5 * image.size.width); |
| 563 image = [image resizableImageWithCapInsets:imageStretchInsets]; | 565 image = [image resizableImageWithCapInsets:imageStretchInsets]; |
| 564 _frameBottom = [[UIImageView alloc] initWithImage:image]; | 566 _frameBottom.reset([[UIImageView alloc] initWithImage:image]); |
| 565 [self addSubview:_frameBottom]; | 567 [self addSubview:_frameBottom]; |
| 566 | 568 |
| 567 _tab = [[CardTabView alloc] initWithFrame:LayoutRectGetRect([self tabLayout]) | 569 _tab.reset([[CardTabView alloc] |
| 568 isIncognito:_isIncognito]; | 570 initWithFrame:LayoutRectGetRect([self tabLayout]) |
| 571 isIncognito:_isIncognito]); |
| 569 [_tab setCloseButtonSide:IsPortrait() ? CardCloseButtonSide::TRAILING | 572 [_tab setCloseButtonSide:IsPortrait() ? CardCloseButtonSide::TRAILING |
| 570 : CardCloseButtonSide::LEADING]; | 573 : CardCloseButtonSide::LEADING]; |
| 571 [[_tab closeButton] addTarget:self | 574 [[_tab closeButton] addTarget:self |
| 572 action:@selector(closeButtonWasTapped:) | 575 action:@selector(closeButtonWasTapped:) |
| 573 forControlEvents:UIControlEventTouchUpInside]; | 576 forControlEvents:UIControlEventTouchUpInside]; |
| 574 [[_tab closeButton] | 577 [[_tab closeButton] |
| 575 addAccessibilityElementFocusedTarget:self | 578 addAccessibilityElementFocusedTarget:self |
| 576 action:@selector(elementDidBecomeFocused:)]; | 579 action:@selector(elementDidBecomeFocused:)]; |
| 577 [_tab closeButton].accessibilityIdentifier = [self closeButtonId]; | 580 [_tab closeButton].accessibilityIdentifier = [self closeButtonId]; |
| 578 | 581 |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 637 | 640 |
| 638 - (TitleLabel*)titleLabel { | 641 - (TitleLabel*)titleLabel { |
| 639 return [_tab titleLabel]; | 642 return [_tab titleLabel]; |
| 640 } | 643 } |
| 641 | 644 |
| 642 - (void)setFavicon:(UIImage*)favicon { | 645 - (void)setFavicon:(UIImage*)favicon { |
| 643 [_tab setFavicon:favicon]; | 646 [_tab setFavicon:favicon]; |
| 644 } | 647 } |
| 645 | 648 |
| 646 - (void)closeButtonWasTapped:(id)sender { | 649 - (void)closeButtonWasTapped:(id)sender { |
| 647 #pragma clang diagnostic push | |
| 648 #pragma clang diagnostic ignored "-Warc-performSelector-leaks" | |
| 649 [_cardCloseTarget performSelector:_cardCloseAction withObject:self]; | 650 [_cardCloseTarget performSelector:_cardCloseAction withObject:self]; |
| 650 #pragma clang diagnostic pop | |
| 651 // Disable the tab's close button to prevent touch handling from the button | 651 // Disable the tab's close button to prevent touch handling from the button |
| 652 // while it's animating closed. | 652 // while it's animating closed. |
| 653 [_tab closeButton].enabled = NO; | 653 [_tab closeButton].enabled = NO; |
| 654 } | 654 } |
| 655 | 655 |
| 656 - (void)addCardCloseTarget:(id)target action:(SEL)action { | 656 - (void)addCardCloseTarget:(id)target action:(SEL)action { |
| 657 DCHECK(!target || [target respondsToSelector:action]); | 657 DCHECK(!target || [target respondsToSelector:action]); |
| 658 _cardCloseTarget = target; | 658 _cardCloseTarget = target; |
| 659 _cardCloseAction = action; | 659 _cardCloseAction = action; |
| 660 } | 660 } |
| (...skipping 11 matching lines...) Expand all Loading... |
| 672 CGRect cardBounds = {CGPointZero, cardSize}; | 672 CGRect cardBounds = {CGPointZero, cardSize}; |
| 673 CGSize viewSize = UIEdgeInsetsInsetRect(cardBounds, kCardImageInsets).size; | 673 CGSize viewSize = UIEdgeInsetsInsetRect(cardBounds, kCardImageInsets).size; |
| 674 CGSize imageSize = [_contents image].size; | 674 CGSize imageSize = [_contents image].size; |
| 675 CGFloat zoomRatio = std::max(viewSize.height / imageSize.height, | 675 CGFloat zoomRatio = std::max(viewSize.height / imageSize.height, |
| 676 viewSize.width / imageSize.width); | 676 viewSize.width / imageSize.width); |
| 677 return CGRectMake(0.0, 0.0, viewSize.width / (zoomRatio * imageSize.width), | 677 return CGRectMake(0.0, 0.0, viewSize.width / (zoomRatio * imageSize.width), |
| 678 viewSize.height / (zoomRatio * imageSize.height)); | 678 viewSize.height / (zoomRatio * imageSize.height)); |
| 679 } | 679 } |
| 680 | 680 |
| 681 - (void)updateImageBoundsAndZoom { | 681 - (void)updateImageBoundsAndZoom { |
| 682 UIImageView* imageView = _contents; | 682 UIImageView* imageView = _contents.get(); |
| 683 DCHECK(!CGRectEqualToRect(self.bounds, CGRectZero)); | 683 DCHECK(!CGRectEqualToRect(self.bounds, CGRectZero)); |
| 684 | 684 |
| 685 imageView.frame = UIEdgeInsetsInsetRect(self.bounds, kCardImageInsets); | 685 imageView.frame = UIEdgeInsetsInsetRect(self.bounds, kCardImageInsets); |
| 686 if (imageView.image) { | 686 if (imageView.image) { |
| 687 // Zoom the image to fill the available space. | 687 // Zoom the image to fill the available space. |
| 688 imageView.layer.contentsRect = | 688 imageView.layer.contentsRect = |
| 689 [self imageContentsRectForCardSize:self.bounds.size]; | 689 [self imageContentsRectForCardSize:self.bounds.size]; |
| 690 } | 690 } |
| 691 } | 691 } |
| 692 | 692 |
| 693 - (void)updateSnapshotAnimations { | 693 - (void)updateSnapshotAnimations { |
| 694 CAAnimation* snapshotAnimation = | 694 CAAnimation* snapshotAnimation = |
| 695 [[_contents layer] animationForKey:kCardViewAnimationKey]; | 695 [[_contents layer] animationForKey:kCardViewAnimationKey]; |
| 696 if (!snapshotAnimation) | 696 if (!snapshotAnimation) |
| 697 return; | 697 return; |
| 698 | 698 |
| 699 // Create copy of animation (animations become immutable after they're added | 699 // Create copy of animation (animations become immutable after they're added |
| 700 // to the layer). | 700 // to the layer). |
| 701 CAAnimationGroup* updatedAnimation = [snapshotAnimation copy]; | 701 base::scoped_nsobject<CAAnimationGroup> updatedAnimation( |
| 702 static_cast<CAAnimationGroup*>([snapshotAnimation copy])); |
| 702 // Extract begin and end sizes of the card. | 703 // Extract begin and end sizes of the card. |
| 703 CAAnimation* cardAnimation = | 704 CAAnimation* cardAnimation = |
| 704 [self.layer animationForKey:kCardViewAnimationKey]; | 705 [self.layer animationForKey:kCardViewAnimationKey]; |
| 705 CABasicAnimation* cardBoundsAnimation = | 706 CABasicAnimation* cardBoundsAnimation = |
| 706 FindAnimationForKeyPath(@"bounds", cardAnimation); | 707 FindAnimationForKeyPath(@"bounds", cardAnimation); |
| 707 CGSize beginCardSize = [cardBoundsAnimation.fromValue CGRectValue].size; | 708 CGSize beginCardSize = [cardBoundsAnimation.fromValue CGRectValue].size; |
| 708 CGSize endCardSize = [cardBoundsAnimation.toValue CGRectValue].size; | 709 CGSize endCardSize = [cardBoundsAnimation.toValue CGRectValue].size; |
| 709 // Update the contentsRect animation. | 710 // Update the contentsRect animation. |
| 710 CABasicAnimation* contentsRectAnimation = | 711 CABasicAnimation* contentsRectAnimation = |
| 711 FindAnimationForKeyPath(@"contentsRect", updatedAnimation); | 712 FindAnimationForKeyPath(@"contentsRect", updatedAnimation); |
| (...skipping 26 matching lines...) Expand all Loading... |
| 738 } | 739 } |
| 739 return LayoutRectGetRect(maskLayout); | 740 return LayoutRectGetRect(maskLayout); |
| 740 } | 741 } |
| 741 | 742 |
| 742 - (void)updateShadowMask { | 743 - (void)updateShadowMask { |
| 743 if (!self.shouldShowShadow) | 744 if (!self.shouldShowShadow) |
| 744 return; | 745 return; |
| 745 | 746 |
| 746 if (self.shouldMaskShadow) { | 747 if (self.shouldMaskShadow) { |
| 747 if (!_shadowMask) { | 748 if (!_shadowMask) { |
| 748 _shadowMask = [[CALayer alloc] init]; | 749 _shadowMask.reset([[CALayer alloc] init]); |
| 749 [_shadowMask setBackgroundColor:[UIColor blackColor].CGColor]; | 750 [_shadowMask setBackgroundColor:[UIColor blackColor].CGColor]; |
| 750 } | 751 } |
| 751 [_frameShadowImageView layer].mask = _shadowMask; | 752 [_frameShadowImageView layer].mask = _shadowMask; |
| 752 [_shadowMask setFrame:[self shadowMaskFrameForBounds:self.bounds]]; | 753 [_shadowMask setFrame:[self shadowMaskFrameForBounds:self.bounds]]; |
| 753 } else { | 754 } else { |
| 754 [_frameShadowImageView layer].mask = nil; | 755 [_frameShadowImageView layer].mask = nil; |
| 755 } | 756 } |
| 756 } | 757 } |
| 757 | 758 |
| 758 - (LayoutRect)tabLayout { | 759 - (LayoutRect)tabLayout { |
| (...skipping 185 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 944 frameAnimation = FrameAnimationMake( | 945 frameAnimation = FrameAnimationMake( |
| 945 [_frameShadowImageView layer], | 946 [_frameShadowImageView layer], |
| 946 UIEdgeInsetsInsetRect(beginBounds, kCardShadowLayoutOutsets), | 947 UIEdgeInsetsInsetRect(beginBounds, kCardShadowLayoutOutsets), |
| 947 UIEdgeInsetsInsetRect(endBounds, kCardShadowLayoutOutsets)); | 948 UIEdgeInsetsInsetRect(endBounds, kCardShadowLayoutOutsets)); |
| 948 frameAnimation.duration = frameDuration; | 949 frameAnimation.duration = frameDuration; |
| 949 frameAnimation.timingFunction = frameTiming; | 950 frameAnimation.timingFunction = frameTiming; |
| 950 [[_frameShadowImageView layer] addAnimation:frameAnimation | 951 [[_frameShadowImageView layer] addAnimation:frameAnimation |
| 951 forKey:kCardViewAnimationKey]; | 952 forKey:kCardViewAnimationKey]; |
| 952 if (self.shouldMaskShadow) { | 953 if (self.shouldMaskShadow) { |
| 953 frameAnimation = FrameAnimationMake( | 954 frameAnimation = FrameAnimationMake( |
| 954 _shadowMask, [self shadowMaskFrameForBounds:beginBounds], | 955 _shadowMask.get(), [self shadowMaskFrameForBounds:beginBounds], |
| 955 [self shadowMaskFrameForBounds:endBounds]); | 956 [self shadowMaskFrameForBounds:endBounds]); |
| 956 frameAnimation.duration = frameDuration; | 957 frameAnimation.duration = frameDuration; |
| 957 frameAnimation.timingFunction = frameTiming; | 958 frameAnimation.timingFunction = frameTiming; |
| 958 [_shadowMask addAnimation:frameAnimation forKey:kCardViewAnimationKey]; | 959 [_shadowMask addAnimation:frameAnimation forKey:kCardViewAnimationKey]; |
| 959 } | 960 } |
| 960 } | 961 } |
| 961 | 962 |
| 962 // Update content snapshot | 963 // Update content snapshot |
| 963 CGRect beginContentFrame = | 964 CGRect beginContentFrame = |
| 964 UIEdgeInsetsInsetRect(beginBounds, kCardImageInsets); | 965 UIEdgeInsetsInsetRect(beginBounds, kCardImageInsets); |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1021 [_tab titleLabel]); | 1022 [_tab titleLabel]); |
| 1022 } | 1023 } |
| 1023 | 1024 |
| 1024 - (void)addAccessibilityTarget:(id)target action:(SEL)action { | 1025 - (void)addAccessibilityTarget:(id)target action:(SEL)action { |
| 1025 DCHECK(!target || [target respondsToSelector:action]); | 1026 DCHECK(!target || [target respondsToSelector:action]); |
| 1026 _accessibilityTarget = target; | 1027 _accessibilityTarget = target; |
| 1027 _accessibilityAction = action; | 1028 _accessibilityAction = action; |
| 1028 } | 1029 } |
| 1029 | 1030 |
| 1030 - (void)elementDidBecomeFocused:(id)sender { | 1031 - (void)elementDidBecomeFocused:(id)sender { |
| 1031 #pragma clang diagnostic push | |
| 1032 #pragma clang diagnostic ignored "-Warc-performSelector-leaks" | |
| 1033 [_accessibilityTarget performSelector:_accessibilityAction withObject:sender]; | 1032 [_accessibilityTarget performSelector:_accessibilityAction withObject:sender]; |
| 1034 #pragma clang diagnostic pop | |
| 1035 } | 1033 } |
| 1036 | 1034 |
| 1037 @end | 1035 @end |
| OLD | NEW |