| // Copyright 2017 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/omnibox/omnibox_container_view.h" |
| |
| #import "ios/chrome/browser/ui/omnibox/omnibox_text_field_ios.h" |
| #import "ios/chrome/browser/ui/util/animation_util.h" |
| #include "ios/chrome/browser/ui/util/rtl_geometry.h" |
| #include "ios/chrome/browser/ui/util/ui_util.h" |
| #import "ios/chrome/browser/ui/util/uikit_ui_util.h" |
| #import "ios/chrome/common/material_timing.h" |
| #include "ios/chrome/grit/ios_strings.h" |
| #include "ios/chrome/grit/ios_theme_resources.h" |
| #include "skia/ext/skia_utils_ios.h" |
| #include "ui/gfx/color_palette.h" |
| #include "ui/gfx/image/image.h" |
| |
| #if !defined(__has_feature) || !__has_feature(objc_arc) |
| #error "This file requires ARC support." |
| #endif |
| |
| namespace { |
| const CGFloat kleadingImageViewEdgeOffset = 9; |
| // Offset from the leading edge to the textfield when no image is shown. |
| const CGFloat kTextFieldLeadingOffsetNoImage = 16; |
| // Space between the leading button and the textfield when a button is shown. |
| const CGFloat kTextFieldLeadingOffsetImage = 6; |
| // Space between the clear button and the edge of the omnibox. |
| const CGFloat kTextFieldClearButtonTrailingOffset = 4; |
| |
| } // namespace |
| |
| #pragma mark - OmniboxContainerView |
| |
| @interface OmniboxContainerView () |
| // Constraints the leading textfield side to the leading of |self|. |
| // Active when the |leadingView| is nil or hidden. |
| @property(nonatomic, strong) NSLayoutConstraint* leadingTextfieldConstraint; |
| // When the |leadingImageView| is not hidden, this is a constraint that links |
| // the leading edge of the button to self leading edge. Used for animations. |
| @property(nonatomic, strong) |
| NSLayoutConstraint* leadingImageViewLeadingConstraint; |
| // The leading image view. Used for autocomplete icons. |
| @property(nonatomic, strong) UIImageView* leadingImageView; |
| // Redefined as readwrite. |
| @property(nonatomic, strong) OmniboxTextFieldIOS* textField; |
| |
| @end |
| |
| @implementation OmniboxContainerView |
| @synthesize textField = _textField; |
| @synthesize leadingImageView = _leadingImageView; |
| @synthesize leadingTextfieldConstraint = _leadingTextfieldConstraint; |
| @synthesize incognito = _incognito; |
| @synthesize leadingImageViewLeadingConstraint = |
| _leadingImageViewLeadingConstraint; |
| |
| #pragma mark - Public methods |
| |
| - (instancetype)initWithFrame:(CGRect)frame |
| textColor:(UIColor*)textColor |
| textFieldTint:(UIColor*)textFieldTint |
| iconTint:(UIColor*)iconTint { |
| self = [super initWithFrame:frame]; |
| if (self) { |
| _textField = [[OmniboxTextFieldIOS alloc] initWithFrame:frame |
| textColor:textColor |
| tintColor:textFieldTint]; |
| [self addSubview:_textField]; |
| |
| _leadingTextfieldConstraint = [_textField.leadingAnchor |
| constraintEqualToAnchor:self.leadingAnchor |
| constant:kTextFieldLeadingOffsetNoImage]; |
| |
| [NSLayoutConstraint activateConstraints:@[ |
| [_textField.trailingAnchor |
| constraintEqualToAnchor:self.trailingAnchor |
| constant:-kTextFieldClearButtonTrailingOffset], |
| [_textField.topAnchor constraintEqualToAnchor:self.topAnchor], |
| [_textField.bottomAnchor constraintEqualToAnchor:self.bottomAnchor], |
| _leadingTextfieldConstraint, |
| ]]; |
| |
| _textField.translatesAutoresizingMaskIntoConstraints = NO; |
| [_textField |
| setContentCompressionResistancePriority:UILayoutPriorityDefaultLow |
| forAxis: |
| UILayoutConstraintAxisHorizontal]; |
| |
| [self createLeadingImageView]; |
| _leadingImageView.tintColor = iconTint; |
| } |
| return self; |
| } |
| |
| - (void)setLeadingImageHidden:(BOOL)hidden { |
| if (hidden) { |
| [_leadingImageView removeFromSuperview]; |
| self.leadingTextfieldConstraint.active = YES; |
| } else { |
| [self addSubview:_leadingImageView]; |
| self.leadingTextfieldConstraint.active = NO; |
| self.leadingImageViewLeadingConstraint = [self.leadingAnchor |
| constraintEqualToAnchor:self.leadingImageView.leadingAnchor |
| constant:-kleadingImageViewEdgeOffset]; |
| |
| NSLayoutConstraint* leadingImageViewToTextField = nil; |
| leadingImageViewToTextField = [self.leadingImageView.trailingAnchor |
| constraintEqualToAnchor:self.textField.leadingAnchor |
| constant:-kTextFieldLeadingOffsetImage]; |
| |
| [NSLayoutConstraint activateConstraints:@[ |
| [_leadingImageView.centerYAnchor |
| constraintEqualToAnchor:self.centerYAnchor], |
| self.leadingImageViewLeadingConstraint, |
| leadingImageViewToTextField, |
| ]]; |
| } |
| } |
| |
| - (void)setLeadingImage:(UIImage*)image { |
| [self.leadingImageView setImage:image]; |
| } |
| |
| - (void)setIncognito:(BOOL)incognito { |
| _incognito = incognito; |
| self.textField.incognito = incognito; |
| } |
| |
| - (void)setLeadingImageAlpha:(CGFloat)alpha { |
| self.leadingImageView.alpha = alpha; |
| } |
| |
| #pragma mark - private |
| |
| - (void)createLeadingImageView { |
| _leadingImageView = [[UIImageView alloc] init]; |
| _leadingImageView.translatesAutoresizingMaskIntoConstraints = NO; |
| [_leadingImageView |
| setContentCompressionResistancePriority:UILayoutPriorityRequired |
| forAxis:UILayoutConstraintAxisHorizontal]; |
| [_leadingImageView |
| setContentCompressionResistancePriority:UILayoutPriorityRequired |
| forAxis:UILayoutConstraintAxisVertical]; |
| [_leadingImageView |
| setContentHuggingPriority:UILayoutPriorityDefaultLow |
| forAxis:UILayoutConstraintAxisHorizontal]; |
| [_leadingImageView setContentHuggingPriority:UILayoutPriorityRequired |
| forAxis:UILayoutConstraintAxisVertical]; |
| |
| // Sometimes the image view is not hidden and has no image. Then it doesn't |
| // have an intrinsic size. In this case the omnibox should appear the same as |
| // with hidden image view. Add a placeholder width constraint. |
| CGFloat placeholderSize = kTextFieldLeadingOffsetNoImage - |
| kleadingImageViewEdgeOffset - |
| kTextFieldLeadingOffsetImage; |
| NSLayoutConstraint* placeholderWidthConstraint = |
| [_leadingImageView.widthAnchor constraintEqualToConstant:placeholderSize]; |
| // The priority must be higher than content hugging. |
| placeholderWidthConstraint.priority = UILayoutPriorityDefaultLow + 1; |
| placeholderWidthConstraint.active = YES; |
| } |
| |
| @end |