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

Unified Diff: ios/chrome/browser/ui/find_bar/find_bar_controller_ios.mm

Issue 2590473002: Upstream Chrome on iOS source code [5/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/find_bar/find_bar_controller_ios.mm
diff --git a/ios/chrome/browser/ui/find_bar/find_bar_controller_ios.mm b/ios/chrome/browser/ui/find_bar/find_bar_controller_ios.mm
new file mode 100644
index 0000000000000000000000000000000000000000..f032bf65af2b22e3c5ecfa784488e9aebf3ac49e
--- /dev/null
+++ b/ios/chrome/browser/ui/find_bar/find_bar_controller_ios.mm
@@ -0,0 +1,480 @@
+// 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/find_bar/find_bar_controller_ios.h"
+
+#include "base/format_macros.h"
+#include "base/i18n/rtl.h"
+#include "base/ios/ios_util.h"
+#include "base/mac/bundle_locations.h"
+#include "base/mac/foundation_util.h"
+#include "base/mac/objc_property_releaser.h"
+#include "base/mac/scoped_nsobject.h"
+#include "base/strings/sys_string_conversions.h"
+#include "components/strings/grit/components_strings.h"
+#import "ios/chrome/browser/find_in_page/find_in_page_controller.h"
+#import "ios/chrome/browser/find_in_page/find_in_page_model.h"
+#import "ios/chrome/browser/ui/UIView+SizeClassSupport.h"
+#import "ios/chrome/browser/ui/commands/UIKit+ChromeExecuteCommand.h"
+#import "ios/chrome/browser/ui/find_bar/find_bar_view.h"
+#include "ios/chrome/browser/ui/ui_util.h"
+#include "ui/base/l10n/l10n_util_mac.h"
+#include "ui/base/resource/resource_bundle.h"
+
+NSString* const kFindInPageContainerViewId = @"kFindInPageContainerViewId";
+
+namespace {
+
+// Find Bar height.
+// Right padding on iPad find bar.
+const CGFloat kFindBarIPhoneHeight = 56;
+const CGFloat kFindBarIPadHeight = 62;
+
+// Find Bar animation drop down duration.
+const CGFloat kAnimationDuration = 0.15;
+
+// For the first |kSearchDelayChars| characters, delay by |kSearchLongDelay|
+// For the remaining characters, delay by |kSearchShortDelay|.
+const NSUInteger kSearchDelayChars = 3;
+const NSTimeInterval kSearchLongDelay = 1.0;
+const NSTimeInterval kSearchShortDelay = 0.100;
+
+} // anonymous namespace
+
+#pragma mark - FindBarControllerIOS
+
+@interface FindBarControllerIOS ()<UITextFieldDelegate> {
+ base::mac::ObjCPropertyReleaser _propertyReleaser_FindInPageController;
+}
+
+// Set up iPad UI
+- (void)setUpIPad;
+// Set up iPhone UI
+- (void)setUpIPhone;
+// Animate find bar to iPad top right, or, when possible, to align find bar
+// horizontally with |alignmentFrame|.
+- (void)showIPadFindBarView:(BOOL)animate
+ intoView:(UIView*)parentView
+ withFrame:(CGRect)targetFrame
+ alignWithFrame:(CGRect)alignmentFrame
+ selectText:(BOOL)selectText;
+// Animate find bar over iPhone toolbar.
+- (void)showIPhoneFindBarView:(BOOL)animate
+ intoView:(UIView*)parentView
+ withFrame:(CGRect)targetFrame
+ selectText:(BOOL)selectText;
+// Returns the appropriate variant of the image for |image_name| based on
+// |_isIncognito| and device idiom.
+- (UIImage*)imageWithName:(NSString*)image_name;
+// Delay searching for the first |kSearchDelayChars| characters of a search term
+// to give time for a user to type out a longer word. Short words are currently
+// very inefficient and lock up the UIWebView.
+- (void)editingChanged:(id)sender;
+// Return the expected find bar height. This will include the status bar height
+// when running iOS7 on an iPhone.
+- (CGFloat)findBarHeight;
+// Selects text in such way that selection menu does not appear and
+// a11y label is read. When -[UITextField selectAll:] is used, iOS
+// will read "Select All" instead of a11y label.
+- (void)selectAllText;
+
+// Redefined to be readwrite. This view acts as background for |findBarView| and
+// contains it as a subview.
+@property(nonatomic, readwrite, strong) UIView* view;
+// The view containing all the buttons and textfields that is common between
+// iPhone and iPad.
+@property(nonatomic, retain) FindBarView* findBarView;
+// Typing delay timer.
+@property(nonatomic, retain) NSTimer* delayTimer;
+// Yes if incognito.
+@property(nonatomic, assign) BOOL isIncognito;
+@end
+
+@implementation FindBarControllerIOS
+
+@synthesize view = _view;
+@synthesize findBarView = _findBarView;
+@synthesize delayTimer = _delayTimer;
+@synthesize isIncognito = _isIncognito;
+
+#pragma mark - Lifecycle
+
+- (instancetype)initWithIncognito:(BOOL)isIncognito {
+ self = [super init];
+ if (self) {
+ _propertyReleaser_FindInPageController.Init(self,
+ [FindBarControllerIOS class]);
+ _isIncognito = isIncognito;
+ }
+ return self;
+}
+
+#pragma mark View Setup & Teardown
+
+- (UIView*)newFindBarView {
+ BOOL isIPad = IsIPadIdiom();
+ UIView* findBarBackground = nil;
+ if (isIPad) {
+ // Future self.view. Contains only |contentView|. Is an image view that is
+ // typecast elsewhere but always is exposed as a UIView.
+ findBarBackground =
+ [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 345, 62)];
+ findBarBackground.backgroundColor = [UIColor clearColor];
+ findBarBackground.userInteractionEnabled = YES;
+ } else {
+ findBarBackground =
+ [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 56)];
+ findBarBackground.backgroundColor = [UIColor whiteColor];
+ }
+
+ self.findBarView = [[[FindBarView alloc]
+ initWithDarkAppearance:self.isIncognito && !IsIPadIdiom()] autorelease];
+ [findBarBackground addSubview:self.findBarView];
+ self.findBarView.translatesAutoresizingMaskIntoConstraints = NO;
+ base::scoped_nsobject<NSMutableArray> constraints(
+ [[NSMutableArray alloc] init]);
+ [constraints addObjectsFromArray:@[
+ [self.findBarView.trailingAnchor
+ constraintEqualToAnchor:findBarBackground.trailingAnchor],
+ [self.findBarView.leadingAnchor
+ constraintEqualToAnchor:findBarBackground.leadingAnchor],
+ [self.findBarView.heightAnchor constraintEqualToConstant:56.0f]
+ ]];
+
+ if (isIPad) {
+ [constraints
+ addObject:[self.findBarView.centerYAnchor
+ constraintEqualToAnchor:findBarBackground.centerYAnchor
+ constant:-2]];
+ } else {
+ [constraints
+ addObject:[self.findBarView.bottomAnchor
+ constraintEqualToAnchor:findBarBackground.bottomAnchor]];
+ }
+
+ [NSLayoutConstraint activateConstraints:constraints];
+
+ self.findBarView.inputField.delegate = self;
+ [self.findBarView.inputField addTarget:self
+ action:@selector(editingChanged:)
+ forControlEvents:UIControlEventEditingChanged];
+ [self.findBarView.nextButton addTarget:self
+ action:@selector(hideKeyboard:)
+ forControlEvents:UIControlEventTouchUpInside];
+ [self.findBarView.previousButton addTarget:self
+ action:@selector(hideKeyboard:)
+ forControlEvents:UIControlEventTouchUpInside];
+
+ return findBarBackground;
+}
+
+- (void)setupViewInView:(UIView*)view {
+ self.view = [[self newFindBarView] autorelease];
+
+ // Idiom specific setup.
+ if ([self shouldShowCompactSearchBarInView:view])
+ [self setUpIPhone];
+ else
+ [self setUpIPad];
+
+ self.view.accessibilityIdentifier = kFindInPageContainerViewId;
+}
+
+- (void)teardownView {
+ [self.view removeFromSuperview];
+ self.view = nil;
+}
+
+- (void)setUpIPhone {
+ CGRect frame = self.view.frame;
+ frame.size.height = [self findBarHeight];
+ self.view.frame = frame;
+
+ if (self.isIncognito) {
+ [self.view setBackgroundColor:[UIColor colorWithWhite:115 / 255.0 alpha:1]];
+ }
+}
+
+- (void)setUpIPad {
+ self.view.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin;
+ UIEdgeInsets backgroundInsets = UIEdgeInsetsMake(6, 9, 10, 8);
+ UIImage* bgImage = [UIImage imageNamed:@"find_bg"];
+ bgImage = [bgImage resizableImageWithCapInsets:backgroundInsets];
+ UIImageView* bgView = (UIImageView*)self.view;
+ [bgView setImage:bgImage];
+}
+
+#pragma mark - Public
+
+- (NSString*)searchTerm {
+ return [self.findBarView.inputField text];
+}
+
+- (BOOL)isFindInPageShown {
+ return self.view != nil;
+}
+
+- (BOOL)isFocused {
+ return [self.findBarView.inputField isFirstResponder];
+}
+
+- (void)updateResultsCount:(FindInPageModel*)model {
+ [self updateWithMatchNumber:model.currentIndex
+ matchCount:model.matches
+ searchText:model.text];
+}
+
+- (void)updateView:(FindInPageModel*)model
+ initialUpdate:(BOOL)initialUpdate
+ focusTextfield:(BOOL)focusTextfield {
+ [self.delayTimer invalidate];
+ self.delayTimer = nil;
+
+ if (initialUpdate) {
+ // Set initial text and first search.
+ [self.findBarView.inputField setText:model.text];
+ [self editingChanged:self.findBarView.inputField];
+ }
+
+ // Focus input field if necessary.
+ if (focusTextfield) {
+ [self.findBarView.inputField becomeFirstResponder];
+ } else {
+ [self.findBarView.inputField resignFirstResponder];
+ }
+
+ [self updateWithMatchNumber:model.currentIndex
+ matchCount:model.matches
+ searchText:model.text];
+}
+
+- (void)updateWithMatchNumber:(NSUInteger)matchNumber
+ matchCount:(NSUInteger)matchCount
+ searchText:(NSString*)searchText {
+ NSString* text = nil;
+ if (searchText.length != 0) {
+ NSString* indexStr = [NSString stringWithFormat:@"%" PRIdNS, matchNumber];
+ NSString* matchesStr = [NSString stringWithFormat:@"%" PRIdNS, matchCount];
+ text = l10n_util::GetNSStringF(IDS_FIND_IN_PAGE_COUNT,
+ base::SysNSStringToUTF16(indexStr),
+ base::SysNSStringToUTF16(matchesStr));
+ }
+ [self.findBarView updateResultsLabelWithText:text];
+
+ BOOL enabled = matchCount != 0;
+ self.findBarView.nextButton.enabled = enabled;
+ self.findBarView.previousButton.enabled = enabled;
+}
+
+- (void)addFindBarView:(BOOL)animate
+ intoView:(UIView*)view
+ withFrame:(CGRect)frame
+ alignWithFrame:(CGRect)omniboxFrame
+ selectText:(BOOL)selectText {
+ // If already showing find bar, nothing to do.
+ if (self.view) {
+ return;
+ }
+ if ([self shouldShowCompactSearchBarInView:view]) {
+ [self showIPhoneFindBarView:animate
+ intoView:view
+ withFrame:frame
+ selectText:selectText];
+ } else {
+ [self showIPadFindBarView:animate
+ intoView:view
+ withFrame:frame
+ alignWithFrame:omniboxFrame
+ selectText:selectText];
+ }
+}
+
+- (void)hideFindBarView:(BOOL)animate {
+ // If view is nil, nothing to hide.
+ if (!self.view) {
+ return;
+ }
+
+ self.findBarView.inputField.selectedTextRange = nil;
+ [self.delayTimer invalidate];
+ self.delayTimer = nil;
+
+ if (animate) {
+ [UIView animateWithDuration:kAnimationDuration
+ animations:^{
+ CGRect frame = self.view.frame;
+ frame.size.height = 0;
+ self.view.frame = frame;
+ }
+ completion:^(BOOL finished) {
+ [self teardownView];
+ }];
+ } else {
+ [self teardownView];
+ }
+}
+
+- (void)hideKeyboard:(id)sender {
+ [self.view endEditing:YES];
+}
+
+- (UIImage*)imageWithName:(NSString*)imageName {
+ NSString* name = !IsIPadIdiom() && self.isIncognito
+ ? [imageName stringByAppendingString:@"_incognito"]
+ : imageName;
+ return [UIImage imageNamed:name];
+}
+
+#pragma mark - Internal
+
+- (void)selectAllText {
+ UITextRange* wholeTextRange = [self.findBarView.inputField
+ textRangeFromPosition:self.findBarView.inputField.beginningOfDocument
+ toPosition:self.findBarView.inputField.endOfDocument];
+ self.findBarView.inputField.selectedTextRange = wholeTextRange;
+}
+
+- (BOOL)shouldShowCompactSearchBarInView:(UIView*)view {
+ return !IsIPadIdiom();
+}
+
+// Animate find bar to iPad top right.
+- (void)showIPadFindBarView:(BOOL)animate
+ intoView:(UIView*)parentView
+ withFrame:(CGRect)targetFrame
+ alignWithFrame:(CGRect)omniboxFrame
+ selectText:(BOOL)selectText {
+ DCHECK(IsIPadIdiom());
+ [self setupViewInView:parentView];
+ UIView* view = self.view;
+ CGRect frame = view.frame;
+ frame.size.width =
+ MIN(CGRectGetWidth(parentView.bounds), CGRectGetWidth(frame));
+ frame.origin.y = targetFrame.origin.y;
+ frame.size.height = 0;
+
+ CGFloat containerWidth = parentView.bounds.size.width;
+ CGFloat nibWidth = frame.size.width;
+
+ // On iPad, there are three possible frames for the Search bar:
+ // 1. In Regular width size class, it is short, right-aligned to the omnibox's
+ // right edge.
+ // 2. In Compact size class, if the short bar width is less than the omnibox,
+ // stretch and align the search bar to the omnibox.
+ // 3. Finally, if the short bar width is more than the omnibox, fill the
+ // container view from edge to edge, ignoring the omnibox.
+ if (view.cr_widthSizeClass == REGULAR) {
+ if (base::i18n::IsRTL()) {
+ frame.origin.x = CGRectGetMinX(omniboxFrame);
+ } else {
+ frame.origin.x =
+ CGRectGetMinX(omniboxFrame) + CGRectGetWidth(omniboxFrame) - nibWidth;
+ }
+ frame.size.width = nibWidth;
+ } else {
+ // Compact size class.
+ if (omniboxFrame.size.width > nibWidth) {
+ frame.origin.x = omniboxFrame.origin.x;
+ frame.size.width = omniboxFrame.size.width;
+ } else {
+ frame.origin.x = 0;
+ frame.size.width = containerWidth;
+ }
+ }
+
+ view.frame = frame;
+ [parentView addSubview:view];
+
+ CGFloat duration = (animate) ? kAnimationDuration : 0;
+ [UIView animateWithDuration:duration
+ animations:^{
+ CGRect frame = view.frame;
+ frame.size.height = [self findBarHeight];
+ view.frame = frame;
+ }
+ completion:^(BOOL finished) {
+ if (selectText)
+ [self selectAllText];
+ }];
+}
+
+// Animate find bar over iPhone toolbar.
+- (void)showIPhoneFindBarView:(BOOL)animate
+ intoView:(UIView*)parentView
+ withFrame:(CGRect)targetFrame
+ selectText:(BOOL)selectText {
+ [self setupViewInView:parentView];
+ UIView* view = self.view;
+ CGRect frame = view.frame;
+ frame.size.width = targetFrame.size.width;
+ frame.origin.y = 0 - frame.size.height;
+ frame.origin.x = 0;
+ view.frame = frame;
+ [parentView addSubview:view];
+
+ CGFloat duration = (animate) ? kAnimationDuration : 0;
+ [UIView animateWithDuration:duration
+ animations:^{
+ CGRect frame = view.frame;
+ frame.origin.y = 0;
+ view.frame = frame;
+ }
+ completion:^(BOOL finished) {
+ if (selectText)
+ [self selectAllText];
+ }];
+}
+
+- (void)textChanged {
+ [self.view chromeExecuteCommand:self.findBarView.inputField];
+}
+
+- (void)editingChanged:(id)sender {
+ [self.delayTimer invalidate];
+ NSUInteger length = [[self searchTerm] length];
+ if (length == 0)
+ return [self textChanged];
+
+ // Delay delivery of text change event. Use a longer delay when the input
+ // length is short.
+ NSTimeInterval delay =
+ (length > kSearchDelayChars) ? kSearchShortDelay : kSearchLongDelay;
+ self.delayTimer =
+ [NSTimer scheduledTimerWithTimeInterval:delay
+ target:self
+ selector:@selector(textChanged)
+ userInfo:nil
+ repeats:NO];
+}
+
+- (CGFloat)findBarHeight {
+ if (IsIPadIdiom())
+ return kFindBarIPadHeight;
+ return StatusBarHeight() + kFindBarIPhoneHeight;
+}
+
+#pragma mark - UITextFieldDelegate
+
+- (BOOL)textFieldShouldBeginEditing:(UITextField*)textField {
+ DCHECK(textField == self.findBarView.inputField);
+ [[NSNotificationCenter defaultCenter]
+ postNotificationName:kFindBarTextFieldWillBecomeFirstResponderNotification
+ object:self];
+ return YES;
+}
+
+- (void)textFieldDidEndEditing:(UITextField*)textField {
+ DCHECK(textField == self.findBarView.inputField);
+ [[NSNotificationCenter defaultCenter]
+ postNotificationName:kFindBarTextFieldDidResignFirstResponderNotification
+ object:self];
+}
+
+- (BOOL)textFieldShouldReturn:(UITextField*)textField {
+ DCHECK(textField == self.findBarView.inputField);
+ [self.findBarView.inputField resignFirstResponder];
+ return YES;
+}
+
+@end
« no previous file with comments | « ios/chrome/browser/ui/find_bar/find_bar_controller_ios.h ('k') | ios/chrome/browser/ui/find_bar/find_bar_text_field.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698