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

Unified Diff: ios/chrome/browser/ui/popup_menu/popup_menu_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/popup_menu/popup_menu_controller.mm
diff --git a/ios/chrome/browser/ui/popup_menu/popup_menu_controller.mm b/ios/chrome/browser/ui/popup_menu/popup_menu_controller.mm
new file mode 100644
index 0000000000000000000000000000000000000000..67844336d01c4c046bc9a25e4611011b1cfdf012
--- /dev/null
+++ b/ios/chrome/browser/ui/popup_menu/popup_menu_controller.mm
@@ -0,0 +1,287 @@
+// Copyright 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/popup_menu/popup_menu_controller.h"
+
+#import "base/ios/weak_nsobject.h"
+#include "base/logging.h"
+#include "base/mac/bundle_locations.h"
+#include "base/mac/objc_property_releaser.h"
+#import "ios/chrome/browser/ui/animation_util.h"
+#import "ios/chrome/browser/ui/popup_menu/popup_menu_view.h"
+#include "ios/chrome/browser/ui/rtl_geometry.h"
+#import "ios/chrome/browser/ui/uikit_ui_util.h"
+#import "ios/chrome/common/material_timing.h"
+#include "ios/chrome/grit/ios_strings.h"
+#include "ui/base/l10n/l10n_util.h"
+
+using ios::material::TimingFunction;
+
+namespace {
+// Inset for the shadows of the contained views.
+static const CGFloat kPopupMenuVerticalInset = 11.0;
+// Duration for the Popup Menu Fade In animation
+static const CGFloat kFadeInAnimationDuration = 0.2;
+// Value to pass in for backgroundButtonTag to not set a tag value for
+// |backgroundButton_|.
+static const NSInteger kBackgroundButtonNoTag = -1;
+// Default width of the popup container.
+static const CGFloat kPopupContainerWidth = 236.0;
+// Default height of the popup container.
+static const CGFloat kPopupContainerHeight = 280.0;
+static const CGFloat kPopoverScaleFactor = 0.03;
+
+static void SetAnchorPoint(CGPoint anchorPoint, UIView* view) {
+ CGPoint oldOrigin = view.frame.origin;
+ view.layer.anchorPoint = anchorPoint;
+ CGPoint newOrigin = view.frame.origin;
+
+ CGPoint transition;
+ transition.x = newOrigin.x - oldOrigin.x;
+ transition.y = newOrigin.y - oldOrigin.y;
+
+ view.center =
+ CGPointMake(view.center.x - transition.x, view.center.y - transition.y);
+}
+
+static CGPoint AnimateInIntermediaryPoint(CGPoint source, CGPoint destination) {
+ CGPoint midPoint = CGPointZero;
+ midPoint.x = destination.x;
+ midPoint.y = source.y - 0.8 * fabs(destination.y - source.y);
+ return midPoint;
+}
+
+} // anonymous namespace
+
+@interface PopupMenuController ()<PopupMenuViewDelegate> {
+ base::mac::ObjCPropertyReleaser propertyReleaser_PopupMenuController_;
+ CGPoint sourceAnimationPoint_;
+}
+@end
+
+@implementation PopupMenuController
+
+@synthesize containerView = containerView_;
+@synthesize backgroundButton = backgroundButton_;
+@synthesize popupContainer = popupContainer_;
+@synthesize delegate = delegate_;
+
+- (id)initWithParentView:(UIView*)parent {
+ return [self initWithParentView:parent
+ backgroundButtonParent:nil
+ backgroundButtonColor:nil
+ backgroundButtonAlpha:1.0
+ backgroundButtonTag:kBackgroundButtonNoTag
+ backgroundButtonSelector:nil];
+}
+
+- (id)initWithParentView:(UIView*)parent
+ backgroundButtonParent:(UIView*)backgroundButtonParent
+ backgroundButtonColor:(UIColor*)backgroundButtonColor
+ backgroundButtonAlpha:(CGFloat)backgroundButtonAlpha
+ backgroundButtonTag:(NSInteger)backgroundButtonTag
+ backgroundButtonSelector:(SEL)backgroundButtonSelector {
+ DCHECK(parent);
+ self = [super init];
+ if (self) {
+ propertyReleaser_PopupMenuController_.Init(self,
+ [PopupMenuController class]);
+
+ popupContainer_ = [[PopupMenuView alloc]
+ initWithFrame:CGRectMake(0, 0, kPopupContainerWidth,
+ kPopupContainerHeight)];
+
+ containerView_ = [[UIView alloc] initWithFrame:[parent bounds]];
+ containerView_.backgroundColor = [UIColor clearColor];
+ [containerView_ setAccessibilityViewIsModal:YES];
+ [popupContainer_ setDelegate:self];
+ // All views are added to the |containerView_| that in turn is added to the
+ // parent view. The Container View is needed to have a simple alpha
+ // transition when the menu is displayed or hidden.
+ [containerView_ addSubview:popupContainer_];
+ [parent addSubview:containerView_];
+
+ // Initialize backgroundButton_.
+ UIView* buttonParent =
+ backgroundButtonParent == nil ? containerView_ : backgroundButtonParent;
+ backgroundButton_ = [[UIButton alloc] initWithFrame:[buttonParent bounds]];
+ [buttonParent addSubview:backgroundButton_];
+ if (buttonParent == containerView_)
+ [buttonParent sendSubviewToBack:backgroundButton_];
+
+ backgroundButton_.autoresizingMask =
+ UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth |
+ UIViewAutoresizingFlexibleBottomMargin |
+ UIViewAutoresizingFlexibleLeadingMargin();
+ backgroundButton_.alpha = backgroundButtonAlpha;
+ if (backgroundButtonTag != kBackgroundButtonNoTag)
+ backgroundButton_.tag = backgroundButtonTag;
+ if (backgroundButtonColor != nil) {
+ backgroundButton_.backgroundColor = backgroundButtonColor;
+ }
+ if (backgroundButtonSelector != nil) {
+ [backgroundButton_ addTarget:nil
+ action:backgroundButtonSelector
+ forControlEvents:UIControlEventTouchDown];
+ } else {
+ [backgroundButton_ addTarget:self
+ action:@selector(tappedBehindPopup:)
+ forControlEvents:UIControlEventTouchDown];
+ }
+ [backgroundButton_ setAccessibilityLabel:l10n_util::GetNSString(
+ IDS_IOS_TOOLBAR_CLOSE_MENU)];
+ }
+ return self;
+}
+
+- (void)setOptimalSize:(CGSize)optimalSize atOrigin:(CGPoint)origin {
+ CGRect popupFrame = [popupContainer_ bounds];
+ popupFrame.size.width = optimalSize.width;
+ popupFrame.size.height = 2 * kPopupMenuVerticalInset + optimalSize.height;
+
+ // If the origin is on the right half of the screen, treat origin as the top-
+ // right coordinate instead of top-left.
+ CGFloat xOffset = origin.x > [containerView_ bounds].size.width / 2
+ ? origin.x - popupFrame.size.width
+ : origin.x;
+ [popupContainer_ setFrame:CGRectOffset(popupFrame, xOffset, origin.y)];
+}
+
+- (void)fadeInPopupFromSource:(CGPoint)source
+ toDestination:(CGPoint)destination {
+ [self animateInFromPoint:source toPoint:destination];
+ UIAccessibilityPostNotification(UIAccessibilityLayoutChangedNotification,
+ containerView_);
+}
+
+- (void)dismissAnimatedWithCompletion:(void (^)(void))completion {
+ [self animateOutToPoint:sourceAnimationPoint_ completion:completion];
+ UIAccessibilityPostNotification(UIAccessibilityLayoutChangedNotification,
+ nil);
+}
+
+// Animate the view on screen (Fade in).
+- (void)fadeInPopup:(void (^)(BOOL finished))completionBlock {
+ [UIView animateWithDuration:kFadeInAnimationDuration
+ delay:0.0
+ options:UIViewAnimationOptionAllowUserInteraction
+ animations:^{
+ [containerView_ setAlpha:1.0];
+ }
+ completion:completionBlock];
+}
+
+- (void)dealloc {
+ [popupContainer_ removeFromSuperview];
+ [backgroundButton_ removeFromSuperview];
+ [containerView_ removeFromSuperview];
+ [super dealloc];
+}
+
+- (void)tappedBehindPopup:(id)sender {
+ [self dismissPopupMenu];
+}
+
+- (void)animateInFromPoint:(CGPoint)source toPoint:(CGPoint)destination {
+ sourceAnimationPoint_ = source;
+
+ // Set anchor to top right for top right destinations.
+ NSUInteger anchorX =
+ destination.x > [containerView_ bounds].size.width / 2 ? 1 : 0;
+ SetAnchorPoint(CGPointMake(anchorX, 0), popupContainer_);
+
+ CGPoint midPoint = AnimateInIntermediaryPoint(source, destination);
+
+ CATransform3D scaleTransform =
+ CATransform3DMakeScale(kPopoverScaleFactor, kPopoverScaleFactor, 1);
+
+ NSValue* destinationScaleValue =
+ [NSValue valueWithCATransform3D:CATransform3DIdentity];
+
+ CABasicAnimation* scaleAnimation =
+ [CABasicAnimation animationWithKeyPath:@"transform"];
+ CAMediaTimingFunction* easeOut = TimingFunction(ios::material::CurveEaseOut);
+ [scaleAnimation setFromValue:[NSValue valueWithCATransform3D:scaleTransform]];
+ [scaleAnimation setToValue:destinationScaleValue];
+ [scaleAnimation setTimingFunction:easeOut];
+ [scaleAnimation setDuration:ios::material::kDuration1];
+
+ CAKeyframeAnimation* positionAnimation =
+ [CAKeyframeAnimation animationWithKeyPath:@"position"];
+ [positionAnimation setValues:@[
+ [NSValue valueWithCGPoint:source], [NSValue valueWithCGPoint:source],
+ [NSValue valueWithCGPoint:midPoint], [NSValue valueWithCGPoint:destination]
+ ]];
+ [positionAnimation setTimingFunction:easeOut];
+ [positionAnimation setDuration:ios::material::kDuration1];
+ [positionAnimation setKeyTimes:@[ @0, @0.2, @0.5, @1 ]];
+
+ CAMediaTimingFunction* linear = TimingFunction(ios::material::CurveLinear);
+ CAAnimation* fadeAnimation = OpacityAnimationMake(0, 1);
+ [fadeAnimation setDuration:ios::material::kDuration2];
+ [fadeAnimation setTimingFunction:linear];
+ [fadeAnimation setBeginTime:ios::material::kDuration2];
+
+ CALayer* layer = [popupContainer_ layer];
+ [layer addAnimation:AnimationGroupMake(
+ @[ scaleAnimation, positionAnimation, fadeAnimation ])
+ forKey:@"popup-in"];
+}
+
+- (void)animateOutToPoint:(CGPoint)destination
+ completion:(void (^)(void))completion {
+ CGPoint source = [[popupContainer_ layer] position];
+
+ CGPoint midPoint = CGPointZero;
+ midPoint.x = destination.x;
+ midPoint.y = source.y - 0.8 * fabs(destination.x - source.x);
+
+ CATransform3D scaleTransform =
+ CATransform3DMakeScale(kPopoverScaleFactor, kPopoverScaleFactor, 1);
+
+ CAMediaTimingFunction* easeIn = TimingFunction(ios::material::CurveEaseIn);
+ [CATransaction begin];
+ [CATransaction setAnimationTimingFunction:easeIn];
+ [CATransaction setAnimationDuration:ios::material::kDuration2];
+
+ base::WeakNSObject<PopupMenuController> weakSelf(self);
+ [CATransaction setCompletionBlock:^{
+ if (completion)
+ completion();
+ }];
+
+ NSValue* sourceScaleValue =
+ [NSValue valueWithCATransform3D:CATransform3DIdentity];
+
+ CABasicAnimation* scaleAnimation =
+ [CABasicAnimation animationWithKeyPath:@"transform"];
+ [scaleAnimation setFromValue:sourceScaleValue];
+ [scaleAnimation setToValue:[NSValue valueWithCATransform3D:scaleTransform]];
+
+ CABasicAnimation* positionAnimation =
+ [CABasicAnimation animationWithKeyPath:@"position"];
+ [positionAnimation setFromValue:[NSValue valueWithCGPoint:source]];
+ [positionAnimation setToValue:[NSValue valueWithCGPoint:destination]];
+
+ CABasicAnimation* fadeAnimation =
+ [CABasicAnimation animationWithKeyPath:@"opacity"];
+ [fadeAnimation setFromValue:@1];
+ [fadeAnimation setToValue:@0];
+
+ CALayer* layer = [popupContainer_ layer];
+ [layer addAnimation:AnimationGroupMake(
+ @[ scaleAnimation, positionAnimation, fadeAnimation ])
+ forKey:@"out"];
+
+ [CATransaction commit];
+}
+
+#pragma mark -
+#pragma mark PopupMenuViewDelegate
+
+- (void)dismissPopupMenu {
+ [delegate_ dismissPopupMenu:self];
+}
+
+@end
« no previous file with comments | « ios/chrome/browser/ui/popup_menu/popup_menu_controller.h ('k') | ios/chrome/browser/ui/popup_menu/popup_menu_view.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698