_ASPendingState.mm 31 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141
  1. //
  2. // _ASPendingState.mm
  3. // AsyncDisplayKit
  4. //
  5. // Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
  6. // This source code is licensed under the BSD-style license found in the
  7. // LICENSE file in the root directory of this source tree. An additional grant
  8. // of patent rights can be found in the PATENTS file in the same directory.
  9. //
  10. #import "_ASPendingState.h"
  11. #import "_ASCoreAnimationExtras.h"
  12. #import "_ASAsyncTransactionContainer.h"
  13. #import "ASAssert.h"
  14. #import "ASInternalHelpers.h"
  15. #import "ASDisplayNodeInternal.h"
  16. #define __shouldSetNeedsDisplay(layer) (flags.needsDisplay \
  17. || (flags.setOpaque && opaque != (layer).opaque)\
  18. || (flags.setBackgroundColor && !CGColorEqualToColor(backgroundColor, (layer).backgroundColor)))
  19. typedef struct {
  20. // Properties
  21. int needsDisplay:1;
  22. int needsLayout:1;
  23. // Flags indicating that a given property should be applied to the view at creation
  24. int setClipsToBounds:1;
  25. int setOpaque:1;
  26. int setNeedsDisplayOnBoundsChange:1;
  27. int setAutoresizesSubviews:1;
  28. int setAutoresizingMask:1;
  29. int setFrame:1;
  30. int setBounds:1;
  31. int setBackgroundColor:1;
  32. int setTintColor:1;
  33. int setContents:1;
  34. int setHidden:1;
  35. int setAlpha:1;
  36. int setCornerRadius:1;
  37. int setContentMode:1;
  38. int setNeedsDisplay:1;
  39. int setAnchorPoint:1;
  40. int setPosition:1;
  41. int setZPosition:1;
  42. int setContentsScale:1;
  43. int setTransform:1;
  44. int setSublayerTransform:1;
  45. int setUserInteractionEnabled:1;
  46. int setExclusiveTouch:1;
  47. int setShadowColor:1;
  48. int setShadowOpacity:1;
  49. int setShadowOffset:1;
  50. int setShadowRadius:1;
  51. int setBorderWidth:1;
  52. int setBorderColor:1;
  53. int setAsyncTransactionContainer:1;
  54. int setAllowsGroupOpacity:1;
  55. int setAllowsEdgeAntialiasing:1;
  56. int setEdgeAntialiasingMask:1;
  57. int setIsAccessibilityElement:1;
  58. int setAccessibilityLabel:1;
  59. int setAccessibilityHint:1;
  60. int setAccessibilityValue:1;
  61. int setAccessibilityTraits:1;
  62. int setAccessibilityFrame:1;
  63. int setAccessibilityLanguage:1;
  64. int setAccessibilityElementsHidden:1;
  65. int setAccessibilityViewIsModal:1;
  66. int setShouldGroupAccessibilityChildren:1;
  67. int setAccessibilityIdentifier:1;
  68. int setAccessibilityNavigationStyle:1;
  69. int setAccessibilityHeaderElements:1;
  70. int setAccessibilityActivationPoint:1;
  71. int setAccessibilityPath:1;
  72. } ASPendingStateFlags;
  73. @implementation _ASPendingState
  74. {
  75. @package //Expose all ivars for ASDisplayNode to bypass getters for efficiency
  76. UIViewAutoresizing autoresizingMask;
  77. unsigned int edgeAntialiasingMask;
  78. CGRect frame; // Frame is only to be used for synchronous views wrapped by nodes (see setFrame:)
  79. CGRect bounds;
  80. CGColorRef backgroundColor;
  81. id contents;
  82. CGFloat alpha;
  83. CGFloat cornerRadius;
  84. UIViewContentMode contentMode;
  85. CGPoint anchorPoint;
  86. CGPoint position;
  87. CGFloat zPosition;
  88. CGFloat contentsScale;
  89. CATransform3D transform;
  90. CATransform3D sublayerTransform;
  91. CGColorRef shadowColor;
  92. CGFloat shadowOpacity;
  93. CGSize shadowOffset;
  94. CGFloat shadowRadius;
  95. CGFloat borderWidth;
  96. CGColorRef borderColor;
  97. BOOL asyncTransactionContainer;
  98. BOOL isAccessibilityElement;
  99. NSString *accessibilityLabel;
  100. NSString *accessibilityHint;
  101. NSString *accessibilityValue;
  102. UIAccessibilityTraits accessibilityTraits;
  103. CGRect accessibilityFrame;
  104. NSString *accessibilityLanguage;
  105. BOOL accessibilityElementsHidden;
  106. BOOL accessibilityViewIsModal;
  107. BOOL shouldGroupAccessibilityChildren;
  108. NSString *accessibilityIdentifier;
  109. UIAccessibilityNavigationStyle accessibilityNavigationStyle;
  110. NSArray *accessibilityHeaderElements;
  111. CGPoint accessibilityActivationPoint;
  112. UIBezierPath *accessibilityPath;
  113. ASPendingStateFlags _flags;
  114. }
  115. /**
  116. * Apply the state's frame, bounds, and position to layer. This will not
  117. * be called on synchronous view-backed nodes which require we directly
  118. * call [view setFrame:].
  119. *
  120. * FIXME: How should we reconcile order-of-operations between setting frame, bounds, position?
  121. * Note we can't read bounds and position in the background, so we have to keep the frame
  122. * value intact until application time (now).
  123. */
  124. ASDISPLAYNODE_INLINE void ASPendingStateApplyMetricsToLayer(_ASPendingState *state, CALayer *layer) {
  125. ASPendingStateFlags flags = state->_flags;
  126. if (flags.setFrame) {
  127. CGRect _bounds = CGRectZero;
  128. CGPoint _position = CGPointZero;
  129. ASBoundsAndPositionForFrame(state->frame, layer.bounds.origin, layer.anchorPoint, &_bounds, &_position);
  130. layer.bounds = _bounds;
  131. layer.position = _position;
  132. } else {
  133. if (flags.setBounds)
  134. layer.bounds = state->bounds;
  135. if (flags.setPosition)
  136. layer.position = state->position;
  137. }
  138. }
  139. @synthesize clipsToBounds=clipsToBounds;
  140. @synthesize opaque=opaque;
  141. @synthesize frame=frame;
  142. @synthesize bounds=bounds;
  143. @synthesize backgroundColor=backgroundColor;
  144. @synthesize contents=contents;
  145. @synthesize hidden=isHidden;
  146. @synthesize needsDisplayOnBoundsChange=needsDisplayOnBoundsChange;
  147. @synthesize allowsGroupOpacity=allowsGroupOpacity;
  148. @synthesize allowsEdgeAntialiasing=allowsEdgeAntialiasing;
  149. @synthesize edgeAntialiasingMask=edgeAntialiasingMask;
  150. @synthesize autoresizesSubviews=autoresizesSubviews;
  151. @synthesize autoresizingMask=autoresizingMask;
  152. @synthesize tintColor=tintColor;
  153. @synthesize alpha=alpha;
  154. @synthesize cornerRadius=cornerRadius;
  155. @synthesize contentMode=contentMode;
  156. @synthesize anchorPoint=anchorPoint;
  157. @synthesize position=position;
  158. @synthesize zPosition=zPosition;
  159. @synthesize contentsScale=contentsScale;
  160. @synthesize transform=transform;
  161. @synthesize sublayerTransform=sublayerTransform;
  162. @synthesize userInteractionEnabled=userInteractionEnabled;
  163. @synthesize exclusiveTouch=exclusiveTouch;
  164. @synthesize shadowColor=shadowColor;
  165. @synthesize shadowOpacity=shadowOpacity;
  166. @synthesize shadowOffset=shadowOffset;
  167. @synthesize shadowRadius=shadowRadius;
  168. @synthesize borderWidth=borderWidth;
  169. @synthesize borderColor=borderColor;
  170. @synthesize asyncdisplaykit_asyncTransactionContainer=asyncTransactionContainer;
  171. static CGColorRef blackColorRef = NULL;
  172. static UIColor *defaultTintColor = nil;
  173. static BOOL defaultAllowsGroupOpacity = YES;
  174. static BOOL defaultAllowsEdgeAntialiasing = NO;
  175. + (void)load
  176. {
  177. // Create temporary view to read default values that are based on linked SDK and Info.plist values
  178. // Ensure this values cached on the main thread before needed
  179. ASDisplayNodeCAssertMainThread();
  180. UIView *view = [[UIView alloc] init];
  181. defaultAllowsGroupOpacity = view.layer.allowsGroupOpacity;
  182. defaultAllowsEdgeAntialiasing = view.layer.allowsEdgeAntialiasing;
  183. }
  184. - (instancetype)init
  185. {
  186. if (!(self = [super init]))
  187. return nil;
  188. static dispatch_once_t onceToken;
  189. dispatch_once(&onceToken, ^{
  190. // Default UIKit color is an RGB color
  191. CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
  192. blackColorRef = CGColorCreate(colorSpace, (CGFloat[]){0,0,0,1} );
  193. CFRetain(blackColorRef);
  194. CGColorSpaceRelease(colorSpace);
  195. defaultTintColor = [UIColor colorWithRed:0.0 green:0.478 blue:1.0 alpha:1.0];
  196. });
  197. // Set defaults, these come from the defaults specified in CALayer and UIView
  198. clipsToBounds = NO;
  199. opaque = YES;
  200. frame = CGRectZero;
  201. bounds = CGRectZero;
  202. backgroundColor = nil;
  203. tintColor = defaultTintColor;
  204. contents = nil;
  205. isHidden = NO;
  206. needsDisplayOnBoundsChange = NO;
  207. allowsGroupOpacity = defaultAllowsGroupOpacity;
  208. allowsEdgeAntialiasing = defaultAllowsEdgeAntialiasing;
  209. autoresizesSubviews = YES;
  210. alpha = 1.0f;
  211. cornerRadius = 0.0f;
  212. contentMode = UIViewContentModeScaleToFill;
  213. _flags.needsDisplay = NO;
  214. anchorPoint = CGPointMake(0.5, 0.5);
  215. position = CGPointZero;
  216. zPosition = 0.0;
  217. contentsScale = 1.0f;
  218. transform = CATransform3DIdentity;
  219. sublayerTransform = CATransform3DIdentity;
  220. userInteractionEnabled = YES;
  221. shadowColor = blackColorRef;
  222. shadowOpacity = 0.0;
  223. shadowOffset = CGSizeMake(0, -3);
  224. shadowRadius = 3;
  225. borderWidth = 0;
  226. borderColor = blackColorRef;
  227. isAccessibilityElement = NO;
  228. accessibilityLabel = nil;
  229. accessibilityHint = nil;
  230. accessibilityValue = nil;
  231. accessibilityTraits = UIAccessibilityTraitNone;
  232. accessibilityFrame = CGRectZero;
  233. accessibilityLanguage = nil;
  234. accessibilityElementsHidden = NO;
  235. accessibilityViewIsModal = NO;
  236. shouldGroupAccessibilityChildren = NO;
  237. accessibilityIdentifier = nil;
  238. accessibilityNavigationStyle = UIAccessibilityNavigationStyleAutomatic;
  239. accessibilityHeaderElements = nil;
  240. accessibilityActivationPoint = CGPointZero;
  241. accessibilityPath = nil;
  242. edgeAntialiasingMask = (kCALayerLeftEdge | kCALayerRightEdge | kCALayerTopEdge | kCALayerBottomEdge);
  243. return self;
  244. }
  245. - (void)setNeedsDisplay
  246. {
  247. _flags.needsDisplay = YES;
  248. }
  249. - (void)setNeedsLayout
  250. {
  251. _flags.needsLayout = YES;
  252. }
  253. - (void)setClipsToBounds:(BOOL)flag
  254. {
  255. clipsToBounds = flag;
  256. _flags.setClipsToBounds = YES;
  257. }
  258. - (void)setOpaque:(BOOL)flag
  259. {
  260. opaque = flag;
  261. _flags.setOpaque = YES;
  262. }
  263. - (void)setNeedsDisplayOnBoundsChange:(BOOL)flag
  264. {
  265. needsDisplayOnBoundsChange = flag;
  266. _flags.setNeedsDisplayOnBoundsChange = YES;
  267. }
  268. - (void)setAllowsGroupOpacity:(BOOL)flag
  269. {
  270. allowsGroupOpacity = flag;
  271. _flags.setAllowsGroupOpacity = YES;
  272. }
  273. - (void)setAllowsEdgeAntialiasing:(BOOL)flag
  274. {
  275. allowsEdgeAntialiasing = flag;
  276. _flags.setAllowsEdgeAntialiasing = YES;
  277. }
  278. - (void)setEdgeAntialiasingMask:(unsigned int)mask
  279. {
  280. edgeAntialiasingMask = mask;
  281. _flags.setEdgeAntialiasingMask = YES;
  282. }
  283. - (void)setAutoresizesSubviews:(BOOL)flag
  284. {
  285. autoresizesSubviews = flag;
  286. _flags.setAutoresizesSubviews = YES;
  287. }
  288. - (void)setAutoresizingMask:(UIViewAutoresizing)mask
  289. {
  290. autoresizingMask = mask;
  291. _flags.setAutoresizingMask = YES;
  292. }
  293. - (void)setFrame:(CGRect)newFrame
  294. {
  295. frame = newFrame;
  296. _flags.setFrame = YES;
  297. }
  298. - (void)setBounds:(CGRect)newBounds
  299. {
  300. ASDisplayNodeAssert(!isnan(newBounds.size.width) && !isnan(newBounds.size.height), @"Invalid bounds %@ provided to %@", NSStringFromCGRect(newBounds), self);
  301. if (isnan(newBounds.size.width))
  302. newBounds.size.width = 0.0;
  303. if (isnan(newBounds.size.height))
  304. newBounds.size.height = 0.0;
  305. bounds = newBounds;
  306. _flags.setBounds = YES;
  307. }
  308. - (CGColorRef)backgroundColor
  309. {
  310. return backgroundColor;
  311. }
  312. - (void)setBackgroundColor:(CGColorRef)color
  313. {
  314. if (color == backgroundColor) {
  315. return;
  316. }
  317. CGColorRelease(backgroundColor);
  318. backgroundColor = CGColorRetain(color);
  319. _flags.setBackgroundColor = YES;
  320. }
  321. - (void)setTintColor:(UIColor *)newTintColor
  322. {
  323. tintColor = newTintColor;
  324. _flags.setTintColor = YES;
  325. }
  326. - (void)setContents:(id)newContents
  327. {
  328. if (contents == newContents) {
  329. return;
  330. }
  331. contents = newContents;
  332. _flags.setContents = YES;
  333. }
  334. - (void)setHidden:(BOOL)flag
  335. {
  336. isHidden = flag;
  337. _flags.setHidden = YES;
  338. }
  339. - (void)setAlpha:(CGFloat)newAlpha
  340. {
  341. alpha = newAlpha;
  342. _flags.setAlpha = YES;
  343. }
  344. - (void)setCornerRadius:(CGFloat)newCornerRadius
  345. {
  346. cornerRadius = newCornerRadius;
  347. _flags.setCornerRadius = YES;
  348. }
  349. - (void)setContentMode:(UIViewContentMode)newContentMode
  350. {
  351. contentMode = newContentMode;
  352. _flags.setContentMode = YES;
  353. }
  354. - (void)setAnchorPoint:(CGPoint)newAnchorPoint
  355. {
  356. anchorPoint = newAnchorPoint;
  357. _flags.setAnchorPoint = YES;
  358. }
  359. - (void)setPosition:(CGPoint)newPosition
  360. {
  361. ASDisplayNodeAssert(!isnan(newPosition.x) && !isnan(newPosition.y), @"Invalid position %@ provided to %@", NSStringFromCGPoint(newPosition), self);
  362. if (isnan(newPosition.x))
  363. newPosition.x = 0.0;
  364. if (isnan(newPosition.y))
  365. newPosition.y = 0.0;
  366. position = newPosition;
  367. _flags.setPosition = YES;
  368. }
  369. - (void)setZPosition:(CGFloat)newPosition
  370. {
  371. zPosition = newPosition;
  372. _flags.setZPosition = YES;
  373. }
  374. - (void)setContentsScale:(CGFloat)newContentsScale
  375. {
  376. contentsScale = newContentsScale;
  377. _flags.setContentsScale = YES;
  378. }
  379. - (void)setTransform:(CATransform3D)newTransform
  380. {
  381. transform = newTransform;
  382. _flags.setTransform = YES;
  383. }
  384. - (void)setSublayerTransform:(CATransform3D)newSublayerTransform
  385. {
  386. sublayerTransform = newSublayerTransform;
  387. _flags.setSublayerTransform = YES;
  388. }
  389. - (void)setUserInteractionEnabled:(BOOL)flag
  390. {
  391. userInteractionEnabled = flag;
  392. _flags.setUserInteractionEnabled = YES;
  393. }
  394. - (void)setExclusiveTouch:(BOOL)flag
  395. {
  396. exclusiveTouch = flag;
  397. _flags.setExclusiveTouch = YES;
  398. }
  399. - (void)setShadowColor:(CGColorRef)color
  400. {
  401. if (shadowColor == color) {
  402. return;
  403. }
  404. if (shadowColor != blackColorRef) {
  405. CGColorRelease(shadowColor);
  406. }
  407. shadowColor = color;
  408. CGColorRetain(shadowColor);
  409. _flags.setShadowColor = YES;
  410. }
  411. - (void)setShadowOpacity:(CGFloat)newOpacity
  412. {
  413. shadowOpacity = newOpacity;
  414. _flags.setShadowOpacity = YES;
  415. }
  416. - (void)setShadowOffset:(CGSize)newOffset
  417. {
  418. shadowOffset = newOffset;
  419. _flags.setShadowOffset = YES;
  420. }
  421. - (void)setShadowRadius:(CGFloat)newRadius
  422. {
  423. shadowRadius = newRadius;
  424. _flags.setShadowRadius = YES;
  425. }
  426. - (void)setBorderWidth:(CGFloat)newWidth
  427. {
  428. borderWidth = newWidth;
  429. _flags.setBorderWidth = YES;
  430. }
  431. - (void)setBorderColor:(CGColorRef)color
  432. {
  433. if (borderColor == color) {
  434. return;
  435. }
  436. if (borderColor != blackColorRef) {
  437. CGColorRelease(borderColor);
  438. }
  439. borderColor = color;
  440. CGColorRetain(borderColor);
  441. _flags.setBorderColor = YES;
  442. }
  443. - (void)asyncdisplaykit_setAsyncTransactionContainer:(BOOL)flag
  444. {
  445. asyncTransactionContainer = flag;
  446. _flags.setAsyncTransactionContainer = YES;
  447. }
  448. - (BOOL)isAccessibilityElement
  449. {
  450. return isAccessibilityElement;
  451. }
  452. - (void)setIsAccessibilityElement:(BOOL)newIsAccessibilityElement
  453. {
  454. isAccessibilityElement = newIsAccessibilityElement;
  455. _flags.setIsAccessibilityElement = YES;
  456. }
  457. - (NSString *)accessibilityLabel
  458. {
  459. return accessibilityLabel;
  460. }
  461. - (void)setAccessibilityLabel:(NSString *)newAccessibilityLabel
  462. {
  463. _flags.setAccessibilityLabel = YES;
  464. if (accessibilityLabel != newAccessibilityLabel) {
  465. accessibilityLabel = [newAccessibilityLabel copy];
  466. }
  467. }
  468. - (NSString *)accessibilityHint
  469. {
  470. return accessibilityHint;
  471. }
  472. - (void)setAccessibilityHint:(NSString *)newAccessibilityHint
  473. {
  474. _flags.setAccessibilityHint = YES;
  475. accessibilityHint = [newAccessibilityHint copy];
  476. }
  477. - (NSString *)accessibilityValue
  478. {
  479. return accessibilityValue;
  480. }
  481. - (void)setAccessibilityValue:(NSString *)newAccessibilityValue
  482. {
  483. _flags.setAccessibilityValue = YES;
  484. accessibilityValue = [newAccessibilityValue copy];
  485. }
  486. - (UIAccessibilityTraits)accessibilityTraits
  487. {
  488. return accessibilityTraits;
  489. }
  490. - (void)setAccessibilityTraits:(UIAccessibilityTraits)newAccessibilityTraits
  491. {
  492. accessibilityTraits = newAccessibilityTraits;
  493. _flags.setAccessibilityTraits = YES;
  494. }
  495. - (CGRect)accessibilityFrame
  496. {
  497. return accessibilityFrame;
  498. }
  499. - (void)setAccessibilityFrame:(CGRect)newAccessibilityFrame
  500. {
  501. accessibilityFrame = newAccessibilityFrame;
  502. _flags.setAccessibilityFrame = YES;
  503. }
  504. - (NSString *)accessibilityLanguage
  505. {
  506. return accessibilityLanguage;
  507. }
  508. - (void)setAccessibilityLanguage:(NSString *)newAccessibilityLanguage
  509. {
  510. _flags.setAccessibilityLanguage = YES;
  511. accessibilityLanguage = newAccessibilityLanguage;
  512. }
  513. - (BOOL)accessibilityElementsHidden
  514. {
  515. return accessibilityElementsHidden;
  516. }
  517. - (void)setAccessibilityElementsHidden:(BOOL)newAccessibilityElementsHidden
  518. {
  519. accessibilityElementsHidden = newAccessibilityElementsHidden;
  520. _flags.setAccessibilityElementsHidden = YES;
  521. }
  522. - (BOOL)accessibilityViewIsModal
  523. {
  524. return accessibilityViewIsModal;
  525. }
  526. - (void)setAccessibilityViewIsModal:(BOOL)newAccessibilityViewIsModal
  527. {
  528. accessibilityViewIsModal = newAccessibilityViewIsModal;
  529. _flags.setAccessibilityViewIsModal = YES;
  530. }
  531. - (BOOL)shouldGroupAccessibilityChildren
  532. {
  533. return shouldGroupAccessibilityChildren;
  534. }
  535. - (void)setShouldGroupAccessibilityChildren:(BOOL)newShouldGroupAccessibilityChildren
  536. {
  537. shouldGroupAccessibilityChildren = newShouldGroupAccessibilityChildren;
  538. _flags.setShouldGroupAccessibilityChildren = YES;
  539. }
  540. - (NSString *)accessibilityIdentifier
  541. {
  542. return accessibilityIdentifier;
  543. }
  544. - (void)setAccessibilityIdentifier:(NSString *)newAccessibilityIdentifier
  545. {
  546. _flags.setAccessibilityIdentifier = YES;
  547. if (accessibilityIdentifier != newAccessibilityIdentifier) {
  548. accessibilityIdentifier = [newAccessibilityIdentifier copy];
  549. }
  550. }
  551. - (UIAccessibilityNavigationStyle)accessibilityNavigationStyle
  552. {
  553. return accessibilityNavigationStyle;
  554. }
  555. - (void)setAccessibilityNavigationStyle:(UIAccessibilityNavigationStyle)newAccessibilityNavigationStyle
  556. {
  557. _flags.setAccessibilityNavigationStyle = YES;
  558. accessibilityNavigationStyle = newAccessibilityNavigationStyle;
  559. }
  560. - (NSArray *)accessibilityHeaderElements
  561. {
  562. return accessibilityHeaderElements;
  563. }
  564. - (void)setAccessibilityHeaderElements:(NSArray *)newAccessibilityHeaderElements
  565. {
  566. _flags.setAccessibilityHeaderElements = YES;
  567. if (accessibilityHeaderElements != newAccessibilityHeaderElements) {
  568. accessibilityHeaderElements = [newAccessibilityHeaderElements copy];
  569. }
  570. }
  571. - (CGPoint)accessibilityActivationPoint
  572. {
  573. if (_flags.setAccessibilityActivationPoint) {
  574. return accessibilityActivationPoint;
  575. }
  576. // Default == Mid-point of the accessibilityFrame
  577. return CGPointMake(CGRectGetMidX(accessibilityFrame), CGRectGetMidY(accessibilityFrame));
  578. }
  579. - (void)setAccessibilityActivationPoint:(CGPoint)newAccessibilityActivationPoint
  580. {
  581. _flags.setAccessibilityActivationPoint = YES;
  582. accessibilityActivationPoint = newAccessibilityActivationPoint;
  583. }
  584. - (UIBezierPath *)accessibilityPath
  585. {
  586. return accessibilityPath;
  587. }
  588. - (void)setAccessibilityPath:(UIBezierPath *)newAccessibilityPath
  589. {
  590. _flags.setAccessibilityPath = YES;
  591. if (accessibilityPath != newAccessibilityPath) {
  592. accessibilityPath = newAccessibilityPath;
  593. }
  594. }
  595. - (void)applyToLayer:(CALayer *)layer
  596. {
  597. ASPendingStateFlags flags = _flags;
  598. if (__shouldSetNeedsDisplay(layer)) {
  599. [layer setNeedsDisplay];
  600. }
  601. if (flags.setAnchorPoint)
  602. layer.anchorPoint = anchorPoint;
  603. if (flags.setZPosition)
  604. layer.zPosition = zPosition;
  605. if (flags.setContentsScale)
  606. layer.contentsScale = contentsScale;
  607. if (flags.setTransform)
  608. layer.transform = transform;
  609. if (flags.setSublayerTransform)
  610. layer.sublayerTransform = sublayerTransform;
  611. if (flags.setContents)
  612. layer.contents = contents;
  613. if (flags.setClipsToBounds)
  614. layer.masksToBounds = clipsToBounds;
  615. if (flags.setBackgroundColor)
  616. layer.backgroundColor = backgroundColor;
  617. if (flags.setOpaque)
  618. layer.opaque = opaque;
  619. if (flags.setHidden)
  620. layer.hidden = isHidden;
  621. if (flags.setAlpha)
  622. layer.opacity = alpha;
  623. if (flags.setCornerRadius)
  624. layer.cornerRadius = cornerRadius;
  625. if (flags.setContentMode)
  626. layer.contentsGravity = ASDisplayNodeCAContentsGravityFromUIContentMode(contentMode);
  627. if (flags.setShadowColor)
  628. layer.shadowColor = shadowColor;
  629. if (flags.setShadowOpacity)
  630. layer.shadowOpacity = shadowOpacity;
  631. if (flags.setShadowOffset)
  632. layer.shadowOffset = shadowOffset;
  633. if (flags.setShadowRadius)
  634. layer.shadowRadius = shadowRadius;
  635. if (flags.setBorderWidth)
  636. layer.borderWidth = borderWidth;
  637. if (flags.setBorderColor)
  638. layer.borderColor = borderColor;
  639. if (flags.setNeedsDisplayOnBoundsChange)
  640. layer.needsDisplayOnBoundsChange = needsDisplayOnBoundsChange;
  641. if (flags.setAllowsGroupOpacity)
  642. layer.allowsGroupOpacity = allowsGroupOpacity;
  643. if (flags.setAllowsEdgeAntialiasing)
  644. layer.allowsEdgeAntialiasing = allowsEdgeAntialiasing;
  645. if (flags.setEdgeAntialiasingMask)
  646. layer.edgeAntialiasingMask = edgeAntialiasingMask;
  647. if (flags.needsLayout)
  648. [layer setNeedsLayout];
  649. if (flags.setAsyncTransactionContainer)
  650. layer.asyncdisplaykit_asyncTransactionContainer = asyncTransactionContainer;
  651. if (flags.setOpaque)
  652. ASDisplayNodeAssert(layer.opaque == opaque, @"Didn't set opaque as desired");
  653. ASPendingStateApplyMetricsToLayer(self, layer);
  654. }
  655. - (void)applyToView:(UIView *)view withSpecialPropertiesHandling:(BOOL)specialPropertiesHandling
  656. {
  657. /*
  658. Use our convenience setters blah here instead of layer.blah
  659. We were accidentally setting some properties on layer here, but view in UIViewBridgeOptimizations.
  660. That could easily cause bugs where it mattered whether you set something up on a bg thread on in -didLoad
  661. because a different setter would be called.
  662. */
  663. CALayer *layer = view.layer;
  664. ASPendingStateFlags flags = _flags;
  665. if (__shouldSetNeedsDisplay(layer)) {
  666. [view setNeedsDisplay];
  667. }
  668. if (flags.setAnchorPoint)
  669. layer.anchorPoint = anchorPoint;
  670. if (flags.setPosition)
  671. layer.position = position;
  672. if (flags.setZPosition)
  673. layer.zPosition = zPosition;
  674. if (flags.setBounds)
  675. view.bounds = bounds;
  676. if (flags.setContentsScale)
  677. layer.contentsScale = contentsScale;
  678. if (flags.setTransform)
  679. layer.transform = transform;
  680. if (flags.setSublayerTransform)
  681. layer.sublayerTransform = sublayerTransform;
  682. if (flags.setContents)
  683. layer.contents = contents;
  684. if (flags.setClipsToBounds)
  685. view.clipsToBounds = clipsToBounds;
  686. if (flags.setBackgroundColor) {
  687. // We have to make sure certain nodes get the background color call directly set
  688. if (specialPropertiesHandling) {
  689. view.backgroundColor = [UIColor colorWithCGColor:backgroundColor];
  690. } else {
  691. // Set the background color to the layer as in the UIView bridge we use this value as background color
  692. layer.backgroundColor = backgroundColor;
  693. }
  694. }
  695. if (flags.setTintColor)
  696. view.tintColor = self.tintColor;
  697. if (flags.setOpaque)
  698. view.layer.opaque = opaque;
  699. if (flags.setHidden)
  700. view.hidden = isHidden;
  701. if (flags.setAlpha)
  702. view.alpha = alpha;
  703. if (flags.setCornerRadius)
  704. layer.cornerRadius = cornerRadius;
  705. if (flags.setContentMode)
  706. view.contentMode = contentMode;
  707. if (flags.setUserInteractionEnabled)
  708. view.userInteractionEnabled = userInteractionEnabled;
  709. #if TARGET_OS_IOS
  710. if (flags.setExclusiveTouch)
  711. view.exclusiveTouch = exclusiveTouch;
  712. #endif
  713. if (flags.setShadowColor)
  714. layer.shadowColor = shadowColor;
  715. if (flags.setShadowOpacity)
  716. layer.shadowOpacity = shadowOpacity;
  717. if (flags.setShadowOffset)
  718. layer.shadowOffset = shadowOffset;
  719. if (flags.setShadowRadius)
  720. layer.shadowRadius = shadowRadius;
  721. if (flags.setBorderWidth)
  722. layer.borderWidth = borderWidth;
  723. if (flags.setBorderColor)
  724. layer.borderColor = borderColor;
  725. if (flags.setAutoresizingMask)
  726. view.autoresizingMask = autoresizingMask;
  727. if (flags.setAutoresizesSubviews)
  728. view.autoresizesSubviews = autoresizesSubviews;
  729. if (flags.setNeedsDisplayOnBoundsChange)
  730. layer.needsDisplayOnBoundsChange = needsDisplayOnBoundsChange;
  731. if (flags.setAllowsGroupOpacity)
  732. layer.allowsGroupOpacity = allowsGroupOpacity;
  733. if (flags.setAllowsEdgeAntialiasing)
  734. layer.allowsEdgeAntialiasing = allowsEdgeAntialiasing;
  735. if (flags.setEdgeAntialiasingMask)
  736. layer.edgeAntialiasingMask = edgeAntialiasingMask;
  737. if (flags.needsLayout)
  738. [view setNeedsLayout];
  739. if (flags.setAsyncTransactionContainer)
  740. view.asyncdisplaykit_asyncTransactionContainer = asyncTransactionContainer;
  741. if (flags.setOpaque)
  742. ASDisplayNodeAssert(view.layer.opaque == opaque, @"Didn't set opaque as desired");
  743. if (flags.setIsAccessibilityElement)
  744. view.isAccessibilityElement = isAccessibilityElement;
  745. if (flags.setAccessibilityLabel)
  746. view.accessibilityLabel = accessibilityLabel;
  747. if (flags.setAccessibilityHint)
  748. view.accessibilityHint = accessibilityHint;
  749. if (flags.setAccessibilityValue)
  750. view.accessibilityValue = accessibilityValue;
  751. if (flags.setAccessibilityTraits)
  752. view.accessibilityTraits = accessibilityTraits;
  753. if (flags.setAccessibilityFrame)
  754. view.accessibilityFrame = accessibilityFrame;
  755. if (flags.setAccessibilityLanguage)
  756. view.accessibilityLanguage = accessibilityLanguage;
  757. if (flags.setAccessibilityElementsHidden)
  758. view.accessibilityElementsHidden = accessibilityElementsHidden;
  759. if (flags.setAccessibilityViewIsModal)
  760. view.accessibilityViewIsModal = accessibilityViewIsModal;
  761. if (flags.setShouldGroupAccessibilityChildren)
  762. view.shouldGroupAccessibilityChildren = shouldGroupAccessibilityChildren;
  763. if (flags.setAccessibilityIdentifier)
  764. view.accessibilityIdentifier = accessibilityIdentifier;
  765. if (flags.setAccessibilityNavigationStyle)
  766. view.accessibilityNavigationStyle = accessibilityNavigationStyle;
  767. #if TARGET_OS_TV
  768. if (flags.setAccessibilityHeaderElements)
  769. view.accessibilityHeaderElements = accessibilityHeaderElements;
  770. #endif
  771. if (flags.setAccessibilityActivationPoint)
  772. view.accessibilityActivationPoint = accessibilityActivationPoint;
  773. if (flags.setAccessibilityPath)
  774. view.accessibilityPath = accessibilityPath;
  775. if (flags.setFrame && specialPropertiesHandling) {
  776. // Frame is only defined when transform is identity because we explicitly diverge from CALayer behavior and define frame without transform
  777. //#if DEBUG
  778. // // Checking if the transform is identity is expensive, so disable when unnecessary. We have assertions on in Release, so DEBUG is the only way I know of.
  779. // ASDisplayNodeAssert(CATransform3DIsIdentity(layer.transform), @"-[ASDisplayNode setFrame:] - self.transform must be identity in order to set the frame property. (From Apple's UIView documentation: If the transform property is not the identity transform, the value of this property is undefined and therefore should be ignored.)");
  780. //#endif
  781. view.frame = frame;
  782. } else {
  783. ASPendingStateApplyMetricsToLayer(self, layer);
  784. }
  785. }
  786. // FIXME: Make this more efficient by tracking which properties are set rather than reading everything.
  787. + (_ASPendingState *)pendingViewStateFromLayer:(CALayer *)layer
  788. {
  789. if (!layer) {
  790. return nil;
  791. }
  792. _ASPendingState *pendingState = [[_ASPendingState alloc] init];
  793. pendingState.anchorPoint = layer.anchorPoint;
  794. pendingState.position = layer.position;
  795. pendingState.zPosition = layer.zPosition;
  796. pendingState.bounds = layer.bounds;
  797. pendingState.contentsScale = layer.contentsScale;
  798. pendingState.transform = layer.transform;
  799. pendingState.sublayerTransform = layer.sublayerTransform;
  800. pendingState.contents = layer.contents;
  801. pendingState.clipsToBounds = layer.masksToBounds;
  802. pendingState.backgroundColor = layer.backgroundColor;
  803. pendingState.opaque = layer.opaque;
  804. pendingState.hidden = layer.hidden;
  805. pendingState.alpha = layer.opacity;
  806. pendingState.cornerRadius = layer.cornerRadius;
  807. pendingState.contentMode = ASDisplayNodeUIContentModeFromCAContentsGravity(layer.contentsGravity);
  808. pendingState.shadowColor = layer.shadowColor;
  809. pendingState.shadowOpacity = layer.shadowOpacity;
  810. pendingState.shadowOffset = layer.shadowOffset;
  811. pendingState.shadowRadius = layer.shadowRadius;
  812. pendingState.borderWidth = layer.borderWidth;
  813. pendingState.borderColor = layer.borderColor;
  814. pendingState.needsDisplayOnBoundsChange = layer.needsDisplayOnBoundsChange;
  815. pendingState.allowsGroupOpacity = layer.allowsGroupOpacity;
  816. pendingState.allowsEdgeAntialiasing = layer.allowsEdgeAntialiasing;
  817. pendingState.edgeAntialiasingMask = layer.edgeAntialiasingMask;
  818. return pendingState;
  819. }
  820. // FIXME: Make this more efficient by tracking which properties are set rather than reading everything.
  821. + (_ASPendingState *)pendingViewStateFromView:(UIView *)view
  822. {
  823. if (!view) {
  824. return nil;
  825. }
  826. _ASPendingState *pendingState = [[_ASPendingState alloc] init];
  827. CALayer *layer = view.layer;
  828. pendingState.anchorPoint = layer.anchorPoint;
  829. pendingState.position = layer.position;
  830. pendingState.zPosition = layer.zPosition;
  831. pendingState.bounds = view.bounds;
  832. pendingState.contentsScale = layer.contentsScale;
  833. pendingState.transform = layer.transform;
  834. pendingState.sublayerTransform = layer.sublayerTransform;
  835. pendingState.contents = layer.contents;
  836. pendingState.clipsToBounds = view.clipsToBounds;
  837. pendingState.backgroundColor = layer.backgroundColor;
  838. pendingState.tintColor = view.tintColor;
  839. pendingState.opaque = layer.opaque;
  840. pendingState.hidden = view.hidden;
  841. pendingState.alpha = view.alpha;
  842. pendingState.cornerRadius = layer.cornerRadius;
  843. pendingState.contentMode = view.contentMode;
  844. pendingState.userInteractionEnabled = view.userInteractionEnabled;
  845. #if TARGET_OS_IOS
  846. pendingState.exclusiveTouch = view.exclusiveTouch;
  847. #endif
  848. pendingState.shadowColor = layer.shadowColor;
  849. pendingState.shadowOpacity = layer.shadowOpacity;
  850. pendingState.shadowOffset = layer.shadowOffset;
  851. pendingState.shadowRadius = layer.shadowRadius;
  852. pendingState.borderWidth = layer.borderWidth;
  853. pendingState.borderColor = layer.borderColor;
  854. pendingState.autoresizingMask = view.autoresizingMask;
  855. pendingState.autoresizesSubviews = view.autoresizesSubviews;
  856. pendingState.needsDisplayOnBoundsChange = layer.needsDisplayOnBoundsChange;
  857. pendingState.allowsGroupOpacity = layer.allowsGroupOpacity;
  858. pendingState.allowsEdgeAntialiasing = layer.allowsEdgeAntialiasing;
  859. pendingState.edgeAntialiasingMask = layer.edgeAntialiasingMask;
  860. pendingState.isAccessibilityElement = view.isAccessibilityElement;
  861. pendingState.accessibilityLabel = view.accessibilityLabel;
  862. pendingState.accessibilityHint = view.accessibilityHint;
  863. pendingState.accessibilityValue = view.accessibilityValue;
  864. pendingState.accessibilityTraits = view.accessibilityTraits;
  865. pendingState.accessibilityFrame = view.accessibilityFrame;
  866. pendingState.accessibilityLanguage = view.accessibilityLanguage;
  867. pendingState.accessibilityElementsHidden = view.accessibilityElementsHidden;
  868. pendingState.accessibilityViewIsModal = view.accessibilityViewIsModal;
  869. pendingState.shouldGroupAccessibilityChildren = view.shouldGroupAccessibilityChildren;
  870. pendingState.accessibilityIdentifier = view.accessibilityIdentifier;
  871. pendingState.accessibilityNavigationStyle = view.accessibilityNavigationStyle;
  872. #if TARGET_OS_TV
  873. pendingState.accessibilityHeaderElements = view.accessibilityHeaderElements;
  874. #endif
  875. pendingState.accessibilityActivationPoint = view.accessibilityActivationPoint;
  876. pendingState.accessibilityPath = view.accessibilityPath;
  877. return pendingState;
  878. }
  879. - (void)clearChanges
  880. {
  881. _flags = (ASPendingStateFlags){ 0 };
  882. }
  883. - (BOOL)hasSetNeedsLayout
  884. {
  885. return _flags.needsLayout;
  886. }
  887. - (BOOL)hasSetNeedsDisplay
  888. {
  889. return _flags.needsDisplay;
  890. }
  891. - (BOOL)hasChanges
  892. {
  893. ASPendingStateFlags flags = _flags;
  894. return (flags.setAnchorPoint
  895. || flags.setPosition
  896. || flags.setZPosition
  897. || flags.setFrame
  898. || flags.setBounds
  899. || flags.setPosition
  900. || flags.setContentsScale
  901. || flags.setTransform
  902. || flags.setSublayerTransform
  903. || flags.setContents
  904. || flags.setClipsToBounds
  905. || flags.setBackgroundColor
  906. || flags.setTintColor
  907. || flags.setHidden
  908. || flags.setAlpha
  909. || flags.setCornerRadius
  910. || flags.setContentMode
  911. || flags.setUserInteractionEnabled
  912. || flags.setExclusiveTouch
  913. || flags.setShadowOpacity
  914. || flags.setShadowOffset
  915. || flags.setShadowRadius
  916. || flags.setShadowColor
  917. || flags.setBorderWidth
  918. || flags.setBorderColor
  919. || flags.setAutoresizingMask
  920. || flags.setAutoresizesSubviews
  921. || flags.setNeedsDisplayOnBoundsChange
  922. || flags.setAllowsGroupOpacity
  923. || flags.setAllowsEdgeAntialiasing
  924. || flags.setEdgeAntialiasingMask
  925. || flags.needsDisplay
  926. || flags.needsLayout
  927. || flags.setAsyncTransactionContainer
  928. || flags.setOpaque
  929. || flags.setIsAccessibilityElement
  930. || flags.setAccessibilityLabel
  931. || flags.setAccessibilityHint
  932. || flags.setAccessibilityValue
  933. || flags.setAccessibilityTraits
  934. || flags.setAccessibilityFrame
  935. || flags.setAccessibilityLanguage
  936. || flags.setAccessibilityElementsHidden
  937. || flags.setAccessibilityViewIsModal
  938. || flags.setShouldGroupAccessibilityChildren
  939. || flags.setAccessibilityIdentifier
  940. || flags.setAccessibilityNavigationStyle
  941. || flags.setAccessibilityHeaderElements
  942. || flags.setAccessibilityActivationPoint
  943. || flags.setAccessibilityPath);
  944. }
  945. - (void)dealloc
  946. {
  947. CGColorRelease(backgroundColor);
  948. if (shadowColor != blackColorRef) {
  949. CGColorRelease(shadowColor);
  950. }
  951. if (borderColor != blackColorRef) {
  952. CGColorRelease(borderColor);
  953. }
  954. }
  955. @end