MASConstraintMaker.m 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250
  1. //
  2. // MASConstraintBuilder.m
  3. // Masonry
  4. //
  5. // Created by Jonas Budelmann on 20/07/13.
  6. // Copyright (c) 2013 cloudling. All rights reserved.
  7. //
  8. #import "MASConstraintMaker.h"
  9. #import "MASViewConstraint.h"
  10. #import "MASCompositeConstraint.h"
  11. #import "MASConstraint+Private.h"
  12. #import "MASViewAttribute.h"
  13. #import "View+MASAdditions.h"
  14. @interface MASConstraintMaker () <MASConstraintDelegate>
  15. @property (nonatomic, weak) MAS_VIEW *view;
  16. @property (nonatomic, strong) NSMutableArray *constraints;
  17. @end
  18. @implementation MASConstraintMaker
  19. - (id)initWithView:(MAS_VIEW *)view {
  20. self = [super init];
  21. if (!self) return nil;
  22. self.view = view;
  23. self.constraints = NSMutableArray.new;
  24. return self;
  25. }
  26. - (NSArray *)install {
  27. if (self.removeExisting) {
  28. NSArray *installedConstraints = [MASViewConstraint installedConstraintsForView:self.view];
  29. for (MASConstraint *constraint in installedConstraints) {
  30. [constraint uninstall];
  31. }
  32. }
  33. NSArray *constraints = self.constraints.copy;
  34. for (MASConstraint *constraint in constraints) {
  35. constraint.updateExisting = self.updateExisting;
  36. [constraint install];
  37. }
  38. [self.constraints removeAllObjects];
  39. return constraints;
  40. }
  41. #pragma mark - MASConstraintDelegate
  42. - (void)constraint:(MASConstraint *)constraint shouldBeReplacedWithConstraint:(MASConstraint *)replacementConstraint {
  43. NSUInteger index = [self.constraints indexOfObject:constraint];
  44. NSAssert(index != NSNotFound, @"Could not find constraint %@", constraint);
  45. [self.constraints replaceObjectAtIndex:index withObject:replacementConstraint];
  46. }
  47. - (MASConstraint *)constraint:(MASConstraint *)constraint addConstraintWithLayoutAttribute:(NSLayoutAttribute)layoutAttribute {
  48. MASViewAttribute *viewAttribute = [[MASViewAttribute alloc] initWithView:self.view layoutAttribute:layoutAttribute];
  49. MASViewConstraint *newConstraint = [[MASViewConstraint alloc] initWithFirstViewAttribute:viewAttribute];
  50. if ([constraint isKindOfClass:MASViewConstraint.class]) {
  51. //replace with composite constraint
  52. NSArray *children = @[constraint, newConstraint];
  53. MASCompositeConstraint *compositeConstraint = [[MASCompositeConstraint alloc] initWithChildren:children];
  54. compositeConstraint.delegate = self;
  55. [self constraint:constraint shouldBeReplacedWithConstraint:compositeConstraint];
  56. return compositeConstraint;
  57. }
  58. if (!constraint) {
  59. newConstraint.delegate = self;
  60. [self.constraints addObject:newConstraint];
  61. }
  62. return newConstraint;
  63. }
  64. - (MASConstraint *)addConstraintWithAttributes:(MASAttribute)attrs {
  65. __unused MASAttribute anyAttribute = (MASAttributeLeft | MASAttributeRight | MASAttributeTop | MASAttributeBottom | MASAttributeLeading
  66. | MASAttributeTrailing | MASAttributeWidth | MASAttributeHeight | MASAttributeCenterX
  67. | MASAttributeCenterY | MASAttributeBaseline
  68. #if TARGET_OS_IPHONE || TARGET_OS_TV
  69. | MASAttributeLeftMargin | MASAttributeRightMargin | MASAttributeTopMargin | MASAttributeBottomMargin
  70. | MASAttributeLeadingMargin | MASAttributeTrailingMargin | MASAttributeCenterXWithinMargins
  71. | MASAttributeCenterYWithinMargins
  72. #endif
  73. );
  74. NSAssert((attrs & anyAttribute) != 0, @"You didn't pass any attribute to make.attributes(...)");
  75. NSMutableArray *attributes = [NSMutableArray array];
  76. if (attrs & MASAttributeLeft) [attributes addObject:self.view.mas_left];
  77. if (attrs & MASAttributeRight) [attributes addObject:self.view.mas_right];
  78. if (attrs & MASAttributeTop) [attributes addObject:self.view.mas_top];
  79. if (attrs & MASAttributeBottom) [attributes addObject:self.view.mas_bottom];
  80. if (attrs & MASAttributeLeading) [attributes addObject:self.view.mas_leading];
  81. if (attrs & MASAttributeTrailing) [attributes addObject:self.view.mas_trailing];
  82. if (attrs & MASAttributeWidth) [attributes addObject:self.view.mas_width];
  83. if (attrs & MASAttributeHeight) [attributes addObject:self.view.mas_height];
  84. if (attrs & MASAttributeCenterX) [attributes addObject:self.view.mas_centerX];
  85. if (attrs & MASAttributeCenterY) [attributes addObject:self.view.mas_centerY];
  86. if (attrs & MASAttributeBaseline) [attributes addObject:self.view.mas_baseline];
  87. #if TARGET_OS_IPHONE || TARGET_OS_TV
  88. if (attrs & MASAttributeLeftMargin) [attributes addObject:self.view.mas_leftMargin];
  89. if (attrs & MASAttributeRightMargin) [attributes addObject:self.view.mas_rightMargin];
  90. if (attrs & MASAttributeTopMargin) [attributes addObject:self.view.mas_topMargin];
  91. if (attrs & MASAttributeBottomMargin) [attributes addObject:self.view.mas_bottomMargin];
  92. if (attrs & MASAttributeLeadingMargin) [attributes addObject:self.view.mas_leadingMargin];
  93. if (attrs & MASAttributeTrailingMargin) [attributes addObject:self.view.mas_trailingMargin];
  94. if (attrs & MASAttributeCenterXWithinMargins) [attributes addObject:self.view.mas_centerXWithinMargins];
  95. if (attrs & MASAttributeCenterYWithinMargins) [attributes addObject:self.view.mas_centerYWithinMargins];
  96. #endif
  97. NSMutableArray *children = [NSMutableArray arrayWithCapacity:attributes.count];
  98. for (MASViewAttribute *a in attributes) {
  99. [children addObject:[[MASViewConstraint alloc] initWithFirstViewAttribute:a]];
  100. }
  101. MASCompositeConstraint *constraint = [[MASCompositeConstraint alloc] initWithChildren:children];
  102. constraint.delegate = self;
  103. [self.constraints addObject:constraint];
  104. return constraint;
  105. }
  106. #pragma mark - standard Attributes
  107. - (MASConstraint *)addConstraintWithLayoutAttribute:(NSLayoutAttribute)layoutAttribute {
  108. return [self constraint:nil addConstraintWithLayoutAttribute:layoutAttribute];
  109. }
  110. - (MASConstraint *)left {
  111. return [self addConstraintWithLayoutAttribute:NSLayoutAttributeLeft];
  112. }
  113. - (MASConstraint *)top {
  114. return [self addConstraintWithLayoutAttribute:NSLayoutAttributeTop];
  115. }
  116. - (MASConstraint *)right {
  117. return [self addConstraintWithLayoutAttribute:NSLayoutAttributeRight];
  118. }
  119. - (MASConstraint *)bottom {
  120. return [self addConstraintWithLayoutAttribute:NSLayoutAttributeBottom];
  121. }
  122. - (MASConstraint *)leading {
  123. return [self addConstraintWithLayoutAttribute:NSLayoutAttributeLeading];
  124. }
  125. - (MASConstraint *)trailing {
  126. return [self addConstraintWithLayoutAttribute:NSLayoutAttributeTrailing];
  127. }
  128. - (MASConstraint *)width {
  129. return [self addConstraintWithLayoutAttribute:NSLayoutAttributeWidth];
  130. }
  131. - (MASConstraint *)height {
  132. return [self addConstraintWithLayoutAttribute:NSLayoutAttributeHeight];
  133. }
  134. - (MASConstraint *)centerX {
  135. return [self addConstraintWithLayoutAttribute:NSLayoutAttributeCenterX];
  136. }
  137. - (MASConstraint *)centerY {
  138. return [self addConstraintWithLayoutAttribute:NSLayoutAttributeCenterY];
  139. }
  140. - (MASConstraint *)baseline {
  141. return [self addConstraintWithLayoutAttribute:NSLayoutAttributeBaseline];
  142. }
  143. - (MASConstraint *(^)(MASAttribute))attributes {
  144. return ^(MASAttribute attrs){
  145. return [self addConstraintWithAttributes:attrs];
  146. };
  147. }
  148. #if TARGET_OS_IPHONE || TARGET_OS_TV
  149. - (MASConstraint *)leftMargin {
  150. return [self addConstraintWithLayoutAttribute:NSLayoutAttributeLeftMargin];
  151. }
  152. - (MASConstraint *)rightMargin {
  153. return [self addConstraintWithLayoutAttribute:NSLayoutAttributeRightMargin];
  154. }
  155. - (MASConstraint *)topMargin {
  156. return [self addConstraintWithLayoutAttribute:NSLayoutAttributeTopMargin];
  157. }
  158. - (MASConstraint *)bottomMargin {
  159. return [self addConstraintWithLayoutAttribute:NSLayoutAttributeBottomMargin];
  160. }
  161. - (MASConstraint *)leadingMargin {
  162. return [self addConstraintWithLayoutAttribute:NSLayoutAttributeLeadingMargin];
  163. }
  164. - (MASConstraint *)trailingMargin {
  165. return [self addConstraintWithLayoutAttribute:NSLayoutAttributeTrailingMargin];
  166. }
  167. - (MASConstraint *)centerXWithinMargins {
  168. return [self addConstraintWithLayoutAttribute:NSLayoutAttributeCenterXWithinMargins];
  169. }
  170. - (MASConstraint *)centerYWithinMargins {
  171. return [self addConstraintWithLayoutAttribute:NSLayoutAttributeCenterYWithinMargins];
  172. }
  173. #endif
  174. #pragma mark - composite Attributes
  175. - (MASConstraint *)edges {
  176. return [self addConstraintWithAttributes:MASAttributeTop | MASAttributeLeft | MASAttributeRight | MASAttributeBottom];
  177. }
  178. - (MASConstraint *)size {
  179. return [self addConstraintWithAttributes:MASAttributeWidth | MASAttributeHeight];
  180. }
  181. - (MASConstraint *)center {
  182. return [self addConstraintWithAttributes:MASAttributeCenterX | MASAttributeCenterY];
  183. }
  184. #pragma mark - grouping
  185. - (MASConstraint *(^)(dispatch_block_t group))group {
  186. return ^id(dispatch_block_t group) {
  187. NSInteger previousCount = self.constraints.count;
  188. group();
  189. NSArray *children = [self.constraints subarrayWithRange:NSMakeRange(previousCount, self.constraints.count - previousCount)];
  190. MASCompositeConstraint *constraint = [[MASCompositeConstraint alloc] initWithChildren:children];
  191. constraint.delegate = self;
  192. return constraint;
  193. };
  194. }
  195. @end