MASConstraintMaker.m 10 KB

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