You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@weex.apache.org by ky...@apache.org on 2018/11/08 03:30:29 UTC

[incubator-weex] branch master updated: [Core] Let affine types of "scroller", "list", "waterfall" match RenderList logic. Autodetect subclass when registering a component and register its affine type. (#1723)

This is an automated email from the ASF dual-hosted git repository.

kyork pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-weex.git


The following commit(s) were added to refs/heads/master by this push:
     new f1117e5  [Core] Let affine types of "scroller", "list", "waterfall" match RenderList logic. Autodetect subclass when registering a component and register its affine type. (#1723)
f1117e5 is described below

commit f1117e56db6a9b72997f6a5d61372e1dc0c2ac7e
Author: wqyfavor <wq...@163.com>
AuthorDate: Thu Nov 8 11:30:22 2018 +0800

    [Core] Let affine types of "scroller", "list", "waterfall" match RenderList logic. Autodetect subclass when registering a component and register its affine type. (#1723)
---
 ios/sdk/WeexSDK/Sources/Bridge/WXCoreBridge.h      |  4 ++
 ios/sdk/WeexSDK/Sources/Bridge/WXCoreBridge.mm     | 10 ++++
 .../WeexSDK/Sources/Component/WXCellComponent.mm   |  4 +-
 .../Sources/Component/WXComponent_internal.h       |  2 +
 ios/sdk/WeexSDK/Sources/Engine/WXSDKEngine.m       | 13 +++++
 .../WeexSDK/Sources/Manager/WXComponentFactory.h   | 10 ++++
 .../WeexSDK/Sources/Manager/WXComponentFactory.m   | 56 +++++++++++++++++++++-
 ios/sdk/WeexSDK/Sources/Model/WXComponent.mm       |  5 ++
 .../core/render/node/factory/render_creator.cpp    | 49 +++++++++++++++----
 .../core/render/node/factory/render_creator.h      |  8 ++++
 weex_core/Source/core/render/node/render_list.cpp  |  3 +-
 11 files changed, 150 insertions(+), 14 deletions(-)

diff --git a/ios/sdk/WeexSDK/Sources/Bridge/WXCoreBridge.h b/ios/sdk/WeexSDK/Sources/Bridge/WXCoreBridge.h
index aa7e5a7..c611eb1 100644
--- a/ios/sdk/WeexSDK/Sources/Bridge/WXCoreBridge.h
+++ b/ios/sdk/WeexSDK/Sources/Bridge/WXCoreBridge.h
@@ -193,6 +193,10 @@ namespace WeexCore
 
 + (void)registerModules:(NSDictionary *)modules;
 
++ (void)registerComponentAffineType:(NSString *)type asType:(NSString *)baseType;
+
++ (BOOL)isComponentAffineType:(NSString *)type asType:(NSString *)baseType;
+
 @end
 
 #endif
diff --git a/ios/sdk/WeexSDK/Sources/Bridge/WXCoreBridge.mm b/ios/sdk/WeexSDK/Sources/Bridge/WXCoreBridge.mm
index 41c5d80..793601e 100644
--- a/ios/sdk/WeexSDK/Sources/Bridge/WXCoreBridge.mm
+++ b/ios/sdk/WeexSDK/Sources/Bridge/WXCoreBridge.mm
@@ -876,6 +876,16 @@ static WeexCore::ScriptBridge* jsBridge = nullptr;
     }
 }
 
++ (void)registerComponentAffineType:(NSString *)type asType:(NSString *)baseType
+{
+    WeexCore::RenderCreator::GetInstance()->RegisterAffineType([type UTF8String] ?: "", [baseType UTF8String] ?: "");
+}
+
++ (BOOL)isComponentAffineType:(NSString *)type asType:(NSString *)baseType
+{
+    return WeexCore::RenderCreator::GetInstance()->IsAffineType([type UTF8String] ?: "", [baseType UTF8String] ?: "");
+}
+
 + (void)setDefaultDimensionIntoRoot:(NSString*)pageId width:(CGFloat)width height:(CGFloat)height
                  isWidthWrapContent:(BOOL)isWidthWrapContent
                 isHeightWrapContent:(BOOL)isHeightWrapContent
diff --git a/ios/sdk/WeexSDK/Sources/Component/WXCellComponent.mm b/ios/sdk/WeexSDK/Sources/Component/WXCellComponent.mm
index 7d1cbf2..1a3b294 100644
--- a/ios/sdk/WeexSDK/Sources/Component/WXCellComponent.mm
+++ b/ios/sdk/WeexSDK/Sources/Component/WXCellComponent.mm
@@ -138,7 +138,7 @@
      For water-fall(aka UICollectionView), we must ignore left value generated by layout engine.
      */
     
-    if ([self.supercomponent.type isEqualToString:@"waterfall"]) {
+    if ([self.supercomponent _isAffineTypeAs:@"waterfall"]) {
         return !CGSizeEqualToSize(frame.size, _calculatedFrame.size);
     }
     else {
@@ -148,7 +148,7 @@
 
 - (void)_assignCalculatedFrame:(CGRect)frame
 {
-    if ([self.supercomponent.type isEqualToString:@"waterfall"]) {
+    if ([self.supercomponent _isAffineTypeAs:@"waterfall"]) {
         frame.origin = CGPointZero;
     }
     else {
diff --git a/ios/sdk/WeexSDK/Sources/Component/WXComponent_internal.h b/ios/sdk/WeexSDK/Sources/Component/WXComponent_internal.h
index f485a18..fc7658d 100644
--- a/ios/sdk/WeexSDK/Sources/Component/WXComponent_internal.h
+++ b/ios/sdk/WeexSDK/Sources/Component/WXComponent_internal.h
@@ -283,4 +283,6 @@ typedef id (^WXDataBindingBlock)(NSDictionary *data, BOOL *needUpdate);
 
 - (void)_buildViewHierarchyLazily;
 
+- (BOOL)_isAffineTypeAs:(NSString *)type;
+
 @end
diff --git a/ios/sdk/WeexSDK/Sources/Engine/WXSDKEngine.m b/ios/sdk/WeexSDK/Sources/Engine/WXSDKEngine.m
index be187db..b5d7e00 100644
--- a/ios/sdk/WeexSDK/Sources/Engine/WXSDKEngine.m
+++ b/ios/sdk/WeexSDK/Sources/Engine/WXSDKEngine.m
@@ -82,6 +82,17 @@
 
 # pragma mark Component Register
 
++ (void)_registerAffineTypes
+{
+    /* register weex core types that should match RenderList or RenderScroller.
+     "list" and "waterfall" must be registered before "scroller" because "WXListComponent" and "WXRecyclerComponent"
+     are both subclasses of "WXScrollerComponent".
+     */
+    [WXComponentFactory registerBaseType:@"list" withClass:NSClassFromString(@"WXListComponent")];
+    [WXComponentFactory registerBaseType:@"waterfall" withClass:NSClassFromString(@"WXRecyclerComponent")];
+    [WXComponentFactory registerBaseType:@"scroller" withClass:NSClassFromString(@"WXScrollerComponent")];
+}
+
 // register some default components when the engine initializes.
 + (void)_registerDefaultComponents
 {
@@ -117,6 +128,8 @@
     [self registerComponent:@"recycle-list" withClass:NSClassFromString(@"WXRecycleListComponent")];
     [self registerComponent:@"cell-slot" withClass:NSClassFromString(@"WXCellSlotComponent") withProperties: @{@"append":@"tree", @"isTemplate":@YES}];
     
+    // other non-default components should be checked with affine-base types.
+    [self _registerAffineTypes];
 }
 
 + (void)registerComponent:(NSString *)name withClass:(Class)clazz
diff --git a/ios/sdk/WeexSDK/Sources/Manager/WXComponentFactory.h b/ios/sdk/WeexSDK/Sources/Manager/WXComponentFactory.h
index 73b08e1..f9fe89e 100644
--- a/ios/sdk/WeexSDK/Sources/Manager/WXComponentFactory.h
+++ b/ios/sdk/WeexSDK/Sources/Manager/WXComponentFactory.h
@@ -32,6 +32,16 @@
 @interface WXComponentFactory : NSObject
 
 /**
+ * @abstract Register an affine base type to weex core. So that all subclasses of clazz will use this type to render.
+ *  For example: WXNestedListComponent is a subclass of WXListComponent and uses type of 'nested-list'.
+ *  It should be rendered using RenderList in weexcore.
+ *
+ * @param typeName weex core type identifier
+ * @param clazz The WXComponent subclass to register
+ */
++ (void)registerBaseType:(NSString *)typeName withClass:(Class)clazz;
+
+/**
  * @abstract Register a component for a given name
  *
  * @param name The component name to register;
diff --git a/ios/sdk/WeexSDK/Sources/Manager/WXComponentFactory.m b/ios/sdk/WeexSDK/Sources/Manager/WXComponentFactory.m
index 0101d7a..3b86e01 100644
--- a/ios/sdk/WeexSDK/Sources/Manager/WXComponentFactory.m
+++ b/ios/sdk/WeexSDK/Sources/Manager/WXComponentFactory.m
@@ -20,9 +20,21 @@
 #import "WXComponentFactory.h"
 #import "WXAssert.h"
 #import "WXLog.h"
-
+#import "WXCoreBridge.h"
+#import "WXComponent.h"
 #import <objc/runtime.h>
 
+@interface WXComponentBaseType : NSObject
+
+@property (nonatomic, strong) NSString* type;
+@property (nonatomic, strong) Class clazz;
+
+@end
+
+@implementation WXComponentBaseType
+
+@end
+
 @implementation WXComponentConfig
 
 - (instancetype)initWithName:(NSString *)name class:(NSString *)clazz pros:(NSDictionary *)pros
@@ -46,6 +58,7 @@
 
 @implementation WXComponentFactory
 {
+    NSMutableArray<WXComponentBaseType*> *_baseTypes;
     NSMutableDictionary *_componentConfigs;
     NSLock *_configLock;
 }
@@ -64,6 +77,7 @@
 - (instancetype)init
 {
     if(self = [super init]){
+        _baseTypes = [NSMutableArray array];
         _componentConfigs = [NSMutableDictionary dictionary];
         _configLock = [[NSLock alloc] init];
     }
@@ -87,6 +101,11 @@
     return [[self sharedInstance] configWithComponentName:name];
 }
 
++ (void)registerBaseType:(NSString *)typeName withClass:(Class)clazz
+{
+    [[self sharedInstance] registerBaseType:typeName withClass:clazz];
+}
+
 + (void)registerComponent:(NSString *)name withClass:(Class)clazz withPros:(NSDictionary *)pros
 {
     [[self sharedInstance] registerComponent:name withClass:clazz withPros:pros];
@@ -214,6 +233,38 @@
     return config;
 }
 
+- (void)registerBaseType:(NSString *)typeName withClass:(Class)clazz
+{
+    if ([typeName length] > 0 && clazz != Nil) {
+        WXComponentBaseType* typePair = [[WXComponentBaseType alloc] init];
+        typePair.type = typeName;
+        typePair.clazz = clazz;
+        [_baseTypes addObject:typePair];
+    }
+}
+
+- (void)registerAffineType:(NSString *)typeName withClass:(Class)clazz
+{
+    // iterates super classes of clazz and check if any super class matches registerd base types
+    if ([_baseTypes count] > 0 && [typeName length] > 0 && clazz != Nil) {
+        Class supercls = [clazz superclass];
+        while (supercls) {
+            if (supercls == [WXComponent class]) {
+                break;
+            }
+            
+            for (WXComponentBaseType* typePair in _baseTypes) {
+                if (supercls == typePair.clazz) {
+                    WXLogInfo(@"Type '%@' is registerd as affine type of '%@' because '%@' is subclass of '%@'.", typeName, typePair.type, clazz, supercls);
+                    [WXCoreBridge registerComponentAffineType:typeName asType:typePair.type];
+                    return; // done, use the first found affine type
+                }
+            }
+            supercls = [supercls superclass];
+        }
+    }
+}
+
 - (void)registerComponent:(NSString *)name withClass:(Class)clazz withPros:(NSDictionary *)pros
 {
     WXAssert(name && clazz, @"name or clazz must not be nil for registering component.");
@@ -230,7 +281,7 @@
     config = [[WXComponentConfig alloc] initWithName:name class:NSStringFromClass(clazz) pros:pros];
     [_componentConfigs setValue:config forKey:name];
     [config registerMethods];
-    
+    [self registerAffineType:name withClass:clazz];
     [_configLock unlock];
 }
 
@@ -248,6 +299,7 @@
         if(config){
             [_componentConfigs setValue:config forKey:name];
             [config registerMethods];
+            [self registerAffineType:name withClass:NSClassFromString(clazz)];
         }
     }
     [_configLock unlock];
diff --git a/ios/sdk/WeexSDK/Sources/Model/WXComponent.mm b/ios/sdk/WeexSDK/Sources/Model/WXComponent.mm
index 95ac414..43fda8b 100644
--- a/ios/sdk/WeexSDK/Sources/Model/WXComponent.mm
+++ b/ios/sdk/WeexSDK/Sources/Model/WXComponent.mm
@@ -493,6 +493,11 @@ static BOOL bNeedRemoveEvents = YES;
     }
 }
 
+- (BOOL)_isAffineTypeAs:(NSString *)type
+{
+    return [WXCoreBridge isComponentAffineType:_type asType:type];
+}
+
 - (CALayer *)layer
 {
     return _layer;
diff --git a/weex_core/Source/core/render/node/factory/render_creator.cpp b/weex_core/Source/core/render/node/factory/render_creator.cpp
index 8632110..0bfc8ee 100644
--- a/weex_core/Source/core/render/node/factory/render_creator.cpp
+++ b/weex_core/Source/core/render/node/factory/render_creator.cpp
@@ -31,22 +31,35 @@ namespace WeexCore {
 
 RenderCreator *RenderCreator::g_pInstance = nullptr;
 
-IRenderObject *RenderCreator::CreateRender(const std::string &type,
-                                           const std::string &ref) {
-  IRenderFactory *factory;
+IRenderFactory *RenderCreator::CreateFactory(const std::string &type) {
   if (type == kRenderText) {
-    factory = new RenderTextFactory();
+    return new RenderTextFactory();
   } else if (type == kRenderList || type == kRenderWaterfall ||
              type == kRenderRecycleList) {
-    factory = new RenderListFactory();
+    return new RenderListFactory();
   } else if (type == kRenderMask) {
-    factory = new RenderMaskFactory();
+    return new RenderMaskFactory();
   } else if (type == kRenderScroller) {
-    factory = new RenderScrollerFactory();
+    return new RenderScrollerFactory();
   } else if (type == kRenderAppBar) {
-    factory = new RenderAppBarFactory();
+    return new RenderAppBarFactory();
   } else {
-    factory = new RenderCommonFactory();
+    // search for affine types
+    auto findAffine = affineTypes_.find(type);
+    if (findAffine != affineTypes_.end()) {
+      return CreateFactory(findAffine->second);
+    }
+    else {
+      return new RenderCommonFactory();
+    }
+  }
+}
+  
+IRenderObject *RenderCreator::CreateRender(const std::string &type,
+                                           const std::string &ref) {
+  IRenderFactory *factory = CreateFactory(type);
+  if (factory == nullptr) {
+    return nullptr;
   }
 
   IRenderObject *render = factory->CreateRender();
@@ -55,4 +68,22 @@ IRenderObject *RenderCreator::CreateRender(const std::string &type,
   delete factory;
   return render;
 }
+  
+void RenderCreator::RegisterAffineType(const std::string &type, const std::string& asType) {
+  if (!type.empty() && !asType.empty()) {
+    affineTypes_[type] = asType;
+  }
+}
+  
+bool RenderCreator::IsAffineType(const std::string &type, const std::string& asType) {
+  if (type == asType) {
+    return true;
+  }
+  
+  auto findAffine = affineTypes_.find(type);
+  if (findAffine == affineTypes_.end()) {
+    return false;
+  }
+  return IsAffineType(findAffine->second, asType);
+}
 }  // namespace WeexCore
diff --git a/weex_core/Source/core/render/node/factory/render_creator.h b/weex_core/Source/core/render/node/factory/render_creator.h
index f5dddfc..b3775d1 100644
--- a/weex_core/Source/core/render/node/factory/render_creator.h
+++ b/weex_core/Source/core/render/node/factory/render_creator.h
@@ -20,10 +20,12 @@
 #define CORE_RENDER_NODE_FACTORY_RENDER_CREATOR_H_
 
 #include <string>
+#include <map>
 
 namespace WeexCore {
 
 class IRenderObject;
+class IRenderFactory;
 
 class RenderCreator {
  private:
@@ -51,10 +53,16 @@ class RenderCreator {
     return g_pInstance;
   }
 
+  IRenderFactory *CreateFactory(const std::string &type);
   IRenderObject *CreateRender(const std::string &type, const std::string &ref);
+  
+  void RegisterAffineType(const std::string &type, const std::string& asType);
+  bool IsAffineType(const std::string &type, const std::string& asType);
 
  private:
   static RenderCreator *g_pInstance;
+  
+  std::map<std::string, std::string> affineTypes_; // affineTypes_[A] = B means A is rendered like B
 };
 }  // namespace WeexCore
 
diff --git a/weex_core/Source/core/render/node/render_list.cpp b/weex_core/Source/core/render/node/render_list.cpp
index ec6284c..ed05abc 100644
--- a/weex_core/Source/core/render/node/render_list.cpp
+++ b/weex_core/Source/core/render/node/render_list.cpp
@@ -26,6 +26,7 @@
 #include "core/render/node/render_list.h"
 #include "core/render/node/render_object.h"
 #include "core/render/page/render_page.h"
+#include "core/render/node/factory/render_creator.h"
 
 namespace WeexCore {
 
@@ -261,7 +262,7 @@ int RenderList::AddRenderObject(int index, RenderObject *child) {
 
 void RenderList::AddRenderObjectWidth(RenderObject *child,
                                       const bool updating) {
-  if (type() == kRenderWaterfall || type() == kRenderRecycleList) {
+  if ((RenderCreator::GetInstance()->IsAffineType(type(), kRenderWaterfall)) || type() == kRenderRecycleList) {
     if (child->type() == kRenderHeader || child->type() == kRenderFooter) {
       child->ApplyStyle(WIDTH, to_string(this->available_width_), updating);
     } else if (child->is_sticky()) {