[go: up one dir, main page]

blob: 28bde42958a0dc5a556e2ef125bfbeda8e1ef6b6 [file] [log] [blame]
// Copyright 2018 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/location_bar/location_bar_steady_view.h"
#include "components/strings/grit/components_strings.h"
#import "ios/chrome/browser/ui/elements/extended_touch_target_button.h"
#import "ios/chrome/browser/ui/infobars/infobar_feature.h"
#import "ios/chrome/browser/ui/omnibox/omnibox_constants.h"
#import "ios/chrome/browser/ui/toolbar/public/toolbar_constants.h"
#import "ios/chrome/browser/ui/util/dynamic_type_util.h"
#import "ios/chrome/browser/ui/util/uikit_ui_util.h"
#import "ios/chrome/common/ui_util/constraints_ui_util.h"
#include "ios/chrome/grit/ios_strings.h"
#include "ui/base/l10n/l10n_util.h"
#if !defined(__has_feature) || !__has_feature(objc_arc)
#error "This file requires ARC support."
#endif
namespace {
// Length of the trailing button side.
const CGFloat kButtonSize = 24;
// Space between the location icon and the location label.
const CGFloat kLocationImageToLabelSpacing = -4.0;
// Minimal horizontal padding between the leading edge of the location bar and
// the content of the location bar.
const CGFloat kLocationBarLeadingPadding = 5.0;
// Trailing space between the trailing button and the trailing edge of the
// location bar.
const CGFloat kButtonTrailingSpacing = 10;
} // namespace
@interface LocationBarSteadyView ()
// The image view displaying the current location icon (i.e. http[s] status).
@property(nonatomic, strong) UIImageView* locationIconImageView;
// The view containing the location label, and (sometimes) the location image
// view.
@property(nonatomic, strong) UIView* locationContainerView;
// Constraints to hide the location image view.
@property(nonatomic, strong)
NSArray<NSLayoutConstraint*>* hideLocationImageConstraints;
// Constraints to show the location image view.
@property(nonatomic, strong)
NSArray<NSLayoutConstraint*>* showLocationImageConstraints;
// Elements to surface in accessibility.
@property(nonatomic, strong) NSMutableArray* accessibleElements;
@end
#pragma mark - LocationBarSteadyViewColorScheme
@implementation LocationBarSteadyViewColorScheme
@synthesize fontColor = _fontColor;
@synthesize placeholderColor = _placeholderColor;
@synthesize trailingButtonColor = _trailingButtonColor;
+ (instancetype)standardScheme {
LocationBarSteadyViewColorScheme* scheme =
[[LocationBarSteadyViewColorScheme alloc] init];
scheme.fontColor = [UIColor colorWithWhite:0 alpha:0.7];
scheme.placeholderColor = [UIColor colorWithWhite:0
alpha:kOmniboxPlaceholderAlpha];
scheme.trailingButtonColor = [UIColor colorWithWhite:0 alpha:0.45];
return scheme;
}
+ (instancetype)incognitoScheme {
LocationBarSteadyViewColorScheme* scheme =
[[LocationBarSteadyViewColorScheme alloc] init];
scheme.fontColor = [UIColor whiteColor];
scheme.placeholderColor = [UIColor colorWithWhite:1 alpha:0.5];
scheme.trailingButtonColor = [UIColor whiteColor];
return scheme;
}
@end
#pragma mark - LocationBarSteadyButton
// Buttons with a darker background in highlighted state.
@interface LocationBarSteadyButton : UIButton
@end
@implementation LocationBarSteadyButton
- (void)layoutSubviews {
[super layoutSubviews];
self.layer.cornerRadius = self.bounds.size.height / 2.0;
}
- (void)setHighlighted:(BOOL)highlighted {
[super setHighlighted:highlighted];
CGFloat duration = highlighted ? 0.1 : 0.2;
[UIView animateWithDuration:duration
delay:0
options:UIViewAnimationOptionBeginFromCurrentState
animations:^{
CGFloat alpha = 0;
if (highlighted)
alpha += 0.07;
self.backgroundColor =
[UIColor colorWithWhite:0 alpha:alpha];
}
completion:nil];
}
@end
#pragma mark - LocationBarSteadyView
@implementation LocationBarSteadyView
@synthesize locationButton = _locationButton;
@synthesize locationLabel = _locationLabel;
@synthesize locationIconImageView = _locationIconImageView;
@synthesize trailingButton = _trailingButton;
@synthesize hideLocationImageConstraints = _hideLocationImageConstraints;
@synthesize showLocationImageConstraints = _showLocationImageConstraints;
@synthesize locationContainerView = _locationContainerView;
@synthesize securityLevelAccessibilityString =
_securityLevelAccessibilityString;
@synthesize accessibleElements = _accessibleElements;
- (instancetype)init {
self = [super initWithFrame:CGRectZero];
if (self) {
_locationLabel = [[UILabel alloc] init];
_locationIconImageView = [[UIImageView alloc] init];
_locationIconImageView.translatesAutoresizingMaskIntoConstraints = NO;
[_locationIconImageView
setContentCompressionResistancePriority:UILayoutPriorityRequired
forAxis:
UILayoutConstraintAxisHorizontal];
SetA11yLabelAndUiAutomationName(
_locationIconImageView,
IDS_IOS_PAGE_INFO_SECURITY_BUTTON_ACCESSIBILITY_LABEL,
@"Page Security Info");
_locationIconImageView.isAccessibilityElement = YES;
// Setup trailing button.
_trailingButton =
[ExtendedTouchTargetButton buttonWithType:UIButtonTypeSystem];
_trailingButton.translatesAutoresizingMaskIntoConstraints = NO;
// Setup label.
_locationLabel.lineBreakMode = NSLineBreakByTruncatingHead;
_locationLabel.translatesAutoresizingMaskIntoConstraints = NO;
[_locationLabel
setContentCompressionResistancePriority:UILayoutPriorityDefaultLow
forAxis:UILayoutConstraintAxisVertical];
_locationLabel.font = [self locationLabelFont];
// Container for location label and icon.
_locationContainerView = [[UIView alloc] init];
_locationContainerView.translatesAutoresizingMaskIntoConstraints = NO;
_locationContainerView.userInteractionEnabled = NO;
[_locationContainerView addSubview:_locationIconImageView];
[_locationContainerView addSubview:_locationLabel];
_showLocationImageConstraints = @[
[_locationContainerView.leadingAnchor
constraintEqualToAnchor:_locationIconImageView.leadingAnchor],
[_locationIconImageView.trailingAnchor
constraintEqualToAnchor:_locationLabel.leadingAnchor
constant:kLocationImageToLabelSpacing],
[_locationLabel.trailingAnchor
constraintEqualToAnchor:_locationContainerView.trailingAnchor],
[_locationIconImageView.centerYAnchor
constraintEqualToAnchor:_locationContainerView.centerYAnchor],
];
_hideLocationImageConstraints = @[
[_locationContainerView.leadingAnchor
constraintEqualToAnchor:_locationLabel.leadingAnchor],
[_locationLabel.trailingAnchor
constraintEqualToAnchor:_locationContainerView.trailingAnchor],
];
[NSLayoutConstraint activateConstraints:_showLocationImageConstraints];
_locationButton = [[LocationBarSteadyButton alloc] init];
_locationButton.translatesAutoresizingMaskIntoConstraints = NO;
[_locationButton addSubview:_trailingButton];
[_locationButton addSubview:_locationContainerView];
[self addSubview:_locationButton];
ApplyVisualConstraints(
@[ @"V:|[label]|", @"V:|[container]|" ],
@{@"label" : _locationLabel, @"container" : _locationContainerView});
AddSameConstraints(self, _locationButton);
// Make the label gravitate towards the center of the view.
NSLayoutConstraint* centerX = [_locationContainerView.centerXAnchor
constraintEqualToAnchor:self.centerXAnchor];
centerX.priority = UILayoutPriorityDefaultHigh;
// Setup and activate constraints.
[NSLayoutConstraint activateConstraints:@[
[_locationContainerView.leadingAnchor
constraintGreaterThanOrEqualToAnchor:self.leadingAnchor
constant:kLocationBarLeadingPadding],
[_trailingButton.centerYAnchor
constraintEqualToAnchor:self.centerYAnchor],
[_locationContainerView.centerYAnchor
constraintEqualToAnchor:self.centerYAnchor],
[_trailingButton.leadingAnchor
constraintGreaterThanOrEqualToAnchor:_locationContainerView
.trailingAnchor],
[_trailingButton.widthAnchor constraintEqualToConstant:kButtonSize],
[_trailingButton.heightAnchor constraintEqualToConstant:kButtonSize],
[self.trailingButton.trailingAnchor
constraintEqualToAnchor:self.trailingAnchor
constant:-kButtonTrailingSpacing],
centerX,
]];
if (IsInfobarUIRebootEnabled()) {
// Setup leading button.
_leadingButton = [InfobarBadgeButton buttonWithType:UIButtonTypeSystem];
_leadingButton.translatesAutoresizingMaskIntoConstraints = NO;
[_locationButton addSubview:_leadingButton];
// Setup and activate the leading button constraints.
[NSLayoutConstraint activateConstraints:@[
[_leadingButton.widthAnchor
constraintEqualToAnchor:_leadingButton.heightAnchor],
[_leadingButton.topAnchor constraintEqualToAnchor:self.topAnchor],
[_leadingButton.bottomAnchor constraintEqualToAnchor:self.bottomAnchor],
[_leadingButton.leadingAnchor
constraintEqualToAnchor:self.leadingAnchor],
[_leadingButton.centerYAnchor
constraintEqualToAnchor:self.centerYAnchor],
]];
}
}
// Setup accessibility.
_trailingButton.isAccessibilityElement = YES;
if (IsInfobarUIRebootEnabled()) {
_leadingButton.isAccessibilityElement = YES;
_leadingButton.accessibilityLabel =
l10n_util::GetNSString(IDS_IOS_INFOBAR_BADGES_PASSWORD_HINT);
}
_locationButton.isAccessibilityElement = YES;
_locationButton.accessibilityLabel =
l10n_util::GetNSString(IDS_ACCNAME_LOCATION);
_accessibleElements = [[NSMutableArray alloc] init];
if (IsInfobarUIRebootEnabled()) {
[_accessibleElements addObject:_leadingButton];
}
[_accessibleElements addObject:_locationButton];
[_accessibleElements addObject:_trailingButton];
// These two elements must remain accessible for egtests, but will not be
// included in accessibility navigation as they are not added to the
// accessibleElements array.
_locationIconImageView.isAccessibilityElement = YES;
_locationLabel.isAccessibilityElement = YES;
[self updateAccessibility];
return self;
}
- (void)setColorScheme:(LocationBarSteadyViewColorScheme*)colorScheme {
self.trailingButton.tintColor = colorScheme.trailingButtonColor;
self.locationLabel.textColor = colorScheme.fontColor;
self.locationIconImageView.tintColor = colorScheme.fontColor;
}
- (void)setLocationImage:(UIImage*)locationImage {
BOOL hadImage = self.locationIconImageView.image != nil;
BOOL hasImage = locationImage != nil;
self.locationIconImageView.image = locationImage;
if (hadImage == hasImage) {
return;
}
if (hasImage) {
[self.locationContainerView addSubview:self.locationIconImageView];
[NSLayoutConstraint
deactivateConstraints:self.hideLocationImageConstraints];
[NSLayoutConstraint activateConstraints:self.showLocationImageConstraints];
} else {
[NSLayoutConstraint
deactivateConstraints:self.showLocationImageConstraints];
[NSLayoutConstraint activateConstraints:self.hideLocationImageConstraints];
[self.locationIconImageView removeFromSuperview];
}
}
- (void)setLocationLabelText:(NSString*)string {
if ([self.locationLabel.text isEqualToString:string]) {
return;
}
self.locationLabel.text = string;
[self updateAccessibility];
}
- (void)setSecurityLevelAccessibilityString:(NSString*)string {
if ([_securityLevelAccessibilityString isEqualToString:string]) {
return;
}
_securityLevelAccessibilityString = [string copy];
[self updateAccessibility];
}
#pragma mark - UIResponder
// This is needed for UIMenu
- (BOOL)canBecomeFirstResponder {
return true;
}
#pragma mark - UIView
- (void)traitCollectionDidChange:(UITraitCollection*)previousTraitCollection {
[super traitCollectionDidChange:previousTraitCollection];
if (previousTraitCollection.preferredContentSizeCategory !=
self.traitCollection.preferredContentSizeCategory) {
self.locationLabel.font = [self locationLabelFont];
}
}
#pragma mark - UIAccessibilityContainer
- (NSArray*)accessibilityElements {
return self.accessibleElements;
}
- (NSInteger)accessibilityElementCount {
return self.accessibleElements.count;
}
- (id)accessibilityElementAtIndex:(NSInteger)index {
return self.accessibleElements[index];
}
- (NSInteger)indexOfAccessibilityElement:(id)element {
return [self.accessibleElements indexOfObject:element];
}
#pragma mark - private
- (void)updateAccessibility {
if (self.securityLevelAccessibilityString.length > 0) {
self.locationButton.accessibilityValue =
[NSString stringWithFormat:@"%@ %@", self.locationLabel.text,
self.securityLevelAccessibilityString];
} else {
self.locationButton.accessibilityValue =
[NSString stringWithFormat:@"%@", self.locationLabel.text];
}
}
// Returns the font size for the location label.
- (UIFont*)locationLabelFont {
return PreferredFontForTextStyleWithMaxCategory(
UIFontTextStyleBody, self.traitCollection.preferredContentSizeCategory,
UIContentSizeCategoryAccessibilityExtraLarge);
}
@end