Return-Path: X-Original-To: archive-asf-public-internal@cust-asf2.ponee.io Delivered-To: archive-asf-public-internal@cust-asf2.ponee.io Received: from cust-asf.ponee.io (cust-asf.ponee.io [163.172.22.183]) by cust-asf2.ponee.io (Postfix) with ESMTP id 30FAA200C39 for ; Thu, 2 Mar 2017 04:29:44 +0100 (CET) Received: by cust-asf.ponee.io (Postfix) id 2F845160B78; Thu, 2 Mar 2017 03:29:44 +0000 (UTC) Delivered-To: archive-asf-public@cust-asf.ponee.io Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by cust-asf.ponee.io (Postfix) with SMTP id 819F7160B70 for ; Thu, 2 Mar 2017 04:29:42 +0100 (CET) Received: (qmail 33871 invoked by uid 500); 2 Mar 2017 03:29:41 -0000 Mailing-List: contact commits-help@weex.incubator.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@weex.incubator.apache.org Delivered-To: mailing list commits@weex.incubator.apache.org Received: (qmail 33862 invoked by uid 99); 2 Mar 2017 03:29:41 -0000 Received: from pnap-us-west-generic-nat.apache.org (HELO spamd1-us-west.apache.org) (209.188.14.142) by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 02 Mar 2017 03:29:41 +0000 Received: from localhost (localhost [127.0.0.1]) by spamd1-us-west.apache.org (ASF Mail Server at spamd1-us-west.apache.org) with ESMTP id 1B024C0A2F for ; Thu, 2 Mar 2017 03:29:41 +0000 (UTC) X-Virus-Scanned: Debian amavisd-new at spamd1-us-west.apache.org X-Spam-Flag: NO X-Spam-Score: -3.568 X-Spam-Level: X-Spam-Status: No, score=-3.568 tagged_above=-999 required=6.31 tests=[KAM_ASCII_DIVIDERS=0.8, RCVD_IN_DNSWL_HI=-5, RCVD_IN_MSPIKE_H3=-0.01, RCVD_IN_MSPIKE_WL=-0.01, RP_MATCHES_RCVD=-0.001, SPF_NEUTRAL=0.652, URIBL_BLOCKED=0.001] autolearn=disabled Received: from mx1-lw-eu.apache.org ([10.40.0.8]) by localhost (spamd1-us-west.apache.org [10.40.0.7]) (amavisd-new, port 10024) with ESMTP id 5lh08aTUwRjz for ; Thu, 2 Mar 2017 03:29:38 +0000 (UTC) Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by mx1-lw-eu.apache.org (ASF Mail Server at mx1-lw-eu.apache.org) with SMTP id 8BB8E5F1A1 for ; Thu, 2 Mar 2017 03:29:36 +0000 (UTC) Received: (qmail 32268 invoked by uid 99); 2 Mar 2017 03:28:35 -0000 Received: from git1-us-west.apache.org (HELO git1-us-west.apache.org) (140.211.11.23) by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 02 Mar 2017 03:28:35 +0000 Received: by git1-us-west.apache.org (ASF Mail Server at git1-us-west.apache.org, from userid 33) id 5105DE95D9; Thu, 2 Mar 2017 03:28:35 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: cxfeng@apache.org To: commits@weex.incubator.apache.org Date: Thu, 02 Mar 2017 03:28:41 -0000 Message-Id: In-Reply-To: References: X-Mailer: ASF-Git Admin Mailer Subject: [07/25] incubator-weex git commit: + [ios] support waterfall layout * Add recycler component to be based component of UICollectionView * Support column-count/column-gap/column-width for multi-column layout archived-at: Thu, 02 Mar 2017 03:29:44 -0000 http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/1c96da7a/ios/sdk/WeexSDK/Sources/Component/Recycler/WXSectionDataController.m ---------------------------------------------------------------------- diff --git a/ios/sdk/WeexSDK/Sources/Component/Recycler/WXSectionDataController.m b/ios/sdk/WeexSDK/Sources/Component/Recycler/WXSectionDataController.m new file mode 100644 index 0000000..c4270d7 --- /dev/null +++ b/ios/sdk/WeexSDK/Sources/Component/Recycler/WXSectionDataController.m @@ -0,0 +1,85 @@ +/** + * Created by Weex. + * Copyright (c) 2016, Alibaba, Inc. All rights reserved. + * + * This source code is licensed under the Apache Licence 2.0. + * For the full copyright and license information,please view the LICENSE file in the root directory of this source tree. + */ + +#import "WXSectionDataController.h" +#import "WXCellComponent.h" +#import "WXHeaderComponent.h" +#import "WXAssert.h" + +@interface WXSectionDataController () + +@end + +@implementation WXSectionDataController + +- (NSInteger)numberOfItems +{ + return self.cellComponents.count; +} + +- (UIView *)cellForItemAtIndex:(NSInteger)index +{ + WXAssertMainThread(); + + WXCellComponent *cellComponent = self.cellComponents[index]; + return cellComponent.view; +} + +- (CGSize)sizeForItemAtIndex:(NSInteger)index +{ + WXAssertMainThread(); + + WXCellComponent *cellComponent = self.cellComponents[index]; + return cellComponent.calculatedFrame.size; +} + +- (UIView *)viewForHeaderAtIndex:(NSInteger)index; +{ + return self.headerComponent.view; +} + +- (CGSize)sizeForHeaderAtIndex:(NSInteger)index +{ + return self.headerComponent.calculatedFrame.size; +} + +- (BOOL)isStickyForHeaderAtIndex:(NSInteger)index +{ + return self.headerComponent.isSticky; +} + +- (NSUInteger)hash +{ + return [super hash]; +} + +- (BOOL)isEqual:(id)object +{ + if ([object isKindOfClass:[WXSectionDataController class]]) { + WXSectionDataController *controller = (WXSectionDataController *)object; + BOOL headerEqual = (self.headerComponent && controller.headerComponent && self.headerComponent == controller.headerComponent) || (!self.headerComponent && !controller.headerComponent); + BOOL footerEqual = (self.footerComponent && controller.footerComponent && self.footerComponent == controller.footerComponent) || (!self.footerComponent && !controller.footerComponent); + BOOL cellEqual = self.cellComponents && controller.cellComponents && self.cellComponents.count == controller.cellComponents.count; + if (cellEqual) { + for (int i = 0; i < self.cellComponents.count; i ++) { + if (self.cellComponents[i] != controller.cellComponents[i]) { + cellEqual = NO; + break; + } + } + } else { + cellEqual = !self.cellComponents && controller.cellComponents; + } + + return headerEqual && footerEqual && cellEqual; + } else { + return NO; + } +} + +@end http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/1c96da7a/ios/sdk/WeexSDK/Sources/Component/WXCellComponent.h ---------------------------------------------------------------------- diff --git a/ios/sdk/WeexSDK/Sources/Component/WXCellComponent.h b/ios/sdk/WeexSDK/Sources/Component/WXCellComponent.h index 2e5bf59..29aa1c6 100644 --- a/ios/sdk/WeexSDK/Sources/Component/WXCellComponent.h +++ b/ios/sdk/WeexSDK/Sources/Component/WXCellComponent.h @@ -7,14 +7,29 @@ */ #import "WXComponent.h" -@class WXListComponent; +@class WXCellComponent; + +@protocol WXCellRenderDelegate + +- (float)cellWidthForLayout:(WXCellComponent *)cell; + +- (void)cellDidLayout:(WXCellComponent *)cell; + +- (void)cellDidRendered:(WXCellComponent *)cell; + +- (void)cellDidRemove:(WXCellComponent *)cell; + +- (void)cell:(WXCellComponent *)cell didMoveToIndex:(NSUInteger)index; + +@end @interface WXCellComponent : WXComponent @property (nonatomic, strong) NSString *scope; @property (nonatomic, assign) BOOL isRecycle; +@property (nonatomic, assign) BOOL isLayoutComplete; @property (nonatomic, assign) UITableViewRowAnimation insertAnimation; @property (nonatomic, assign) UITableViewRowAnimation deleteAnimation; -@property (nonatomic, weak) WXListComponent *list; +@property (nonatomic, weak) id delegate; @end http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/1c96da7a/ios/sdk/WeexSDK/Sources/Component/WXCellComponent.m ---------------------------------------------------------------------- diff --git a/ios/sdk/WeexSDK/Sources/Component/WXCellComponent.m b/ios/sdk/WeexSDK/Sources/Component/WXCellComponent.m index adf91a8..593628a 100644 --- a/ios/sdk/WeexSDK/Sources/Component/WXCellComponent.m +++ b/ios/sdk/WeexSDK/Sources/Component/WXCellComponent.m @@ -15,6 +15,7 @@ @implementation WXCellComponent { NSIndexPath *_indexPathBeforeMove; + BOOL _isUseContainerWidth; } - (instancetype)initWithRef:(NSString *)ref type:(NSString *)type styles:(NSDictionary *)styles attributes:(NSDictionary *)attributes events:(NSArray *)events weexInstance:(WXSDKInstance *)weexInstance @@ -38,12 +39,18 @@ } +- (BOOL)isEqual:(id)object +{ + WXCellComponent *cell = object; + return self == cell && self.isLayoutComplete == cell.isLayoutComplete && CGRectEqualToRect(self.calculatedFrame, cell.calculatedFrame); +} + - (void)_frameDidCalculated:(BOOL)isChanged { [super _frameDidCalculated:isChanged]; if (isChanged) { - [self.list cellDidLayout:self]; + [self.delegate cellDidLayout:self]; } } @@ -54,7 +61,7 @@ [super displayCompletionBlock](layer, finished); } - [self.list cellDidRendered:self]; + [self.delegate cellDidRendered:self]; }; } @@ -79,8 +86,8 @@ - (void)_moveToSupercomponent:(WXComponent *)newSupercomponent atIndex:(NSUInteger)index { - if (self.list == newSupercomponent) { - [self.list cell:self didMoveToIndex:index]; + if (self.delegate == newSupercomponent) { + [self.delegate cell:self didMoveToIndex:index]; [super _removeFromSupercomponent]; [newSupercomponent _insertSubcomponent:self atIndex:index]; } else { @@ -92,7 +99,7 @@ { [super _removeFromSupercomponent]; - [self.list cellDidRemove:self]; + [self.delegate cellDidRemove:self]; } - (void)removeFromSuperview @@ -102,8 +109,10 @@ - (void)_calculateFrameWithSuperAbsolutePosition:(CGPoint)superAbsolutePosition gatherDirtyComponents:(NSMutableSet *)dirtyComponents { - if (isUndefined(self.cssNode->style.dimensions[CSS_WIDTH]) && self.list) { - self.cssNode->style.dimensions[CSS_WIDTH] = self.list.scrollerCSSNode->style.dimensions[CSS_WIDTH]; + if (self.delegate && (isUndefined(self.cssNode->style.dimensions[CSS_WIDTH]) || _isUseContainerWidth)) { + self.cssNode->style.dimensions[CSS_WIDTH] = [self.delegate cellWidthForLayout:self]; + //TODO: set _isUseContainerWidth to NO if updateStyles have width + _isUseContainerWidth = YES; } if ([self needsLayout]) { http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/1c96da7a/ios/sdk/WeexSDK/Sources/Component/WXComponent+GradientColor.h ---------------------------------------------------------------------- diff --git a/ios/sdk/WeexSDK/Sources/Component/WXComponent+GradientColor.h b/ios/sdk/WeexSDK/Sources/Component/WXComponent+GradientColor.h index 0706eed..92b7596 100644 --- a/ios/sdk/WeexSDK/Sources/Component/WXComponent+GradientColor.h +++ b/ios/sdk/WeexSDK/Sources/Component/WXComponent+GradientColor.h @@ -1,10 +1,11 @@ -// -// WXComponent+GradientColor.h -// Pods -// -// Created by bobning on 16/12/23. -// -// +/** + * Created by Weex. + * Copyright (c) 2016, Alibaba, Inc. All rights reserved. + * + * This source code is licensed under the Apache Licence 2.0. + * For the full copyright and license information,please view the LICENSE file in the root directory of this source tree. + */ + #import #import http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/1c96da7a/ios/sdk/WeexSDK/Sources/Component/WXComponent+GradientColor.m ---------------------------------------------------------------------- diff --git a/ios/sdk/WeexSDK/Sources/Component/WXComponent+GradientColor.m b/ios/sdk/WeexSDK/Sources/Component/WXComponent+GradientColor.m index e710ed0..86c3379 100644 --- a/ios/sdk/WeexSDK/Sources/Component/WXComponent+GradientColor.m +++ b/ios/sdk/WeexSDK/Sources/Component/WXComponent+GradientColor.m @@ -1,10 +1,11 @@ -// -// WXComponent+GradientColor.m -// Pods -// -// Created by bobning on 16/12/23. -// -// +/** + * Created by Weex. + * Copyright (c) 2016, Alibaba, Inc. All rights reserved. + * + * This source code is licensed under the Apache Licence 2.0. + * For the full copyright and license information,please view the LICENSE file in the root directory of this source tree. + */ + #import "WXComponent+GradientColor.h" #import "WXComponent_internal.h" http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/1c96da7a/ios/sdk/WeexSDK/Sources/Component/WXFooterComponent.h ---------------------------------------------------------------------- diff --git a/ios/sdk/WeexSDK/Sources/Component/WXFooterComponent.h b/ios/sdk/WeexSDK/Sources/Component/WXFooterComponent.h new file mode 100644 index 0000000..e9c801c --- /dev/null +++ b/ios/sdk/WeexSDK/Sources/Component/WXFooterComponent.h @@ -0,0 +1,13 @@ +/** + * Created by Weex. + * Copyright (c) 2016, Alibaba, Inc. All rights reserved. + * + * This source code is licensed under the Apache Licence 2.0. + * For the full copyright and license information,please view the LICENSE file in the root directory of this source tree. + */ + +#import + +@interface WXFooterComponent : WXComponent + +@end http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/1c96da7a/ios/sdk/WeexSDK/Sources/Component/WXFooterComponent.m ---------------------------------------------------------------------- diff --git a/ios/sdk/WeexSDK/Sources/Component/WXFooterComponent.m b/ios/sdk/WeexSDK/Sources/Component/WXFooterComponent.m new file mode 100644 index 0000000..f139eaf --- /dev/null +++ b/ios/sdk/WeexSDK/Sources/Component/WXFooterComponent.m @@ -0,0 +1,13 @@ +/** + * Created by Weex. + * Copyright (c) 2016, Alibaba, Inc. All rights reserved. + * + * This source code is licensed under the Apache Licence 2.0. + * For the full copyright and license information,please view the LICENSE file in the root directory of this source tree. + */ + +#import "WXFooterComponent.h" + +@implementation WXFooterComponent + +@end http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/1c96da7a/ios/sdk/WeexSDK/Sources/Component/WXHeaderComponent.h ---------------------------------------------------------------------- diff --git a/ios/sdk/WeexSDK/Sources/Component/WXHeaderComponent.h b/ios/sdk/WeexSDK/Sources/Component/WXHeaderComponent.h new file mode 100644 index 0000000..5aaf616 --- /dev/null +++ b/ios/sdk/WeexSDK/Sources/Component/WXHeaderComponent.h @@ -0,0 +1,25 @@ +/** + * Created by Weex. + * Copyright (c) 2016, Alibaba, Inc. All rights reserved. + * + * This source code is licensed under the Apache Licence 2.0. + * For the full copyright and license information,please view the LICENSE file in the root directory of this source tree. + */ + +#import +@class WXHeaderComponent; + +@protocol WXHeaderRenderDelegate + +- (float)headerWidthForLayout:(WXHeaderComponent *)cell; + +- (void)headerDidLayout:(WXHeaderComponent *)cell; + +@end + +@interface WXHeaderComponent : WXComponent + +@property (nonatomic, weak) id delegate; +@property (nonatomic, assign, readonly) BOOL isSticky; + +@end http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/1c96da7a/ios/sdk/WeexSDK/Sources/Component/WXHeaderComponent.m ---------------------------------------------------------------------- diff --git a/ios/sdk/WeexSDK/Sources/Component/WXHeaderComponent.m b/ios/sdk/WeexSDK/Sources/Component/WXHeaderComponent.m new file mode 100644 index 0000000..f54938d --- /dev/null +++ b/ios/sdk/WeexSDK/Sources/Component/WXHeaderComponent.m @@ -0,0 +1,62 @@ +/** + * Created by Weex. + * Copyright (c) 2016, Alibaba, Inc. All rights reserved. + * + * This source code is licensed under the Apache Licence 2.0. + * For the full copyright and license information,please view the LICENSE file in the root directory of this source tree. + */ + +#import "WXHeaderComponent.h" +#import "WXComponent_internal.h" + +@implementation WXHeaderComponent +{ + BOOL _isUseContainerWidth; +} + +//TODO: header remove->need reload +- (instancetype)initWithRef:(NSString *)ref type:(NSString *)type styles:(NSDictionary *)styles attributes:(NSDictionary *)attributes events:(NSArray *)events weexInstance:(WXSDKInstance *)weexInstance +{ + self = [super initWithRef:ref type:type styles:styles attributes:attributes events:events weexInstance:weexInstance]; + + if (self) { + _async = YES; + _isNeedJoinLayoutSystem = NO; + } + + return self; +} + +- (BOOL)isSticky +{ + return _positionType == WXPositionTypeSticky; +} + +- (void)_frameDidCalculated:(BOOL)isChanged +{ + [super _frameDidCalculated:isChanged]; + + if (isChanged) { + [self.delegate headerDidLayout:self]; + } +} + +- (void)_calculateFrameWithSuperAbsolutePosition:(CGPoint)superAbsolutePosition gatherDirtyComponents:(NSMutableSet *)dirtyComponents +{ + if (self.delegate && (isUndefined(self.cssNode->style.dimensions[CSS_WIDTH]) || _isUseContainerWidth)) { + self.cssNode->style.dimensions[CSS_WIDTH] = [self.delegate headerWidthForLayout:self]; + //TODO: set _isUseContainerWidth to NO if updateStyles have width + _isUseContainerWidth = YES; + } + + if ([self needsLayout]) { + layoutNode(self.cssNode, CSS_UNDEFINED, CSS_UNDEFINED, CSS_DIRECTION_INHERIT); + if ([WXLog logLevel] >= WXLogLevelDebug) { + print_css_node(self.cssNode, CSS_PRINT_LAYOUT | CSS_PRINT_STYLE | CSS_PRINT_CHILDREN); + } + } + + [super _calculateFrameWithSuperAbsolutePosition:superAbsolutePosition gatherDirtyComponents:dirtyComponents]; +} + +@end http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/1c96da7a/ios/sdk/WeexSDK/Sources/Component/WXListComponent.h ---------------------------------------------------------------------- diff --git a/ios/sdk/WeexSDK/Sources/Component/WXListComponent.h b/ios/sdk/WeexSDK/Sources/Component/WXListComponent.h index 007f502..2497c3b 100644 --- a/ios/sdk/WeexSDK/Sources/Component/WXListComponent.h +++ b/ios/sdk/WeexSDK/Sources/Component/WXListComponent.h @@ -8,18 +8,6 @@ #import "WXScrollerComponent.h" -@class WXCellComponent; -@class WXHeaderComponent; @interface WXListComponent : WXScrollerComponent -- (void)cellDidRemove:(WXCellComponent *)cell; - -- (void)cellDidLayout:(WXCellComponent *)cell; - -- (void)headerDidLayout:(WXHeaderComponent *)header; - -- (void)cellDidRendered:(WXCellComponent *)cell; - -- (void)cell:(WXCellComponent *)cell didMoveToIndex:(NSUInteger)index; - @end http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/1c96da7a/ios/sdk/WeexSDK/Sources/Component/WXListComponent.m ---------------------------------------------------------------------- diff --git a/ios/sdk/WeexSDK/Sources/Component/WXListComponent.m b/ios/sdk/WeexSDK/Sources/Component/WXListComponent.m index 4ab6b2c..943bcf8 100644 --- a/ios/sdk/WeexSDK/Sources/Component/WXListComponent.m +++ b/ios/sdk/WeexSDK/Sources/Component/WXListComponent.m @@ -8,6 +8,7 @@ #import "WXListComponent.h" #import "WXCellComponent.h" +#import "WXHeaderComponent.h" #import "WXComponent.h" #import "WXComponent_internal.h" #import "NSArray+Weex.h" @@ -52,53 +53,6 @@ @end -@interface WXHeaderComponent : WXComponent - -@property (nonatomic, weak) WXListComponent *list; - -@end - -@implementation WXHeaderComponent - -//TODO: header remove->need reload -- (instancetype)initWithRef:(NSString *)ref type:(NSString *)type styles:(NSDictionary *)styles attributes:(NSDictionary *)attributes events:(NSArray *)events weexInstance:(WXSDKInstance *)weexInstance -{ - self = [super initWithRef:ref type:type styles:styles attributes:attributes events:events weexInstance:weexInstance]; - - if (self) { - _async = YES; - _isNeedJoinLayoutSystem = NO; - } - - return self; -} - -- (void)_frameDidCalculated:(BOOL)isChanged -{ - [super _frameDidCalculated:isChanged]; - - if (isChanged) { - [self.list headerDidLayout:self]; - } -} - -- (void)_calculateFrameWithSuperAbsolutePosition:(CGPoint)superAbsolutePosition gatherDirtyComponents:(NSMutableSet *)dirtyComponents -{ - if (isUndefined(self.cssNode->style.dimensions[CSS_WIDTH]) && self.list) { - self.cssNode->style.dimensions[CSS_WIDTH] = self.list.scrollerCSSNode->style.dimensions[CSS_WIDTH]; - } - - if ([self needsLayout]) { - layoutNode(self.cssNode, CSS_UNDEFINED, CSS_UNDEFINED, CSS_DIRECTION_INHERIT); - if ([WXLog logLevel] >= WXLogLevelDebug) { - print_css_node(self.cssNode, CSS_PRINT_LAYOUT | CSS_PRINT_STYLE | CSS_PRINT_CHILDREN); - } - } - - [super _calculateFrameWithSuperAbsolutePosition:superAbsolutePosition gatherDirtyComponents:dirtyComponents]; -} - -@end @interface WXSection : NSObject @@ -133,7 +87,7 @@ } @end -@interface WXListComponent () +@interface WXListComponent () @end @@ -246,9 +200,9 @@ - (void)_insertSubcomponent:(WXComponent *)subcomponent atIndex:(NSInteger)index { if ([subcomponent isKindOfClass:[WXCellComponent class]]) { - ((WXCellComponent *)subcomponent).list = self; + ((WXCellComponent *)subcomponent).delegate = self; } else if ([subcomponent isKindOfClass:[WXHeaderComponent class]]) { - ((WXHeaderComponent *)subcomponent).list = self; + ((WXHeaderComponent *)subcomponent).delegate = self; } else if (![subcomponent isKindOfClass:[WXRefreshComponent class]] && ![subcomponent isKindOfClass:[WXLoadingComponent class]] && subcomponent->_positionType != WXPositionTypeFixed) { @@ -295,6 +249,13 @@ } } +#pragma mark - WXHeaderRenderDelegate + +- (float)headerWidthForLayout:(WXHeaderComponent *)cell +{ + return self.scrollerCSSNode->style.dimensions[CSS_WIDTH]; +} + - (void)headerDidLayout:(WXHeaderComponent *)header { [self.weexInstance.componentManager _addUITask:^{ @@ -302,10 +263,16 @@ [_tableView beginUpdates]; [_tableView endUpdates]; }]; - } +#pragma mark - WXCellRenderDelegate + +- (float)cellWidthForLayout:(WXCellComponent *)cell +{ + return self.scrollerCSSNode->style.dimensions[CSS_WIDTH]; +} + - (void)cellDidRemove:(WXCellComponent *)cell { WXAssertComponentThread(); http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/1c96da7a/ios/sdk/WeexSDK/Sources/Component/WXTransform.m ---------------------------------------------------------------------- diff --git a/ios/sdk/WeexSDK/Sources/Component/WXTransform.m b/ios/sdk/WeexSDK/Sources/Component/WXTransform.m index a72f39b..e5ed68b 100644 --- a/ios/sdk/WeexSDK/Sources/Component/WXTransform.m +++ b/ios/sdk/WeexSDK/Sources/Component/WXTransform.m @@ -87,7 +87,7 @@ } if (_translateX || _translateY) { - nativeTransform = CGAffineTransformTranslate(nativeTransform, _translateX ? [_translateX valueForMaximumValue:view.bounds.size.width] : 0, _translateY ? [_translateY valueForMaximumValue:view.bounds.size.height] : 0); + nativeTransform = CGAffineTransformTranslate(nativeTransform, _translateX ? [_translateX valueForMaximum:view.bounds.size.width] : 0, _translateY ? [_translateY valueForMaximum:view.bounds.size.height] : 0); } nativeTransform = CGAffineTransformScale(nativeTransform, _scaleX, _scaleY); @@ -131,8 +131,8 @@ * http://ronnqvi.st/translate-rotate-translate/ **/ CGPoint anchorPoint = CGPointMake( - _originX ? [_originX valueForMaximumValue:view.bounds.size.width] / view.bounds.size.width : 0.5, - _originY ? [_originY valueForMaximumValue:view.bounds.size.width] / view.bounds.size.height : 0.5); + _originX ? [_originX valueForMaximum:view.bounds.size.width] / view.bounds.size.width : 0.5, + _originY ? [_originY valueForMaximum:view.bounds.size.width] / view.bounds.size.height : 0.5); [self setAnchorPoint:anchorPoint forView:view]; } @@ -220,8 +220,8 @@ } } - _originX = [WXLength lengthWithValue:originX type:typeX]; - _originY = [WXLength lengthWithValue:originY type:typeY]; + _originX = [WXLength lengthWithFloat:originX type:typeX]; + _originY = [WXLength lengthWithFloat:originY type:typeY]; } - (void)parseRotate:(NSArray *)value @@ -235,20 +235,20 @@ WXLength *translateX; double x = [value[0] doubleValue]; if ([value[0] hasSuffix:@"%"]) { - translateX = [WXLength lengthWithValue:x type:WXLengthTypePercent]; + translateX = [WXLength lengthWithFloat:x type:WXLengthTypePercent]; } else { x = WXPixelScale(x, self.weexInstance.pixelScaleFactor); - translateX = [WXLength lengthWithValue:x type:WXLengthTypeFixed]; + translateX = [WXLength lengthWithFloat:x type:WXLengthTypeFixed]; } WXLength *translateY; if (value.count > 1) { double y = [value[1] doubleValue]; if ([value[1] hasSuffix:@"%"]) { - translateY = [WXLength lengthWithValue:y type:WXLengthTypePercent]; + translateY = [WXLength lengthWithFloat:y type:WXLengthTypePercent]; } else { y = WXPixelScale(y, self.weexInstance.pixelScaleFactor); - translateY = [WXLength lengthWithValue:y type:WXLengthTypeFixed]; + translateY = [WXLength lengthWithFloat:y type:WXLengthTypeFixed]; } } http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/1c96da7a/ios/sdk/WeexSDK/Sources/Engine/WXSDKEngine.m ---------------------------------------------------------------------- diff --git a/ios/sdk/WeexSDK/Sources/Engine/WXSDKEngine.m b/ios/sdk/WeexSDK/Sources/Engine/WXSDKEngine.m index e804aea..cd9f50e 100644 --- a/ios/sdk/WeexSDK/Sources/Engine/WXSDKEngine.m +++ b/ios/sdk/WeexSDK/Sources/Engine/WXSDKEngine.m @@ -72,6 +72,8 @@ [self registerComponent:@"image" withClass:NSClassFromString(@"WXImageComponent") withProperties:nil]; [self registerComponent:@"scroller" withClass:NSClassFromString(@"WXScrollerComponent") withProperties:nil]; [self registerComponent:@"list" withClass:NSClassFromString(@"WXListComponent") withProperties:nil]; + [self registerComponent:@"recycler" withClass:NSClassFromString(@"WXRecyclerComponent") withProperties:nil]; + [self registerComponent:@"waterfall" withClass:NSClassFromString(@"WXRecyclerComponent") withProperties:nil]; [self registerComponent:@"header" withClass:NSClassFromString(@"WXHeaderComponent")]; [self registerComponent:@"cell" withClass:NSClassFromString(@"WXCellComponent")]; http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/1c96da7a/ios/sdk/WeexSDK/Sources/Module/WXAnimationModule.m ---------------------------------------------------------------------- diff --git a/ios/sdk/WeexSDK/Sources/Module/WXAnimationModule.m b/ios/sdk/WeexSDK/Sources/Module/WXAnimationModule.m index 3eafce0..81fd481 100644 --- a/ios/sdk/WeexSDK/Sources/Module/WXAnimationModule.m +++ b/ios/sdk/WeexSDK/Sources/Module/WXAnimationModule.m @@ -167,16 +167,16 @@ WX_EXPORT_METHOD(@selector(transition:args:callback:)) if ((wxTransform.translateX && ![wxTransform.translateX isEqualToLength:oldTransform.translateX]) || (!wxTransform.translateX && oldTransform.translateX)) { WXAnimationInfo *newInfo = [info copy]; newInfo.propertyName = @"transform.translation.x"; - newInfo.fromValue = @([oldTransform.translateX valueForMaximumValue:view.bounds.size.width]); - newInfo.toValue = @([wxTransform.translateX valueForMaximumValue:view.bounds.size.width]); + newInfo.fromValue = @([oldTransform.translateX valueForMaximum:view.bounds.size.width]); + newInfo.toValue = @([wxTransform.translateX valueForMaximum:view.bounds.size.width]); [infos addObject:newInfo]; } if ((wxTransform.translateY && ![wxTransform.translateY isEqualToLength:oldTransform.translateY]) || (!wxTransform.translateY && oldTransform.translateY)) { WXAnimationInfo *newInfo = [info copy]; newInfo.propertyName = @"transform.translation.y"; - newInfo.fromValue = @([oldTransform.translateY valueForMaximumValue:view.bounds.size.height]); - newInfo.toValue = @([wxTransform.translateY valueForMaximumValue:view.bounds.size.height]); + newInfo.fromValue = @([oldTransform.translateY valueForMaximum:view.bounds.size.height]); + newInfo.toValue = @([wxTransform.translateY valueForMaximum:view.bounds.size.height]); [infos addObject:newInfo]; } http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/1c96da7a/ios/sdk/WeexSDK/Sources/Utility/WXConvert.h ---------------------------------------------------------------------- diff --git a/ios/sdk/WeexSDK/Sources/Utility/WXConvert.h b/ios/sdk/WeexSDK/Sources/Utility/WXConvert.h index 75658c6..bef72d0 100644 --- a/ios/sdk/WeexSDK/Sources/Utility/WXConvert.h +++ b/ios/sdk/WeexSDK/Sources/Utility/WXConvert.h @@ -11,6 +11,7 @@ #import "WXLog.h" #import "WXLayoutDefine.h" #import "WXType.h" +#import "WXLength.h" @interface WXConvert : NSObject @@ -68,6 +69,8 @@ typedef BOOL WXClipType; + (WXGradientType)gradientType:(id)value; ++ (WXLength *)WXLength:(id)value isFloat:(BOOL)isFloat scaleFactor:(CGFloat)scaleFactor; + @end @interface WXConvert (Deprecated) http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/1c96da7a/ios/sdk/WeexSDK/Sources/Utility/WXConvert.m ---------------------------------------------------------------------- diff --git a/ios/sdk/WeexSDK/Sources/Utility/WXConvert.m b/ios/sdk/WeexSDK/Sources/Utility/WXConvert.m index 15c5f6c..b72d7df 100644 --- a/ios/sdk/WeexSDK/Sources/Utility/WXConvert.m +++ b/ios/sdk/WeexSDK/Sources/Utility/WXConvert.m @@ -8,6 +8,7 @@ #import "WXConvert.h" #import "WXUtility.h" +#import "WXAssert.h" @implementation WXConvert @@ -723,6 +724,34 @@ WX_NUMBER_CONVERT(NSUInteger, unsignedIntegerValue) return type; } +#pragma mark - Length + ++ (WXLength *)WXLength:(id)value isFloat:(BOOL)isFloat scaleFactor:(CGFloat)scaleFactor +{ + if (!value) { + return nil; + } + + WXLengthType type = WXLengthTypeFixed; + if ([value isKindOfClass:[NSString class]]) { + if ([value isEqualToString:@"auto"]) { + type = WXLengthTypeAuto; + } else if ([value isEqualToString:@"normal"]){ + type = WXLengthTypeNormal; + } else if ([value hasSuffix:@"%"]) { + type = WXLengthTypePercent; + } + } else if (![value isKindOfClass:[NSNumber class]]) { + WXAssert(NO, @"Unsupported type:%@ for WXLength", NSStringFromClass([value class])); + } + + if (isFloat) { + return [WXLength lengthWithFloat:([value floatValue] * scaleFactor) type:type]; + } else { + return [WXLength lengthWithInt:([value intValue] * scaleFactor) type:type]; + } +} + @end @implementation WXConvert (Deprecated) http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/1c96da7a/ios/sdk/WeexSDK/Sources/Utility/WXDiffUtil.h ---------------------------------------------------------------------- diff --git a/ios/sdk/WeexSDK/Sources/Utility/WXDiffUtil.h b/ios/sdk/WeexSDK/Sources/Utility/WXDiffUtil.h new file mode 100644 index 0000000..c7edda9 --- /dev/null +++ b/ios/sdk/WeexSDK/Sources/Utility/WXDiffUtil.h @@ -0,0 +1,32 @@ +/** + * Created by Weex. + * Copyright (c) 2016, Alibaba, Inc. All rights reserved. + * + * This source code is licensed under the Apache Licence 2.0. + * For the full copyright and license information,please view the LICENSE file in the root directory of this source tree. + */ + +#import + +@interface WXDiffUpdateIndex : NSObject + +@property (nonatomic, assign, readonly) NSUInteger oldIndex; +@property (nonatomic, assign, readonly) NSUInteger newIndex; + +@end + +@interface WXDiffResult : NSObject + +@property (nonatomic, strong, readonly) NSIndexSet *inserts; +@property (nonatomic, strong, readonly) NSIndexSet *deletes; +@property (nonatomic, strong, readonly) NSArray *updates; + +- (BOOL)hasChanges; + +@end + +@interface WXDiffUtil : NSObject + ++ (WXDiffResult *)diffWithMinimumDistance:(NSArray *)newArray oldArray:(NSArray *)oldArray; + +@end http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/1c96da7a/ios/sdk/WeexSDK/Sources/Utility/WXDiffUtil.m ---------------------------------------------------------------------- diff --git a/ios/sdk/WeexSDK/Sources/Utility/WXDiffUtil.m b/ios/sdk/WeexSDK/Sources/Utility/WXDiffUtil.m new file mode 100644 index 0000000..44bd737 --- /dev/null +++ b/ios/sdk/WeexSDK/Sources/Utility/WXDiffUtil.m @@ -0,0 +1,165 @@ +/** + * Created by Weex. + * Copyright (c) 2016, Alibaba, Inc. All rights reserved. + * + * This source code is licensed under the Apache Licence 2.0. + * For the full copyright and license information,please view the LICENSE file in the root directory of this source tree. + */ + +#import "WXDiffUtil.h" + +typedef enum : NSUInteger { + WXDiffOperationDoNothing, + WXDiffOperationUpdate, + WXDiffOperationDelete, + WXDiffOperationInsert +} WXDiffOperation; + +@implementation WXDiffUpdateIndex + +- (instancetype)initWithOldIndex:(NSUInteger)oldIndex newIndex:(NSUInteger)newIndex +{ + if (self = [super init]) { + _oldIndex = oldIndex; + _newIndex = newIndex; + } + + return self; +} + +@end + +@implementation WXDiffResult + +- (instancetype)initWithInserts:(NSIndexSet *)inserts + deletes:(NSIndexSet *)deletes + updates:(NSArray *)updates +{ + if (self = [super init]) { + _inserts = [inserts copy]; + _deletes = [deletes copy]; + _updates = [updates copy]; + } + + return self; +} + +- (BOOL)hasChanges +{ + return _updates.count > 0 || _inserts.count > 0 || _deletes.count > 0; +} + +- (NSString *)description +{ + return [NSString stringWithFormat:@"<%@: %p; %zi inserts; %zi deletes; %zi updates", NSStringFromClass([self class]), self, _inserts.count, _deletes.count, _updates.count]; +} + + +@end + +@implementation WXDiffUtil + ++ (WXDiffResult *)diffWithMinimumDistance:(NSArray *)newArray oldArray:(NSArray *)oldArray +{ + // Using the levenshtein algorithm + // https://en.wikipedia.org/wiki/Levenshtein_distance + + int oldSize = (int)(oldArray.count + 1); + int newSize = (int)(newArray.count + 1); + + int **matrix = malloc(oldSize * sizeof(int *)); + for (int i = 0; i < oldSize; i++) { + matrix[i] = malloc(newSize * sizeof(int)); + } + + matrix[0][0] = 0; + + for (int i = 1; i < oldSize; i++) { + matrix[i][0] = i; + } + + for (int j = 1; j < newSize; j++) { + matrix[0][j] = j; + } + + for (int oldIndex = 1; oldIndex < oldSize; oldIndex ++) { + for (int newIndex = 1; newIndex < newSize; newIndex ++) { + if ([oldArray[oldIndex - 1] isEqual:newArray[newIndex - 1]]) { + matrix[oldIndex][newIndex] = matrix[oldIndex - 1][newIndex - 1]; + } else { + int updateCost = matrix[oldIndex - 1][newIndex - 1] + 1; + int insertCost = matrix[oldIndex][newIndex - 1] + 1; + int deleteCost = matrix[oldIndex - 1][newIndex] + 1; + matrix[oldIndex][newIndex] = MIN(MIN(insertCost, deleteCost), updateCost); + } + } + } + + NSMutableArray *updates = [NSMutableArray array]; + NSMutableIndexSet *inserts = [NSMutableIndexSet indexSet]; + NSMutableIndexSet *deletes = [NSMutableIndexSet indexSet]; + int oldIndex = oldSize - 1; + int newIndex = newSize - 1; + while (oldIndex != 0 || newIndex != 0) { + WXDiffOperation operation = [self _operationInMatrix:matrix newIndex:newIndex oldIndex:oldIndex]; + switch (operation) { + case WXDiffOperationUpdate: + newIndex --; + oldIndex --; + [updates addObject:[[WXDiffUpdateIndex alloc] initWithOldIndex:oldIndex newIndex:newIndex]]; + break; + case WXDiffOperationDelete: + oldIndex --; + [deletes addIndex:oldIndex]; + break; + case WXDiffOperationInsert: + newIndex --; + [inserts addIndex:newIndex]; + break; + case WXDiffOperationDoNothing: + newIndex --; + oldIndex --; + break; + } + } + + for (int i = 0; i < oldSize; i++) { + free(matrix[i]); + } + free(matrix); + + WXDiffResult *result = [[WXDiffResult alloc] initWithInserts:inserts deletes:deletes updates:updates]; + return result; +} + ++ (WXDiffOperation)_operationInMatrix:(int **)matrix newIndex:(int)newIndex oldIndex:(int)oldIndex +{ + if (newIndex == 0) { + return WXDiffOperationDelete; + } + + if (oldIndex == 0) { + return WXDiffOperationInsert; + } + + int cost = matrix[oldIndex][newIndex]; + + int costBeforeInsert = matrix[oldIndex][newIndex - 1]; + if (costBeforeInsert + 1 == cost) { + return WXDiffOperationInsert; + } + + int costBeforDelete = matrix[oldIndex - 1][newIndex]; + if (costBeforDelete + 1 == cost) { + return WXDiffOperationDelete; + } + + int costBeforUpdate = matrix[oldIndex - 1][newIndex - 1]; + if (costBeforUpdate + 1 == cost) { + return WXDiffOperationUpdate; + } + + return WXDiffOperationDoNothing; +} + +@end http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/1c96da7a/ios/sdk/WeexSDK/Sources/Utility/WXLength.h ---------------------------------------------------------------------- diff --git a/ios/sdk/WeexSDK/Sources/Utility/WXLength.h b/ios/sdk/WeexSDK/Sources/Utility/WXLength.h index b8480ea..491d2d7 100644 --- a/ios/sdk/WeexSDK/Sources/Utility/WXLength.h +++ b/ios/sdk/WeexSDK/Sources/Utility/WXLength.h @@ -12,13 +12,20 @@ typedef enum : NSUInteger { WXLengthTypeFixed, WXLengthTypePercent, WXLengthTypeAuto, + WXLengthTypeNormal } WXLengthType; @interface WXLength : NSObject -+ (instancetype)lengthWithValue:(float)value type:(WXLengthType)type; ++ (instancetype)lengthWithFloat:(float)value type:(WXLengthType)type; -- (float)valueForMaximumValue:(float)maximumValue; ++ (instancetype)lengthWithInt:(int)value type:(WXLengthType)type; + +- (float)valueForMaximum:(float)maximumValue; + +- (int)intValue; + +- (float)floatValue; - (BOOL)isEqualToLength:(WXLength *)length; @@ -28,4 +35,6 @@ typedef enum : NSUInteger { - (BOOL)isAuto; +- (BOOL)isNormal; + @end http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/1c96da7a/ios/sdk/WeexSDK/Sources/Utility/WXLength.m ---------------------------------------------------------------------- diff --git a/ios/sdk/WeexSDK/Sources/Utility/WXLength.m b/ios/sdk/WeexSDK/Sources/Utility/WXLength.m index 30cf57e..e64526d 100644 --- a/ios/sdk/WeexSDK/Sources/Utility/WXLength.m +++ b/ios/sdk/WeexSDK/Sources/Utility/WXLength.m @@ -11,25 +11,38 @@ @implementation WXLength { - float _value; + float _floatValue; + int _intValue; WXLengthType _type; + BOOL _isFloat; } -+ (instancetype)lengthWithValue:(float)value type:(WXLengthType)type ++ (instancetype)lengthWithFloat:(float)value type:(WXLengthType)type { WXLength *length = [WXLength new]; - length->_value = value; + length->_floatValue = value; length->_type = type; + length->_isFloat = YES; return length; } -- (float)valueForMaximumValue:(float)maximumValue ++ (instancetype)lengthWithInt:(int)value type:(WXLengthType)type { + WXLength *length = [WXLength new]; + length->_intValue = value; + length->_type = type; + length->_isFloat = NO; + return length; +} + +- (float)valueForMaximum:(float)maximumValue +{ + switch (_type) { case WXLengthTypeFixed: - return _value; + return _isFloat ? _floatValue : _intValue; case WXLengthTypePercent: - return maximumValue * _value / 100.0; + return maximumValue * (_isFloat ? _floatValue : _intValue) / 100.0; case WXLengthTypeAuto: return maximumValue; default: @@ -38,9 +51,22 @@ } } +- (int)intValue +{ + WXAssert(!_isFloat, @"call `intValue` for non-int length"); + return _intValue; +} + +- (float)floatValue +{ + WXAssert(_isFloat, @"call `floatValue` for non-float length"); + return _floatValue; +} + - (BOOL)isEqualToLength:(WXLength *)length { - return length && _type == length->_type && _value == length->_value; + return length && _type == length->_type && _isFloat == length->_isFloat + && _floatValue == length->_floatValue && _intValue == length->_intValue; } - (BOOL)isFixed @@ -58,4 +84,9 @@ return _type == WXLengthTypeAuto; } +- (BOOL)isNormal +{ + return _type == WXLengthTypeNormal; +} + @end