blob: e7a861673477c1d619ad799d8077fea929772731 [file] [log] [blame]
// 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.
#ifndef IOS_CHROME_COMMON_UI_UTIL_CONSTRAINTS_UI_UTIL_H_
#define IOS_CHROME_COMMON_UI_UTIL_CONSTRAINTS_UI_UTIL_H_
#import <UIKit/UIKit.h>
// A bitmask to refer to sides of a layout rectangle.
enum class LayoutSides {
kTop = 1 << 0,
kLeading = 1 << 1,
kBottom = 1 << 2,
kTrailing = 1 << 3,
};
// Implementation of bitwise "or", "and" operators (as those are not
// automatically defined for "class enum").
constexpr LayoutSides operator|(LayoutSides lhs, LayoutSides rhs) {
return static_cast<LayoutSides>(
static_cast<std::underlying_type<LayoutSides>::type>(lhs) |
static_cast<std::underlying_type<LayoutSides>::type>(rhs));
};
constexpr LayoutSides operator&(LayoutSides lhs, LayoutSides rhs) {
return static_cast<LayoutSides>(
static_cast<std::underlying_type<LayoutSides>::type>(lhs) &
static_cast<std::underlying_type<LayoutSides>::type>(rhs));
};
// Returns whether the |flag| is set in |mask|.
constexpr bool IsLayoutSidesMaskSet(LayoutSides mask, LayoutSides flag) {
return (mask & flag) == flag;
}
// Same as NSDirectionalEdgeInsets but available on iOS 10.
struct ChromeDirectionalEdgeInsets {
CGFloat top, leading, bottom, trailing; // specify amount to inset (positive)
// for each of the edges. values can
// be negative to 'outset'
};
inline ChromeDirectionalEdgeInsets ChromeDirectionalEdgeInsetsMake(
CGFloat top,
CGFloat leading,
CGFloat bottom,
CGFloat trailing) {
ChromeDirectionalEdgeInsets insets = {top, leading, bottom, trailing};
return insets;
}
// Defines a protocol for common -...Anchor methods of UIView and UILayoutGuide.
@protocol LayoutGuideProvider<NSObject>
@property(nonatomic, readonly, strong) NSLayoutXAxisAnchor* leadingAnchor;
@property(nonatomic, readonly, strong) NSLayoutXAxisAnchor* trailingAnchor;
@property(nonatomic, readonly, strong) NSLayoutXAxisAnchor* leftAnchor;
@property(nonatomic, readonly, strong) NSLayoutXAxisAnchor* rightAnchor;
@property(nonatomic, readonly, strong) NSLayoutYAxisAnchor* topAnchor;
@property(nonatomic, readonly, strong) NSLayoutYAxisAnchor* bottomAnchor;
@property(nonatomic, readonly, strong) NSLayoutDimension* widthAnchor;
@property(nonatomic, readonly, strong) NSLayoutDimension* heightAnchor;
@property(nonatomic, readonly, strong) NSLayoutXAxisAnchor* centerXAnchor;
@property(nonatomic, readonly, strong) NSLayoutYAxisAnchor* centerYAnchor;
@end
// UIView already supports the methods in LayoutGuideProvider.
@interface UIView (LayoutGuideProvider)<LayoutGuideProvider>
@end
// UILayoutGuide already supports the methods in LayoutGuideProvider.
@interface UILayoutGuide (LayoutGuideProvider)<LayoutGuideProvider>
@end
#pragma mark - Visual constraints.
// Applies all |constraints| to views in |subviewsDictionary|.
void ApplyVisualConstraints(NSArray* constraints,
NSDictionary* subviewsDictionary);
// Applies all |constraints| with |metrics| to views in |subviewsDictionary|.
void ApplyVisualConstraintsWithMetrics(NSArray* constraints,
NSDictionary* subviewsDictionary,
NSDictionary* metrics);
// Applies all |constraints| with |metrics| and |options| to views in
// |subviewsDictionary|.
void ApplyVisualConstraintsWithMetricsAndOptions(
NSArray* constraints,
NSDictionary* subviewsDictionary,
NSDictionary* metrics,
NSLayoutFormatOptions options);
// Returns constraints based on the visual constraints described with
// |constraints| and |metrics| to views in |subviewsDictionary|.
NSArray* VisualConstraintsWithMetrics(NSArray* constraints,
NSDictionary* subviewsDictionary,
NSDictionary* metrics);
// Returns constraints based on the visual constraints described with
// |constraints|, |metrics| and |options| to views in |subviewsDictionary|.
NSArray* VisualConstraintsWithMetricsAndOptions(
NSArray* constraints,
NSDictionary* subviewsDictionary,
NSDictionary* metrics,
NSLayoutFormatOptions options);
#pragma mark - Constraints between two views.
// Most methods in this group can take a layout guide or a view.
// Adds a constraint that |view1| and |view2| are center-aligned horizontally
// and vertically.
void AddSameCenterConstraints(id<LayoutGuideProvider> view1,
id<LayoutGuideProvider> view2);
// Adds a constraint that |view1| and |view2| are center-aligned horizontally.
// |view1| and |view2| must be in the same view hierarchy.
void AddSameCenterXConstraint(id<LayoutGuideProvider> view1,
id<LayoutGuideProvider> view2);
// Deprecated version:
void AddSameCenterXConstraint(UIView* unused_parentView,
UIView* subview1,
UIView* subview2);
// Adds a constraint that |view1| and |view2| are center-aligned vertically.
// |view1| and |view2| must be in the same view hierarchy.
void AddSameCenterYConstraint(id<LayoutGuideProvider> view1,
id<LayoutGuideProvider> view2);
// Deprecated version:
void AddSameCenterYConstraint(UIView* unused_parentView,
UIView* subview1,
UIView* subview2);
// Adds constraints to make two views' size and center equal by pinning leading,
// trailing, top and bottom anchors.
void AddSameConstraints(id<LayoutGuideProvider> view1,
id<LayoutGuideProvider> view2);
// Adds constraints to make |innerView| leading, trailing, top and bottom
// anchors equals to |outerView| safe area (or view bounds) anchors.
void PinToSafeArea(id<LayoutGuideProvider> innerView, UIView* outerView);
// Constraints |side_flags| of |view1| and |view2| together.
// Example usage: AddSameConstraintsToSides(view1, view2,
// LayoutSides::kTop|LayoutSides::kLeading)
void AddSameConstraintsToSides(id<LayoutGuideProvider> view1,
id<LayoutGuideProvider> view2,
LayoutSides side_flags);
// Constraints |side_flags| sides of |innerView| and |outerView| together, with
// |innerView| inset by |insets|. Example usage:
// AddSameConstraintsToSidesWithInsets(view1, view2,
// LayoutSides::kTop|LayoutSides::kLeading, ChromeDirectionalEdgeInsets{10, 5,
// 10, 5}) - This will constraint innerView to be inside of outerView, with
// leading/trailing inset by 10 and top/bottom inset by 5.
// Edge insets for sides not listed in |side_flags| are ignored.
void AddSameConstraintsToSidesWithInsets(id<LayoutGuideProvider> innerView,
id<LayoutGuideProvider> outerView,
LayoutSides side_flags,
ChromeDirectionalEdgeInsets insets);
// Adds an optional amount of padding to the top and bottom of a view using a
// constraint with a lowered priority. One use case is with a collectionview or
// tableview cell. When the cell is self-sizing, these constraints will kick in
// and expand the cell to add the desired padding around the inner views, but
// the padding is optional so that the inner views are not artificially
// shortened when fixed-size cells cut into that padding. The padding is added
// between |outerView| and |innerView|.
void AddOptionalVerticalPadding(UIView* outerView,
UIView* innerView,
CGFloat padding);
void AddOptionalVerticalPadding(UIView* outerView,
UIView* topInnerView,
UIView* bottomInnerView,
CGFloat padding);
#pragma mark - Safe Area.
// Returns a safeAreaLayoutGuide for a given view.
id<LayoutGuideProvider> SafeAreaLayoutGuideForView(UIView* view);
#endif // IOS_CHROME_COMMON_UI_UTIL_CONSTRAINTS_UI_UTIL_H_