Swiftgram/AsyncDisplayKit/Private/ASDisplayNode+FrameworkPrivate.h
appleguy 55b5dff80c [ASLayoutSpec] Initial commit to support visualizing layout specs (with Playground app). (#2554)
* Initial ASLayoutSpecPlayground commit

* Initial exploratory stab at the main challenge of the app - visualizing ASLayoutSpecs

* Halfway through moving debug features out of ASDK framework files and into debug files. Project builds.

* [ASLayoutSpecPlayground] Created new Inspector node, cleaning up internal implementation to start formalizing support for layout spec visualization.

* Workaround for ensuring creation of visualizerNode for ALL layoutspecs

* continued development

* Layout Inspector Work in Progress

* Resizing the playground works in the shrink direction, not for grow.

* added new ASLayoutableInspectorNode features

* Cleaned up examples code.

* Cleaning up  code.

* more code cleanup

* [ASLayoutableInspector] Transition to an ASTableNode-based architecture to support larger numbers of buttons / customizable types.

* [ASLayoutableInspector] Support different layoutable property types to set up buttons that can edit all of them.

* Huy debugging

* Refactored layout inspector code for extensibility.

* Properly lock layoutableContextMap

* Fix context handling in ASDisplayNode:measureWithSizeRange

* Fix ASLayoutSpecPlayground:ViewController:toggleVisualization

* added slider to InspectorCell

* [ASLayoutSpecPlayground] Improvements to propagation of visualize mode, resize handle, minor cleanup.

* Fix to ASEnvironment

* [ASLayoutSpecPlayground] Fix a few minor issues from the merge with latest master.

* Implement layout spec cache

* add pager ndoe

* add more examples

* add more layout examples

* [ASLayoutPlayground] Fix merge issues

* [ASLayoutPlayground] Fix up the example project from the 2.0 API changes.

* [ASLayoutPlayground] Some fixes (#2411)

* [ASLayoutPlayground]: Some fixes
* Fixed crash when tapping descender.
* Fixed setting the item to inspect.
* Fixed button states in inspector node.
* Added sliders for spacingBefore, spacingAfter, ascender.

* [ASLayoutSpecPlayground] Deselect the buttons when editing is over.

* [ASLayoutSpecPlayground] Changed flexGrow/Shrink's values from YES/NO to 1.0/0.0

* [Project] Create new Debug/ directory for advanced tools dedicated to debugging.

* [LayoutSpecPlayground] Rename project without AS in title, to be consistent with LayoutSpecExamples.

* [Bulid] Fix Xcode project to use new Debug subdirectory / group.

* [Bulid] Fix a small merge error.

* [Build] Fix build issue for Framework target.

* [Bulid] Fix podspec to expose InspectorNode header; Remove old-cocoapods emojis from ASDKgram :)

* Move aside ASLayoutSpecPlayground-Swift to match master

* [LayoutSpecPlayground] Cleanup implementation in several files, xcodeproj, etc.

* [ASControlNode] Add comment for new assertion, to be enabled in a separate diff.
2016-11-08 20:16:16 -08:00

189 lines
8.5 KiB
Objective-C

//
// ASDisplayNode+FrameworkPrivate.h
// AsyncDisplayKit
//
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
// This source code is licensed under the BSD-style license found in the
// LICENSE file in the root directory of this source tree. An additional grant
// of patent rights can be found in the PATENTS file in the same directory.
//
//
// The following methods are ONLY for use by _ASDisplayLayer, _ASDisplayView, and ASDisplayNode.
// These methods must never be called or overridden by other classes.
//
#import "_AS-objc-internal.h"
#import "ASDisplayNode.h"
#import "ASThread.h"
NS_ASSUME_NONNULL_BEGIN
/**
Hierarchy state is propagated from nodes to all of their children when certain behaviors are required from the subtree.
Examples include rasterization and external driving of the .interfaceState property.
By passing this information explicitly, performance is optimized by avoiding iteration up the supernode chain.
Lastly, this avoidance of supernode traversal protects against the possibility of deadlocks when a supernode is
simultaneously attempting to materialize views / layers for its subtree (as many related methods require property locking)
Note: as the hierarchy deepens, more state properties may be enabled. However, state properties may never be disabled /
cancelled below the point they are enabled. They continue to the leaves of the hierarchy.
*/
typedef NS_OPTIONS(NSUInteger, ASHierarchyState)
{
/** The node may or may not have a supernode, but no supernode has a special hierarchy-influencing option enabled. */
ASHierarchyStateNormal = 0,
/** The node has a supernode with .shouldRasterizeDescendants = YES.
Note: the root node of the rasterized subtree (the one with the property set on it) will NOT have this state set. */
ASHierarchyStateRasterized = 1 << 0,
/** The node or one of its supernodes is managed by a class like ASRangeController. Most commonly, these nodes are
ASCellNode objects or a subnode of one, and are used in ASTableView or ASCollectionView.
These nodes also receive regular updates to the .interfaceState property with more detailed status information. */
ASHierarchyStateRangeManaged = 1 << 1,
/** Down-propagated version of _flags.visibilityNotificationsDisabled. This flag is very rarely set, but by having it
locally available to nodes, they do not have to walk up supernodes at the critical points it is checked. */
ASHierarchyStateTransitioningSupernodes = 1 << 2,
/** One of the supernodes of this node is performing a transition.
Any layout calculated during this state should not be applied immediately, but pending until later. */
ASHierarchyStateLayoutPending = 1 << 3,
ASHierarchyStateVisualizeLayout = 1 << 4
};
ASDISPLAYNODE_INLINE BOOL ASHierarchyStateIncludesLayoutPending(ASHierarchyState hierarchyState)
{
return ((hierarchyState & ASHierarchyStateLayoutPending) == ASHierarchyStateLayoutPending);
}
ASDISPLAYNODE_INLINE BOOL ASHierarchyStateIncludesRangeManaged(ASHierarchyState hierarchyState)
{
return ((hierarchyState & ASHierarchyStateRangeManaged) == ASHierarchyStateRangeManaged);
}
ASDISPLAYNODE_INLINE BOOL ASHierarchyStateIncludesVisualizeLayout(ASHierarchyState hierarchyState)
{
return ((hierarchyState & ASHierarchyStateVisualizeLayout) == ASHierarchyStateVisualizeLayout);
}
ASDISPLAYNODE_INLINE BOOL ASHierarchyStateIncludesRasterized(ASHierarchyState hierarchyState)
{
return ((hierarchyState & ASHierarchyStateRasterized) == ASHierarchyStateRasterized);
}
ASDISPLAYNODE_INLINE BOOL ASHierarchyStateIncludesTransitioningSupernodes(ASHierarchyState hierarchyState)
{
return ((hierarchyState & ASHierarchyStateTransitioningSupernodes) == ASHierarchyStateTransitioningSupernodes);
}
__unused static NSString * _Nonnull NSStringFromASHierarchyState(ASHierarchyState hierarchyState)
{
NSMutableArray *states = [NSMutableArray array];
if (hierarchyState == ASHierarchyStateNormal) {
[states addObject:@"Normal"];
}
if (ASHierarchyStateIncludesRangeManaged(hierarchyState)) {
[states addObject:@"RangeManaged"];
}
if (ASHierarchyStateIncludesLayoutPending(hierarchyState)) {
[states addObject:@"LayoutPending"];
}
if (ASHierarchyStateIncludesRasterized(hierarchyState)) {
[states addObject:@"Rasterized"];
}
if (ASHierarchyStateIncludesTransitioningSupernodes(hierarchyState)) {
[states addObject:@"TransitioningSupernodes"];
}
return [NSString stringWithFormat:@"{ %@ }", [states componentsJoinedByString:@" | "]];
}
@interface ASDisplayNode ()
{
@protected
ASInterfaceState _interfaceState;
ASHierarchyState _hierarchyState;
}
// The view class to use when creating a new display node instance. Defaults to _ASDisplayView.
+ (Class)viewClass;
// These methods are recursive, and either union or remove the provided interfaceState to all sub-elements.
- (void)enterInterfaceState:(ASInterfaceState)interfaceState;
- (void)exitInterfaceState:(ASInterfaceState)interfaceState;
- (void)recursivelySetInterfaceState:(ASInterfaceState)interfaceState;
// These methods are recursive, and either union or remove the provided hierarchyState to all sub-elements.
- (void)enterHierarchyState:(ASHierarchyState)hierarchyState;
- (void)exitHierarchyState:(ASHierarchyState)hierarchyState;
// Changed before calling willEnterHierarchy / didExitHierarchy.
@property (nonatomic, readwrite, assign, getter = isInHierarchy) BOOL inHierarchy;
// Call willEnterHierarchy if necessary and set inHierarchy = YES if visibility notifications are enabled on all of its parents
- (void)__enterHierarchy;
// Call didExitHierarchy if necessary and set inHierarchy = NO if visibility notifications are enabled on all of its parents
- (void)__exitHierarchy;
/**
* @abstract Returns the Hierarchy State of the node.
*
* @return The current ASHierarchyState of the node, indicating whether it is rasterized or managed by a range controller.
*
* @see ASInterfaceState
*/
@property (nonatomic, readwrite) ASHierarchyState hierarchyState;
/**
* @abstract Return if the node is range managed or not
*
* @discussion Currently only set interface state on nodes in table and collection views. For other nodes, if they are
* in the hierarchy we enable all ASInterfaceState types with `ASInterfaceStateInHierarchy`, otherwise `None`.
*/
- (BOOL)supportsRangeManagedInterfaceState;
// The two methods below will eventually be exposed, but their names are subject to change.
/**
* @abstract Ensure that all rendering is complete for this node and its descendants.
*
* @discussion Calling this method on the main thread after a node is added to the view hierarchy will ensure that
* placeholder states are never visible to the user. It is used by ASTableView, ASCollectionView, and ASViewController
* to implement their respective ".neverShowPlaceholders" option.
*
* If all nodes have layer.contents set and/or their layer does not have -needsDisplay set, the method will return immediately.
*
* This method is capable of handling a mixed set of nodes, with some not having started display, some in progress on an
* asynchronous display operation, and some already finished.
*
* In order to guarantee against deadlocks, this method should only be called on the main thread.
* It may block on the private queue, [_ASDisplayLayer displayQueue]
*/
- (void)recursivelyEnsureDisplaySynchronously:(BOOL)synchronously;
/**
* @abstract Allows a node to bypass all ensureDisplay passes. Defaults to NO.
*
* @discussion Nodes that are expensive to draw and expected to have placeholder even with
* .neverShowPlaceholders enabled should set this to YES.
*
* ASImageNode uses the default of NO, as it is often used for UI images that are expected to synchronize with ensureDisplay.
*
* ASNetworkImageNode and ASMultiplexImageNode set this to YES, because they load data from a database or server,
* and are expected to support a placeholder state given that display is often blocked on slow data fetching.
*/
@property (nonatomic, assign) BOOL shouldBypassEnsureDisplay;
/**
* @abstract Checks whether a node should be scheduled for display, considering its current and new interface states.
*/
- (BOOL)shouldScheduleDisplayWithNewInterfaceState:(ASInterfaceState)newInterfaceState;
@end
@interface UIView (ASDisplayNodeInternal)
@property (nullable, atomic, weak, readwrite) ASDisplayNode *asyncdisplaykit_node;
@end
@interface CALayer (ASDisplayNodeInternal)
@property (nullable, atomic, weak, readwrite) ASDisplayNode *asyncdisplaykit_node;
@end
NS_ASSUME_NONNULL_END