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

Side by Side 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 unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #import "ios/chrome/browser/ui/omnibox/page_info_view_controller.h"
6
7 #include "base/bind.h"
8 #include "base/location.h"
9 #include "base/mac/bundle_locations.h"
10 #import "base/mac/foundation_util.h"
11 #include "base/mac/objc_property_releaser.h"
12 #include "base/mac/scoped_nsobject.h"
13 #include "base/message_loop/message_loop.h"
14 #include "base/single_thread_task_runner.h"
15 #include "base/strings/sys_string_conversions.h"
16 #include "base/threading/thread_task_runner_handle.h"
17 #include "components/strings/grit/components_strings.h"
18 #import "ios/chrome/browser/ui/animation_util.h"
19 #import "ios/chrome/browser/ui/commands/UIKit+ChromeExecuteCommand.h"
20 #include "ios/chrome/browser/ui/commands/ios_command_ids.h"
21 #import "ios/chrome/browser/ui/fancy_ui/bidi_container_view.h"
22 #include "ios/chrome/browser/ui/omnibox/page_info_model.h"
23 #import "ios/chrome/browser/ui/popup_menu/popup_menu_view.h"
24 #include "ios/chrome/browser/ui/rtl_geometry.h"
25 #include "ios/chrome/browser/ui/ui_util.h"
26 #import "ios/chrome/browser/ui/uikit_ui_util.h"
27 #import "ios/chrome/common/material_timing.h"
28 #include "ios/chrome/grit/ios_strings.h"
29 #import "ios/third_party/material_components_ios/src/components/Typography/src/M aterialTypography.h"
30 #import "ios/third_party/material_roboto_font_loader_ios/src/src/MaterialRobotoF ontLoader.h"
31 #include "ui/base/l10n/l10n_util.h"
32 #include "ui/base/l10n/l10n_util_mac.h"
33 #import "ui/gfx/ios/NSString+CrStringDrawing.h"
34 #import "ui/gfx/ios/uikit_util.h"
35
36 using ios::material::TimingFunction;
37
38 namespace {
39
40 // The width of the view.
41 const CGFloat kViewWidthRegular = 600.0;
42 const CGFloat kViewWidthCompact = 288.0;
43 const CGFloat kViewWidthiPhoneLandscape = 400.0;
44 // Spacing in between sections.
45 const CGFloat kVerticalSpacing = 20.0;
46 // Initial position for the left side of the frame.
47 const CGFloat kInitialFramePosition = 8.0;
48 // Alpha for the shield.
49 const CGFloat kShieldAlpha = 0.5;
50 // Scroll View inset.
51 const CGFloat kScrollViewInset = 5.0;
52 // The size of the footer (rounded corner and shadow) for page info view.
53 const CGFloat kPageInfoViewFooterSize = 15.0;
54 // Padding between the window frame and content.
55 const CGFloat kFramePadding = 24;
56 // Padding for the initial line of the view.
57 const CGFloat kInitialLinePadding = 40;
58 // Padding between the bottom of the content and the window frame.
59 const CGFloat kFrameBottomPadding = 16;
60 // Spacing between the optional headline and description text views.
61 const CGFloat kHeadlineSpacing = 16;
62 // Spacing between the image and the text.
63 const CGFloat kImageSpacing = 16;
64 // Square size of the image.
65 const CGFloat kImageSize = 24;
66 // The height of the headline label.
67 const CGFloat kHeadlineHeight = 19;
68 // The hex color for the help button text.
69 const int kPageInfoHelpButtonRGB = 0x3b8cfe;
70 // The grey scale color for the text within the page info alert.
71 const CGFloat kPageInfoTextGreyComponent = 0.2;
72
73 inline UIColor* PageInfoTextColor() {
74 return [UIColor colorWithWhite:kPageInfoTextGreyComponent alpha:1];
75 }
76
77 inline UIColor* PageInfoHelpButtonColor() {
78 return UIColorFromRGB(kPageInfoHelpButtonRGB);
79 }
80
81 inline UIFont* PageInfoHeadlineFont() {
82 return [[MDFRobotoFontLoader sharedInstance] mediumFontOfSize:16];
83 }
84
85 inline CATransform3D PageInfoAnimationScale() {
86 return CATransform3DMakeScale(0.03, 0.03, 1);
87 }
88
89 // Offset to make sure image aligns with the header line.
90 inline CGFloat PageInfoImageVerticalOffset() {
91 return ui::AlignValueToUpperPixel((kHeadlineHeight - kImageSize) / 2.0);
92 }
93
94 // The X position of the text fields. Variants for with and without an image.
95 const CGFloat kTextXPositionNoImage = kFramePadding;
96 const CGFloat kTextXPosition =
97 kTextXPositionNoImage + kImageSize + kImageSpacing;
98
99 // The X offset for the help button.
100 const CGFloat kButtonXOffset = kTextXPosition;
101
102 } // namespace
103
104 PageInfoModelBubbleBridge::PageInfoModelBubbleBridge()
105 : controller_(nil), weak_ptr_factory_(this) {}
106
107 PageInfoModelBubbleBridge::~PageInfoModelBubbleBridge() {}
108
109 void PageInfoModelBubbleBridge::OnPageInfoModelChanged() {
110 // Check to see if a layout has already been scheduled.
111 if (weak_ptr_factory_.HasWeakPtrs())
112 return;
113
114 // Delay performing layout by a second so that all the animations from
115 // InfoBubbleWindow and origin updates from BaseBubbleController finish, so
116 // that we don't all race trying to change the frame's origin.
117 //
118 // Using MessageLoop is superior here to |-performSelector:| because it will
119 // not retain its target; if the child outlives its parent, zombies get left
120 // behind (http://crbug.com/59619). This will cancel the scheduled task if
121 // the controller (and thus this bridge) get destroyed before the message
122 // can be delivered.
123 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
124 FROM_HERE, base::Bind(&PageInfoModelBubbleBridge::PerformLayout,
125 weak_ptr_factory_.GetWeakPtr()),
126 base::TimeDelta::FromMilliseconds(1000 /* milliseconds */));
127 }
128
129 @interface PageInfoViewController ()<UIGestureRecognizerDelegate> {
130 // Scroll View inside the PageInfoView used to display content that exceeds
131 // the available space.
132 base::scoped_nsobject<UIScrollView> scrollView_;
133 // Container View added inside the Scroll View. All content is added to this
134 // view instead of PopupMenuController.containerView_.
135 base::scoped_nsobject<BidiContainerView> innerContainerView_;
136
137 // Origin of the arrow at the top of the popup window.
138 CGPoint origin_;
139
140 // Model for the data to display.
141 std::unique_ptr<PageInfoModel> model_;
142
143 // Thin bridge that pushes model-changed notifications from C++ to Cocoa.
144 std::unique_ptr<PageInfoModelObserver> bridge_;
145
146 // Width of the view. Depends on the device (iPad/iPhone).
147 CGFloat viewWidth_;
148
149 // Width of the text fields.
150 CGFloat textWidth_;
151
152 // YES when the popup has finished animating in. NO otherwise.
153 BOOL animateInCompleted_;
154
155 base::mac::ObjCPropertyReleaser propertyReleaser_PageInfoViewController_;
156 }
157
158 // Adds the state image at a pre-determined x position and the given y. This
159 // does not affect the next Y position because the image is placed next to
160 // a text field that is larger and accounts for the image's size.
161 - (void)addImageViewForInfo:(const PageInfoModel::SectionInfo&)info
162 toSubviews:(NSMutableArray*)subviews
163 atOffset:(CGFloat)offset;
164
165 // Adds the title text field at the given x,y position, and returns the y
166 // position for the next element.
167 - (CGFloat)addHeadlineViewForInfo:(const PageInfoModel::SectionInfo&)info
168 toSubviews:(NSMutableArray*)subviews
169 atPoint:(CGPoint)point;
170
171 // Adds the description text field at the given x,y position, and returns the y
172 // position for the next element.
173 - (CGFloat)addDescriptionViewForInfo:(const PageInfoModel::SectionInfo&)info
174 toSubviews:(NSMutableArray*)subviews
175 atPoint:(CGPoint)point;
176
177 // Returns a button with title and action configured for |buttonAction|.
178 - (UIButton*)buttonForAction:(PageInfoModel::ButtonAction)buttonAction;
179
180 // Adds the the button |buttonAction| that explains the icons. Returns the y
181 // position delta for the next offset.
182 - (CGFloat)addButton:(PageInfoModel::ButtonAction)buttonAction
183 toSubviews:(NSMutableArray*)subviews
184 atOffset:(CGFloat)offset;
185
186 @property(nonatomic, retain) UIView* containerView;
187 @property(nonatomic, retain) UIView* popupContainer;
188 @end
189
190 @implementation PageInfoViewController
191
192 @synthesize containerView = containerView_;
193 @synthesize popupContainer = popupContainer_;
194
195 - (id)initWithModel:(PageInfoModel*)model
196 bridge:(PageInfoModelObserver*)bridge
197 sourceFrame:(CGRect)source
198 parentView:(UIView*)parent {
199 DCHECK(parent);
200 self = [super init];
201 if (self) {
202 propertyReleaser_PageInfoViewController_.Init(
203 self, [PageInfoViewController class]);
204
205 scrollView_.reset(
206 [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, 240, 128)]);
207 [scrollView_ setMultipleTouchEnabled:YES];
208 [scrollView_ setClipsToBounds:YES];
209 [scrollView_ setShowsHorizontalScrollIndicator:NO];
210 [scrollView_ setIndicatorStyle:UIScrollViewIndicatorStyleBlack];
211 [scrollView_
212 setAutoresizingMask:(UIViewAutoresizingFlexibleTrailingMargin() |
213 UIViewAutoresizingFlexibleTopMargin)];
214
215 innerContainerView_.reset(
216 [[BidiContainerView alloc] initWithFrame:CGRectMake(0, 0, 194, 327)]);
217 [innerContainerView_ setBackgroundColor:[UIColor clearColor]];
218 [innerContainerView_
219 setAccessibilityLabel:@"Page Security Info Scroll Container"];
220 [innerContainerView_
221 setAutoresizingMask:(UIViewAutoresizingFlexibleTrailingMargin() |
222 UIViewAutoresizingFlexibleBottomMargin)];
223
224 model_.reset(model);
225 bridge_.reset(bridge);
226 origin_ = CGPointMake(CGRectGetMidX(source), CGRectGetMaxY(source));
227
228 UIInterfaceOrientation orientation =
229 [[UIApplication sharedApplication] statusBarOrientation];
230 viewWidth_ = IsCompact() ? kViewWidthCompact : kViewWidthRegular;
231 // Special case iPhone landscape.
232 if (!IsIPadIdiom() && UIInterfaceOrientationIsLandscape(orientation))
233 viewWidth_ = kViewWidthiPhoneLandscape;
234
235 textWidth_ = viewWidth_ - (kImageSize + kImageSpacing + kFramePadding * 2 +
236 kScrollViewInset * 2);
237
238 base::scoped_nsobject<UILongPressGestureRecognizer> touchDownRecognizer(
239 [[UILongPressGestureRecognizer alloc]
240 initWithTarget:self
241 action:@selector(rootViewTapped:)]);
242 // Setting the duration to .001 makes this similar to a control event
243 // UIControlEventTouchDown.
244 [touchDownRecognizer setMinimumPressDuration:.001];
245 [touchDownRecognizer setDelegate:self];
246
247 containerView_ = [[UIView alloc] initWithFrame:[parent bounds]];
248 [containerView_ addGestureRecognizer:touchDownRecognizer];
249 [containerView_
250 setBackgroundColor:[UIColor colorWithWhite:0 alpha:kShieldAlpha]];
251 [containerView_ setTag:IDC_HIDE_PAGE_INFO];
252 [containerView_ setOpaque:NO];
253 [containerView_ setAlpha:0];
254 [containerView_ setAccessibilityViewIsModal:YES];
255
256 popupContainer_ = [[UIView alloc] initWithFrame:CGRectZero];
257 [popupContainer_ setBackgroundColor:[UIColor whiteColor]];
258 [popupContainer_ setClipsToBounds:YES];
259 [containerView_ addSubview:popupContainer_];
260
261 [self.popupContainer addSubview:scrollView_];
262 [scrollView_ addSubview:innerContainerView_];
263 [scrollView_ setAccessibilityIdentifier:@"Page Security Scroll View"];
264 [parent addSubview:self.containerView];
265 [self performLayout];
266
267 [self animatePageInfoViewIn:source];
268 UIAccessibilityPostNotification(UIAccessibilityLayoutChangedNotification,
269 containerView_);
270 }
271
272 return self;
273 }
274
275 - (void)performLayout {
276 CGFloat offset = kInitialLinePadding;
277
278 // Keep the new subviews in an array that gets replaced at the end.
279 NSMutableArray* subviews = [NSMutableArray array];
280
281 int sectionCount = model_->GetSectionCount();
282 PageInfoModel::ButtonAction action = PageInfoModel::BUTTON_NONE;
283
284 for (int i = 0; i < sectionCount; i++) {
285 PageInfoModel::SectionInfo info = model_->GetSectionInfo(i);
286
287 if (action == PageInfoModel::BUTTON_NONE &&
288 info.button != PageInfoModel::BUTTON_NONE) {
289 // Show the button corresponding to the first section that requires a
290 // button.
291 action = info.button;
292 }
293
294 // Only certain sections have images. This affects the X position.
295 BOOL hasImage = model_->GetIconImage(info.icon_id) != nil;
296 CGFloat xPosition = (hasImage ? kTextXPosition : kTextXPositionNoImage);
297
298 // Insert the image subview for sections that are appropriate.
299 CGFloat imageBaseline = offset + kImageSize;
300 if (hasImage) {
301 [self addImageViewForInfo:info
302 toSubviews:subviews
303 atOffset:offset + PageInfoImageVerticalOffset()];
304 }
305
306 // Add the title.
307 if (!info.headline.empty()) {
308 offset += [self addHeadlineViewForInfo:info
309 toSubviews:subviews
310 atPoint:CGPointMake(xPosition, offset)];
311 offset += kHeadlineSpacing;
312 }
313
314 // Create the description of the state.
315 offset += [self addDescriptionViewForInfo:info
316 toSubviews:subviews
317 atPoint:CGPointMake(xPosition, offset)];
318
319 // If at this point the description and optional headline and button are
320 // not as tall as the image, adjust the offset by the difference.
321 CGFloat imageBaselineDelta = imageBaseline - offset;
322 if (imageBaselineDelta > 0)
323 offset += imageBaselineDelta;
324
325 // Add the separators.
326 int testSectionCount = sectionCount - 1;
327 if (i != testSectionCount ||
328 (i == testSectionCount && action != PageInfoModel::BUTTON_NONE)) {
329 offset += kVerticalSpacing;
330 }
331 }
332
333 // The last item at the bottom of the window is the help center link. Do not
334 // show this for the internal pages, which have one section.
335 offset += [self addButton:action toSubviews:subviews atOffset:offset];
336
337 // Add the bottom padding.
338 offset += kVerticalSpacing;
339 CGRect frame =
340 CGRectMake(kInitialFramePosition, origin_.y, viewWidth_, offset);
341
342 // Increase the size of the frame by the amount used for drawing rounded
343 // corners and shadow.
344 frame.size.height += kPageInfoViewFooterSize;
345
346 if (CGRectGetMaxY(frame) >
347 CGRectGetMaxY([[self containerView] superview].bounds) -
348 kFrameBottomPadding) {
349 // If the frame is bigger than the parent view than change the frame to
350 // fit in the superview bounds.
351 frame.size.height = [[self containerView] superview].bounds.size.height -
352 kFrameBottomPadding - frame.origin.y;
353
354 [scrollView_ setScrollEnabled:YES];
355 [scrollView_ flashScrollIndicators];
356 } else {
357 [scrollView_ setScrollEnabled:NO];
358 }
359
360 CGRect containerBounds = [containerView_ bounds];
361 CGRect popupFrame = frame;
362 popupFrame.origin.x =
363 CGRectGetMidX(containerBounds) - CGRectGetWidth(popupFrame) / 2.0;
364 popupFrame.origin.y =
365 CGRectGetMidY(containerBounds) - CGRectGetHeight(popupFrame) / 2.0;
366
367 popupFrame.origin = AlignPointToPixel(popupFrame.origin);
368 CGRect innerFrame = CGRectMake(0, 0, popupFrame.size.width, offset);
369
370 // If the initial animation has completed, animate the new frames.
371 if (animateInCompleted_) {
372 [UIView cr_animateWithDuration:ios::material::kDuration3
373 delay:0
374 curve:ios::material::CurveEaseInOut
375 options:0
376 animations:^{
377 [popupContainer_ setFrame:popupFrame];
378 [scrollView_ setFrame:[popupContainer_ bounds]];
379 [innerContainerView_ setFrame:innerFrame];
380 }
381 completion:nil];
382 } else {
383 // Popup hasn't finished animating in yet. Set frames immediately.
384 [popupContainer_ setFrame:popupFrame];
385 [scrollView_ setFrame:[popupContainer_ bounds]];
386 [innerContainerView_ setFrame:innerFrame];
387 }
388
389 for (UIView* view in [innerContainerView_ subviews]) {
390 [view removeFromSuperview];
391 }
392
393 for (UIView* view in subviews) {
394 [innerContainerView_ addSubview:view];
395 [innerContainerView_ setSubviewNeedsAdjustmentForRTL:view];
396 }
397
398 [scrollView_ setContentSize:innerContainerView_.get().frame.size];
399 }
400
401 - (void)dismiss {
402 [self animatePageInfoViewOut];
403 UIAccessibilityPostNotification(UIAccessibilityLayoutChangedNotification,
404 nil);
405 }
406
407 #pragma mark - Helper methods to create subviews.
408
409 - (void)addImageViewForInfo:(const PageInfoModel::SectionInfo&)info
410 toSubviews:(NSMutableArray*)subviews
411 atOffset:(CGFloat)offset {
412 CGRect frame = CGRectMake(kFramePadding, offset, kImageSize, kImageSize);
413 base::scoped_nsobject<UIImageView> imageView(
414 [[UIImageView alloc] initWithFrame:frame]);
415 [imageView setImage:model_->GetIconImage(info.icon_id)->ToUIImage()];
416 [subviews addObject:imageView.get()];
417 }
418
419 - (CGFloat)addHeadlineViewForInfo:(const PageInfoModel::SectionInfo&)info
420 toSubviews:(NSMutableArray*)subviews
421 atPoint:(CGPoint)point {
422 CGRect frame = CGRectMake(point.x, point.y, textWidth_, kHeadlineHeight);
423 base::scoped_nsobject<UILabel> label([[UILabel alloc] initWithFrame:frame]);
424 [label setTextAlignment:NSTextAlignmentNatural];
425 [label setText:base::SysUTF16ToNSString(info.headline)];
426 [label setTextColor:PageInfoTextColor()];
427 [label setFont:PageInfoHeadlineFont()];
428 [label setBackgroundColor:[UIColor clearColor]];
429 [label setFrame:frame];
430 [label setLineBreakMode:NSLineBreakByTruncatingHead];
431 [subviews addObject:label.get()];
432 return CGRectGetHeight(frame);
433 }
434
435 - (CGFloat)addDescriptionViewForInfo:(const PageInfoModel::SectionInfo&)info
436 toSubviews:(NSMutableArray*)subviews
437 atPoint:(CGPoint)point {
438 CGRect frame = CGRectMake(point.x, point.y, textWidth_, kImageSize);
439 base::scoped_nsobject<UILabel> label([[UILabel alloc] initWithFrame:frame]);
440 [label setTextAlignment:NSTextAlignmentNatural];
441 NSString* description = base::SysUTF16ToNSString(info.description);
442 UIFont* font = [MDCTypography captionFont];
443 [label setTextColor:PageInfoTextColor()];
444 [label setText:description];
445 [label setFont:font];
446 [label setNumberOfLines:0];
447 [label setBackgroundColor:[UIColor clearColor]];
448
449 // If the text is oversized, resize the text field.
450 CGSize constraintSize = CGSizeMake(textWidth_, CGFLOAT_MAX);
451 CGSize sizeToFit =
452 [description cr_boundingSizeWithSize:constraintSize font:font];
453 frame.size.height = sizeToFit.height;
454 [label setFrame:frame];
455 [subviews addObject:label.get()];
456 return CGRectGetHeight(frame);
457 }
458
459 - (UIButton*)buttonForAction:(PageInfoModel::ButtonAction)buttonAction {
460 if (buttonAction == PageInfoModel::BUTTON_NONE) {
461 return nil;
462 }
463 UIButton* button = [[[UIButton alloc] initWithFrame:CGRectZero] autorelease];
464 int messageId = IDS_IOS_PAGE_INFO_RELOAD;
465 NSInteger tag = IDC_RELOAD;
466 NSString* accessibilityID = @"Reload button";
467 switch (buttonAction) {
468 case PageInfoModel::BUTTON_NONE:
469 NOTREACHED();
470 return nil;
471 case PageInfoModel::BUTTON_SHOW_SECURITY_HELP:
472 messageId = IDS_PAGE_INFO_HELP_CENTER_LINK;
473 tag = IDC_SHOW_SECURITY_HELP;
474 accessibilityID = @"What do these mean?";
475 break;
476 case PageInfoModel::BUTTON_RELOAD:
477 messageId = IDS_IOS_PAGE_INFO_RELOAD;
478 tag = IDC_RELOAD;
479 accessibilityID = @"Reload button";
480 [button addTarget:self
481 action:@selector(dismiss)
482 forControlEvents:UIControlEventTouchUpInside];
483 break;
484 };
485
486 NSString* title = l10n_util::GetNSStringWithFixup(messageId);
487 SetA11yLabelAndUiAutomationName(button, messageId, accessibilityID);
488 [button setTitle:title forState:UIControlStateNormal];
489 [button setTag:tag];
490 [button addTarget:nil
491 action:@selector(chromeExecuteCommand:)
492 forControlEvents:UIControlEventTouchUpInside];
493 return button;
494 }
495
496 - (CGFloat)addButton:(PageInfoModel::ButtonAction)buttonAction
497 toSubviews:(NSMutableArray*)subviews
498 atOffset:(CGFloat)offset {
499 UIButton* button = [self buttonForAction:buttonAction];
500 if (!button) {
501 return 0;
502 }
503 // The size of the initial frame is irrelevant since it will be changed based
504 // on the size for the string inside.
505 CGRect frame = CGRectMake(kButtonXOffset, offset, 100, 10);
506
507 UIFont* font = [MDCTypography captionFont];
508 CGSize sizeWithFont =
509 [[[button titleLabel] text] cr_pixelAlignedSizeWithFont:font];
510 frame.size = sizeWithFont;
511
512 [button setFrame:frame];
513
514 [button.titleLabel setFont:font];
515 [button.titleLabel setTextAlignment:NSTextAlignmentLeft];
516 [button setTitleColor:PageInfoHelpButtonColor()
517 forState:UIControlStateNormal];
518 [button setTitleColor:PageInfoHelpButtonColor()
519 forState:UIControlStateSelected];
520 [button setBackgroundColor:[UIColor clearColor]];
521
522 [subviews addObject:button];
523
524 return CGRectGetHeight([button frame]);
525 }
526
527 #pragma mark - UIGestureRecognizerDelegate Implemenation
528
529 - (void)rootViewTapped:(UIGestureRecognizer*)sender {
530 CGPoint pt = [sender locationInView:containerView_];
531 if (!CGRectContainsPoint([popupContainer_ frame], pt)) {
532 [containerView_ chromeExecuteCommand:containerView_];
533 }
534 }
535
536 - (BOOL)gestureRecognizer:(UIGestureRecognizer*)gestureRecognizer
537 shouldReceiveTouch:(UITouch*)touch {
538 CGPoint pt = [touch locationInView:containerView_];
539 return !CGRectContainsPoint([popupContainer_ frame], pt);
540 }
541
542 - (void)animatePageInfoViewIn:(CGRect)source {
543 // Animate the info card itself.
544 CATransform3D scaleTransform = PageInfoAnimationScale();
545 CGPoint fromPoint = CGPointMake(CGRectGetMidX(source), CGRectGetMidY(source));
546
547 CABasicAnimation* scaleAnimation =
548 [CABasicAnimation animationWithKeyPath:@"transform"];
549 [scaleAnimation setFromValue:[NSValue valueWithCATransform3D:scaleTransform]];
550
551 CABasicAnimation* positionAnimation =
552 [CABasicAnimation animationWithKeyPath:@"position"];
553 [positionAnimation setFromValue:[NSValue valueWithCGPoint:fromPoint]];
554
555 CAAnimationGroup* sizeAnimation = [CAAnimationGroup animation];
556 [sizeAnimation setAnimations:@[ scaleAnimation, positionAnimation ]];
557 [sizeAnimation
558 setTimingFunction:TimingFunction(ios::material::CurveEaseInOut)];
559 [sizeAnimation setDuration:ios::material::kDuration3];
560
561 CABasicAnimation* fadeAnimation =
562 [CABasicAnimation animationWithKeyPath:@"opacity"];
563 [fadeAnimation setTimingFunction:TimingFunction(ios::material::CurveEaseOut)];
564 [fadeAnimation setDuration:ios::material::kDuration6];
565 [fadeAnimation setFromValue:@0];
566 [fadeAnimation setToValue:@1];
567
568 [[popupContainer_ layer] addAnimation:fadeAnimation forKey:@"fade"];
569 [[popupContainer_ layer] addAnimation:sizeAnimation forKey:@"size"];
570
571 // Animation the background grey overlay.
572 CABasicAnimation* overlayAnimation =
573 [CABasicAnimation animationWithKeyPath:@"opacity"];
574 [overlayAnimation
575 setTimingFunction:TimingFunction(ios::material::CurveEaseOut)];
576 [overlayAnimation setDuration:ios::material::kDuration3];
577 [overlayAnimation setFromValue:@0];
578 [overlayAnimation setToValue:@1];
579
580 [[containerView_ layer] addAnimation:overlayAnimation forKey:@"fade"];
581 [containerView_ setAlpha:1];
582
583 // Animate the contents of the info card.
584 CALayer* contentsLayer = [innerContainerView_ layer];
585
586 CGRect startFrame = CGRectOffset([innerContainerView_ frame], 0, -32);
587 CAAnimation* contentSlideAnimation = FrameAnimationMake(
588 contentsLayer, startFrame, [innerContainerView_ frame]);
589 [contentSlideAnimation
590 setTimingFunction:TimingFunction(ios::material::CurveEaseOut)];
591 [contentSlideAnimation setDuration:ios::material::kDuration5];
592 contentSlideAnimation =
593 DelayedAnimationMake(contentSlideAnimation, ios::material::kDuration2);
594 [contentsLayer addAnimation:contentSlideAnimation forKey:@"slide"];
595
596 [CATransaction begin];
597 [CATransaction setCompletionBlock:^{
598 [innerContainerView_ setAlpha:1];
599 animateInCompleted_ = YES;
600 }];
601 CAAnimation* contentFadeAnimation = OpacityAnimationMake(0.0, 1.0);
602 [contentFadeAnimation
603 setTimingFunction:TimingFunction(ios::material::CurveEaseOut)];
604 [contentFadeAnimation setDuration:ios::material::kDuration5];
605 contentFadeAnimation =
606 DelayedAnimationMake(contentFadeAnimation, ios::material::kDuration1);
607 [contentsLayer addAnimation:contentFadeAnimation forKey:@"fade"];
608 [CATransaction commit];
609
610 // Since the animations have delay on them, the alpha of the content view
611 // needs to be set to zero and then one after the animation starts. If these
612 // steps are not taken, there will be a visible flash/jump from the initial
613 // spot during the animation.
614 [innerContainerView_ setAlpha:0];
615 }
616
617 - (void)animatePageInfoViewOut {
618 [CATransaction begin];
619 [CATransaction setCompletionBlock:^{
620 [self.containerView removeFromSuperview];
621 }];
622
623 CABasicAnimation* opacityAnimation =
624 [CABasicAnimation animationWithKeyPath:@"opacity"];
625 [opacityAnimation
626 setTimingFunction:TimingFunction(ios::material::CurveEaseIn)];
627 [opacityAnimation setDuration:ios::material::kDuration3];
628 [opacityAnimation setFromValue:@1];
629 [opacityAnimation setToValue:@0];
630 [[containerView_ layer] addAnimation:opacityAnimation forKey:@"animateOut"];
631
632 [popupContainer_ setAlpha:0];
633 [containerView_ setAlpha:0];
634 [CATransaction commit];
635 }
636
637 @end
OLDNEW
« 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