Swiftgram/AsyncDisplayKit/Debug/ASLayoutElementInspectorCell.m
appleguy 55b5dff80c [ASLayoutSpec] Initial commit to support visualizing layout specs (with Playground app). (#2554)
* Initial ASLayoutSpecPlayground commit

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

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

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

* Workaround for ensuring creation of visualizerNode for ALL layoutspecs

* continued development

* Layout Inspector Work in Progress

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

* added new ASLayoutableInspectorNode features

* Cleaned up examples code.

* Cleaning up  code.

* more code cleanup

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

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

* Huy debugging

* Refactored layout inspector code for extensibility.

* Properly lock layoutableContextMap

* Fix context handling in ASDisplayNode:measureWithSizeRange

* Fix ASLayoutSpecPlayground:ViewController:toggleVisualization

* added slider to InspectorCell

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

* Fix to ASEnvironment

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

* Implement layout spec cache

* add pager ndoe

* add more examples

* add more layout examples

* [ASLayoutPlayground] Fix merge issues

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

* [ASLayoutPlayground] Some fixes (#2411)

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

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

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

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

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

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

* [Bulid] Fix a small merge error.

* [Build] Fix build issue for Framework target.

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

* Move aside ASLayoutSpecPlayground-Swift to match master

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

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

570 lines
21 KiB
Objective-C

//
// 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