mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-12-22 14:20:20 +00:00
[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.
This commit is contained in:
@@ -25,6 +25,7 @@ Pod::Spec.new do |spec|
|
||||
'AsyncDisplayKit/Details/**/*.h',
|
||||
'AsyncDisplayKit/Layout/*.h',
|
||||
'Base/*.h',
|
||||
'AsyncDisplayKit/Debug/ASLayoutElementInspectorNode.h',
|
||||
'AsyncDisplayKit/TextKit/ASTextNodeTypes.h',
|
||||
'AsyncDisplayKit/TextKit/ASTextKitComponents.h'
|
||||
]
|
||||
|
||||
@@ -472,14 +472,24 @@
|
||||
DBDB83971C6E879900D0098C /* ASPagerFlowLayout.m in Sources */ = {isa = PBXBuildFile; fileRef = DBDB83931C6E879900D0098C /* ASPagerFlowLayout.m */; };
|
||||
DE040EF91C2B40AC004692FF /* ASCollectionViewFlowLayoutInspector.h in Headers */ = {isa = PBXBuildFile; fileRef = 251B8EF41BBB3D690087C538 /* ASCollectionViewFlowLayoutInspector.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
DE0702FC1C3671E900D7DE62 /* libAsyncDisplayKit.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 058D09AC195D04C000B7D73C /* libAsyncDisplayKit.a */; };
|
||||
DE4843DB1C93EAB100A1F33B /* ASLayoutTransition.mm in Sources */ = {isa = PBXBuildFile; fileRef = E52405B21C8FEF03004DC8E7 /* ASLayoutTransition.mm */; };
|
||||
DE4843DC1C93EAC100A1F33B /* ASLayoutTransition.h in Headers */ = {isa = PBXBuildFile; fileRef = E52405B41C8FEF16004DC8E7 /* ASLayoutTransition.h */; };
|
||||
DE6EA3231C14000600183B10 /* ASDisplayNode+FrameworkPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = DE6EA3211C14000600183B10 /* ASDisplayNode+FrameworkPrivate.h */; };
|
||||
DE84918D1C8FFF2B003D89E9 /* ASRunLoopQueue.h in Headers */ = {isa = PBXBuildFile; fileRef = 81EE384D1C8E94F000456208 /* ASRunLoopQueue.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
DE84918E1C8FFF9F003D89E9 /* ASRunLoopQueue.mm in Sources */ = {isa = PBXBuildFile; fileRef = 81EE384E1C8E94F000456208 /* ASRunLoopQueue.mm */; };
|
||||
DE89C1701DCEB9CC00D49D74 /* ASLayoutElementInspectorCell.h in Headers */ = {isa = PBXBuildFile; fileRef = DE89C16A1DCEB9CC00D49D74 /* ASLayoutElementInspectorCell.h */; };
|
||||
DE89C1711DCEB9CC00D49D74 /* ASLayoutElementInspectorCell.m in Sources */ = {isa = PBXBuildFile; fileRef = DE89C16B1DCEB9CC00D49D74 /* ASLayoutElementInspectorCell.m */; };
|
||||
DE89C1731DCEB9CC00D49D74 /* ASLayoutElementInspectorCell.m in Sources */ = {isa = PBXBuildFile; fileRef = DE89C16B1DCEB9CC00D49D74 /* ASLayoutElementInspectorCell.m */; };
|
||||
DE89C1741DCEB9CC00D49D74 /* ASLayoutElementInspectorNode.h in Headers */ = {isa = PBXBuildFile; fileRef = DE89C16C1DCEB9CC00D49D74 /* ASLayoutElementInspectorNode.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
DE89C1751DCEB9CC00D49D74 /* ASLayoutElementInspectorNode.m in Sources */ = {isa = PBXBuildFile; fileRef = DE89C16D1DCEB9CC00D49D74 /* ASLayoutElementInspectorNode.m */; };
|
||||
DE89C1771DCEB9CC00D49D74 /* ASLayoutElementInspectorNode.m in Sources */ = {isa = PBXBuildFile; fileRef = DE89C16D1DCEB9CC00D49D74 /* ASLayoutElementInspectorNode.m */; };
|
||||
DE89C1781DCEB9CC00D49D74 /* ASLayoutSpec+Debug.h in Headers */ = {isa = PBXBuildFile; fileRef = DE89C16E1DCEB9CC00D49D74 /* ASLayoutSpec+Debug.h */; };
|
||||
DE89C1791DCEB9CC00D49D74 /* ASLayoutSpec+Debug.m in Sources */ = {isa = PBXBuildFile; fileRef = DE89C16F1DCEB9CC00D49D74 /* ASLayoutSpec+Debug.m */; };
|
||||
DE89C17B1DCEB9CC00D49D74 /* ASLayoutSpec+Debug.m in Sources */ = {isa = PBXBuildFile; fileRef = DE89C16F1DCEB9CC00D49D74 /* ASLayoutSpec+Debug.m */; };
|
||||
DE8BEAC21C2DF3FC00D57C12 /* ASDelegateProxy.h in Headers */ = {isa = PBXBuildFile; fileRef = DE8BEABF1C2DF3FC00D57C12 /* ASDelegateProxy.h */; };
|
||||
DE8BEAC31C2DF3FC00D57C12 /* ASDelegateProxy.m in Sources */ = {isa = PBXBuildFile; fileRef = DE8BEAC01C2DF3FC00D57C12 /* ASDelegateProxy.m */; };
|
||||
DE8BEAC41C2DF3FC00D57C12 /* ASDelegateProxy.m in Sources */ = {isa = PBXBuildFile; fileRef = DE8BEAC01C2DF3FC00D57C12 /* ASDelegateProxy.m */; };
|
||||
DEB8ED7C1DD003D300DBDE55 /* ASLayoutTransition.mm in Sources */ = {isa = PBXBuildFile; fileRef = E52405B21C8FEF03004DC8E7 /* ASLayoutTransition.mm */; };
|
||||
DEB8ED7E1DD007F400DBDE55 /* ASLayoutElementInspectorNode.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DE89C16C1DCEB9CC00D49D74 /* ASLayoutElementInspectorNode.h */; };
|
||||
DEC146B71C37A16A004A0EE7 /* ASCollectionInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = DEC146B41C37A16A004A0EE7 /* ASCollectionInternal.h */; };
|
||||
DEC146B81C37A16A004A0EE7 /* ASCollectionInternal.m in Sources */ = {isa = PBXBuildFile; fileRef = DEC146B51C37A16A004A0EE7 /* ASCollectionInternal.m */; };
|
||||
DEC146B91C37A16A004A0EE7 /* ASCollectionInternal.m in Sources */ = {isa = PBXBuildFile; fileRef = DEC146B51C37A16A004A0EE7 /* ASCollectionInternal.m */; };
|
||||
@@ -662,6 +672,7 @@
|
||||
dstPath = "include/$(PRODUCT_NAME)";
|
||||
dstSubfolderSpec = 16;
|
||||
files = (
|
||||
DEB8ED7E1DD007F400DBDE55 /* ASLayoutElementInspectorNode.h in CopyFiles */,
|
||||
69127CFE1DD2B387004BF6E2 /* ASEventLog.h in CopyFiles */,
|
||||
693117CE1DC7C72700DE4784 /* ASDisplayNode+Deprecated.h in CopyFiles */,
|
||||
69F381A51DA4630D00CF2278 /* NSArray+Diffing.h in CopyFiles */,
|
||||
@@ -1016,8 +1027,8 @@
|
||||
69F10C851C84C35D0026140C /* ASRangeControllerUpdateRangeProtocol+Beta.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "ASRangeControllerUpdateRangeProtocol+Beta.h"; sourceTree = "<group>"; };
|
||||
69FEE53C1D95A9AF0086F066 /* ASLayoutElementStyleTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASLayoutElementStyleTests.m; sourceTree = "<group>"; };
|
||||
6BDC61F51978FEA400E50D21 /* AsyncDisplayKit.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; path = AsyncDisplayKit.h; sourceTree = "<group>"; };
|
||||
764D83D21C8EA515009B4FB8 /* AsyncDisplayKit+Debug.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "AsyncDisplayKit+Debug.h"; sourceTree = "<group>"; };
|
||||
764D83D31C8EA515009B4FB8 /* AsyncDisplayKit+Debug.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "AsyncDisplayKit+Debug.m"; sourceTree = "<group>"; };
|
||||
764D83D21C8EA515009B4FB8 /* AsyncDisplayKit+Debug.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "AsyncDisplayKit+Debug.h"; path = "../AsyncDisplayKit+Debug.h"; sourceTree = "<group>"; };
|
||||
764D83D31C8EA515009B4FB8 /* AsyncDisplayKit+Debug.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "AsyncDisplayKit+Debug.m"; path = "../AsyncDisplayKit+Debug.m"; sourceTree = "<group>"; };
|
||||
7A06A7381C35F08800FE8DAA /* ASRelativeLayoutSpec.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = ASRelativeLayoutSpec.mm; path = AsyncDisplayKit/Layout/ASRelativeLayoutSpec.mm; sourceTree = "<group>"; };
|
||||
7A06A7391C35F08800FE8DAA /* ASRelativeLayoutSpec.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ASRelativeLayoutSpec.h; path = AsyncDisplayKit/Layout/ASRelativeLayoutSpec.h; sourceTree = "<group>"; };
|
||||
7AB338681C55B97B0055FDE8 /* ASRelativeLayoutSpecSnapshotTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASRelativeLayoutSpecSnapshotTests.mm; sourceTree = "<group>"; };
|
||||
@@ -1166,6 +1177,12 @@
|
||||
DBDB83921C6E879900D0098C /* ASPagerFlowLayout.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASPagerFlowLayout.h; sourceTree = "<group>"; };
|
||||
DBDB83931C6E879900D0098C /* ASPagerFlowLayout.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASPagerFlowLayout.m; sourceTree = "<group>"; };
|
||||
DE6EA3211C14000600183B10 /* ASDisplayNode+FrameworkPrivate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "ASDisplayNode+FrameworkPrivate.h"; sourceTree = "<group>"; };
|
||||
DE89C16A1DCEB9CC00D49D74 /* ASLayoutElementInspectorCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASLayoutElementInspectorCell.h; sourceTree = "<group>"; };
|
||||
DE89C16B1DCEB9CC00D49D74 /* ASLayoutElementInspectorCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASLayoutElementInspectorCell.m; sourceTree = "<group>"; };
|
||||
DE89C16C1DCEB9CC00D49D74 /* ASLayoutElementInspectorNode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASLayoutElementInspectorNode.h; sourceTree = "<group>"; };
|
||||
DE89C16D1DCEB9CC00D49D74 /* ASLayoutElementInspectorNode.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASLayoutElementInspectorNode.m; sourceTree = "<group>"; };
|
||||
DE89C16E1DCEB9CC00D49D74 /* ASLayoutSpec+Debug.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "ASLayoutSpec+Debug.h"; sourceTree = "<group>"; };
|
||||
DE89C16F1DCEB9CC00D49D74 /* ASLayoutSpec+Debug.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "ASLayoutSpec+Debug.m"; sourceTree = "<group>"; };
|
||||
DE8BEABF1C2DF3FC00D57C12 /* ASDelegateProxy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASDelegateProxy.h; sourceTree = "<group>"; };
|
||||
DE8BEAC01C2DF3FC00D57C12 /* ASDelegateProxy.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASDelegateProxy.m; sourceTree = "<group>"; };
|
||||
DEC146B41C37A16A004A0EE7 /* ASCollectionInternal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ASCollectionInternal.h; path = Details/ASCollectionInternal.h; sourceTree = "<group>"; };
|
||||
@@ -1360,12 +1377,11 @@
|
||||
ACC945A81BA9E7A0005E1FB8 /* ASViewController.h */,
|
||||
9CFFC6BF1CCAC73C006A6476 /* ASViewController.mm */,
|
||||
6BDC61F51978FEA400E50D21 /* AsyncDisplayKit.h */,
|
||||
764D83D21C8EA515009B4FB8 /* AsyncDisplayKit+Debug.h */,
|
||||
764D83D31C8EA515009B4FB8 /* AsyncDisplayKit+Debug.m */,
|
||||
DB55C2651C641AE4004EDCF5 /* ASContextTransitioning.h */,
|
||||
68FC85E71CE29C7D00EDD713 /* ASVisibilityProtocols.h */,
|
||||
68FC85E81CE29C7D00EDD713 /* ASVisibilityProtocols.m */,
|
||||
92074A5E1CC8B9DD00918F75 /* tvOS */,
|
||||
DE89C1691DCEB9CC00D49D74 /* Debug */,
|
||||
058D09E1195D050800B7D73C /* Details */,
|
||||
058D0A01195D050800B7D73C /* Private */,
|
||||
AC6456051B0A333200CF11B8 /* Layout */,
|
||||
@@ -1757,6 +1773,21 @@
|
||||
name = "Supporting Files";
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
DE89C1691DCEB9CC00D49D74 /* Debug */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
DE89C16A1DCEB9CC00D49D74 /* ASLayoutElementInspectorCell.h */,
|
||||
DE89C16B1DCEB9CC00D49D74 /* ASLayoutElementInspectorCell.m */,
|
||||
DE89C16C1DCEB9CC00D49D74 /* ASLayoutElementInspectorNode.h */,
|
||||
DE89C16D1DCEB9CC00D49D74 /* ASLayoutElementInspectorNode.m */,
|
||||
DE89C16E1DCEB9CC00D49D74 /* ASLayoutSpec+Debug.h */,
|
||||
DE89C16F1DCEB9CC00D49D74 /* ASLayoutSpec+Debug.m */,
|
||||
764D83D21C8EA515009B4FB8 /* AsyncDisplayKit+Debug.h */,
|
||||
764D83D31C8EA515009B4FB8 /* AsyncDisplayKit+Debug.m */,
|
||||
);
|
||||
path = Debug;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
FD40E2760492F0CAAEAD552D /* Pods */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@@ -1788,6 +1819,7 @@
|
||||
68355B411CB57A6C001D4E68 /* ASImageContainerProtocolCategories.h in Headers */,
|
||||
7630FFA81C9E267E007A7C0E /* ASVideoNode.h in Headers */,
|
||||
B350623F1B010EFD0018CF92 /* _ASAsyncTransactionContainer.h in Headers */,
|
||||
DE89C1741DCEB9CC00D49D74 /* ASLayoutElementInspectorNode.h in Headers */,
|
||||
B13CA1011C52004900E031AB /* ASCollectionNode+Beta.h in Headers */,
|
||||
254C6B7E1BF94DF4003EC431 /* ASTextKitTailTruncater.h in Headers */,
|
||||
B35062411B010EFD0018CF92 /* _ASAsyncTransactionGroup.h in Headers */,
|
||||
@@ -1898,6 +1930,7 @@
|
||||
B35062261B010EFD0018CF92 /* ASRangeController.h in Headers */,
|
||||
34EFC76E1B701CF400AD841F /* ASRatioLayoutSpec.h in Headers */,
|
||||
254C6B741BF94DF4003EC431 /* ASTextNodeWordKerner.h in Headers */,
|
||||
DE89C1781DCEB9CC00D49D74 /* ASLayoutSpec+Debug.h in Headers */,
|
||||
DB55C2671C641AE4004EDCF5 /* ASContextTransitioning.h in Headers */,
|
||||
68B0277B1C1A79D60041016B /* ASDisplayNode+Beta.h in Headers */,
|
||||
CCF18FF41D2575E300DF5895 /* NSIndexSet+ASHelpers.h in Headers */,
|
||||
@@ -1925,6 +1958,7 @@
|
||||
044284FE1BAA387800D16268 /* ASStackLayoutSpecUtilities.h in Headers */,
|
||||
34EFC7751B701D2400AD841F /* ASStackPositionedLayout.h in Headers */,
|
||||
69E1006E1CA89CB600D88C1B /* ASEnvironmentInternal.h in Headers */,
|
||||
DE89C1701DCEB9CC00D49D74 /* ASLayoutElementInspectorCell.h in Headers */,
|
||||
34EFC7771B701D2D00AD841F /* ASStackUnpositionedLayout.h in Headers */,
|
||||
9C6BB3B31B8CC9C200F13F52 /* ASAbsoluteLayoutElement.h in Headers */,
|
||||
34EFC7731B701D0700AD841F /* ASAbsoluteLayoutSpec.h in Headers */,
|
||||
@@ -2152,6 +2186,7 @@
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
058D0A22195D050800B7D73C /* _ASAsyncTransaction.mm in Sources */,
|
||||
E52405B31C8FEF03004DC8E7 /* ASLayoutTransition.mm in Sources */,
|
||||
8B0768B41CE752EC002E1453 /* ASDefaultPlaybackButton.m in Sources */,
|
||||
E55D86321CA8A14000A0C26F /* ASLayoutElement.mm in Sources */,
|
||||
68FC85E41CE29B7E00EDD713 /* ASTabBarController.m in Sources */,
|
||||
@@ -2185,6 +2220,7 @@
|
||||
DBC452DC1C5BF64600B16017 /* NSArray+Diffing.m in Sources */,
|
||||
AC3C4A521A1139C100143C57 /* ASCollectionView.mm in Sources */,
|
||||
9CFFC6C21CCAC768006A6476 /* ASTableNode.mm in Sources */,
|
||||
DE89C1751DCEB9CC00D49D74 /* ASLayoutElementInspectorNode.m in Sources */,
|
||||
205F0E1E1B373A2C007741D0 /* ASCollectionViewLayoutController.mm in Sources */,
|
||||
68FC85EB1CE29C7D00EDD713 /* ASVisibilityProtocols.m in Sources */,
|
||||
058D0A13195D050800B7D73C /* ASControlNode.mm in Sources */,
|
||||
@@ -2205,6 +2241,7 @@
|
||||
0587F9BE1A7309ED00AFF0BA /* ASEditableTextNode.mm in Sources */,
|
||||
464052231A3F83C40061C0BA /* ASFlowLayoutController.mm in Sources */,
|
||||
257754C41BEE458E00737CA5 /* ASTextNodeWordKerner.m in Sources */,
|
||||
DE89C1791DCEB9CC00D49D74 /* ASLayoutSpec+Debug.m in Sources */,
|
||||
058D0A1A195D050800B7D73C /* ASHighlightOverlayLayer.mm in Sources */,
|
||||
058D0A2B195D050800B7D73C /* ASImageNode+CGExtras.m in Sources */,
|
||||
CC3B208B1C3F7A5400798563 /* ASWeakSet.m in Sources */,
|
||||
@@ -2231,9 +2268,9 @@
|
||||
0442850F1BAA64EC00D16268 /* ASMultidimensionalArrayUtils.mm in Sources */,
|
||||
7A06A73A1C35F08800FE8DAA /* ASRelativeLayoutSpec.mm in Sources */,
|
||||
6907C2591DC4ECFE00374C66 /* ASObjectDescriptionHelpers.m in Sources */,
|
||||
E52405B31C8FEF03004DC8E7 /* ASLayoutTransition.mm in Sources */,
|
||||
69CB62AD1CB8165900024920 /* _ASDisplayViewAccessiblity.mm in Sources */,
|
||||
257754AB1BEE44CD00737CA5 /* ASTextKitEntityAttribute.m in Sources */,
|
||||
DE89C1711DCEB9CC00D49D74 /* ASLayoutElementInspectorCell.m in Sources */,
|
||||
055F1A3919ABD413004DAFF1 /* ASRangeController.mm in Sources */,
|
||||
044285091BAA63FE00D16268 /* ASBatchFetching.m in Sources */,
|
||||
257754AE1BEE44CD00737CA5 /* ASTextKitRenderer+Positioning.mm in Sources */,
|
||||
@@ -2339,10 +2376,10 @@
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
DEB8ED7C1DD003D300DBDE55 /* ASLayoutTransition.mm in Sources */,
|
||||
9F98C0261DBE29E000476D92 /* ASControlTargetAction.m in Sources */,
|
||||
9C70F2091CDABA36007D6C76 /* ASViewController.mm in Sources */,
|
||||
8BBBAB8D1CEBAF1E00107FC6 /* ASDefaultPlaybackButton.m in Sources */,
|
||||
DE4843DB1C93EAB100A1F33B /* ASLayoutTransition.mm in Sources */,
|
||||
B30BF6541C59D889004FCD53 /* ASLayoutManager.m in Sources */,
|
||||
92DD2FE71BF4D0850074C9DD /* ASMapNode.mm in Sources */,
|
||||
636EA1A51C7FF4EF00EE152F /* ASDefaultPlayButton.m in Sources */,
|
||||
@@ -2404,6 +2441,7 @@
|
||||
B350621E1B010EFD0018CF92 /* ASHighlightOverlayLayer.mm in Sources */,
|
||||
9CC606651D24DF9E006581A0 /* NSIndexSet+ASHelpers.m in Sources */,
|
||||
92074A641CC8BA1900918F75 /* ASImageNode+tvOS.m in Sources */,
|
||||
DE89C17B1DCEB9CC00D49D74 /* ASLayoutSpec+Debug.m in Sources */,
|
||||
B35062541B010EFD0018CF92 /* ASImageNode+CGExtras.m in Sources */,
|
||||
68355B401CB57A69001D4E68 /* ASImageContainerProtocolCategories.m in Sources */,
|
||||
B35062031B010EFD0018CF92 /* ASImageNode.mm in Sources */,
|
||||
@@ -2424,6 +2462,7 @@
|
||||
B35062071B010EFD0018CF92 /* ASNetworkImageNode.mm in Sources */,
|
||||
34EFC76D1B701CF100AD841F /* ASOverlayLayoutSpec.mm in Sources */,
|
||||
044285101BAA64EC00D16268 /* ASMultidimensionalArrayUtils.mm in Sources */,
|
||||
DE89C1731DCEB9CC00D49D74 /* ASLayoutElementInspectorCell.m in Sources */,
|
||||
B35062271B010EFD0018CF92 /* ASRangeController.mm in Sources */,
|
||||
0442850A1BAA63FE00D16268 /* ASBatchFetching.m in Sources */,
|
||||
68FC85E61CE29B9400EDD713 /* ASNavigationController.m in Sources */,
|
||||
@@ -2459,6 +2498,7 @@
|
||||
697796611D8AC8D3007E93D7 /* ASLayoutSpec+Subclasses.mm in Sources */,
|
||||
B350623B1B010EFD0018CF92 /* NSMutableAttributedString+TextKitAdditions.m in Sources */,
|
||||
044284FD1BAA365100D16268 /* UICollectionViewLayout+ASConvenience.m in Sources */,
|
||||
DE89C1771DCEB9CC00D49D74 /* ASLayoutElementInspectorNode.m in Sources */,
|
||||
254C6B8A1BF94F8A003EC431 /* ASTextKitRenderer+TextChecking.mm in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
|
||||
@@ -10,6 +10,8 @@
|
||||
|
||||
#import <AsyncDisplayKit/ASDisplayNode.h>
|
||||
|
||||
#pragma once
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/**
|
||||
|
||||
@@ -14,6 +14,8 @@
|
||||
#import "AsyncDisplayKit+Debug.h"
|
||||
#import "ASInternalHelpers.h"
|
||||
#import "ASControlTargetAction.h"
|
||||
#import "ASDisplayNode+FrameworkPrivate.h"
|
||||
#import "ASLayoutElementInspectorNode.h"
|
||||
|
||||
// UIControl allows dragging some distance outside of the control itself during
|
||||
// tracking. This value depends on the device idiom (25 or 70 points), so
|
||||
@@ -241,6 +243,9 @@ void _ASEnumerateControlEventsIncludedInMaskWithBlock(ASControlNodeEvent mask, v
|
||||
{
|
||||
NSParameterAssert(action);
|
||||
NSParameterAssert(controlEventMask != 0);
|
||||
// This assertion would likely be helpful to users who aren't familiar with the implications of layer-backing.
|
||||
// However, it would represent an API change (in debug) as it did not used to assert.
|
||||
// ASDisplayNodeAssert(!self.isLayerBacked, @"ASControlNode is layer backed, will never be able to call target in target:action: pair.");
|
||||
|
||||
ASDN::MutexLocker l(_controlLock);
|
||||
|
||||
@@ -448,4 +453,21 @@ void _ASEnumerateControlEventsIncludedInMaskWithBlock(ASControlNodeEvent mask, v
|
||||
return _debugHighlightOverlay;
|
||||
}
|
||||
|
||||
// methods for visualizing ASLayoutSpecs
|
||||
- (void)setHierarchyState:(ASHierarchyState)hierarchyState
|
||||
{
|
||||
[super setHierarchyState:hierarchyState];
|
||||
|
||||
if (self.shouldVisualizeLayoutSpecs) {
|
||||
[self addTarget:self action:@selector(inspectElement) forControlEvents:ASControlNodeEventTouchUpInside];
|
||||
} else {
|
||||
[self removeTarget:self action:@selector(inspectElement) forControlEvents:ASControlNodeEventTouchUpInside];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)inspectElement
|
||||
{
|
||||
[ASLayoutElementInspectorNode sharedInstance].layoutElementToEdit = self;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -8,6 +8,8 @@
|
||||
// of patent rights can be found in the PATENTS file in the same directory.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
#import <AsyncDisplayKit/_ASAsyncTransactionContainer.h>
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#import "ASDisplayNode+Subclasses.h"
|
||||
#import "ASDisplayNode+FrameworkPrivate.h"
|
||||
#import "ASDisplayNode+Beta.h"
|
||||
#import "AsyncDisplayKit+Debug.h"
|
||||
|
||||
#import <objc/runtime.h>
|
||||
|
||||
@@ -49,6 +50,10 @@ NSString * const ASRenderingEngineDidDisplayNodesScheduledBeforeTimestamp = @"AS
|
||||
@protocol CALayerDelegate;
|
||||
|
||||
@interface ASDisplayNode () <UIGestureRecognizerDelegate, _ASDisplayLayerDelegate, _ASTransitionContextCompletionDelegate>
|
||||
{
|
||||
BOOL _shouldCacheLayoutSpec;
|
||||
ASLayoutSpec *_layoutSpec;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -717,6 +722,23 @@ static ASDisplayNodeMethodOverrides GetASDisplayNodeMethodOverrides(Class c)
|
||||
|
||||
[self cancelLayoutTransition];
|
||||
|
||||
BOOL didCreateNewContext = NO;
|
||||
BOOL didOverrideExistingContext = NO;
|
||||
BOOL shouldVisualizeLayout = ASHierarchyStateIncludesVisualizeLayout(_hierarchyState);
|
||||
ASLayoutElementContext context;
|
||||
if (ASLayoutElementContextIsNull(ASLayoutElementGetCurrentContext())) {
|
||||
context = ASLayoutElementContextMake(ASLayoutElementContextDefaultTransitionID, shouldVisualizeLayout);
|
||||
ASLayoutElementSetCurrentContext(context);
|
||||
didCreateNewContext = YES;
|
||||
} else {
|
||||
context = ASLayoutElementGetCurrentContext();
|
||||
if (context.needsVisualizeNode != shouldVisualizeLayout) {
|
||||
context.needsVisualizeNode = shouldVisualizeLayout;
|
||||
ASLayoutElementSetCurrentContext(context);
|
||||
didOverrideExistingContext = YES;
|
||||
}
|
||||
}
|
||||
|
||||
// Prepare for layout transition
|
||||
auto previousLayout = _calculatedDisplayNodeLayout;
|
||||
auto pendingLayout = std::make_shared<ASDisplayNodeLayout>(
|
||||
@@ -724,6 +746,14 @@ static ASDisplayNodeMethodOverrides GetASDisplayNodeMethodOverrides(Class c)
|
||||
constrainedSize,
|
||||
parentSize
|
||||
);
|
||||
|
||||
if (didCreateNewContext) {
|
||||
ASLayoutElementClearCurrentContext();
|
||||
} else if (didOverrideExistingContext) {
|
||||
context.needsVisualizeNode = !context.needsVisualizeNode;
|
||||
ASLayoutElementSetCurrentContext(context);
|
||||
}
|
||||
|
||||
_pendingLayoutTransition = [[ASLayoutTransition alloc] initWithNode:self
|
||||
pendingLayout:pendingLayout
|
||||
previousLayout:previousLayout];
|
||||
@@ -831,9 +861,11 @@ static ASDisplayNodeMethodOverrides GetASDisplayNodeMethodOverrides(Class c)
|
||||
|
||||
ASLayout *newLayout;
|
||||
{
|
||||
ASLayoutElementSetCurrentContext(ASLayoutElementContextMake(transitionID, NO));
|
||||
|
||||
ASDN::MutexLocker l(__instanceLock__);
|
||||
|
||||
BOOL shouldVisualizeLayout = ASHierarchyStateIncludesVisualizeLayout(_hierarchyState);
|
||||
ASLayoutElementSetCurrentContext(ASLayoutElementContextMake(transitionID, shouldVisualizeLayout));
|
||||
|
||||
BOOL automaticallyManagesSubnodesDisabled = (self.automaticallyManagesSubnodes == NO);
|
||||
self.automaticallyManagesSubnodes = YES; // Temporary flag for 1.9.x
|
||||
newLayout = [self calculateLayoutThatFits:constrainedSize
|
||||
@@ -2438,7 +2470,12 @@ void recursivelyTriggerDisplayForLayer(CALayer *layer, BOOL shouldBlock)
|
||||
layoutSpec = [[ASLayoutSpec alloc] init];
|
||||
}
|
||||
|
||||
if (_shouldCacheLayoutSpec) {
|
||||
_layoutSpec = layoutSpec;
|
||||
} else {
|
||||
ASDisplayNodeAssert(layoutSpec.isMutable, @"Node %@ returned layout spec %@ that has already been used. Layout specs should always be regenerated.", self, layoutSpec);
|
||||
}
|
||||
|
||||
layoutSpec.parent = self;
|
||||
layoutSpec.isMutable = NO;
|
||||
}
|
||||
@@ -2486,7 +2523,10 @@ void recursivelyTriggerDisplayForLayer(CALayer *layer, BOOL shouldBlock)
|
||||
__ASDisplayNodeCheckForLayoutMethodOverrides;
|
||||
|
||||
BOOL measureLayoutSpec = _measurementOptions & ASDisplayNodePerformanceMeasurementOptionLayoutSpec;
|
||||
if (_layoutSpecBlock != NULL) {
|
||||
|
||||
if (_shouldCacheLayoutSpec && _layoutSpec != nil) {
|
||||
return _layoutSpec;
|
||||
} else if (_layoutSpecBlock != NULL) {
|
||||
return ({
|
||||
ASDN::MutexLocker l(__instanceLock__);
|
||||
ASDN::SumScopeTimer t(_layoutSpecTotalTime, measureLayoutSpec);
|
||||
@@ -3700,4 +3740,42 @@ ASLayoutElementStyleForwarding
|
||||
self.automaticallyManagesSubnodes = enabled;
|
||||
}
|
||||
|
||||
#pragma mark - ASDisplayNode(LayoutDebugging)
|
||||
|
||||
- (void)setShouldVisualizeLayoutSpecs:(BOOL)shouldVisualizeLayoutSpecs
|
||||
{
|
||||
ASDN::MutexLocker l(__instanceLock__);
|
||||
if (shouldVisualizeLayoutSpecs != [self shouldVisualizeLayoutSpecs]) {
|
||||
if (shouldVisualizeLayoutSpecs) {
|
||||
[self enterHierarchyState:ASHierarchyStateVisualizeLayout];
|
||||
} else {
|
||||
[self exitHierarchyState:ASHierarchyStateVisualizeLayout];
|
||||
}
|
||||
[self setNeedsLayout];
|
||||
}
|
||||
}
|
||||
|
||||
- (BOOL)shouldVisualizeLayoutSpecs
|
||||
{
|
||||
ASDN::MutexLocker l(__instanceLock__);
|
||||
return ASHierarchyStateIncludesVisualizeLayout(_hierarchyState);
|
||||
}
|
||||
|
||||
- (void)setShouldCacheLayoutSpec:(BOOL)shouldCacheLayoutSpec
|
||||
{
|
||||
ASDN::MutexLocker l(__instanceLock__);
|
||||
if (_shouldCacheLayoutSpec != shouldCacheLayoutSpec) {
|
||||
_shouldCacheLayoutSpec = shouldCacheLayoutSpec;
|
||||
if (_shouldCacheLayoutSpec == NO) {
|
||||
_layoutSpec = nil;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (BOOL)shouldCacheLayoutSpec
|
||||
{
|
||||
ASDN::MutexLocker l(__instanceLock__);
|
||||
return _shouldCacheLayoutSpec;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -10,12 +10,19 @@
|
||||
// of patent rights can be found in the PATENTS file in the same directory.
|
||||
//
|
||||
|
||||
#import "ASDisplayNode.h"
|
||||
#import "ASControlNode.h"
|
||||
#import "ASImageNode.h"
|
||||
#import "ASRangeController.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface ASDisplayNode (Visualization)
|
||||
@property (nonatomic, assign) BOOL shouldVisualizeLayoutSpecs;
|
||||
@property (nonatomic, assign) BOOL shouldCacheLayoutSpec;
|
||||
|
||||
@end
|
||||
|
||||
@interface ASImageNode (Debugging)
|
||||
|
||||
/**
|
||||
|
||||
28
AsyncDisplayKit/Debug/ASLayoutElementInspectorCell.h
Normal file
28
AsyncDisplayKit/Debug/ASLayoutElementInspectorCell.h
Normal file
@@ -0,0 +1,28 @@
|
||||
//
|
||||
// ASLayoutElementInspectorCell.h
|
||||
// AsyncDisplayKit
|
||||
//
|
||||
// Created by Hannah Troisi on 3/27/16.
|
||||
// Copyright © 2016 Facebook. All rights reserved.
|
||||
//
|
||||
|
||||
#import <AsyncDisplayKit/ASCellNode.h>
|
||||
|
||||
typedef NS_ENUM(NSInteger, ASLayoutElementPropertyType) {
|
||||
ASLayoutElementPropertyFlexGrow = 0,
|
||||
ASLayoutElementPropertyFlexShrink,
|
||||
ASLayoutElementPropertyAlignSelf,
|
||||
ASLayoutElementPropertyFlexBasis,
|
||||
ASLayoutElementPropertySpacingBefore,
|
||||
ASLayoutElementPropertySpacingAfter,
|
||||
ASLayoutElementPropertyAscender,
|
||||
ASLayoutElementPropertyDescender,
|
||||
ASLayoutElementPropertyCount
|
||||
};
|
||||
|
||||
@interface ASLayoutElementInspectorCell : ASCellNode
|
||||
|
||||
- (instancetype)initWithProperty:(ASLayoutElementPropertyType)property layoutElementToEdit:(id<ASLayoutElement>)layoutable NS_DESIGNATED_INITIALIZER;
|
||||
|
||||
@end
|
||||
|
||||
569
AsyncDisplayKit/Debug/ASLayoutElementInspectorCell.m
Normal file
569
AsyncDisplayKit/Debug/ASLayoutElementInspectorCell.m
Normal file
@@ -0,0 +1,569 @@
|
||||
//
|
||||
// ASLayoutElementInspectorCell.m
|
||||
// AsyncDisplayKit
|
||||
//
|
||||
// Created by Hannah Troisi on 3/27/16.
|
||||
// Copyright © 2016 Facebook. All rights reserved.
|
||||
//
|
||||
|
||||
#import "ASLayoutElementInspectorCell.h"
|
||||
#import <AsyncDisplayKit/AsyncDisplayKit.h>
|
||||
|
||||
typedef NS_ENUM(NSInteger, CellDataType) {
|
||||
CellDataTypeBool,
|
||||
CellDataTypeFloat,
|
||||
};
|
||||
|
||||
__weak static ASLayoutElementInspectorCell *__currentlyOpenedCell = nil;
|
||||
|
||||
@protocol InspectorCellEditingBubbleProtocol <NSObject>
|
||||
- (void)valueChangedToIndex:(NSUInteger)index;
|
||||
@end
|
||||
|
||||
@interface ASLayoutElementInspectorCellEditingBubble : ASDisplayNode
|
||||
@property (nonatomic, strong, readwrite) id<InspectorCellEditingBubbleProtocol> delegate;
|
||||
- (instancetype)initWithEnumOptions:(BOOL)yes enumStrings:(NSArray<NSString *> *)options currentOptionIndex:(NSUInteger)currentOption;
|
||||
- (instancetype)initWithSliderMinValue:(CGFloat)min maxValue:(CGFloat)max currentValue:(CGFloat)current
|
||||
;@end
|
||||
|
||||
@interface ASLayoutElementInspectorCell () <InspectorCellEditingBubbleProtocol>
|
||||
@end
|
||||
|
||||
@implementation ASLayoutElementInspectorCell
|
||||
{
|
||||
ASLayoutElementPropertyType _propertyType;
|
||||
CellDataType _dataType;
|
||||
id<ASLayoutElement> _layoutElementToEdit;
|
||||
|
||||
ASButtonNode *_buttonNode;
|
||||
ASTextNode *_textNode;
|
||||
ASTextNode *_textNode2;
|
||||
|
||||
ASLayoutElementInspectorCellEditingBubble *_textBubble;
|
||||
}
|
||||
|
||||
#pragma mark - Lifecycle
|
||||
|
||||
- (instancetype)initWithProperty:(ASLayoutElementPropertyType)property layoutElementToEdit:(id<ASLayoutElement>)layoutElement
|
||||
{
|
||||
self = [super init];
|
||||
if (self) {
|
||||
|
||||
_propertyType = property;
|
||||
_dataType = [ASLayoutElementInspectorCell dataTypeForProperty:property];
|
||||
_layoutElementToEdit = layoutElement;
|
||||
|
||||
self.automaticallyManagesSubnodes = YES;
|
||||
|
||||
_buttonNode = [self makeBtnNodeWithTitle:[ASLayoutElementInspectorCell propertyStringForPropertyType:property]];
|
||||
[_buttonNode addTarget:self action:@selector(buttonTapped:) forControlEvents:ASControlNodeEventTouchUpInside];
|
||||
|
||||
_textNode = [[ASTextNode alloc] init];
|
||||
_textNode.attributedText = [ASLayoutElementInspectorCell propertyValueAttributedStringForProperty:property withLayoutElement:layoutElement];
|
||||
|
||||
[self updateButtonStateForProperty:property withLayoutElement:layoutElement];
|
||||
|
||||
_textNode2 = [[ASTextNode alloc] init];
|
||||
_textNode2.attributedText = [ASLayoutElementInspectorCell propertyValueDetailAttributedStringForProperty:property withLayoutElement:layoutElement];
|
||||
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)updateButtonStateForProperty:(ASLayoutElementPropertyType)property withLayoutElement:(id<ASLayoutElement>)layoutElement
|
||||
{
|
||||
if (property == ASLayoutElementPropertyFlexGrow) {
|
||||
_buttonNode.selected = layoutElement.style.flexGrow;
|
||||
}
|
||||
else if (property == ASLayoutElementPropertyFlexShrink) {
|
||||
_buttonNode.selected = layoutElement.style.flexShrink;
|
||||
}
|
||||
}
|
||||
|
||||
- (ASLayoutSpec *)layoutSpecThatFits:(ASSizeRange)constrainedSize
|
||||
{
|
||||
ASStackLayoutSpec *horizontalSpec = [ASStackLayoutSpec horizontalStackLayoutSpec];
|
||||
horizontalSpec.children = @[_buttonNode, _textNode];
|
||||
horizontalSpec.style.flexGrow = 1.0;
|
||||
horizontalSpec.alignItems = ASStackLayoutAlignItemsCenter;
|
||||
horizontalSpec.justifyContent = ASStackLayoutJustifyContentSpaceBetween;
|
||||
|
||||
ASLayoutSpec *childSpec;
|
||||
if (_textBubble) {
|
||||
ASStackLayoutSpec *verticalSpec = [ASStackLayoutSpec verticalStackLayoutSpec];
|
||||
verticalSpec.children = @[horizontalSpec, _textBubble];
|
||||
verticalSpec.spacing = 8;
|
||||
verticalSpec.style.flexGrow = 1.0;
|
||||
_textBubble.style.flexGrow = 1.0;
|
||||
childSpec = verticalSpec;
|
||||
} else {
|
||||
childSpec = horizontalSpec;
|
||||
}
|
||||
ASInsetLayoutSpec *insetSpec = [ASInsetLayoutSpec insetLayoutSpecWithInsets:UIEdgeInsetsMake(2, 4, 2, 4) child:childSpec];
|
||||
insetSpec.style.flexGrow =1.0;
|
||||
|
||||
return insetSpec;
|
||||
}
|
||||
|
||||
+ (NSAttributedString *)propertyValueAttributedStringForProperty:(ASLayoutElementPropertyType)property withLayoutElement:(id<ASLayoutElement>)layoutElement
|
||||
{
|
||||
NSString *valueString;
|
||||
|
||||
switch (property) {
|
||||
case ASLayoutElementPropertyFlexGrow:
|
||||
valueString = layoutElement.style.flexGrow ? @"YES" : @"NO";
|
||||
break;
|
||||
case ASLayoutElementPropertyFlexShrink:
|
||||
valueString = layoutElement.style.flexShrink ? @"YES" : @"NO";
|
||||
break;
|
||||
case ASLayoutElementPropertyAlignSelf:
|
||||
valueString = [ASLayoutElementInspectorCell alignSelfEnumValueString:layoutElement.style.alignSelf];
|
||||
break;
|
||||
case ASLayoutElementPropertyFlexBasis:
|
||||
if (layoutElement.style.flexBasis.unit && layoutElement.style.flexBasis.value) { // ENUM TYPE
|
||||
valueString = [NSString stringWithFormat:@"%0.0f %@", layoutElement.style.flexBasis.value,
|
||||
[ASLayoutElementInspectorCell ASRelativeDimensionEnumString:layoutElement.style.alignSelf]];
|
||||
} else {
|
||||
valueString = @"0 pts";
|
||||
}
|
||||
break;
|
||||
case ASLayoutElementPropertySpacingBefore:
|
||||
valueString = [NSString stringWithFormat:@"%0.0f", layoutElement.style.spacingBefore];
|
||||
break;
|
||||
case ASLayoutElementPropertySpacingAfter:
|
||||
valueString = [NSString stringWithFormat:@"%0.0f", layoutElement.style.spacingAfter];
|
||||
break;
|
||||
case ASLayoutElementPropertyAscender:
|
||||
valueString = [NSString stringWithFormat:@"%0.0f", layoutElement.style.ascender];
|
||||
break;
|
||||
case ASLayoutElementPropertyDescender:
|
||||
valueString = [NSString stringWithFormat:@"%0.0f", layoutElement.style.descender];
|
||||
break;
|
||||
default:
|
||||
valueString = @"?";
|
||||
break;
|
||||
}
|
||||
return [ASLayoutElementInspectorCell attributedStringFromString:valueString];
|
||||
}
|
||||
|
||||
+ (NSAttributedString *)propertyValueDetailAttributedStringForProperty:(ASLayoutElementPropertyType)property withLayoutElement:(id<ASLayoutElement>)layoutElement
|
||||
{
|
||||
NSString *valueString;
|
||||
|
||||
switch (property) {
|
||||
case ASLayoutElementPropertyFlexGrow:
|
||||
case ASLayoutElementPropertyFlexShrink:
|
||||
case ASLayoutElementPropertyAlignSelf:
|
||||
case ASLayoutElementPropertyFlexBasis:
|
||||
case ASLayoutElementPropertySpacingBefore:
|
||||
case ASLayoutElementPropertySpacingAfter:
|
||||
case ASLayoutElementPropertyAscender:
|
||||
case ASLayoutElementPropertyDescender:
|
||||
default:
|
||||
return nil;
|
||||
}
|
||||
return [ASLayoutElementInspectorCell attributedStringFromString:valueString];
|
||||
}
|
||||
|
||||
- (void)endEditingValue
|
||||
{
|
||||
_textBubble = nil;
|
||||
__currentlyOpenedCell = nil;
|
||||
_buttonNode.selected = NO;
|
||||
[self setNeedsLayout];
|
||||
}
|
||||
|
||||
- (void)beginEditingValue
|
||||
{
|
||||
_textBubble.delegate = self;
|
||||
__currentlyOpenedCell = self;
|
||||
[self setNeedsLayout];
|
||||
}
|
||||
|
||||
- (void)valueChangedToIndex:(NSUInteger)index
|
||||
{
|
||||
switch (_propertyType) {
|
||||
|
||||
case ASLayoutElementPropertyAlignSelf:
|
||||
_layoutElementToEdit.style.alignSelf = index;
|
||||
_textNode.attributedText = [ASLayoutElementInspectorCell attributedStringFromString:[ASLayoutElementInspectorCell alignSelfEnumValueString:index]];
|
||||
break;
|
||||
|
||||
case ASLayoutElementPropertySpacingBefore:
|
||||
_layoutElementToEdit.style.spacingBefore = (CGFloat)index;
|
||||
_textNode.attributedText = [ASLayoutElementInspectorCell attributedStringFromString:[NSString stringWithFormat:@"%0.0f", _layoutElementToEdit.style.spacingBefore]];
|
||||
break;
|
||||
|
||||
case ASLayoutElementPropertySpacingAfter:
|
||||
_layoutElementToEdit.style.spacingAfter = (CGFloat)index;
|
||||
_textNode.attributedText = [ASLayoutElementInspectorCell attributedStringFromString:[NSString stringWithFormat:@"%0.0f", _layoutElementToEdit.style.spacingAfter]];
|
||||
break;
|
||||
|
||||
case ASLayoutElementPropertyAscender:
|
||||
_layoutElementToEdit.style.ascender = (CGFloat)index;
|
||||
_textNode.attributedText = [ASLayoutElementInspectorCell attributedStringFromString:[NSString stringWithFormat:@"%0.0f", _layoutElementToEdit.style.ascender]];
|
||||
break;
|
||||
|
||||
case ASLayoutElementPropertyDescender:
|
||||
_layoutElementToEdit.style.descender = (CGFloat)index;
|
||||
_textNode.attributedText = [ASLayoutElementInspectorCell attributedStringFromString:[NSString stringWithFormat:@"%0.0f", _layoutElementToEdit.style.descender]];
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
[self setNeedsLayout];
|
||||
}
|
||||
|
||||
#pragma mark - gesture handling
|
||||
|
||||
- (void)buttonTapped:(ASButtonNode *)sender
|
||||
{
|
||||
BOOL selfIsEditing = (self == __currentlyOpenedCell);
|
||||
[__currentlyOpenedCell endEditingValue];
|
||||
if (selfIsEditing) {
|
||||
sender.selected = NO;
|
||||
return;
|
||||
}
|
||||
|
||||
// NSUInteger currentAlignSelfValue;
|
||||
// NSUInteger nextAlignSelfValue;
|
||||
// CGFloat newValue;
|
||||
|
||||
sender.selected = !sender.selected;
|
||||
switch (_propertyType) {
|
||||
|
||||
case ASLayoutElementPropertyFlexGrow:
|
||||
_layoutElementToEdit.style.flexGrow = sender.isSelected ? 1.0 : 0.0;
|
||||
_textNode.attributedText = [ASLayoutElementInspectorCell attributedStringFromString:sender.selected ? @"YES" : @"NO"];
|
||||
break;
|
||||
|
||||
case ASLayoutElementPropertyFlexShrink:
|
||||
_layoutElementToEdit.style.flexShrink = sender.isSelected ? 1.0 : 0.0;
|
||||
_textNode.attributedText = [ASLayoutElementInspectorCell attributedStringFromString:sender.selected ? @"YES" : @"NO"];
|
||||
break;
|
||||
|
||||
case ASLayoutElementPropertyAlignSelf:
|
||||
_textBubble = [[ASLayoutElementInspectorCellEditingBubble alloc] initWithEnumOptions:YES
|
||||
enumStrings:[ASLayoutElementInspectorCell alignSelfEnumStringArray]
|
||||
currentOptionIndex:_layoutElementToEdit.style.alignSelf];
|
||||
|
||||
[self beginEditingValue];
|
||||
// if ([self layoutSpec]) {
|
||||
// currentAlignSelfValue = [[self layoutSpec] alignSelf];
|
||||
// nextAlignSelfValue = (currentAlignSelfValue + 1 <= ASStackLayoutAlignSelfStretch) ? currentAlignSelfValue + 1 : 0;
|
||||
// [[self layoutSpec] setAlignSelf:nextAlignSelfValue];
|
||||
//
|
||||
// } else if ([self node]) {
|
||||
// currentAlignSelfValue = [[self node] alignSelf];
|
||||
// nextAlignSelfValue = (currentAlignSelfValue + 1 <= ASStackLayoutAlignSelfStretch) ? currentAlignSelfValue + 1 : 0;
|
||||
// [[self node] setAlignSelf:nextAlignSelfValue];
|
||||
// }
|
||||
break;
|
||||
|
||||
case ASLayoutElementPropertySpacingBefore:
|
||||
_textBubble = [[ASLayoutElementInspectorCellEditingBubble alloc] initWithSliderMinValue:0 maxValue:100 currentValue:_layoutElementToEdit.style.spacingBefore];
|
||||
[self beginEditingValue];
|
||||
_textNode.attributedText = [ASLayoutElementInspectorCell attributedStringFromString:[NSString stringWithFormat:@"%0.0f", _layoutElementToEdit.style.spacingBefore]];
|
||||
break;
|
||||
|
||||
case ASLayoutElementPropertySpacingAfter:
|
||||
_textBubble = [[ASLayoutElementInspectorCellEditingBubble alloc] initWithSliderMinValue:0 maxValue:100 currentValue:_layoutElementToEdit.style.spacingAfter];
|
||||
[self beginEditingValue];
|
||||
_textNode.attributedText = [ASLayoutElementInspectorCell attributedStringFromString:[NSString stringWithFormat:@"%0.0f", _layoutElementToEdit.style.spacingAfter]];
|
||||
break;
|
||||
|
||||
|
||||
case ASLayoutElementPropertyAscender:
|
||||
_textBubble = [[ASLayoutElementInspectorCellEditingBubble alloc] initWithSliderMinValue:0 maxValue:100 currentValue:_layoutElementToEdit.style.ascender];
|
||||
[self beginEditingValue];
|
||||
_textNode.attributedText = [ASLayoutElementInspectorCell attributedStringFromString:[NSString stringWithFormat:@"%0.0f", _layoutElementToEdit.style.ascender]];
|
||||
break;
|
||||
|
||||
case ASLayoutElementPropertyDescender:
|
||||
_textBubble = [[ASLayoutElementInspectorCellEditingBubble alloc] initWithSliderMinValue:0 maxValue:100 currentValue:_layoutElementToEdit.style.descender];
|
||||
[self beginEditingValue];
|
||||
_textNode.attributedText = [ASLayoutElementInspectorCell attributedStringFromString:[NSString stringWithFormat:@"%0.0f", _layoutElementToEdit.style.descender]];
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
[self setNeedsLayout];
|
||||
}
|
||||
|
||||
#pragma mark - cast layoutElementToEdit
|
||||
|
||||
- (ASDisplayNode *)node
|
||||
{
|
||||
if (_layoutElementToEdit.layoutElementType == ASLayoutElementTypeDisplayNode) {
|
||||
return (ASDisplayNode *)_layoutElementToEdit;
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (ASLayoutSpec *)layoutSpec
|
||||
{
|
||||
if (_layoutElementToEdit.layoutElementType == ASLayoutElementTypeLayoutSpec) {
|
||||
return (ASLayoutSpec *)_layoutElementToEdit;
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
|
||||
#pragma mark - data / property type helper methods
|
||||
|
||||
+ (CellDataType)dataTypeForProperty:(ASLayoutElementPropertyType)property
|
||||
{
|
||||
switch (property) {
|
||||
|
||||
case ASLayoutElementPropertyFlexGrow:
|
||||
case ASLayoutElementPropertyFlexShrink:
|
||||
return CellDataTypeBool;
|
||||
|
||||
case ASLayoutElementPropertySpacingBefore:
|
||||
case ASLayoutElementPropertySpacingAfter:
|
||||
case ASLayoutElementPropertyAscender:
|
||||
case ASLayoutElementPropertyDescender:
|
||||
return CellDataTypeFloat;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return CellDataTypeBool;
|
||||
}
|
||||
|
||||
+ (NSString *)propertyStringForPropertyType:(ASLayoutElementPropertyType)property
|
||||
{
|
||||
NSString *string;
|
||||
switch (property) {
|
||||
case ASLayoutElementPropertyFlexGrow:
|
||||
string = @"FlexGrow";
|
||||
break;
|
||||
case ASLayoutElementPropertyFlexShrink:
|
||||
string = @"FlexShrink";
|
||||
break;
|
||||
case ASLayoutElementPropertyAlignSelf:
|
||||
string = @"AlignSelf";
|
||||
break;
|
||||
case ASLayoutElementPropertyFlexBasis:
|
||||
string = @"FlexBasis";
|
||||
break;
|
||||
case ASLayoutElementPropertySpacingBefore:
|
||||
string = @"SpacingBefore";
|
||||
break;
|
||||
case ASLayoutElementPropertySpacingAfter:
|
||||
string = @"SpacingAfter";
|
||||
break;
|
||||
case ASLayoutElementPropertyAscender:
|
||||
string = @"Ascender";
|
||||
break;
|
||||
case ASLayoutElementPropertyDescender:
|
||||
string = @"Descender";
|
||||
break;
|
||||
default:
|
||||
string = @"Unknown";
|
||||
break;
|
||||
}
|
||||
return string;
|
||||
}
|
||||
|
||||
+ (NSDictionary *)alignSelfTypeNames
|
||||
{
|
||||
return @{@(ASStackLayoutAlignSelfAuto) : @"Auto",
|
||||
@(ASStackLayoutAlignSelfStart) : @"Start",
|
||||
@(ASStackLayoutAlignSelfEnd) : @"End",
|
||||
@(ASStackLayoutAlignSelfCenter) : @"Center",
|
||||
@(ASStackLayoutAlignSelfStretch) : @"Stretch"};
|
||||
}
|
||||
|
||||
+ (NSString *)alignSelfEnumValueString:(NSUInteger)type
|
||||
{
|
||||
return [[self class] alignSelfTypeNames][@(type)];
|
||||
}
|
||||
|
||||
+ (NSArray <NSString *> *)alignSelfEnumStringArray
|
||||
{
|
||||
return @[@"ASStackLayoutAlignSelfAuto",
|
||||
@"ASStackLayoutAlignSelfStart",
|
||||
@"ASStackLayoutAlignSelfEnd",
|
||||
@"ASStackLayoutAlignSelfCenter",
|
||||
@"ASStackLayoutAlignSelfStretch"];
|
||||
}
|
||||
|
||||
+ (NSDictionary *)ASRelativeDimensionTypeNames
|
||||
{
|
||||
return @{@(ASDimensionUnitPoints) : @"pts",
|
||||
@(ASDimensionUnitFraction) : @"%"};
|
||||
}
|
||||
|
||||
+ (NSString *)ASRelativeDimensionEnumString:(NSUInteger)type
|
||||
{
|
||||
return [[self class] ASRelativeDimensionTypeNames][@(type)];
|
||||
}
|
||||
|
||||
#pragma mark - formatting helper methods
|
||||
|
||||
+ (NSAttributedString *)attributedStringFromString:(NSString *)string
|
||||
{
|
||||
return [ASLayoutElementInspectorCell attributedStringFromString:string withTextColor:[UIColor whiteColor]];
|
||||
}
|
||||
|
||||
+ (NSAttributedString *)attributedStringFromString:(NSString *)string withTextColor:(nullable UIColor *)color
|
||||
{
|
||||
NSDictionary *attributes = @{NSForegroundColorAttributeName : color,
|
||||
NSFontAttributeName : [UIFont fontWithName:@"Menlo-Regular" size:12]};
|
||||
|
||||
return [[NSAttributedString alloc] initWithString:string attributes:attributes];
|
||||
}
|
||||
|
||||
- (ASButtonNode *)makeBtnNodeWithTitle:(NSString *)title
|
||||
{
|
||||
UIColor *orangeColor = [UIColor colorWithRed:255/255.0 green:181/255.0 blue:68/255.0 alpha:1];
|
||||
UIImage *orangeStretchBtnImg = [ASLayoutElementInspectorCell imageForButtonWithBackgroundColor:orangeColor
|
||||
borderColor:[UIColor whiteColor]
|
||||
borderWidth:3];
|
||||
UIImage *greyStretchBtnImg = [ASLayoutElementInspectorCell imageForButtonWithBackgroundColor:[UIColor darkGrayColor]
|
||||
borderColor:[UIColor lightGrayColor]
|
||||
borderWidth:3];
|
||||
UIImage *clearStretchBtnImg = [ASLayoutElementInspectorCell imageForButtonWithBackgroundColor:[UIColor clearColor]
|
||||
borderColor:[UIColor whiteColor]
|
||||
borderWidth:3];
|
||||
ASButtonNode *btn = [[ASButtonNode alloc] init];
|
||||
btn.contentEdgeInsets = UIEdgeInsetsMake(5, 5, 5, 5);
|
||||
[btn setAttributedTitle:[ASLayoutElementInspectorCell attributedStringFromString:title] forState:ASControlStateNormal];
|
||||
[btn setAttributedTitle:[ASLayoutElementInspectorCell attributedStringFromString:title withTextColor:[UIColor lightGrayColor]] forState:ASControlStateDisabled];
|
||||
[btn setBackgroundImage:clearStretchBtnImg forState:ASControlStateNormal];
|
||||
[btn setBackgroundImage:orangeStretchBtnImg forState:ASControlStateSelected];
|
||||
[btn setBackgroundImage:greyStretchBtnImg forState:ASControlStateDisabled];
|
||||
|
||||
return btn;
|
||||
}
|
||||
|
||||
#define CORNER_RADIUS 3
|
||||
+ (UIImage *)imageForButtonWithBackgroundColor:(UIColor *)backgroundColor borderColor:(UIColor *)borderColor borderWidth:(CGFloat)width
|
||||
{
|
||||
CGSize unstretchedSize = CGSizeMake(2 * CORNER_RADIUS + 1, 2 * CORNER_RADIUS + 1);
|
||||
CGRect rect = (CGRect) {CGPointZero, unstretchedSize};
|
||||
UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:rect cornerRadius:CORNER_RADIUS];
|
||||
|
||||
// create a graphics context for the following status button
|
||||
UIGraphicsBeginImageContextWithOptions(unstretchedSize, NO, 0);
|
||||
|
||||
[path addClip];
|
||||
[backgroundColor setFill];
|
||||
[path fill];
|
||||
|
||||
path.lineWidth = width;
|
||||
[borderColor setStroke];
|
||||
[path stroke];
|
||||
|
||||
UIImage *btnImage = UIGraphicsGetImageFromCurrentImageContext();
|
||||
UIGraphicsEndImageContext();
|
||||
|
||||
return [btnImage stretchableImageWithLeftCapWidth:CORNER_RADIUS topCapHeight:CORNER_RADIUS];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
|
||||
@implementation ASLayoutElementInspectorCellEditingBubble
|
||||
{
|
||||
NSMutableArray<ASButtonNode *> *_textNodes;
|
||||
ASDisplayNode *_slider;
|
||||
}
|
||||
|
||||
- (instancetype)initWithEnumOptions:(BOOL)yes enumStrings:(NSArray<NSString *> *)options currentOptionIndex:(NSUInteger)currentOption
|
||||
{
|
||||
self = [super init];
|
||||
if (self) {
|
||||
self.automaticallyManagesSubnodes = YES;
|
||||
self.backgroundColor = [UIColor colorWithRed:255/255.0 green:181/255.0 blue:68/255.0 alpha:1];
|
||||
|
||||
_textNodes = [[NSMutableArray alloc] init];
|
||||
int index = 0;
|
||||
for (NSString *optionStr in options) {
|
||||
ASButtonNode *btn = [[ASButtonNode alloc] init];
|
||||
[btn setAttributedTitle:[ASLayoutElementInspectorCell attributedStringFromString:optionStr] forState:ASControlStateNormal];
|
||||
[btn setAttributedTitle:[ASLayoutElementInspectorCell attributedStringFromString:optionStr withTextColor:[UIColor redColor]]
|
||||
forState:ASControlStateSelected];
|
||||
[btn addTarget:self action:@selector(enumOptionSelected:) forControlEvents:ASControlNodeEventTouchUpInside];
|
||||
btn.selected = (index == currentOption) ? YES : NO;
|
||||
[_textNodes addObject:btn];
|
||||
index++;
|
||||
}
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (instancetype)initWithSliderMinValue:(CGFloat)min maxValue:(CGFloat)max currentValue:(CGFloat)current
|
||||
{
|
||||
if (self = [super init]) {
|
||||
self.userInteractionEnabled = YES;
|
||||
self.automaticallyManagesSubnodes = YES;
|
||||
self.backgroundColor = [UIColor colorWithRed:255/255.0 green:181/255.0 blue:68/255.0 alpha:1];
|
||||
|
||||
__weak id weakSelf = self;
|
||||
_slider = [[ASDisplayNode alloc] initWithViewBlock:^UIView * _Nonnull{
|
||||
UISlider *slider = [[UISlider alloc] init];
|
||||
slider.minimumValue = min;
|
||||
slider.maximumValue = max;
|
||||
slider.value = current;
|
||||
[slider addTarget:weakSelf action:@selector(sliderValueChanged:) forControlEvents:UIControlEventValueChanged];
|
||||
|
||||
return slider;
|
||||
}];
|
||||
_slider.userInteractionEnabled = YES;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (ASLayoutSpec *)layoutSpecThatFits:(ASSizeRange)constrainedSize
|
||||
{
|
||||
_slider.style.preferredSize = CGSizeMake(constrainedSize.max.width, 25);
|
||||
|
||||
NSMutableArray *children = [[NSMutableArray alloc] init];
|
||||
if (_textNodes) {
|
||||
ASStackLayoutSpec *textStack = [ASStackLayoutSpec verticalStackLayoutSpec];
|
||||
textStack.children = _textNodes;
|
||||
textStack.spacing = 2;
|
||||
[children addObject:textStack];
|
||||
}
|
||||
if (_slider) {
|
||||
_slider.style.flexGrow = 1.0;
|
||||
[children addObject:_slider];
|
||||
}
|
||||
|
||||
ASStackLayoutSpec *verticalStackSpec = [ASStackLayoutSpec verticalStackLayoutSpec];
|
||||
verticalStackSpec.children = children;
|
||||
verticalStackSpec.spacing = 2;
|
||||
verticalStackSpec.style.flexGrow = 1.0;
|
||||
verticalStackSpec.style.alignSelf = ASStackLayoutAlignSelfStretch;
|
||||
|
||||
ASInsetLayoutSpec *insetSpec = [ASInsetLayoutSpec insetLayoutSpecWithInsets:UIEdgeInsetsMake(8, 8, 8, 8) child:verticalStackSpec];
|
||||
|
||||
return insetSpec;
|
||||
}
|
||||
|
||||
#pragma mark - gesture handling
|
||||
- (void)enumOptionSelected:(ASButtonNode *)sender
|
||||
{
|
||||
sender.selected = !sender.selected;
|
||||
for (ASButtonNode *node in _textNodes) {
|
||||
if (node != sender) {
|
||||
node.selected = NO;
|
||||
}
|
||||
}
|
||||
[self.delegate valueChangedToIndex:[_textNodes indexOfObject:sender]];
|
||||
[self setNeedsLayout];
|
||||
}
|
||||
|
||||
- (void)sliderValueChanged:(UISlider *)sender
|
||||
{
|
||||
[self.delegate valueChangedToIndex:roundf(sender.value)];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
25
AsyncDisplayKit/Debug/ASLayoutElementInspectorNode.h
Normal file
25
AsyncDisplayKit/Debug/ASLayoutElementInspectorNode.h
Normal file
@@ -0,0 +1,25 @@
|
||||
//
|
||||
// ASLayoutElementInspectorNode.h
|
||||
// Sample
|
||||
//
|
||||
// Created by Hannah Troisi on 3/19/16.
|
||||
// Copyright © 2016 Facebook. All rights reserved.
|
||||
//
|
||||
|
||||
#import <AsyncDisplayKit/AsyncDisplayKit.h>
|
||||
|
||||
@protocol ASLayoutElementInspectorNodeDelegate <NSObject>
|
||||
|
||||
- (void)toggleVisualization:(BOOL)toggle;
|
||||
|
||||
@end
|
||||
|
||||
@interface ASLayoutElementInspectorNode : ASDisplayNode
|
||||
|
||||
@property (nonatomic, strong) id<ASLayoutElement> layoutElementToEdit;
|
||||
@property (nonatomic, strong) id<ASLayoutElementInspectorNodeDelegate> delegate;
|
||||
@property (nonatomic, assign) CGFloat vizNodeInsetSize;
|
||||
|
||||
+ (instancetype)sharedInstance;
|
||||
|
||||
@end
|
||||
406
AsyncDisplayKit/Debug/ASLayoutElementInspectorNode.m
Normal file
406
AsyncDisplayKit/Debug/ASLayoutElementInspectorNode.m
Normal file
@@ -0,0 +1,406 @@
|
||||
//
|
||||
// ASLayoutElementInspectorNode.m
|
||||
// Sample
|
||||
//
|
||||
// Created by Hannah Troisi on 3/19/16.
|
||||
// Copyright © 2016 Facebook. All rights reserved.
|
||||
//
|
||||
|
||||
#import "ASLayoutElementInspectorNode.h"
|
||||
#import "ASLayoutElementInspectorCell.h"
|
||||
#import "ASDisplayNode+Beta.h"
|
||||
#import "ASLayoutSpec+Debug.h"
|
||||
#import <AsyncDisplayKit/AsyncDisplayKit.h>
|
||||
|
||||
@interface ASLayoutElementInspectorNode () <ASTableDelegate, ASTableDataSource>
|
||||
@end
|
||||
|
||||
@implementation ASLayoutElementInspectorNode
|
||||
{
|
||||
ASTableNode *_tableNode;
|
||||
}
|
||||
|
||||
#pragma mark - class methods
|
||||
+ (instancetype)sharedInstance
|
||||
{
|
||||
static ASLayoutElementInspectorNode *__inspector = nil;
|
||||
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
__inspector = [[ASLayoutElementInspectorNode alloc] init];
|
||||
});
|
||||
|
||||
return __inspector;
|
||||
}
|
||||
|
||||
#pragma mark - lifecycle
|
||||
- (instancetype)init
|
||||
{
|
||||
self = [super init];
|
||||
if (self) {
|
||||
|
||||
_tableNode = [[ASTableNode alloc] init];
|
||||
_tableNode.delegate = self;
|
||||
_tableNode.dataSource = self;
|
||||
|
||||
[self addSubnode:_tableNode]; // required because of manual layout
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)didLoad
|
||||
{
|
||||
[super didLoad];
|
||||
_tableNode.view.backgroundColor = [UIColor colorWithRed:40/255.0 green:43/255.0 blue:53/255.0 alpha:1];
|
||||
_tableNode.view.separatorStyle = UITableViewCellSeparatorStyleNone;
|
||||
_tableNode.view.allowsSelection = NO;
|
||||
_tableNode.view.sectionHeaderHeight = 40;
|
||||
}
|
||||
|
||||
- (void)layout
|
||||
{
|
||||
[super layout];
|
||||
_tableNode.frame = self.bounds;
|
||||
}
|
||||
|
||||
#pragma mark - intstance methods
|
||||
- (void)setLayoutElementToEdit:(id<ASLayoutElement>)layoutElementToEdit
|
||||
{
|
||||
if (_layoutElementToEdit != layoutElementToEdit) {
|
||||
_layoutElementToEdit = layoutElementToEdit;
|
||||
}
|
||||
[_tableNode reloadData];
|
||||
}
|
||||
|
||||
#pragma mark - ASTableDataSource
|
||||
|
||||
- (ASCellNode *)tableView:(ASTableView *)tableView nodeForRowAtIndexPath:(NSIndexPath *)indexPath
|
||||
{
|
||||
if (indexPath.section == 0) {
|
||||
NSDictionary *attributes = @{NSForegroundColorAttributeName : [UIColor colorWithRed:255/255.0 green:181/255.0 blue:68/255.0 alpha:1],
|
||||
NSFontAttributeName : [UIFont fontWithName:@"Menlo-Regular" size:12]};
|
||||
ASTextCellNode *textCell = [[ASTextCellNode alloc] initWithAttributes:attributes insets:UIEdgeInsetsMake(0, 4, 0, 0)];
|
||||
textCell.text = [_layoutElementToEdit description];
|
||||
return textCell;
|
||||
} else {
|
||||
return [[ASLayoutElementInspectorCell alloc] initWithProperty:(ASLayoutElementPropertyType)indexPath.row layoutElementToEdit:_layoutElementToEdit];
|
||||
}
|
||||
}
|
||||
|
||||
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
|
||||
{
|
||||
if (section == 0) {
|
||||
return 1;
|
||||
} else {
|
||||
return ASLayoutElementPropertyCount;
|
||||
}
|
||||
}
|
||||
|
||||
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
|
||||
- (nullable UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
|
||||
{
|
||||
UILabel *headerTitle = [[UILabel alloc] initWithFrame:CGRectZero];
|
||||
|
||||
NSString *title;
|
||||
if (section == 0) {
|
||||
title = @"<Layoutable> Item";
|
||||
} else {
|
||||
title = @"<Layoutable> Properties";
|
||||
}
|
||||
|
||||
NSDictionary *attributes = @{NSForegroundColorAttributeName : [UIColor whiteColor],
|
||||
NSFontAttributeName : [UIFont fontWithName:@"Menlo-Bold" size:12]};
|
||||
headerTitle.attributedText = [[NSAttributedString alloc] initWithString:title attributes:attributes];
|
||||
|
||||
return headerTitle;
|
||||
}
|
||||
|
||||
//- (ASLayoutSpec *)layoutSpecThatFits:(ASSizeRange)constrainedSize
|
||||
//{
|
||||
// // navigate layout hierarchy
|
||||
//
|
||||
// _parentNodeNavBtn.alignSelf = ASStackLayoutAlignSelfCenter;
|
||||
// _childNodeNavBtn.alignSelf = ASStackLayoutAlignSelfCenter;
|
||||
//
|
||||
// ASStackLayoutSpec *horizontalStackNav = [ASStackLayoutSpec horizontalStackLayoutSpec];
|
||||
// horizontalStackNav.style.flexGrow = 1.0;
|
||||
// horizontalStackNav.alignSelf = ASStackLayoutAlignSelfCenter;
|
||||
// horizontalStackNav.children = @[_siblingNodeLefttNavBtn, _siblingNodeRightNavBtn];
|
||||
//
|
||||
// ASStackLayoutSpec *horizontalStack = [ASStackLayoutSpec horizontalStackLayoutSpec];
|
||||
// horizontalStack.style.flexGrow = 1.0;
|
||||
// ASLayoutSpec *spacer = [[ASLayoutSpec alloc] init];
|
||||
//
|
||||
// spacer.style.flexGrow = 1.0;
|
||||
// horizontalStack.children = @[_flexGrowBtn, spacer];
|
||||
// _flexGrowValue.alignSelf = ASStackLayoutAlignSelfEnd; // FIXME: make framework give a warning if you use ASAlignmentBottom!!!!!
|
||||
//
|
||||
// ASStackLayoutSpec *horizontalStack2 = [ASStackLayoutSpec horizontalStackLayoutSpec];
|
||||
// horizontalStack2.style.flexGrow = 1.0;
|
||||
// horizontalStack2.children = @[_flexShrinkBtn, spacer];
|
||||
// _flexShrinkValue.alignSelf = ASStackLayoutAlignSelfEnd;
|
||||
//
|
||||
// ASStackLayoutSpec *horizontalStack3 = [ASStackLayoutSpec horizontalStackLayoutSpec];
|
||||
// horizontalStack3.style.flexGrow = 1.0;
|
||||
// horizontalStack3.children = @[_flexBasisBtn, spacer, _flexBasisValue];
|
||||
// _flexBasisValue.alignSelf = ASStackLayoutAlignSelfEnd;
|
||||
//
|
||||
// ASStackLayoutSpec *itemDescriptionStack = [ASStackLayoutSpec verticalStackLayoutSpec];
|
||||
// itemDescriptionStack.children = @[_itemDescription];
|
||||
// itemDescriptionStack.spacing = 5;
|
||||
// itemDescriptionStack.style.flexGrow = 1.0;
|
||||
//
|
||||
// ASStackLayoutSpec *layoutableStack = [ASStackLayoutSpec verticalStackLayoutSpec];
|
||||
// layoutableStack.children = @[_layoutablePropertiesSectionTitle, horizontalStack, horizontalStack2, horizontalStack3, _alignSelfBtn];
|
||||
// layoutableStack.spacing = 5;
|
||||
// layoutableStack.style.flexGrow = 1.0;
|
||||
//
|
||||
// ASStackLayoutSpec *layoutSpecStack = [ASStackLayoutSpec verticalStackLayoutSpec];
|
||||
// layoutSpecStack.children = @[_layoutSpecPropertiesSectionTitle, _alignItemsBtn];
|
||||
// layoutSpecStack.spacing = 5;
|
||||
// layoutSpecStack.style.flexGrow = 1.0;
|
||||
//
|
||||
// ASStackLayoutSpec *debugHelpStack = [ASStackLayoutSpec verticalStackLayoutSpec];
|
||||
// debugHelpStack.children = @[_debugSectionTitle, _vizNodeInsetSizeBtn, _vizNodeBordersBtn];
|
||||
// debugHelpStack.spacing = 5;
|
||||
// debugHelpStack.style.flexGrow = 1.0;
|
||||
//
|
||||
// ASStackLayoutSpec *verticalLayoutableStack = [ASStackLayoutSpec verticalStackLayoutSpec];
|
||||
// verticalLayoutableStack.style.flexGrow = 1.0;
|
||||
// verticalLayoutableStack.spacing = 20;
|
||||
// verticalLayoutableStack.children = @[_parentNodeNavBtn, horizontalStackNav, _childNodeNavBtn, itemDescriptionStack, layoutableStack, layoutSpecStack, debugHelpStack];
|
||||
// verticalLayoutableStack.alignItems = ASStackLayoutAlignItemsStretch; // stretch headerStack to fill horizontal space
|
||||
//
|
||||
// ASLayoutSpec *insetSpec = [ASInsetLayoutSpec insetLayoutSpecWithInsets:UIEdgeInsetsMake(100, 10, 10, 10) child:verticalLayoutableStack];
|
||||
// insetSpec.style.flexGrow = 1.0;
|
||||
// return insetSpec;
|
||||
//}
|
||||
//
|
||||
//#pragma mark - configure Inspector node for layoutable
|
||||
//- (void)updateInspectorWithLayoutable
|
||||
//{
|
||||
// _itemDescription.attributedText = [self attributedStringFromLayoutable:_layoutElementToEdit];
|
||||
//
|
||||
// if ([self node]) {
|
||||
// UIColor *nodeBackgroundColor = [[self node] backgroundColor];
|
||||
// UIImage *colorBtnImg = [ASLayoutElementInspectorNode imageForButtonWithBackgroundColor:nodeBackgroundColor
|
||||
// borderColor:[UIColor whiteColor]
|
||||
// borderWidth:3];
|
||||
// [_itemBackgroundColorBtn setBackgroundImage:colorBtnImg forState:ASControlStateNormal];
|
||||
// } else {
|
||||
// _itemBackgroundColorBtn.enabled = NO;
|
||||
// }
|
||||
//
|
||||
// _flexGrowBtn.selected = [self.layoutElementToEdit flexGrow];
|
||||
// _flexGrowValue.attributedText = [self attributedStringFromString: (_flexGrowBtn.selected) ? @"YES" : @"NO"];
|
||||
//
|
||||
// _flexShrinkBtn.selected = self.layoutElementToEdit.style.flexShrink;
|
||||
// _flexShrinkValue.attributedText = [self attributedStringFromString: (_flexShrinkBtn.selected) ? @"YES" : @"NO"];
|
||||
//
|
||||
// // _flexBasisBtn.selected = self.layoutElementToEdit.style.flexShrink;
|
||||
// // _flexBasisValue.attributedText = [self attributedStringFromString: (_flexBasisBtn.selected) ? @"YES" : @"NO"];
|
||||
//
|
||||
//
|
||||
// NSUInteger alignSelfValue = [self.layoutElementToEdit alignSelf];
|
||||
// NSString *newTitle = [@"alignSelf:" stringByAppendingString:[self alignSelfName:alignSelfValue]];
|
||||
// [_alignSelfBtn setAttributedTitle:[self attributedStringFromString:newTitle] forState:ASControlStateNormal];
|
||||
//
|
||||
// if ([self layoutSpec]) {
|
||||
// _alignItemsBtn.enabled = YES;
|
||||
//// NSUInteger alignItemsValue = [[self layoutSpec] alignItems];
|
||||
//// newTitle = [@"alignItems:" stringByAppendingString:[self alignSelfName:alignItemsValue]];
|
||||
//// [_alignItemsBtn setAttributedTitle:[self attributedStringFromString:newTitle] forState:ASControlStateNormal];
|
||||
// }
|
||||
//
|
||||
// [self setNeedsLayout];
|
||||
//}
|
||||
|
||||
|
||||
//- (void)enableInspectorNodesForLayoutable
|
||||
//{
|
||||
// if ([self layoutSpec]) {
|
||||
//
|
||||
// _itemBackgroundColorBtn.enabled = YES;
|
||||
// _flexGrowBtn.enabled = YES;
|
||||
// _flexShrinkBtn.enabled = YES;
|
||||
// _flexBasisBtn.enabled = YES;
|
||||
// _alignSelfBtn.enabled = YES;
|
||||
// _spacingBeforeBtn.enabled = YES;
|
||||
// _spacingAfterBtn.enabled = YES;
|
||||
// _alignItemsBtn.enabled = YES;
|
||||
//
|
||||
// } else if ([self node]) {
|
||||
//
|
||||
// _itemBackgroundColorBtn.enabled = YES;
|
||||
// _flexGrowBtn.enabled = YES;
|
||||
// _flexShrinkBtn.enabled = YES;
|
||||
// _flexBasisBtn.enabled = YES;
|
||||
// _alignSelfBtn.enabled = YES;
|
||||
// _spacingBeforeBtn.enabled = YES;
|
||||
// _spacingAfterBtn.enabled = YES;
|
||||
// _alignItemsBtn.enabled = NO;
|
||||
//
|
||||
// } else {
|
||||
//
|
||||
// _itemBackgroundColorBtn.enabled = NO;
|
||||
// _flexGrowBtn.enabled = NO;
|
||||
// _flexShrinkBtn.enabled = NO;
|
||||
// _flexBasisBtn.enabled = NO;
|
||||
// _alignSelfBtn.enabled = NO;
|
||||
// _spacingBeforeBtn.enabled = NO;
|
||||
// _spacingAfterBtn.enabled = NO;
|
||||
// _alignItemsBtn.enabled = YES;
|
||||
// }
|
||||
//}
|
||||
|
||||
//+ (NSDictionary *)alignSelfTypeNames
|
||||
//{
|
||||
// return @{@(ASStackLayoutAlignSelfAuto) : @"Auto",
|
||||
// @(ASStackLayoutAlignSelfStart) : @"Start",
|
||||
// @(ASStackLayoutAlignSelfEnd) : @"End",
|
||||
// @(ASStackLayoutAlignSelfCenter) : @"Center",
|
||||
// @(ASStackLayoutAlignSelfStretch) : @"Stretch"};
|
||||
//}
|
||||
//
|
||||
//- (NSString *)alignSelfName:(NSUInteger)type
|
||||
//{
|
||||
// return [[self class] alignSelfTypeNames][@(type)];
|
||||
//}
|
||||
//
|
||||
//+ (NSDictionary *)alignItemTypeNames
|
||||
//{
|
||||
// return @{@(ASStackLayoutAlignItemsBaselineFirst) : @"BaselineFirst",
|
||||
// @(ASStackLayoutAlignItemsBaselineLast) : @"BaselineLast",
|
||||
// @(ASStackLayoutAlignItemsCenter) : @"Center",
|
||||
// @(ASStackLayoutAlignItemsEnd) : @"End",
|
||||
// @(ASStackLayoutAlignItemsStart) : @"Start",
|
||||
// @(ASStackLayoutAlignItemsStretch) : @"Stretch"};
|
||||
//}
|
||||
//
|
||||
//- (NSString *)alignItemName:(NSUInteger)type
|
||||
//{
|
||||
// return [[self class] alignItemTypeNames][@(type)];
|
||||
//}
|
||||
|
||||
//#pragma mark - gesture handling
|
||||
//- (void)changeColor:(ASButtonNode *)sender
|
||||
//{
|
||||
// if ([self node]) {
|
||||
// NSArray *colorArray = @[[UIColor orangeColor],
|
||||
// [UIColor redColor],
|
||||
// [UIColor greenColor],
|
||||
// [UIColor purpleColor]];
|
||||
//
|
||||
// UIColor *nodeBackgroundColor = [(ASDisplayNode *)self.layoutElementToEdit backgroundColor];
|
||||
//
|
||||
// NSUInteger colorIndex = [colorArray indexOfObject:nodeBackgroundColor];
|
||||
// colorIndex = (colorIndex + 1 < [colorArray count]) ? colorIndex + 1 : 0;
|
||||
//
|
||||
// [[self node] setBackgroundColor: [colorArray objectAtIndex:colorIndex]];
|
||||
// }
|
||||
//
|
||||
// [self updateInspectorWithLayoutable];
|
||||
//}
|
||||
//
|
||||
//- (void)setFlexGrowValue:(ASButtonNode *)sender
|
||||
//{
|
||||
// [sender setSelected:!sender.isSelected]; // FIXME: fix ASControlNode documentation that this is automatic - unlike highlighted, it is up to the application to decide when a button should be selected or not. Selected is a more persistant thing and highlighted is for the moment, like as a user has a finger on it,
|
||||
//
|
||||
// if ([self layoutSpec]) {
|
||||
// [[self layoutSpec] setFlexGrow:sender.isSelected];
|
||||
// } else if ([self node]) {
|
||||
// [[self node] setFlexGrow:sender.isSelected];
|
||||
// }
|
||||
//
|
||||
// [self updateInspectorWithLayoutable];
|
||||
//}
|
||||
//
|
||||
//- (void)setFlexShrinkValue:(ASButtonNode *)sender
|
||||
//{
|
||||
// [sender setSelected:!sender.isSelected]; // FIXME: fix ASControlNode documentation that this is automatic - unlike highlighted, it is up to the application to decide when a button should be selected or not. Selected is a more persistant thing and highlighted is for the moment, like as a user has a finger on it,
|
||||
//
|
||||
// if ([self layoutSpec]) {
|
||||
// [[self layoutSpec] setFlexShrink:sender.isSelected];
|
||||
// } else if ([self node]) {
|
||||
// [[self node] setFlexShrink:sender.isSelected];
|
||||
// }
|
||||
//
|
||||
// [self updateInspectorWithLayoutable];
|
||||
//}
|
||||
//
|
||||
//- (void)setAlignSelfValue:(ASButtonNode *)sender
|
||||
//{
|
||||
// NSUInteger currentAlignSelfValue;
|
||||
// NSUInteger nextAlignSelfValue;
|
||||
//
|
||||
// if ([self layoutSpec]) {
|
||||
// currentAlignSelfValue = [[self layoutSpec] alignSelf];
|
||||
// nextAlignSelfValue = (currentAlignSelfValue + 1 <= ASStackLayoutAlignSelfStretch) ? currentAlignSelfValue + 1 : 0;
|
||||
// [[self layoutSpec] setAlignSelf:nextAlignSelfValue];
|
||||
//
|
||||
// } else if ([self node]) {
|
||||
// currentAlignSelfValue = [[self node] alignSelf];
|
||||
// nextAlignSelfValue = (currentAlignSelfValue + 1 <= ASStackLayoutAlignSelfStretch) ? currentAlignSelfValue + 1 : 0;
|
||||
// [[self node] setAlignSelf:nextAlignSelfValue];
|
||||
// }
|
||||
//
|
||||
// [self updateInspectorWithLayoutable];
|
||||
//}
|
||||
//
|
||||
//- (void)setAlignItemsValue:(ASButtonNode *)sender
|
||||
//{
|
||||
// NSUInteger currentAlignItemsValue;
|
||||
// NSUInteger nextAlignItemsValue;
|
||||
//
|
||||
// if ([self layoutSpec]) {
|
||||
// currentAlignItemsValue = [[self layoutSpec] alignSelf];
|
||||
// nextAlignItemsValue = (currentAlignItemsValue + 1 <= ASStackLayoutAlignSelfStretch) ? currentAlignItemsValue + 1 : 0;
|
||||
//// [[self layoutSpec] setAlignItems:nextAlignItemsValue];
|
||||
//
|
||||
// } else if ([self node]) {
|
||||
// currentAlignItemsValue = [[self node] alignSelf];
|
||||
// nextAlignItemsValue = (currentAlignItemsValue + 1 <= ASStackLayoutAlignSelfStretch) ? currentAlignItemsValue + 1 : 0;
|
||||
//// [[self node] setAlignItems:nextAlignItemsValue];
|
||||
// }
|
||||
//
|
||||
// [self updateInspectorWithLayoutable];
|
||||
//}
|
||||
//- (void)setFlexBasisValue:(ASButtonNode *)sender
|
||||
//{
|
||||
// [sender setSelected:!sender.isSelected]; // FIXME: fix ASControlNode documentation that this is automatic - unlike highlighted, it is up to the application to decide when a button should be selected or not. Selected is a more persistant thing and highlighted is for the moment, like as a user has a finger on it,
|
||||
// FIXME: finish
|
||||
//}
|
||||
//
|
||||
//- (void)setVizNodeInsets:(ASButtonNode *)sender
|
||||
//{
|
||||
// BOOL newState = !sender.selected;
|
||||
//
|
||||
// if (newState == YES) {
|
||||
// self.vizNodeInsetSize = 0;
|
||||
// [self.delegate toggleVisualization:NO]; // FIXME
|
||||
// [self.delegate toggleVisualization:YES]; // FIXME
|
||||
// _vizNodeBordersBtn.selected = YES;
|
||||
//
|
||||
// } else {
|
||||
// self.vizNodeInsetSize = 10;
|
||||
// [self.delegate toggleVisualization:NO]; // FIXME
|
||||
// [self.delegate toggleVisualization:YES]; // FIXME
|
||||
// }
|
||||
//
|
||||
// sender.selected = newState;
|
||||
//}
|
||||
//
|
||||
//- (void)setVizNodeBorders:(ASButtonNode *)sender
|
||||
//{
|
||||
// BOOL newState = !sender.selected;
|
||||
//
|
||||
// [self.delegate toggleVisualization:newState]; // FIXME
|
||||
//
|
||||
// sender.selected = newState;
|
||||
//}
|
||||
|
||||
@end
|
||||
21
AsyncDisplayKit/Debug/ASLayoutSpec+Debug.h
Normal file
21
AsyncDisplayKit/Debug/ASLayoutSpec+Debug.h
Normal file
@@ -0,0 +1,21 @@
|
||||
//
|
||||
// ASLayoutSpec+Debug.h
|
||||
// AsyncDisplayKit
|
||||
//
|
||||
// Created by Hannah Troisi on 3/20/16.
|
||||
//
|
||||
//
|
||||
|
||||
#pragma once
|
||||
#import "ASControlNode.h"
|
||||
|
||||
@class ASLayoutSpec;
|
||||
|
||||
@interface ASLayoutSpecVisualizerNode : ASControlNode
|
||||
|
||||
@property (nonatomic, strong) ASLayoutSpec *layoutSpec;
|
||||
|
||||
- (instancetype)initWithLayoutSpec:(ASLayoutSpec *)layoutSpec;
|
||||
|
||||
@end
|
||||
|
||||
73
AsyncDisplayKit/Debug/ASLayoutSpec+Debug.m
Normal file
73
AsyncDisplayKit/Debug/ASLayoutSpec+Debug.m
Normal file
@@ -0,0 +1,73 @@
|
||||
//
|
||||
// ASLayoutSpec+Debug.m
|
||||
// AsyncDisplayKit
|
||||
//
|
||||
// Created by Hannah Troisi on 3/20/16.
|
||||
//
|
||||
//
|
||||
|
||||
#import "ASLayoutSpec+Debug.h"
|
||||
#import "ASDisplayNode+Beta.h"
|
||||
#import "AsyncDisplayKit.h"
|
||||
#import "ASLayoutElementInspectorNode.h"
|
||||
|
||||
@implementation ASLayoutSpecVisualizerNode
|
||||
|
||||
- (instancetype)initWithLayoutSpec:(ASLayoutSpec *)layoutSpec
|
||||
{
|
||||
self = [super init];
|
||||
if (self) {
|
||||
self.borderWidth = 2;
|
||||
self.borderColor = [[UIColor redColor] CGColor];
|
||||
self.layoutSpec = layoutSpec;
|
||||
self.layoutSpec.neverShouldVisualize = YES;
|
||||
self.automaticallyManagesSubnodes = YES;
|
||||
self.shouldCacheLayoutSpec = YES;
|
||||
[self addTarget:self action:@selector(visualizerNodeTapped:) forControlEvents:ASControlNodeEventTouchUpInside];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (ASLayoutSpec *)layoutSpecThatFits:(ASSizeRange)constrainedSize
|
||||
{
|
||||
CGFloat insetFloat = [ASLayoutElementInspectorNode sharedInstance].vizNodeInsetSize;
|
||||
UIEdgeInsets insets = UIEdgeInsetsMake(insetFloat, insetFloat, insetFloat, insetFloat);
|
||||
|
||||
// FIXME in framework: auto pass properties to children
|
||||
ASInsetLayoutSpec *insetSpec = [ASInsetLayoutSpec insetLayoutSpecWithInsets:insets child:self.layoutSpec];
|
||||
insetSpec.neverShouldVisualize = YES;
|
||||
|
||||
// propogate child's layoutSpec properties to the inset that we are adding
|
||||
// insetSpec.style.flexGrow = _layoutSpec.style.flexGrow;
|
||||
// insetSpec.style.flexShrink = _layoutSpec.style.flexShrink;
|
||||
// insetSpec.alignSelf = _layoutSpec.alignSelf;
|
||||
|
||||
// NSLog(@"%@: vizNode = %f, child = %f", self, insetSpec.style.flexGrow, _layoutSpec.style.flexGrow);
|
||||
|
||||
return insetSpec;
|
||||
}
|
||||
|
||||
- (void)setLayoutSpec:(ASLayoutSpec *)layoutSpec // FIXME: this is duplicated in InspectorNode - make it a category on ASLayoutSpec?
|
||||
{
|
||||
_layoutSpec = layoutSpec; // FIXME: should copy layoutSpec properities to self?
|
||||
|
||||
if ([layoutSpec isKindOfClass:[ASInsetLayoutSpec class]]) {
|
||||
self.borderColor = [[UIColor redColor] CGColor];
|
||||
|
||||
} else if ([layoutSpec isKindOfClass:[ASStackLayoutSpec class]]) {
|
||||
self.borderColor = [[UIColor greenColor] CGColor];
|
||||
}
|
||||
}
|
||||
|
||||
- (NSString *)description
|
||||
{
|
||||
return [self.layoutSpec description]; // FIXME: expand on layoutSpec description (e.g. have StackLayoutSpec return horz/vert)
|
||||
}
|
||||
|
||||
- (void)visualizerNodeTapped:(UIGestureRecognizer *)sender
|
||||
{
|
||||
[[ASLayoutElementInspectorNode sharedInstance] setLayoutElementToEdit:self.layoutSpec];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -60,6 +60,10 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
*/
|
||||
@property (nullable, strong, nonatomic) NSArray<id<ASLayoutElement>> *children;
|
||||
|
||||
@property (nonatomic, assign) BOOL shouldVisualize;
|
||||
@property (nonatomic, assign) BOOL neverShouldVisualize;
|
||||
- (void)recursivelySetShouldVisualize:(BOOL)visualize;
|
||||
|
||||
@end
|
||||
|
||||
/**
|
||||
|
||||
@@ -12,6 +12,11 @@
|
||||
#import "ASLayoutSpecPrivate.h"
|
||||
#import "ASLayoutSpec+Subclasses.h"
|
||||
#import "ASLayoutElementStylePrivate.h"
|
||||
#import "ASLayoutSpec+Debug.h"
|
||||
|
||||
#import <objc/runtime.h>
|
||||
#import <map>
|
||||
#import <vector>
|
||||
|
||||
@implementation ASLayoutSpec
|
||||
|
||||
@@ -60,7 +65,34 @@
|
||||
|
||||
- (id<ASLayoutElement>)finalLayoutElement
|
||||
{
|
||||
if (ASLayoutElementGetCurrentContext().needsVisualizeNode && !self.neverShouldVisualize) {
|
||||
return [[ASLayoutSpecVisualizerNode alloc] initWithLayoutSpec:self];
|
||||
} else {
|
||||
return self;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)recursivelySetShouldVisualize:(BOOL)visualize
|
||||
{
|
||||
NSMutableArray *mutableChildren = [self.children mutableCopy];
|
||||
|
||||
for (id<ASLayoutElement>layoutElement in self.children) {
|
||||
if (layoutElement.layoutElementType == ASLayoutElementTypeLayoutSpec) {
|
||||
ASLayoutSpec *layoutSpec = (ASLayoutSpec *)layoutElement;
|
||||
|
||||
[mutableChildren replaceObjectAtIndex:[mutableChildren indexOfObjectIdenticalTo:layoutSpec]
|
||||
withObject:[[ASLayoutSpecVisualizerNode alloc] initWithLayoutSpec:layoutSpec]];
|
||||
|
||||
[layoutSpec recursivelySetShouldVisualize:visualize];
|
||||
layoutSpec.shouldVisualize = visualize;
|
||||
}
|
||||
}
|
||||
|
||||
if ([mutableChildren count] == 1) { // HACK for wrapper layoutSpecs (e.g. insetLayoutSpec)
|
||||
self.child = mutableChildren[0];
|
||||
} else if ([mutableChildren count] > 1) {
|
||||
self.children = mutableChildren;
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - Style
|
||||
@@ -113,6 +145,9 @@
|
||||
ASDisplayNodeAssert(_childrenArray.count < 2, @"This layout spec does not support more than one child. Use the setChildren: or the setChild:AtIndex: API");
|
||||
|
||||
if (child) {
|
||||
if (child.layoutElementType == ASLayoutElementTypeLayoutSpec) {
|
||||
[(ASLayoutSpec *)child setShouldVisualize:self.shouldVisualize];
|
||||
}
|
||||
id<ASLayoutElement> finalLayoutElement = [self layoutElementToAddFromLayoutElement:child];
|
||||
if (finalLayoutElement) {
|
||||
_childrenArray[0] = finalLayoutElement;
|
||||
@@ -142,7 +177,11 @@
|
||||
NSUInteger i = 0;
|
||||
for (id<ASLayoutElement> child in children) {
|
||||
ASDisplayNodeAssert([child conformsToProtocol:NSProtocolFromString(@"ASLayoutElement")], @"Child %@ of spec %@ is not an ASLayoutElement!", child, self);
|
||||
_childrenArray[i] = [self layoutElementToAddFromLayoutElement:child];
|
||||
id <ASLayoutElement> finalLayoutElement = [self layoutElementToAddFromLayoutElement:child];
|
||||
if (finalLayoutElement.layoutElementType == ASLayoutElementTypeLayoutSpec) {
|
||||
[(ASLayoutSpec *)finalLayoutElement setShouldVisualize:self.shouldVisualize];
|
||||
}
|
||||
_childrenArray[i] = finalLayoutElement;
|
||||
i += 1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,7 +46,8 @@ typedef NS_OPTIONS(NSUInteger, ASHierarchyState)
|
||||
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
|
||||
ASHierarchyStateLayoutPending = 1 << 3,
|
||||
ASHierarchyStateVisualizeLayout = 1 << 4
|
||||
};
|
||||
|
||||
ASDISPLAYNODE_INLINE BOOL ASHierarchyStateIncludesLayoutPending(ASHierarchyState hierarchyState)
|
||||
@@ -59,6 +60,11 @@ ASDISPLAYNODE_INLINE BOOL ASHierarchyStateIncludesRangeManaged(ASHierarchyState
|
||||
return ((hierarchyState & ASHierarchyStateRangeManaged) == ASHierarchyStateRangeManaged);
|
||||
}
|
||||
|
||||
ASDISPLAYNODE_INLINE BOOL ASHierarchyStateIncludesVisualizeLayout(ASHierarchyState hierarchyState)
|
||||
{
|
||||
return ((hierarchyState & ASHierarchyStateVisualizeLayout) == ASHierarchyStateVisualizeLayout);
|
||||
}
|
||||
|
||||
ASDISPLAYNODE_INLINE BOOL ASHierarchyStateIncludesRasterized(ASHierarchyState hierarchyState)
|
||||
{
|
||||
return ((hierarchyState & ASHierarchyStateRasterized) == ASHierarchyStateRasterized);
|
||||
|
||||
@@ -144,6 +144,9 @@ ASEnvironmentState ASEnvironmentMergeObjectAndState(ASEnvironmentState environme
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -819,7 +819,7 @@ NSString *NSStringFromASHierarchyChangeType(_ASHierarchyChangeType changeType)
|
||||
NSDictionary *map = [self sectionToIndexSetMapFromChanges:changes];
|
||||
NSMutableString *str = [NSMutableString stringWithString:@"{ "];
|
||||
[map enumerateKeysAndObjectsUsingBlock:^(NSNumber * _Nonnull section, NSIndexSet * _Nonnull indexSet, BOOL * _Nonnull stop) {
|
||||
[str appendFormat:@"@%lu : %@ ", section.integerValue, [indexSet as_smallDescription]];
|
||||
[str appendFormat:@"@%lu : %@ ", (long)section.integerValue, [indexSet as_smallDescription]];
|
||||
}];
|
||||
[str appendString:@"}"];
|
||||
return str;
|
||||
|
||||
7
examples/LayoutSpecExamples/Sample.xcodeproj/project.xcworkspace/contents.xcworkspacedata
generated
Normal file
7
examples/LayoutSpecExamples/Sample.xcodeproj/project.xcworkspace/contents.xcworkspacedata
generated
Normal file
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Workspace
|
||||
version = "1.0">
|
||||
<FileRef
|
||||
location = "self:">
|
||||
</FileRef>
|
||||
</Workspace>
|
||||
10
examples/LayoutSpecExamples/Sample.xcworkspace/contents.xcworkspacedata
generated
Normal file
10
examples/LayoutSpecExamples/Sample.xcworkspace/contents.xcworkspacedata
generated
Normal file
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Workspace
|
||||
version = "1.0">
|
||||
<FileRef
|
||||
location = "group:Sample.xcodeproj">
|
||||
</FileRef>
|
||||
<FileRef
|
||||
location = "group:Pods/Pods.xcodeproj">
|
||||
</FileRef>
|
||||
</Workspace>
|
||||
BIN
examples/LayoutSpecPlayground/Default-568h@2x.png
Normal file
BIN
examples/LayoutSpecPlayground/Default-568h@2x.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 17 KiB |
BIN
examples/LayoutSpecPlayground/Default-667h@2x.png
Normal file
BIN
examples/LayoutSpecPlayground/Default-667h@2x.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 18 KiB |
BIN
examples/LayoutSpecPlayground/Default-736h@3x.png
Normal file
BIN
examples/LayoutSpecPlayground/Default-736h@3x.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 23 KiB |
6
examples/LayoutSpecPlayground/Podfile
Normal file
6
examples/LayoutSpecPlayground/Podfile
Normal file
@@ -0,0 +1,6 @@
|
||||
source 'https://github.com/CocoaPods/Specs.git'
|
||||
platform :ios, '7.1'
|
||||
target 'Sample' do
|
||||
pod 'AsyncDisplayKit', :path => '../..'
|
||||
end
|
||||
|
||||
958
examples/LayoutSpecPlayground/Sample.xcodeproj/project.pbxproj
Normal file
958
examples/LayoutSpecPlayground/Sample.xcodeproj/project.pbxproj
Normal file
@@ -0,0 +1,958 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>archiveVersion</key>
|
||||
<string>1</string>
|
||||
<key>classes</key>
|
||||
<dict/>
|
||||
<key>objectVersion</key>
|
||||
<string>46</string>
|
||||
<key>objects</key>
|
||||
<dict>
|
||||
<key>0585427F19D4DBE100606EA6</key>
|
||||
<dict>
|
||||
<key>isa</key>
|
||||
<string>PBXFileReference</string>
|
||||
<key>lastKnownFileType</key>
|
||||
<string>image.png</string>
|
||||
<key>name</key>
|
||||
<string>Default-568h@2x.png</string>
|
||||
<key>path</key>
|
||||
<string>../Default-568h@2x.png</string>
|
||||
<key>sourceTree</key>
|
||||
<string><group></string>
|
||||
</dict>
|
||||
<key>0585428019D4DBE100606EA6</key>
|
||||
<dict>
|
||||
<key>fileRef</key>
|
||||
<string>0585427F19D4DBE100606EA6</string>
|
||||
<key>isa</key>
|
||||
<string>PBXBuildFile</string>
|
||||
</dict>
|
||||
<key>05E2127819D4DB510098F589</key>
|
||||
<dict>
|
||||
<key>children</key>
|
||||
<array>
|
||||
<string>05E2128319D4DB510098F589</string>
|
||||
<string>05E2128219D4DB510098F589</string>
|
||||
<string>1A943BF0259746F18D6E423F</string>
|
||||
<string>1AE410B73DA5C3BD087ACDD7</string>
|
||||
</array>
|
||||
<key>indentWidth</key>
|
||||
<string>2</string>
|
||||
<key>isa</key>
|
||||
<string>PBXGroup</string>
|
||||
<key>sourceTree</key>
|
||||
<string><group></string>
|
||||
<key>tabWidth</key>
|
||||
<string>2</string>
|
||||
<key>usesTabs</key>
|
||||
<string>0</string>
|
||||
</dict>
|
||||
<key>05E2127919D4DB510098F589</key>
|
||||
<dict>
|
||||
<key>attributes</key>
|
||||
<dict>
|
||||
<key>LastUpgradeCheck</key>
|
||||
<string>0720</string>
|
||||
<key>ORGANIZATIONNAME</key>
|
||||
<string>Facebook</string>
|
||||
<key>TargetAttributes</key>
|
||||
<dict>
|
||||
<key>05E2128019D4DB510098F589</key>
|
||||
<dict>
|
||||
<key>CreatedOnToolsVersion</key>
|
||||
<string>6.0.1</string>
|
||||
</dict>
|
||||
</dict>
|
||||
</dict>
|
||||
<key>buildConfigurationList</key>
|
||||
<string>05E2127C19D4DB510098F589</string>
|
||||
<key>compatibilityVersion</key>
|
||||
<string>Xcode 3.2</string>
|
||||
<key>developmentRegion</key>
|
||||
<string>English</string>
|
||||
<key>hasScannedForEncodings</key>
|
||||
<string>0</string>
|
||||
<key>isa</key>
|
||||
<string>PBXProject</string>
|
||||
<key>knownRegions</key>
|
||||
<array>
|
||||
<string>en</string>
|
||||
<string>Base</string>
|
||||
</array>
|
||||
<key>mainGroup</key>
|
||||
<string>05E2127819D4DB510098F589</string>
|
||||
<key>productRefGroup</key>
|
||||
<string>05E2128219D4DB510098F589</string>
|
||||
<key>projectDirPath</key>
|
||||
<string></string>
|
||||
<key>projectReferences</key>
|
||||
<array/>
|
||||
<key>projectRoot</key>
|
||||
<string></string>
|
||||
<key>targets</key>
|
||||
<array>
|
||||
<string>05E2128019D4DB510098F589</string>
|
||||
</array>
|
||||
</dict>
|
||||
<key>05E2127C19D4DB510098F589</key>
|
||||
<dict>
|
||||
<key>buildConfigurations</key>
|
||||
<array>
|
||||
<string>05E212A219D4DB510098F589</string>
|
||||
<string>05E212A319D4DB510098F589</string>
|
||||
</array>
|
||||
<key>defaultConfigurationIsVisible</key>
|
||||
<string>0</string>
|
||||
<key>defaultConfigurationName</key>
|
||||
<string>Release</string>
|
||||
<key>isa</key>
|
||||
<string>XCConfigurationList</string>
|
||||
</dict>
|
||||
<key>05E2127D19D4DB510098F589</key>
|
||||
<dict>
|
||||
<key>buildActionMask</key>
|
||||
<string>2147483647</string>
|
||||
<key>files</key>
|
||||
<array>
|
||||
<string>76466F321C9DFFC4006C4D2D</string>
|
||||
<string>05E2128719D4DB510098F589</string>
|
||||
<string>7602C7651CA4F83100D0D917</string>
|
||||
<string>76466F341C9DFFC4006C4D2D</string>
|
||||
<string>76F58D5C1C9E15C1004512CC</string>
|
||||
<string>76466F351C9DFFC4006C4D2D</string>
|
||||
<string>80A6A5181D88F08F00473431</string>
|
||||
</array>
|
||||
<key>isa</key>
|
||||
<string>PBXSourcesBuildPhase</string>
|
||||
<key>runOnlyForDeploymentPostprocessing</key>
|
||||
<string>0</string>
|
||||
</dict>
|
||||
<key>05E2127E19D4DB510098F589</key>
|
||||
<dict>
|
||||
<key>buildActionMask</key>
|
||||
<string>2147483647</string>
|
||||
<key>files</key>
|
||||
<array>
|
||||
<string>B971D066CC023A00C53D8575</string>
|
||||
</array>
|
||||
<key>isa</key>
|
||||
<string>PBXFrameworksBuildPhase</string>
|
||||
<key>runOnlyForDeploymentPostprocessing</key>
|
||||
<string>0</string>
|
||||
</dict>
|
||||
<key>05E2127F19D4DB510098F589</key>
|
||||
<dict>
|
||||
<key>buildActionMask</key>
|
||||
<string>2147483647</string>
|
||||
<key>files</key>
|
||||
<array>
|
||||
<string>0585428019D4DBE100606EA6</string>
|
||||
<string>6C2C82AC19EE274300767484</string>
|
||||
<string>6C2C82AD19EE274300767484</string>
|
||||
<string>7602C7671CA4FB5300D0D917</string>
|
||||
</array>
|
||||
<key>isa</key>
|
||||
<string>PBXResourcesBuildPhase</string>
|
||||
<key>runOnlyForDeploymentPostprocessing</key>
|
||||
<string>0</string>
|
||||
</dict>
|
||||
<key>05E2128019D4DB510098F589</key>
|
||||
<dict>
|
||||
<key>buildConfigurationList</key>
|
||||
<string>05E212A419D4DB510098F589</string>
|
||||
<key>buildPhases</key>
|
||||
<array>
|
||||
<string>E080B80F89C34A25B3488E26</string>
|
||||
<string>05E2127D19D4DB510098F589</string>
|
||||
<string>05E2127E19D4DB510098F589</string>
|
||||
<string>05E2127F19D4DB510098F589</string>
|
||||
<string>F012A6F39E0149F18F564F50</string>
|
||||
<string>2291CF7AF2D4B273DDAD8AAC</string>
|
||||
</array>
|
||||
<key>buildRules</key>
|
||||
<array/>
|
||||
<key>dependencies</key>
|
||||
<array/>
|
||||
<key>isa</key>
|
||||
<string>PBXNativeTarget</string>
|
||||
<key>name</key>
|
||||
<string>Sample</string>
|
||||
<key>productName</key>
|
||||
<string>Sample</string>
|
||||
<key>productReference</key>
|
||||
<string>05E2128119D4DB510098F589</string>
|
||||
<key>productType</key>
|
||||
<string>com.apple.product-type.application</string>
|
||||
</dict>
|
||||
<key>05E2128119D4DB510098F589</key>
|
||||
<dict>
|
||||
<key>explicitFileType</key>
|
||||
<string>wrapper.application</string>
|
||||
<key>includeInIndex</key>
|
||||
<string>0</string>
|
||||
<key>isa</key>
|
||||
<string>PBXFileReference</string>
|
||||
<key>path</key>
|
||||
<string>Sample.app</string>
|
||||
<key>sourceTree</key>
|
||||
<string>BUILT_PRODUCTS_DIR</string>
|
||||
</dict>
|
||||
<key>05E2128219D4DB510098F589</key>
|
||||
<dict>
|
||||
<key>children</key>
|
||||
<array>
|
||||
<string>05E2128119D4DB510098F589</string>
|
||||
</array>
|
||||
<key>isa</key>
|
||||
<string>PBXGroup</string>
|
||||
<key>name</key>
|
||||
<string>Products</string>
|
||||
<key>sourceTree</key>
|
||||
<string><group></string>
|
||||
</dict>
|
||||
<key>05E2128319D4DB510098F589</key>
|
||||
<dict>
|
||||
<key>children</key>
|
||||
<array>
|
||||
<string>76466F2A1C9DFFC4006C4D2D</string>
|
||||
<string>76466F2B1C9DFFC4006C4D2D</string>
|
||||
<string>76466F301C9DFFC4006C4D2D</string>
|
||||
<string>76466F311C9DFFC4006C4D2D</string>
|
||||
<string>76F58D5A1C9E15C1004512CC</string>
|
||||
<string>76F58D5B1C9E15C1004512CC</string>
|
||||
<string>76466F2E1C9DFFC4006C4D2D</string>
|
||||
<string>76466F2F1C9DFFC4006C4D2D</string>
|
||||
<string>80A6A5161D88F08F00473431</string>
|
||||
<string>80A6A5171D88F08F00473431</string>
|
||||
<string>7602C7631CA4F83100D0D917</string>
|
||||
<string>7602C7641CA4F83100D0D917</string>
|
||||
<string>05E2128419D4DB510098F589</string>
|
||||
</array>
|
||||
<key>isa</key>
|
||||
<string>PBXGroup</string>
|
||||
<key>path</key>
|
||||
<string>Sample</string>
|
||||
<key>sourceTree</key>
|
||||
<string><group></string>
|
||||
</dict>
|
||||
<key>05E2128419D4DB510098F589</key>
|
||||
<dict>
|
||||
<key>children</key>
|
||||
<array>
|
||||
<string>0585427F19D4DBE100606EA6</string>
|
||||
<string>6C2C82AA19EE274300767484</string>
|
||||
<string>7602C7661CA4FB5300D0D917</string>
|
||||
<string>6C2C82AB19EE274300767484</string>
|
||||
<string>05E2128519D4DB510098F589</string>
|
||||
<string>05E2128619D4DB510098F589</string>
|
||||
</array>
|
||||
<key>isa</key>
|
||||
<string>PBXGroup</string>
|
||||
<key>name</key>
|
||||
<string>Supporting Files</string>
|
||||
<key>sourceTree</key>
|
||||
<string><group></string>
|
||||
</dict>
|
||||
<key>05E2128519D4DB510098F589</key>
|
||||
<dict>
|
||||
<key>isa</key>
|
||||
<string>PBXFileReference</string>
|
||||
<key>lastKnownFileType</key>
|
||||
<string>text.plist.xml</string>
|
||||
<key>path</key>
|
||||
<string>Info.plist</string>
|
||||
<key>sourceTree</key>
|
||||
<string><group></string>
|
||||
</dict>
|
||||
<key>05E2128619D4DB510098F589</key>
|
||||
<dict>
|
||||
<key>isa</key>
|
||||
<string>PBXFileReference</string>
|
||||
<key>lastKnownFileType</key>
|
||||
<string>sourcecode.c.objc</string>
|
||||
<key>path</key>
|
||||
<string>main.m</string>
|
||||
<key>sourceTree</key>
|
||||
<string><group></string>
|
||||
</dict>
|
||||
<key>05E2128719D4DB510098F589</key>
|
||||
<dict>
|
||||
<key>fileRef</key>
|
||||
<string>05E2128619D4DB510098F589</string>
|
||||
<key>isa</key>
|
||||
<string>PBXBuildFile</string>
|
||||
</dict>
|
||||
<key>05E212A219D4DB510098F589</key>
|
||||
<dict>
|
||||
<key>buildSettings</key>
|
||||
<dict>
|
||||
<key>ALWAYS_SEARCH_USER_PATHS</key>
|
||||
<string>NO</string>
|
||||
<key>CLANG_CXX_LANGUAGE_STANDARD</key>
|
||||
<string>gnu++0x</string>
|
||||
<key>CLANG_CXX_LIBRARY</key>
|
||||
<string>libc++</string>
|
||||
<key>CLANG_ENABLE_MODULES</key>
|
||||
<string>YES</string>
|
||||
<key>CLANG_ENABLE_OBJC_ARC</key>
|
||||
<string>YES</string>
|
||||
<key>CLANG_WARN_BOOL_CONVERSION</key>
|
||||
<string>YES</string>
|
||||
<key>CLANG_WARN_CONSTANT_CONVERSION</key>
|
||||
<string>YES</string>
|
||||
<key>CLANG_WARN_DIRECT_OBJC_ISA_USAGE</key>
|
||||
<string>YES_ERROR</string>
|
||||
<key>CLANG_WARN_EMPTY_BODY</key>
|
||||
<string>YES</string>
|
||||
<key>CLANG_WARN_ENUM_CONVERSION</key>
|
||||
<string>YES</string>
|
||||
<key>CLANG_WARN_INT_CONVERSION</key>
|
||||
<string>YES</string>
|
||||
<key>CLANG_WARN_OBJC_ROOT_CLASS</key>
|
||||
<string>YES_ERROR</string>
|
||||
<key>CLANG_WARN_UNREACHABLE_CODE</key>
|
||||
<string>YES</string>
|
||||
<key>CLANG_WARN__DUPLICATE_METHOD_MATCH</key>
|
||||
<string>YES</string>
|
||||
<key>CODE_SIGN_IDENTITY[sdk=iphoneos*]</key>
|
||||
<string>iPhone Developer</string>
|
||||
<key>COPY_PHASE_STRIP</key>
|
||||
<string>NO</string>
|
||||
<key>ENABLE_STRICT_OBJC_MSGSEND</key>
|
||||
<string>YES</string>
|
||||
<key>ENABLE_TESTABILITY</key>
|
||||
<string>YES</string>
|
||||
<key>GCC_C_LANGUAGE_STANDARD</key>
|
||||
<string>gnu99</string>
|
||||
<key>GCC_DYNAMIC_NO_PIC</key>
|
||||
<string>NO</string>
|
||||
<key>GCC_OPTIMIZATION_LEVEL</key>
|
||||
<string>0</string>
|
||||
<key>GCC_PREPROCESSOR_DEFINITIONS</key>
|
||||
<array>
|
||||
<string>DEBUG=1</string>
|
||||
<string>$(inherited)</string>
|
||||
</array>
|
||||
<key>GCC_SYMBOLS_PRIVATE_EXTERN</key>
|
||||
<string>NO</string>
|
||||
<key>GCC_WARN_64_TO_32_BIT_CONVERSION</key>
|
||||
<string>YES</string>
|
||||
<key>GCC_WARN_ABOUT_RETURN_TYPE</key>
|
||||
<string>YES_ERROR</string>
|
||||
<key>GCC_WARN_UNDECLARED_SELECTOR</key>
|
||||
<string>YES</string>
|
||||
<key>GCC_WARN_UNINITIALIZED_AUTOS</key>
|
||||
<string>YES_AGGRESSIVE</string>
|
||||
<key>GCC_WARN_UNUSED_FUNCTION</key>
|
||||
<string>YES</string>
|
||||
<key>GCC_WARN_UNUSED_VARIABLE</key>
|
||||
<string>YES</string>
|
||||
<key>IPHONEOS_DEPLOYMENT_TARGET</key>
|
||||
<string>7.1</string>
|
||||
<key>MTL_ENABLE_DEBUG_INFO</key>
|
||||
<string>YES</string>
|
||||
<key>ONLY_ACTIVE_ARCH</key>
|
||||
<string>YES</string>
|
||||
<key>SDKROOT</key>
|
||||
<string>iphoneos</string>
|
||||
</dict>
|
||||
<key>isa</key>
|
||||
<string>XCBuildConfiguration</string>
|
||||
<key>name</key>
|
||||
<string>Debug</string>
|
||||
</dict>
|
||||
<key>05E212A319D4DB510098F589</key>
|
||||
<dict>
|
||||
<key>buildSettings</key>
|
||||
<dict>
|
||||
<key>ALWAYS_SEARCH_USER_PATHS</key>
|
||||
<string>NO</string>
|
||||
<key>CLANG_CXX_LANGUAGE_STANDARD</key>
|
||||
<string>gnu++0x</string>
|
||||
<key>CLANG_CXX_LIBRARY</key>
|
||||
<string>libc++</string>
|
||||
<key>CLANG_ENABLE_MODULES</key>
|
||||
<string>YES</string>
|
||||
<key>CLANG_ENABLE_OBJC_ARC</key>
|
||||
<string>YES</string>
|
||||
<key>CLANG_WARN_BOOL_CONVERSION</key>
|
||||
<string>YES</string>
|
||||
<key>CLANG_WARN_CONSTANT_CONVERSION</key>
|
||||
<string>YES</string>
|
||||
<key>CLANG_WARN_DIRECT_OBJC_ISA_USAGE</key>
|
||||
<string>YES_ERROR</string>
|
||||
<key>CLANG_WARN_EMPTY_BODY</key>
|
||||
<string>YES</string>
|
||||
<key>CLANG_WARN_ENUM_CONVERSION</key>
|
||||
<string>YES</string>
|
||||
<key>CLANG_WARN_INT_CONVERSION</key>
|
||||
<string>YES</string>
|
||||
<key>CLANG_WARN_OBJC_ROOT_CLASS</key>
|
||||
<string>YES_ERROR</string>
|
||||
<key>CLANG_WARN_UNREACHABLE_CODE</key>
|
||||
<string>YES</string>
|
||||
<key>CLANG_WARN__DUPLICATE_METHOD_MATCH</key>
|
||||
<string>YES</string>
|
||||
<key>CODE_SIGN_IDENTITY[sdk=iphoneos*]</key>
|
||||
<string>iPhone Developer</string>
|
||||
<key>COPY_PHASE_STRIP</key>
|
||||
<string>YES</string>
|
||||
<key>ENABLE_NS_ASSERTIONS</key>
|
||||
<string>NO</string>
|
||||
<key>ENABLE_STRICT_OBJC_MSGSEND</key>
|
||||
<string>YES</string>
|
||||
<key>GCC_C_LANGUAGE_STANDARD</key>
|
||||
<string>gnu99</string>
|
||||
<key>GCC_WARN_64_TO_32_BIT_CONVERSION</key>
|
||||
<string>YES</string>
|
||||
<key>GCC_WARN_ABOUT_RETURN_TYPE</key>
|
||||
<string>YES_ERROR</string>
|
||||
<key>GCC_WARN_UNDECLARED_SELECTOR</key>
|
||||
<string>YES</string>
|
||||
<key>GCC_WARN_UNINITIALIZED_AUTOS</key>
|
||||
<string>YES_AGGRESSIVE</string>
|
||||
<key>GCC_WARN_UNUSED_FUNCTION</key>
|
||||
<string>YES</string>
|
||||
<key>GCC_WARN_UNUSED_VARIABLE</key>
|
||||
<string>YES</string>
|
||||
<key>IPHONEOS_DEPLOYMENT_TARGET</key>
|
||||
<string>7.1</string>
|
||||
<key>MTL_ENABLE_DEBUG_INFO</key>
|
||||
<string>NO</string>
|
||||
<key>SDKROOT</key>
|
||||
<string>iphoneos</string>
|
||||
<key>VALIDATE_PRODUCT</key>
|
||||
<string>YES</string>
|
||||
</dict>
|
||||
<key>isa</key>
|
||||
<string>XCBuildConfiguration</string>
|
||||
<key>name</key>
|
||||
<string>Release</string>
|
||||
</dict>
|
||||
<key>05E212A419D4DB510098F589</key>
|
||||
<dict>
|
||||
<key>buildConfigurations</key>
|
||||
<array>
|
||||
<string>05E212A519D4DB510098F589</string>
|
||||
<string>05E212A619D4DB510098F589</string>
|
||||
</array>
|
||||
<key>defaultConfigurationIsVisible</key>
|
||||
<string>0</string>
|
||||
<key>defaultConfigurationName</key>
|
||||
<string>Release</string>
|
||||
<key>isa</key>
|
||||
<string>XCConfigurationList</string>
|
||||
</dict>
|
||||
<key>05E212A519D4DB510098F589</key>
|
||||
<dict>
|
||||
<key>baseConfigurationReference</key>
|
||||
<string>FDF496F367580DF9280D36EA</string>
|
||||
<key>buildSettings</key>
|
||||
<dict>
|
||||
<key>ASSETCATALOG_COMPILER_APPICON_NAME</key>
|
||||
<string>AppIcon</string>
|
||||
<key>INFOPLIST_FILE</key>
|
||||
<string>Sample/Info.plist</string>
|
||||
<key>IPHONEOS_DEPLOYMENT_TARGET</key>
|
||||
<string>7.1</string>
|
||||
<key>LD_RUNPATH_SEARCH_PATHS</key>
|
||||
<string>$(inherited) @executable_path/Frameworks</string>
|
||||
<key>PRODUCT_BUNDLE_IDENTIFIER</key>
|
||||
<string>com.facebook.AsyncDisplayKit.$(PRODUCT_NAME:rfc1034identifier)</string>
|
||||
<key>PRODUCT_NAME</key>
|
||||
<string>$(TARGET_NAME)</string>
|
||||
<key>TARGETED_DEVICE_FAMILY</key>
|
||||
<string>1,2</string>
|
||||
</dict>
|
||||
<key>isa</key>
|
||||
<string>XCBuildConfiguration</string>
|
||||
<key>name</key>
|
||||
<string>Debug</string>
|
||||
</dict>
|
||||
<key>05E212A619D4DB510098F589</key>
|
||||
<dict>
|
||||
<key>baseConfigurationReference</key>
|
||||
<string>5C5154389F056C672F4E9EEA</string>
|
||||
<key>buildSettings</key>
|
||||
<dict>
|
||||
<key>ASSETCATALOG_COMPILER_APPICON_NAME</key>
|
||||
<string>AppIcon</string>
|
||||
<key>INFOPLIST_FILE</key>
|
||||
<string>Sample/Info.plist</string>
|
||||
<key>IPHONEOS_DEPLOYMENT_TARGET</key>
|
||||
<string>7.1</string>
|
||||
<key>LD_RUNPATH_SEARCH_PATHS</key>
|
||||
<string>$(inherited) @executable_path/Frameworks</string>
|
||||
<key>PRODUCT_BUNDLE_IDENTIFIER</key>
|
||||
<string>com.facebook.AsyncDisplayKit.$(PRODUCT_NAME:rfc1034identifier)</string>
|
||||
<key>PRODUCT_NAME</key>
|
||||
<string>$(TARGET_NAME)</string>
|
||||
<key>TARGETED_DEVICE_FAMILY</key>
|
||||
<string>1,2</string>
|
||||
</dict>
|
||||
<key>isa</key>
|
||||
<string>XCBuildConfiguration</string>
|
||||
<key>name</key>
|
||||
<string>Release</string>
|
||||
</dict>
|
||||
<key>088AA6578212BE9BFBB07B70</key>
|
||||
<dict>
|
||||
<key>includeInIndex</key>
|
||||
<string>1</string>
|
||||
<key>isa</key>
|
||||
<string>PBXFileReference</string>
|
||||
<key>lastKnownFileType</key>
|
||||
<string>text.xcconfig</string>
|
||||
<key>name</key>
|
||||
<string>Pods.release.xcconfig</string>
|
||||
<key>path</key>
|
||||
<string>Pods/Target Support Files/Pods/Pods.release.xcconfig</string>
|
||||
<key>sourceTree</key>
|
||||
<string><group></string>
|
||||
</dict>
|
||||
<key>1A943BF0259746F18D6E423F</key>
|
||||
<dict>
|
||||
<key>children</key>
|
||||
<array>
|
||||
<string>3D24B17D1E4A4E7A9566C5E9</string>
|
||||
<string>54A6EB3DE8D9A9EC4AE2867D</string>
|
||||
</array>
|
||||
<key>isa</key>
|
||||
<string>PBXGroup</string>
|
||||
<key>name</key>
|
||||
<string>Frameworks</string>
|
||||
<key>sourceTree</key>
|
||||
<string><group></string>
|
||||
</dict>
|
||||
<key>1AE410B73DA5C3BD087ACDD7</key>
|
||||
<dict>
|
||||
<key>children</key>
|
||||
<array>
|
||||
<string>C068F1D3F0CC317E895FCDAB</string>
|
||||
<string>088AA6578212BE9BFBB07B70</string>
|
||||
<string>FDF496F367580DF9280D36EA</string>
|
||||
<string>5C5154389F056C672F4E9EEA</string>
|
||||
</array>
|
||||
<key>isa</key>
|
||||
<string>PBXGroup</string>
|
||||
<key>name</key>
|
||||
<string>Pods</string>
|
||||
<key>sourceTree</key>
|
||||
<string><group></string>
|
||||
</dict>
|
||||
<key>2291CF7AF2D4B273DDAD8AAC</key>
|
||||
<dict>
|
||||
<key>buildActionMask</key>
|
||||
<string>2147483647</string>
|
||||
<key>files</key>
|
||||
<array/>
|
||||
<key>inputPaths</key>
|
||||
<array/>
|
||||
<key>isa</key>
|
||||
<string>PBXShellScriptBuildPhase</string>
|
||||
<key>name</key>
|
||||
<string>[CP] Embed Pods Frameworks</string>
|
||||
<key>outputPaths</key>
|
||||
<array/>
|
||||
<key>runOnlyForDeploymentPostprocessing</key>
|
||||
<string>0</string>
|
||||
<key>shellPath</key>
|
||||
<string>/bin/sh</string>
|
||||
<key>shellScript</key>
|
||||
<string>"${SRCROOT}/Pods/Target Support Files/Pods-Sample/Pods-Sample-frameworks.sh"
|
||||
</string>
|
||||
<key>showEnvVarsInLog</key>
|
||||
<string>0</string>
|
||||
</dict>
|
||||
<key>3D24B17D1E4A4E7A9566C5E9</key>
|
||||
<dict>
|
||||
<key>explicitFileType</key>
|
||||
<string>archive.ar</string>
|
||||
<key>includeInIndex</key>
|
||||
<string>0</string>
|
||||
<key>isa</key>
|
||||
<string>PBXFileReference</string>
|
||||
<key>path</key>
|
||||
<string>libPods.a</string>
|
||||
<key>sourceTree</key>
|
||||
<string>BUILT_PRODUCTS_DIR</string>
|
||||
</dict>
|
||||
<key>54A6EB3DE8D9A9EC4AE2867D</key>
|
||||
<dict>
|
||||
<key>explicitFileType</key>
|
||||
<string>archive.ar</string>
|
||||
<key>includeInIndex</key>
|
||||
<string>0</string>
|
||||
<key>isa</key>
|
||||
<string>PBXFileReference</string>
|
||||
<key>path</key>
|
||||
<string>libPods-Sample.a</string>
|
||||
<key>sourceTree</key>
|
||||
<string>BUILT_PRODUCTS_DIR</string>
|
||||
</dict>
|
||||
<key>5C5154389F056C672F4E9EEA</key>
|
||||
<dict>
|
||||
<key>includeInIndex</key>
|
||||
<string>1</string>
|
||||
<key>isa</key>
|
||||
<string>PBXFileReference</string>
|
||||
<key>lastKnownFileType</key>
|
||||
<string>text.xcconfig</string>
|
||||
<key>name</key>
|
||||
<string>Pods-Sample.release.xcconfig</string>
|
||||
<key>path</key>
|
||||
<string>Pods/Target Support Files/Pods-Sample/Pods-Sample.release.xcconfig</string>
|
||||
<key>sourceTree</key>
|
||||
<string><group></string>
|
||||
</dict>
|
||||
<key>6C2C82AA19EE274300767484</key>
|
||||
<dict>
|
||||
<key>isa</key>
|
||||
<string>PBXFileReference</string>
|
||||
<key>lastKnownFileType</key>
|
||||
<string>image.png</string>
|
||||
<key>path</key>
|
||||
<string>Default-667h@2x.png</string>
|
||||
<key>sourceTree</key>
|
||||
<string>SOURCE_ROOT</string>
|
||||
</dict>
|
||||
<key>6C2C82AB19EE274300767484</key>
|
||||
<dict>
|
||||
<key>isa</key>
|
||||
<string>PBXFileReference</string>
|
||||
<key>lastKnownFileType</key>
|
||||
<string>image.png</string>
|
||||
<key>path</key>
|
||||
<string>Default-736h@3x.png</string>
|
||||
<key>sourceTree</key>
|
||||
<string>SOURCE_ROOT</string>
|
||||
</dict>
|
||||
<key>6C2C82AC19EE274300767484</key>
|
||||
<dict>
|
||||
<key>fileRef</key>
|
||||
<string>6C2C82AA19EE274300767484</string>
|
||||
<key>isa</key>
|
||||
<string>PBXBuildFile</string>
|
||||
</dict>
|
||||
<key>6C2C82AD19EE274300767484</key>
|
||||
<dict>
|
||||
<key>fileRef</key>
|
||||
<string>6C2C82AB19EE274300767484</string>
|
||||
<key>isa</key>
|
||||
<string>PBXBuildFile</string>
|
||||
</dict>
|
||||
<key>7602C7631CA4F83100D0D917</key>
|
||||
<dict>
|
||||
<key>fileEncoding</key>
|
||||
<string>4</string>
|
||||
<key>isa</key>
|
||||
<string>PBXFileReference</string>
|
||||
<key>lastKnownFileType</key>
|
||||
<string>sourcecode.c.h</string>
|
||||
<key>path</key>
|
||||
<string>Utilities.h</string>
|
||||
<key>sourceTree</key>
|
||||
<string><group></string>
|
||||
</dict>
|
||||
<key>7602C7641CA4F83100D0D917</key>
|
||||
<dict>
|
||||
<key>fileEncoding</key>
|
||||
<string>4</string>
|
||||
<key>isa</key>
|
||||
<string>PBXFileReference</string>
|
||||
<key>lastKnownFileType</key>
|
||||
<string>sourcecode.c.objc</string>
|
||||
<key>path</key>
|
||||
<string>Utilities.m</string>
|
||||
<key>sourceTree</key>
|
||||
<string><group></string>
|
||||
</dict>
|
||||
<key>7602C7651CA4F83100D0D917</key>
|
||||
<dict>
|
||||
<key>fileRef</key>
|
||||
<string>7602C7641CA4F83100D0D917</string>
|
||||
<key>isa</key>
|
||||
<string>PBXBuildFile</string>
|
||||
</dict>
|
||||
<key>7602C7661CA4FB5300D0D917</key>
|
||||
<dict>
|
||||
<key>isa</key>
|
||||
<string>PBXFileReference</string>
|
||||
<key>lastKnownFileType</key>
|
||||
<string>image.png</string>
|
||||
<key>path</key>
|
||||
<string>resizeHandle.png</string>
|
||||
<key>sourceTree</key>
|
||||
<string><group></string>
|
||||
</dict>
|
||||
<key>7602C7671CA4FB5300D0D917</key>
|
||||
<dict>
|
||||
<key>fileRef</key>
|
||||
<string>7602C7661CA4FB5300D0D917</string>
|
||||
<key>isa</key>
|
||||
<string>PBXBuildFile</string>
|
||||
</dict>
|
||||
<key>76466F2A1C9DFFC4006C4D2D</key>
|
||||
<dict>
|
||||
<key>fileEncoding</key>
|
||||
<string>4</string>
|
||||
<key>isa</key>
|
||||
<string>PBXFileReference</string>
|
||||
<key>lastKnownFileType</key>
|
||||
<string>sourcecode.c.h</string>
|
||||
<key>path</key>
|
||||
<string>AppDelegate.h</string>
|
||||
<key>sourceTree</key>
|
||||
<string><group></string>
|
||||
</dict>
|
||||
<key>76466F2B1C9DFFC4006C4D2D</key>
|
||||
<dict>
|
||||
<key>fileEncoding</key>
|
||||
<string>4</string>
|
||||
<key>isa</key>
|
||||
<string>PBXFileReference</string>
|
||||
<key>lastKnownFileType</key>
|
||||
<string>sourcecode.c.objc</string>
|
||||
<key>path</key>
|
||||
<string>AppDelegate.m</string>
|
||||
<key>sourceTree</key>
|
||||
<string><group></string>
|
||||
</dict>
|
||||
<key>76466F2E1C9DFFC4006C4D2D</key>
|
||||
<dict>
|
||||
<key>fileEncoding</key>
|
||||
<string>4</string>
|
||||
<key>isa</key>
|
||||
<string>PBXFileReference</string>
|
||||
<key>lastKnownFileType</key>
|
||||
<string>sourcecode.c.h</string>
|
||||
<key>path</key>
|
||||
<string>PhotoPostNode.h</string>
|
||||
<key>sourceTree</key>
|
||||
<string><group></string>
|
||||
</dict>
|
||||
<key>76466F2F1C9DFFC4006C4D2D</key>
|
||||
<dict>
|
||||
<key>fileEncoding</key>
|
||||
<string>4</string>
|
||||
<key>isa</key>
|
||||
<string>PBXFileReference</string>
|
||||
<key>lastKnownFileType</key>
|
||||
<string>sourcecode.c.objc</string>
|
||||
<key>path</key>
|
||||
<string>PhotoPostNode.m</string>
|
||||
<key>sourceTree</key>
|
||||
<string><group></string>
|
||||
</dict>
|
||||
<key>76466F301C9DFFC4006C4D2D</key>
|
||||
<dict>
|
||||
<key>fileEncoding</key>
|
||||
<string>4</string>
|
||||
<key>isa</key>
|
||||
<string>PBXFileReference</string>
|
||||
<key>lastKnownFileType</key>
|
||||
<string>sourcecode.c.h</string>
|
||||
<key>path</key>
|
||||
<string>ViewController.h</string>
|
||||
<key>sourceTree</key>
|
||||
<string><group></string>
|
||||
</dict>
|
||||
<key>76466F311C9DFFC4006C4D2D</key>
|
||||
<dict>
|
||||
<key>fileEncoding</key>
|
||||
<string>4</string>
|
||||
<key>isa</key>
|
||||
<string>PBXFileReference</string>
|
||||
<key>lastKnownFileType</key>
|
||||
<string>sourcecode.c.objc</string>
|
||||
<key>path</key>
|
||||
<string>ViewController.m</string>
|
||||
<key>sourceTree</key>
|
||||
<string><group></string>
|
||||
</dict>
|
||||
<key>76466F321C9DFFC4006C4D2D</key>
|
||||
<dict>
|
||||
<key>fileRef</key>
|
||||
<string>76466F2B1C9DFFC4006C4D2D</string>
|
||||
<key>isa</key>
|
||||
<string>PBXBuildFile</string>
|
||||
</dict>
|
||||
<key>76466F341C9DFFC4006C4D2D</key>
|
||||
<dict>
|
||||
<key>fileRef</key>
|
||||
<string>76466F2F1C9DFFC4006C4D2D</string>
|
||||
<key>isa</key>
|
||||
<string>PBXBuildFile</string>
|
||||
</dict>
|
||||
<key>76466F351C9DFFC4006C4D2D</key>
|
||||
<dict>
|
||||
<key>fileRef</key>
|
||||
<string>76466F311C9DFFC4006C4D2D</string>
|
||||
<key>isa</key>
|
||||
<string>PBXBuildFile</string>
|
||||
</dict>
|
||||
<key>76F58D5A1C9E15C1004512CC</key>
|
||||
<dict>
|
||||
<key>fileEncoding</key>
|
||||
<string>4</string>
|
||||
<key>isa</key>
|
||||
<string>PBXFileReference</string>
|
||||
<key>lastKnownFileType</key>
|
||||
<string>sourcecode.c.h</string>
|
||||
<key>path</key>
|
||||
<string>PlaygroundContainerNode.h</string>
|
||||
<key>sourceTree</key>
|
||||
<string><group></string>
|
||||
</dict>
|
||||
<key>76F58D5B1C9E15C1004512CC</key>
|
||||
<dict>
|
||||
<key>fileEncoding</key>
|
||||
<string>4</string>
|
||||
<key>isa</key>
|
||||
<string>PBXFileReference</string>
|
||||
<key>lastKnownFileType</key>
|
||||
<string>sourcecode.c.objc</string>
|
||||
<key>path</key>
|
||||
<string>PlaygroundContainerNode.m</string>
|
||||
<key>sourceTree</key>
|
||||
<string><group></string>
|
||||
</dict>
|
||||
<key>76F58D5C1C9E15C1004512CC</key>
|
||||
<dict>
|
||||
<key>fileRef</key>
|
||||
<string>76F58D5B1C9E15C1004512CC</string>
|
||||
<key>isa</key>
|
||||
<string>PBXBuildFile</string>
|
||||
</dict>
|
||||
<key>80A6A5161D88F08F00473431</key>
|
||||
<dict>
|
||||
<key>fileEncoding</key>
|
||||
<string>4</string>
|
||||
<key>isa</key>
|
||||
<string>PBXFileReference</string>
|
||||
<key>lastKnownFileType</key>
|
||||
<string>sourcecode.c.h</string>
|
||||
<key>path</key>
|
||||
<string>LayoutExampleNodes.h</string>
|
||||
<key>sourceTree</key>
|
||||
<string><group></string>
|
||||
</dict>
|
||||
<key>80A6A5171D88F08F00473431</key>
|
||||
<dict>
|
||||
<key>fileEncoding</key>
|
||||
<string>4</string>
|
||||
<key>isa</key>
|
||||
<string>PBXFileReference</string>
|
||||
<key>lastKnownFileType</key>
|
||||
<string>sourcecode.c.objc</string>
|
||||
<key>path</key>
|
||||
<string>LayoutExampleNodes.m</string>
|
||||
<key>sourceTree</key>
|
||||
<string><group></string>
|
||||
</dict>
|
||||
<key>80A6A5181D88F08F00473431</key>
|
||||
<dict>
|
||||
<key>fileRef</key>
|
||||
<string>80A6A5171D88F08F00473431</string>
|
||||
<key>isa</key>
|
||||
<string>PBXBuildFile</string>
|
||||
</dict>
|
||||
<key>B971D066CC023A00C53D8575</key>
|
||||
<dict>
|
||||
<key>fileRef</key>
|
||||
<string>54A6EB3DE8D9A9EC4AE2867D</string>
|
||||
<key>isa</key>
|
||||
<string>PBXBuildFile</string>
|
||||
</dict>
|
||||
<key>C068F1D3F0CC317E895FCDAB</key>
|
||||
<dict>
|
||||
<key>includeInIndex</key>
|
||||
<string>1</string>
|
||||
<key>isa</key>
|
||||
<string>PBXFileReference</string>
|
||||
<key>lastKnownFileType</key>
|
||||
<string>text.xcconfig</string>
|
||||
<key>name</key>
|
||||
<string>Pods.debug.xcconfig</string>
|
||||
<key>path</key>
|
||||
<string>Pods/Target Support Files/Pods/Pods.debug.xcconfig</string>
|
||||
<key>sourceTree</key>
|
||||
<string><group></string>
|
||||
</dict>
|
||||
<key>E080B80F89C34A25B3488E26</key>
|
||||
<dict>
|
||||
<key>buildActionMask</key>
|
||||
<string>2147483647</string>
|
||||
<key>files</key>
|
||||
<array/>
|
||||
<key>inputPaths</key>
|
||||
<array/>
|
||||
<key>isa</key>
|
||||
<string>PBXShellScriptBuildPhase</string>
|
||||
<key>name</key>
|
||||
<string>[CP] Check Pods Manifest.lock</string>
|
||||
<key>outputPaths</key>
|
||||
<array/>
|
||||
<key>runOnlyForDeploymentPostprocessing</key>
|
||||
<string>0</string>
|
||||
<key>shellPath</key>
|
||||
<string>/bin/sh</string>
|
||||
<key>shellScript</key>
|
||||
<string>diff "${PODS_ROOT}/../Podfile.lock" "${PODS_ROOT}/Manifest.lock" > /dev/null
|
||||
if [[ $? != 0 ]] ; then
|
||||
cat << EOM
|
||||
error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.
|
||||
EOM
|
||||
exit 1
|
||||
fi
|
||||
</string>
|
||||
<key>showEnvVarsInLog</key>
|
||||
<string>0</string>
|
||||
</dict>
|
||||
<key>F012A6F39E0149F18F564F50</key>
|
||||
<dict>
|
||||
<key>buildActionMask</key>
|
||||
<string>2147483647</string>
|
||||
<key>files</key>
|
||||
<array/>
|
||||
<key>inputPaths</key>
|
||||
<array/>
|
||||
<key>isa</key>
|
||||
<string>PBXShellScriptBuildPhase</string>
|
||||
<key>name</key>
|
||||
<string>[CP] Copy Pods Resources</string>
|
||||
<key>outputPaths</key>
|
||||
<array/>
|
||||
<key>runOnlyForDeploymentPostprocessing</key>
|
||||
<string>0</string>
|
||||
<key>shellPath</key>
|
||||
<string>/bin/sh</string>
|
||||
<key>shellScript</key>
|
||||
<string>"${SRCROOT}/Pods/Target Support Files/Pods-Sample/Pods-Sample-resources.sh"
|
||||
</string>
|
||||
<key>showEnvVarsInLog</key>
|
||||
<string>0</string>
|
||||
</dict>
|
||||
<key>FDF496F367580DF9280D36EA</key>
|
||||
<dict>
|
||||
<key>includeInIndex</key>
|
||||
<string>1</string>
|
||||
<key>isa</key>
|
||||
<string>PBXFileReference</string>
|
||||
<key>lastKnownFileType</key>
|
||||
<string>text.xcconfig</string>
|
||||
<key>name</key>
|
||||
<string>Pods-Sample.debug.xcconfig</string>
|
||||
<key>path</key>
|
||||
<string>Pods/Target Support Files/Pods-Sample/Pods-Sample.debug.xcconfig</string>
|
||||
<key>sourceTree</key>
|
||||
<string><group></string>
|
||||
</dict>
|
||||
</dict>
|
||||
<key>rootObject</key>
|
||||
<string>05E2127919D4DB510098F589</string>
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -0,0 +1,91 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "0730"
|
||||
version = "1.3">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
buildImplicitDependencies = "YES">
|
||||
<BuildActionEntries>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "YES"
|
||||
buildForArchiving = "YES"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "05E2128019D4DB510098F589"
|
||||
BuildableName = "Sample.app"
|
||||
BlueprintName = "Sample"
|
||||
ReferencedContainer = "container:Sample.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
</BuildActionEntries>
|
||||
</BuildAction>
|
||||
<TestAction
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES">
|
||||
<Testables>
|
||||
</Testables>
|
||||
<MacroExpansion>
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "05E2128019D4DB510098F589"
|
||||
BuildableName = "Sample.app"
|
||||
BlueprintName = "Sample"
|
||||
ReferencedContainer = "container:Sample.xcodeproj">
|
||||
</BuildableReference>
|
||||
</MacroExpansion>
|
||||
<AdditionalOptions>
|
||||
</AdditionalOptions>
|
||||
</TestAction>
|
||||
<LaunchAction
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
launchStyle = "0"
|
||||
useCustomWorkingDirectory = "NO"
|
||||
ignoresPersistentStateOnLaunch = "NO"
|
||||
debugDocumentVersioning = "YES"
|
||||
debugServiceExtension = "internal"
|
||||
allowLocationSimulation = "YES">
|
||||
<BuildableProductRunnable
|
||||
runnableDebuggingMode = "0">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "05E2128019D4DB510098F589"
|
||||
BuildableName = "Sample.app"
|
||||
BlueprintName = "Sample"
|
||||
ReferencedContainer = "container:Sample.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
<AdditionalOptions>
|
||||
</AdditionalOptions>
|
||||
</LaunchAction>
|
||||
<ProfileAction
|
||||
buildConfiguration = "Release"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||
savedToolIdentifier = ""
|
||||
useCustomWorkingDirectory = "NO"
|
||||
debugDocumentVersioning = "YES">
|
||||
<BuildableProductRunnable
|
||||
runnableDebuggingMode = "0">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "05E2128019D4DB510098F589"
|
||||
BuildableName = "Sample.app"
|
||||
BlueprintName = "Sample"
|
||||
ReferencedContainer = "container:Sample.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
</ProfileAction>
|
||||
<AnalyzeAction
|
||||
buildConfiguration = "Debug">
|
||||
</AnalyzeAction>
|
||||
<ArchiveAction
|
||||
buildConfiguration = "Release"
|
||||
revealArchiveInOrganizer = "YES">
|
||||
</ArchiveAction>
|
||||
</Scheme>
|
||||
10
examples/LayoutSpecPlayground/Sample.xcworkspace/contents.xcworkspacedata
generated
Normal file
10
examples/LayoutSpecPlayground/Sample.xcworkspace/contents.xcworkspacedata
generated
Normal file
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Workspace
|
||||
version = "1.0">
|
||||
<FileRef
|
||||
location = "group:Sample.xcodeproj">
|
||||
</FileRef>
|
||||
<FileRef
|
||||
location = "group:Pods/Pods.xcodeproj">
|
||||
</FileRef>
|
||||
</Workspace>
|
||||
16
examples/LayoutSpecPlayground/Sample/AppDelegate.h
Normal file
16
examples/LayoutSpecPlayground/Sample/AppDelegate.h
Normal file
@@ -0,0 +1,16 @@
|
||||
//
|
||||
// AppDelegate.h
|
||||
// ASLayoutSpecPlayground
|
||||
//
|
||||
// Created by Hannah Troisi on 3/11/16.
|
||||
// Copyright © 2016 Hannah Troisi. All rights reserved.
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
@interface AppDelegate : UIResponder <UIApplicationDelegate>
|
||||
|
||||
@property (strong, nonatomic) UIWindow *window;
|
||||
|
||||
@end
|
||||
|
||||
50
examples/LayoutSpecPlayground/Sample/AppDelegate.m
Normal file
50
examples/LayoutSpecPlayground/Sample/AppDelegate.m
Normal file
@@ -0,0 +1,50 @@
|
||||
//
|
||||
// AppDelegate.m
|
||||
// ASLayoutSpecPlayground
|
||||
//
|
||||
// Created by Hannah Troisi on 3/11/16.
|
||||
// Copyright © 2016 Hannah Troisi. All rights reserved.
|
||||
//
|
||||
|
||||
#import "AppDelegate.h"
|
||||
#import "ViewController.h"
|
||||
#import "Utilities.h"
|
||||
#import <AsyncDisplayKit/ASLayoutElementInspectorNode.h>
|
||||
|
||||
@implementation AppDelegate
|
||||
|
||||
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
|
||||
|
||||
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
|
||||
|
||||
UIViewController *rootVC = nil;
|
||||
|
||||
UIDevice *device = [UIDevice currentDevice];
|
||||
if (device.userInterfaceIdiom == UIUserInterfaceIdiomPad) {
|
||||
|
||||
ASViewController *masterVC = [[ASViewController alloc] initWithNode:[ASLayoutElementInspectorNode sharedInstance]];
|
||||
masterVC.view.backgroundColor = [UIColor customOrangeColor];
|
||||
UINavigationController *masterNav = [[UINavigationController alloc] initWithRootViewController:masterVC];
|
||||
|
||||
ViewController *detailVC = [[ViewController alloc] init];
|
||||
UINavigationController *detailNav = [[UINavigationController alloc] initWithRootViewController:detailVC];
|
||||
|
||||
UISplitViewController *splitVC = [[UISplitViewController alloc] init];
|
||||
splitVC.viewControllers = @[masterNav, detailNav];
|
||||
splitVC.preferredDisplayMode = UISplitViewControllerDisplayModeAllVisible;
|
||||
splitVC.maximumPrimaryColumnWidth = 250;
|
||||
|
||||
rootVC = splitVC;
|
||||
|
||||
} else {
|
||||
// FIXME: make this work for iPhones
|
||||
NSAssert(YES, @"App optimized for iPad only.");
|
||||
}
|
||||
|
||||
[self.window setRootViewController:rootVC];
|
||||
[self.window makeKeyAndVisible];
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
@end
|
||||
45
examples/LayoutSpecPlayground/Sample/Info.plist
Normal file
45
examples/LayoutSpecPlayground/Sample/Info.plist
Normal file
@@ -0,0 +1,45 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>en</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>$(EXECUTABLE_NAME)</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>$(PRODUCT_NAME)</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.0</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleURLTypes</key>
|
||||
<array>
|
||||
<dict/>
|
||||
</array>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1</string>
|
||||
<key>LSRequiresIPhoneOS</key>
|
||||
<true/>
|
||||
<key>NSAppTransportSecurity</key>
|
||||
<dict>
|
||||
<key>NSAllowsArbitraryLoads</key>
|
||||
<true/>
|
||||
</dict>
|
||||
<key>UIRequiredDeviceCapabilities</key>
|
||||
<array>
|
||||
<string>armv7</string>
|
||||
</array>
|
||||
<key>UISupportedInterfaceOrientations</key>
|
||||
<array>
|
||||
<string>UIInterfaceOrientationPortrait</string>
|
||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
||||
49
examples/LayoutSpecPlayground/Sample/LayoutExampleNodes.h
Normal file
49
examples/LayoutSpecPlayground/Sample/LayoutExampleNodes.h
Normal file
@@ -0,0 +1,49 @@
|
||||
//
|
||||
// LayoutExampleNodes.h
|
||||
// Sample
|
||||
//
|
||||
// Created by Hannah Troisi on 9/13/16.
|
||||
// Copyright © 2016 Facebook. All rights reserved.
|
||||
//
|
||||
|
||||
#import <AsyncDisplayKit/AsyncDisplayKit.h>
|
||||
|
||||
@interface LayoutExampleNode : ASDisplayNode
|
||||
|
||||
- (NSAttributedString *)usernameAttributedStringWithFontSize:(CGFloat)size;
|
||||
- (NSAttributedString *)locationAttributedStringWithFontSize:(CGFloat)size;
|
||||
- (NSAttributedString *)uploadDateAttributedStringWithFontSize:(CGFloat)size;
|
||||
- (NSAttributedString *)likesAttributedStringWithFontSize:(CGFloat)size;
|
||||
- (NSAttributedString *)descriptionAttributedStringWithFontSize:(CGFloat)size;
|
||||
|
||||
@end
|
||||
|
||||
@interface HorizontalStackWithSpacer : LayoutExampleNode
|
||||
|
||||
@property (nonatomic, strong) ASTextNode *usernameNode;
|
||||
@property (nonatomic, strong) ASTextNode *postLocationNode;
|
||||
@property (nonatomic, strong) ASTextNode *postTimeNode;
|
||||
|
||||
@end
|
||||
|
||||
@interface PhotoWithInsetTextOverlay : LayoutExampleNode
|
||||
|
||||
@property (nonatomic, strong) ASNetworkImageNode *photoNode;
|
||||
@property (nonatomic, strong) ASTextNode *titleNode;
|
||||
|
||||
@end
|
||||
|
||||
@interface PhotoWithOutsetIconOverlay : LayoutExampleNode
|
||||
|
||||
@property (nonatomic, strong) ASNetworkImageNode *photoNode;
|
||||
@property (nonatomic, strong) ASNetworkImageNode *iconNode;
|
||||
|
||||
@end
|
||||
|
||||
@interface FlexibleSeparatorSurroundingContent : LayoutExampleNode
|
||||
|
||||
@property (nonatomic, strong) ASImageNode *topSeparator;
|
||||
@property (nonatomic, strong) ASImageNode *bottomSeparator;
|
||||
@property (nonatomic, strong) ASTextNode *textNode;
|
||||
|
||||
@end
|
||||
272
examples/LayoutSpecPlayground/Sample/LayoutExampleNodes.m
Normal file
272
examples/LayoutSpecPlayground/Sample/LayoutExampleNodes.m
Normal file
@@ -0,0 +1,272 @@
|
||||
//
|
||||
// LayoutExampleNodes.m
|
||||
// Sample
|
||||
//
|
||||
// Created by Hannah Troisi on 9/13/16.
|
||||
// Copyright © 2016 Facebook. All rights reserved.
|
||||
//
|
||||
|
||||
#import "LayoutExampleNodes.h"
|
||||
#import "Utilities.h"
|
||||
#import "UIImage+ASConvenience.h"
|
||||
|
||||
#define USER_IMAGE_HEIGHT 60
|
||||
#define HORIZONTAL_BUFFER 10
|
||||
#define VERTICAL_BUFFER 5
|
||||
#define FONT_SIZE 20
|
||||
|
||||
@implementation LayoutExampleNode
|
||||
|
||||
- (instancetype)init
|
||||
{
|
||||
self = [super init];
|
||||
if (self) {
|
||||
self.automaticallyManagesSubnodes = YES;
|
||||
self.shouldVisualizeLayoutSpecs = NO;
|
||||
self.shouldCacheLayoutSpec = NO;
|
||||
self.backgroundColor = [UIColor whiteColor];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
#pragma mark - helper methods
|
||||
|
||||
- (NSAttributedString *)usernameAttributedStringWithFontSize:(CGFloat)size
|
||||
{
|
||||
return [NSAttributedString attributedStringWithString:@"hannahmbanana"
|
||||
fontSize:size
|
||||
color:[UIColor darkBlueColor]
|
||||
firstWordColor:nil];
|
||||
}
|
||||
|
||||
- (NSAttributedString *)locationAttributedStringWithFontSize:(CGFloat)size
|
||||
{
|
||||
return [NSAttributedString attributedStringWithString:@"San Fransisco, CA"
|
||||
fontSize:size
|
||||
color:[UIColor lightBlueColor]
|
||||
firstWordColor:nil];
|
||||
}
|
||||
|
||||
- (NSAttributedString *)uploadDateAttributedStringWithFontSize:(CGFloat)size
|
||||
{
|
||||
return [NSAttributedString attributedStringWithString:@"30m"
|
||||
fontSize:size
|
||||
color:[UIColor lightGrayColor]
|
||||
firstWordColor:nil];
|
||||
}
|
||||
|
||||
- (NSAttributedString *)likesAttributedStringWithFontSize:(CGFloat)size
|
||||
{
|
||||
return [NSAttributedString attributedStringWithString:@"♥︎ 17 likes"
|
||||
fontSize:size
|
||||
color:[UIColor darkBlueColor]
|
||||
firstWordColor:nil];
|
||||
}
|
||||
|
||||
- (NSAttributedString *)descriptionAttributedStringWithFontSize:(CGFloat)size
|
||||
{
|
||||
NSString *string = [NSString stringWithFormat:@"hannahmbanana check out this cool pic from the internet!"];
|
||||
NSAttributedString *attrString = [NSAttributedString attributedStringWithString:string
|
||||
fontSize:size
|
||||
color:[UIColor darkGrayColor]
|
||||
firstWordColor:[UIColor darkBlueColor]];
|
||||
return attrString;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation HorizontalStackWithSpacer
|
||||
|
||||
- (instancetype)init
|
||||
{
|
||||
self = [super init];
|
||||
|
||||
if (self) {
|
||||
_usernameNode = [[ASTextNode alloc] init];
|
||||
_usernameNode.attributedText = [self usernameAttributedStringWithFontSize:FONT_SIZE];
|
||||
|
||||
_postLocationNode = [[ASTextNode alloc] init];
|
||||
_postLocationNode.maximumNumberOfLines = 1;
|
||||
_postLocationNode.attributedText = [self locationAttributedStringWithFontSize:FONT_SIZE];
|
||||
|
||||
_postTimeNode = [[ASTextNode alloc] init];
|
||||
_postTimeNode.attributedText = [self uploadDateAttributedStringWithFontSize:FONT_SIZE];
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (ASLayoutSpec *)layoutSpecThatFits:(ASSizeRange)constrainedSize
|
||||
{
|
||||
_usernameNode.style.flexShrink = 1.0;
|
||||
_postLocationNode.style.flexShrink = 1.0;
|
||||
|
||||
ASStackLayoutSpec *verticalStackSpec = [ASStackLayoutSpec verticalStackLayoutSpec];
|
||||
verticalStackSpec.style.flexShrink = 1.0;
|
||||
|
||||
// Example: see ASDKgram for how this technique can be used to animate in the location label
|
||||
// once a separate network request provides the data.
|
||||
if (_postLocationNode.attributedText) {
|
||||
[verticalStackSpec setChildren:@[_usernameNode, _postLocationNode]];
|
||||
} else {
|
||||
[verticalStackSpec setChildren:@[_usernameNode]];
|
||||
}
|
||||
|
||||
ASLayoutSpec *spacerSpec = [[ASLayoutSpec alloc] init];
|
||||
spacerSpec.style.flexGrow = 1.0;
|
||||
spacerSpec.style.flexShrink = 1.0;
|
||||
|
||||
// horizontal stack
|
||||
ASStackLayoutSpec *horizontalStackSpec = [ASStackLayoutSpec horizontalStackLayoutSpec];
|
||||
horizontalStackSpec.alignItems = ASStackLayoutAlignItemsCenter; // center items vertically in horiz stack
|
||||
horizontalStackSpec.justifyContent = ASStackLayoutJustifyContentStart; // justify content to left
|
||||
horizontalStackSpec.style.flexShrink = 1.0;
|
||||
horizontalStackSpec.style.flexGrow = 1.0;
|
||||
[horizontalStackSpec setChildren:@[verticalStackSpec, spacerSpec, _postTimeNode]];
|
||||
|
||||
// inset horizontal stack
|
||||
UIEdgeInsets insets = UIEdgeInsetsMake(0, 10, 0, 10);
|
||||
ASInsetLayoutSpec *headerInsetSpec = [ASInsetLayoutSpec insetLayoutSpecWithInsets:insets child:horizontalStackSpec];
|
||||
headerInsetSpec.style.flexShrink = 1.0;
|
||||
headerInsetSpec.style.flexGrow = 1.0;
|
||||
|
||||
return headerInsetSpec;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@implementation PhotoWithInsetTextOverlay
|
||||
|
||||
- (instancetype)init
|
||||
{
|
||||
self = [super init];
|
||||
|
||||
if (self) {
|
||||
_photoNode = [[ASNetworkImageNode alloc] init];
|
||||
_photoNode.URL = [NSURL URLWithString:@"http://asyncdisplaykit.org/static/images/layout-examples-photo-with-inset-text-overlay-photo.png"];
|
||||
|
||||
_titleNode = [[ASTextNode alloc] init];
|
||||
_titleNode.maximumNumberOfLines = 2;
|
||||
_titleNode.truncationAttributedText = [NSAttributedString attributedStringWithString:@"..."
|
||||
fontSize:16
|
||||
color:[UIColor whiteColor]
|
||||
firstWordColor:nil];
|
||||
_titleNode.attributedText = [NSAttributedString attributedStringWithString:@"family fall hikes"
|
||||
fontSize:16
|
||||
color:[UIColor whiteColor]
|
||||
firstWordColor:nil];
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (ASLayoutSpec *)layoutSpecThatFits:(ASSizeRange)constrainedSize
|
||||
{
|
||||
_photoNode.style.preferredSize = CGSizeMake(USER_IMAGE_HEIGHT*2, USER_IMAGE_HEIGHT*2);
|
||||
|
||||
UIEdgeInsets insets = UIEdgeInsetsMake(INFINITY, 12, 12, 12);
|
||||
ASInsetLayoutSpec *textInsetSpec = [ASInsetLayoutSpec insetLayoutSpecWithInsets:insets
|
||||
child:_titleNode];
|
||||
|
||||
ASOverlayLayoutSpec *textOverlaySpec = [ASOverlayLayoutSpec overlayLayoutSpecWithChild:_photoNode
|
||||
overlay:textInsetSpec];
|
||||
|
||||
return textOverlaySpec;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@implementation PhotoWithOutsetIconOverlay
|
||||
|
||||
- (instancetype)init
|
||||
{
|
||||
self = [super init];
|
||||
|
||||
if (self) {
|
||||
|
||||
_photoNode = [[ASNetworkImageNode alloc] init];
|
||||
_photoNode.URL = [NSURL URLWithString:@"http://asyncdisplaykit.org/static/images/layout-examples-photo-with-outset-icon-overlay-photo.png"];
|
||||
|
||||
_iconNode = [[ASNetworkImageNode alloc] init];
|
||||
_iconNode.URL = [NSURL URLWithString:@"http://asyncdisplaykit.org/static/images/layout-examples-photo-with-outset-icon-overlay-icon.png"];
|
||||
|
||||
[_iconNode setImageModificationBlock:^UIImage *(UIImage *image) { // FIXME: in framework autocomplete for setImageModificationBlock line seems broken
|
||||
CGSize profileImageSize = CGSizeMake(USER_IMAGE_HEIGHT, USER_IMAGE_HEIGHT);
|
||||
return [image makeCircularImageWithSize:profileImageSize withBorderWidth:10];
|
||||
}];
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (ASLayoutSpec *)layoutSpecThatFits:(ASSizeRange)constrainedSize
|
||||
{
|
||||
_iconNode.style.preferredSize = CGSizeMake(40, 40);
|
||||
_photoNode.style.preferredSize = CGSizeMake(150, 150);
|
||||
|
||||
CGFloat x = 150;
|
||||
CGFloat y = 0;
|
||||
|
||||
_iconNode.style.layoutPosition = CGPointMake(x, y);
|
||||
_photoNode.style.layoutPosition = CGPointMake(40 / 2.0, 40 / 2.0);
|
||||
|
||||
ASAbsoluteLayoutSpec *absoluteLayoutSpec = [ASAbsoluteLayoutSpec absoluteLayoutSpecWithChildren:@[_photoNode, _iconNode]];
|
||||
|
||||
return absoluteLayoutSpec;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@implementation FlexibleSeparatorSurroundingContent
|
||||
|
||||
- (instancetype)init
|
||||
{
|
||||
self = [super init];
|
||||
|
||||
if (self) {
|
||||
|
||||
self.backgroundColor = [UIColor cyanColor];
|
||||
|
||||
_topSeparator = [[ASImageNode alloc] init];
|
||||
_topSeparator.image = [UIImage as_resizableRoundedImageWithCornerRadius:1.0
|
||||
cornerColor:[UIColor blackColor]
|
||||
fillColor:[UIColor blackColor]];
|
||||
|
||||
_textNode = [[ASTextNode alloc] init];
|
||||
_textNode.attributedText = [NSAttributedString attributedStringWithString:@"this is a long text node"
|
||||
fontSize:16
|
||||
color:[UIColor blackColor]
|
||||
firstWordColor:nil];
|
||||
|
||||
_bottomSeparator = [[ASImageNode alloc] init];
|
||||
_bottomSeparator.image = [UIImage as_resizableRoundedImageWithCornerRadius:1.0
|
||||
cornerColor:[UIColor blackColor]
|
||||
fillColor:[UIColor blackColor]];
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (ASLayoutSpec *)layoutSpecThatFits:(ASSizeRange)constrainedSize
|
||||
{
|
||||
_topSeparator.style.flexGrow = 1.0;
|
||||
_bottomSeparator.style.flexGrow = 1.0;
|
||||
|
||||
UIEdgeInsets contentInsets = UIEdgeInsetsMake(10, 10, 10, 10);
|
||||
ASInsetLayoutSpec *insetContentSpec = [ASInsetLayoutSpec insetLayoutSpecWithInsets:contentInsets
|
||||
child:_textNode];
|
||||
// final vertical stack
|
||||
ASStackLayoutSpec *verticalStackSpec = [ASStackLayoutSpec verticalStackLayoutSpec];
|
||||
verticalStackSpec.direction = ASStackLayoutDirectionVertical;
|
||||
verticalStackSpec.justifyContent = ASStackLayoutJustifyContentCenter;
|
||||
verticalStackSpec.alignItems = ASStackLayoutAlignItemsStretch;
|
||||
verticalStackSpec.children = @[_topSeparator, insetContentSpec, _bottomSeparator];
|
||||
|
||||
return verticalStackSpec;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
15
examples/LayoutSpecPlayground/Sample/PhotoPostNode.h
Normal file
15
examples/LayoutSpecPlayground/Sample/PhotoPostNode.h
Normal file
@@ -0,0 +1,15 @@
|
||||
//
|
||||
// PhotoPostNode.h
|
||||
// ASLayoutSpecPlayground
|
||||
//
|
||||
// Created by Hannah Troisi on 3/11/16.
|
||||
// Copyright © 2016 Hannah Troisi. All rights reserved.
|
||||
//
|
||||
|
||||
#import "AsyncDisplayKit.h"
|
||||
|
||||
@interface PhotoPostNode : ASDisplayNode
|
||||
|
||||
- (instancetype)initWithIndex:(NSUInteger)index;
|
||||
|
||||
@end
|
||||
249
examples/LayoutSpecPlayground/Sample/PhotoPostNode.m
Normal file
249
examples/LayoutSpecPlayground/Sample/PhotoPostNode.m
Normal file
@@ -0,0 +1,249 @@
|
||||
//
|
||||
// PhotoPostNode.m
|
||||
// ASLayoutSpecPlayground
|
||||
//
|
||||
// Created by Hannah Troisi on 3/11/16.
|
||||
// Copyright © 2016 Hannah Troisi. All rights reserved.
|
||||
//
|
||||
|
||||
#import "PhotoPostNode.h"
|
||||
#import "AsyncDisplayKit+Debug.h"
|
||||
#import "Utilities.h"
|
||||
|
||||
#define USER_IMAGE_HEIGHT 60
|
||||
#define HORIZONTAL_BUFFER 10
|
||||
#define VERTICAL_BUFFER 5
|
||||
#define FONT_SIZE 20
|
||||
|
||||
@implementation PhotoPostNode
|
||||
{
|
||||
NSUInteger _index;
|
||||
ASNetworkImageNode *_userAvatarImageView;
|
||||
ASNetworkImageNode *_photoImageView;
|
||||
ASTextNode *_userNameLabel;
|
||||
ASTextNode *_photoLocationLabel;
|
||||
ASTextNode *_photoTimeIntervalSincePostLabel;
|
||||
ASTextNode *_photoLikesLabel;
|
||||
ASTextNode *_photoDescriptionLabel;
|
||||
}
|
||||
|
||||
#pragma mark - Lifecycle
|
||||
|
||||
- (instancetype)initWithIndex:(NSUInteger)index
|
||||
{
|
||||
self = [super init];
|
||||
|
||||
if (self) {
|
||||
|
||||
self.backgroundColor = [UIColor whiteColor];
|
||||
self.automaticallyManagesSubnodes = YES;
|
||||
self.shouldVisualizeLayoutSpecs = YES;
|
||||
self.shouldCacheLayoutSpec = YES;
|
||||
|
||||
_index = index;
|
||||
|
||||
_userAvatarImageView = [[ASNetworkImageNode alloc] init];
|
||||
_userAvatarImageView.URL = [NSURL URLWithString:@"https://s-media-cache-ak0.pinimg.com/avatars/503h_1458880322_140.jpg"];
|
||||
|
||||
[_userAvatarImageView setImageModificationBlock:^UIImage *(UIImage *image) { // FIXME: in framework autocomplete for setImageModificationBlock line seems broken
|
||||
CGSize profileImageSize = CGSizeMake(USER_IMAGE_HEIGHT, USER_IMAGE_HEIGHT);
|
||||
return [image makeCircularImageWithSize:profileImageSize withBorderWidth:0];
|
||||
}];
|
||||
|
||||
_userNameLabel = [[ASTextNode alloc] init];
|
||||
_userNameLabel.attributedText = [self usernameAttributedStringWithFontSize:FONT_SIZE];
|
||||
|
||||
_photoLocationLabel = [[ASTextNode alloc] init];
|
||||
_photoLocationLabel.maximumNumberOfLines = 1;
|
||||
_photoLocationLabel.attributedText = [self locationAttributedStringWithFontSize:FONT_SIZE];
|
||||
|
||||
_photoTimeIntervalSincePostLabel = [[ASTextNode alloc] init];
|
||||
_photoTimeIntervalSincePostLabel.attributedText = [self uploadDateAttributedStringWithFontSize:FONT_SIZE];
|
||||
|
||||
_photoImageView = [[ASNetworkImageNode alloc] init];
|
||||
_photoImageView.URL = [NSURL URLWithString:@"https://s-media-cache-ak0.pinimg.com/564x/9f/5b/3a/9f5b3a35640bc7a5d484b66124c48c46.jpg"];
|
||||
|
||||
_photoLikesLabel = [[ASTextNode alloc] init];
|
||||
_photoLikesLabel.attributedText = [self likesAttributedStringWithFontSize:FONT_SIZE];
|
||||
|
||||
_photoDescriptionLabel = [[ASTextNode alloc] init];
|
||||
_photoDescriptionLabel.attributedText = [self descriptionAttributedStringWithFontSize:FONT_SIZE];
|
||||
_photoDescriptionLabel.maximumNumberOfLines = 3;
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (ASLayoutSpec *)layoutSpecThatFits:(ASSizeRange)constrainedSize
|
||||
{
|
||||
switch (_index) {
|
||||
case 1:
|
||||
return [self layoutSpecThatFitsNavBar:constrainedSize];
|
||||
case 2:
|
||||
return [self layoutSpecThatFitsASDKgram:constrainedSize];
|
||||
default:
|
||||
return [self layoutSpecThatFitsASDKgram:constrainedSize];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
- (ASLayoutSpec *)layoutSpecThatFitsNavBar:(ASSizeRange)constrainedSize
|
||||
{
|
||||
// username / photo location header vertical stack
|
||||
|
||||
_userNameLabel.style.flexShrink = 1.0;
|
||||
_photoLocationLabel.style.flexShrink = 1.0;
|
||||
|
||||
ASStackLayoutSpec *headerSubStack = [ASStackLayoutSpec verticalStackLayoutSpec];
|
||||
headerSubStack.style.flexShrink = 1.0;
|
||||
|
||||
if (_photoLocationLabel.attributedText) {
|
||||
[headerSubStack setChildren:@[_userNameLabel, _photoLocationLabel]];
|
||||
} else {
|
||||
[headerSubStack setChildren:@[_userNameLabel]];
|
||||
}
|
||||
|
||||
// header stack
|
||||
|
||||
_userAvatarImageView.style.preferredSize = CGSizeMake(USER_IMAGE_HEIGHT, USER_IMAGE_HEIGHT);
|
||||
_photoTimeIntervalSincePostLabel.style.spacingBefore = HORIZONTAL_BUFFER; // hack to remove double spaces around spacer
|
||||
|
||||
UIEdgeInsets avatarInsets = UIEdgeInsetsMake(HORIZONTAL_BUFFER, 0, HORIZONTAL_BUFFER, HORIZONTAL_BUFFER);
|
||||
ASInsetLayoutSpec *avatarInset = [ASInsetLayoutSpec insetLayoutSpecWithInsets:avatarInsets child:_userAvatarImageView];
|
||||
|
||||
ASLayoutSpec *spacer = [[ASLayoutSpec alloc] init];
|
||||
spacer.style.flexGrow = 1.0;
|
||||
spacer.style.flexShrink = 1.0; // FIXME: this overrides stuff :) THIS IS A SYSTEMIC ISSUE - can we make layoutSpecThatFits only run once? cache layoutSpec, just use new constrainedSize, don't put properties in layoutSpecThatFits
|
||||
// separate the idea of laying out and rerunning with new constrainedSize
|
||||
|
||||
ASStackLayoutSpec *headerStack = [ASStackLayoutSpec horizontalStackLayoutSpec];
|
||||
headerStack.alignItems = ASStackLayoutAlignItemsCenter; // center items vertically in horizontal stack
|
||||
headerStack.justifyContent = ASStackLayoutJustifyContentStart; // justify content to the left side of the header stack
|
||||
headerStack.style.flexShrink = 1.0;
|
||||
headerStack.style.flexGrow = 1.0;
|
||||
|
||||
[headerStack setChildren:@[avatarInset, headerSubStack, spacer, _photoTimeIntervalSincePostLabel]];
|
||||
|
||||
// header inset stack
|
||||
|
||||
UIEdgeInsets insets = UIEdgeInsetsMake(0, HORIZONTAL_BUFFER, 0, HORIZONTAL_BUFFER);
|
||||
ASInsetLayoutSpec *headerWithInset = [ASInsetLayoutSpec insetLayoutSpecWithInsets:insets child:headerStack];
|
||||
headerWithInset.style.flexShrink = 1.0;
|
||||
headerWithInset.style.flexGrow = 1.0;
|
||||
|
||||
return headerWithInset;
|
||||
}
|
||||
|
||||
- (ASLayoutSpec *)layoutSpecThatFitsASDKgram:(ASSizeRange)constrainedSize
|
||||
{
|
||||
// username / photo location header vertical stack
|
||||
|
||||
_userNameLabel.style.flexShrink = 1.0;
|
||||
_photoLocationLabel.style.flexShrink = 1.0;
|
||||
|
||||
ASStackLayoutSpec *headerSubStack = [ASStackLayoutSpec verticalStackLayoutSpec];
|
||||
headerSubStack.style.flexShrink = 1.0;
|
||||
|
||||
if (_photoLocationLabel.attributedText) {
|
||||
[headerSubStack setChildren:@[_userNameLabel, _photoLocationLabel]];
|
||||
} else {
|
||||
[headerSubStack setChildren:@[_userNameLabel]];
|
||||
}
|
||||
|
||||
// header stack
|
||||
|
||||
_userAvatarImageView.style.preferredSize = CGSizeMake(USER_IMAGE_HEIGHT, USER_IMAGE_HEIGHT);
|
||||
_photoTimeIntervalSincePostLabel.style.spacingBefore = HORIZONTAL_BUFFER; // hack to remove double spaces around spacer
|
||||
|
||||
UIEdgeInsets avatarInsets = UIEdgeInsetsMake(HORIZONTAL_BUFFER, 0, HORIZONTAL_BUFFER, HORIZONTAL_BUFFER);
|
||||
ASInsetLayoutSpec *avatarInset = [ASInsetLayoutSpec insetLayoutSpecWithInsets:avatarInsets child:_userAvatarImageView];
|
||||
|
||||
ASLayoutSpec *spacer = [[ASLayoutSpec alloc] init];
|
||||
spacer.style.flexGrow = 1.0;
|
||||
spacer.style.flexShrink = 1.0; // FIXME: this overrides stuff :) THIS IS A SYSTEMIC ISSUE - can we make layoutSpecThatFits only run once? cache layoutSpec, just use new constrainedSize, don't put properties in layoutSpecThatFits
|
||||
// separate the idea of laying out and rerunning with new constrainedSize
|
||||
|
||||
ASStackLayoutSpec *headerStack = [ASStackLayoutSpec horizontalStackLayoutSpec];
|
||||
headerStack.alignItems = ASStackLayoutAlignItemsCenter; // center items vertically in horizontal stack
|
||||
headerStack.justifyContent = ASStackLayoutJustifyContentStart; // justify content to the left side of the header stack
|
||||
headerStack.style.flexShrink = 1.0;
|
||||
headerStack.style.flexGrow = 1.0;
|
||||
|
||||
[headerStack setChildren:@[avatarInset, headerSubStack, spacer, _photoTimeIntervalSincePostLabel]];
|
||||
|
||||
// header inset stack
|
||||
|
||||
UIEdgeInsets insets = UIEdgeInsetsMake(0, HORIZONTAL_BUFFER, 0, HORIZONTAL_BUFFER);
|
||||
ASInsetLayoutSpec *headerWithInset = [ASInsetLayoutSpec insetLayoutSpecWithInsets:insets child:headerStack];
|
||||
headerWithInset.style.flexShrink = 1.0;
|
||||
headerWithInset.style.flexGrow = 1.0;
|
||||
|
||||
// footer stack
|
||||
|
||||
ASStackLayoutSpec *footerStack = [ASStackLayoutSpec verticalStackLayoutSpec];
|
||||
footerStack.spacing = VERTICAL_BUFFER;
|
||||
|
||||
[footerStack setChildren:@[_photoLikesLabel, _photoDescriptionLabel]];
|
||||
|
||||
// footer inset stack
|
||||
|
||||
UIEdgeInsets footerInsets = UIEdgeInsetsMake(VERTICAL_BUFFER, HORIZONTAL_BUFFER, VERTICAL_BUFFER, HORIZONTAL_BUFFER);
|
||||
ASInsetLayoutSpec *footerWithInset = [ASInsetLayoutSpec insetLayoutSpecWithInsets:footerInsets child:footerStack];
|
||||
|
||||
// vertical stack
|
||||
|
||||
ASRatioLayoutSpec *photoRatioSpec = [ASRatioLayoutSpec ratioLayoutSpecWithRatio:1.0 child:_photoImageView];
|
||||
|
||||
ASStackLayoutSpec *verticalStack = [ASStackLayoutSpec verticalStackLayoutSpec];
|
||||
verticalStack.alignItems = ASStackLayoutAlignItemsStretch; // sretch headerStack to fill horizontal space
|
||||
[verticalStack setChildren:@[headerWithInset, photoRatioSpec, footerWithInset]];
|
||||
verticalStack.style.flexShrink = 1.0;
|
||||
|
||||
return verticalStack;
|
||||
}
|
||||
|
||||
#pragma mark - helper methods
|
||||
|
||||
- (NSAttributedString *)usernameAttributedStringWithFontSize:(CGFloat)size
|
||||
{
|
||||
return [NSAttributedString attributedStringWithString:@"hannahmbanana"
|
||||
fontSize:size
|
||||
color:[UIColor darkBlueColor]
|
||||
firstWordColor:nil];
|
||||
}
|
||||
|
||||
- (NSAttributedString *)locationAttributedStringWithFontSize:(CGFloat)size
|
||||
{
|
||||
return [NSAttributedString attributedStringWithString:@"San Fransisco, CA"
|
||||
fontSize:size
|
||||
color:[UIColor lightBlueColor]
|
||||
firstWordColor:nil];
|
||||
}
|
||||
|
||||
- (NSAttributedString *)uploadDateAttributedStringWithFontSize:(CGFloat)size
|
||||
{
|
||||
return [NSAttributedString attributedStringWithString:@"30m"
|
||||
fontSize:size
|
||||
color:[UIColor lightGrayColor]
|
||||
firstWordColor:nil];
|
||||
}
|
||||
|
||||
- (NSAttributedString *)likesAttributedStringWithFontSize:(CGFloat)size
|
||||
{
|
||||
return [NSAttributedString attributedStringWithString:@"♥︎ 17 likes"
|
||||
fontSize:size
|
||||
color:[UIColor darkBlueColor]
|
||||
firstWordColor:nil];
|
||||
}
|
||||
|
||||
- (NSAttributedString *)descriptionAttributedStringWithFontSize:(CGFloat)size
|
||||
{
|
||||
NSString *string = [NSString stringWithFormat:@"hannahmbanana check out this cool pic from the internet!"];
|
||||
NSAttributedString *attrString = [NSAttributedString attributedStringWithString:string
|
||||
fontSize:size
|
||||
color:[UIColor darkGrayColor]
|
||||
firstWordColor:[UIColor darkBlueColor]];
|
||||
return attrString;
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,24 @@
|
||||
//
|
||||
// PlaygroundContainerNode.h
|
||||
// Sample
|
||||
//
|
||||
// Created by Hannah Troisi on 3/19/16.
|
||||
// Copyright © 2016 Facebook. All rights reserved.
|
||||
//
|
||||
|
||||
#import <AsyncDisplayKit/AsyncDisplayKit.h>
|
||||
|
||||
@protocol PlaygroundContainerNodeDelegate <NSObject>
|
||||
|
||||
- (void)relayoutWithSize:(ASSizeRange)size;
|
||||
|
||||
@end
|
||||
|
||||
@interface PlaygroundContainerNode : ASCellNode
|
||||
|
||||
@property (nonatomic, weak) id<PlaygroundContainerNodeDelegate> delegate;
|
||||
|
||||
+ (NSUInteger)containerNodeCount;
|
||||
- (instancetype)initWithIndex:(NSUInteger)index;
|
||||
|
||||
@end
|
||||
124
examples/LayoutSpecPlayground/Sample/PlaygroundContainerNode.m
Normal file
124
examples/LayoutSpecPlayground/Sample/PlaygroundContainerNode.m
Normal file
@@ -0,0 +1,124 @@
|
||||
//
|
||||
// PlaygroundContainerNode.m
|
||||
// Sample
|
||||
//
|
||||
// Created by Hannah Troisi on 3/19/16.
|
||||
// Copyright © 2016 Facebook. All rights reserved.
|
||||
//
|
||||
|
||||
#import "PlaygroundContainerNode.h"
|
||||
#import "LayoutExampleNodes.h"
|
||||
#import "PhotoPostNode.h"
|
||||
#import <AsyncDisplayKit/ASLayoutElementInspectorNode.h>
|
||||
#import <AsyncDisplayKit/AsyncDisplayKit+Debug.h>
|
||||
|
||||
#define RESIZE_HANDLE_SIZE 30
|
||||
|
||||
@implementation PlaygroundContainerNode
|
||||
{
|
||||
ASDisplayNode *_playgroundNode;
|
||||
ASImageNode *_resizeHandle;
|
||||
CGPoint _resizeStartLocation;
|
||||
}
|
||||
|
||||
#pragma mark - Lifecycle
|
||||
|
||||
+ (NSUInteger)containerNodeCount
|
||||
{
|
||||
return 5;
|
||||
}
|
||||
|
||||
+ (ASDisplayNode *)nodeForIndex:(NSUInteger)index
|
||||
{
|
||||
switch (index) {
|
||||
case 0: return [[HorizontalStackWithSpacer alloc] init];
|
||||
case 1: return [[PhotoWithInsetTextOverlay alloc] init];
|
||||
case 2: return [[PhotoWithOutsetIconOverlay alloc] init];
|
||||
case 3: return [[FlexibleSeparatorSurroundingContent alloc] init];
|
||||
case 4: return [[PhotoPostNode alloc] initWithIndex:0];
|
||||
default: return [[PhotoPostNode alloc] initWithIndex:1];
|
||||
}
|
||||
}
|
||||
|
||||
- (instancetype)initWithIndex:(NSUInteger)index
|
||||
{
|
||||
self = [super init];
|
||||
|
||||
if (self) {
|
||||
self.backgroundColor = [UIColor whiteColor]; //[UIColor colorWithRed:255/255.0 green:181/255.0 blue:68/255.0 alpha:1];
|
||||
self.automaticallyManagesSubnodes = YES;
|
||||
|
||||
_playgroundNode = [[self class] nodeForIndex:index];
|
||||
|
||||
_resizeHandle = [[ASImageNode alloc] init];
|
||||
_resizeHandle.image = [UIImage imageNamed:@"resizeHandle"];
|
||||
_resizeHandle.userInteractionEnabled = YES;
|
||||
// [self addSubnode:_resizeHandle];
|
||||
|
||||
[ASLayoutElementInspectorNode sharedInstance].style.flexBasis = ASDimensionMakeWithFraction(1.0);
|
||||
[ASLayoutElementInspectorNode sharedInstance].vizNodeInsetSize = 10.0;
|
||||
|
||||
self.shouldVisualizeLayoutSpecs = NO;
|
||||
self.shouldCacheLayoutSpec = NO;
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)didLoad
|
||||
{
|
||||
[super didLoad];
|
||||
UIPanGestureRecognizer *gr = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(resizePlayground:)];
|
||||
[_resizeHandle.view addGestureRecognizer:gr];
|
||||
}
|
||||
|
||||
// manually layout _resizeHandle // FIXME: add this to an overlayStack in layoutSpecThatFits?
|
||||
- (void)layout
|
||||
{
|
||||
[super layout];
|
||||
[self.view bringSubviewToFront:_resizeHandle.view];
|
||||
|
||||
CGSize playgroundSize = _playgroundNode.calculatedLayout.size;
|
||||
CGRect rect = CGRectZero;
|
||||
rect.size = CGSizeMake(RESIZE_HANDLE_SIZE, RESIZE_HANDLE_SIZE);
|
||||
rect.origin = CGPointMake(playgroundSize.width - rect.size.width, playgroundSize.height - rect.size.height);
|
||||
_resizeHandle.frame = rect;
|
||||
}
|
||||
|
||||
- (ASLayoutSpec *)layoutSpecThatFits:(ASSizeRange)constrainedSize
|
||||
{
|
||||
_playgroundNode.style.flexGrow = 1.0;
|
||||
_playgroundNode.style.flexShrink = 1.0;
|
||||
|
||||
return [ASInsetLayoutSpec insetLayoutSpecWithInsets:UIEdgeInsetsMake(10, 10, 10, 10)
|
||||
child:_playgroundNode];
|
||||
}
|
||||
|
||||
#pragma mark - Gesture Handling
|
||||
|
||||
- (void)resizePlayground:(UIPanGestureRecognizer *)sender
|
||||
{
|
||||
if (sender.state == UIGestureRecognizerStateBegan) {
|
||||
_resizeStartLocation = [sender locationInView:sender.view];
|
||||
}
|
||||
else if (sender.state == UIGestureRecognizerStateChanged) {
|
||||
CGPoint location = [sender locationInView:sender.view];
|
||||
CGPoint translation = CGPointMake(location.x - _resizeStartLocation.x, location.y - _resizeStartLocation.y);
|
||||
[self changePlaygroundFrameWithTranslation:translation];
|
||||
}
|
||||
else if (sender.state == UIGestureRecognizerStateEnded || sender.state == UIGestureRecognizerStateCancelled || sender.state == UIGestureRecognizerStateFailed) {
|
||||
_resizeStartLocation = CGPointZero;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)changePlaygroundFrameWithTranslation:(CGPoint)translation
|
||||
{
|
||||
ASSizeRange constrainedSize = self.constrainedSizeForCalculatedLayout;
|
||||
|
||||
constrainedSize.max.width = MAX(0, constrainedSize.max.width + translation.x);
|
||||
constrainedSize.max.height = MAX(0, constrainedSize.max.height + translation.y);
|
||||
|
||||
[self.delegate relayoutWithSize:constrainedSize];
|
||||
}
|
||||
|
||||
@end
|
||||
32
examples/LayoutSpecPlayground/Sample/Utilities.h
Normal file
32
examples/LayoutSpecPlayground/Sample/Utilities.h
Normal file
@@ -0,0 +1,32 @@
|
||||
//
|
||||
// Utilities.h
|
||||
// Flickrgram
|
||||
//
|
||||
// Created by Hannah Troisi on 3/9/16.
|
||||
// Copyright © 2016 Hannah Troisi. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
@interface UIColor (Additions)
|
||||
|
||||
+ (UIColor *)darkBlueColor;
|
||||
+ (UIColor *)lightBlueColor;
|
||||
+ (UIColor *)duskColor;
|
||||
+ (UIColor *)customOrangeColor;
|
||||
|
||||
@end
|
||||
|
||||
@interface UIImage (Additions)
|
||||
|
||||
- (UIImage *)makeCircularImageWithSize:(CGSize)size withBorderWidth:(CGFloat)width;
|
||||
|
||||
@end
|
||||
|
||||
@interface NSAttributedString (Additions)
|
||||
|
||||
+ (NSAttributedString *)attributedStringWithString:(NSString *)string fontSize:(CGFloat)size
|
||||
color:(UIColor *)color firstWordColor:(UIColor *)firstWordColor;
|
||||
|
||||
@end
|
||||
98
examples/LayoutSpecPlayground/Sample/Utilities.m
Normal file
98
examples/LayoutSpecPlayground/Sample/Utilities.m
Normal file
@@ -0,0 +1,98 @@
|
||||
//
|
||||
// Utilities.m
|
||||
// Flickrgram
|
||||
//
|
||||
// Created by Hannah Troisi on 3/9/16.
|
||||
// Copyright © 2016 Hannah Troisi. All rights reserved.
|
||||
//
|
||||
|
||||
#import "Utilities.h"
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
#define StrokeRoundedImages 0
|
||||
|
||||
@implementation UIColor (Additions)
|
||||
|
||||
+ (UIColor *)darkBlueColor
|
||||
{
|
||||
return [UIColor colorWithRed:18.0/255.0 green:86.0/255.0 blue:136.0/255.0 alpha:1.0];
|
||||
}
|
||||
|
||||
+ (UIColor *)lightBlueColor
|
||||
{
|
||||
return [UIColor colorWithRed:0.0 green:122.0/255.0 blue:1.0 alpha:1.0];
|
||||
}
|
||||
|
||||
+ (UIColor *)duskColor
|
||||
{
|
||||
return [UIColor colorWithRed:255/255.0 green:181/255.0 blue:68/255.0 alpha:1];
|
||||
}
|
||||
|
||||
+ (UIColor *)customOrangeColor
|
||||
{
|
||||
return [UIColor colorWithRed:40/255.0 green:43/255.0 blue:53/255.0 alpha:1.0];
|
||||
}
|
||||
|
||||
|
||||
@end
|
||||
|
||||
@implementation UIImage (Additions)
|
||||
|
||||
- (UIImage *)makeCircularImageWithSize:(CGSize)size withBorderWidth:(CGFloat)width
|
||||
{
|
||||
// make a CGRect with the image's size
|
||||
CGRect circleRect = (CGRect) {CGPointZero, size};
|
||||
|
||||
// begin the image context since we're not in a drawRect:
|
||||
UIGraphicsBeginImageContextWithOptions(circleRect.size, NO, 0);
|
||||
|
||||
// create a UIBezierPath circle
|
||||
UIBezierPath *circle = [UIBezierPath bezierPathWithRoundedRect:circleRect cornerRadius:circleRect.size.width/2];
|
||||
|
||||
// clip to the circle
|
||||
[circle addClip];
|
||||
|
||||
[[UIColor whiteColor] set];
|
||||
[circle fill];
|
||||
|
||||
// draw the image in the circleRect *AFTER* the context is clipped
|
||||
[self drawInRect:circleRect];
|
||||
|
||||
// create a border (for white background pictures)
|
||||
if (width > 0) {
|
||||
circle.lineWidth = width;
|
||||
[[UIColor whiteColor] set];
|
||||
[circle stroke];
|
||||
}
|
||||
|
||||
// get an image from the image context
|
||||
UIImage *roundedImage = UIGraphicsGetImageFromCurrentImageContext();
|
||||
|
||||
// end the image context since we're not in a drawRect:
|
||||
UIGraphicsEndImageContext();
|
||||
|
||||
return roundedImage;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation NSAttributedString (Additions)
|
||||
|
||||
+ (NSAttributedString *)attributedStringWithString:(NSString *)string fontSize:(CGFloat)size
|
||||
color:(nullable UIColor *)color firstWordColor:(nullable UIColor *)firstWordColor
|
||||
{
|
||||
NSDictionary *attributes = @{NSForegroundColorAttributeName: color ? : [UIColor blackColor],
|
||||
NSFontAttributeName: [UIFont boldSystemFontOfSize:size]};
|
||||
NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithString:string];
|
||||
[attributedString addAttributes:attributes range:NSMakeRange(0, string.length)];
|
||||
|
||||
if (firstWordColor) {
|
||||
NSRange firstSpaceRange = [string rangeOfCharacterFromSet:[NSCharacterSet whitespaceCharacterSet]];
|
||||
NSRange firstWordRange = NSMakeRange(0, firstSpaceRange.location);
|
||||
[attributedString addAttribute:NSForegroundColorAttributeName value:firstWordColor range:firstWordRange];
|
||||
}
|
||||
|
||||
return attributedString;
|
||||
}
|
||||
|
||||
@end
|
||||
14
examples/LayoutSpecPlayground/Sample/ViewController.h
Normal file
14
examples/LayoutSpecPlayground/Sample/ViewController.h
Normal file
@@ -0,0 +1,14 @@
|
||||
//
|
||||
// ViewController.h
|
||||
// ASLayoutSpecPlayground
|
||||
//
|
||||
// Created by Hannah Troisi on 3/11/16.
|
||||
// Copyright © 2016 Hannah Troisi. All rights reserved.
|
||||
//
|
||||
|
||||
#import "AsyncDisplayKit.h"
|
||||
|
||||
@interface ViewController : ASViewController
|
||||
|
||||
@end
|
||||
|
||||
92
examples/LayoutSpecPlayground/Sample/ViewController.m
Normal file
92
examples/LayoutSpecPlayground/Sample/ViewController.m
Normal file
@@ -0,0 +1,92 @@
|
||||
//
|
||||
// ViewController.m
|
||||
// ASLayoutSpecPlayground
|
||||
//
|
||||
// Created by Hannah Troisi on 3/11/16.
|
||||
// Copyright © 2016 Hannah Troisi. All rights reserved.
|
||||
//
|
||||
|
||||
#import "ViewController.h"
|
||||
#import "PlaygroundContainerNode.h"
|
||||
#import "ASLayoutElementInspectorNode.h"
|
||||
|
||||
@interface ViewController () <ASPagerDelegate, ASPagerDataSource, ASLayoutElementInspectorNodeDelegate, PlaygroundContainerNodeDelegate>
|
||||
@end
|
||||
|
||||
@implementation ViewController
|
||||
{
|
||||
ASPagerNode *_pagerNode;
|
||||
ASSizeRange _sizeRange;
|
||||
}
|
||||
|
||||
#pragma mark - Lifecycle
|
||||
|
||||
- (instancetype)init
|
||||
{
|
||||
_pagerNode = [[ASPagerNode alloc] init];
|
||||
self = [super initWithNode:_pagerNode];
|
||||
|
||||
if (self) {
|
||||
_pagerNode.delegate = self;
|
||||
_pagerNode.dataSource = self;
|
||||
self.navigationItem.title = @"ASLayoutSpec Playground";
|
||||
self.edgesForExtendedLayout = UIRectEdgeNone;
|
||||
[ASLayoutElementInspectorNode sharedInstance].delegate = self;
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
#pragma mark - ASPagerNodeDataSource
|
||||
|
||||
- (NSInteger)numberOfPagesInPagerNode:(ASPagerNode *)pagerNode
|
||||
{
|
||||
return [PlaygroundContainerNode containerNodeCount];
|
||||
}
|
||||
|
||||
- (ASCellNodeBlock)pagerNode:(ASPagerNode *)pagerNode nodeBlockAtIndex:(NSInteger)index
|
||||
{
|
||||
return ^{
|
||||
PlaygroundContainerNode *containerCellNode = [[PlaygroundContainerNode alloc] initWithIndex:index];
|
||||
containerCellNode.delegate = self;
|
||||
return containerCellNode;
|
||||
};
|
||||
}
|
||||
|
||||
// [ASViewController] Override this method to provide a custom size range to the backing node.
|
||||
// Neccessary to allow the user to stretch / shrink the size of playground container.
|
||||
- (ASSizeRange)nodeConstrainedSize
|
||||
{
|
||||
if (CGSizeEqualToSize(_sizeRange.max, CGSizeZero)) {
|
||||
return [super nodeConstrainedSize];
|
||||
}
|
||||
return _sizeRange;
|
||||
}
|
||||
|
||||
- (ASSizeRange)pagerNode:(ASPagerNode *)pagerNode constrainedSizeForNodeAtIndexPath:(NSIndexPath *)indexPath
|
||||
{
|
||||
if (CGSizeEqualToSize(_sizeRange.max, CGSizeZero)) {
|
||||
return [super nodeConstrainedSize];
|
||||
}
|
||||
return _sizeRange;
|
||||
}
|
||||
|
||||
#pragma mark - PlaygroundContainerNodeDelegate
|
||||
|
||||
- (void)relayoutWithSize:(ASSizeRange)size
|
||||
{
|
||||
// NSLog(@"DELEGATE constrainedSize = %@", NSStringFromCGSize(size.max));
|
||||
_sizeRange = size;
|
||||
[self.view setNeedsLayout];
|
||||
[_pagerNode reloadData];
|
||||
}
|
||||
|
||||
#pragma mark - ASLayoutElementInspectorNodeDelegate
|
||||
|
||||
- (void)toggleVisualization:(BOOL)toggle
|
||||
{
|
||||
NSLog(@"shouldVisualizeLayoutSpecs:%d", toggle);
|
||||
[self.node setShouldVisualizeLayoutSpecs:toggle];
|
||||
}
|
||||
|
||||
@end
|
||||
20
examples/LayoutSpecPlayground/Sample/main.m
Normal file
20
examples/LayoutSpecPlayground/Sample/main.m
Normal file
@@ -0,0 +1,20 @@
|
||||
/* This file provided by Facebook is for non-commercial testing and evaluation
|
||||
* purposes only. Facebook reserves all rights not expressly granted.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* FACEBOOK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
#import "AppDelegate.h"
|
||||
|
||||
int main(int argc, char * argv[]) {
|
||||
@autoreleasepool {
|
||||
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
|
||||
}
|
||||
}
|
||||
BIN
examples/LayoutSpecPlayground/Sample/resizeHandle.png
Normal file
BIN
examples/LayoutSpecPlayground/Sample/resizeHandle.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 238 B |
Reference in New Issue
Block a user