mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-12-27 00:17:39 +00:00
Initial attempt at implementing Display Traits
Initial attempt to get display traits working with ASEnvironment. To get proper ASDisplayTraits support, you must use an ASViewController. The ASViewController implements UITraitCollection-related methods (`traitCollectionDidChange:`, `willTransitionToTraitCollection:withTransitionCoordinator:`, viewWillTransitionToSize:withTransitionCoordinator`) to update the internal ASDisplayTraits and propagate them to subnodes. ASTableNode and ASCollectionNode don't actually have their cells as subnodes, so a little bit of trickery is involved (on `setEnvironment:` the table/collection node gets its data controllers completedNodes and propagates the new traits. see `ASDisplayTraitsCollectionTableSetEnvironmentState`). The data controller also passes the current display traits when creating new cells. ASViewController also supports the ability to return a custom set of display traits. So if you have a modal dialog that should always be told it is in a compact size class, you can set the override block before displaying the VC. A new example, called Display Traits, has been added. It shows how display traits can be used in a ASViewController with a normal ASDisplayNode as its root, as well as in ASViewControllers hosting table nodes and collection nodes. There is also an example of overriding the default display traits of a VC. Please provide feedback!
This commit is contained in:
@@ -10,6 +10,7 @@
|
||||
#import "ASCollectionInternal.h"
|
||||
#import "ASCollectionViewLayoutFacilitatorProtocol.h"
|
||||
#import "ASDisplayNode+Subclasses.h"
|
||||
#import "ASEnvironmentInternal.h"
|
||||
#import "ASRangeControllerUpdateRangeProtocol+Beta.h"
|
||||
#include <vector>
|
||||
|
||||
@@ -244,4 +245,6 @@
|
||||
[self.view reloadDataImmediately];
|
||||
}
|
||||
|
||||
ASDisplayTraitsCollectionTableSetEnvironmentState
|
||||
|
||||
@end
|
||||
|
||||
@@ -91,7 +91,7 @@ static NSString * const kCellReuseIdentifier = @"_ASCollectionViewCell";
|
||||
#pragma mark -
|
||||
#pragma mark ASCollectionView.
|
||||
|
||||
@interface ASCollectionView () <ASRangeControllerDataSource, ASRangeControllerDelegate, ASDataControllerSource, ASCellNodeLayoutDelegate, ASDelegateProxyInterceptor, ASBatchFetchingScrollView> {
|
||||
@interface ASCollectionView () <ASRangeControllerDataSource, ASRangeControllerDelegate, ASDataControllerSource, ASCellNodeLayoutDelegate, ASDelegateProxyInterceptor, ASBatchFetchingScrollView, ASDataControllerEnvironmentDelegate> {
|
||||
ASCollectionViewProxy *_proxyDataSource;
|
||||
ASCollectionViewProxy *_proxyDelegate;
|
||||
|
||||
@@ -225,6 +225,7 @@ static NSString * const kCellReuseIdentifier = @"_ASCollectionViewCell";
|
||||
_dataController = [[ASCollectionDataController alloc] initWithAsyncDataFetching:NO];
|
||||
_dataController.delegate = _rangeController;
|
||||
_dataController.dataSource = self;
|
||||
_dataController.environmentDelegate = self;
|
||||
|
||||
_batchContext = [[ASBatchContext alloc] init];
|
||||
|
||||
@@ -917,6 +918,14 @@ static NSString * const kCellReuseIdentifier = @"_ASCollectionViewCell";
|
||||
}
|
||||
}
|
||||
|
||||
- (id<ASEnvironment>)dataControllerEnvironment
|
||||
{
|
||||
if (self.collectionNode) {
|
||||
return self.collectionNode;
|
||||
}
|
||||
return self.strongCollectionNode;
|
||||
}
|
||||
|
||||
#pragma mark - ASCollectionViewDataControllerSource Supplementary view support
|
||||
|
||||
- (ASCellNode *)dataController:(ASCollectionDataController *)dataController supplementaryNodeOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath
|
||||
|
||||
@@ -2687,11 +2687,13 @@ static const char *ASDisplayNodeDrawingPriorityKey = "ASDrawingPriority";
|
||||
|
||||
- (ASEnvironmentState)environmentState
|
||||
{
|
||||
ASDN::MutexLocker l(_propertyLock);
|
||||
return _environmentState;
|
||||
}
|
||||
|
||||
- (void)setEnvironmentState:(ASEnvironmentState)environmentState
|
||||
{
|
||||
ASDN::MutexLocker l(_propertyLock);
|
||||
_environmentState = environmentState;
|
||||
}
|
||||
|
||||
@@ -2707,7 +2709,12 @@ static const char *ASDisplayNodeDrawingPriorityKey = "ASDrawingPriority";
|
||||
|
||||
- (BOOL)supportsUpwardPropagation
|
||||
{
|
||||
return ASEnvironmentStatePropagationEnabled();
|
||||
return ASEnvironmentStateUpwardPropagationEnabled();
|
||||
}
|
||||
|
||||
- (BOOL)supportsDownwardPropagation
|
||||
{
|
||||
return ASEnvironmentStateDownwardPropagationEnabled();
|
||||
}
|
||||
|
||||
ASEnvironmentLayoutOptionsForwarding
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
// Copyright © 2015 Facebook. All rights reserved.
|
||||
//
|
||||
|
||||
#import "ASEnvironmentInternal.h"
|
||||
#import "ASFlowLayoutController.h"
|
||||
#import "ASTableViewInternal.h"
|
||||
#import "ASDisplayNode+Subclasses.h"
|
||||
@@ -158,4 +159,6 @@
|
||||
[self.view clearFetchedData];
|
||||
}
|
||||
|
||||
ASDisplayTraitsCollectionTableSetEnvironmentState
|
||||
|
||||
@end
|
||||
@@ -16,6 +16,7 @@
|
||||
#import "ASDisplayNodeExtras.h"
|
||||
#import "ASDisplayNode+Beta.h"
|
||||
#import "ASDisplayNode+FrameworkPrivate.h"
|
||||
#import "ASEnvironmentInternal.h"
|
||||
#import "ASInternalHelpers.h"
|
||||
#import "ASLayout.h"
|
||||
#import "ASLayoutController.h"
|
||||
@@ -88,7 +89,7 @@ static NSString * const kCellReuseIdentifier = @"_ASTableViewCell";
|
||||
- (instancetype)_initWithTableView:(ASTableView *)tableView;
|
||||
@end
|
||||
|
||||
@interface ASTableView () <ASRangeControllerDataSource, ASRangeControllerDelegate, ASDataControllerSource, _ASTableViewCellDelegate, ASCellNodeLayoutDelegate, ASDelegateProxyInterceptor, ASBatchFetchingScrollView>
|
||||
@interface ASTableView () <ASRangeControllerDataSource, ASRangeControllerDelegate, ASDataControllerSource, _ASTableViewCellDelegate, ASCellNodeLayoutDelegate, ASDelegateProxyInterceptor, ASBatchFetchingScrollView, ASDataControllerEnvironmentDelegate>
|
||||
{
|
||||
ASTableViewProxy *_proxyDataSource;
|
||||
ASTableViewProxy *_proxyDelegate;
|
||||
@@ -175,6 +176,7 @@ static NSString * const kCellReuseIdentifier = @"_ASTableViewCell";
|
||||
_dataController = [[dataControllerClass alloc] initWithAsyncDataFetching:NO];
|
||||
_dataController.dataSource = self;
|
||||
_dataController.delegate = _rangeController;
|
||||
_dataController.environmentDelegate = self;
|
||||
|
||||
_layoutController.dataSource = _dataController;
|
||||
|
||||
@@ -1078,6 +1080,16 @@ static NSString * const kCellReuseIdentifier = @"_ASTableViewCell";
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - ASDataControllerEnvironmentDelegate
|
||||
|
||||
- (id<ASEnvironment>)dataControllerEnvironment
|
||||
{
|
||||
if (self.tableNode) {
|
||||
return self.tableNode;
|
||||
}
|
||||
return self.strongTableNode;
|
||||
}
|
||||
|
||||
#pragma mark - _ASTableViewCellDelegate
|
||||
|
||||
- (void)didLayoutSubviewsOfTableViewCell:(_ASTableViewCell *)tableViewCell
|
||||
|
||||
@@ -11,12 +11,27 @@
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
typedef ASDisplayTraits (^ASDisplayTraitsForTraitCollectionBlock)(UITraitCollection *traitCollection);
|
||||
typedef ASDisplayTraits (^ASDisplayTraitsForTraitWindowSizeBlock)(CGSize windowSize);
|
||||
|
||||
@interface ASViewController<__covariant DisplayNodeType : ASDisplayNode *> : UIViewController
|
||||
|
||||
- (instancetype)initWithNode:(DisplayNodeType)node NS_DESIGNATED_INITIALIZER;
|
||||
|
||||
@property (nonatomic, strong, readonly) DisplayNodeType node;
|
||||
|
||||
@property (nonatomic, strong) id displayTraitsContext;
|
||||
|
||||
/**
|
||||
* Set this block to customize the ASDisplayTraits returned when the VC transitions to the given traitCollection.
|
||||
*/
|
||||
@property (nonatomic, copy) ASDisplayTraitsForTraitCollectionBlock overrideDisplayTraitsWithTraitCollection;
|
||||
|
||||
/**
|
||||
* Set this block to customize the ASDisplayTraits returned when the VC transitions to the given window size.
|
||||
*/
|
||||
@property (nonatomic, copy) ASDisplayTraitsForTraitWindowSizeBlock overrideDisplayTraitsWithWindowSize;
|
||||
|
||||
/**
|
||||
* @abstract Passthrough property to the the .interfaceState of the node.
|
||||
* @return The current ASInterfaceState of the node, indicating whether it is visible and other situational properties.
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#import "ASDimension.h"
|
||||
#import "ASDisplayNode+FrameworkPrivate.h"
|
||||
#import "ASDisplayNode+Beta.h"
|
||||
#import "ASEnvironmentInternal.h"
|
||||
#import "ASRangeControllerUpdateRangeProtocol+Beta.h"
|
||||
|
||||
@implementation ASViewController
|
||||
@@ -42,10 +43,18 @@
|
||||
_node = node;
|
||||
|
||||
_automaticallyAdjustRangeModeBasedOnViewEvents = NO;
|
||||
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
if (_displayTraitsContext != nil) {
|
||||
ASDisplayTraitsClearDisplayContext(self.node);
|
||||
_displayTraitsContext = nil;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)loadView
|
||||
{
|
||||
ASDisplayNodeAssertTrue(!_node.layerBacked);
|
||||
@@ -132,4 +141,66 @@
|
||||
return _node.interfaceState;
|
||||
}
|
||||
|
||||
#pragma mark - ASDisplayTraits
|
||||
|
||||
- (ASDisplayTraits)displayTraitsForTraitCollection:(UITraitCollection *)traitCollection
|
||||
{
|
||||
if (self.overrideDisplayTraitsWithTraitCollection) {
|
||||
return self.overrideDisplayTraitsWithTraitCollection(traitCollection);
|
||||
}
|
||||
|
||||
ASDisplayTraits displayTraits = ASDisplayTraitsFromUITraitCollection(traitCollection);
|
||||
displayTraits.displayContext = _displayTraitsContext;
|
||||
return displayTraits;
|
||||
}
|
||||
|
||||
- (ASDisplayTraits)displayTraitsForWindowSize:(CGSize)windowSize
|
||||
{
|
||||
if (self.overrideDisplayTraitsWithWindowSize) {
|
||||
return self.overrideDisplayTraitsWithWindowSize(windowSize);
|
||||
}
|
||||
return self.node.environmentState.displayTraits;
|
||||
}
|
||||
|
||||
- (void)progagateNewDisplayTraits:(ASDisplayTraits)displayTraits
|
||||
{
|
||||
ASEnvironmentState environmentState = self.node.environmentState;
|
||||
ASDisplayTraits oldDisplayTraits = environmentState.displayTraits;
|
||||
|
||||
if (ASDisplayTraitsIsEqualToASDisplayTraits(displayTraits, oldDisplayTraits) == NO) {
|
||||
environmentState.displayTraits = displayTraits;
|
||||
[self.node setEnvironmentState:environmentState];
|
||||
[self.node setNeedsLayout];
|
||||
|
||||
NSArray<id<ASEnvironment>> *children = [self.node children];
|
||||
for (id<ASEnvironment> child in children) {
|
||||
ASEnvironmentStatePropagateDown(child, environmentState.displayTraits);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void)traitCollectionDidChange:(UITraitCollection *)previousTraitCollection
|
||||
{
|
||||
[super traitCollectionDidChange:previousTraitCollection];
|
||||
|
||||
ASDisplayTraits displayTraits = [self displayTraitsForTraitCollection:self.traitCollection];
|
||||
[self progagateNewDisplayTraits:displayTraits];
|
||||
}
|
||||
|
||||
- (void)willTransitionToTraitCollection:(UITraitCollection *)newCollection withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator
|
||||
{
|
||||
[super willTransitionToTraitCollection:newCollection withTransitionCoordinator:coordinator];
|
||||
|
||||
ASDisplayTraits displayTraits = [self displayTraitsForTraitCollection:self.traitCollection];
|
||||
[self progagateNewDisplayTraits:displayTraits];
|
||||
}
|
||||
|
||||
- (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator
|
||||
{
|
||||
[super viewWillTransitionToSize:size withTransitionCoordinator:coordinator];
|
||||
|
||||
ASDisplayTraits displayTraits = [self displayTraitsForWindowSize:size];
|
||||
[self progagateNewDisplayTraits:displayTraits];
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -17,6 +17,7 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@class ASCellNode;
|
||||
@class ASDataController;
|
||||
@protocol ASEnvironment;
|
||||
|
||||
typedef NSUInteger ASDataControllerAnimationOptions;
|
||||
|
||||
@@ -64,6 +65,11 @@ FOUNDATION_EXPORT NSString * const ASDataControllerRowNodeKind;
|
||||
*/
|
||||
- (void)dataControllerUnlockDataSource;
|
||||
|
||||
|
||||
@end
|
||||
|
||||
@protocol ASDataControllerEnvironmentDelegate
|
||||
- (id<ASEnvironment>)dataControllerEnvironment;
|
||||
@end
|
||||
|
||||
/**
|
||||
@@ -122,6 +128,11 @@ FOUNDATION_EXPORT NSString * const ASDataControllerRowNodeKind;
|
||||
*/
|
||||
@property (nonatomic, weak) id<ASDataControllerDelegate> delegate;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
@property (nonatomic, weak) id<ASDataControllerEnvironmentDelegate> environmentDelegate;
|
||||
|
||||
/**
|
||||
* Designated initializer.
|
||||
*
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#import "ASAssert.h"
|
||||
#import "ASCellNode.h"
|
||||
#import "ASDisplayNode.h"
|
||||
#import "ASEnvironmentInternal.h"
|
||||
#import "ASFlowLayoutController.h"
|
||||
#import "ASInternalHelpers.h"
|
||||
#import "ASLayout.h"
|
||||
@@ -519,8 +520,17 @@ static void *kASSizingQueueContext = &kASSizingQueueContext;
|
||||
for (NSUInteger i = 0; i < rowNum; i++) {
|
||||
NSIndexPath *indexPath = [sectionIndex indexPathByAddingIndex:i];
|
||||
ASCellNodeBlock nodeBlock = [_dataSource dataController:self nodeBlockAtIndexPath:indexPath];
|
||||
|
||||
// When creating a node, make sure to pass along the current display traits so it will be laid out properly
|
||||
ASCellNodeBlock nodeBlockPropagatingDisplayTraits = ^{
|
||||
ASCellNode *cellNode = nodeBlock();
|
||||
id<ASEnvironment> environment = [self.environmentDelegate dataControllerEnvironment];
|
||||
ASEnvironmentStatePropagateDown(cellNode, [environment environmentState].displayTraits);
|
||||
return cellNode;
|
||||
};
|
||||
|
||||
ASSizeRange constrainedSize = [self constrainedSizeForNodeOfKind:ASDataControllerRowNodeKind atIndexPath:indexPath];
|
||||
[contexts addObject:[[ASIndexedNodeContext alloc] initWithNodeBlock:nodeBlock
|
||||
[contexts addObject:[[ASIndexedNodeContext alloc] initWithNodeBlock:nodeBlockPropagatingDisplayTraits
|
||||
indexPath:indexPath
|
||||
constrainedSize:constrainedSize]];
|
||||
}
|
||||
|
||||
@@ -14,6 +14,8 @@
|
||||
#import "ASStackLayoutDefines.h"
|
||||
#import "ASRelativeSize.h"
|
||||
|
||||
@protocol ASEnvironment;
|
||||
@class UITraitCollection;
|
||||
|
||||
ASDISPLAYNODE_EXTERN_C_BEGIN
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
@@ -59,17 +61,50 @@ typedef struct ASEnvironmentHierarchyState {
|
||||
unsigned layoutPending:1; // = NO
|
||||
} ASEnvironmentHierarchyState;
|
||||
|
||||
#pragma mark - ASDisplayTraits
|
||||
|
||||
typedef struct ASDisplayTraits {
|
||||
CGFloat displayScale;
|
||||
UIUserInterfaceSizeClass horizontalSizeClass;
|
||||
UIUserInterfaceIdiom userInterfaceIdiom;
|
||||
UIUserInterfaceSizeClass verticalSizeClass;
|
||||
UIForceTouchCapability forceTouchCapability;
|
||||
|
||||
// WARNING:
|
||||
// This pointer is in a C struct and therefore not managed by ARC. It is
|
||||
// an unsafe unretained pointer, so when you dereference it you better be
|
||||
// sure that it is valid.
|
||||
//
|
||||
// Use displayContext when you wish to pass view context specific data along with the
|
||||
// trait collcetion to subnodes. This should be a piece of data owned by an
|
||||
// ASViewController, which will ensure that the data is still valid when laying out
|
||||
// its subviews. When the VC is dealloc'ed, the displayContext it created will also
|
||||
// be dealloced but any subnodes that are hanging around (why would they be?) will now
|
||||
// have a displayContext that points to a bad pointer.
|
||||
//
|
||||
// An added precaution is to call ASDisplayTraitsClearDisplayContext from your ASVC's desctructor
|
||||
// which will propagate a nil displayContext to its subnodes.
|
||||
//__unsafe_unretained id displayContext;
|
||||
id __unsafe_unretained displayContext;
|
||||
} ASDisplayTraits;
|
||||
|
||||
extern void ASDisplayTraitsClearDisplayContext(id<ASEnvironment> rootEnvironment);
|
||||
|
||||
extern ASDisplayTraits ASDisplayTraitsFromUITraitCollection(UITraitCollection *traitCollection);
|
||||
extern BOOL ASDisplayTraitsIsEqualToASDisplayTraits(ASDisplayTraits displayTraits0, ASDisplayTraits displayTraits1);
|
||||
|
||||
#pragma mark - ASEnvironmentState
|
||||
|
||||
typedef struct ASEnvironmentState {
|
||||
struct ASEnvironmentHierarchyState hierarchyState;
|
||||
struct ASEnvironmentLayoutOptionsState layoutOptionsState;
|
||||
struct ASDisplayTraits displayTraits;
|
||||
} ASEnvironmentState;
|
||||
extern ASEnvironmentState ASEnvironmentStateMakeDefault();
|
||||
|
||||
ASDISPLAYNODE_EXTERN_C_END
|
||||
|
||||
@class ASTraitCollection;
|
||||
|
||||
#pragma mark - ASEnvironment
|
||||
|
||||
@@ -93,6 +128,33 @@ ASDISPLAYNODE_EXTERN_C_END
|
||||
/// Classes should implement this method and return YES / NO dependent if upward propagation is enabled or not
|
||||
- (BOOL)supportsUpwardPropagation;
|
||||
|
||||
/// Classes should implement this method and return YES / NO dependent if downware propagation is enabled or not
|
||||
- (BOOL)supportsDownwardPropagation;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
// ASCollection/TableNodes don't actually have ASCellNodes as subnodes. Because of this we can't rely on display trait
|
||||
// downward propagation via ASEnvironment. Instead if the new environmentState has displayTraits that are different from
|
||||
// the cells', then we propagate downward explicitly and request a relayout.
|
||||
//
|
||||
// If there is any new downward propagating state, it should be added to this define.
|
||||
//
|
||||
// This logic is used in both ASCollectionNode and ASTableNode
|
||||
#define ASDisplayTraitsCollectionTableSetEnvironmentState \
|
||||
- (void)setEnvironmentState:(ASEnvironmentState)environmentState\
|
||||
{\
|
||||
ASDisplayTraits oldDisplayTraits = self.environmentState.displayTraits;\
|
||||
[super setEnvironmentState:environmentState];\
|
||||
ASDisplayTraits currentDisplayTraits = environmentState.displayTraits;\
|
||||
if (ASDisplayTraitsIsEqualToASDisplayTraits(currentDisplayTraits, oldDisplayTraits) == NO) {\
|
||||
NSArray<NSArray <ASCellNode *> *> *completedNodes = [self.view.dataController completedNodes];\
|
||||
for (NSArray *sectionArray in completedNodes) {\
|
||||
for (ASCellNode *cellNode in sectionArray) {\
|
||||
ASEnvironmentStatePropagateDown(cellNode, currentDisplayTraits);\
|
||||
[cellNode setNeedsLayout];\
|
||||
}\
|
||||
}\
|
||||
}\
|
||||
}\
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
@@ -1,33 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#import "ASEnvironment.h"
|
||||
|
||||
ASEnvironmentLayoutOptionsState _ASEnvironmentLayoutOptionsStateMakeDefault()
|
||||
{
|
||||
return (ASEnvironmentLayoutOptionsState) {
|
||||
// Default values can be defined in here
|
||||
};
|
||||
}
|
||||
|
||||
ASEnvironmentHierarchyState _ASEnvironmentHierarchyStateMakeDefault()
|
||||
{
|
||||
return (ASEnvironmentHierarchyState) {
|
||||
// Default values can be defined in here
|
||||
};
|
||||
}
|
||||
|
||||
ASEnvironmentState ASEnvironmentStateMakeDefault()
|
||||
{
|
||||
return (ASEnvironmentState) {
|
||||
.layoutOptionsState = _ASEnvironmentLayoutOptionsStateMakeDefault(),
|
||||
.hierarchyState = _ASEnvironmentHierarchyStateMakeDefault()
|
||||
};
|
||||
}
|
||||
77
AsyncDisplayKit/Details/ASEnvironment.mm
Normal file
77
AsyncDisplayKit/Details/ASEnvironment.mm
Normal file
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#import "ASEnvironment.h"
|
||||
#import "ASEnvironmentInternal.h"
|
||||
|
||||
ASEnvironmentLayoutOptionsState _ASEnvironmentLayoutOptionsStateMakeDefault()
|
||||
{
|
||||
return (ASEnvironmentLayoutOptionsState) {
|
||||
// Default values can be defined in here
|
||||
};
|
||||
}
|
||||
|
||||
ASEnvironmentHierarchyState _ASEnvironmentHierarchyStateMakeDefault()
|
||||
{
|
||||
return (ASEnvironmentHierarchyState) {
|
||||
// Default values can be defined in here
|
||||
};
|
||||
}
|
||||
|
||||
extern void ASDisplayTraitsClearDisplayContext(id<ASEnvironment> rootEnvironment)
|
||||
{
|
||||
ASEnvironmentState envState = [rootEnvironment environmentState];
|
||||
ASDisplayTraits displayTraits = envState.displayTraits;
|
||||
displayTraits.displayContext = nil;
|
||||
envState.displayTraits = displayTraits;
|
||||
[rootEnvironment setEnvironmentState:envState];
|
||||
|
||||
for (id<ASEnvironment> child in [rootEnvironment children]) {
|
||||
ASEnvironmentStatePropagateDown(child, displayTraits);
|
||||
}
|
||||
}
|
||||
|
||||
ASDisplayTraits _ASDisplayTraitsMakeDefault()
|
||||
{
|
||||
return (ASDisplayTraits) {
|
||||
// Default values can be defined in here
|
||||
};
|
||||
}
|
||||
|
||||
ASDisplayTraits ASDisplayTraitsFromUITraitCollection(UITraitCollection *traitCollection)
|
||||
{
|
||||
return (ASDisplayTraits) {
|
||||
.displayScale = traitCollection.displayScale,
|
||||
.horizontalSizeClass = traitCollection.horizontalSizeClass,
|
||||
.userInterfaceIdiom = traitCollection.userInterfaceIdiom,
|
||||
.verticalSizeClass = traitCollection.verticalSizeClass,
|
||||
.forceTouchCapability = traitCollection.forceTouchCapability,
|
||||
};
|
||||
}
|
||||
|
||||
BOOL ASDisplayTraitsIsEqualToASDisplayTraits(ASDisplayTraits displayTraits0, ASDisplayTraits displayTraits1)
|
||||
{
|
||||
return
|
||||
displayTraits0.verticalSizeClass == displayTraits1.verticalSizeClass &&
|
||||
displayTraits0.horizontalSizeClass == displayTraits1.horizontalSizeClass &&
|
||||
displayTraits0.displayScale == displayTraits1.displayScale &&
|
||||
displayTraits0.userInterfaceIdiom == displayTraits1.userInterfaceIdiom &&
|
||||
displayTraits0.forceTouchCapability == displayTraits1.forceTouchCapability;
|
||||
}
|
||||
|
||||
ASEnvironmentState ASEnvironmentStateMakeDefault()
|
||||
{
|
||||
return (ASEnvironmentState) {
|
||||
.layoutOptionsState = _ASEnvironmentLayoutOptionsStateMakeDefault(),
|
||||
.hierarchyState = _ASEnvironmentHierarchyStateMakeDefault(),
|
||||
.displayTraits = _ASDisplayTraitsMakeDefault()
|
||||
};
|
||||
}
|
||||
|
||||
@@ -80,7 +80,7 @@
|
||||
|
||||
id<ASLayoutable> finalLayoutable = [child finalLayoutable];
|
||||
if (finalLayoutable != child) {
|
||||
if (ASEnvironmentStatePropagationEnabled()) {
|
||||
if (ASEnvironmentStateUpwardPropagationEnabled()) {
|
||||
ASEnvironmentStatePropagateUp(finalLayoutable, child.environmentState.layoutOptionsState);
|
||||
} else {
|
||||
// If state propagation is not enabled the layout options state needs to be copied manually
|
||||
@@ -168,11 +168,13 @@
|
||||
|
||||
- (ASEnvironmentState)environmentState
|
||||
{
|
||||
ASDN::MutexLocker l(_propertyLock);
|
||||
return _environmentState;
|
||||
}
|
||||
|
||||
- (void)setEnvironmentState:(ASEnvironmentState)environmentState
|
||||
{
|
||||
ASDN::MutexLocker l(_propertyLock);
|
||||
_environmentState = environmentState;
|
||||
}
|
||||
|
||||
@@ -181,7 +183,12 @@
|
||||
// the specifications that are known to have more than one.
|
||||
- (BOOL)supportsUpwardPropagation
|
||||
{
|
||||
return ASEnvironmentStatePropagationEnabled();
|
||||
return ASEnvironmentStateUpwardPropagationEnabled();
|
||||
}
|
||||
|
||||
- (BOOL)supportsDownwardPropagation
|
||||
{
|
||||
return ASEnvironmentStateDownwardPropagationEnabled();
|
||||
}
|
||||
|
||||
- (void)propagateUpLayoutable:(id<ASLayoutable>)layoutable
|
||||
|
||||
@@ -79,7 +79,7 @@ extern void ASLayoutableClearCurrentContext();
|
||||
#define ASEnvironmentLayoutOptionsForwarding \
|
||||
- (void)propagateUpLayoutOptionsState\
|
||||
{\
|
||||
if (!ASEnvironmentStatePropagationEnabled()) {\
|
||||
if (!ASEnvironmentStateUpwardPropagationEnabled()) {\
|
||||
return;\
|
||||
}\
|
||||
id<ASEnvironment> parent = [self parent];\
|
||||
|
||||
@@ -12,7 +12,8 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
BOOL ASEnvironmentStatePropagationEnabled();
|
||||
BOOL ASEnvironmentStateUpwardPropagationEnabled();
|
||||
BOOL ASEnvironmentStateDownwardPropagationEnabled();
|
||||
|
||||
|
||||
#pragma mark - Set and get extensible values for layout options
|
||||
@@ -45,10 +46,12 @@ static const struct ASEnvironmentStateExtensions ASEnvironmentDefaultStateExtens
|
||||
static const struct ASEnvironmentLayoutOptionsState ASEnvironmentDefaultLayoutOptionsState = {};
|
||||
ASEnvironmentState ASEnvironmentMergeObjectAndState(ASEnvironmentState environmentState, ASEnvironmentLayoutOptionsState state, ASEnvironmentStatePropagation propagation);
|
||||
|
||||
|
||||
static const struct ASEnvironmentHierarchyState ASEnvironmentDefaultHierarchyState = {};
|
||||
ASEnvironmentState ASEnvironmentMergeObjectAndState(ASEnvironmentState environmentState, ASEnvironmentHierarchyState state, ASEnvironmentStatePropagation propagation);
|
||||
|
||||
static const struct ASDisplayTraits ASEnvironmentDefaultDisplayTraits = {};
|
||||
ASEnvironmentState ASEnvironmentMergeObjectAndState(ASEnvironmentState environmentState, ASDisplayTraits state, ASEnvironmentStatePropagation propagation);
|
||||
|
||||
|
||||
#pragma mark - Propagation
|
||||
|
||||
|
||||
@@ -15,11 +15,17 @@
|
||||
//#define LOG(...) NSLog(__VA_ARGS__)
|
||||
#define LOG(...)
|
||||
|
||||
#define AS_SUPPORT_PROPAGATION NO
|
||||
#define AS_SUPPORT_UPWARD_PROPAGATION NO
|
||||
#define AS_SUPPORT_DOWNWARD_PROPAGATION YES
|
||||
|
||||
BOOL ASEnvironmentStatePropagationEnabled()
|
||||
BOOL ASEnvironmentStateUpwardPropagationEnabled()
|
||||
{
|
||||
return AS_SUPPORT_PROPAGATION;
|
||||
return AS_SUPPORT_UPWARD_PROPAGATION;
|
||||
}
|
||||
|
||||
BOOL ASEnvironmentStateDownwardPropagationEnabled()
|
||||
{
|
||||
return AS_SUPPORT_DOWNWARD_PROPAGATION;
|
||||
}
|
||||
|
||||
|
||||
@@ -106,15 +112,15 @@ UIEdgeInsets _ASEnvironmentLayoutOptionsExtensionGetEdgeInsetsAtIndex(id<ASEnvir
|
||||
|
||||
ASEnvironmentState ASEnvironmentMergeObjectAndState(ASEnvironmentState environmentState, ASEnvironmentHierarchyState hierarchyState, ASEnvironmentStatePropagation propagation) {
|
||||
// Merge object and hierarchy state
|
||||
LOG(@"Merge object and state: %@ - ASEnvironmentHierarchyState", object);
|
||||
LOG(@"Merge object and state: %@ - ASEnvironmentHierarchyState", hierarchyState);
|
||||
return environmentState;
|
||||
}
|
||||
|
||||
ASEnvironmentState ASEnvironmentMergeObjectAndState(ASEnvironmentState environmentState, ASEnvironmentLayoutOptionsState layoutOptionsState, ASEnvironmentStatePropagation propagation) {
|
||||
// Merge object and layout options state
|
||||
LOG(@"Merge object and state: %@ - ASEnvironmentLayoutOptionsState", object);
|
||||
LOG(@"Merge object and state: %@ - ASEnvironmentLayoutOptionsState", layoutOptionsState);
|
||||
|
||||
if (!ASEnvironmentStatePropagationEnabled()) {
|
||||
if (!ASEnvironmentStateUpwardPropagationEnabled() && propagation == ASEnvironmentStatePropagation::UP) {
|
||||
return environmentState;
|
||||
}
|
||||
|
||||
@@ -188,3 +194,23 @@ ASEnvironmentState ASEnvironmentMergeObjectAndState(ASEnvironmentState environme
|
||||
|
||||
return environmentState;
|
||||
}
|
||||
|
||||
ASEnvironmentState ASEnvironmentMergeObjectAndState(ASEnvironmentState childEnvironmentState, ASDisplayTraits parentDisplayTraits, ASEnvironmentStatePropagation propagation) {
|
||||
if (propagation == ASEnvironmentStatePropagation::DOWN && !ASEnvironmentStateDownwardPropagationEnabled()) {
|
||||
return childEnvironmentState;
|
||||
}
|
||||
|
||||
// Support propagate down
|
||||
if (propagation == ASEnvironmentStatePropagation::DOWN) {
|
||||
ASDisplayTraits childDisplayTraits = childEnvironmentState.displayTraits;
|
||||
childDisplayTraits.horizontalSizeClass = parentDisplayTraits.horizontalSizeClass;
|
||||
childDisplayTraits.verticalSizeClass = parentDisplayTraits.verticalSizeClass;
|
||||
childDisplayTraits.userInterfaceIdiom = parentDisplayTraits.userInterfaceIdiom;
|
||||
childDisplayTraits.forceTouchCapability = parentDisplayTraits.forceTouchCapability;
|
||||
childDisplayTraits.displayScale = parentDisplayTraits.displayScale;
|
||||
childDisplayTraits.displayContext = parentDisplayTraits.displayContext;
|
||||
childEnvironmentState.displayTraits = childDisplayTraits;
|
||||
|
||||
}
|
||||
return childEnvironmentState;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user