Commit 50ac3f62 authored by David Jean's avatar David Jean Committed by Commit Bot

[ios] add manual fallback address cell

Will merge the cell_utils with card_cell after crrev/c/1303730 is merged.

Bug: 845472
Change-Id: Iead98637aeaa8b7e3b0252057b8592ef4fff0529
Reviewed-on: https://chromium-review.googlesource.com/c/1317853
Commit-Queue: David Jean <djean@chromium.org>
Reviewed-by: default avatarEric Noyau <noyau@chromium.org>
Cr-Commit-Position: refs/heads/master@{#606423}
parent 19ab1de3
...@@ -46,6 +46,7 @@ source_set("manual_fill_ui") { ...@@ -46,6 +46,7 @@ source_set("manual_fill_ui") {
sources = [ sources = [
"action_cell.h", "action_cell.h",
"action_cell.mm", "action_cell.mm",
"address_list_delegate.h",
"card_list_delegate.h", "card_list_delegate.h",
"credential.h", "credential.h",
"credential.mm", "credential.mm",
...@@ -53,8 +54,12 @@ source_set("manual_fill_ui") { ...@@ -53,8 +54,12 @@ source_set("manual_fill_ui") {
"keyboard_observer_helper.mm", "keyboard_observer_helper.mm",
"manual_fill_accessory_view_controller.h", "manual_fill_accessory_view_controller.h",
"manual_fill_accessory_view_controller.mm", "manual_fill_accessory_view_controller.mm",
"manual_fill_address_cell.h",
"manual_fill_address_cell.mm",
"manual_fill_card_cell.h", "manual_fill_card_cell.h",
"manual_fill_card_cell.mm", "manual_fill_card_cell.mm",
"manual_fill_cell_utils.h",
"manual_fill_cell_utils.mm",
"manual_fill_content_delegate.h", "manual_fill_content_delegate.h",
"manual_fill_password_cell.h", "manual_fill_password_cell.h",
"manual_fill_password_cell.mm", "manual_fill_password_cell.mm",
......
// 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.
#ifndef IOS_CHROME_BROWSER_UI_AUTOFILL_MANUAL_FILL_ADDRESS_LIST_DELEGATE_H_
#define IOS_CHROME_BROWSER_UI_AUTOFILL_MANUAL_FILL_ADDRESS_LIST_DELEGATE_H_
// Delegate for actions in manual fallback's addresses list.
@protocol AddressListDelegate
// Dismisses the presented view controller and continues as pop over on iPads
// or above the keyboard elsewhere.
- (void)dismissPresentedViewController;
// Opens addresses settings.
- (void)openAddressSettings;
@end
#endif // IOS_CHROME_BROWSER_UI_AUTOFILL_MANUAL_FILL_ADDRESS_LIST_DELEGATE_H_
...@@ -13,7 +13,7 @@ class CreditCard; ...@@ -13,7 +13,7 @@ class CreditCard;
@protocol CardListDelegate @protocol CardListDelegate
// Dismisses the presented view controller and continues as pop over on iPads // Dismisses the presented view controller and continues as pop over on iPads
// or above the keyboard else. // or above the keyboard elsewhere.
- (void)dismissPresentedViewController; - (void)dismissPresentedViewController;
// Opens cards settings. // Opens cards settings.
......
// 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.
#ifndef IOS_CHROME_BROWSER_UI_AUTOFILL_MANUAL_FILL_MANUAL_FILL_ADDRESS_CELL_H_
#define IOS_CHROME_BROWSER_UI_AUTOFILL_MANUAL_FILL_MANUAL_FILL_ADDRESS_CELL_H_
#import <UIKit/UIKit.h>
#import "ios/chrome/browser/ui/table_view/cells/table_view_item.h"
namespace autofill {
class AutofillProfile;
} // namespace autofill
// TODO(crbug.com/845472): rename, see
// https://crrev.com/c/1317853/7/ios/chrome/browser/ui/autofill/manual_fill/manual_fill_address_cell.h#17.
@protocol ManualFillContentDelegate;
// Wrapper to show address cells in a ChromeTableViewController.
@interface ManualFillAddressItem : TableViewItem
// Inits an address with a |profile| and the |delegate| for user selection.
- (instancetype)initWithAutofillProfile:
(const autofill::AutofillProfile&)profile
delegate:(id<ManualFillContentDelegate>)delegate
NS_DESIGNATED_INITIALIZER;
- (instancetype)initWithType:(NSInteger)type NS_UNAVAILABLE;
@end
// Cell to display an Address into parts that are interactable
// and sendable the data to the delegate.
@interface ManualFillAddressCell : UITableViewCell
// Updates the cell with address and the |delegate| to be notified.
- (void)setUpWithAutofillProfile:(const autofill::AutofillProfile&)profile
delegate:(id<ManualFillContentDelegate>)delegate;
@end
#endif // IOS_CHROME_BROWSER_UI_AUTOFILL_MANUAL_FILL_MANUAL_FILL_ADDRESS_CELL_H_
// 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/autofill/manual_fill/manual_fill_address_cell.h"
#include "base/strings/sys_string_conversions.h"
#include "base/strings/utf_string_conversions.h"
#include "components/autofill/core/browser/autofill_profile.h"
#include "ios/chrome/browser/application_context.h"
#import "ios/chrome/browser/ui/autofill/manual_fill/address_list_delegate.h"
#import "ios/chrome/browser/ui/autofill/manual_fill/manual_fill_cell_utils.h"
#import "ios/chrome/browser/ui/autofill/manual_fill/manual_fill_content_delegate.h"
#import "ios/chrome/browser/ui/autofill/manual_fill/uicolor_manualfill.h"
#import "ios/chrome/browser/ui/list_model/list_model.h"
#import "ios/chrome/common/ui_util/constraints_ui_util.h"
#include "ios/chrome/grit/ios_strings.h"
#include "ui/base/l10n/l10n_util_mac.h"
#if !defined(__has_feature) || !__has_feature(objc_arc)
#error "This file requires ARC support."
#endif
@interface ManualFillAddressItem ()
// The content delegate for this item.
@property(nonatomic, weak, readonly) id<ManualFillContentDelegate> delegate;
// The address/profile for this item.
@property(nonatomic, readonly) autofill::AutofillProfile profile;
@end
@implementation ManualFillAddressItem
- (instancetype)
initWithAutofillProfile:(const autofill::AutofillProfile&)profile
delegate:(id<ManualFillContentDelegate>)delegate {
self = [super initWithType:kItemTypeEnumZero];
if (self) {
_delegate = delegate;
_profile = profile;
self.cellClass = [ManualFillAddressCell class];
}
return self;
}
- (void)configureCell:(ManualFillAddressCell*)cell
withStyler:(ChromeTableViewStyler*)styler {
[super configureCell:cell withStyler:styler];
[cell setUpWithAutofillProfile:self.profile delegate:self.delegate];
}
@end
namespace {
// Left and right margins of the cell content.
static const CGFloat sideMargins = 16;
// Margin left and right of multiple buttons on same line.
static const CGFloat InnerMarginWidth = 16.0;
} // namespace
@interface ManualFillAddressCell ()
// The separator gray line.
@property(nonatomic, strong) UIView* grayLine;
// The label with the line1 -- line2.
@property(nonatomic, strong) UILabel* addressLabel;
// The vertical constraints for all the lines.
@property(nonatomic, strong) NSArray<NSLayoutConstraint*>* verticalConstraints;
// The constraints for the first/middle/last name line.
@property(nonatomic, strong) NSArray<NSLayoutConstraint*>* nameLineConstraints;
// The constraints for the zip/city line.
@property(nonatomic, strong)
NSArray<NSLayoutConstraint*>* zipCityLineConstraints;
// The constraints for the state/country line.
@property(nonatomic, strong)
NSArray<NSLayoutConstraint*>* stateCountryLineConstraints;
// A button showing the address associated first name.
@property(nonatomic, strong) UIButton* firstNameButton;
// The separator label between first and middle name/initial.
@property(nonatomic, strong) UILabel* middleNameSeparatorLabel;
// A button showing the address associated middle name or initial.
@property(nonatomic, strong) UIButton* middleNameButton;
// The separator label between middle name/initial and last name.
@property(nonatomic, strong) UILabel* lastNameSeparatorLabel;
// A button showing the address associated last name.
@property(nonatomic, strong) UIButton* lastNameButton;
// A button showing the address line 1.
@property(nonatomic, strong) UIButton* line1Button;
// An optional button showing the address line 2.
@property(nonatomic, strong) UIButton* line2Button;
// A button showing zip code.
@property(nonatomic, strong) UIButton* zipButton;
// The separator label between zip and city.
@property(nonatomic, strong) UILabel* citySeparatorLabel;
// A button showing city.
@property(nonatomic, strong) UIButton* cityButton;
// A button showing state/province.
@property(nonatomic, strong) UIButton* stateButton;
// The separator label between state and country.
@property(nonatomic, strong) UILabel* countrySeparatorLabel;
// A button showing country.
@property(nonatomic, strong) UIButton* countryButton;
// The content delegate for this item.
@property(nonatomic, weak) id<ManualFillContentDelegate> delegate;
// The credit address/profile data for this cell.
// TODO(crbug.com/845472): move to cocoa model.
@property(nonatomic, assign) autofill::AutofillProfile profile;
@end
@implementation ManualFillAddressCell
#pragma mark - Public
- (void)prepareForReuse {
[super prepareForReuse];
[NSLayoutConstraint deactivateConstraints:self.verticalConstraints];
self.verticalConstraints = @[];
[NSLayoutConstraint deactivateConstraints:self.nameLineConstraints];
self.nameLineConstraints = @[];
[NSLayoutConstraint deactivateConstraints:self.zipCityLineConstraints];
self.zipCityLineConstraints = @[];
[NSLayoutConstraint deactivateConstraints:self.stateCountryLineConstraints];
self.stateCountryLineConstraints = @[];
self.addressLabel.text = @"";
[self.firstNameButton setTitle:@"" forState:UIControlStateNormal];
[self.middleNameButton setTitle:@"" forState:UIControlStateNormal];
[self.lastNameButton setTitle:@"" forState:UIControlStateNormal];
[self.line1Button setTitle:@"" forState:UIControlStateNormal];
[self.line2Button setTitle:@"" forState:UIControlStateNormal];
[self.zipButton setTitle:@"" forState:UIControlStateNormal];
[self.cityButton setTitle:@"" forState:UIControlStateNormal];
[self.stateButton setTitle:@"" forState:UIControlStateNormal];
[self.countryButton setTitle:@"" forState:UIControlStateNormal];
[self.line2Button setTitle:@"" forState:UIControlStateNormal];
self.delegate = nil;
// TODO(crbug.com/845472): clear profile.
}
- (void)setUpWithAutofillProfile:(const autofill::AutofillProfile&)profile
delegate:(id<ManualFillContentDelegate>)delegate {
if (self.contentView.subviews.count == 0) {
[self createViewHierarchy];
}
self.delegate = delegate;
self.profile = profile;
NSMutableArray<UIView*>* verticalLeadViews = [[NSMutableArray alloc] init];
NSString* line1 = [self fieldValueOfType:autofill::ADDRESS_HOME_LINE1];
NSString* line2 = [self fieldValueOfType:autofill::ADDRESS_HOME_LINE2];
// Top label, summary of line 1 and 2.
NSMutableAttributedString* attributedString =
[[NSMutableAttributedString alloc]
initWithString:line1 ? line1 : @""
attributes:@{
NSForegroundColorAttributeName : UIColor.blackColor,
NSFontAttributeName :
[UIFont preferredFontForTextStyle:UIFontTextStyleHeadline]
}];
if (line2.length) {
NSString* line2String = [NSString stringWithFormat:@" –– %@", line2];
NSDictionary* attributes = @{
NSForegroundColorAttributeName : UIColor.lightGrayColor,
NSFontAttributeName :
[UIFont preferredFontForTextStyle:UIFontTextStyleBody]
};
NSAttributedString* line2StringAttributedString =
[[NSAttributedString alloc] initWithString:line2String
attributes:attributes];
[attributedString appendAttributedString:line2StringAttributedString];
}
self.addressLabel.attributedText = attributedString;
[verticalLeadViews addObject:self.addressLabel];
// Name line, first middle and last.
NSMutableArray<UIView*>* nameLineViews = [[NSMutableArray alloc] init];
NSString* firstName = [self fieldValueOfType:autofill::NAME_FIRST];
NSString* lastName = [self fieldValueOfType:autofill::NAME_LAST];
NSString* middleName = [self fieldValueOfType:autofill::NAME_MIDDLE];
if (!middleName || middleName.length == 0) {
middleName = [self fieldValueOfType:autofill::NAME_MIDDLE_INITIAL];
}
bool showFirstName = firstName.length;
bool showMiddleName = middleName.length;
bool showLastName = lastName.length;
if (showFirstName) {
[self.firstNameButton setTitle:firstName forState:UIControlStateNormal];
[nameLineViews addObject:self.firstNameButton];
self.firstNameButton.hidden = NO;
} else {
self.firstNameButton.hidden = YES;
}
if (showFirstName && showMiddleName) {
[nameLineViews addObject:self.middleNameSeparatorLabel];
self.middleNameSeparatorLabel.hidden = NO;
} else {
self.middleNameSeparatorLabel.hidden = YES;
}
if (showMiddleName) {
[self.middleNameButton setTitle:middleName forState:UIControlStateNormal];
[nameLineViews addObject:self.middleNameButton];
self.middleNameButton.hidden = NO;
} else {
self.middleNameButton.hidden = YES;
}
if ((showFirstName || showMiddleName) && showLastName) {
[nameLineViews addObject:self.lastNameSeparatorLabel];
self.lastNameSeparatorLabel.hidden = NO;
} else {
self.lastNameSeparatorLabel.hidden = YES;
}
if (showLastName) {
[self.lastNameButton setTitle:lastName forState:UIControlStateNormal];
[nameLineViews addObject:self.lastNameButton];
self.lastNameButton.hidden = NO;
} else {
self.lastNameButton.hidden = YES;
}
self.nameLineConstraints = HorizontalConstraintsForViewsOnGuideWithShift(
nameLineViews, self.grayLine, -InnerMarginWidth);
if (nameLineViews.count) {
[verticalLeadViews addObject:nameLineViews.firstObject];
}
// Address line 1.
if (line1.length) {
[self.line1Button setTitle:line1 forState:UIControlStateNormal];
[verticalLeadViews addObject:self.line1Button];
self.line1Button.hidden = NO;
} else {
self.line1Button.hidden = YES;
}
// Address line 2.
if (line2.length) {
[self.line2Button setTitle:line2 forState:UIControlStateNormal];
[verticalLeadViews addObject:self.line2Button];
self.line2Button.hidden = NO;
} else {
self.line2Button.hidden = YES;
}
// Zip and city line.
NSMutableArray<UIView*>* zipCityLineViews = [[NSMutableArray alloc] init];
NSString* zip = [self fieldValueOfType:autofill::ADDRESS_HOME_ZIP];
NSString* city = [self fieldValueOfType:autofill::ADDRESS_HOME_CITY];
if (zip.length) {
[self.zipButton setTitle:zip forState:UIControlStateNormal];
[zipCityLineViews addObject:self.zipButton];
self.zipButton.hidden = NO;
} else {
self.zipButton.hidden = YES;
}
if (zip.length && city.length) {
[zipCityLineViews addObject:self.citySeparatorLabel];
self.citySeparatorLabel.hidden = NO;
} else {
self.citySeparatorLabel.hidden = YES;
}
if (city.length) {
[self.cityButton setTitle:city forState:UIControlStateNormal];
[zipCityLineViews addObject:self.cityButton];
self.cityButton.hidden = NO;
} else {
self.cityButton.hidden = YES;
}
self.zipCityLineConstraints = HorizontalConstraintsForViewsOnGuideWithShift(
zipCityLineViews, self.grayLine, -InnerMarginWidth);
if (zipCityLineViews.count) {
[verticalLeadViews addObject:zipCityLineViews.firstObject];
}
// State and country line.
NSMutableArray<UIView*>* stateCountryLineViews =
[[NSMutableArray alloc] init];
NSString* state = [self fieldValueOfType:autofill::ADDRESS_HOME_STATE];
NSString* country = [self fieldValueOfType:autofill::ADDRESS_HOME_COUNTRY];
if (state.length) {
[self.stateButton setTitle:state forState:UIControlStateNormal];
[stateCountryLineViews addObject:self.stateButton];
self.stateButton.hidden = NO;
} else {
self.stateButton.hidden = YES;
}
if (state.length && country.length) {
[stateCountryLineViews addObject:self.countrySeparatorLabel];
self.countrySeparatorLabel.hidden = NO;
} else {
self.countrySeparatorLabel.hidden = YES;
}
if (country.length) {
[self.countryButton setTitle:country forState:UIControlStateNormal];
[stateCountryLineViews addObject:self.countryButton];
self.countryButton.hidden = NO;
} else {
self.countryButton.hidden = YES;
}
self.stateCountryLineConstraints =
HorizontalConstraintsForViewsOnGuideWithShift(
stateCountryLineViews, self.grayLine, -InnerMarginWidth);
if (stateCountryLineViews.count) {
[verticalLeadViews addObject:stateCountryLineViews.firstObject];
}
self.verticalConstraints = VerticalConstraintsSpacingForViewsInContainer(
verticalLeadViews, self.contentView);
}
#pragma mark - Private
// Creates and sets up the view hierarchy.
- (void)createViewHierarchy {
self.selectionStyle = UITableViewCellSelectionStyleNone;
self.grayLine = [[UIView alloc] init];
self.grayLine.backgroundColor = [UIColor colorWithWhite:0.88 alpha:1];
self.grayLine.translatesAutoresizingMaskIntoConstraints = NO;
[self.contentView addSubview:self.grayLine];
self.addressLabel = CreateLabel();
[self.contentView addSubview:self.addressLabel];
HorizontalConstraintsForViewsOnGuideWithShift(@[ self.addressLabel ],
self.grayLine, 0);
self.firstNameButton = CreateButtonWithSelectorAndTarget(
@selector(userDidTapAddressInfo:), self);
[self.contentView addSubview:self.firstNameButton];
HorizontalConstraintsMarginForButtonWithWidth(self.firstNameButton,
InnerMarginWidth);
self.middleNameSeparatorLabel = CreateLabel();
self.middleNameSeparatorLabel.text = @"·";
[self.contentView addSubview:self.middleNameSeparatorLabel];
self.middleNameButton = CreateButtonWithSelectorAndTarget(
@selector(userDidTapAddressInfo:), self);
[self.contentView addSubview:self.middleNameButton];
HorizontalConstraintsMarginForButtonWithWidth(self.middleNameButton,
InnerMarginWidth);
self.lastNameSeparatorLabel = CreateLabel();
self.lastNameSeparatorLabel.text = @"·";
[self.contentView addSubview:self.lastNameSeparatorLabel];
self.lastNameButton = CreateButtonWithSelectorAndTarget(
@selector(userDidTapAddressInfo:), self);
[self.contentView addSubview:self.lastNameButton];
HorizontalConstraintsMarginForButtonWithWidth(self.lastNameButton,
InnerMarginWidth);
SyncBaselinesForViewsOnView(
@[
self.middleNameSeparatorLabel, self.middleNameButton,
self.lastNameSeparatorLabel, self.lastNameButton
],
self.firstNameButton);
self.line1Button = CreateButtonWithSelectorAndTarget(
@selector(userDidTapAddressInfo:), self);
[self.contentView addSubview:self.line1Button];
HorizontalConstraintsForViewsOnGuideWithShift(@[ self.line1Button ],
self.grayLine, 0);
self.line2Button = CreateButtonWithSelectorAndTarget(
@selector(userDidTapAddressInfo:), self);
[self.contentView addSubview:self.line2Button];
HorizontalConstraintsForViewsOnGuideWithShift(@[ self.line2Button ],
self.grayLine, 0);
self.zipButton = CreateButtonWithSelectorAndTarget(
@selector(userDidTapAddressInfo:), self);
[self.contentView addSubview:self.zipButton];
HorizontalConstraintsMarginForButtonWithWidth(self.zipButton,
InnerMarginWidth);
self.citySeparatorLabel = CreateLabel();
self.citySeparatorLabel.text = @"·";
[self.contentView addSubview:self.citySeparatorLabel];
self.cityButton = CreateButtonWithSelectorAndTarget(
@selector(userDidTapAddressInfo:), self);
[self.contentView addSubview:self.cityButton];
HorizontalConstraintsMarginForButtonWithWidth(self.cityButton,
InnerMarginWidth);
SyncBaselinesForViewsOnView(@[ self.citySeparatorLabel, self.cityButton ],
self.zipButton);
self.stateButton = CreateButtonWithSelectorAndTarget(
@selector(userDidTapAddressInfo:), self);
[self.contentView addSubview:self.stateButton];
HorizontalConstraintsMarginForButtonWithWidth(self.stateButton,
InnerMarginWidth);
self.countrySeparatorLabel = CreateLabel();
self.countrySeparatorLabel.text = @"·";
[self.contentView addSubview:self.countrySeparatorLabel];
self.countryButton = CreateButtonWithSelectorAndTarget(
@selector(userDidTapAddressInfo:), self);
[self.contentView addSubview:self.countryButton];
HorizontalConstraintsMarginForButtonWithWidth(self.countryButton,
InnerMarginWidth);
SyncBaselinesForViewsOnView(
@[ self.countrySeparatorLabel, self.countryButton ], self.stateButton);
self.nameLineConstraints = @[];
self.zipCityLineConstraints = @[];
self.stateCountryLineConstraints = @[];
self.verticalConstraints = @[];
id<LayoutGuideProvider> safeArea =
SafeAreaLayoutGuideForView(self.contentView);
[NSLayoutConstraint activateConstraints:@[
// Common vertical constraints.
[self.grayLine.bottomAnchor
constraintEqualToAnchor:self.contentView.bottomAnchor],
[self.grayLine.heightAnchor constraintEqualToConstant:1],
// Horizontal constraints.
[self.grayLine.leadingAnchor constraintEqualToAnchor:safeArea.leadingAnchor
constant:sideMargins],
[safeArea.trailingAnchor
constraintEqualToAnchor:self.grayLine.trailingAnchor
constant:sideMargins],
]];
}
// Takes in an autofill profile and an autofill field type and returns the
// corresponding field value.
- (NSString*)fieldValueOfType:(autofill::ServerFieldType)fieldType {
return base::SysUTF16ToNSString(
self.profile.GetInfo(autofill::AutofillType(fieldType),
GetApplicationContext()->GetApplicationLocale()));
}
- (void)userDidTapAddressInfo:(UIButton*)sender {
[self.delegate userDidPickContent:sender.titleLabel.text isSecure:NO];
}
@end
// 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.
#ifndef IOS_CHROME_BROWSER_UI_AUTOFILL_MANUAL_FILL_MANUAL_FILL_CELL_UTILS_H_
#define IOS_CHROME_BROWSER_UI_AUTOFILL_MANUAL_FILL_MANUAL_FILL_CELL_UTILS_H_
#import <UIKit/UIKit.h>
// Creates a blank button in fallback style, for the given |action| and
// |target|.
UIButton* CreateButtonWithSelectorAndTarget(SEL action, id target);
// Creates horizontal constraints for given |button| based on given |width| on
// both sides.
void HorizontalConstraintsMarginForButtonWithWidth(UIButton* button,
CGFloat width);
// Sets vertical constraints on firstBaselineAnchor for the button or label rows
// in |views| inside |container| starting at its topAnchor. Returns the applied
// constrainst to allow caller to deactivate them later.
NSArray<NSLayoutConstraint*>* VerticalConstraintsSpacingForViewsInContainer(
NSArray<UIView*>* views,
UIView* container);
// Sets constraints for the given |views|, so as to lay them out horizontally,
// parallel to the given |guide| view, and applying the given constant |shift|
// to the whole row. Returns the applied constraints to allow caller to
// deactivate them later.
NSArray<NSLayoutConstraint*>* HorizontalConstraintsForViewsOnGuideWithShift(
NSArray<UIView*>* views,
UIView* guide,
CGFloat shift);
// Sets all baseline anchors for the gievn |views| to match the one on |onView|.
// Returns the applied constrainst to allow caller to deactivate them later.
NSArray<NSLayoutConstraint*>* SyncBaselinesForViewsOnView(
NSArray<UIView*>* views,
UIView* onView);
// Creates a blank label with autoresize mask off and adjustable font size.
UILabel* CreateLabel();
#endif // IOS_CHROME_BROWSER_UI_AUTOFILL_MANUAL_FILL_MANUAL_FILL_CELL_UTILS_H_
// 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/autofill/manual_fill/manual_fill_cell_utils.h"
#include "base/strings/sys_string_conversions.h"
#include "base/strings/utf_string_conversions.h"
#import "ios/chrome/browser/ui/autofill/manual_fill/uicolor_manualfill.h"
#import "ios/chrome/common/ui_util/constraints_ui_util.h"
#include "ios/chrome/grit/ios_strings.h"
#include "ui/base/l10n/l10n_util_mac.h"
#if !defined(__has_feature) || !__has_feature(objc_arc)
#error "This file requires ARC support."
#endif
namespace {
// The multiplier for the base system spacing at the top margin.
static const CGFloat TopSystemSpacingMultiplier = 1.58;
// The multiplier for the base system spacing between elements (vertical).
static const CGFloat MiddleSystemSpacingMultiplier = 1.83;
// The multiplier for the base system spacing at the bottom margin.
static const CGFloat BottomSystemSpacingMultiplier = 2.26;
} // namespace
UIButton* CreateButtonWithSelectorAndTarget(SEL action, id target) {
UIButton* button = [UIButton buttonWithType:UIButtonTypeSystem];
[button setTitleColor:UIColor.cr_manualFillTintColor
forState:UIControlStateNormal];
button.translatesAutoresizingMaskIntoConstraints = NO;
button.titleLabel.font =
[UIFont preferredFontForTextStyle:UIFontTextStyleBody];
button.titleLabel.adjustsFontForContentSizeCategory = YES;
[button addTarget:target
action:action
forControlEvents:UIControlEventTouchUpInside];
return button;
}
void HorizontalConstraintsMarginForButtonWithWidth(UIButton* button,
CGFloat width) {
[NSLayoutConstraint activateConstraints:@[
[button.leadingAnchor
constraintEqualToAnchor:button.titleLabel.leadingAnchor
constant:-width],
[button.trailingAnchor
constraintEqualToAnchor:button.titleLabel.trailingAnchor
constant:width],
]];
}
NSArray<NSLayoutConstraint*>* VerticalConstraintsSpacingForViewsInContainer(
NSArray<UIView*>* views,
UIView* container) {
NSMutableArray* verticalConstraints = [[NSMutableArray alloc] init];
// Multipliers of these constraints are calculated based on a 24 base
// system spacing.
NSLayoutYAxisAnchor* previousAnchor = container.topAnchor;
CGFloat multiplier = TopSystemSpacingMultiplier;
for (UIView* view in views) {
[verticalConstraints
addObject:[view.firstBaselineAnchor
constraintEqualToSystemSpacingBelowAnchor:previousAnchor
multiplier:multiplier]];
multiplier = MiddleSystemSpacingMultiplier;
previousAnchor = view.lastBaselineAnchor;
}
multiplier = BottomSystemSpacingMultiplier;
[verticalConstraints
addObject:[container.bottomAnchor
constraintEqualToSystemSpacingBelowAnchor:previousAnchor
multiplier:multiplier]];
[NSLayoutConstraint activateConstraints:verticalConstraints];
return verticalConstraints;
}
NSArray<NSLayoutConstraint*>* HorizontalConstraintsForViewsOnGuideWithShift(
NSArray<UIView*>* views,
UIView* guide,
CGFloat shift) {
NSMutableArray* horizontalConstraints = [[NSMutableArray alloc] init];
NSLayoutXAxisAnchor* previousAnchor = guide.leadingAnchor;
for (UIView* view in views) {
[horizontalConstraints
addObject:[view.leadingAnchor constraintEqualToAnchor:previousAnchor
constant:shift]];
previousAnchor = view.trailingAnchor;
shift = 0;
}
if (views.count > 0) {
[horizontalConstraints
addObject:[views.lastObject.trailingAnchor
constraintLessThanOrEqualToAnchor:guide.trailingAnchor
constant:shift]];
}
[NSLayoutConstraint activateConstraints:horizontalConstraints];
return horizontalConstraints;
}
NSArray<NSLayoutConstraint*>* SyncBaselinesForViewsOnView(
NSArray<UIView*>* views,
UIView* onView) {
NSMutableArray* baselinesConstraints = [[NSMutableArray alloc] init];
for (UIView* view in views) {
[baselinesConstraints
addObject:[view.firstBaselineAnchor
constraintEqualToAnchor:onView.firstBaselineAnchor]];
}
[NSLayoutConstraint activateConstraints:baselinesConstraints];
return baselinesConstraints;
}
UILabel* CreateLabel() {
UILabel* label = [[UILabel alloc] init];
label.translatesAutoresizingMaskIntoConstraints = NO;
label.adjustsFontForContentSizeCategory = YES;
return label;
}
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
@protocol PasswordListDelegate @protocol PasswordListDelegate
// Dismisses the presented view controller and continues as pop over on iPads // Dismisses the presented view controller and continues as pop over on iPads
// or above the keyboard else. // or above the keyboard elsewhere.
- (void)dismissPresentedViewController; - (void)dismissPresentedViewController;
// Requests to open the list of all passwords. // Requests to open the list of all passwords.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment