diff --git a/Android/doric/src/main/java/pub/doric/shader/SuperNode.java b/Android/doric/src/main/java/pub/doric/shader/SuperNode.java index 06c434cc..4aece2a7 100644 --- a/Android/doric/src/main/java/pub/doric/shader/SuperNode.java +++ b/Android/doric/src/main/java/pub/doric/shader/SuperNode.java @@ -85,10 +85,9 @@ public abstract class SuperNode extends ViewNode { protected abstract void blendSubNode(JSObject subProperties); protected void blendSubLayoutConfig(ViewNode viewNode, JSObject jsObject) { - JSValue jsValue = jsObject.getProperty("margin"); + JSValue margin = jsObject.getProperty("margin"); JSValue widthSpec = jsObject.getProperty("widthSpec"); JSValue heightSpec = jsObject.getProperty("heightSpec"); - ViewGroup.LayoutParams layoutParams = viewNode.getLayoutParams(); if (widthSpec.isNumber()) { switch (widthSpec.asNumber().toInt()) { @@ -114,20 +113,20 @@ public abstract class SuperNode extends ViewNode { break; } } - if (jsValue.isObject() && layoutParams instanceof ViewGroup.MarginLayoutParams) { - JSValue topVal = jsValue.asObject().getProperty("top"); + if (margin.isObject() && layoutParams instanceof ViewGroup.MarginLayoutParams) { + JSValue topVal = margin.asObject().getProperty("top"); if (topVal.isNumber()) { ((ViewGroup.MarginLayoutParams) layoutParams).topMargin = DoricUtils.dp2px(topVal.asNumber().toFloat()); } - JSValue leftVal = jsValue.asObject().getProperty("left"); + JSValue leftVal = margin.asObject().getProperty("left"); if (leftVal.isNumber()) { ((ViewGroup.MarginLayoutParams) layoutParams).leftMargin = DoricUtils.dp2px(leftVal.asNumber().toFloat()); } - JSValue rightVal = jsValue.asObject().getProperty("right"); + JSValue rightVal = margin.asObject().getProperty("right"); if (rightVal.isNumber()) { ((ViewGroup.MarginLayoutParams) layoutParams).rightMargin = DoricUtils.dp2px(rightVal.asNumber().toFloat()); } - JSValue bottomVal = jsValue.asObject().getProperty("bottom"); + JSValue bottomVal = margin.asObject().getProperty("bottom"); if (bottomVal.isNumber()) { ((ViewGroup.MarginLayoutParams) layoutParams).bottomMargin = DoricUtils.dp2px(bottomVal.asNumber().toFloat()); } diff --git a/iOS/Example/Example/ViewController.m b/iOS/Example/Example/ViewController.m index e638a42a..bb96000b 100644 --- a/iOS/Example/Example/ViewController.m +++ b/iOS/Example/Example/ViewController.m @@ -30,7 +30,7 @@ - (void)viewDidLoad { NSString *jsContent = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil]; self.doricContext = [[DoricContext alloc] initWithScript:jsContent source:@"test.js"]; [self.doricContext.rootNode setupRootView:[[DoricStackView new] also:^(DoricStackView *it) { - it.layoutConfig = [[DoricStackConfig alloc] initWithWidth:DoricLayoutAtMost height:DoricLayoutAtMost]; + it.layoutConfig = [[DoricLayoutConfig alloc] initWithWidth:DoricLayoutAtMost height:DoricLayoutAtMost]; [self.view addSubview:it]; }]]; [self.doricContext initContextWithWidth:self.view.width height:self.view.height]; diff --git a/iOS/Pod/Classes/Shader/DoricGroupNode.h b/iOS/Pod/Classes/Shader/DoricGroupNode.h index f96bbdc2..202eb7c2 100644 --- a/iOS/Pod/Classes/Shader/DoricGroupNode.h +++ b/iOS/Pod/Classes/Shader/DoricGroupNode.h @@ -24,7 +24,7 @@ NS_ASSUME_NONNULL_BEGIN -@interface DoricGroupNode : DoricSuperNode +@interface DoricGroupNode : DoricSuperNode @end NS_ASSUME_NONNULL_END diff --git a/iOS/Pod/Classes/Shader/DoricHLayoutNode.h b/iOS/Pod/Classes/Shader/DoricHLayoutNode.h index 4f6d6086..edcbda0a 100644 --- a/iOS/Pod/Classes/Shader/DoricHLayoutNode.h +++ b/iOS/Pod/Classes/Shader/DoricHLayoutNode.h @@ -22,5 +22,5 @@ #import "DoricGroupNode.h" -@interface DoricHLayoutNode : DoricGroupNode +@interface DoricHLayoutNode : DoricGroupNode @end diff --git a/iOS/Pod/Classes/Shader/DoricHLayoutNode.m b/iOS/Pod/Classes/Shader/DoricHLayoutNode.m index 93d68ca0..ee66564a 100644 --- a/iOS/Pod/Classes/Shader/DoricHLayoutNode.m +++ b/iOS/Pod/Classes/Shader/DoricHLayoutNode.m @@ -37,29 +37,4 @@ - (void)blendView:(DoricHLayoutView *)view forPropName:(NSString *)name propValu [super blendView:view forPropName:name propValue:prop]; } } - -- (void)blendSubNode:(DoricViewNode *)subNode layoutConfig:(NSDictionary *)layoutConfig { - [super blendSubNode:subNode layoutConfig:layoutConfig]; - if (![subNode.layoutConfig isKindOfClass:DoricLinearConfig.class]) { - DoricLog(@"blend DoricHLayoutView child error,layout params not match"); - return; - } - DoricLinearConfig *params = (DoricLinearConfig *) subNode.layoutConfig; - NSDictionary *margin = layoutConfig[@"margin"]; - if (margin) { - params.margin = DoricMarginMake( - [(NSNumber *) margin[@"left"] floatValue], - [(NSNumber *) margin[@"top"] floatValue], - [(NSNumber *) margin[@"right"] floatValue], - [(NSNumber *) margin[@"bottom"] floatValue]); - } - NSNumber *alignment = layoutConfig[@"alignment"]; - if (alignment) { - params.alignment = (DoricGravity) [alignment integerValue]; - } -} - -- (DoricLinearConfig *)generateDefaultLayoutParams { - return [[DoricLinearConfig alloc] init]; -} @end diff --git a/iOS/Pod/Classes/Shader/DoricLayouts.h b/iOS/Pod/Classes/Shader/DoricLayouts.h index 0ebdbc93..dbae4c21 100644 --- a/iOS/Pod/Classes/Shader/DoricLayouts.h +++ b/iOS/Pod/Classes/Shader/DoricLayouts.h @@ -54,43 +54,27 @@ typedef NS_ENUM(NSInteger, DoricGravity) { @interface DoricLayoutConfig : NSObject @property(nonatomic, assign) DoricLayoutSpec widthSpec; @property(nonatomic, assign) DoricLayoutSpec heightSpec; +@property(nonatomic) DoricMargin margin; @property(nonatomic, assign) DoricGravity alignment; +@property(nonatomic, assign) NSUInteger weight; - (instancetype)init; - (instancetype)initWithWidth:(DoricLayoutSpec)width height:(DoricLayoutSpec)height; -@end - -@interface DoricStackConfig : DoricLayoutConfig -@end - -@interface DoricMarginConfig : DoricLayoutConfig -@property(nonatomic) DoricMargin margin; - - (instancetype)initWithWidth:(DoricLayoutSpec)width height:(DoricLayoutSpec)height margin:(DoricMargin)margin; -@end -@interface DoricLinearConfig : DoricMarginConfig -@property(nonatomic, assign) NSUInteger weight; @end -@interface DoricLayoutContainer : UIView - -- (T)configForChild:(__kindof UIView *)child; - -- (void)layout; - -- (void)requestLayout; -@end - -@interface DoricStackView : DoricLayoutContainer +@interface DoricLayoutContainer : UIView @property(nonatomic, assign) DoricGravity gravity; @end -@interface DoricLinearView : DoricLayoutContainer -@property(nonatomic, assign) DoricGravity gravity; +@interface DoricStackView : DoricLayoutContainer +@end + +@interface DoricLinearView : DoricLayoutContainer @property(nonatomic, assign) CGFloat space; @end diff --git a/iOS/Pod/Classes/Shader/DoricLayouts.m b/iOS/Pod/Classes/Shader/DoricLayouts.m index 088d3339..b073cac7 100644 --- a/iOS/Pod/Classes/Shader/DoricLayouts.m +++ b/iOS/Pod/Classes/Shader/DoricLayouts.m @@ -46,107 +46,74 @@ - (instancetype)initWithWidth:(DoricLayoutSpec)width height:(DoricLayoutSpec)hei } return self; } -@end - -@implementation DoricMarginConfig -- (instancetype)init { - if (self = [super init]) { - _margin = DoricMarginMake(0, 0, 0, 0); - } - return self; -} - (instancetype)initWithWidth:(DoricLayoutSpec)width height:(DoricLayoutSpec)height margin:(DoricMargin)margin { - if (self = [super initWithWidth:width height:height]) { + if (self = [super init]) { + _widthSpec = width; + _heightSpec = height; _margin = margin; } return self; } @end -@implementation DoricStackConfig -@end - -@implementation DoricLinearConfig -@end - @interface DoricLayoutContainer () -@property(nonatomic, assign) BOOL waitingLayout; +@property(nonatomic, assign) CGFloat contentWidth; +@property(nonatomic, assign) CGFloat contentHeight; +@property(nonatomic, assign) NSUInteger contentWeight; + +- (void)layout:(CGSize)targetSize; + +- (CGSize)sizeContent:(CGSize)size; @end @implementation DoricLayoutContainer -- (instancetype)init { - if (self = [super init]) { - _waitingLayout = NO; - } - return self; -} -- (instancetype)initWithFrame:(CGRect)frame { - if (self = [super initWithFrame:frame]) { - _waitingLayout = NO; - } - return self; -} - -- (instancetype)initWithCoder:(NSCoder *)coder { - if (self = [super initWithCoder:coder]) { - _waitingLayout = NO; - } - return self; -} - - -- (DoricLayoutConfig *)configForChild:(UIView *)child { - DoricLayoutConfig *config = child.layoutConfig; - if (!config) { - config = [[DoricLayoutConfig alloc] init]; - } - return config; -} - -- (void)requestLayout { - if ([self.superview isKindOfClass:[DoricLinearView class]]) { - [(DoricLinearView *) self.superview requestLayout]; - return; - } - if (self.waitingLayout) { - return; - } - self.waitingLayout = YES; - __weak typeof(self) _self = self; - dispatch_async(dispatch_get_main_queue(), ^{ - __strong typeof(_self) self = _self; - [self sizeToFit]; - [self layout]; - self.waitingLayout = NO; - }); -} - -- (void)setNeedsLayout { - [super setNeedsLayout]; - if (self.waitingLayout) { - return; - } - [self requestLayout]; -} - -- (BOOL)waitingLayout { +- (void)layoutSubviews { if ([self.superview isKindOfClass:[DoricLayoutContainer class]]) { - return [(DoricLayoutContainer *) self.superview waitingLayout]; + [self.superview layoutSubviews]; + } else { + CGSize size = [self sizeThatFits:CGSizeMake(self.superview.width, self.superview.height)]; + [self layout:size]; } - return _waitingLayout; } -- (void)layout { - [self.subviews enumerateObjectsUsingBlock:^(__kindof UIView *child, NSUInteger idx, BOOL *stop) { - if ([child isKindOfClass:[DoricLayoutContainer class]]) { - [(DoricLayoutContainer *) child layout]; - } - }]; +- (CGSize)sizeThatFits:(CGSize)size { + CGFloat width = self.width; + CGFloat height = self.height; + + DoricLayoutConfig *config = self.layoutConfig; + if (!config) { + config = [DoricLayoutConfig new]; + } + if (config.widthSpec == DoricLayoutAtMost + || config.widthSpec == DoricLayoutWrapContent) { + width = size.width - config.margin.left - config.margin.right; + } + if (config.heightSpec == DoricLayoutAtMost + || config.heightSpec == DoricLayoutWrapContent) { + height = size.height - config.margin.top - config.margin.bottom; + } + + CGSize contentSize = [self sizeContent:CGSizeMake(width, height)]; + if (config.widthSpec == DoricLayoutWrapContent) { + width = contentSize.width; + } + if (config.heightSpec == DoricLayoutWrapContent) { + height = contentSize.height; + } + return CGSizeMake(width, height); } +- (CGSize)sizeContent:(CGSize)size { + return size; +} + +- (void)layout:(CGSize)targetSize { + self.width = targetSize.width; + self.height = targetSize.height; +} @end @@ -157,175 +124,223 @@ @interface DoricStackView () @end @implementation DoricStackView -- (DoricStackConfig *)configForChild:(UIView *)child { - DoricStackConfig *config = (DoricStackConfig *) child.layoutConfig; - if (!config) { - config = [[DoricStackConfig alloc] init]; - } - return config; -} - -- (void)sizeToFit { - DoricLayoutConfig *config = self.layoutConfig; - self.contentWidth = 0; - self.contentHeight = 0; +- (CGSize)sizeContent:(CGSize)size { + CGFloat contentWidth = 0; + CGFloat contentHeight = 0; for (UIView *child in self.subviews) { if (child.isHidden) { continue; } - DoricStackConfig *childConfig = [self configForChild:child]; + DoricLayoutConfig *childConfig = child.layoutConfig; + if (!childConfig) { + childConfig = [DoricLayoutConfig new]; + } + CGSize childSize = CGSizeMake(child.width, child.height); if ([child isKindOfClass:[DoricLayoutContainer class]] || childConfig.widthSpec == DoricLayoutWrapContent || childConfig.heightSpec == DoricLayoutWrapContent) { - [child sizeToFit]; + childSize = [child sizeThatFits:CGSizeMake(size.width, size.height - contentHeight)]; } - self.contentWidth = MAX(self.contentWidth, child.width); - self.contentHeight = MAX(self.contentHeight, child.height); - } - if (config.widthSpec == DoricLayoutWrapContent) { - self.width = self.contentWidth; - } else if (config.widthSpec == DoricLayoutAtMost) { - self.width = self.superview.width; - } - if (config.heightSpec == DoricLayoutWrapContent) { - self.height = self.contentHeight; - } else if (config.heightSpec == DoricLayoutAtMost) { - self.height = self.superview.height; + if (childConfig.widthSpec == DoricLayoutExact) { + childSize.width = child.width; + } else if (childConfig.widthSpec == DoricLayoutAtMost) { + childSize.width = size.width; + } + if (childConfig.heightSpec == DoricLayoutExact) { + childSize.height = child.height; + } else if (childConfig.heightSpec == DoricLayoutAtMost) { + childSize.height = size.height - contentHeight; + } + if (childConfig.weight) { + childSize.height = child.height; + } + contentWidth = MAX(contentWidth, childSize.width + childConfig.margin.left + childConfig.margin.right); + contentHeight = MAX(contentHeight, childSize.height + childConfig.margin.top + childConfig.margin.bottom); } + self.contentWidth = contentWidth; + self.contentHeight = contentHeight; + return CGSizeMake(contentWidth, contentHeight); } -- (void)layout { +- (void)layout:(CGSize)targetSize { for (UIView *child in self.subviews) { if (child.isHidden) { continue; } - DoricStackConfig *childConfig = [self configForChild:child]; + DoricLayoutConfig *childConfig = child.layoutConfig; + if (!childConfig) { + childConfig = [DoricLayoutConfig new]; + } + + CGSize size = [child sizeThatFits:CGSizeMake(targetSize.width, targetSize.height)]; + if (childConfig.widthSpec == DoricLayoutExact) { + size.width = child.width; + } + if (childConfig.heightSpec == DoricLayoutExact) { + size.height = child.height; + } + if (childConfig.widthSpec == DoricLayoutExact) { + size.width = child.width; + } else if (childConfig.widthSpec == DoricLayoutAtMost) { + size.width = targetSize.width; + } + if (childConfig.heightSpec == DoricLayoutExact) { + size.height = child.height; + } else if (childConfig.heightSpec == DoricLayoutAtMost) { + size.height = targetSize.height; + } + child.width = size.width; + child.height = size.height; + DoricGravity gravity = childConfig.alignment | self.gravity; + if ((gravity & LEFT) == LEFT) { child.left = 0; } else if ((gravity & RIGHT) == RIGHT) { - child.right = self.width; + child.right = targetSize.width; } else if ((gravity & CENTER_X) == CENTER_X) { - child.centerX = self.width / 2; - } - if ((gravity & TOP) == TOP) { - child.top = 0; - } else if ((gravity & BOTTOM) == BOTTOM) { - child.bottom = self.height; - } else if ((gravity & CENTER_Y) == CENTER_Y) { - child.centerY = self.height / 2; - } - if (childConfig.widthSpec == DoricLayoutAtMost) { - child.width = self.width; - } - if (childConfig.heightSpec == DoricLayoutAtMost) { - child.height = self.height; - } - - if ([child isKindOfClass:[DoricLayoutContainer class]]) { - [(DoricLayoutContainer *) child layout]; - } - } -} -@end - -@interface DoricLinearView () -@property(nonatomic, assign) CGFloat contentWidth; -@property(nonatomic, assign) CGFloat contentHeight; -@property(nonatomic, assign) NSUInteger contentWeight; -@end - -@implementation DoricLinearView -- (DoricLinearConfig *)configForChild:(UIView *)child { - DoricLinearConfig *config = (DoricLinearConfig *) child.layoutConfig; - if (!config) { - config = [[DoricLinearConfig alloc] init]; - } - return config; -} -@end - -@implementation DoricVLayoutView - -- (void)sizeToFit { - DoricLayoutConfig *config = self.layoutConfig; - self.contentWidth = 0; - self.contentHeight = 0; - self.contentWeight = 0; - for (UIView *child in self.subviews) { - if (child.isHidden) { - continue; - } - DoricLinearConfig *childConfig = [self configForChild:child]; - if ([child isKindOfClass:[DoricLayoutContainer class]] - || childConfig.widthSpec == DoricLayoutWrapContent - || childConfig.heightSpec == DoricLayoutWrapContent) { - [child sizeToFit]; - } - self.contentWidth = MAX(self.contentWidth, child.width + childConfig.margin.left + childConfig.margin.right); - self.contentHeight += child.height + self.space + childConfig.margin.top + childConfig.margin.bottom; - self.contentWeight += childConfig.weight; - } - self.contentHeight -= self.space; - if (config.widthSpec == DoricLayoutWrapContent) { - self.width = self.contentWidth; - } else if (config.widthSpec == DoricLayoutAtMost) { - self.width = self.superview.width; - } - if (config.heightSpec == DoricLayoutWrapContent) { - self.height = self.contentHeight; - } else if (config.heightSpec == DoricLayoutAtMost) { - self.height = self.superview.height; - } - if (self.contentWeight) { - CGFloat remain = self.height - self.contentHeight; - for (UIView *child in self.subviews) { - if (child.isHidden) { - continue; - } - DoricLinearConfig *childConfig = [self configForChild:child]; - if (childConfig.weight) { - child.height += remain / self.contentWeight * childConfig.weight; - } - } - self.contentHeight = self.height; - } -} - -- (void)layout { - CGFloat yStart = 0; - if ((self.gravity & TOP) == TOP) { - yStart = 0; - } else if ((self.gravity & BOTTOM) == BOTTOM) { - yStart = self.height - self.contentHeight; - } else if ((self.gravity & CENTER_Y) == CENTER_Y) { - yStart = (self.height - self.contentHeight) / 2; - } - for (UIView *child in self.subviews) { - if (child.isHidden) { - continue; - } - DoricLinearConfig *childConfig = [self configForChild:child]; - DoricGravity gravity = childConfig.alignment | self.gravity; - if ((gravity & LEFT) == LEFT) { - child.left = 0; - } else if ((gravity & RIGHT) == RIGHT) { - child.right = self.width; - } else if ((gravity & CENTER_X) == CENTER_X) { - child.centerX = self.width / 2; + child.centerX = targetSize.width / 2; } else { if (childConfig.margin.left) { child.left = childConfig.margin.left; } else if (childConfig.margin.right) { - child.right = self.width - childConfig.margin.right; + child.right = targetSize.width - childConfig.margin.right; } } - if (childConfig.widthSpec == DoricLayoutAtMost) { - child.width = self.width; + + if ((gravity & TOP) == TOP) { + child.top = 0; + } else if ((gravity & BOTTOM) == BOTTOM) { + child.bottom = targetSize.height; + } else if ((gravity & CENTER_Y) == CENTER_Y) { + child.centerY = targetSize.height / 2; + } else { + if (childConfig.margin.top) { + child.top = childConfig.margin.top; + } else if (childConfig.margin.bottom) { + child.bottom = targetSize.height - childConfig.margin.bottom; + } } - if (childConfig.heightSpec == DoricLayoutAtMost) { - child.height = self.height - yStart - childConfig.margin.top - childConfig.margin.bottom - self.space; + + if ([child isKindOfClass:[DoricLayoutContainer class]]) { + [(DoricLayoutContainer *) child layout:size]; + } + } + self.width = targetSize.width; + self.height = targetSize.height; +} +@end + +@implementation DoricLinearView +@end + +@implementation DoricVLayoutView +- (CGSize)sizeContent:(CGSize)size { + CGFloat contentWidth = 0; + CGFloat contentHeight = 0; + NSUInteger contentWeight = 0; + for (UIView *child in self.subviews) { + if (child.isHidden) { + continue; + } + DoricLayoutConfig *childConfig = child.layoutConfig; + if (!childConfig) { + childConfig = [DoricLayoutConfig new]; + } + CGSize childSize = CGSizeMake(child.width, child.height); + if ([child isKindOfClass:[DoricLayoutContainer class]] + || childConfig.widthSpec == DoricLayoutWrapContent + || childConfig.heightSpec == DoricLayoutWrapContent) { + childSize = [child sizeThatFits:CGSizeMake(size.width, size.height - contentHeight)]; + } + if (childConfig.widthSpec == DoricLayoutExact) { + childSize.width = child.width; + } else if (childConfig.widthSpec == DoricLayoutAtMost) { + childSize.width = size.width; + } + if (childConfig.heightSpec == DoricLayoutExact) { + childSize.height = child.height; + } else if (childConfig.heightSpec == DoricLayoutAtMost) { + childSize.height = size.height - contentHeight; + } + if (childConfig.weight) { + childSize.height = child.height; + } + contentWidth = MAX(contentWidth, childSize.width + childConfig.margin.left + childConfig.margin.right); + contentHeight += childSize.height + self.space + childConfig.margin.top + childConfig.margin.bottom; + contentWeight += childConfig.weight; + } + contentHeight -= self.space; + self.contentWidth = contentWidth; + self.contentHeight = contentHeight; + self.contentWeight = contentWeight; + if (contentWeight) { + contentHeight = size.height; + } + return CGSizeMake(contentWidth, contentHeight); +} + +- (void)layout:(CGSize)targetSize { + CGFloat yStart = 0; + if ((self.gravity & TOP) == TOP) { + yStart = 0; + } else if ((self.gravity & BOTTOM) == BOTTOM) { + yStart = targetSize.height - self.contentHeight; + } else if ((self.gravity & CENTER_Y) == CENTER_Y) { + yStart = (targetSize.height - self.contentHeight) / 2; + } + CGFloat remain = targetSize.height - self.contentHeight; + for (UIView *child in self.subviews) { + if (child.isHidden) { + continue; + } + DoricLayoutConfig *childConfig = child.layoutConfig; + if (!childConfig) { + childConfig = [DoricLayoutConfig new]; + } + + CGSize size = [child sizeThatFits:CGSizeMake(targetSize.width, targetSize.height - yStart)]; + if (childConfig.widthSpec == DoricLayoutExact) { + size.width = child.width; + } + if (childConfig.heightSpec == DoricLayoutExact) { + size.height = child.height; + } + if (childConfig.widthSpec == DoricLayoutExact) { + size.width = child.width; + } else if (childConfig.widthSpec == DoricLayoutAtMost) { + size.width = targetSize.width; + } + if (childConfig.heightSpec == DoricLayoutExact) { + size.height = child.height; + } else if (childConfig.heightSpec == DoricLayoutAtMost) { + size.height = targetSize.height - yStart; + } + if (childConfig.weight) { + size.height = child.height; + } + + if (childConfig.weight) { + size.height += remain / self.contentWeight * childConfig.weight; + } + child.width = size.width; + child.height = size.height; + + DoricGravity gravity = childConfig.alignment | self.gravity; + + if ((gravity & LEFT) == LEFT) { + child.left = 0; + } else if ((gravity & RIGHT) == RIGHT) { + child.right = self.width; + } else if ((gravity & CENTER_X) == CENTER_X) { + child.centerX = targetSize.width / 2; + } else { + if (childConfig.margin.left) { + child.left = childConfig.margin.left; + } else if (childConfig.margin.right) { + child.right = targetSize.width - childConfig.margin.right; + } } if (childConfig.margin.top) { yStart += childConfig.margin.top; @@ -336,102 +351,124 @@ - (void)layout { yStart += childConfig.margin.bottom; } if ([child isKindOfClass:[DoricLayoutContainer class]]) { - [(DoricLayoutContainer *) child layout]; + [(DoricLayoutContainer *) child layout:size]; } } + self.width = targetSize.width; + self.height = targetSize.height; } @end @implementation DoricHLayoutView -- (void)sizeToFit { - DoricLinearConfig *config; - if ([self.superview isKindOfClass:[DoricLinearView class]]) { - config = [(DoricLinearView *) self.superview configForChild:self]; - } else { - config = (DoricLinearConfig *) self.layoutConfig; - if (!config) { - config = [[DoricLinearConfig alloc] init]; - } - } - self.contentWidth = 0; - self.contentHeight = 0; - self.contentWeight = 0; + +- (CGSize)sizeContent:(CGSize)size { + CGFloat contentWidth = 0; + CGFloat contentHeight = 0; + NSUInteger contentWeight = 0; for (UIView *child in self.subviews) { if (child.isHidden) { continue; } - DoricLinearConfig *childConfig = [self configForChild:child]; + DoricLayoutConfig *childConfig = child.layoutConfig; + if (!childConfig) { + childConfig = [DoricLayoutConfig new]; + } + CGSize childSize = CGSizeMake(child.width, child.height); if ([child isKindOfClass:[DoricLayoutContainer class]] || childConfig.widthSpec == DoricLayoutWrapContent || childConfig.heightSpec == DoricLayoutWrapContent) { - [child sizeToFit]; + childSize = [child sizeThatFits:CGSizeMake(size.width - contentWidth, size.height)]; } - self.contentHeight = MAX(self.contentHeight, child.height + childConfig.margin.top + childConfig.margin.bottom); - self.contentWidth += child.width + self.space + childConfig.margin.left + childConfig.margin.right; - self.contentWeight += childConfig.weight; - } - self.contentWidth -= self.space; - if (config.widthSpec == DoricLayoutWrapContent) { - self.width = self.contentWidth; - } else if (config.widthSpec == DoricLayoutAtMost) { - self.width = self.superview.width; - } - if (config.heightSpec == DoricLayoutWrapContent) { - self.height = self.contentHeight; - } else if (config.heightSpec == DoricLayoutAtMost) { - self.height = self.superview.height; - } - if (self.contentWeight) { - CGFloat remain = self.width - self.contentWidth; - for (UIView *child in self.subviews) { - if (child.isHidden) { - continue; - } - DoricLinearConfig *childConfig = [self configForChild:child]; - if (childConfig.weight) { - child.width += remain / self.contentWeight * childConfig.weight; - } + if (childConfig.widthSpec == DoricLayoutExact) { + childSize.width = child.width; + } else if (childConfig.widthSpec == DoricLayoutAtMost) { + childSize.width = size.width - contentWidth; } - self.contentWidth = self.width; + if (childConfig.heightSpec == DoricLayoutExact) { + childSize.height = child.height; + } else if (childConfig.heightSpec == DoricLayoutAtMost) { + childSize.height = size.height; + } + if (childConfig.weight) { + childSize.width = child.width; + } + contentWidth += childSize.width + self.space + childConfig.margin.left + childConfig.margin.right; + contentHeight = MAX(contentHeight, childSize.height + childConfig.margin.top + childConfig.margin.bottom); + contentWeight += childConfig.weight; } + contentWidth -= self.space; + self.contentWidth = contentWidth; + self.contentHeight = contentHeight; + self.contentWeight = contentWeight; + if (contentWeight) { + contentWidth = size.width; + } + return CGSizeMake(contentWidth, contentHeight); } -- (void)layout { +- (void)layout:(CGSize)targetSize { CGFloat xStart = 0; - if ((self.gravity & LEFT) == LEFT) { + if (self.contentWeight) { + xStart = 0; + } else if ((self.gravity & LEFT) == LEFT) { xStart = 0; } else if ((self.gravity & RIGHT) == RIGHT) { - xStart = self.width - self.contentWidth; + xStart = targetSize.width - self.contentWidth; } else if ((self.gravity & CENTER_X) == CENTER_X) { - xStart = (self.width - self.contentWidth) / 2; + xStart = (targetSize.width - self.contentWidth) / 2; } + CGFloat remain = targetSize.width - self.contentWidth; for (UIView *child in self.subviews) { if (child.isHidden) { continue; } - DoricLinearConfig *childConfig = [self configForChild:child]; + DoricLayoutConfig *childConfig = child.layoutConfig; + if (!childConfig) { + childConfig = [DoricLayoutConfig new]; + } + + CGSize size = [child sizeThatFits:CGSizeMake(targetSize.width - xStart, targetSize.height)]; + if (childConfig.widthSpec == DoricLayoutExact) { + size.width = child.width; + } + if (childConfig.heightSpec == DoricLayoutExact) { + size.height = child.height; + } + if (childConfig.widthSpec == DoricLayoutExact) { + size.width = child.width; + } else if (childConfig.widthSpec == DoricLayoutAtMost) { + size.width = targetSize.width - xStart; + } + if (childConfig.heightSpec == DoricLayoutExact) { + size.height = child.height; + } else if (childConfig.heightSpec == DoricLayoutAtMost) { + size.height = targetSize.height; + } + if (childConfig.weight) { + size.width = child.width; + } + + if (childConfig.weight) { + size.width += remain / self.contentWeight * childConfig.weight; + } + child.width = size.width; + child.height = size.height; + DoricGravity gravity = childConfig.alignment | self.gravity; if ((gravity & TOP) == TOP) { child.top = 0; } else if ((gravity & BOTTOM) == BOTTOM) { - child.bottom = self.height; + child.bottom = targetSize.height; } else if ((gravity & CENTER_Y) == CENTER_Y) { - child.centerY = self.height / 2; + child.centerY = targetSize.height / 2; } else { if (childConfig.margin.top) { child.top = childConfig.margin.top; } else if (childConfig.margin.bottom) { - child.bottom = self.height - childConfig.margin.bottom; + child.bottom = targetSize.height - childConfig.margin.bottom; } } - if (childConfig.heightSpec == DoricLayoutAtMost) { - child.height = self.height; - } - if (childConfig.widthSpec == DoricLayoutAtMost) { - child.width = self.width - xStart - childConfig.margin.right - childConfig.margin.left - self.space; - } - if (childConfig.margin.left) { xStart += childConfig.margin.left; } @@ -441,9 +478,11 @@ - (void)layout { xStart += childConfig.margin.right; } if ([child isKindOfClass:[DoricLayoutContainer class]]) { - [(DoricLayoutContainer *) child layout]; + [(DoricLayoutContainer *) child layout:size]; } } + self.width = targetSize.width; + self.height = targetSize.height; } @end diff --git a/iOS/Pod/Classes/Shader/DoricRootNode.m b/iOS/Pod/Classes/Shader/DoricRootNode.m index c06ce43b..7272a937 100644 --- a/iOS/Pod/Classes/Shader/DoricRootNode.m +++ b/iOS/Pod/Classes/Shader/DoricRootNode.m @@ -31,6 +31,6 @@ - (void)render:(NSDictionary *)props { [self blend:props]; } - (void)requestLayout { - [self.view requestLayout]; + [self.view setNeedsLayout]; } @end diff --git a/iOS/Pod/Classes/Shader/DoricStackNode.h b/iOS/Pod/Classes/Shader/DoricStackNode.h index 375cafad..947d9c75 100644 --- a/iOS/Pod/Classes/Shader/DoricStackNode.h +++ b/iOS/Pod/Classes/Shader/DoricStackNode.h @@ -22,5 +22,5 @@ #import "DoricGroupNode.h" -@interface DoricStackNode : DoricGroupNode +@interface DoricStackNode : DoricGroupNode @end diff --git a/iOS/Pod/Classes/Shader/DoricStackNode.m b/iOS/Pod/Classes/Shader/DoricStackNode.m index e349055f..9e2f7569 100644 --- a/iOS/Pod/Classes/Shader/DoricStackNode.m +++ b/iOS/Pod/Classes/Shader/DoricStackNode.m @@ -21,7 +21,6 @@ // #import "DoricStackNode.h" -#import "DoricUtil.h" @implementation DoricStackNode @@ -36,22 +35,4 @@ - (void)blendView:(DoricStackView *)view forPropName:(NSString *)name propValue: [super blendView:view forPropName:name propValue:prop]; } } - -- (DoricStackConfig *)generateDefaultLayoutParams { - return [[DoricStackConfig alloc] init]; -} - -- (void)blendSubNode:(DoricViewNode *)subNode layoutConfig:(NSDictionary *)layoutConfig { - [super blendSubNode:subNode layoutConfig:layoutConfig]; - if (![subNode.layoutConfig isKindOfClass:DoricStackConfig.class]) { - DoricLog(@"blend DoricHLayoutView child error,layout params not match"); - return; - } - DoricStackConfig *params = (DoricStackConfig *) subNode.layoutConfig; - NSNumber *alignment = layoutConfig[@"alignment"]; - if (alignment) { - params.alignment = (DoricGravity) [alignment integerValue]; - } -} - @end diff --git a/iOS/Pod/Classes/Shader/DoricSuperNode.h b/iOS/Pod/Classes/Shader/DoricSuperNode.h index d8b0c52d..b9915f07 100644 --- a/iOS/Pod/Classes/Shader/DoricSuperNode.h +++ b/iOS/Pod/Classes/Shader/DoricSuperNode.h @@ -20,8 +20,8 @@ #import #import "DoricViewNode.h" -@interface DoricSuperNode : DoricViewNode -- (P)generateDefaultLayoutParams; +@interface DoricSuperNode : DoricViewNode +- (DoricLayoutConfig *)generateDefaultLayoutParams; - (void)blendSubNode:(DoricViewNode *)subNode layoutConfig:(NSDictionary *)layoutConfig; diff --git a/iOS/Pod/Classes/Shader/DoricSuperNode.m b/iOS/Pod/Classes/Shader/DoricSuperNode.m index 439fc6e9..b06ee2db 100644 --- a/iOS/Pod/Classes/Shader/DoricSuperNode.m +++ b/iOS/Pod/Classes/Shader/DoricSuperNode.m @@ -80,17 +80,20 @@ - (void)blendSubNode:(DoricViewNode *)subNode layoutConfig:(NSDictionary *)layou } }]; - if ([params isKindOfClass:DoricMarginConfig.class]) { - DoricMarginConfig *marginParams = (DoricMarginConfig *) params; - NSDictionary *margin = layoutConfig[@"margin"]; - if (margin) { - marginParams.margin = DoricMarginMake( - [(NSNumber *) margin[@"left"] floatValue], - [(NSNumber *) margin[@"top"] floatValue], - [(NSNumber *) margin[@"right"] floatValue], - [(NSNumber *) margin[@"bottom"] floatValue]); - } + NSDictionary *margin = layoutConfig[@"margin"]; + if (margin) { + params.margin = DoricMarginMake( + [(NSNumber *) margin[@"left"] floatValue], + [(NSNumber *) margin[@"top"] floatValue], + [(NSNumber *) margin[@"right"] floatValue], + [(NSNumber *) margin[@"bottom"] floatValue]); } + + NSNumber *alignment = layoutConfig[@"alignment"]; + if (alignment) { + params.alignment = (DoricGravity) [alignment integerValue]; + } + } - (void)blendSubNode:(NSDictionary *)subModel { diff --git a/iOS/Pod/Classes/Shader/DoricVLayoutNode.h b/iOS/Pod/Classes/Shader/DoricVLayoutNode.h index 6024eaa2..853f3f7b 100644 --- a/iOS/Pod/Classes/Shader/DoricVLayoutNode.h +++ b/iOS/Pod/Classes/Shader/DoricVLayoutNode.h @@ -22,5 +22,5 @@ #import "DoricGroupNode.h" -@interface DoricVLayoutNode : DoricGroupNode +@interface DoricVLayoutNode : DoricGroupNode @end diff --git a/iOS/Pod/Classes/Shader/DoricVLayoutNode.m b/iOS/Pod/Classes/Shader/DoricVLayoutNode.m index c1fea393..d7b5d94d 100644 --- a/iOS/Pod/Classes/Shader/DoricVLayoutNode.m +++ b/iOS/Pod/Classes/Shader/DoricVLayoutNode.m @@ -21,7 +21,6 @@ // #import "DoricVLayoutNode.h" -#import "DoricUtil.h" @implementation DoricVLayoutNode @@ -39,28 +38,4 @@ - (void)blendView:(DoricVLayoutView *)view forPropName:(NSString *)name propValu } } -- (void)blendSubNode:(DoricViewNode *)subNode layoutConfig:(NSDictionary *)layoutconfig { - [super blendSubNode:subNode layoutConfig:layoutconfig]; - if (![subNode.layoutConfig isKindOfClass:DoricLinearConfig.class]) { - DoricLog(@"blend DoricVLayoutView child error,layout params not match"); - return; - } - DoricLinearConfig *params = (DoricLinearConfig *) subNode.layoutConfig; - NSDictionary *margin = layoutconfig[@"margin"]; - if (margin) { - params.margin = DoricMarginMake( - [(NSNumber *) margin[@"left"] floatValue], - [(NSNumber *) margin[@"top"] floatValue], - [(NSNumber *) margin[@"right"] floatValue], - [(NSNumber *) margin[@"bottom"] floatValue]); - } - NSNumber *alignment = layoutconfig[@"alignment"]; - if (alignment) { - params.alignment = (DoricGravity) [alignment integerValue]; - } -} - -- (DoricLinearConfig *)generateDefaultLayoutParams { - return [[DoricLinearConfig alloc] init]; -} @end diff --git a/js-framework/src/ui/layout.ts b/js-framework/src/ui/layout.ts index 6cba6db9..bfeb246a 100644 --- a/js-framework/src/ui/layout.ts +++ b/js-framework/src/ui/layout.ts @@ -16,14 +16,6 @@ import { LayoutConfig, Group, Property, IView } from "./view"; import { Gravity } from "../util/gravity"; -export interface StackConfig extends LayoutConfig { - -} - -export interface LinearConfig extends LayoutConfig { - weight?: number -} - export interface IStack extends IView { gravity?: Gravity } diff --git a/js-framework/src/ui/view.ts b/js-framework/src/ui/view.ts index 73869189..5e4be06f 100644 --- a/js-framework/src/ui/view.ts +++ b/js-framework/src/ui/view.ts @@ -35,6 +35,8 @@ export interface LayoutConfig { bottom?: number, } alignment?: Gravity + //Only affective in VLayout or HLayout + weight?: number } export function Property(target: Object, propKey: string) {