// // MASConstraint.m // Masonry // // Created by Nick Tymchenko on 1/20/14. // #import "MASConstraint.h" #import "MASConstraint+Private.h" #define MASMethodNotImplemented() \ @throw [NSException exceptionWithName:NSInternalInconsistencyException \ reason:[NSString stringWithFormat:@"You must override %@ in a subclass.", NSStringFromSelector(_cmd)] \ userInfo:nil] @implementation MASConstraint #pragma mark - Init - (id)init { NSAssert(![self isMemberOfClass:[MASConstraint class]], @"MASConstraint is an abstract class, you should not instantiate it directly."); return [super init]; } #pragma mark - NSLayoutRelation proxies - (MASConstraint * (^)(id))equalTo { return [^id(id attribute) { return self.equalToWithRelation(attribute, NSLayoutRelationEqual); } copy]; } - (MASConstraint * (^)(id))mas_equalTo { return [^id(id attribute) { return self.equalToWithRelation(attribute, NSLayoutRelationEqual); } copy]; } - (MASConstraint * (^)(id))greaterThanOrEqualTo { return [^id(id attribute) { return self.equalToWithRelation(attribute, NSLayoutRelationGreaterThanOrEqual); } copy]; } - (MASConstraint * (^)(id))mas_greaterThanOrEqualTo { return [^id(id attribute) { return self.equalToWithRelation(attribute, NSLayoutRelationGreaterThanOrEqual); } copy]; } - (MASConstraint * (^)(id))lessThanOrEqualTo { return [^id(id attribute) { return self.equalToWithRelation(attribute, NSLayoutRelationLessThanOrEqual); } copy]; } - (MASConstraint * (^)(id))mas_lessThanOrEqualTo { return [^id(id attribute) { return self.equalToWithRelation(attribute, NSLayoutRelationLessThanOrEqual); } copy]; } #pragma mark - MASLayoutPriority proxies - (MASConstraint * (^)(void))priorityLow { return [^id{ self.priority(MASLayoutPriorityDefaultLow); return self; } copy]; } - (MASConstraint * (^)(void))priorityMedium { return [^id{ self.priority(MASLayoutPriorityDefaultMedium); return self; } copy]; } - (MASConstraint * (^)(void))priorityHigh { return [^id{ self.priority(MASLayoutPriorityDefaultHigh); return self; } copy]; } #pragma mark - NSLayoutConstraint constant proxies - (MASConstraint * (^)(MASEdgeInsets))insets { return [^id(MASEdgeInsets insets){ self.insets = insets; return self; } copy]; } - (MASConstraint * (^)(CGFloat))inset { return [^id(CGFloat inset){ self.inset = inset; return self; } copy]; } - (MASConstraint * (^)(CGSize))sizeOffset { return [^id(CGSize offset) { self.sizeOffset = offset; return self; } copy]; } - (MASConstraint * (^)(CGPoint))centerOffset { return [^id(CGPoint offset) { self.centerOffset = offset; return self; } copy]; } - (MASConstraint * (^)(CGFloat))offset { return [^id(CGFloat offset){ self.offset = offset; return self; } copy]; } - (MASConstraint * (^)(NSValue *value))valueOffset { return [^id(NSValue *offset) { NSAssert([offset isKindOfClass:NSValue.class], @"expected an NSValue offset, got: %@", offset); [self setLayoutConstantWithValue:offset]; return self; } copy]; } - (MASConstraint * (^)(id offset))mas_offset { // Will never be called due to macro return nil; } #pragma mark - NSLayoutConstraint constant setter - (void)setLayoutConstantWithValue:(NSValue *)value { if ([value isKindOfClass:NSNumber.class]) { self.offset = [(NSNumber *)value doubleValue]; } else if (strcmp(value.objCType, @encode(CGPoint)) == 0) { CGPoint point; [value getValue:&point]; self.centerOffset = point; } else if (strcmp(value.objCType, @encode(CGSize)) == 0) { CGSize size; [value getValue:&size]; self.sizeOffset = size; } else if (strcmp(value.objCType, @encode(MASEdgeInsets)) == 0) { MASEdgeInsets insets; [value getValue:&insets]; self.insets = insets; } else { NSAssert(NO, @"attempting to set layout constant with unsupported value: %@", value); } } #pragma mark - Semantic properties - (MASConstraint *)with { return self; } - (MASConstraint *)and { return self; } #pragma mark - Chaining - (MASConstraint *)addConstraintWithLayoutAttribute:(NSLayoutAttribute __unused)layoutAttribute { MASMethodNotImplemented(); } - (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 *)firstBaseline { return [self addConstraintWithLayoutAttribute:NSLayoutAttributeFirstBaseline]; } - (MASConstraint *)lastBaseline { return [self addConstraintWithLayoutAttribute:NSLayoutAttributeLastBaseline]; } #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 - Abstract - (MASConstraint * (^)(CGFloat multiplier))multipliedBy { MASMethodNotImplemented(); } - (MASConstraint * (^)(CGFloat divider))dividedBy { MASMethodNotImplemented(); } - (MASConstraint * (^)(MASLayoutPriority priority))priority { MASMethodNotImplemented(); } - (MASConstraint * (^)(id, NSLayoutRelation))equalToWithRelation { MASMethodNotImplemented(); } - (MASConstraint * (^)(id key))key { MASMethodNotImplemented(); } - (void)setInsets:(MASEdgeInsets __unused)insets { MASMethodNotImplemented(); } - (void)setInset:(CGFloat __unused)inset { MASMethodNotImplemented(); } - (void)setSizeOffset:(CGSize __unused)sizeOffset { MASMethodNotImplemented(); } - (void)setCenterOffset:(CGPoint __unused)centerOffset { MASMethodNotImplemented(); } - (void)setOffset:(CGFloat __unused)offset { MASMethodNotImplemented(); } #if TARGET_OS_MAC && !(TARGET_OS_IPHONE || TARGET_OS_TV) - (MASConstraint *)animator { MASMethodNotImplemented(); } #endif - (void)activate { MASMethodNotImplemented(); } - (void)deactivate { MASMethodNotImplemented(); } - (void)install { MASMethodNotImplemented(); } - (void)uninstall { MASMethodNotImplemented(); } @end