blob: e7ae711dfe2a8dc93fa34f26d07cb34f35d448b9 [file] [log] [blame]
// Copyright 2017 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#import "ios/chrome/browser/bubble/ui_bundled/bubble_view_controller.h"
#import "base/notreached.h"
#import "ios/chrome/browser/bubble/ui_bundled/bubble_constants.h"
#import "ios/chrome/browser/bubble/ui_bundled/bubble_view.h"
#import "ios/chrome/browser/shared/public/features/features.h"
#import "ios/chrome/browser/shared/ui/util/animation_util.h"
#import "ios/chrome/common/material_timing.h"
namespace {
// The vertical offset distance used in the sink-down animation.
const CGFloat kVerticalOffset = 8.0f;
BubbleView* BubbleViewWithType(
BubbleViewType bubble_view_type,
NSString* text,
NSString* title,
BubbleArrowDirection arrow_direction,
BubbleAlignment alignment,
id<BubbleViewDelegate> delegate,
BubblePageControlPage page = BubblePageControlPageNone) {
BOOL show_title = NO;
BOOL show_close_button = NO;
BOOL show_snooze_button = NO;
BOOL show_next_button = NO;
NSTextAlignment text_alignment = NSTextAlignmentNatural;
switch (bubble_view_type) {
case BubbleViewTypeDefault:
text_alignment = NSTextAlignmentCenter;
break;
case BubbleViewTypeWithClose:
show_close_button = YES;
break;
case BubbleViewTypeRich:
show_title = YES;
break;
case BubbleViewTypeRichWithSnooze:
show_title = YES;
show_snooze_button = YES;
break;
case BubbleViewTypeRichWithNext:
show_title = YES;
show_next_button = YES;
break;
}
BubbleView* bubble_view =
[[BubbleView alloc] initWithText:text
arrowDirection:arrow_direction
alignment:alignment
showsCloseButton:show_close_button
title:show_title ? title : nil
showsSnoozeButton:show_snooze_button
showsNextButton:show_next_button
page:page
textAlignment:text_alignment
delegate:delegate];
return bubble_view;
}
} // namespace
@interface BubbleViewController ()
@property(nonatomic, copy, readonly) NSString* text;
@property(nonatomic, assign, readonly) BubbleArrowDirection arrowDirection;
@property(nonatomic, assign, readonly) BubbleAlignment alignment;
@property(nonatomic, weak) id<BubbleViewDelegate> delegate;
@property(nonatomic, assign, readonly) BubbleViewType bubbleViewType;
@property(nonatomic, strong) BubbleView* view;
@end
@implementation BubbleViewController {
BubblePageControlPage _page;
}
@synthesize text = _text;
@synthesize arrowDirection = _arrowDirection;
@synthesize alignment = _alignment;
@dynamic view;
- (instancetype)initWithText:(NSString*)text
title:(NSString*)titleString
arrowDirection:(BubbleArrowDirection)direction
alignment:(BubbleAlignment)alignment
bubbleViewType:(BubbleViewType)type
pageControlPage:(BubblePageControlPage)page
delegate:(id<BubbleViewDelegate>)delegate {
self = [super initWithNibName:nil bundle:nil];
if (self) {
_text = text;
self.title = [titleString copy];
_arrowDirection = direction;
_alignment = alignment;
_bubbleViewType = type;
_page = page;
_delegate = delegate;
}
return self;
}
- (void)loadView {
self.view = BubbleViewWithType(self.bubbleViewType, self.text, self.title,
self.arrowDirection, self.alignment,
self.delegate, _page);
// Begin hidden.
[self.view setAlpha:0.0f];
[self.view setHidden:YES];
}
// Animate the bubble view in with a fade-in and sink-down animation if
// `animated` is YES, otherwise just show the bubble view.
- (void)displayAnimated:(BOOL)animated {
if (!animated) {
[self.view setAlpha:1.0f];
[self.view setHidden:NO];
return;
}
// Set the frame's origin to be slightly higher on the screen, so that the
// view will be properly positioned once it sinks down.
CGRect frame = self.view.frame;
frame.origin.y = frame.origin.y - kVerticalOffset;
[self.view setFrame:frame];
[self.view setHidden:NO];
// Set the y-coordinate of `frame.origin` to its final value.
frame.origin.y = frame.origin.y + kVerticalOffset;
[UIView animateWithDuration:kMaterialDuration3
delay:0.0
options:UIViewAnimationOptionCurveEaseOut
animations:^{
[self.view setFrame:frame];
[self.view setAlpha:1.0f];
}
completion:nil];
}
- (void)setArrowHidden:(BOOL)hidden animated:(BOOL)animated {
[self.view setArrowHidden:hidden animated:animated];
}
- (void)dismissAnimated:(BOOL)animated {
NSTimeInterval duration = (animated ? kMaterialDuration3 : 0.0);
[UIView animateWithDuration:duration
animations:^{
[self.view setAlpha:0.0f];
}
completion:^(BOOL finished) {
[self.view setHidden:YES];
[self willMoveToParentViewController:nil];
[self.view removeFromSuperview];
[self removeFromParentViewController];
}];
}
- (void)setBubbleAlignmentOffset:(CGFloat)alignmentOffset {
self.view.alignmentOffset = alignmentOffset;
}
@end