Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(357)

Unified Diff: ios/chrome/browser/ui/tab_switcher/tab_switcher_panel_cell.mm

Issue 2588733002: Upstream Chrome on iOS source code [9/11]. (Closed)
Patch Set: Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: ios/chrome/browser/ui/tab_switcher/tab_switcher_panel_cell.mm
diff --git a/ios/chrome/browser/ui/tab_switcher/tab_switcher_panel_cell.mm b/ios/chrome/browser/ui/tab_switcher/tab_switcher_panel_cell.mm
new file mode 100644
index 0000000000000000000000000000000000000000..6b9072a3a96d42f683c4b431bef560c9af884802
--- /dev/null
+++ b/ios/chrome/browser/ui/tab_switcher/tab_switcher_panel_cell.mm
@@ -0,0 +1,456 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import "ios/chrome/browser/ui/tab_switcher/tab_switcher_panel_cell.h"
+
+#include "base/mac/scoped_nsobject.h"
+#import "ios/chrome/browser/tabs/tab.h"
+#import "ios/chrome/browser/ui/fade_truncated_label.h"
+#import "ios/chrome/browser/ui/image_util.h"
+#import "ios/chrome/browser/ui/tab_switcher/tab_switcher_button.h"
+#import "ios/chrome/browser/ui/tab_switcher/tab_switcher_cache.h"
+#import "ios/chrome/browser/ui/tab_switcher/tab_switcher_utils.h"
+#import "ios/chrome/browser/ui/uikit_ui_util.h"
+#include "ios/chrome/grit/ios_strings.h"
+#include "ios/chrome/grit/ios_theme_resources.h"
+#import "ios/third_party/material_components_ios/src/components/Palettes/src/MaterialPalettes.h"
+#import "ios/third_party/material_roboto_font_loader_ios/src/src/MaterialRobotoFontLoader.h"
+#import "ios/third_party/material_text_accessibility_ios/src/src/MDFTextAccessibility.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/gfx/image/image.h"
+#include "url/gurl.h"
+
+namespace gfx {
+class ImageSkia;
+}
+
+namespace {
+const CGFloat kFontSize = 16;
+const CGFloat kCellCornerRadius = 2;
+const CGFloat kBarHeight = 44;
+const CGFloat kTitleLabelTextAlpha = .54;
+const CGFloat kNewTabIconAlpha = .87;
+} // Anonymous namespace
+
+CGFloat tabSwitcherLocalSessionCellTopBarHeight() {
+ return kBarHeight;
+}
+
+@interface TabSwitcherSessionCell ()
+
+// Returns the container view with rounded corners to which all cell subviews
+// should be added.
+- (UIView*)containerView;
+
+@end
+
+@implementation TabSwitcherSessionCell {
+ base::scoped_nsobject<UIView> _containerView;
+ CGSize _cachedShadowSize;
+}
+
+// Returns the cell's identifier used for the cell's re-use.
++ (NSString*)identifier {
+ return NSStringFromClass([self class]);
+}
+
+- (instancetype)initWithFrame:(CGRect)frame {
+ self = [super initWithFrame:frame];
+ if (self) {
+ [self contentView].isAccessibilityElement = YES;
+ _containerView.reset([[UIView alloc] initWithFrame:self.bounds]);
+ [_containerView setAutoresizingMask:UIViewAutoresizingFlexibleHeight |
+ UIViewAutoresizingFlexibleWidth];
+ [[_containerView layer] setCornerRadius:kCellCornerRadius];
+ [[_containerView layer] setMasksToBounds:YES];
+ [[self contentView] addSubview:_containerView];
+ [self updateShadow];
+ [[[self contentView] layer] setShouldRasterize:YES];
+ [[[self contentView] layer]
+ setRasterizationScale:[[UIScreen mainScreen] scale]];
+ }
+ return self;
+}
+
+- (void)layoutSubviews {
+ [super layoutSubviews];
+ [self updateShadow];
+}
+
+- (void)updateShadow {
+ if (!CGSizeEqualToSize(_cachedShadowSize, self.bounds.size)) {
+ CGRect offsetedRectangle = CGRectOffset(self.bounds, 0, 6);
+ UIBezierPath* shadowPath =
+ [UIBezierPath bezierPathWithRoundedRect:offsetedRectangle
+ cornerRadius:kCellCornerRadius];
+ [[self contentView].layer setShadowPath:shadowPath.CGPath];
+ [[self contentView].layer setShadowColor:[UIColor blackColor].CGColor];
+ [[self contentView].layer setShadowOpacity:0.5];
+ _cachedShadowSize = self.bounds.size;
+ }
+}
+
+- (UIView*)containerView {
+ return _containerView.get();
+}
+
+@end
+
+@implementation TabSwitcherLocalSessionCell {
+ base::scoped_nsobject<UIView> _topBar;
+ base::scoped_nsobject<UILabel> _titleLabel;
+ base::scoped_nsobject<UIImageView> _favicon;
+ base::scoped_nsobject<UIButton> _closeButton;
+ base::scoped_nsobject<UIImageView> _shadow;
+ base::scoped_nsobject<UIImageView> _snapshot;
+ base::scoped_nsobject<TabSwitcherButton> _snapshotButton;
+ PendingSnapshotRequest _currentPendingSnapshotRequest;
+ id<SessionCellDelegate> _delegate; // weak
+}
+
+- (instancetype)initWithFrame:(CGRect)frame {
+ self = [super initWithFrame:frame];
+ if (self) {
+ // Top bar.
+ _topBar.reset([[UIView alloc] initWithFrame:CGRectZero]);
+ [_topBar setTranslatesAutoresizingMaskIntoConstraints:NO];
+ [[self containerView] addSubview:_topBar];
+
+ // Snapshot view.
+ _snapshot.reset([[UIImageView alloc] initWithFrame:CGRectZero]);
+ [_snapshot setTranslatesAutoresizingMaskIntoConstraints:NO];
+ [_snapshot setContentMode:UIViewContentModeScaleAspectFill];
+ [_snapshot setClipsToBounds:YES];
+ [[self containerView] addSubview:_snapshot];
+
+ // Cell button.
+ _snapshotButton.reset([[TabSwitcherButton alloc] initWithFrame:CGRectZero]);
+ [_snapshotButton setTranslatesAutoresizingMaskIntoConstraints:NO];
+ [_snapshotButton addTarget:self
+ action:@selector(snapshotPressed)
+ forControlEvents:UIControlEventTouchUpInside];
+ [[self containerView] addSubview:_snapshotButton];
+
+ // Shadow view.
+ _shadow.reset([[UIImageView alloc] initWithFrame:CGRectZero]);
+ [_shadow setTranslatesAutoresizingMaskIntoConstraints:NO];
+ ResourceBundle& rb = ResourceBundle::GetSharedInstance();
+ gfx::Image shadow = rb.GetNativeImageNamed(IDR_IOS_TOOLBAR_SHADOW);
+ [_shadow setImage:shadow.ToUIImage()];
+ [[self containerView] addSubview:_shadow];
+
+ // Constraints on the Top bar, snapshot view, and shadow view.
+ NSDictionary* viewsDictionary = @{
+ @"bar" : _topBar.get(),
+ @"shadow" : _shadow.get(),
+ @"snapshot" : _snapshot.get(),
+ @"snapshotButton" : _snapshotButton.get(),
+ };
+ NSArray* constraints = @[
+ @"H:|-0-[bar]-0-|",
+ @"H:|-0-[shadow]-0-|",
+ @"H:|-0-[snapshot]-0-|",
+ @"H:|-0-[snapshotButton]-0-|",
+ @"V:|-0-[bar(==barHeight)]-0-[snapshot]-0-|",
+ @"V:[bar]-0-[snapshotButton]-0-|",
+ @"V:[bar]-0-[shadow]",
+ ];
+ NSDictionary* metrics =
+ @{ @"barHeight" : @(tabSwitcherLocalSessionCellTopBarHeight()) };
+ ApplyVisualConstraintsWithMetrics(constraints, viewsDictionary, metrics,
+ [self containerView]);
+
+ // Create and add subviews to the cell bar.
+ // Title label.
+ _titleLabel.reset([[UILabel alloc] initWithFrame:CGRectZero]);
+ [_titleLabel setTranslatesAutoresizingMaskIntoConstraints:NO];
+ [_titleLabel setFont:[[MDFRobotoFontLoader sharedInstance]
+ regularFontOfSize:kFontSize]];
+ [_topBar addSubview:_titleLabel];
+
+ // Favicon.
+ _favicon.reset([[UIImageView alloc] initWithFrame:CGRectZero]);
+ [_favicon setTranslatesAutoresizingMaskIntoConstraints:NO];
+ [_topBar addSubview:_favicon];
+
+ // Close button.
+ _closeButton.reset([[UIButton alloc] initWithFrame:CGRectZero]);
+ [_closeButton
+ setImage:[[UIImage imageNamed:@"card_close_button"]
+ imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]
+ forState:UIControlStateNormal];
+ [_closeButton setTranslatesAutoresizingMaskIntoConstraints:NO];
+ [_closeButton addTarget:self
+ action:@selector(closeButtonPressed)
+ forControlEvents:UIControlEventTouchUpInside];
+ [_closeButton setExclusiveTouch:YES];
+ [_topBar addSubview:_closeButton];
+
+ // Constraints on the title label, favicon, and close button.
+ NSDictionary* barViewsDictionary = @{
+ @"favicon" : _favicon.get(),
+ @"title" : _titleLabel.get(),
+ @"closeButton" : _closeButton.get()
+ };
+ NSArray* barConstraints = @[
+ @"H:|-16-[favicon(==24)]-8-[title]-0-[closeButton(==32)]-8-|",
+ @"V:[favicon(==24)]",
+ @"V:[closeButton(==32)]",
+ ];
+ ApplyVisualConstraints(barConstraints, barViewsDictionary, _topBar);
+ AddSameCenterYConstraint(_topBar, _favicon);
+ AddSameCenterYConstraint(_topBar, _titleLabel);
+ AddSameCenterYConstraint(_topBar, _closeButton);
+ }
+ return self;
+}
+
+- (UIView*)topBar {
+ return _topBar.get();
+}
+
+- (UIImage*)screenshot {
+ return [_snapshot image];
+}
+
+- (void)setSnapshot:(UIImage*)image {
+ DCHECK(!ImageHasAlphaChannel(image));
+ [_snapshot setImage:image];
+}
+
+- (void)setAppearanceForTab:(Tab*)tab cellSize:(CGSize)cellSize {
+ [_titleLabel setText:tab.title];
+ [self contentView].accessibilityLabel = tab.title;
+ if (tab.favicon) {
+ [_favicon setImage:tab.favicon];
+ } else {
+ // No favicon is available, use placeholder instead.
+ ResourceBundle& rb = ResourceBundle::GetSharedInstance();
+ [_favicon
+ setImage:rb.GetNativeImageNamed(IDR_IOS_OMNIBOX_HTTP).ToUIImage()];
+ }
+
+ CGSize snapshotSize = cellSize;
+ snapshotSize.height -= tabSwitcherLocalSessionCellTopBarHeight();
+ base::WeakNSObject<TabSwitcherLocalSessionCell> weakCell(self);
+ _currentPendingSnapshotRequest =
+ [[self cache] requestSnapshotForTab:tab
+ withSize:snapshotSize
+ completionBlock:^(UIImage* image) {
+ DCHECK([NSThread isMainThread]);
+ [weakCell setSnapshot:image];
+ _currentPendingSnapshotRequest = {};
+ }];
+}
+
+- (void)setSessionType:(ios_internal::SessionType)type {
+ UIColor* topBarBackgroundColor;
+ UIColor* closeButtonTintColor;
+ UIColor* textColor;
+ UIColor* snapshotBackgroundColor;
+ if (type == ios_internal::SessionType::OFF_THE_RECORD_SESSION) {
+ topBarBackgroundColor = [[MDCPalette greyPalette] tint700];
+ closeButtonTintColor = [[MDCPalette greyPalette] tint100];
+ textColor = [[MDCPalette greyPalette] tint100];
+ snapshotBackgroundColor = [[MDCPalette greyPalette] tint900];
+ } else {
+ topBarBackgroundColor = [[MDCPalette greyPalette] tint100];
+ closeButtonTintColor = [[MDCPalette greyPalette] tint700];
+ textColor = [[MDCPalette greyPalette] tint700];
+ snapshotBackgroundColor = [UIColor whiteColor];
+ }
+ [_topBar setBackgroundColor:topBarBackgroundColor];
+ [[_closeButton imageView] setTintColor:closeButtonTintColor];
+ [_titleLabel setTextColor:textColor];
+ [_titleLabel setBackgroundColor:topBarBackgroundColor];
+ [_snapshot setBackgroundColor:snapshotBackgroundColor];
+}
+
+- (void)setDelegate:(id<SessionCellDelegate>)delegate {
+ _delegate = delegate;
+}
+
+- (void)snapshotPressed {
+ [_delegate cellPressed:self];
+}
+
+- (void)closeButtonPressed {
+ [_delegate deleteButtonPressedForCell:self];
+}
+
+- (void)prepareForReuse {
+ [[self cache] cancelPendingSnapshotRequest:_currentPendingSnapshotRequest];
+ _currentPendingSnapshotRequest.clear();
+ [_snapshot setImage:nil];
+ [_snapshotButton resetState];
+ [super prepareForReuse];
+}
+
+- (TabSwitcherCache*)cache {
+ return [_delegate tabSwitcherCache];
+}
+
+#pragma mark - UIAccessibilityAction
+
+- (NSArray*)accessibilityCustomActions {
+ base::scoped_nsobject<NSMutableArray> customActions(
+ [[NSMutableArray alloc] init]);
+ base::scoped_nsobject<UIAccessibilityCustomAction> customAction(
+ [[UIAccessibilityCustomAction alloc]
+ initWithName:l10n_util::GetNSString(IDS_IOS_TAB_SWITCHER_CLOSE_TAB)
+ target:self
+ selector:@selector(closeButtonPressed)]);
+ [customActions addObject:customAction.autorelease()];
+ return customActions.autorelease();
+}
+
+@end
+
+@implementation TabSwitcherDistantSessionCell {
+ base::scoped_nsobject<UILabel> _titleLabel;
+ base::scoped_nsobject<UIImageView> _favicon;
+ base::scoped_nsobject<UIImageView> _newTabIcon;
+ base::scoped_nsobject<UIView> _verticallyCenteredView;
+ base::scoped_nsobject<TabSwitcherButton> _raisedButton;
+ base::scoped_nsobject<NSOperation> _faviconObtainer;
+ id<SessionCellDelegate> _delegate; // weak
+}
+
+- (instancetype)initWithFrame:(CGRect)frame {
+ self = [super initWithFrame:frame];
+ if (self) {
+ // Create and add the button that contains all other subviews.
+ _raisedButton.reset([[TabSwitcherButton alloc] initWithFrame:CGRectZero]);
+ [_raisedButton setTranslatesAutoresizingMaskIntoConstraints:NO];
+ [_raisedButton addTarget:self
+ action:@selector(cellPressed)
+ forControlEvents:UIControlEventTouchUpInside];
+ [[self containerView] addSubview:_raisedButton];
+ ApplyVisualConstraints(@[ @"H:|-0-[button]-0-|", @"V:|-0-[button]-0-|" ],
+ @{ @"button" : _raisedButton.get() },
+ [self containerView]);
+
+ // Create and add view that will be vertically centered in the space over
+ // the favicon.
+ _verticallyCenteredView.reset([[UIView alloc] initWithFrame:CGRectZero]);
+ [_verticallyCenteredView setTranslatesAutoresizingMaskIntoConstraints:NO];
+ [_verticallyCenteredView setUserInteractionEnabled:NO];
+ [_raisedButton addSubview:_verticallyCenteredView];
+
+ // Create and add title label to |_verticallyCenteredContent|.
+ _titleLabel.reset([[UILabel alloc] initWithFrame:CGRectZero]);
+ [_titleLabel setTranslatesAutoresizingMaskIntoConstraints:NO];
+ [_titleLabel setNumberOfLines:5];
+ [_titleLabel setTextAlignment:NSTextAlignmentCenter];
+ [_titleLabel setFont:[[MDFRobotoFontLoader sharedInstance]
+ regularFontOfSize:kFontSize]];
+ [_verticallyCenteredView addSubview:_titleLabel];
+
+ // Create and add new tab icon to |_verticallyCenteredContent|.
+ UIImage* newTabIcon = [[UIImage imageNamed:@"tabswitcher_new_tab"]
+ imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
+ _newTabIcon.reset([[UIImageView alloc] initWithImage:newTabIcon]);
+ [_newTabIcon setAlpha:0];
+ [_newTabIcon setTranslatesAutoresizingMaskIntoConstraints:NO];
+ [_verticallyCenteredView addSubview:_newTabIcon];
+
+ // Create and add favicon image container.
+ _favicon.reset([[UIImageView alloc] initWithFrame:CGRectZero]);
+ [_favicon setTranslatesAutoresizingMaskIntoConstraints:NO];
+ [_raisedButton addSubview:_favicon];
+
+ // Add constraints to the button's subviews.
+ NSDictionary* viewsDictionary = @{
+ @"newTabIcon" : _newTabIcon.get(),
+ @"title" : _titleLabel.get(),
+ @"favicon" : _favicon.get(),
+ @"centeredView" : _verticallyCenteredView.get(),
+ };
+ NSArray* constraintsInButton = @[
+ @"H:|-0-[centeredView]-0-|",
+ @"H:[favicon(==16)]",
+ @"V:|-(>=16)-[centeredView]-(>=16)-[favicon(==16)]-16-|",
+ ];
+ ApplyVisualConstraints(constraintsInButton, viewsDictionary, _raisedButton);
+ AddSameCenterXConstraint(_raisedButton, _favicon.get());
+ [_raisedButton
+ addConstraint:[NSLayoutConstraint
+ constraintWithItem:_verticallyCenteredView.get()
+ attribute:NSLayoutAttributeCenterY
+ relatedBy:NSLayoutRelationEqual
+ toItem:_favicon.get()
+ attribute:NSLayoutAttributeCenterY
+ multiplier:0.5
+ constant:0]];
+
+ // Add constraints to the subviews of the vertically centered view.
+ NSArray* constraintsInVerticallyCenteredView = @[
+ @"H:|-16-[title]-16-|",
+ @"V:|-0-[newTabIcon(==24)]-16-[title(>=16)]-0-|",
+ ];
+ ApplyVisualConstraints(constraintsInVerticallyCenteredView, viewsDictionary,
+ _verticallyCenteredView);
+ AddSameCenterXConstraint(_verticallyCenteredView, _newTabIcon.get());
+ }
+ return self;
+}
+
+- (void)setTitle:(NSString*)titleString {
+ [_titleLabel setText:titleString];
+ [self contentView].accessibilityLabel = titleString;
+}
+
+- (void)setSessionGURL:(GURL const&)gurl
+ withBrowserState:(ios::ChromeBrowserState*)browserState {
+ ios_internal::FaviconGetterCompletionBlock block = ^(UIImage* favicon) {
+ UIColor* imageDominantColor =
+ DominantColorForImage(gfx::Image(favicon), 1.0);
+ MDCPalette* dominantPalette =
+ [MDCPalette paletteGeneratedFromColor:imageDominantColor];
+ UIColor* backgroundColor = dominantPalette.tint300;
+ UIColor* textColor =
+ [MDFTextAccessibility textColorOnBackgroundColor:backgroundColor
+ targetTextAlpha:kTitleLabelTextAlpha
+ font:[_titleLabel font]];
+ UIColor* iconColor =
+ [MDFTextAccessibility textColorOnBackgroundColor:backgroundColor
+ targetTextAlpha:kNewTabIconAlpha
+ font:[_titleLabel font]];
+ [_raisedButton setBackgroundColor:backgroundColor];
+ [_titleLabel setTextColor:textColor];
+ [_newTabIcon setTintColor:iconColor];
+ [_newTabIcon setAlpha:1.0];
+ [_favicon setImage:favicon];
+ [UIView animateWithDuration:0.2
+ animations:^{
+ [_raisedButton setAlpha:1.0];
+ }];
+ };
+ GURL gurlCopy = gurl;
+ _faviconObtainer.reset([[NSBlockOperation blockOperationWithBlock:^{
+ ios_internal::GetFavicon(gurlCopy, browserState, block);
+ }] retain]);
+ NSOperationQueue* operationQueue = [NSOperationQueue mainQueue];
+ [operationQueue addOperation:_faviconObtainer];
+}
+
+- (void)setDelegate:(id<SessionCellDelegate>)delegate {
+ _delegate = delegate;
+}
+
+- (void)cellPressed {
+ [_delegate cellPressed:self];
+}
+
+- (void)prepareForReuse {
+ [_newTabIcon setAlpha:0];
+ [_faviconObtainer cancel];
+ _faviconObtainer.reset();
+ [_raisedButton setAlpha:0];
+ [_raisedButton resetState];
+ [super prepareForReuse];
+}
+
+@end

Powered by Google App Engine
This is Rietveld 408576698