MASConstraintMaker.m 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261
  1. //
  2. // MASConstraintMaker.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. | MASAttributeFirstBaseline | MASAttributeLastBaseline
  69. #if TARGET_OS_IPHONE || TARGET_OS_TV
  70. | MASAttributeLeftMargin | MASAttributeRightMargin | MASAttributeTopMargin | MASAttributeBottomMargin
  71. | MASAttributeLeadingMargin | MASAttributeTrailingMargin | MASAttributeCenterXWithinMargins
  72. | MASAttributeCenterYWithinMargins
  73. #endif
  74. );
  75. NSAssert((attrs & anyAttribute) != 0, @"You didn't pass any attribute to make.attributes(...)");
  76. NSMutableArray *attributes = [NSMutableArray array];
  77. if (attrs & MASAttributeLeft) [attributes addObject:self.view.mas_left];
  78. if (attrs & MASAttributeRight) [attributes addObject:self.view.mas_right];
  79. if (attrs & MASAttributeTop) [attributes addObject:self.view.mas_top];
  80. if (attrs & MASAttributeBottom) [attributes addObject:self.view.mas_bottom];
  81. if (attrs & MASAttributeLeading) [attributes addObject:self.view.mas_leading];
  82. if (attrs & MASAttributeTrailing) [attributes addObject:self.view.mas_trailing];
  83. if (attrs & MASAttributeWidth) [attributes addObject:self.view.mas_width];
  84. if (attrs & MASAttributeHeight) [attributes addObject:self.view.mas_height];
  85. if (attrs & MASAttributeCenterX) [attributes addObject:self.view.mas_centerX];
  86. if (attrs & MASAttributeCenterY) [attributes addObject:self.view.mas_centerY];
  87. if (attrs & MASAttributeBaseline) [attributes addObject:self.view.mas_baseline];
  88. if (attrs & MASAttributeFirstBaseline) [attributes addObject:self.view.mas_firstBaseline];
  89. if (attrs & MASAttributeLastBaseline) [attributes addObject:self.view.mas_lastBaseline];
  90. #if TARGET_OS_IPHONE || TARGET_OS_TV
  91. if (attrs & MASAttributeLeftMargin) [attributes addObject:self.view.mas_leftMargin];
  92. if (attrs & MASAttributeRightMargin) [attributes addObject:self.view.mas_rightMargin];
  93. if (attrs & MASAttributeTopMargin) [attributes addObject:self.view.mas_topMargin];
  94. if (attrs & MASAttributeBottomMargin) [attributes addObject:self.view.mas_bottomMargin];
  95. if (attrs & MASAttributeLeadingMargin) [attributes addObject:self.view.mas_leadingMargin];
  96. if (attrs & MASAttributeTrailingMargin) [attributes addObject:self.view.mas_trailingMargin];
  97. if (attrs & MASAttributeCenterXWithinMargins) [attributes addObject:self.view.mas_centerXWithinMargins];
  98. if (attrs & MASAttributeCenterYWithinMargins) [attributes addObject:self.view.mas_centerYWithinMargins];
  99. #endif
  100. NSMutableArray *children = [NSMutableArray arrayWithCapacity:attributes.count];
  101. for (MASViewAttribute *a in attributes) {
  102. [children addObject:[[MASViewConstraint alloc] initWithFirstViewAttribute:a]];
  103. }
  104. MASCompositeConstraint *constraint = [[MASCompositeConstraint alloc] initWithChildren:children];
  105. constraint.delegate = self;
  106. [self.constraints addObject:constraint];
  107. return constraint;
  108. }
  109. #pragma mark - standard Attributes
  110. - (MASConstraint *)addConstraintWithLayoutAttribute:(NSLayoutAttribute)layoutAttribute {
  111. return [self constraint:nil addConstraintWithLayoutAttribute:layoutAttribute];
  112. }
  113. - (MASConstraint *)left {
  114. return [self addConstraintWithLayoutAttribute:NSLayoutAttributeLeft];
  115. }
  116. - (MASConstraint *)top {
  117. return [self addConstraintWithLayoutAttribute:NSLayoutAttributeTop];
  118. }
  119. - (MASConstraint *)right {
  120. return [self addConstraintWithLayoutAttribute:NSLayoutAttributeRight];
  121. }
  122. - (MASConstraint *)bottom {
  123. return [self addConstraintWithLayoutAttribute:NSLayoutAttributeBottom];
  124. }
  125. - (MASConstraint *)leading {
  126. return [self addConstraintWithLayoutAttribute:NSLayoutAttributeLeading];
  127. }
  128. - (MASConstraint *)trailing {
  129. return [self addConstraintWithLayoutAttribute:NSLayoutAttributeTrailing];
  130. }
  131. - (MASConstraint *)width {
  132. return [self addConstraintWithLayoutAttribute:NSLayoutAttributeWidth];
  133. }
  134. - (MASConstraint *)height {
  135. return [self addConstraintWithLayoutAttribute:NSLayoutAttributeHeight];
  136. }
  137. - (MASConstraint *)centerX {
  138. return [self addConstraintWithLayoutAttribute:NSLayoutAttributeCenterX];
  139. }
  140. - (MASConstraint *)centerY {
  141. return [self addConstraintWithLayoutAttribute:NSLayoutAttributeCenterY];
  142. }
  143. - (MASConstraint *)baseline {
  144. return [self addConstraintWithLayoutAttribute:NSLayoutAttributeBaseline];
  145. }
  146. - (MASConstraint *(^)(MASAttribute))attributes {
  147. return [^(MASAttribute attrs){
  148. return [self addConstraintWithAttributes:attrs];
  149. } copy];
  150. }
  151. - (MASConstraint *)firstBaseline {
  152. return [self addConstraintWithLayoutAttribute:NSLayoutAttributeFirstBaseline];
  153. }
  154. - (MASConstraint *)lastBaseline {
  155. return [self addConstraintWithLayoutAttribute:NSLayoutAttributeLastBaseline];
  156. }
  157. #if TARGET_OS_IPHONE || TARGET_OS_TV
  158. - (MASConstraint *)leftMargin {
  159. return [self addConstraintWithLayoutAttribute:NSLayoutAttributeLeftMargin];
  160. }
  161. - (MASConstraint *)rightMargin {
  162. return [self addConstraintWithLayoutAttribute:NSLayoutAttributeRightMargin];
  163. }
  164. - (MASConstraint *)topMargin {
  165. return [self addConstraintWithLayoutAttribute:NSLayoutAttributeTopMargin];
  166. }
  167. - (MASConstraint *)bottomMargin {
  168. return [self addConstraintWithLayoutAttribute:NSLayoutAttributeBottomMargin];
  169. }
  170. - (MASConstraint *)leadingMargin {
  171. return [self addConstraintWithLayoutAttribute:NSLayoutAttributeLeadingMargin];
  172. }
  173. - (MASConstraint *)trailingMargin {
  174. return [self addConstraintWithLayoutAttribute:NSLayoutAttributeTrailingMargin];
  175. }
  176. - (MASConstraint *)centerXWithinMargins {
  177. return [self addConstraintWithLayoutAttribute:NSLayoutAttributeCenterXWithinMargins];
  178. }
  179. - (MASConstraint *)centerYWithinMargins {
  180. return [self addConstraintWithLayoutAttribute:NSLayoutAttributeCenterYWithinMargins];
  181. }
  182. #endif
  183. #pragma mark - composite Attributes
  184. - (MASConstraint *)edges {
  185. return [self addConstraintWithAttributes:MASAttributeTop | MASAttributeLeft | MASAttributeRight | MASAttributeBottom];
  186. }
  187. - (MASConstraint *)size {
  188. return [self addConstraintWithAttributes:MASAttributeWidth | MASAttributeHeight];
  189. }
  190. - (MASConstraint *)center {
  191. return [self addConstraintWithAttributes:MASAttributeCenterX | MASAttributeCenterY];
  192. }
  193. #pragma mark - grouping
  194. - (MASConstraint *(^)(dispatch_block_t group))group {
  195. return [^id(dispatch_block_t group) {
  196. NSInteger previousCount = self.constraints.count;
  197. group();
  198. NSArray *children = [self.constraints subarrayWithRange:NSMakeRange(previousCount, self.constraints.count - previousCount)];
  199. MASCompositeConstraint *constraint = [[MASCompositeConstraint alloc] initWithChildren:children];
  200. constraint.delegate = self;
  201. return constraint;
  202. } copy];
  203. }
  204. @end