//
|
// MASConstraintBuilder.m
|
// Masonry
|
//
|
// Created by Jonas Budelmann on 20/07/13.
|
// Copyright (c) 2013 cloudling. All rights reserved.
|
//
|
|
#import "MASConstraintMaker.h"
|
#import "MASViewConstraint.h"
|
#import "MASCompositeConstraint.h"
|
#import "MASConstraint+Private.h"
|
#import "MASViewAttribute.h"
|
#import "View+MASAdditions.h"
|
|
@interface MASConstraintMaker () <MASConstraintDelegate>
|
|
@property (nonatomic, weak) MAS_VIEW *view;
|
@property (nonatomic, strong) NSMutableArray *constraints;
|
|
@end
|
|
@implementation MASConstraintMaker
|
|
- (id)initWithView:(MAS_VIEW *)view {
|
self = [super init];
|
if (!self) return nil;
|
|
self.view = view;
|
self.constraints = NSMutableArray.new;
|
|
return self;
|
}
|
|
- (NSArray *)install {
|
if (self.removeExisting) {
|
NSArray *installedConstraints = [MASViewConstraint installedConstraintsForView:self.view];
|
for (MASConstraint *constraint in installedConstraints) {
|
[constraint uninstall];
|
}
|
}
|
NSArray *constraints = self.constraints.copy;
|
for (MASConstraint *constraint in constraints) {
|
constraint.updateExisting = self.updateExisting;
|
[constraint install];
|
}
|
[self.constraints removeAllObjects];
|
return constraints;
|
}
|
|
#pragma mark - MASConstraintDelegate
|
|
- (void)constraint:(MASConstraint *)constraint shouldBeReplacedWithConstraint:(MASConstraint *)replacementConstraint {
|
NSUInteger index = [self.constraints indexOfObject:constraint];
|
NSAssert(index != NSNotFound, @"Could not find constraint %@", constraint);
|
[self.constraints replaceObjectAtIndex:index withObject:replacementConstraint];
|
}
|
|
- (MASConstraint *)constraint:(MASConstraint *)constraint addConstraintWithLayoutAttribute:(NSLayoutAttribute)layoutAttribute {
|
MASViewAttribute *viewAttribute = [[MASViewAttribute alloc] initWithView:self.view layoutAttribute:layoutAttribute];
|
MASViewConstraint *newConstraint = [[MASViewConstraint alloc] initWithFirstViewAttribute:viewAttribute];
|
if ([constraint isKindOfClass:MASViewConstraint.class]) {
|
//replace with composite constraint
|
NSArray *children = @[constraint, newConstraint];
|
MASCompositeConstraint *compositeConstraint = [[MASCompositeConstraint alloc] initWithChildren:children];
|
compositeConstraint.delegate = self;
|
[self constraint:constraint shouldBeReplacedWithConstraint:compositeConstraint];
|
return compositeConstraint;
|
}
|
if (!constraint) {
|
newConstraint.delegate = self;
|
[self.constraints addObject:newConstraint];
|
}
|
return newConstraint;
|
}
|
|
- (MASConstraint *)addConstraintWithAttributes:(MASAttribute)attrs {
|
__unused MASAttribute anyAttribute = (MASAttributeLeft | MASAttributeRight | MASAttributeTop | MASAttributeBottom | MASAttributeLeading
|
| MASAttributeTrailing | MASAttributeWidth | MASAttributeHeight | MASAttributeCenterX
|
| MASAttributeCenterY | MASAttributeBaseline
|
#if (__IPHONE_OS_VERSION_MIN_REQUIRED >= 80000) || (__TV_OS_VERSION_MIN_REQUIRED >= 9000) || (__MAC_OS_X_VERSION_MIN_REQUIRED >= 101100)
|
| MASAttributeFirstBaseline | MASAttributeLastBaseline
|
#endif
|
#if TARGET_OS_IPHONE || TARGET_OS_TV
|
| MASAttributeLeftMargin | MASAttributeRightMargin | MASAttributeTopMargin | MASAttributeBottomMargin
|
| MASAttributeLeadingMargin | MASAttributeTrailingMargin | MASAttributeCenterXWithinMargins
|
| MASAttributeCenterYWithinMargins
|
#endif
|
);
|
|
NSAssert((attrs & anyAttribute) != 0, @"You didn't pass any attribute to make.attributes(...)");
|
|
NSMutableArray *attributes = [NSMutableArray array];
|
|
if (attrs & MASAttributeLeft) [attributes addObject:self.view.mas_left];
|
if (attrs & MASAttributeRight) [attributes addObject:self.view.mas_right];
|
if (attrs & MASAttributeTop) [attributes addObject:self.view.mas_top];
|
if (attrs & MASAttributeBottom) [attributes addObject:self.view.mas_bottom];
|
if (attrs & MASAttributeLeading) [attributes addObject:self.view.mas_leading];
|
if (attrs & MASAttributeTrailing) [attributes addObject:self.view.mas_trailing];
|
if (attrs & MASAttributeWidth) [attributes addObject:self.view.mas_width];
|
if (attrs & MASAttributeHeight) [attributes addObject:self.view.mas_height];
|
if (attrs & MASAttributeCenterX) [attributes addObject:self.view.mas_centerX];
|
if (attrs & MASAttributeCenterY) [attributes addObject:self.view.mas_centerY];
|
if (attrs & MASAttributeBaseline) [attributes addObject:self.view.mas_baseline];
|
|
#if (__IPHONE_OS_VERSION_MIN_REQUIRED >= 80000) || (__TV_OS_VERSION_MIN_REQUIRED >= 9000) || (__MAC_OS_X_VERSION_MIN_REQUIRED >= 101100)
|
|
if (attrs & MASAttributeFirstBaseline) [attributes addObject:self.view.mas_firstBaseline];
|
if (attrs & MASAttributeLastBaseline) [attributes addObject:self.view.mas_lastBaseline];
|
|
#endif
|
|
#if TARGET_OS_IPHONE || TARGET_OS_TV
|
|
if (attrs & MASAttributeLeftMargin) [attributes addObject:self.view.mas_leftMargin];
|
if (attrs & MASAttributeRightMargin) [attributes addObject:self.view.mas_rightMargin];
|
if (attrs & MASAttributeTopMargin) [attributes addObject:self.view.mas_topMargin];
|
if (attrs & MASAttributeBottomMargin) [attributes addObject:self.view.mas_bottomMargin];
|
if (attrs & MASAttributeLeadingMargin) [attributes addObject:self.view.mas_leadingMargin];
|
if (attrs & MASAttributeTrailingMargin) [attributes addObject:self.view.mas_trailingMargin];
|
if (attrs & MASAttributeCenterXWithinMargins) [attributes addObject:self.view.mas_centerXWithinMargins];
|
if (attrs & MASAttributeCenterYWithinMargins) [attributes addObject:self.view.mas_centerYWithinMargins];
|
|
#endif
|
|
NSMutableArray *children = [NSMutableArray arrayWithCapacity:attributes.count];
|
|
for (MASViewAttribute *a in attributes) {
|
[children addObject:[[MASViewConstraint alloc] initWithFirstViewAttribute:a]];
|
}
|
|
MASCompositeConstraint *constraint = [[MASCompositeConstraint alloc] initWithChildren:children];
|
constraint.delegate = self;
|
[self.constraints addObject:constraint];
|
return constraint;
|
}
|
|
#pragma mark - standard Attributes
|
|
- (MASConstraint *)addConstraintWithLayoutAttribute:(NSLayoutAttribute)layoutAttribute {
|
return [self constraint:nil addConstraintWithLayoutAttribute:layoutAttribute];
|
}
|
|
- (MASConstraint *)left {
|
return [self addConstraintWithLayoutAttribute:NSLayoutAttributeLeft];
|
}
|
|
- (MASConstraint *)top {
|
return [self addConstraintWithLayoutAttribute:NSLayoutAttributeTop];
|
}
|
|
- (MASConstraint *)right {
|
return [self addConstraintWithLayoutAttribute:NSLayoutAttributeRight];
|
}
|
|
- (MASConstraint *)bottom {
|
return [self addConstraintWithLayoutAttribute:NSLayoutAttributeBottom];
|
}
|
|
- (MASConstraint *)leading {
|
return [self addConstraintWithLayoutAttribute:NSLayoutAttributeLeading];
|
}
|
|
- (MASConstraint *)trailing {
|
return [self addConstraintWithLayoutAttribute:NSLayoutAttributeTrailing];
|
}
|
|
- (MASConstraint *)width {
|
return [self addConstraintWithLayoutAttribute:NSLayoutAttributeWidth];
|
}
|
|
- (MASConstraint *)height {
|
return [self addConstraintWithLayoutAttribute:NSLayoutAttributeHeight];
|
}
|
|
- (MASConstraint *)centerX {
|
return [self addConstraintWithLayoutAttribute:NSLayoutAttributeCenterX];
|
}
|
|
- (MASConstraint *)centerY {
|
return [self addConstraintWithLayoutAttribute:NSLayoutAttributeCenterY];
|
}
|
|
- (MASConstraint *)baseline {
|
return [self addConstraintWithLayoutAttribute:NSLayoutAttributeBaseline];
|
}
|
|
- (MASConstraint *(^)(MASAttribute))attributes {
|
return ^(MASAttribute attrs){
|
return [self addConstraintWithAttributes:attrs];
|
};
|
}
|
|
#if (__IPHONE_OS_VERSION_MIN_REQUIRED >= 80000) || (__TV_OS_VERSION_MIN_REQUIRED >= 9000) || (__MAC_OS_X_VERSION_MIN_REQUIRED >= 101100)
|
|
- (MASConstraint *)firstBaseline {
|
return [self addConstraintWithLayoutAttribute:NSLayoutAttributeFirstBaseline];
|
}
|
|
- (MASConstraint *)lastBaseline {
|
return [self addConstraintWithLayoutAttribute:NSLayoutAttributeLastBaseline];
|
}
|
|
#endif
|
|
|
#if TARGET_OS_IPHONE || TARGET_OS_TV
|
|
- (MASConstraint *)leftMargin {
|
return [self addConstraintWithLayoutAttribute:NSLayoutAttributeLeftMargin];
|
}
|
|
- (MASConstraint *)rightMargin {
|
return [self addConstraintWithLayoutAttribute:NSLayoutAttributeRightMargin];
|
}
|
|
- (MASConstraint *)topMargin {
|
return [self addConstraintWithLayoutAttribute:NSLayoutAttributeTopMargin];
|
}
|
|
- (MASConstraint *)bottomMargin {
|
return [self addConstraintWithLayoutAttribute:NSLayoutAttributeBottomMargin];
|
}
|
|
- (MASConstraint *)leadingMargin {
|
return [self addConstraintWithLayoutAttribute:NSLayoutAttributeLeadingMargin];
|
}
|
|
- (MASConstraint *)trailingMargin {
|
return [self addConstraintWithLayoutAttribute:NSLayoutAttributeTrailingMargin];
|
}
|
|
- (MASConstraint *)centerXWithinMargins {
|
return [self addConstraintWithLayoutAttribute:NSLayoutAttributeCenterXWithinMargins];
|
}
|
|
- (MASConstraint *)centerYWithinMargins {
|
return [self addConstraintWithLayoutAttribute:NSLayoutAttributeCenterYWithinMargins];
|
}
|
|
#endif
|
|
|
#pragma mark - composite Attributes
|
|
- (MASConstraint *)edges {
|
return [self addConstraintWithAttributes:MASAttributeTop | MASAttributeLeft | MASAttributeRight | MASAttributeBottom];
|
}
|
|
- (MASConstraint *)size {
|
return [self addConstraintWithAttributes:MASAttributeWidth | MASAttributeHeight];
|
}
|
|
- (MASConstraint *)center {
|
return [self addConstraintWithAttributes:MASAttributeCenterX | MASAttributeCenterY];
|
}
|
|
#pragma mark - grouping
|
|
- (MASConstraint *(^)(dispatch_block_t group))group {
|
return ^id(dispatch_block_t group) {
|
NSInteger previousCount = self.constraints.count;
|
group();
|
|
NSArray *children = [self.constraints subarrayWithRange:NSMakeRange(previousCount, self.constraints.count - previousCount)];
|
MASCompositeConstraint *constraint = [[MASCompositeConstraint alloc] initWithChildren:children];
|
constraint.delegate = self;
|
return constraint;
|
};
|
}
|
|
@end
|