add macOS descriptors for layout plugin

Summary: Add macOS only descriptors. Currently does not support Yoga/YogaKit or accessibility features; will add those in a later diff.

Reviewed By: priteshrnandgaonkar

Differential Revision: D27332601

fbshipit-source-id: 35c93cf715f004dbf8dbf8753534f1d4f9801b4c
This commit is contained in:
Kyle Cui
2021-03-29 16:11:32 -07:00
committed by Facebook GitHub Bot
parent 7c44d4d4f0
commit ed69c4f16a
14 changed files with 700 additions and 1 deletions

View File

@@ -71,7 +71,11 @@ NSObject* flattenLayoutEditorMessage(NSObject* field);
if (!_rootNode) { if (!_rootNode) {
// TODO: T61384369 get rid off this if condition. // TODO: T61384369 get rid off this if condition.
#if TARGET_OS_IPHONE
_rootNode = [UIApplication sharedApplication]; _rootNode = [UIApplication sharedApplication];
#elif TARGET_OS_OSX
_rootNode = [NSApplication sharedApplication];
#endif
} }
[SKInvalidation enableInvalidations]; [SKInvalidation enableInvalidations];
@@ -366,7 +370,11 @@ NSObject* flattenLayoutEditorMessage(NSObject* field) {
- (void)onCallSetSearchActive:(BOOL)active - (void)onCallSetSearchActive:(BOOL)active
withConnection:(id<FlipperConnection>)connection { withConnection:(id<FlipperConnection>)connection {
if (active) { if (active) {
#if TARGET_OS_IPHONE
[_tapListener mountWithFrame:[[UIScreen mainScreen] bounds]]; [_tapListener mountWithFrame:[[UIScreen mainScreen] bounds]];
#elif TARGET_OS_OSX
[_tapListener mountWithFrame:NSRectToCGRect([NSScreen mainScreen].frame)];
#endif
__block id<NSObject> rootNode = _rootNode; __block id<NSObject> rootNode = _rootNode;
[_tapListener listenForTapWithBlock:^(CGPoint touchPoint) { [_tapListener listenForTapWithBlock:^(CGPoint touchPoint) {

View File

@@ -9,12 +9,25 @@
#import "SKDescriptorMapper.h" #import "SKDescriptorMapper.h"
#if TARGET_OS_IPHONE
#import <FlipperKitLayoutIOSDescriptors/SKApplicationDescriptor.h> #import <FlipperKitLayoutIOSDescriptors/SKApplicationDescriptor.h>
#import <FlipperKitLayoutIOSDescriptors/SKButtonDescriptor.h> #import <FlipperKitLayoutIOSDescriptors/SKButtonDescriptor.h>
#import <FlipperKitLayoutIOSDescriptors/SKScrollViewDescriptor.h> #import <FlipperKitLayoutIOSDescriptors/SKScrollViewDescriptor.h>
#import <FlipperKitLayoutIOSDescriptors/SKViewControllerDescriptor.h> #import <FlipperKitLayoutIOSDescriptors/SKViewControllerDescriptor.h>
#import <FlipperKitLayoutIOSDescriptors/SKViewDescriptor.h> #import <FlipperKitLayoutIOSDescriptors/SKViewDescriptor.h>
#elif TARGET_OS_OSX
#import <FlipperKitLayoutMacOSDescriptors/SKNSApplicationDescriptor.h>
#import <FlipperKitLayoutMacOSDescriptors/SKNSButtonDescriptor.h>
#import <FlipperKitLayoutMacOSDescriptors/SKNSScrollViewDescriptor.h>
#import <FlipperKitLayoutMacOSDescriptors/SKNSViewControllerDescriptor.h>
#import <FlipperKitLayoutMacOSDescriptors/SKNSViewDescriptor.h>
#import <FlipperKitLayoutMacOSDescriptors/SKNSWindowDescriptor.h>
#endif
@implementation SKDescriptorMapper { @implementation SKDescriptorMapper {
NSMutableDictionary<NSString*, SKNodeDescriptor*>* _descriptors; NSMutableDictionary<NSString*, SKNodeDescriptor*>* _descriptors;
} }
@@ -23,6 +36,7 @@
if (self = [super init]) { if (self = [super init]) {
_descriptors = [NSMutableDictionary new]; _descriptors = [NSMutableDictionary new];
#if TARGET_OS_IPHONE
[self registerDescriptor:[[SKApplicationDescriptor alloc] [self registerDescriptor:[[SKApplicationDescriptor alloc]
initWithDescriptorMapper:self] initWithDescriptorMapper:self]
forClass:[UIApplication class]]; forClass:[UIApplication class]];
@@ -38,6 +52,27 @@
[self registerDescriptor:[[SKViewDescriptor alloc] [self registerDescriptor:[[SKViewDescriptor alloc]
initWithDescriptorMapper:self] initWithDescriptorMapper:self]
forClass:[UIView class]]; forClass:[UIView class]];
#elif TARGET_OS_OSX
[self registerDescriptor:[[SKNSApplicationDescriptor alloc]
initWithDescriptorMapper:self]
forClass:[NSApplication class]];
[self registerDescriptor:[[SKNSViewControllerDescriptor alloc]
initWithDescriptorMapper:self]
forClass:[NSViewController class]];
[self registerDescriptor:[[SKNSScrollViewDescriptor alloc]
initWithDescriptorMapper:self]
forClass:[NSScrollView class]];
[self registerDescriptor:[[SKNSButtonDescriptor alloc]
initWithDescriptorMapper:self]
forClass:[NSButton class]];
[self registerDescriptor:[[SKNSViewDescriptor alloc]
initWithDescriptorMapper:self]
forClass:[NSView class]];
[self registerDescriptor:[[SKNSWindowDescriptor alloc]
initWithDescriptorMapper:self]
forClass:[NSWindow class]];
#endif
} }
return self; return self;

View File

@@ -0,0 +1,17 @@
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#import <AppKit/AppKit.h>
#import <Foundation/Foundation.h>
#import <FlipperKitLayoutHelpers/SKNodeDescriptor.h>
@class SKDescriptorMapper;
@interface SKNSApplicationDescriptor : SKNodeDescriptor<NSApplication*>
@end

View File

@@ -0,0 +1,61 @@
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#if FB_SONARKIT_ENABLED
#import "SKNSApplicationDescriptor.h"
#import <FlipperKitLayoutHelpers/SKHiddenWindow.h>
#import <objc/runtime.h>
@implementation SKNSApplicationDescriptor
- (NSString*)identifierForNode:(NSApplication*)node {
return [NSString stringWithFormat:@"%p", node];
}
- (NSUInteger)childCountForNode:(NSApplication*)node {
return [[self visibleChildrenForNode:node] count];
}
- (id)childForNode:(NSApplication*)node atIndex:(NSUInteger)index {
return [self visibleChildrenForNode:node][index];
}
- (void)setHighlighted:(BOOL)highlighted forNode:(NSApplication*)node {
SKNodeDescriptor* windowDescriptor =
[self descriptorForClass:[NSWindow class]];
[windowDescriptor setHighlighted:highlighted forNode:[node keyWindow]];
}
- (void)hitTest:(SKTouch*)touch forNode:(NSApplication*)node {
bool finish = true;
for (NSInteger index = [self childCountForNode:node] - 1; index >= 0;
index--) {
NSWindow* child = [self childForNode:node atIndex:index];
if ([touch containedIn:child.frame]) {
[touch continueWithChildIndex:index withOffset:child.frame.origin];
finish = false;
}
}
if (finish) {
[touch finish];
}
}
- (NSArray<NSWindow*>*)visibleChildrenForNode:(NSApplication*)node {
NSMutableArray<NSWindow*>* children = [NSMutableArray new];
for (NSWindow* window in node.windows) {
[children addObject:window];
}
return children;
}
@end
#endif

View File

@@ -0,0 +1,18 @@
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#import <AppKit/AppKit.h>
#import <Foundation/Foundation.h>
#import <FlipperKitLayoutHelpers/SKNodeDescriptor.h>
@class NSButton;
@class SKDescriptorMapper;
@interface SKNSButtonDescriptor : SKNodeDescriptor<NSButton*>
@end

View File

@@ -0,0 +1,75 @@
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#if FB_SONARKIT_ENABLED
#import "SKNSButtonDescriptor.h"
#import <FlipperKitLayoutHelpers/NSColor+SKSonarValueCoder.h>
#import <FlipperKitLayoutHelpers/SKObject.h>
@implementation SKNSButtonDescriptor
- (NSString*)identifierForNode:(NSButton*)node {
return [NSString stringWithFormat:@"%p", node];
}
- (NSUInteger)childCountForNode:(NSButton*)node {
return 0;
}
- (id)childForNode:(NSButton*)node atIndex:(NSUInteger)index {
return nil;
}
- (NSArray<SKNamed<NSDictionary*>*>*)dataForNode:(NSButton*)node {
SKNodeDescriptor* viewDescriptor = [self descriptorForClass:[NSView class]];
auto* viewData = [viewDescriptor dataForNode:node];
NSMutableArray* data = [NSMutableArray new];
[data addObjectsFromArray:viewData];
[data addObject:[SKNamed
newWithName:@"NSButton"
withValue:@{
@"enabled" : SKMutableObject(@(node.enabled)),
@"highlighted" : SKMutableObject(@(node.highlighted)),
@"title" : SKMutableObject(node.title),
}]];
return data;
}
- (NSDictionary<NSString*, SKNodeUpdateData>*)dataMutationsForNode:
(NSButton*)node {
NSDictionary* buttonMutations = @{};
SKNodeDescriptor* viewDescriptor = [self descriptorForClass:[NSView class]];
NSDictionary* viewMutations = [viewDescriptor dataMutationsForNode:node];
NSMutableDictionary* mutations = [NSMutableDictionary new];
[mutations addEntriesFromDictionary:buttonMutations];
[mutations addEntriesFromDictionary:viewMutations];
return mutations;
}
- (NSArray<SKNamed<NSString*>*>*)attributesForNode:(NSScrollView*)node {
SKNodeDescriptor* descriptor = [self descriptorForClass:[NSView class]];
return [descriptor attributesForNode:node];
}
- (void)setHighlighted:(BOOL)highlighted forNode:(NSButton*)node {
SKNodeDescriptor* viewDescriptor = [self descriptorForClass:[NSView class]];
[viewDescriptor setHighlighted:highlighted forNode:node];
}
- (void)hitTest:(SKTouch*)touch forNode:(NSButton*)node {
[touch finish];
}
@end
#endif

View File

@@ -0,0 +1,16 @@
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#import <AppKit/AppKit.h>
#import <FlipperKitLayoutHelpers/SKNodeDescriptor.h>
@class SKDescriptorMapper;
@interface SKNSScrollViewDescriptor : SKNodeDescriptor<NSScrollView*>
@end

View File

@@ -0,0 +1,88 @@
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#if FB_SONARKIT_ENABLED
#import "SKNSScrollViewDescriptor.h"
@implementation SKNSScrollViewDescriptor
- (NSString*)identifierForNode:(NSScrollView*)node {
SKNodeDescriptor* descriptor = [self descriptorForClass:[NSView class]];
return [descriptor identifierForNode:node];
}
- (NSUInteger)childCountForNode:(NSScrollView*)node {
SKNodeDescriptor* descriptor = [self descriptorForClass:[NSView class]];
return [descriptor childCountForNode:node];
}
- (id)childForNode:(NSScrollView*)node atIndex:(NSUInteger)index {
SKNodeDescriptor* descriptor = [self descriptorForClass:[NSView class]];
return [descriptor childForNode:node atIndex:index];
}
- (id)dataForNode:(NSScrollView*)node {
SKNodeDescriptor* descriptor = [self descriptorForClass:[NSView class]];
return [descriptor dataForNode:node];
}
- (id)dataMutationsForNode:(NSScrollView*)node {
SKNodeDescriptor* descriptor = [self descriptorForClass:[NSView class]];
return [descriptor dataMutationsForNode:node];
}
- (NSArray<SKNamed<NSString*>*>*)attributesForNode:(NSScrollView*)node {
SKNodeDescriptor* descriptor = [self descriptorForClass:[NSView class]];
return [descriptor attributesForNode:node];
}
- (void)setHighlighted:(BOOL)highlighted forNode:(NSScrollView*)node {
SKNodeDescriptor* descriptor = [self descriptorForClass:[NSView class]];
[descriptor setHighlighted:highlighted forNode:node];
}
- (void)hitTest:(SKTouch*)touch forNode:(NSScrollView*)node {
bool finish = true;
for (NSInteger index = [self childCountForNode:node] - 1; index >= 0;
index--) {
id<NSObject> childNode = [self childForNode:node atIndex:index];
CGRect frame;
if ([childNode isKindOfClass:[NSViewController class]]) {
NSViewController* child = (NSViewController*)childNode;
if (child.view.isHidden) {
continue;
}
frame = child.view.frame;
} else {
NSView* child = (NSView*)childNode;
if (child.isHidden) {
continue;
}
frame = child.frame;
}
frame.origin.x -= node.documentVisibleRect.origin.x;
frame.origin.y -= node.documentVisibleRect.origin.y;
if ([touch containedIn:frame]) {
[touch continueWithChildIndex:index withOffset:frame.origin];
finish = false;
}
}
if (finish) {
[touch finish];
}
}
@end
#endif

View File

@@ -0,0 +1,20 @@
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#if FB_SONARKIT_ENABLED
#import <AppKit/AppKit.h>
#import <FlipperKitLayoutHelpers/SKNodeDescriptor.h>
@class SKDescriptorMapper;
@interface SKNSViewControllerDescriptor : SKNodeDescriptor<NSViewController*>
@end
#endif

View File

@@ -0,0 +1,45 @@
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#if FB_SONARKIT_ENABLED
#import "SKNSViewControllerDescriptor.h"
@implementation SKNSViewControllerDescriptor
- (NSString*)identifierForNode:(NSViewController*)node {
return [NSString stringWithFormat:@"%p", node];
}
- (NSUInteger)childCountForNode:(NSViewController*)node {
return 1;
}
- (id)childForNode:(NSViewController*)node atIndex:(NSUInteger)index {
return node.view;
}
- (void)setHighlightedForNode:(NSViewController*)node {
}
- (NSArray<SKNamed<NSString*>*>*)attributesForNode:(NSViewController*)node {
return @[ [SKNamed newWithName:@"addr"
withValue:[NSString stringWithFormat:@"%p", node]] ];
}
- (void)setHighlighted:(BOOL)highlighted forNode:(NSViewController*)node {
SKNodeDescriptor* descriptor = [self descriptorForClass:[NSView class]];
[descriptor setHighlighted:highlighted forNode:node.view];
}
- (void)hitTest:(SKTouch*)touch forNode:(NSViewController*)node {
[touch continueWithChildIndex:0 withOffset:(CGPoint){0, 0}];
}
@end
#endif

View File

@@ -0,0 +1,20 @@
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#if FB_SONARKIT_ENABLED
#import <AppKit/AppKit.h>
#import <FlipperKitLayoutHelpers/SKNodeDescriptor.h>
@class SKDescriptorMapper;
@interface SKNSViewDescriptor : SKNodeDescriptor<NSView*>
@end
#endif

View File

@@ -0,0 +1,221 @@
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#if FB_SONARKIT_ENABLED
#import "SKNSViewDescriptor.h"
#import <FlipperKitHighlightOverlay/SKHighlightOverlay.h>
#import <FlipperKitLayoutHelpers/FlipperKitLayoutDescriptorMapperProtocol.h>
#import <FlipperKitLayoutHelpers/NSColor+SKSonarValueCoder.h>
#import <FlipperKitLayoutHelpers/SKHiddenWindow.h>
#import <FlipperKitLayoutHelpers/SKNamed.h>
#import <FlipperKitLayoutHelpers/SKObject.h>
@implementation SKNSViewDescriptor
- (instancetype)initWithDescriptorMapper:
(id<SKDescriptorMapperProtocol>)mapper {
if (self = [super initWithDescriptorMapper:mapper]) {
initEnumDictionaries();
}
return self;
}
- (NSString*)identifierForNode:(NSView*)node {
return [NSString stringWithFormat:@"%p", node];
}
- (NSUInteger)childCountForNode:(NSView*)node {
return [[self validChildrenForNode:node] count];
}
- (id)childForNode:(NSView*)node atIndex:(NSUInteger)index {
return [[self validChildrenForNode:node] objectAtIndex:index];
}
- (NSArray*)validChildrenForNode:(NSView*)node {
NSMutableArray* validChildren = [NSMutableArray new];
// Use NSViewControllers for children which responds to a different
// viewController than their parent
for (NSView* child in node.subviews) {
BOOL responderIsNSViewController =
[child.nextResponder isKindOfClass:[NSViewController class]];
if (!child.isHidden) {
if (responderIsNSViewController &&
child.nextResponder != node.nextResponder) {
[validChildren addObject:child.nextResponder];
} else {
[validChildren addObject:child];
}
}
}
return validChildren;
}
- (NSArray<SKNamed<NSDictionary*>*>*)dataForNode:(NSView*)node {
return [NSArray
arrayWithObjects:
[SKNamed newWithName:@"NSView"
withValue:@{
@"frame" : SKMutableObject(node.frame),
@"bounds" : SKObject(node.bounds),
@"alphaValue" : SKMutableObject(@(node.alphaValue)),
@"tag" : @(node.tag),
}],
[SKNamed
newWithName:@"CALayer"
withValue:@{
@"shadowColor" : SKMutableObject(
node.layer.shadowColor
? [NSColor colorWithCGColor:node.layer.shadowColor]
: nil),
@"shadowOpacity" :
SKMutableObject(@(node.layer.shadowOpacity)),
@"shadowRadius" : SKMutableObject(@(node.layer.shadowRadius)),
@"shadowOffset" : SKMutableObject(node.layer.shadowOffset),
@"backgroundColor" : SKMutableObject(
node.layer.backgroundColor
? [NSColor
colorWithCGColor:node.layer.backgroundColor]
: nil),
@"borderColor" : SKMutableObject(
node.layer.borderColor
? [NSColor colorWithCGColor:node.layer.borderColor]
: nil),
@"borderWidth" : SKMutableObject(@(node.layer.borderWidth)),
@"cornerRadius" : SKMutableObject(@(node.layer.cornerRadius)),
@"masksToBounds" :
SKMutableObject(@(node.layer.masksToBounds)),
}],
nil];
}
- (NSDictionary<NSString*, SKNodeUpdateData>*)dataMutationsForNode:
(NSView*)node {
NSDictionary<NSString*, SKNodeUpdateData>* dataMutations = @{
// NSView
@"NSView.alphaValue" : ^(NSNumber* value){
node.alphaValue = [value floatValue];
}
,
@"NSView.frame.origin.y": ^(NSNumber *value) {
CGRect frame = node.frame;
frame.origin.y = [value floatValue];
node.frame = frame;
},
@"NSView.frame.origin.x": ^(NSNumber *value) {
CGRect frame = node.frame;
frame.origin.x = [value floatValue];
node.frame = frame;
},
@"NSView.frame.size.width": ^(NSNumber *value) {
CGRect frame = node.frame;
frame.size.width = [value floatValue];
node.frame = frame;
},
@"NSView.frame.size.height": ^(NSNumber *value) {
CGRect frame = node.frame;
frame.size.width = [value floatValue];
node.frame = frame;
},
// CALayer
@"CALayer.shadowColor": ^(NSNumber *value) {
node.layer.shadowColor = [NSColor fromSonarValue:value].CGColor;
},
@"CALayer.shadowOpacity": ^(NSNumber *value) {
node.layer.shadowOpacity = [value floatValue];
},
@"CALayer.shadowRadius": ^(NSNumber *value) {
node.layer.shadowRadius = [value floatValue];
},
@"CALayer.shadowOffset.width": ^(NSNumber *value) {
CGSize offset = node.layer.shadowOffset;
offset.width = [value floatValue];
node.layer.shadowOffset = offset;
},
@"CALayer.shadowOffset.height": ^(NSNumber *value) {
CGSize offset = node.layer.shadowOffset;
offset.height = [value floatValue];
node.layer.shadowOffset = offset;
},
@"CALayer.backgroundColor": ^(NSNumber *value) {
node.layer.backgroundColor = [NSColor fromSonarValue:value].CGColor;
},
@"CALayer.borderColor": ^(NSNumber *value) {
node.layer.borderColor = [NSColor fromSonarValue:value].CGColor;
},
@"CALayer.borderWidth": ^(NSNumber *value) {
node.layer.borderWidth = [value floatValue];
},
@"CALayer.cornerRadius": ^(NSNumber *value) {
node.layer.cornerRadius = [value floatValue];
},
@"CALayer.masksToBounds": ^(NSNumber *value) {
node.layer.masksToBounds = [value boolValue];
},
}
;
return dataMutations;
}
- (NSArray<SKNamed<NSString*>*>*)attributesForNode:(NSView*)node {
return @[ [SKNamed newWithName:@"addr"
withValue:[NSString stringWithFormat:@"%p", node]] ];
}
- (void)setHighlighted:(BOOL)highlighted forNode:(NSView*)node {
SKHighlightOverlay* overlay = [SKHighlightOverlay sharedInstance];
if (highlighted == YES) {
[overlay mountInView:node withFrame:node.bounds];
} else {
[overlay unmount];
}
}
- (void)hitTest:(SKTouch*)touch forNode:(NSView*)node {
bool finish = true;
for (NSInteger index = [self childCountForNode:node] - 1; index >= 0;
index--) {
id<NSObject> childNode = [self childForNode:node atIndex:index];
NSView* viewForNode = nil;
if ([childNode isKindOfClass:[NSViewController class]]) {
NSViewController* child = (NSViewController*)childNode;
viewForNode = child.view;
} else {
viewForNode = (NSView*)childNode;
}
if (viewForNode.isHidden || viewForNode.alphaValue <= 0 ||
[[viewForNode class] isEqual:[SKHiddenWindow class]]) {
/*SKHiddenWindow is the pink overlay which is added in window to capture
the gestures.*/
continue;
}
if ([touch containedIn:viewForNode.frame]) {
[touch continueWithChildIndex:index withOffset:viewForNode.frame.origin];
finish = false;
}
}
if (finish) {
[touch finish];
}
}
static void initEnumDictionaries() {}
@end
#endif

View File

@@ -0,0 +1,17 @@
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#import <AppKit/AppKit.h>
#import <Foundation/Foundation.h>
#import <FlipperKitLayoutHelpers/SKNodeDescriptor.h>
@class SKDescriptorMapper;
@interface SKNSWindowDescriptor : SKNodeDescriptor<NSWindow*>
@end

View File

@@ -0,0 +1,58 @@
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#if FB_SONARKIT_ENABLED
#import "SKNSWindowDescriptor.h"
#import <FlipperKitLayoutHelpers/SKHiddenWindow.h>
#import <objc/runtime.h>
@implementation SKNSWindowDescriptor
- (NSString*)identifierForNode:(NSWindow*)node {
return [NSString stringWithFormat:@"%p", node];
}
- (NSUInteger)childCountForNode:(NSWindow*)node {
return [[self visibleChildrenForNode:node] count];
}
- (id)childForNode:(NSWindow*)node atIndex:(NSUInteger)index {
return [self visibleChildrenForNode:node][index];
}
- (void)setHighlighted:(BOOL)highlighted forNode:(NSWindow*)node {
SKNodeDescriptor* viewDescriptor = [self descriptorForClass:[NSView class]];
[viewDescriptor setHighlighted:highlighted forNode:node.contentView];
}
- (void)hitTest:(SKTouch*)touch forNode:(NSWindow*)node {
bool finish = true;
for (NSInteger index = [self childCountForNode:node] - 1; index >= 0;
index--) {
NSView* child = [self childForNode:node atIndex:index];
if ([touch containedIn:child.frame]) {
[touch continueWithChildIndex:index withOffset:child.frame.origin];
finish = false;
}
}
if (finish) {
[touch finish];
}
}
- (NSArray<NSView*>*)visibleChildrenForNode:(NSWindow*)node {
NSMutableArray<NSView*>* children = [NSMutableArray new];
[children addObject:node.contentView];
return children;
}
@end
#endif