// Copyright 2018 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef IOS_CHROME_BROWSER_AUTOFILL_UI_BUNDLED_MANUAL_FILL_MANUAL_FILL_CELL_UTILS_H_
#define IOS_CHROME_BROWSER_AUTOFILL_UI_BUNDLED_MANUAL_FILL_MANUAL_FILL_CELL_UTILS_H_
#import <UIKit/UIKit.h>
#import <vector>
#import "ios/chrome/browser/autofill/ui_bundled/manual_fill/manual_fill_site_info.h"
@class TableViewCell;
// Margins of the cell content.
extern const CGFloat kCellMargin;
// Left and right margins for the chips.
extern const CGFloat kChipsHorizontalMargin;
// Options for `AppendHorizontalConstraintsForViews`.
typedef NS_OPTIONS(NSUInteger, AppendConstraints) {
AppendConstraintsNone = 0,
// Add an equal constraint to the baselines.
AppendConstraintsHorizontalSyncBaselines = 1 << 0,
// The views can be constraint smaller than the guide.
AppendConstraintsHorizontalEqualOrSmallerThanGuide = 1 << 1,
};
// Struct used to bundle views that are part of the manual fill cells with an
// ElementType. This bundling is used by the
// `AppendVerticalConstraintsSpacingForViews` method to determine which spacing
// to add above the `view` when creating vertical constraints.
struct ManualFillCellView {
// Enum which represents possible types of UI element that are added to a
// manual fill cell.
enum class ElementType {
// The first chip button of a chip group.
kFirstChipButtonOfGroup,
// A labeled chip button that is not the first of its group.
kLabeledChipButton,
// A chip button that is not the first of its group and is unlabeled.
kOtherChipButton,
// A grey line to separate the header from the rest of the cell.
kHeaderSeparator,
// The view presenting the instructions on how to use virtual cards.
kVirtualCardInstructions,
// A grey line to separate the virtual card instruction view from the rest
// of the cell.
kVirtualCardInstructionsSeparator,
// Any other element not falling into one of the above types.
kOther,
};
UIView* view;
ElementType type;
// Operator overloads.
bool operator==(const ManualFillCellView& rhs) const {
return [view isEqual:rhs.view] && type == rhs.type;
}
bool operator!=(const ManualFillCellView& rhs) const {
return !(*this == rhs);
}
};
// Returns the horizontal spacing to use between the different chip buttons.
CGFloat GetHorizontalSpacingBetweenChips();
// Creates a blank button in chip style, for the given `action` and `target`.
UIButton* CreateChipWithSelectorAndTarget(SEL action, id target);
// Adds vertical constraints to given list, laying `manual_fill_cell_views`
// vertically (based on firstBaselineAnchor for the buttons or labels) following
// the `layout_guide`. Constraints are not activated.
void AppendVerticalConstraintsSpacingForViews(
NSMutableArray<NSLayoutConstraint*>* constraints,
const std::vector<ManualFillCellView>& manual_fill_cell_views,
UILayoutGuide* layout_guide);
// Adds vertical constraints like `AppendVerticalConstraintsSpacingForViews`
// above but using an `offset` to shift the first view's top anchor upwards when
// displaying a password cell that is connected to the previous one.
// TODO(crbug.com/326398845): Remove the `offset` parameter once the Keyboard
// Accessory Upgrade feature has launched both on iPhone and iPad.
void AppendVerticalConstraintsSpacingForViews(
NSMutableArray<NSLayoutConstraint*>* constraints,
const std::vector<ManualFillCellView>& manual_fill_cell_views,
UILayoutGuide* layout_guide,
CGFloat offset);
// Creates a ManualFillCellView with each chip button of `chip_groups`,
// and adds the ManualFillCellViews to `vertical_lead_views`.
void AddChipGroupsToVerticalLeadViews(
NSArray<NSArray<UIView*>*>* chip_groups,
std::vector<ManualFillCellView>& vertical_lead_views);
// Creates a ManualFillCellView with the `view` and adds the ManualFillCellView
// to `vertical_lead_views`.
void AddViewToVerticalLeadViews(
UIView* view,
ManualFillCellView::ElementType type,
std::vector<ManualFillCellView>& vertical_lead_views);
// Adds constraints to the given list, for the given `views`, so as to lay them
// out horizontally, aligned with the `layout_guide`. Constraints are not
// activated.
void AppendHorizontalConstraintsForViews(
NSMutableArray<NSLayoutConstraint*>* constraints,
NSArray<UIView*>* views,
UILayoutGuide* layout_guide);
// Adds constraints like `AppendHorizontalConstraintsForViews` above but also
// applies the given constant `margin` at both ends of the whole row.
void AppendHorizontalConstraintsForViews(
NSMutableArray<NSLayoutConstraint*>* constraints,
NSArray<UIView*>* views,
UILayoutGuide* layout_guide,
CGFloat margin);
// Adds constraints like `AppendHorizontalConstraintsForViews` above
// but with given `options`.
void AppendHorizontalConstraintsForViews(
NSMutableArray<NSLayoutConstraint*>* constraints,
NSArray<UIView*>* views,
UILayoutGuide* layout_guide,
CGFloat margin,
AppendConstraints options);
// Adds constraints like `AppendHorizontalConstraintsForViews` above,
// but with the given `trailing_view`, which is a view that is attached to the
// trailing side of the cell. The last view of `views` is therefore constraint
// to not overlap `trailing_view` when valid (i.e., when not `nil`).
// TODO(crbug.com/326398845): Remove the `margin` parameter once the Keyboard
// Accessory Upgrade feature has launched both on iPhone and iPad.
void AppendHorizontalConstraintsForViews(
NSMutableArray<NSLayoutConstraint*>* constraints,
NSArray<UIView*>* views,
UILayoutGuide* layout_guide,
CGFloat margin,
AppendConstraints options,
UIView* trailing_view);
// Creates and adds constraints to `constraints` with the goal of laying as many
// `views` as possible horizontally. The available horizontal space is
// determined by the width of `layout_guide`. Whenever there's not enough
// horizontal space left to welcome the next view, a new row of views is
// generated below. The starting view of every row is then added to
// `vertical_lead_views`.
void LayViewsHorizontallyWhenPossible(
NSArray<UIView*>* views,
UILayoutGuide* guide,
NSMutableArray<NSLayoutConstraint*>* constraints,
NSMutableArray<UIView*>* vertical_lead_views);
// Creates and adds constraints like `LayViewsHorizontallyWhenPossible` above,
// but with a given `first_row_trailing_view` that should be taken into account
// when laying the first row of views. `first_row_trailing_view` being a view
// that's attached to the trailing side of the cell and limiting the space
// available horizontally.
void LayViewsHorizontallyWhenPossible(
NSArray<UIView*>* views,
UILayoutGuide* guide,
NSMutableArray<NSLayoutConstraint*>* constraints,
NSMutableArray<UIView*>* vertical_lead_views,
UIView* first_row_trailing_view);
// Creates a blank label with autoresize mask off and adjustable font size.
UILabel* CreateLabel();
// Creates an attributed string composed of a title and subtitle. Used to
// generate the string for the manual fill cell's header label.
NSMutableAttributedString* CreateHeaderAttributedString(NSString* title,
NSString* subtitle);
// Creates an horizontal stack view containing an icon, a label and an overflow
// menu button. Used to create the different manual fill cells' header. `label`
// should never be `nil`.
UIStackView* CreateHeaderView(UIView* icon,
UILabel* label,
UIButton* overflow_menu_button);
// Creates and configures the overflow menu button that's displayed in the
// cell's header.
UIButton* CreateOverflowMenuButton();
// Creates a gray horizontal line separator. The gray line is added to the given
// `container` and proper constraints are enabled to keep the line in the
// desired location within the horizontal safe area.
UIView* CreateGraySeparatorForContainer(UIView* container);
// Creates the button used to fill the current form with the manual fill entity
// data.
UIButton* CreateAutofillFormButton();
// Creates a layout guide for the cell and adds it to the given 'content_view`.
// `cell_has_header` indicates whether or not the layout guide should take a
// header into account.
UILayoutGuide* AddLayoutGuideToContentView(UIView* content_view,
BOOL cell_has_header);
// Creates the attributed string containing the site name and potentially a host
// subtitle for the site name label.
NSMutableAttributedString* CreateSiteNameLabelAttributedText(
ManualFillSiteInfo* siteInfo);
// Sets the cell's container and its overflow menu button's accessibility label
// with the given `accessibility_context`. `accessibility_context` contains
// information on the position of the cell and its title (if any). Adding this
// information to the accessibility labels gives more context on the UI
// elements, and, therefore, allows accessibility users to better differentiate
// the different cells and their buttons.
void GiveAccessibilityContextToCellAndButton(UIView* cell_container,
UIButton* overflow_menu_button,
UIButton* autofill_form_button,
NSString* accessibility_context);
// Set up the cell accessibility elements so that the cell itself is accessible
// as a container and the accessibility subviews are read in the right order.
// Without setting the cell's accessibility elements, VoiceOver would read the
// elements following the view's hierarchy, meaning that it would follow the
// back to front order instead of the top to bottom order.
void SetUpCellAccessibilityElements(TableViewCell* cell,
NSArray<UIView*>* accessibilityElements);
#endif // IOS_CHROME_BROWSER_AUTOFILL_UI_BUNDLED_MANUAL_FILL_MANUAL_FILL_CELL_UTILS_H_