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 #import "base/mac/objc_property_releaser.h" | 29 |
30 #import "base/mac/scoped_nsobject.h" | |
31 #include "components/strings/grit/components_strings.h" | 30 #include "components/strings/grit/components_strings.h" |
32 #import "ios/chrome/browser/ui/animation_util.h" | 31 #import "ios/chrome/browser/ui/animation_util.h" |
33 #import "ios/chrome/browser/ui/reversed_animation.h" | 32 #import "ios/chrome/browser/ui/reversed_animation.h" |
34 #import "ios/chrome/browser/ui/rtl_geometry.h" | 33 #import "ios/chrome/browser/ui/rtl_geometry.h" |
35 #import "ios/chrome/browser/ui/stack_view/close_button.h" | 34 #import "ios/chrome/browser/ui/stack_view/close_button.h" |
36 #import "ios/chrome/browser/ui/stack_view/title_label.h" | 35 #import "ios/chrome/browser/ui/stack_view/title_label.h" |
37 #import "ios/chrome/browser/ui/ui_util.h" | 36 #import "ios/chrome/browser/ui/ui_util.h" |
38 #import "ios/chrome/common/material_timing.h" | 37 #import "ios/chrome/common/material_timing.h" |
39 #import "ios/third_party/material_components_ios/src/components/Typography/src/M
aterialTypography.h" | 38 #import "ios/third_party/material_components_ios/src/components/Typography/src/M
aterialTypography.h" |
40 #include "ui/base/l10n/l10n_util.h" | 39 #include "ui/base/l10n/l10n_util.h" |
41 #include "ui/base/resource/resource_bundle.h" | 40 #include "ui/base/resource/resource_bundle.h" |
42 #include "ui/gfx/favicon_size.h" | 41 #include "ui/gfx/favicon_size.h" |
43 #include "ui/gfx/image/image.h" | 42 #include "ui/gfx/image/image.h" |
44 #import "ui/gfx/ios/uikit_util.h" | 43 #import "ui/gfx/ios/uikit_util.h" |
45 | 44 |
| 45 #if !defined(__has_feature) || !__has_feature(objc_arc) |
| 46 #error "This file requires ARC support." |
| 47 #endif |
| 48 |
46 using ios::material::TimingFunction; | 49 using ios::material::TimingFunction; |
47 | 50 |
48 const UIEdgeInsets kCardImageInsets = {48.0, 4.0, 4.0, 4.0}; | 51 const UIEdgeInsets kCardImageInsets = {48.0, 4.0, 4.0, 4.0}; |
49 const CGFloat kCardFrameInset = 1.0; | 52 const CGFloat kCardFrameInset = 1.0; |
50 const CGFloat kCardShadowThickness = 16.0; | 53 const CGFloat kCardShadowThickness = 16.0; |
51 const CGFloat kCardFrameCornerRadius = 4.0; | 54 const CGFloat kCardFrameCornerRadius = 4.0; |
52 const CGFloat kCardTabTopInset = 4; | 55 const CGFloat kCardTabTopInset = 4; |
53 const CGFloat kCardFrameBackgroundBrightness = 242.0 / 255.0; | 56 const CGFloat kCardFrameBackgroundBrightness = 242.0 / 255.0; |
54 const CGFloat kCardFrameBackgroundBrightnessIncognito = 80.0 / 255.0; | 57 const CGFloat kCardFrameBackgroundBrightnessIncognito = 80.0 / 255.0; |
55 const CGFloat kCardFrameImageSnapshotOverlap = 1.0; | 58 const CGFloat kCardFrameImageSnapshotOverlap = 1.0; |
(...skipping 22 matching lines...) Expand all Loading... |
78 return [UIImage imageNamed:name]; | 81 return [UIImage imageNamed:name]; |
79 } | 82 } |
80 | 83 |
81 } // namespace | 84 } // namespace |
82 | 85 |
83 #pragma mark - | 86 #pragma mark - |
84 | 87 |
85 @interface CardTabView : UIView | 88 @interface CardTabView : UIView |
86 | 89 |
87 @property(nonatomic, assign) CardCloseButtonSide closeButtonSide; | 90 @property(nonatomic, assign) CardCloseButtonSide closeButtonSide; |
88 @property(nonatomic, retain) UIImageView* favIconView; | 91 @property(nonatomic, strong) UIImageView* favIconView; |
89 @property(nonatomic, retain) UIImage* favicon; | 92 @property(nonatomic, strong) UIImage* favicon; |
90 @property(nonatomic, retain) CloseButton* closeButton; | 93 @property(nonatomic, strong) CloseButton* closeButton; |
91 @property(nonatomic, retain) TitleLabel* titleLabel; | 94 @property(nonatomic, strong) TitleLabel* titleLabel; |
92 @property(nonatomic, assign) BOOL isIncognito; | 95 @property(nonatomic, assign) BOOL isIncognito; |
93 | 96 |
94 // Layout helper selectors that calculate the frames for subviews given the | 97 // Layout helper selectors that calculate the frames for subviews given the |
95 // bounds of the card tab. Note that the frames returned by these selectors | 98 // bounds of the card tab. Note that the frames returned by these selectors |
96 // will be different depending on the value of the |displaySide| property. | 99 // will be different depending on the value of the |displaySide| property. |
97 - (LayoutRect)faviconLayoutForBounds:(CGRect)bounds; | 100 - (LayoutRect)faviconLayoutForBounds:(CGRect)bounds; |
98 - (CGRect)faviconFrameForBounds:(CGRect)bounds; | 101 - (CGRect)faviconFrameForBounds:(CGRect)bounds; |
99 - (LayoutRect)titleLabelLayoutForBounds:(CGRect)bounds; | 102 - (LayoutRect)titleLabelLayoutForBounds:(CGRect)bounds; |
100 - (CGRect)titleLabelFrameForBounds:(CGRect)bounds; | 103 - (CGRect)titleLabelFrameForBounds:(CGRect)bounds; |
101 - (LayoutRect)closeButtonLayoutForBounds:(CGRect)bounds; | 104 - (LayoutRect)closeButtonLayoutForBounds:(CGRect)bounds; |
(...skipping 15 matching lines...) Expand all Loading... |
117 - (void)cleanUpAnimations; | 120 - (void)cleanUpAnimations; |
118 | 121 |
119 // Initialize a CardTabView with |frame| and |isIncognito| state. | 122 // Initialize a CardTabView with |frame| and |isIncognito| state. |
120 - (instancetype)initWithFrame:(CGRect)frame | 123 - (instancetype)initWithFrame:(CGRect)frame |
121 isIncognito:(BOOL)isIncognito NS_DESIGNATED_INITIALIZER; | 124 isIncognito:(BOOL)isIncognito NS_DESIGNATED_INITIALIZER; |
122 | 125 |
123 - (instancetype)initWithCoder:(NSCoder*)aDecoder NS_UNAVAILABLE; | 126 - (instancetype)initWithCoder:(NSCoder*)aDecoder NS_UNAVAILABLE; |
124 | 127 |
125 @end | 128 @end |
126 | 129 |
127 @implementation CardTabView { | 130 @implementation CardTabView |
128 base::mac::ObjCPropertyReleaser _propertyReleaser_CardTabView; | |
129 } | |
130 | 131 |
131 #pragma mark - Property Implementation | 132 #pragma mark - Property Implementation |
132 | 133 |
133 @synthesize closeButtonSide = _closeButtonSide; | 134 @synthesize closeButtonSide = _closeButtonSide; |
134 @synthesize favIconView = _faviconView; | 135 @synthesize favIconView = _faviconView; |
135 @synthesize favicon = _favicon; | 136 @synthesize favicon = _favicon; |
136 @synthesize closeButton = _closeButton; | 137 @synthesize closeButton = _closeButton; |
137 @synthesize titleLabel = _titleLabel; | 138 @synthesize titleLabel = _titleLabel; |
138 @synthesize isIncognito = _isIncognito; | 139 @synthesize isIncognito = _isIncognito; |
139 | 140 |
140 - (instancetype)initWithFrame:(CGRect)frame { | 141 - (instancetype)initWithFrame:(CGRect)frame { |
141 return [self initWithFrame:frame isIncognito:NO]; | 142 return [self initWithFrame:frame isIncognito:NO]; |
142 } | 143 } |
143 | 144 |
144 - (instancetype)initWithFrame:(CGRect)frame isIncognito:(BOOL)isIncognito { | 145 - (instancetype)initWithFrame:(CGRect)frame isIncognito:(BOOL)isIncognito { |
145 self = [super initWithFrame:frame]; | 146 self = [super initWithFrame:frame]; |
146 if (!self) | 147 if (!self) |
147 return self; | 148 return self; |
148 | 149 |
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]; | |
277 _favicon = favicon; | 275 _favicon = favicon; |
278 [self updateFaviconImage]; | 276 [self updateFaviconImage]; |
279 } | 277 } |
280 } | 278 } |
281 | 279 |
282 - (void)updateTitleColors { | 280 - (void)updateTitleColors { |
283 UIColor* titleColor = [UIColor blackColor]; | 281 UIColor* titleColor = [UIColor blackColor]; |
284 if (_isIncognito) | 282 if (_isIncognito) |
285 titleColor = [UIColor whiteColor]; | 283 titleColor = [UIColor whiteColor]; |
286 | 284 |
(...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
430 else if (element == _titleLabel) | 428 else if (element == _titleLabel) |
431 index = closeButtonLeading ? 1 : 0; | 429 index = closeButtonLeading ? 1 : 0; |
432 return index; | 430 return index; |
433 } | 431 } |
434 | 432 |
435 @end | 433 @end |
436 | 434 |
437 #pragma mark - | 435 #pragma mark - |
438 | 436 |
439 @interface CardView () { | 437 @interface CardView () { |
440 base::scoped_nsobject<UIImageView> _contents; | 438 UIImageView* _contents; |
441 base::scoped_nsobject<CardTabView> _tab; | 439 CardTabView* _tab; |
442 id _cardCloseTarget; // weak | 440 __weak id _cardCloseTarget; |
443 SEL _cardCloseAction; | 441 SEL _cardCloseAction; |
444 id _accessibilityTarget; // weak | 442 __weak id _accessibilityTarget; |
445 SEL _accessibilityAction; | 443 SEL _accessibilityAction; |
446 | 444 |
447 BOOL _isIncognito; // YES if the card should use the incognito styling. | 445 BOOL _isIncognito; // YES if the card should use the incognito styling. |
448 | 446 |
449 // Pieces of the card frame, split into four UIViews. | 447 // Pieces of the card frame, split into four UIViews. |
450 base::scoped_nsobject<UIImageView> _frameLeft; | 448 UIImageView* _frameLeft; |
451 base::scoped_nsobject<UIImageView> _frameRight; | 449 UIImageView* _frameRight; |
452 base::scoped_nsobject<UIImageView> _frameTop; | 450 UIImageView* _frameTop; |
453 base::scoped_nsobject<UIImageView> _frameBottom; | 451 UIImageView* _frameBottom; |
454 base::scoped_nsobject<UIImageView> _frameShadowImageView; | 452 UIImageView* _frameShadowImageView; |
455 base::scoped_nsobject<CALayer> _shadowMask; | 453 CALayer* _shadowMask; |
456 } | 454 } |
457 | 455 |
458 // The LayoutRect for the CardTabView. | 456 // The LayoutRect for the CardTabView. |
459 - (LayoutRect)tabLayout; | 457 - (LayoutRect)tabLayout; |
460 | 458 |
461 // Sends |_cardCloseAction| to |_cardCloseTarget| with |self| as the sender. | 459 // Sends |_cardCloseAction| to |_cardCloseTarget| with |self| as the sender. |
462 - (void)closeButtonWasTapped:(id)sender; | 460 - (void)closeButtonWasTapped:(id)sender; |
463 | 461 |
464 // Resizes/zooms the snapshot to avoid stretching given the card's current | 462 // Resizes/zooms the snapshot to avoid stretching given the card's current |
465 // bounds. | 463 // bounds. |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
504 if (!self) | 502 if (!self) |
505 return self; | 503 return self; |
506 | 504 |
507 _isIncognito = isIncognito; | 505 _isIncognito = isIncognito; |
508 CGRect bounds = self.bounds; | 506 CGRect bounds = self.bounds; |
509 | 507 |
510 self.opaque = NO; | 508 self.opaque = NO; |
511 self.contentMode = UIViewContentModeRedraw; | 509 self.contentMode = UIViewContentModeRedraw; |
512 | 510 |
513 CGRect shadowFrame = UIEdgeInsetsInsetRect(bounds, kCardShadowLayoutOutsets); | 511 CGRect shadowFrame = UIEdgeInsetsInsetRect(bounds, kCardShadowLayoutOutsets); |
514 _frameShadowImageView.reset([[UIImageView alloc] initWithFrame:shadowFrame]); | 512 _frameShadowImageView = [[UIImageView alloc] initWithFrame:shadowFrame]; |
515 [_frameShadowImageView | 513 [_frameShadowImageView |
516 setAutoresizingMask:(UIViewAutoresizingFlexibleWidth | | 514 setAutoresizingMask:(UIViewAutoresizingFlexibleWidth | |
517 UIViewAutoresizingFlexibleHeight)]; | 515 UIViewAutoresizingFlexibleHeight)]; |
518 [self addSubview:_frameShadowImageView]; | 516 [self addSubview:_frameShadowImageView]; |
519 | 517 |
520 // Calling properties for side-effects. | 518 // Calling properties for side-effects. |
521 self.shouldShowShadow = YES; | 519 self.shouldShowShadow = YES; |
522 self.shouldMaskShadow = YES; | 520 self.shouldMaskShadow = YES; |
523 | 521 |
524 UIImage* image = [UIImage imageNamed:kCardShadowImageName]; | 522 UIImage* image = [UIImage imageNamed:kCardShadowImageName]; |
525 image = [image resizableImageWithCapInsets:kShadowStretchInsets]; | 523 image = [image resizableImageWithCapInsets:kShadowStretchInsets]; |
526 [_frameShadowImageView setImage:image]; | 524 [_frameShadowImageView setImage:image]; |
527 | 525 |
528 CGRect snapshotFrame = UIEdgeInsetsInsetRect(bounds, kCardImageInsets); | 526 CGRect snapshotFrame = UIEdgeInsetsInsetRect(bounds, kCardImageInsets); |
529 _contents.reset([[UIImageView alloc] initWithFrame:snapshotFrame]); | 527 _contents = [[UIImageView alloc] initWithFrame:snapshotFrame]; |
530 [_contents setClipsToBounds:YES]; | 528 [_contents setClipsToBounds:YES]; |
531 [_contents setContentMode:UIViewContentModeScaleAspectFill]; | 529 [_contents setContentMode:UIViewContentModeScaleAspectFill]; |
532 [_contents setFrame:snapshotFrame]; | 530 [_contents setFrame:snapshotFrame]; |
533 [_contents setAutoresizingMask:UIViewAutoresizingFlexibleWidth | | 531 [_contents setAutoresizingMask:UIViewAutoresizingFlexibleWidth | |
534 UIViewAutoresizingFlexibleHeight]; | 532 UIViewAutoresizingFlexibleHeight]; |
535 [self addSubview:_contents]; | 533 [self addSubview:_contents]; |
536 | 534 |
537 image = [UIImage imageNamed:isIncognito ? @"border_frame_incognito_left" | 535 image = [UIImage imageNamed:isIncognito ? @"border_frame_incognito_left" |
538 : @"border_frame_left"]; | 536 : @"border_frame_left"]; |
539 UIEdgeInsets imageStretchInsets = UIEdgeInsetsMake( | 537 UIEdgeInsets imageStretchInsets = UIEdgeInsetsMake( |
540 0.5 * image.size.height, 0.0, 0.5 * image.size.height, 0.0); | 538 0.5 * image.size.height, 0.0, 0.5 * image.size.height, 0.0); |
541 image = [image resizableImageWithCapInsets:imageStretchInsets]; | 539 image = [image resizableImageWithCapInsets:imageStretchInsets]; |
542 _frameLeft.reset([[UIImageView alloc] initWithImage:image]); | 540 _frameLeft = [[UIImageView alloc] initWithImage:image]; |
543 [self addSubview:_frameLeft]; | 541 [self addSubview:_frameLeft]; |
544 | 542 |
545 image = [UIImage imageNamed:isIncognito ? @"border_frame_incognito_right" | 543 image = [UIImage imageNamed:isIncognito ? @"border_frame_incognito_right" |
546 : @"border_frame_right"]; | 544 : @"border_frame_right"]; |
547 imageStretchInsets = UIEdgeInsetsMake(0.5 * image.size.height, 0.0, | 545 imageStretchInsets = UIEdgeInsetsMake(0.5 * image.size.height, 0.0, |
548 0.5 * image.size.height, 0.0); | 546 0.5 * image.size.height, 0.0); |
549 image = [image resizableImageWithCapInsets:imageStretchInsets]; | 547 image = [image resizableImageWithCapInsets:imageStretchInsets]; |
550 _frameRight.reset([[UIImageView alloc] initWithImage:image]); | 548 _frameRight = [[UIImageView alloc] initWithImage:image]; |
551 [self addSubview:_frameRight]; | 549 [self addSubview:_frameRight]; |
552 | 550 |
553 image = [UIImage imageNamed:isIncognito ? @"border_frame_incognito_top" | 551 image = [UIImage imageNamed:isIncognito ? @"border_frame_incognito_top" |
554 : @"border_frame_top"]; | 552 : @"border_frame_top"]; |
555 imageStretchInsets = UIEdgeInsetsMake(0.0, 0.5 * image.size.width, 0.0, | 553 imageStretchInsets = UIEdgeInsetsMake(0.0, 0.5 * image.size.width, 0.0, |
556 0.5 * image.size.width); | 554 0.5 * image.size.width); |
557 image = [image resizableImageWithCapInsets:imageStretchInsets]; | 555 image = [image resizableImageWithCapInsets:imageStretchInsets]; |
558 _frameTop.reset([[UIImageView alloc] initWithImage:image]); | 556 _frameTop = [[UIImageView alloc] initWithImage:image]; |
559 [self addSubview:_frameTop]; | 557 [self addSubview:_frameTop]; |
560 | 558 |
561 image = [UIImage imageNamed:isIncognito ? @"border_frame_incognito_bottom" | 559 image = [UIImage imageNamed:isIncognito ? @"border_frame_incognito_bottom" |
562 : @"border_frame_bottom"]; | 560 : @"border_frame_bottom"]; |
563 imageStretchInsets = UIEdgeInsetsMake(0.0, 0.5 * image.size.width, 0.0, | 561 imageStretchInsets = UIEdgeInsetsMake(0.0, 0.5 * image.size.width, 0.0, |
564 0.5 * image.size.width); | 562 0.5 * image.size.width); |
565 image = [image resizableImageWithCapInsets:imageStretchInsets]; | 563 image = [image resizableImageWithCapInsets:imageStretchInsets]; |
566 _frameBottom.reset([[UIImageView alloc] initWithImage:image]); | 564 _frameBottom = [[UIImageView alloc] initWithImage:image]; |
567 [self addSubview:_frameBottom]; | 565 [self addSubview:_frameBottom]; |
568 | 566 |
569 _tab.reset([[CardTabView alloc] | 567 _tab = [[CardTabView alloc] initWithFrame:LayoutRectGetRect([self tabLayout]) |
570 initWithFrame:LayoutRectGetRect([self tabLayout]) | 568 isIncognito:_isIncognito]; |
571 isIncognito:_isIncognito]); | |
572 [_tab setCloseButtonSide:IsPortrait() ? CardCloseButtonSide::TRAILING | 569 [_tab setCloseButtonSide:IsPortrait() ? CardCloseButtonSide::TRAILING |
573 : CardCloseButtonSide::LEADING]; | 570 : CardCloseButtonSide::LEADING]; |
574 [[_tab closeButton] addTarget:self | 571 [[_tab closeButton] addTarget:self |
575 action:@selector(closeButtonWasTapped:) | 572 action:@selector(closeButtonWasTapped:) |
576 forControlEvents:UIControlEventTouchUpInside]; | 573 forControlEvents:UIControlEventTouchUpInside]; |
577 [[_tab closeButton] | 574 [[_tab closeButton] |
578 addAccessibilityElementFocusedTarget:self | 575 addAccessibilityElementFocusedTarget:self |
579 action:@selector(elementDidBecomeFocused:)]; | 576 action:@selector(elementDidBecomeFocused:)]; |
580 [_tab closeButton].accessibilityIdentifier = [self closeButtonId]; | 577 [_tab closeButton].accessibilityIdentifier = [self closeButtonId]; |
581 | 578 |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
640 | 637 |
641 - (TitleLabel*)titleLabel { | 638 - (TitleLabel*)titleLabel { |
642 return [_tab titleLabel]; | 639 return [_tab titleLabel]; |
643 } | 640 } |
644 | 641 |
645 - (void)setFavicon:(UIImage*)favicon { | 642 - (void)setFavicon:(UIImage*)favicon { |
646 [_tab setFavicon:favicon]; | 643 [_tab setFavicon:favicon]; |
647 } | 644 } |
648 | 645 |
649 - (void)closeButtonWasTapped:(id)sender { | 646 - (void)closeButtonWasTapped:(id)sender { |
| 647 #pragma clang diagnostic push |
| 648 #pragma clang diagnostic ignored "-Warc-performSelector-leaks" |
650 [_cardCloseTarget performSelector:_cardCloseAction withObject:self]; | 649 [_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.get(); | 682 UIImageView* imageView = _contents; |
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 base::scoped_nsobject<CAAnimationGroup> updatedAnimation( | 701 CAAnimationGroup* updatedAnimation = [snapshotAnimation copy]; |
702 static_cast<CAAnimationGroup*>([snapshotAnimation copy])); | |
703 // Extract begin and end sizes of the card. | 702 // Extract begin and end sizes of the card. |
704 CAAnimation* cardAnimation = | 703 CAAnimation* cardAnimation = |
705 [self.layer animationForKey:kCardViewAnimationKey]; | 704 [self.layer animationForKey:kCardViewAnimationKey]; |
706 CABasicAnimation* cardBoundsAnimation = | 705 CABasicAnimation* cardBoundsAnimation = |
707 FindAnimationForKeyPath(@"bounds", cardAnimation); | 706 FindAnimationForKeyPath(@"bounds", cardAnimation); |
708 CGSize beginCardSize = [cardBoundsAnimation.fromValue CGRectValue].size; | 707 CGSize beginCardSize = [cardBoundsAnimation.fromValue CGRectValue].size; |
709 CGSize endCardSize = [cardBoundsAnimation.toValue CGRectValue].size; | 708 CGSize endCardSize = [cardBoundsAnimation.toValue CGRectValue].size; |
710 // Update the contentsRect animation. | 709 // Update the contentsRect animation. |
711 CABasicAnimation* contentsRectAnimation = | 710 CABasicAnimation* contentsRectAnimation = |
712 FindAnimationForKeyPath(@"contentsRect", updatedAnimation); | 711 FindAnimationForKeyPath(@"contentsRect", updatedAnimation); |
(...skipping 26 matching lines...) Expand all Loading... |
739 } | 738 } |
740 return LayoutRectGetRect(maskLayout); | 739 return LayoutRectGetRect(maskLayout); |
741 } | 740 } |
742 | 741 |
743 - (void)updateShadowMask { | 742 - (void)updateShadowMask { |
744 if (!self.shouldShowShadow) | 743 if (!self.shouldShowShadow) |
745 return; | 744 return; |
746 | 745 |
747 if (self.shouldMaskShadow) { | 746 if (self.shouldMaskShadow) { |
748 if (!_shadowMask) { | 747 if (!_shadowMask) { |
749 _shadowMask.reset([[CALayer alloc] init]); | 748 _shadowMask = [[CALayer alloc] init]; |
750 [_shadowMask setBackgroundColor:[UIColor blackColor].CGColor]; | 749 [_shadowMask setBackgroundColor:[UIColor blackColor].CGColor]; |
751 } | 750 } |
752 [_frameShadowImageView layer].mask = _shadowMask; | 751 [_frameShadowImageView layer].mask = _shadowMask; |
753 [_shadowMask setFrame:[self shadowMaskFrameForBounds:self.bounds]]; | 752 [_shadowMask setFrame:[self shadowMaskFrameForBounds:self.bounds]]; |
754 } else { | 753 } else { |
755 [_frameShadowImageView layer].mask = nil; | 754 [_frameShadowImageView layer].mask = nil; |
756 } | 755 } |
757 } | 756 } |
758 | 757 |
759 - (LayoutRect)tabLayout { | 758 - (LayoutRect)tabLayout { |
(...skipping 185 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
945 frameAnimation = FrameAnimationMake( | 944 frameAnimation = FrameAnimationMake( |
946 [_frameShadowImageView layer], | 945 [_frameShadowImageView layer], |
947 UIEdgeInsetsInsetRect(beginBounds, kCardShadowLayoutOutsets), | 946 UIEdgeInsetsInsetRect(beginBounds, kCardShadowLayoutOutsets), |
948 UIEdgeInsetsInsetRect(endBounds, kCardShadowLayoutOutsets)); | 947 UIEdgeInsetsInsetRect(endBounds, kCardShadowLayoutOutsets)); |
949 frameAnimation.duration = frameDuration; | 948 frameAnimation.duration = frameDuration; |
950 frameAnimation.timingFunction = frameTiming; | 949 frameAnimation.timingFunction = frameTiming; |
951 [[_frameShadowImageView layer] addAnimation:frameAnimation | 950 [[_frameShadowImageView layer] addAnimation:frameAnimation |
952 forKey:kCardViewAnimationKey]; | 951 forKey:kCardViewAnimationKey]; |
953 if (self.shouldMaskShadow) { | 952 if (self.shouldMaskShadow) { |
954 frameAnimation = FrameAnimationMake( | 953 frameAnimation = FrameAnimationMake( |
955 _shadowMask.get(), [self shadowMaskFrameForBounds:beginBounds], | 954 _shadowMask, [self shadowMaskFrameForBounds:beginBounds], |
956 [self shadowMaskFrameForBounds:endBounds]); | 955 [self shadowMaskFrameForBounds:endBounds]); |
957 frameAnimation.duration = frameDuration; | 956 frameAnimation.duration = frameDuration; |
958 frameAnimation.timingFunction = frameTiming; | 957 frameAnimation.timingFunction = frameTiming; |
959 [_shadowMask addAnimation:frameAnimation forKey:kCardViewAnimationKey]; | 958 [_shadowMask addAnimation:frameAnimation forKey:kCardViewAnimationKey]; |
960 } | 959 } |
961 } | 960 } |
962 | 961 |
963 // Update content snapshot | 962 // Update content snapshot |
964 CGRect beginContentFrame = | 963 CGRect beginContentFrame = |
965 UIEdgeInsetsInsetRect(beginBounds, kCardImageInsets); | 964 UIEdgeInsetsInsetRect(beginBounds, kCardImageInsets); |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1022 [_tab titleLabel]); | 1021 [_tab titleLabel]); |
1023 } | 1022 } |
1024 | 1023 |
1025 - (void)addAccessibilityTarget:(id)target action:(SEL)action { | 1024 - (void)addAccessibilityTarget:(id)target action:(SEL)action { |
1026 DCHECK(!target || [target respondsToSelector:action]); | 1025 DCHECK(!target || [target respondsToSelector:action]); |
1027 _accessibilityTarget = target; | 1026 _accessibilityTarget = target; |
1028 _accessibilityAction = action; | 1027 _accessibilityAction = action; |
1029 } | 1028 } |
1030 | 1029 |
1031 - (void)elementDidBecomeFocused:(id)sender { | 1030 - (void)elementDidBecomeFocused:(id)sender { |
| 1031 #pragma clang diagnostic push |
| 1032 #pragma clang diagnostic ignored "-Warc-performSelector-leaks" |
1032 [_accessibilityTarget performSelector:_accessibilityAction withObject:sender]; | 1033 [_accessibilityTarget performSelector:_accessibilityAction withObject:sender]; |
| 1034 #pragma clang diagnostic pop |
1033 } | 1035 } |
1034 | 1036 |
1035 @end | 1037 @end |
OLD | NEW |