| // | 
| //  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 |