| Index: ios/chrome/browser/ui/find_bar/find_bar_view.mm
|
| diff --git a/ios/chrome/browser/ui/find_bar/find_bar_view.mm b/ios/chrome/browser/ui/find_bar/find_bar_view.mm
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..443c7e3964b6d2a23347d5c68d6098e9c9f086d3
|
| --- /dev/null
|
| +++ b/ios/chrome/browser/ui/find_bar/find_bar_view.mm
|
| @@ -0,0 +1,271 @@
|
| +// Copyright 2016 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_view.h"
|
| +
|
| +#include "base/mac/scoped_nsobject.h"
|
| +#include "components/strings/grit/components_strings.h"
|
| +#import "ios/chrome/browser/ui/commands/ios_command_ids.h"
|
| +#import "ios/chrome/browser/ui/find_bar/find_bar_touch_forwarding_view.h"
|
| +#import "ios/chrome/browser/ui/uikit_ui_util.h"
|
| +#include "ios/chrome/grit/ios_strings.h"
|
| +#import "ios/third_party/material_components_ios/src/components/Typography/src/MaterialTypography.h"
|
| +#include "ui/base/l10n/l10n_util_mac.h"
|
| +#import "ui/gfx/ios/NSString+CrStringDrawing.h"
|
| +
|
| +NSString* const kFindInPageInputFieldId = @"kFindInPageInputFieldId";
|
| +NSString* const kFindInPageNextButtonId = @"kFindInPageNextButtonId";
|
| +NSString* const kFindInPagePreviousButtonId = @"kFindInPagePreviousButtonId";
|
| +NSString* const kFindInPageCloseButtonId = @"kFindInPageCloseButtonId";
|
| +
|
| +@interface FindBarView ()
|
| +
|
| +// The overlay that shows number of results in format "1 of 13".
|
| +@property(nonatomic, assign) UILabel* resultsLabel;
|
| +@property(nonatomic, assign) UIView* separator;
|
| +
|
| +// Initializes all subviews.
|
| +- (void)setupSubviews;
|
| +// Sets up appearance of subviews, such as fonts, background colors.
|
| +- (void)configureApperance:(BOOL)isDark;
|
| +// Convenience method that returns images for light and dark appearances.
|
| +- (UIImage*)imageWithName:(NSString*)imageName isDark:(BOOL)isDark;
|
| +
|
| +@end
|
| +
|
| +@implementation FindBarView
|
| +@synthesize inputField = _inputField;
|
| +@synthesize resultsLabel = _resultsLabel;
|
| +@synthesize previousButton = _previousButton;
|
| +@synthesize nextButton = _nextButton;
|
| +@synthesize closeButton = _closeButton;
|
| +@synthesize separator = _separator;
|
| +
|
| +- (instancetype)initWithDarkAppearance:(BOOL)darkAppearance {
|
| + self = [super initWithFrame:CGRectZero];
|
| + if (self) {
|
| + [self setupSubviews];
|
| + [self configureApperance:darkAppearance];
|
| + }
|
| + return self;
|
| +}
|
| +
|
| +#pragma mark - Public methods
|
| +
|
| +- (void)updateResultsLabelWithText:(NSString*)text {
|
| + self.resultsLabel.hidden = (text.length == 0);
|
| + self.resultsLabel.text = text;
|
| +}
|
| +
|
| +#pragma mark - Internal
|
| +
|
| +- (void)setupSubviews {
|
| + [self setBackgroundColor:[UIColor clearColor]];
|
| +
|
| + // Input field.
|
| + base::scoped_nsobject<UITextField> inputFieldScoped(
|
| + [[UITextField alloc] initWithFrame:CGRectZero]);
|
| + self.inputField = inputFieldScoped;
|
| + self.inputField.backgroundColor = [UIColor clearColor];
|
| + self.inputField.tag = IDC_FIND_UPDATE;
|
| + self.inputField.translatesAutoresizingMaskIntoConstraints = NO;
|
| + self.inputField.placeholder =
|
| + l10n_util::GetNSString(IDS_IOS_PLACEHOLDER_FIND_IN_PAGE);
|
| +
|
| + // Label containing number of found results.
|
| + base::scoped_nsobject<UILabel> resultsLabelScoped(
|
| + [[UILabel alloc] initWithFrame:CGRectZero]);
|
| + self.resultsLabel = resultsLabelScoped;
|
| + self.resultsLabel.textColor = [UIColor lightGrayColor];
|
| + self.resultsLabel.font = [UIFont systemFontOfSize:14];
|
| + [self.resultsLabel
|
| + setContentCompressionResistancePriority:UILayoutPriorityRequired
|
| + forAxis:UILayoutConstraintAxisHorizontal];
|
| + [self.resultsLabel
|
| + setContentHuggingPriority:UILayoutPriorityRequired
|
| + forAxis:UILayoutConstraintAxisHorizontal];
|
| +
|
| + // Stack view that holds |inputField| and |resultsLabel|.
|
| + base::scoped_nsobject<UIStackView> inputStackView([[UIStackView alloc]
|
| + initWithArrangedSubviews:@[ inputFieldScoped, resultsLabelScoped ]]);
|
| + [inputStackView setLayoutMargins:UIEdgeInsetsMake(0, 12, 0, 12)];
|
| + [inputStackView setLayoutMarginsRelativeArrangement:YES];
|
| + [inputStackView setSpacing:12];
|
| + [inputStackView setTranslatesAutoresizingMaskIntoConstraints:NO];
|
| + [self addSubview:inputStackView];
|
| +
|
| + base::scoped_nsobject<NSMutableArray> constraints(
|
| + [[NSMutableArray alloc] init]);
|
| + [constraints addObjectsFromArray:@[
|
| + [[inputStackView leadingAnchor] constraintEqualToAnchor:self.leadingAnchor],
|
| + [[inputStackView topAnchor] constraintEqualToAnchor:self.topAnchor],
|
| + [[inputStackView bottomAnchor] constraintEqualToAnchor:self.bottomAnchor],
|
| + ]];
|
| +
|
| + // Touch-forwarding view is put on top of |inputStackView| to forward touches
|
| + // to |inputField|.
|
| + // Unlike a gesture recognizer, forwarding all touch events allows for using
|
| + // long press, pinch and other manipulatiosn on the target textfield.
|
| + base::scoped_nsobject<FindBarTouchForwardingView> forwarder(
|
| + [[FindBarTouchForwardingView alloc] init]);
|
| + [forwarder setTargetView:self.inputField];
|
| + [self addSubview:forwarder];
|
| + [constraints addObjectsFromArray:@[
|
| + [[forwarder leadingAnchor]
|
| + constraintEqualToAnchor:[inputStackView leadingAnchor]],
|
| + [[forwarder topAnchor] constraintEqualToAnchor:[inputStackView topAnchor]],
|
| + [[forwarder bottomAnchor]
|
| + constraintEqualToAnchor:[inputStackView bottomAnchor]],
|
| + [[forwarder trailingAnchor]
|
| + constraintEqualToAnchor:[inputStackView trailingAnchor]],
|
| + ]];
|
| + [forwarder setTranslatesAutoresizingMaskIntoConstraints:NO];
|
| +
|
| + // Thin line separator between buttons and input.
|
| + base::scoped_nsobject<UIView> separatorScoped(
|
| + [[UIView alloc] initWithFrame:CGRectZero]);
|
| + UIView* separator = separatorScoped;
|
| + separator.backgroundColor = [UIColor colorWithWhite:0.83 alpha:1];
|
| + [self addSubview:separator];
|
| + [constraints addObjectsFromArray:@[
|
| + [separator.widthAnchor constraintEqualToConstant:1],
|
| + [separator.bottomAnchor constraintEqualToAnchor:self.bottomAnchor
|
| + constant:-8],
|
| + [separator.topAnchor constraintEqualToAnchor:self.topAnchor constant:8],
|
| + [separator.leadingAnchor
|
| + constraintEqualToAnchor:inputStackView.get().trailingAnchor],
|
| + ]];
|
| + separator.translatesAutoresizingMaskIntoConstraints = NO;
|
| + self.separator = separator;
|
| +
|
| + // Previous button with an arrow.
|
| + base::scoped_nsobject<UIButton> previousButtonScoped(
|
| + [[UIButton alloc] initWithFrame:CGRectZero]);
|
| + self.previousButton = previousButtonScoped;
|
| + [self addSubview:self.previousButton];
|
| + [constraints addObjectsFromArray:@[
|
| + [self.previousButton.centerYAnchor
|
| + constraintEqualToAnchor:self.centerYAnchor],
|
| + [self.previousButton.widthAnchor constraintEqualToConstant:48],
|
| + [self.previousButton.heightAnchor constraintEqualToConstant:56],
|
| + [self.previousButton.leadingAnchor
|
| + constraintEqualToAnchor:separator.trailingAnchor],
|
| + ]];
|
| + self.previousButton.isAccessibilityElement = YES;
|
| + self.previousButton.accessibilityTraits = UIAccessibilityTraitButton;
|
| + self.previousButton.tag = IDC_FIND_PREVIOUS;
|
| + self.previousButton.translatesAutoresizingMaskIntoConstraints = NO;
|
| +
|
| + // Next button with an arrow.
|
| + base::scoped_nsobject<UIButton> nextButtonScoped(
|
| + [[UIButton alloc] initWithFrame:CGRectZero]);
|
| + self.nextButton = nextButtonScoped;
|
| + [self addSubview:self.nextButton];
|
| + [constraints addObjectsFromArray:@[
|
| + [self.nextButton.centerYAnchor constraintEqualToAnchor:self.centerYAnchor],
|
| + [self.nextButton.widthAnchor constraintEqualToConstant:48],
|
| + [self.nextButton.heightAnchor constraintEqualToConstant:56],
|
| + [self.nextButton.leadingAnchor
|
| + constraintEqualToAnchor:self.previousButton.trailingAnchor],
|
| + ]];
|
| + self.nextButton.tag = IDC_FIND_NEXT;
|
| + self.nextButton.translatesAutoresizingMaskIntoConstraints = NO;
|
| +
|
| + // Close button with a cross.
|
| + base::scoped_nsobject<UIButton> closeButtonScoped(
|
| + [[UIButton alloc] initWithFrame:CGRectZero]);
|
| + self.closeButton = closeButtonScoped;
|
| + [self addSubview:self.closeButton];
|
| + [constraints addObjectsFromArray:@[
|
| + [self.closeButton.centerYAnchor constraintEqualToAnchor:self.centerYAnchor],
|
| + [self.closeButton.trailingAnchor constraintEqualToAnchor:self.trailingAnchor
|
| + constant:-4],
|
| + [self.closeButton.widthAnchor constraintEqualToConstant:48],
|
| + [self.closeButton.heightAnchor constraintEqualToConstant:56],
|
| + [self.closeButton.leadingAnchor
|
| + constraintEqualToAnchor:self.nextButton.trailingAnchor],
|
| + ]];
|
| + self.closeButton.tag = IDC_FIND_CLOSE;
|
| + self.closeButton.translatesAutoresizingMaskIntoConstraints = NO;
|
| +
|
| + // Connect outlets.
|
| + [self.nextButton addTarget:self
|
| + action:@selector(chromeExecuteCommand:)
|
| + forControlEvents:UIControlEventTouchUpInside];
|
| + [self.previousButton addTarget:self
|
| + action:@selector(chromeExecuteCommand:)
|
| + forControlEvents:UIControlEventTouchUpInside];
|
| + [self.closeButton addTarget:self
|
| + action:@selector(chromeExecuteCommand:)
|
| + forControlEvents:UIControlEventTouchUpInside];
|
| +
|
| + // A11y labels.
|
| + SetA11yLabelAndUiAutomationName(self.closeButton,
|
| + IDS_FIND_IN_PAGE_CLOSE_TOOLTIP,
|
| + kFindInPageCloseButtonId);
|
| + SetA11yLabelAndUiAutomationName(self.previousButton,
|
| + IDS_FIND_IN_PAGE_PREVIOUS_TOOLTIP,
|
| + kFindInPagePreviousButtonId);
|
| + SetA11yLabelAndUiAutomationName(
|
| + self.nextButton, IDS_FIND_IN_PAGE_NEXT_TOOLTIP, kFindInPageNextButtonId);
|
| + self.inputField.accessibilityIdentifier = kFindInPageInputFieldId;
|
| +
|
| + // Configure fonts.
|
| + [self.inputField setFont:[MDCTypography body1Font]];
|
| + [self.resultsLabel setFont:[MDCTypography body1Font]];
|
| +
|
| + [NSLayoutConstraint activateConstraints:constraints];
|
| +}
|
| +
|
| +- (void)configureApperance:(BOOL)isDark {
|
| + [self.closeButton setImage:[self imageWithName:@"find_close" isDark:isDark]
|
| + forState:UIControlStateNormal];
|
| + [self.closeButton
|
| + setImage:[self imageWithName:@"find_close_pressed" isDark:isDark]
|
| + forState:UIControlStateHighlighted];
|
| +
|
| + [self.previousButton setImage:[self imageWithName:@"find_prev" isDark:isDark]
|
| + forState:UIControlStateNormal];
|
| + [self.previousButton
|
| + setImage:[self imageWithName:@"find_prev_pressed" isDark:isDark]
|
| + forState:UIControlStateHighlighted];
|
| + [self.previousButton
|
| + setImage:[self imageWithName:@"find_prev_disabled" isDark:isDark]
|
| + forState:UIControlStateDisabled];
|
| +
|
| + [self.nextButton setImage:[self imageWithName:@"find_next" isDark:isDark]
|
| + forState:UIControlStateNormal];
|
| + [self.nextButton
|
| + setImage:[self imageWithName:@"find_next_pressed" isDark:isDark]
|
| + forState:UIControlStateHighlighted];
|
| + [self.nextButton
|
| + setImage:[self imageWithName:@"find_next_disabled" isDark:isDark]
|
| + forState:UIControlStateDisabled];
|
| +
|
| + if (!isDark) {
|
| + return;
|
| + }
|
| +
|
| + // Setup dark appearance.
|
| + [self.inputField setTextColor:[UIColor whiteColor]];
|
| + NSString* placeholder = [self.inputField placeholder];
|
| + UIColor* inputTextColor = [UIColor colorWithWhite:1 alpha:0.7];
|
| + NSDictionary* attributes = @{NSForegroundColorAttributeName : inputTextColor};
|
| + [self.inputField
|
| + setAttributedPlaceholder:[[[NSAttributedString alloc]
|
| + initWithString:placeholder
|
| + attributes:attributes] autorelease]];
|
| + UIColor* resultTextColor = [UIColor colorWithWhite:1 alpha:0.3];
|
| + [self.resultsLabel setTextColor:resultTextColor];
|
| + UIColor* separatorColor = [UIColor colorWithWhite:0 alpha:0.1];
|
| + [self.separator setBackgroundColor:separatorColor];
|
| +}
|
| +
|
| +- (UIImage*)imageWithName:(NSString*)imageName isDark:(BOOL)isDark {
|
| + NSString* name =
|
| + isDark ? [imageName stringByAppendingString:@"_incognito"] : imageName;
|
| + return [UIImage imageNamed:name];
|
| +}
|
| +
|
| +@end
|
|
|