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

Unified Diff: ios/chrome/browser/ui/sad_tab/sad_tab_view.mm

Issue 2589583003: Upstream Chrome on iOS source code [7/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
« no previous file with comments | « ios/chrome/browser/ui/sad_tab/sad_tab_view.h ('k') | ios/chrome/browser/ui/settings/README.md » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: ios/chrome/browser/ui/sad_tab/sad_tab_view.mm
diff --git a/ios/chrome/browser/ui/sad_tab/sad_tab_view.mm b/ios/chrome/browser/ui/sad_tab/sad_tab_view.mm
new file mode 100644
index 0000000000000000000000000000000000000000..f791f5de78735fb53caf1963b54bacf570e13443
--- /dev/null
+++ b/ios/chrome/browser/ui/sad_tab/sad_tab_view.mm
@@ -0,0 +1,401 @@
+// 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/sad_tab/sad_tab_view.h"
+
+#import "base/ios/weak_nsobject.h"
+#include "base/logging.h"
+#include "base/mac/scoped_block.h"
+#include "base/mac/scoped_nsobject.h"
+#include "base/strings/sys_string_conversions.h"
+#include "components/grit/components_scaled_resources.h"
+#include "components/strings/grit/components_strings.h"
+#include "ios/chrome/browser/chrome_url_constants.h"
+#import "ios/chrome/browser/ui/colors/MDCPalette+CrAdditions.h"
+#import "ios/chrome/browser/ui/commands/UIKit+ChromeExecuteCommand.h"
+#import "ios/chrome/browser/ui/commands/open_url_command.h"
+#include "ios/chrome/browser/ui/rtl_geometry.h"
+#include "ios/chrome/browser/ui/ui_util.h"
+#import "ios/chrome/browser/ui/url_loader.h"
+#import "ios/chrome/browser/ui/util/label_link_controller.h"
+#import "ios/third_party/material_components_ios/src/components/Buttons/src/MaterialButtons.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"
+#include "ios/web/public/interstitials/web_interstitial.h"
+#include "ios/web/public/web_state/web_state.h"
+#import "net/base/mac/url_conversions.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/gfx/image/image.h"
+
+namespace {
+// Color constants.
+const CGFloat kBackgroundColorBrightness = 247.0f / 255.0f;
+const CGFloat kTitleLabelTextColorBrightness = 22.0f / 255.0f;
+const CGFloat kMessageLabelTextColorBrightness = 80.0f / 255.0f;
+// Layout constants.
+const UIEdgeInsets kLayoutInsets = {24.0f, 24.0f, 24.0f, 24.0f};
+const CGFloat kLayoutBoundsMaxWidth = 600.0f;
+const CGFloat kContainerViewLandscapeTopPadding = 22.0f;
+const CGFloat kTitleLabelTopPadding = 26.0f;
+const CGFloat kMessageLabelTopPadding = 16.0f;
+const CGFloat kHelpLabelTopPadding = 16.0f;
+const CGFloat kReloadButtonHeight = 48.0f;
+const CGFloat kReloadButtonTopPadding = 16.0f;
+// Label font sizes.
+const CGFloat kTitleLabelFontSize = 23.0f;
+const CGFloat kMessageLabelFontSize = 14.0f;
+const CGFloat kHelpLabelFontSize = 14.0f;
+} // namespace
+
+@interface SadTabView () {
+ // The block called when |_reloadButton| is tapped.
+ base::mac::ScopedBlock<ProceduralBlock> _reloadHandler;
+ // Backing objects for properties of the same name.
+ base::scoped_nsobject<UIView> _containerView;
+ base::scoped_nsobject<UIImageView> _imageView;
+ base::scoped_nsobject<UILabel> _titleLabel;
+ base::scoped_nsobject<UILabel> _messageLabel;
+ base::scoped_nsobject<UILabel> _helpLabel;
+ base::scoped_nsobject<LabelLinkController> _helpLabelLinkController;
+ base::scoped_nsobject<MDCButton> _reloadButton;
+}
+
+// Container view that displays all other subviews.
+@property(nonatomic, readonly) UIView* containerView;
+// Displays the Sad Tab face.
+@property(nonatomic, readonly) UIImageView* imageView;
+// Displays the Sad Tab title.
+@property(nonatomic, readonly) UILabel* titleLabel;
+// Displays the Sad Tab message.
+@property(nonatomic, readonly) UILabel* messageLabel;
+// Displays the Sad Tab help message.
+@property(nonatomic, readonly) UILabel* helpLabel;
+// Button used to trigger a reload.
+@property(nonatomic, readonly) UIButton* reloadButton;
+
+// The bounds of |containerView|, with a height updated to CGFLOAT_MAX to allow
+// text to be laid out using as many lines as necessary.
+@property(nonatomic, readonly) CGRect containerBounds;
+
+// Subview layout methods. Must be called in the following order, as subsequent
+// layouts reference the values set in previous functions.
+- (void)layoutImageView;
+- (void)layoutTitleLabel;
+- (void)layoutMessageLabel;
+- (void)layoutHelpLabel;
+- (void)layoutReloadButton;
+- (void)layoutContainerView;
+
+// The action selector for |_reloadButton|.
+- (void)handleReloadButtonTapped;
+
+// Returns the desired background color.
++ (UIColor*)sadTabBackgroundColor;
+
+@end
+
+#pragma mark - SadTabView
+
+@implementation SadTabView
+
+- (instancetype)initWithReloadHandler:(ProceduralBlock)reloadHandler {
+ self = [super initWithFrame:CGRectZero];
+ if (self) {
+ DCHECK(reloadHandler);
+ _reloadHandler.reset([reloadHandler copy]);
+ self.backgroundColor = [[self class] sadTabBackgroundColor];
+ }
+ return self;
+}
+
+- (instancetype)init {
+ NOTREACHED();
+ return nil;
+}
+
+- (instancetype)initWithFrame:(CGRect)frame {
+ NOTREACHED();
+ return nil;
+}
+
+- (instancetype)initWithCoder:(NSCoder*)aDecoder {
+ NOTREACHED();
+ return nil;
+}
+
+#pragma mark Accessors
+
+- (UIView*)containerView {
+ if (!_containerView) {
+ _containerView.reset([[UIView alloc] initWithFrame:CGRectZero]);
+ [_containerView setBackgroundColor:self.backgroundColor];
+ }
+ return _containerView;
+}
+
+- (UIImageView*)imageView {
+ if (!_imageView) {
+ ui::ResourceBundle& resourceBundle =
+ ui::ResourceBundle::GetSharedInstance();
+ UIImage* image =
+ resourceBundle.GetNativeImageNamed(IDR_CRASH_SAD_TAB).ToUIImage();
+ _imageView.reset([[UIImageView alloc] initWithImage:image]);
+ [_imageView setBackgroundColor:self.backgroundColor];
+ }
+ return _imageView.get();
+}
+
+- (UILabel*)titleLabel {
+ if (!_titleLabel) {
+ _titleLabel.reset([[UILabel alloc] initWithFrame:CGRectZero]);
+ [_titleLabel setBackgroundColor:self.backgroundColor];
+ [_titleLabel setText:base::SysUTF8ToNSString(
+ l10n_util::GetStringUTF8(IDS_SAD_TAB_TITLE))];
+ [_titleLabel setLineBreakMode:NSLineBreakByWordWrapping];
+ [_titleLabel setNumberOfLines:0];
+ [_titleLabel
+ setTextColor:[UIColor colorWithWhite:kTitleLabelTextColorBrightness
+ alpha:1.0]];
+ [_titleLabel setFont:[[MDFRobotoFontLoader sharedInstance]
+ regularFontOfSize:kTitleLabelFontSize]];
+ }
+ return _titleLabel.get();
+}
+
+- (UILabel*)messageLabel {
+ if (!_messageLabel) {
+ _messageLabel.reset([[UILabel alloc] initWithFrame:CGRectZero]);
+ [_messageLabel setBackgroundColor:self.backgroundColor];
+ std::string messageText = l10n_util::GetStringUTF8(IDS_SAD_TAB_MESSAGE);
+ [_messageLabel setText:base::SysUTF8ToNSString(messageText)];
+ [_messageLabel setLineBreakMode:NSLineBreakByWordWrapping];
+ [_messageLabel setNumberOfLines:0];
+ [_messageLabel
+ setTextColor:[UIColor colorWithWhite:kMessageLabelTextColorBrightness
+ alpha:1.0]];
+ [_messageLabel setFont:[[MDFRobotoFontLoader sharedInstance]
+ regularFontOfSize:kMessageLabelFontSize]];
+ }
+ return _messageLabel.get();
+}
+
+- (UILabel*)helpLabel {
+ if (!_helpLabel) {
+ _helpLabel.reset([[UILabel alloc] initWithFrame:CGRectZero]);
+ [_helpLabel setBackgroundColor:self.backgroundColor];
+ [_helpLabel setNumberOfLines:0];
+ [_helpLabel setFont:[[MDFRobotoFontLoader sharedInstance]
+ regularFontOfSize:kHelpLabelFontSize]];
+ [_helpLabel
+ setTextColor:[UIColor colorWithWhite:kMessageLabelTextColorBrightness
+ alpha:1.0]];
+ // Fetch help text.
+ base::string16 helpLinkText(
+ l10n_util::GetStringUTF16(IDS_SAD_TAB_HELP_LINK));
+ NSString* helpText = base::SysUTF16ToNSString(
+ l10n_util::GetStringFUTF16(IDS_SAD_TAB_HELP_MESSAGE, helpLinkText));
+ [_helpLabel setText:helpText];
+ // Create link controller.
+ base::WeakNSObject<SadTabView> weakSelf(self);
+ _helpLabelLinkController.reset([[LabelLinkController alloc]
+ initWithLabel:_helpLabel
+ action:^(const GURL& url) {
+ base::scoped_nsobject<OpenUrlCommand> openCommand(
+ [[OpenUrlCommand alloc] initWithURLFromChrome:url]);
+ [weakSelf chromeExecuteCommand:openCommand];
+ }]);
+ [_helpLabelLinkController
+ setLinkFont:[[MDFRobotoFontLoader sharedInstance]
+ boldFontOfSize:kHelpLabelFontSize]];
+ [_helpLabelLinkController setLinkUnderlineStyle:NSUnderlineStyleSingle];
+ NSRange linkRange =
+ [helpText rangeOfString:base::SysUTF16ToNSString(helpLinkText)];
+ DCHECK_NE(linkRange.location, static_cast<NSUInteger>(NSNotFound));
+ DCHECK_NE(linkRange.length, 0U);
+ [_helpLabelLinkController addLinkWithRange:linkRange
+ url:GURL(kCrashReasonURL)];
+ }
+ return _helpLabel.get();
+}
+
+- (UIButton*)reloadButton {
+ if (!_reloadButton) {
+ _reloadButton.reset([[MDCFlatButton alloc] init]);
+ [_reloadButton setBackgroundColor:[[MDCPalette cr_bluePalette] tint500]
+ forState:UIControlStateNormal];
+ [_reloadButton setBackgroundColor:[[MDCPalette greyPalette] tint500]
+ forState:UIControlStateDisabled];
+ [_reloadButton setCustomTitleColor:[UIColor whiteColor]];
+ [_reloadButton setUnderlyingColorHint:[UIColor blackColor]];
+ [_reloadButton setInkColor:[UIColor colorWithWhite:1 alpha:0.2f]];
+ NSString* title = base::SysUTF8ToNSString(
+ l10n_util::GetStringUTF8(IDS_SAD_TAB_RELOAD_LABEL));
+ [_reloadButton setTitle:title forState:UIControlStateNormal];
+ [_reloadButton setTitleColor:[UIColor whiteColor]
+ forState:UIControlStateNormal];
+ [_reloadButton addTarget:self
+ action:@selector(handleReloadButtonTapped)
+ forControlEvents:UIControlEventTouchUpInside];
+ }
+ return _reloadButton.get();
+}
+
+- (CGRect)containerBounds {
+ CGFloat containerWidth = std::min(
+ CGRectGetWidth(self.bounds) - kLayoutInsets.left - kLayoutInsets.right,
+ kLayoutBoundsMaxWidth);
+ return CGRectMake(0.0, 0.0, containerWidth, CGFLOAT_MAX);
+}
+
+#pragma mark Layout
+
+- (void)willMoveToSuperview:(nullable UIView*)newSuperview {
+ [super willMoveToSuperview:newSuperview];
+
+ if (self.containerView.superview) {
+ DCHECK_EQ(self.containerView.superview, self);
+ return;
+ }
+
+ [self addSubview:self.containerView];
+ [self.containerView addSubview:self.imageView];
+ [self.containerView addSubview:self.titleLabel];
+ [self.containerView addSubview:self.messageLabel];
+ [self.containerView addSubview:self.helpLabel];
+}
+
+- (void)layoutSubviews {
+ [super layoutSubviews];
+
+ [self layoutImageView];
+ [self layoutTitleLabel];
+ [self layoutMessageLabel];
+ [self layoutHelpLabel];
+ [self layoutReloadButton];
+ [self layoutContainerView];
+}
+
+- (CGSize)sizeThatFits:(CGSize)size {
+ return size;
+}
+
+- (void)layoutImageView {
+ LayoutRect imageViewLayout = LayoutRectZero;
+ imageViewLayout.boundingWidth = CGRectGetWidth(self.containerBounds);
+ imageViewLayout.size = self.imageView.bounds.size;
+ self.imageView.frame =
+ AlignRectOriginAndSizeToPixels(LayoutRectGetRect(imageViewLayout));
+}
+
+- (void)layoutTitleLabel {
+ CGRect containerBounds = self.containerBounds;
+ LayoutRect titleLabelLayout = LayoutRectZero;
+ titleLabelLayout.boundingWidth = CGRectGetWidth(containerBounds);
+ titleLabelLayout.size = [self.titleLabel sizeThatFits:containerBounds.size];
+ titleLabelLayout.position.originY =
+ CGRectGetMaxY(self.imageView.frame) + kTitleLabelTopPadding;
+ self.titleLabel.frame =
+ AlignRectOriginAndSizeToPixels(LayoutRectGetRect(titleLabelLayout));
+}
+
+- (void)layoutMessageLabel {
+ CGRect containerBounds = self.containerBounds;
+ LayoutRect messageLabelLayout = LayoutRectZero;
+ messageLabelLayout.boundingWidth = CGRectGetWidth(containerBounds);
+ messageLabelLayout.size =
+ [self.messageLabel sizeThatFits:containerBounds.size];
+ messageLabelLayout.position.originY =
+ CGRectGetMaxY(self.titleLabel.frame) + kMessageLabelTopPadding;
+ self.messageLabel.frame =
+ AlignRectOriginAndSizeToPixels(LayoutRectGetRect(messageLabelLayout));
+}
+
+- (void)layoutHelpLabel {
+ CGRect containerBounds = self.containerBounds;
+ LayoutRect helpLabelLayout = LayoutRectZero;
+ helpLabelLayout.boundingWidth = CGRectGetWidth(containerBounds);
+ helpLabelLayout.size = [self.helpLabel sizeThatFits:containerBounds.size];
+ helpLabelLayout.position.originY =
+ CGRectGetMaxY(self.messageLabel.frame) + kHelpLabelTopPadding;
+ self.helpLabel.frame =
+ AlignRectOriginAndSizeToPixels(LayoutRectGetRect(helpLabelLayout));
+}
+
+- (void)layoutReloadButton {
+ CGRect containerBounds = self.containerBounds;
+ BOOL isIPadIdiom = IsIPadIdiom();
+ BOOL isPortrait = IsPortrait();
+ BOOL shouldAddReloadButtonToContainer = isIPadIdiom || !isPortrait;
+ LayoutRect reloadButtonLayout = LayoutRectZero;
+ reloadButtonLayout.size =
+ isIPadIdiom
+ ? [self.reloadButton sizeThatFits:CGSizeZero]
+ : CGSizeMake(CGRectGetWidth(containerBounds), kReloadButtonHeight);
+ if (shouldAddReloadButtonToContainer) {
+ // Right-align reloadButton and add it below helpLabel when adding it to
+ // the containerView.
+ if (self.reloadButton.superview != self.containerView)
+ [self.containerView addSubview:self.reloadButton];
+ reloadButtonLayout.boundingWidth = CGRectGetWidth(containerBounds);
+ reloadButtonLayout.position = LayoutRectPositionMake(
+ CGRectGetWidth(containerBounds) - reloadButtonLayout.size.width,
+ CGRectGetMaxY(self.helpLabel.frame) + kReloadButtonTopPadding);
+ } else {
+ // Bottom-align the reloadButton with the bounds specified by kLayoutInsets.
+ if (self.reloadButton.superview != self)
+ [self addSubview:self.reloadButton];
+ reloadButtonLayout.boundingWidth = CGRectGetWidth(self.bounds);
+ reloadButtonLayout.position = LayoutRectPositionMake(
+ UIEdgeInsetsGetLeading(kLayoutInsets),
+ CGRectGetMaxY(self.bounds) - kLayoutInsets.bottom -
+ reloadButtonLayout.size.height);
+ }
+ self.reloadButton.frame =
+ AlignRectOriginAndSizeToPixels(LayoutRectGetRect(reloadButtonLayout));
+}
+
+- (void)layoutContainerView {
+ UIView* bottomSubview = self.reloadButton.superview == self.containerView
+ ? self.reloadButton
+ : self.helpLabel;
+ CGSize containerSize = CGSizeMake(CGRectGetWidth(self.containerBounds),
+ CGRectGetMaxY(bottomSubview.frame));
+ CGFloat containerOriginX =
+ (CGRectGetWidth(self.bounds) - containerSize.width) / 2.0f;
+ CGFloat containerOriginY = 0.0f;
+ if (IsIPadIdiom()) {
+ // Center the containerView on iPads.
+ containerOriginY =
+ (CGRectGetHeight(self.bounds) - containerSize.height) / 2.0f;
+ } else if (IsPortrait()) {
+ // Align containerView to a quarter of the view height on portrait iPhones.
+ containerOriginY =
+ (CGRectGetHeight(self.bounds) - containerSize.height) / 4.0f;
+ } else {
+ // Top-align containerView on landscape iPhones.
+ containerOriginY = kContainerViewLandscapeTopPadding;
+ }
+ self.containerView.frame = AlignRectOriginAndSizeToPixels(
+ CGRectMake(containerOriginX, containerOriginY, containerSize.width,
+ containerSize.height));
+}
+
+#pragma mark Util
+
+- (void)handleHelpLabelLinkButtonTapped {
+ base::scoped_nsobject<OpenUrlCommand> openCommand(
+ [[OpenUrlCommand alloc] initWithURLFromChrome:GURL(kCrashReasonURL)]);
+ [self chromeExecuteCommand:openCommand];
+}
+
+- (void)handleReloadButtonTapped {
+ _reloadHandler.get()();
+}
+
++ (UIColor*)sadTabBackgroundColor {
+ return [UIColor colorWithWhite:kBackgroundColorBrightness alpha:1.0];
+}
+
+@end
« no previous file with comments | « ios/chrome/browser/ui/sad_tab/sad_tab_view.h ('k') | ios/chrome/browser/ui/settings/README.md » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698