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

Unified Diff: ios/chrome/browser/ui/omnibox/page_info_view_controller.mm

Issue 2589803002: Upstream Chrome on iOS source code [6/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/omnibox/page_info_view_controller.mm
diff --git a/ios/chrome/browser/ui/omnibox/page_info_view_controller.mm b/ios/chrome/browser/ui/omnibox/page_info_view_controller.mm
new file mode 100644
index 0000000000000000000000000000000000000000..78fb2a5a7b825d9bb004acf85b47c11bf6fdea45
--- /dev/null
+++ b/ios/chrome/browser/ui/omnibox/page_info_view_controller.mm
@@ -0,0 +1,637 @@
+// Copyright (c) 2012 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/omnibox/page_info_view_controller.h"
+
+#include "base/bind.h"
+#include "base/location.h"
+#include "base/mac/bundle_locations.h"
+#import "base/mac/foundation_util.h"
+#include "base/mac/objc_property_releaser.h"
+#include "base/mac/scoped_nsobject.h"
+#include "base/message_loop/message_loop.h"
+#include "base/single_thread_task_runner.h"
+#include "base/strings/sys_string_conversions.h"
+#include "base/threading/thread_task_runner_handle.h"
+#include "components/strings/grit/components_strings.h"
+#import "ios/chrome/browser/ui/animation_util.h"
+#import "ios/chrome/browser/ui/commands/UIKit+ChromeExecuteCommand.h"
+#include "ios/chrome/browser/ui/commands/ios_command_ids.h"
+#import "ios/chrome/browser/ui/fancy_ui/bidi_container_view.h"
+#include "ios/chrome/browser/ui/omnibox/page_info_model.h"
+#import "ios/chrome/browser/ui/popup_menu/popup_menu_view.h"
+#include "ios/chrome/browser/ui/rtl_geometry.h"
+#include "ios/chrome/browser/ui/ui_util.h"
+#import "ios/chrome/browser/ui/uikit_ui_util.h"
+#import "ios/chrome/common/material_timing.h"
+#include "ios/chrome/grit/ios_strings.h"
+#import "ios/third_party/material_components_ios/src/components/Typography/src/MaterialTypography.h"
+#import "ios/third_party/material_roboto_font_loader_ios/src/src/MaterialRobotoFontLoader.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/l10n/l10n_util_mac.h"
+#import "ui/gfx/ios/NSString+CrStringDrawing.h"
+#import "ui/gfx/ios/uikit_util.h"
+
+using ios::material::TimingFunction;
+
+namespace {
+
+// The width of the view.
+const CGFloat kViewWidthRegular = 600.0;
+const CGFloat kViewWidthCompact = 288.0;
+const CGFloat kViewWidthiPhoneLandscape = 400.0;
+// Spacing in between sections.
+const CGFloat kVerticalSpacing = 20.0;
+// Initial position for the left side of the frame.
+const CGFloat kInitialFramePosition = 8.0;
+// Alpha for the shield.
+const CGFloat kShieldAlpha = 0.5;
+// Scroll View inset.
+const CGFloat kScrollViewInset = 5.0;
+// The size of the footer (rounded corner and shadow) for page info view.
+const CGFloat kPageInfoViewFooterSize = 15.0;
+// Padding between the window frame and content.
+const CGFloat kFramePadding = 24;
+// Padding for the initial line of the view.
+const CGFloat kInitialLinePadding = 40;
+// Padding between the bottom of the content and the window frame.
+const CGFloat kFrameBottomPadding = 16;
+// Spacing between the optional headline and description text views.
+const CGFloat kHeadlineSpacing = 16;
+// Spacing between the image and the text.
+const CGFloat kImageSpacing = 16;
+// Square size of the image.
+const CGFloat kImageSize = 24;
+// The height of the headline label.
+const CGFloat kHeadlineHeight = 19;
+// The hex color for the help button text.
+const int kPageInfoHelpButtonRGB = 0x3b8cfe;
+// The grey scale color for the text within the page info alert.
+const CGFloat kPageInfoTextGreyComponent = 0.2;
+
+inline UIColor* PageInfoTextColor() {
+ return [UIColor colorWithWhite:kPageInfoTextGreyComponent alpha:1];
+}
+
+inline UIColor* PageInfoHelpButtonColor() {
+ return UIColorFromRGB(kPageInfoHelpButtonRGB);
+}
+
+inline UIFont* PageInfoHeadlineFont() {
+ return [[MDFRobotoFontLoader sharedInstance] mediumFontOfSize:16];
+}
+
+inline CATransform3D PageInfoAnimationScale() {
+ return CATransform3DMakeScale(0.03, 0.03, 1);
+}
+
+// Offset to make sure image aligns with the header line.
+inline CGFloat PageInfoImageVerticalOffset() {
+ return ui::AlignValueToUpperPixel((kHeadlineHeight - kImageSize) / 2.0);
+}
+
+// The X position of the text fields. Variants for with and without an image.
+const CGFloat kTextXPositionNoImage = kFramePadding;
+const CGFloat kTextXPosition =
+ kTextXPositionNoImage + kImageSize + kImageSpacing;
+
+// The X offset for the help button.
+const CGFloat kButtonXOffset = kTextXPosition;
+
+} // namespace
+
+PageInfoModelBubbleBridge::PageInfoModelBubbleBridge()
+ : controller_(nil), weak_ptr_factory_(this) {}
+
+PageInfoModelBubbleBridge::~PageInfoModelBubbleBridge() {}
+
+void PageInfoModelBubbleBridge::OnPageInfoModelChanged() {
+ // Check to see if a layout has already been scheduled.
+ if (weak_ptr_factory_.HasWeakPtrs())
+ return;
+
+ // Delay performing layout by a second so that all the animations from
+ // InfoBubbleWindow and origin updates from BaseBubbleController finish, so
+ // that we don't all race trying to change the frame's origin.
+ //
+ // Using MessageLoop is superior here to |-performSelector:| because it will
+ // not retain its target; if the child outlives its parent, zombies get left
+ // behind (http://crbug.com/59619). This will cancel the scheduled task if
+ // the controller (and thus this bridge) get destroyed before the message
+ // can be delivered.
+ base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
+ FROM_HERE, base::Bind(&PageInfoModelBubbleBridge::PerformLayout,
+ weak_ptr_factory_.GetWeakPtr()),
+ base::TimeDelta::FromMilliseconds(1000 /* milliseconds */));
+}
+
+@interface PageInfoViewController ()<UIGestureRecognizerDelegate> {
+ // Scroll View inside the PageInfoView used to display content that exceeds
+ // the available space.
+ base::scoped_nsobject<UIScrollView> scrollView_;
+ // Container View added inside the Scroll View. All content is added to this
+ // view instead of PopupMenuController.containerView_.
+ base::scoped_nsobject<BidiContainerView> innerContainerView_;
+
+ // Origin of the arrow at the top of the popup window.
+ CGPoint origin_;
+
+ // Model for the data to display.
+ std::unique_ptr<PageInfoModel> model_;
+
+ // Thin bridge that pushes model-changed notifications from C++ to Cocoa.
+ std::unique_ptr<PageInfoModelObserver> bridge_;
+
+ // Width of the view. Depends on the device (iPad/iPhone).
+ CGFloat viewWidth_;
+
+ // Width of the text fields.
+ CGFloat textWidth_;
+
+ // YES when the popup has finished animating in. NO otherwise.
+ BOOL animateInCompleted_;
+
+ base::mac::ObjCPropertyReleaser propertyReleaser_PageInfoViewController_;
+}
+
+// Adds the state image at a pre-determined x position and the given y. This
+// does not affect the next Y position because the image is placed next to
+// a text field that is larger and accounts for the image's size.
+- (void)addImageViewForInfo:(const PageInfoModel::SectionInfo&)info
+ toSubviews:(NSMutableArray*)subviews
+ atOffset:(CGFloat)offset;
+
+// Adds the title text field at the given x,y position, and returns the y
+// position for the next element.
+- (CGFloat)addHeadlineViewForInfo:(const PageInfoModel::SectionInfo&)info
+ toSubviews:(NSMutableArray*)subviews
+ atPoint:(CGPoint)point;
+
+// Adds the description text field at the given x,y position, and returns the y
+// position for the next element.
+- (CGFloat)addDescriptionViewForInfo:(const PageInfoModel::SectionInfo&)info
+ toSubviews:(NSMutableArray*)subviews
+ atPoint:(CGPoint)point;
+
+// Returns a button with title and action configured for |buttonAction|.
+- (UIButton*)buttonForAction:(PageInfoModel::ButtonAction)buttonAction;
+
+// Adds the the button |buttonAction| that explains the icons. Returns the y
+// position delta for the next offset.
+- (CGFloat)addButton:(PageInfoModel::ButtonAction)buttonAction
+ toSubviews:(NSMutableArray*)subviews
+ atOffset:(CGFloat)offset;
+
+@property(nonatomic, retain) UIView* containerView;
+@property(nonatomic, retain) UIView* popupContainer;
+@end
+
+@implementation PageInfoViewController
+
+@synthesize containerView = containerView_;
+@synthesize popupContainer = popupContainer_;
+
+- (id)initWithModel:(PageInfoModel*)model
+ bridge:(PageInfoModelObserver*)bridge
+ sourceFrame:(CGRect)source
+ parentView:(UIView*)parent {
+ DCHECK(parent);
+ self = [super init];
+ if (self) {
+ propertyReleaser_PageInfoViewController_.Init(
+ self, [PageInfoViewController class]);
+
+ scrollView_.reset(
+ [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, 240, 128)]);
+ [scrollView_ setMultipleTouchEnabled:YES];
+ [scrollView_ setClipsToBounds:YES];
+ [scrollView_ setShowsHorizontalScrollIndicator:NO];
+ [scrollView_ setIndicatorStyle:UIScrollViewIndicatorStyleBlack];
+ [scrollView_
+ setAutoresizingMask:(UIViewAutoresizingFlexibleTrailingMargin() |
+ UIViewAutoresizingFlexibleTopMargin)];
+
+ innerContainerView_.reset(
+ [[BidiContainerView alloc] initWithFrame:CGRectMake(0, 0, 194, 327)]);
+ [innerContainerView_ setBackgroundColor:[UIColor clearColor]];
+ [innerContainerView_
+ setAccessibilityLabel:@"Page Security Info Scroll Container"];
+ [innerContainerView_
+ setAutoresizingMask:(UIViewAutoresizingFlexibleTrailingMargin() |
+ UIViewAutoresizingFlexibleBottomMargin)];
+
+ model_.reset(model);
+ bridge_.reset(bridge);
+ origin_ = CGPointMake(CGRectGetMidX(source), CGRectGetMaxY(source));
+
+ UIInterfaceOrientation orientation =
+ [[UIApplication sharedApplication] statusBarOrientation];
+ viewWidth_ = IsCompact() ? kViewWidthCompact : kViewWidthRegular;
+ // Special case iPhone landscape.
+ if (!IsIPadIdiom() && UIInterfaceOrientationIsLandscape(orientation))
+ viewWidth_ = kViewWidthiPhoneLandscape;
+
+ textWidth_ = viewWidth_ - (kImageSize + kImageSpacing + kFramePadding * 2 +
+ kScrollViewInset * 2);
+
+ base::scoped_nsobject<UILongPressGestureRecognizer> touchDownRecognizer(
+ [[UILongPressGestureRecognizer alloc]
+ initWithTarget:self
+ action:@selector(rootViewTapped:)]);
+ // Setting the duration to .001 makes this similar to a control event
+ // UIControlEventTouchDown.
+ [touchDownRecognizer setMinimumPressDuration:.001];
+ [touchDownRecognizer setDelegate:self];
+
+ containerView_ = [[UIView alloc] initWithFrame:[parent bounds]];
+ [containerView_ addGestureRecognizer:touchDownRecognizer];
+ [containerView_
+ setBackgroundColor:[UIColor colorWithWhite:0 alpha:kShieldAlpha]];
+ [containerView_ setTag:IDC_HIDE_PAGE_INFO];
+ [containerView_ setOpaque:NO];
+ [containerView_ setAlpha:0];
+ [containerView_ setAccessibilityViewIsModal:YES];
+
+ popupContainer_ = [[UIView alloc] initWithFrame:CGRectZero];
+ [popupContainer_ setBackgroundColor:[UIColor whiteColor]];
+ [popupContainer_ setClipsToBounds:YES];
+ [containerView_ addSubview:popupContainer_];
+
+ [self.popupContainer addSubview:scrollView_];
+ [scrollView_ addSubview:innerContainerView_];
+ [scrollView_ setAccessibilityIdentifier:@"Page Security Scroll View"];
+ [parent addSubview:self.containerView];
+ [self performLayout];
+
+ [self animatePageInfoViewIn:source];
+ UIAccessibilityPostNotification(UIAccessibilityLayoutChangedNotification,
+ containerView_);
+ }
+
+ return self;
+}
+
+- (void)performLayout {
+ CGFloat offset = kInitialLinePadding;
+
+ // Keep the new subviews in an array that gets replaced at the end.
+ NSMutableArray* subviews = [NSMutableArray array];
+
+ int sectionCount = model_->GetSectionCount();
+ PageInfoModel::ButtonAction action = PageInfoModel::BUTTON_NONE;
+
+ for (int i = 0; i < sectionCount; i++) {
+ PageInfoModel::SectionInfo info = model_->GetSectionInfo(i);
+
+ if (action == PageInfoModel::BUTTON_NONE &&
+ info.button != PageInfoModel::BUTTON_NONE) {
+ // Show the button corresponding to the first section that requires a
+ // button.
+ action = info.button;
+ }
+
+ // Only certain sections have images. This affects the X position.
+ BOOL hasImage = model_->GetIconImage(info.icon_id) != nil;
+ CGFloat xPosition = (hasImage ? kTextXPosition : kTextXPositionNoImage);
+
+ // Insert the image subview for sections that are appropriate.
+ CGFloat imageBaseline = offset + kImageSize;
+ if (hasImage) {
+ [self addImageViewForInfo:info
+ toSubviews:subviews
+ atOffset:offset + PageInfoImageVerticalOffset()];
+ }
+
+ // Add the title.
+ if (!info.headline.empty()) {
+ offset += [self addHeadlineViewForInfo:info
+ toSubviews:subviews
+ atPoint:CGPointMake(xPosition, offset)];
+ offset += kHeadlineSpacing;
+ }
+
+ // Create the description of the state.
+ offset += [self addDescriptionViewForInfo:info
+ toSubviews:subviews
+ atPoint:CGPointMake(xPosition, offset)];
+
+ // If at this point the description and optional headline and button are
+ // not as tall as the image, adjust the offset by the difference.
+ CGFloat imageBaselineDelta = imageBaseline - offset;
+ if (imageBaselineDelta > 0)
+ offset += imageBaselineDelta;
+
+ // Add the separators.
+ int testSectionCount = sectionCount - 1;
+ if (i != testSectionCount ||
+ (i == testSectionCount && action != PageInfoModel::BUTTON_NONE)) {
+ offset += kVerticalSpacing;
+ }
+ }
+
+ // The last item at the bottom of the window is the help center link. Do not
+ // show this for the internal pages, which have one section.
+ offset += [self addButton:action toSubviews:subviews atOffset:offset];
+
+ // Add the bottom padding.
+ offset += kVerticalSpacing;
+ CGRect frame =
+ CGRectMake(kInitialFramePosition, origin_.y, viewWidth_, offset);
+
+ // Increase the size of the frame by the amount used for drawing rounded
+ // corners and shadow.
+ frame.size.height += kPageInfoViewFooterSize;
+
+ if (CGRectGetMaxY(frame) >
+ CGRectGetMaxY([[self containerView] superview].bounds) -
+ kFrameBottomPadding) {
+ // If the frame is bigger than the parent view than change the frame to
+ // fit in the superview bounds.
+ frame.size.height = [[self containerView] superview].bounds.size.height -
+ kFrameBottomPadding - frame.origin.y;
+
+ [scrollView_ setScrollEnabled:YES];
+ [scrollView_ flashScrollIndicators];
+ } else {
+ [scrollView_ setScrollEnabled:NO];
+ }
+
+ CGRect containerBounds = [containerView_ bounds];
+ CGRect popupFrame = frame;
+ popupFrame.origin.x =
+ CGRectGetMidX(containerBounds) - CGRectGetWidth(popupFrame) / 2.0;
+ popupFrame.origin.y =
+ CGRectGetMidY(containerBounds) - CGRectGetHeight(popupFrame) / 2.0;
+
+ popupFrame.origin = AlignPointToPixel(popupFrame.origin);
+ CGRect innerFrame = CGRectMake(0, 0, popupFrame.size.width, offset);
+
+ // If the initial animation has completed, animate the new frames.
+ if (animateInCompleted_) {
+ [UIView cr_animateWithDuration:ios::material::kDuration3
+ delay:0
+ curve:ios::material::CurveEaseInOut
+ options:0
+ animations:^{
+ [popupContainer_ setFrame:popupFrame];
+ [scrollView_ setFrame:[popupContainer_ bounds]];
+ [innerContainerView_ setFrame:innerFrame];
+ }
+ completion:nil];
+ } else {
+ // Popup hasn't finished animating in yet. Set frames immediately.
+ [popupContainer_ setFrame:popupFrame];
+ [scrollView_ setFrame:[popupContainer_ bounds]];
+ [innerContainerView_ setFrame:innerFrame];
+ }
+
+ for (UIView* view in [innerContainerView_ subviews]) {
+ [view removeFromSuperview];
+ }
+
+ for (UIView* view in subviews) {
+ [innerContainerView_ addSubview:view];
+ [innerContainerView_ setSubviewNeedsAdjustmentForRTL:view];
+ }
+
+ [scrollView_ setContentSize:innerContainerView_.get().frame.size];
+}
+
+- (void)dismiss {
+ [self animatePageInfoViewOut];
+ UIAccessibilityPostNotification(UIAccessibilityLayoutChangedNotification,
+ nil);
+}
+
+#pragma mark - Helper methods to create subviews.
+
+- (void)addImageViewForInfo:(const PageInfoModel::SectionInfo&)info
+ toSubviews:(NSMutableArray*)subviews
+ atOffset:(CGFloat)offset {
+ CGRect frame = CGRectMake(kFramePadding, offset, kImageSize, kImageSize);
+ base::scoped_nsobject<UIImageView> imageView(
+ [[UIImageView alloc] initWithFrame:frame]);
+ [imageView setImage:model_->GetIconImage(info.icon_id)->ToUIImage()];
+ [subviews addObject:imageView.get()];
+}
+
+- (CGFloat)addHeadlineViewForInfo:(const PageInfoModel::SectionInfo&)info
+ toSubviews:(NSMutableArray*)subviews
+ atPoint:(CGPoint)point {
+ CGRect frame = CGRectMake(point.x, point.y, textWidth_, kHeadlineHeight);
+ base::scoped_nsobject<UILabel> label([[UILabel alloc] initWithFrame:frame]);
+ [label setTextAlignment:NSTextAlignmentNatural];
+ [label setText:base::SysUTF16ToNSString(info.headline)];
+ [label setTextColor:PageInfoTextColor()];
+ [label setFont:PageInfoHeadlineFont()];
+ [label setBackgroundColor:[UIColor clearColor]];
+ [label setFrame:frame];
+ [label setLineBreakMode:NSLineBreakByTruncatingHead];
+ [subviews addObject:label.get()];
+ return CGRectGetHeight(frame);
+}
+
+- (CGFloat)addDescriptionViewForInfo:(const PageInfoModel::SectionInfo&)info
+ toSubviews:(NSMutableArray*)subviews
+ atPoint:(CGPoint)point {
+ CGRect frame = CGRectMake(point.x, point.y, textWidth_, kImageSize);
+ base::scoped_nsobject<UILabel> label([[UILabel alloc] initWithFrame:frame]);
+ [label setTextAlignment:NSTextAlignmentNatural];
+ NSString* description = base::SysUTF16ToNSString(info.description);
+ UIFont* font = [MDCTypography captionFont];
+ [label setTextColor:PageInfoTextColor()];
+ [label setText:description];
+ [label setFont:font];
+ [label setNumberOfLines:0];
+ [label setBackgroundColor:[UIColor clearColor]];
+
+ // If the text is oversized, resize the text field.
+ CGSize constraintSize = CGSizeMake(textWidth_, CGFLOAT_MAX);
+ CGSize sizeToFit =
+ [description cr_boundingSizeWithSize:constraintSize font:font];
+ frame.size.height = sizeToFit.height;
+ [label setFrame:frame];
+ [subviews addObject:label.get()];
+ return CGRectGetHeight(frame);
+}
+
+- (UIButton*)buttonForAction:(PageInfoModel::ButtonAction)buttonAction {
+ if (buttonAction == PageInfoModel::BUTTON_NONE) {
+ return nil;
+ }
+ UIButton* button = [[[UIButton alloc] initWithFrame:CGRectZero] autorelease];
+ int messageId = IDS_IOS_PAGE_INFO_RELOAD;
+ NSInteger tag = IDC_RELOAD;
+ NSString* accessibilityID = @"Reload button";
+ switch (buttonAction) {
+ case PageInfoModel::BUTTON_NONE:
+ NOTREACHED();
+ return nil;
+ case PageInfoModel::BUTTON_SHOW_SECURITY_HELP:
+ messageId = IDS_PAGE_INFO_HELP_CENTER_LINK;
+ tag = IDC_SHOW_SECURITY_HELP;
+ accessibilityID = @"What do these mean?";
+ break;
+ case PageInfoModel::BUTTON_RELOAD:
+ messageId = IDS_IOS_PAGE_INFO_RELOAD;
+ tag = IDC_RELOAD;
+ accessibilityID = @"Reload button";
+ [button addTarget:self
+ action:@selector(dismiss)
+ forControlEvents:UIControlEventTouchUpInside];
+ break;
+ };
+
+ NSString* title = l10n_util::GetNSStringWithFixup(messageId);
+ SetA11yLabelAndUiAutomationName(button, messageId, accessibilityID);
+ [button setTitle:title forState:UIControlStateNormal];
+ [button setTag:tag];
+ [button addTarget:nil
+ action:@selector(chromeExecuteCommand:)
+ forControlEvents:UIControlEventTouchUpInside];
+ return button;
+}
+
+- (CGFloat)addButton:(PageInfoModel::ButtonAction)buttonAction
+ toSubviews:(NSMutableArray*)subviews
+ atOffset:(CGFloat)offset {
+ UIButton* button = [self buttonForAction:buttonAction];
+ if (!button) {
+ return 0;
+ }
+ // The size of the initial frame is irrelevant since it will be changed based
+ // on the size for the string inside.
+ CGRect frame = CGRectMake(kButtonXOffset, offset, 100, 10);
+
+ UIFont* font = [MDCTypography captionFont];
+ CGSize sizeWithFont =
+ [[[button titleLabel] text] cr_pixelAlignedSizeWithFont:font];
+ frame.size = sizeWithFont;
+
+ [button setFrame:frame];
+
+ [button.titleLabel setFont:font];
+ [button.titleLabel setTextAlignment:NSTextAlignmentLeft];
+ [button setTitleColor:PageInfoHelpButtonColor()
+ forState:UIControlStateNormal];
+ [button setTitleColor:PageInfoHelpButtonColor()
+ forState:UIControlStateSelected];
+ [button setBackgroundColor:[UIColor clearColor]];
+
+ [subviews addObject:button];
+
+ return CGRectGetHeight([button frame]);
+}
+
+#pragma mark - UIGestureRecognizerDelegate Implemenation
+
+- (void)rootViewTapped:(UIGestureRecognizer*)sender {
+ CGPoint pt = [sender locationInView:containerView_];
+ if (!CGRectContainsPoint([popupContainer_ frame], pt)) {
+ [containerView_ chromeExecuteCommand:containerView_];
+ }
+}
+
+- (BOOL)gestureRecognizer:(UIGestureRecognizer*)gestureRecognizer
+ shouldReceiveTouch:(UITouch*)touch {
+ CGPoint pt = [touch locationInView:containerView_];
+ return !CGRectContainsPoint([popupContainer_ frame], pt);
+}
+
+- (void)animatePageInfoViewIn:(CGRect)source {
+ // Animate the info card itself.
+ CATransform3D scaleTransform = PageInfoAnimationScale();
+ CGPoint fromPoint = CGPointMake(CGRectGetMidX(source), CGRectGetMidY(source));
+
+ CABasicAnimation* scaleAnimation =
+ [CABasicAnimation animationWithKeyPath:@"transform"];
+ [scaleAnimation setFromValue:[NSValue valueWithCATransform3D:scaleTransform]];
+
+ CABasicAnimation* positionAnimation =
+ [CABasicAnimation animationWithKeyPath:@"position"];
+ [positionAnimation setFromValue:[NSValue valueWithCGPoint:fromPoint]];
+
+ CAAnimationGroup* sizeAnimation = [CAAnimationGroup animation];
+ [sizeAnimation setAnimations:@[ scaleAnimation, positionAnimation ]];
+ [sizeAnimation
+ setTimingFunction:TimingFunction(ios::material::CurveEaseInOut)];
+ [sizeAnimation setDuration:ios::material::kDuration3];
+
+ CABasicAnimation* fadeAnimation =
+ [CABasicAnimation animationWithKeyPath:@"opacity"];
+ [fadeAnimation setTimingFunction:TimingFunction(ios::material::CurveEaseOut)];
+ [fadeAnimation setDuration:ios::material::kDuration6];
+ [fadeAnimation setFromValue:@0];
+ [fadeAnimation setToValue:@1];
+
+ [[popupContainer_ layer] addAnimation:fadeAnimation forKey:@"fade"];
+ [[popupContainer_ layer] addAnimation:sizeAnimation forKey:@"size"];
+
+ // Animation the background grey overlay.
+ CABasicAnimation* overlayAnimation =
+ [CABasicAnimation animationWithKeyPath:@"opacity"];
+ [overlayAnimation
+ setTimingFunction:TimingFunction(ios::material::CurveEaseOut)];
+ [overlayAnimation setDuration:ios::material::kDuration3];
+ [overlayAnimation setFromValue:@0];
+ [overlayAnimation setToValue:@1];
+
+ [[containerView_ layer] addAnimation:overlayAnimation forKey:@"fade"];
+ [containerView_ setAlpha:1];
+
+ // Animate the contents of the info card.
+ CALayer* contentsLayer = [innerContainerView_ layer];
+
+ CGRect startFrame = CGRectOffset([innerContainerView_ frame], 0, -32);
+ CAAnimation* contentSlideAnimation = FrameAnimationMake(
+ contentsLayer, startFrame, [innerContainerView_ frame]);
+ [contentSlideAnimation
+ setTimingFunction:TimingFunction(ios::material::CurveEaseOut)];
+ [contentSlideAnimation setDuration:ios::material::kDuration5];
+ contentSlideAnimation =
+ DelayedAnimationMake(contentSlideAnimation, ios::material::kDuration2);
+ [contentsLayer addAnimation:contentSlideAnimation forKey:@"slide"];
+
+ [CATransaction begin];
+ [CATransaction setCompletionBlock:^{
+ [innerContainerView_ setAlpha:1];
+ animateInCompleted_ = YES;
+ }];
+ CAAnimation* contentFadeAnimation = OpacityAnimationMake(0.0, 1.0);
+ [contentFadeAnimation
+ setTimingFunction:TimingFunction(ios::material::CurveEaseOut)];
+ [contentFadeAnimation setDuration:ios::material::kDuration5];
+ contentFadeAnimation =
+ DelayedAnimationMake(contentFadeAnimation, ios::material::kDuration1);
+ [contentsLayer addAnimation:contentFadeAnimation forKey:@"fade"];
+ [CATransaction commit];
+
+ // Since the animations have delay on them, the alpha of the content view
+ // needs to be set to zero and then one after the animation starts. If these
+ // steps are not taken, there will be a visible flash/jump from the initial
+ // spot during the animation.
+ [innerContainerView_ setAlpha:0];
+}
+
+- (void)animatePageInfoViewOut {
+ [CATransaction begin];
+ [CATransaction setCompletionBlock:^{
+ [self.containerView removeFromSuperview];
+ }];
+
+ CABasicAnimation* opacityAnimation =
+ [CABasicAnimation animationWithKeyPath:@"opacity"];
+ [opacityAnimation
+ setTimingFunction:TimingFunction(ios::material::CurveEaseIn)];
+ [opacityAnimation setDuration:ios::material::kDuration3];
+ [opacityAnimation setFromValue:@1];
+ [opacityAnimation setToValue:@0];
+ [[containerView_ layer] addAnimation:opacityAnimation forKey:@"animateOut"];
+
+ [popupContainer_ setAlpha:0];
+ [containerView_ setAlpha:0];
+ [CATransaction commit];
+}
+
+@end
« no previous file with comments | « ios/chrome/browser/ui/omnibox/page_info_view_controller.h ('k') | ios/chrome/browser/ui/omnibox/preload_provider.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698