Swiftgram/AsyncDisplayKit/Private/ASEnvironmentInternal.mm
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

218 lines
9.1 KiB
Plaintext

//
// ASEnvironmentInternal.mm
// 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.
//
#import "ASEnvironmentInternal.h"
#import <queue>
//#define LOG(...) NSLog(__VA_ARGS__)
#define LOG(...)
#define AS_SUPPORT_PROPAGATION YES
#define AS_DOES_NOT_SUPPORT_PROPAGATION NO
BOOL ASEnvironmentStatePropagationEnabled()
{
return AS_DOES_NOT_SUPPORT_PROPAGATION;
}
BOOL ASEnvironmentStateTraitCollectionPropagationEnabled()
{
return AS_SUPPORT_PROPAGATION;
}
#pragma mark - Traversing an ASEnvironment Tree
void ASEnvironmentPerformBlockOnObjectAndChildren(id<ASEnvironment> object, void(^block)(id<ASEnvironment> node))
{
if (!object) {
return;
}
std::queue<id<ASEnvironment>> queue;
queue.push(object);
while (!queue.empty()) {
id<ASEnvironment> object = queue.front(); queue.pop();
block(object);
for (id<ASEnvironment> child in [object children]) {
queue.push(child);
}
}
}
void ASEnvironmentPerformBlockOnObjectAndParents(id<ASEnvironment> object, void(^block)(id<ASEnvironment> node))
{
while (object) {
block(object);
object = [object parent];
}
}
#pragma mark - Set and get extensible values from state structs
void _ASEnvironmentLayoutOptionsExtensionSetBoolAtIndex(id<ASEnvironment> object, int idx, BOOL value)
{
NSCAssert(idx < kMaxEnvironmentStateBoolExtensions, @"Setting index outside of max bool extensions space");
ASEnvironmentState state = object.environmentState;
state.layoutOptionsState._extensions.boolExtensions[idx] = value;
object.environmentState = state;
}
BOOL _ASEnvironmentLayoutOptionsExtensionGetBoolAtIndex(id<ASEnvironment> object, int idx)
{
NSCAssert(idx < kMaxEnvironmentStateBoolExtensions, @"Accessing index outside of max bool extensions space");
return object.environmentState.layoutOptionsState._extensions.boolExtensions[idx];
}
void _ASEnvironmentLayoutOptionsExtensionSetIntegerAtIndex(id<ASEnvironment> object, int idx, NSInteger value)
{
NSCAssert(idx < kMaxEnvironmentStateIntegerExtensions, @"Setting index outside of max integer extensions space");
ASEnvironmentState state = object.environmentState;
state.layoutOptionsState._extensions.integerExtensions[idx] = value;
object.environmentState = state;
}
NSInteger _ASEnvironmentLayoutOptionsExtensionGetIntegerAtIndex(id<ASEnvironment> object, int idx)
{
NSCAssert(idx < kMaxEnvironmentStateIntegerExtensions, @"Accessing index outside of max integer extensions space");
return object.environmentState.layoutOptionsState._extensions.integerExtensions[idx];
}
void _ASEnvironmentLayoutOptionsExtensionSetEdgeInsetsAtIndex(id<ASEnvironment> object, int idx, UIEdgeInsets value)
{
NSCAssert(idx < kMaxEnvironmentStateEdgeInsetExtensions, @"Setting index outside of max edge insets extensions space");
ASEnvironmentState state = object.environmentState;
state.layoutOptionsState._extensions.edgeInsetsExtensions[idx] = value;
object.environmentState = state;
}
UIEdgeInsets _ASEnvironmentLayoutOptionsExtensionGetEdgeInsetsAtIndex(id<ASEnvironment> object, int idx)
{
NSCAssert(idx < kMaxEnvironmentStateEdgeInsetExtensions, @"Accessing index outside of max edge insets extensions space");
return object.environmentState.layoutOptionsState._extensions.edgeInsetsExtensions[idx];
}
#pragma mark - Merging functions for states
ASEnvironmentState ASEnvironmentMergeObjectAndState(ASEnvironmentState environmentState, ASEnvironmentHierarchyState hierarchyState, ASEnvironmentStatePropagation propagation) {
// Merge object and hierarchy state
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", layoutOptionsState);
if (!ASEnvironmentStatePropagationEnabled() && propagation == ASEnvironmentStatePropagation::UP) {
return environmentState;
}
// Support propagate up
if (propagation == ASEnvironmentStatePropagation::UP) {
// Object is the parent and the state is the state of the child
const ASEnvironmentLayoutOptionsState defaultState = ASEnvironmentLayoutOptionsStateMakeDefault();
ASEnvironmentLayoutOptionsState parentLayoutOptionsState = environmentState.layoutOptionsState;
// For every field check if the parent value is equal to the default and if so propegate up the value of the passed
// in layout options state
if (parentLayoutOptionsState.spacingBefore == defaultState.spacingBefore) {
parentLayoutOptionsState.spacingBefore = layoutOptionsState.spacingBefore;
}
if (parentLayoutOptionsState.spacingAfter == defaultState.spacingAfter) {
parentLayoutOptionsState.spacingAfter = layoutOptionsState.spacingAfter;
}
if (parentLayoutOptionsState.alignSelf == defaultState.alignSelf) {
parentLayoutOptionsState.alignSelf = layoutOptionsState.alignSelf;
}
if (parentLayoutOptionsState.flexGrow == defaultState.flexGrow) {
parentLayoutOptionsState.flexGrow = layoutOptionsState.flexGrow;
}
if (parentLayoutOptionsState.flexShrink == defaultState.flexShrink) {
parentLayoutOptionsState.flexShrink = layoutOptionsState.flexShrink;
}
if (ASDimensionEqualToDimension(parentLayoutOptionsState.flexBasis, defaultState.flexBasis)) {
parentLayoutOptionsState.flexBasis = layoutOptionsState.flexBasis;
}
if (parentLayoutOptionsState.alignSelf == defaultState.alignSelf) {
parentLayoutOptionsState.alignSelf = layoutOptionsState.alignSelf;
}
if (parentLayoutOptionsState.ascender == defaultState.ascender) {
parentLayoutOptionsState.ascender = layoutOptionsState.ascender;
}
if (parentLayoutOptionsState.descender == defaultState.descender) {
parentLayoutOptionsState.descender = layoutOptionsState.descender;
}
if (CGPointEqualToPoint(parentLayoutOptionsState.layoutPosition, defaultState.layoutPosition)) {
// For now it is unclear if we should be up-propagating sizeRange or layoutPosition.
// parentLayoutOptionsState.layoutPosition = layoutOptionsState.layoutPosition;
}
// Merge extended values if necessary
const ASEnvironmentStateExtensions defaultExtensions = ASEnvironmentDefaultStateExtensions;
const ASEnvironmentStateExtensions layoutOptionsStateExtensions = layoutOptionsState._extensions;
ASEnvironmentStateExtensions parentLayoutOptionsExtensions = parentLayoutOptionsState._extensions;
for (int i = 0; i < kMaxEnvironmentStateBoolExtensions; i++) {
if (parentLayoutOptionsExtensions.boolExtensions[i] == defaultExtensions.boolExtensions[i]) {
parentLayoutOptionsExtensions.boolExtensions[i] = layoutOptionsStateExtensions.boolExtensions[i];
}
}
for (int i = 0; i < kMaxEnvironmentStateIntegerExtensions; i++) {
if (parentLayoutOptionsExtensions.integerExtensions[i] == defaultExtensions.integerExtensions[i]) {
parentLayoutOptionsExtensions.integerExtensions[i] = layoutOptionsStateExtensions.integerExtensions[i];
}
}
for (int i = 0; i < kMaxEnvironmentStateEdgeInsetExtensions; i++) {
if (UIEdgeInsetsEqualToEdgeInsets(parentLayoutOptionsExtensions.edgeInsetsExtensions[i], defaultExtensions.edgeInsetsExtensions[i])) {
parentLayoutOptionsExtensions.edgeInsetsExtensions[i] = layoutOptionsStateExtensions.edgeInsetsExtensions[i];
}
}
parentLayoutOptionsState._extensions = parentLayoutOptionsExtensions;
// Update layout options state
environmentState.layoutOptionsState = parentLayoutOptionsState;
}
return environmentState;
}
ASEnvironmentState ASEnvironmentMergeObjectAndState(ASEnvironmentState childEnvironmentState, ASEnvironmentTraitCollection parentTraitCollection, ASEnvironmentStatePropagation propagation) {
if (propagation == ASEnvironmentStatePropagation::DOWN && !ASEnvironmentStateTraitCollectionPropagationEnabled()) {
return childEnvironmentState;
}
// Support propagate down
if (propagation == ASEnvironmentStatePropagation::DOWN) {
ASEnvironmentTraitCollection childTraitCollection = childEnvironmentState.environmentTraitCollection;
childTraitCollection.horizontalSizeClass = parentTraitCollection.horizontalSizeClass;
childTraitCollection.verticalSizeClass = parentTraitCollection.verticalSizeClass;
childTraitCollection.userInterfaceIdiom = parentTraitCollection.userInterfaceIdiom;
childTraitCollection.forceTouchCapability = parentTraitCollection.forceTouchCapability;
childTraitCollection.displayScale = parentTraitCollection.displayScale;
childTraitCollection.containerSize = parentTraitCollection.containerSize;
childEnvironmentState.environmentTraitCollection = childTraitCollection;
}
return childEnvironmentState;
}