// // ASTraitCollection.mm // Texture // // Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. // Changes after 4/13/2017 are: Copyright (c) Pinterest, Inc. All rights reserved. // Licensed under Apache 2.0: http://www.apache.org/licenses/LICENSE-2.0 // #import #import #import #import #import #pragma mark - ASPrimitiveTraitCollection void ASTraitCollectionPropagateDown(id element, ASPrimitiveTraitCollection traitCollection) { if (element) { element.primitiveTraitCollection = traitCollection; } for (id subelement in element.sublayoutElements) { ASTraitCollectionPropagateDown(subelement, traitCollection); } } ASPrimitiveTraitCollection ASPrimitiveTraitCollectionMakeDefault() { ASPrimitiveTraitCollection tc = {}; tc.userInterfaceIdiom = UIUserInterfaceIdiomUnspecified; tc.forceTouchCapability = UIForceTouchCapabilityUnknown; tc.displayScale = 0.0; tc.horizontalSizeClass = UIUserInterfaceSizeClassUnspecified; tc.verticalSizeClass = UIUserInterfaceSizeClassUnspecified; tc.containerSize = CGSizeZero; if (AS_AVAILABLE_IOS(10)) { tc.displayGamut = UIDisplayGamutUnspecified; tc.preferredContentSizeCategory = UIContentSizeCategoryUnspecified; tc.layoutDirection = UITraitEnvironmentLayoutDirectionUnspecified; } #if AS_BUILD_UIUSERINTERFACESTYLE if (AS_AVAILABLE_IOS_TVOS(12, 10)) { tc.userInterfaceStyle = UIUserInterfaceStyleUnspecified; } #endif return tc; } ASPrimitiveTraitCollection ASPrimitiveTraitCollectionFromUITraitCollection(UITraitCollection *traitCollection) { ASPrimitiveTraitCollection environmentTraitCollection = ASPrimitiveTraitCollectionMakeDefault(); environmentTraitCollection.horizontalSizeClass = traitCollection.horizontalSizeClass; environmentTraitCollection.verticalSizeClass = traitCollection.verticalSizeClass; environmentTraitCollection.displayScale = traitCollection.displayScale; environmentTraitCollection.userInterfaceIdiom = traitCollection.userInterfaceIdiom; environmentTraitCollection.forceTouchCapability = traitCollection.forceTouchCapability; if (AS_AVAILABLE_IOS(10)) { environmentTraitCollection.displayGamut = traitCollection.displayGamut; environmentTraitCollection.layoutDirection = traitCollection.layoutDirection; ASDisplayNodeCAssertPermanent(traitCollection.preferredContentSizeCategory); environmentTraitCollection.preferredContentSizeCategory = traitCollection.preferredContentSizeCategory; } #if AS_BUILD_UIUSERINTERFACESTYLE if (AS_AVAILABLE_IOS_TVOS(12, 10)) { environmentTraitCollection.userInterfaceStyle = traitCollection.userInterfaceStyle; } #endif return environmentTraitCollection; } BOOL ASPrimitiveTraitCollectionIsEqualToASPrimitiveTraitCollection(ASPrimitiveTraitCollection lhs, ASPrimitiveTraitCollection rhs) { return !memcmp(&lhs, &rhs, sizeof(ASPrimitiveTraitCollection)); } // Named so as not to conflict with a hidden Apple function, in case compiler decides not to inline ASDISPLAYNODE_INLINE NSString *AS_NSStringFromUIUserInterfaceIdiom(UIUserInterfaceIdiom idiom) { switch (idiom) { case UIUserInterfaceIdiomTV: return @"TV"; case UIUserInterfaceIdiomPad: return @"Pad"; case UIUserInterfaceIdiomPhone: return @"Phone"; case UIUserInterfaceIdiomCarPlay: return @"CarPlay"; default: return @"Unspecified"; } } // Named so as not to conflict with a hidden Apple function, in case compiler decides not to inline ASDISPLAYNODE_INLINE NSString *AS_NSStringFromUIForceTouchCapability(UIForceTouchCapability capability) { switch (capability) { case UIForceTouchCapabilityAvailable: return @"Available"; case UIForceTouchCapabilityUnavailable: return @"Unavailable"; default: return @"Unknown"; } } // Named so as not to conflict with a hidden Apple function, in case compiler decides not to inline ASDISPLAYNODE_INLINE NSString *AS_NSStringFromUIUserInterfaceSizeClass(UIUserInterfaceSizeClass sizeClass) { switch (sizeClass) { case UIUserInterfaceSizeClassCompact: return @"Compact"; case UIUserInterfaceSizeClassRegular: return @"Regular"; default: return @"Unspecified"; } } // Named so as not to conflict with a hidden Apple function, in case compiler decides not to inline API_AVAILABLE(ios(10)) ASDISPLAYNODE_INLINE NSString *AS_NSStringFromUIDisplayGamut(UIDisplayGamut displayGamut) { switch (displayGamut) { case UIDisplayGamutSRGB: return @"sRGB"; case UIDisplayGamutP3: return @"P3"; default: return @"Unspecified"; } } // Named so as not to conflict with a hidden Apple function, in case compiler decides not to inline API_AVAILABLE(ios(10)) ASDISPLAYNODE_INLINE NSString *AS_NSStringFromUITraitEnvironmentLayoutDirection(UITraitEnvironmentLayoutDirection layoutDirection) { switch (layoutDirection) { case UITraitEnvironmentLayoutDirectionLeftToRight: return @"LeftToRight"; case UITraitEnvironmentLayoutDirectionRightToLeft: return @"RightToLeft"; default: return @"Unspecified"; } } // Named so as not to conflict with a hidden Apple function, in case compiler decides not to inline #if AS_BUILD_UIUSERINTERFACESTYLE API_AVAILABLE(tvos(10.0), ios(12.0)) ASDISPLAYNODE_INLINE NSString *AS_NSStringFromUIUserInterfaceStyle(UIUserInterfaceStyle userInterfaceStyle) { switch (userInterfaceStyle) { case UIUserInterfaceStyleLight: return @"Light"; case UIUserInterfaceStyleDark: return @"Dark"; default: return @"Unspecified"; } } #endif NSString *NSStringFromASPrimitiveTraitCollection(ASPrimitiveTraitCollection traits) { NSMutableArray *props = [NSMutableArray array]; [props addObject:@{ @"verticalSizeClass": AS_NSStringFromUIUserInterfaceSizeClass(traits.verticalSizeClass) }]; [props addObject:@{ @"horizontalSizeClass": AS_NSStringFromUIUserInterfaceSizeClass(traits.horizontalSizeClass) }]; [props addObject:@{ @"displayScale": [NSString stringWithFormat: @"%.0lf", (double)traits.displayScale] }]; [props addObject:@{ @"userInterfaceIdiom": AS_NSStringFromUIUserInterfaceIdiom(traits.userInterfaceIdiom) }]; [props addObject:@{ @"forceTouchCapability": AS_NSStringFromUIForceTouchCapability(traits.forceTouchCapability) }]; #if AS_BUILD_UIUSERINTERFACESTYLE if (AS_AVAILABLE_IOS_TVOS(12, 10)) { [props addObject:@{ @"userInterfaceStyle": AS_NSStringFromUIUserInterfaceStyle(traits.userInterfaceStyle) }]; } #endif if (AS_AVAILABLE_IOS(10)) { [props addObject:@{ @"layoutDirection": AS_NSStringFromUITraitEnvironmentLayoutDirection(traits.layoutDirection) }]; [props addObject:@{ @"preferredContentSizeCategory": traits.preferredContentSizeCategory }]; [props addObject:@{ @"displayGamut": AS_NSStringFromUIDisplayGamut(traits.displayGamut) }]; } [props addObject:@{ @"containerSize": NSStringFromCGSize(traits.containerSize) }]; return ASObjectDescriptionMakeWithoutObject(props); } #pragma mark - ASTraitCollection @implementation ASTraitCollection { ASPrimitiveTraitCollection _prim; } + (ASTraitCollection *)traitCollectionWithASPrimitiveTraitCollection:(ASPrimitiveTraitCollection)traits NS_RETURNS_RETAINED { ASTraitCollection *tc = [[ASTraitCollection alloc] init]; if (AS_AVAILABLE_IOS(10)) { ASDisplayNodeCAssertPermanent(traits.preferredContentSizeCategory); } tc->_prim = traits; return tc; } - (ASPrimitiveTraitCollection)primitiveTraitCollection { return _prim; } - (UIUserInterfaceSizeClass)horizontalSizeClass { return _prim.horizontalSizeClass; } -(UIUserInterfaceSizeClass)verticalSizeClass { return _prim.verticalSizeClass; } - (CGFloat)displayScale { return _prim.displayScale; } - (UIDisplayGamut)displayGamut { return _prim.displayGamut; } - (UIForceTouchCapability)forceTouchCapability { return _prim.forceTouchCapability; } - (UITraitEnvironmentLayoutDirection)layoutDirection { return _prim.layoutDirection; } - (CGSize)containerSize { return _prim.containerSize; } #if AS_BUILD_UIUSERINTERFACESTYLE - (UIUserInterfaceStyle)userInterfaceStyle { return _prim.userInterfaceStyle; } #endif - (UIContentSizeCategory)preferredContentSizeCategory { return _prim.preferredContentSizeCategory; } - (NSUInteger)hash { return ASHashBytes(&_prim, sizeof(ASPrimitiveTraitCollection)); } - (BOOL)isEqual:(id)object { if (!object || ![object isKindOfClass:ASTraitCollection.class]) { return NO; } return [self isEqualToTraitCollection:object]; } - (BOOL)isEqualToTraitCollection:(ASTraitCollection *)traitCollection { if (traitCollection == nil) { return NO; } if (self == traitCollection) { return YES; } return ASPrimitiveTraitCollectionIsEqualToASPrimitiveTraitCollection(_prim, traitCollection->_prim); } @end