Fabric: ScrollView: xplat part (shadow node, props, localdata, descriptor)

Summary:
All the props of a scrollview, and local data.
LocalData part is probably the most interesting: with it we precompute content size which we use inside native scrollview. Previously we rely on some assumptions like "ScrollView must have only one subview" instead, and that was not so efficient and straight-forward.

Reviewed By: fkgozali

Differential Revision: D7961869

fbshipit-source-id: fa070b8423a3e7739aeb62220e51213683e1a223
This commit is contained in:
Valentin Shergin 2018-05-17 20:03:39 -07:00 committed by Facebook Github Bot
parent e3a3999b75
commit bd99d3a6f4
8 changed files with 337 additions and 0 deletions

View File

@ -0,0 +1,24 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#pragma once
#include <fabric/core/ConcreteComponentDescriptor.h>
#include <fabric/scrollview/ScrollViewShadowNode.h>
namespace facebook {
namespace react {
class ScrollViewComponentDescriptor final: public ConcreteComponentDescriptor<ScrollViewShadowNode> {
public:
ComponentName getComponentName() const override {
return "ScrollView";
}
};
} // namespace react
} // namespace facebook

View File

@ -0,0 +1,36 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#include "ScrollViewLocalData.h"
#include <fabric/debug/debugStringConvertibleUtils.h>
#include <fabric/graphics/conversions.h>
namespace facebook {
namespace react {
ScrollViewLocalData::ScrollViewLocalData(Rect contentBoundingRect):
contentBoundingRect(contentBoundingRect) {}
Size ScrollViewLocalData::getContentSize() const {
return Size {contentBoundingRect.getMaxX(), contentBoundingRect.getMaxY()};
}
#pragma mark - DebugStringConvertible
std::string ScrollViewLocalData::getDebugName() const {
return "ScrollViewLocalData";
}
SharedDebugStringConvertibleList ScrollViewLocalData::getDebugProps() const {
return {
debugStringConvertibleItem("contentBoundingRect", contentBoundingRect)
};
}
} // namespace react
} // namespace facebook

View File

@ -0,0 +1,46 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#pragma once
#include <fabric/core/LocalData.h>
#include <fabric/graphics/Geometry.h>
namespace facebook {
namespace react {
class ScrollViewLocalData;
using SharedScrollViewLocalData = std::shared_ptr<const ScrollViewLocalData>;
/*
* LocalData for <ScrollView> component.
*/
class ScrollViewLocalData:
public LocalData {
public:
ScrollViewLocalData(Rect contentBoundingRect);
/*
* Compound size of all nested (first level only) components;
* is used for computing `contentSize`.
*/
const Rect contentBoundingRect;
#pragma mark - Getters
Size getContentSize() const;
#pragma mark - DebugStringConvertible
std::string getDebugName() const override;
SharedDebugStringConvertibleList getDebugProps() const override;
};
} // namespace react
} // namespace facebook

View File

@ -0,0 +1,84 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#include "ScrollViewProps.h"
#include <fabric/graphics/conversions.h>
#include <fabric/scrollview/conversions.h>
#include <fabric/debug/debugStringConvertibleUtils.h>
#include <fabric/core/propsConversions.h>
namespace facebook {
namespace react {
ScrollViewProps::ScrollViewProps(const ScrollViewProps &sourceProps, const RawProps &rawProps):
ViewProps(sourceProps, rawProps),
alwaysBounceHorizontal(convertRawProp(rawProps, "alwaysBounceHorizontal", sourceProps.alwaysBounceHorizontal)),
alwaysBounceVertical(convertRawProp(rawProps, "alwaysBounceVertical", sourceProps.alwaysBounceVertical)),
bounces(convertRawProp(rawProps, "bounces", sourceProps.bounces)),
bouncesZoom(convertRawProp(rawProps, "bouncesZoom", sourceProps.bouncesZoom)),
canCancelContentTouches(convertRawProp(rawProps, "canCancelContentTouches", sourceProps.canCancelContentTouches)),
centerContent(convertRawProp(rawProps, "centerContent", sourceProps.centerContent)),
automaticallyAdjustContentInsets(convertRawProp(rawProps, "automaticallyAdjustContentInsets", sourceProps.automaticallyAdjustContentInsets)),
decelerationRate(convertRawProp(rawProps, "decelerationRate", sourceProps.decelerationRate)),
directionalLockEnabled(convertRawProp(rawProps, "directionalLockEnabled", sourceProps.directionalLockEnabled)),
indicatorStyle(convertRawProp(rawProps, "indicatorStyle", sourceProps.indicatorStyle)),
keyboardDismissMode(convertRawProp(rawProps, "keyboardDismissMode", sourceProps.keyboardDismissMode)),
maximumZoomScale(convertRawProp(rawProps, "maximumZoomScale", sourceProps.maximumZoomScale)),
minimumZoomScale(convertRawProp(rawProps, "minimumZoomScale", sourceProps.minimumZoomScale)),
scrollEnabled(convertRawProp(rawProps, "scrollEnabled", sourceProps.scrollEnabled)),
pagingEnabled(convertRawProp(rawProps, "pagingEnabled", sourceProps.pagingEnabled)),
pinchGestureEnabled(convertRawProp(rawProps, "pinchGestureEnabled", sourceProps.pinchGestureEnabled)),
scrollsToTop(convertRawProp(rawProps, "scrollsToTop", sourceProps.scrollsToTop)),
showsHorizontalScrollIndicator(convertRawProp(rawProps, "showsHorizontalScrollIndicator", sourceProps.showsHorizontalScrollIndicator)),
showsVerticalScrollIndicator(convertRawProp(rawProps, "showsVerticalScrollIndicator", sourceProps.showsVerticalScrollIndicator)),
scrollEventThrottle(convertRawProp(rawProps, "scrollEventThrottle", sourceProps.scrollEventThrottle)),
zoomScale(convertRawProp(rawProps, "zoomScale", sourceProps.zoomScale)),
contentInset(convertRawProp(rawProps, "contentInset", sourceProps.contentInset)),
scrollIndicatorInsets(convertRawProp(rawProps, "scrollIndicatorInsets", sourceProps.scrollIndicatorInsets)),
snapToInterval(convertRawProp(rawProps, "snapToInterval", sourceProps.snapToInterval)),
snapToAlignment(convertRawProp(rawProps, "snapToAlignment", sourceProps.snapToAlignment)) {}
#pragma mark - DebugStringConvertible
SharedDebugStringConvertibleList ScrollViewProps::getDebugProps() const {
ScrollViewProps defaultScrollViewProps;
return
ViewProps::getDebugProps() +
SharedDebugStringConvertibleList {
debugStringConvertibleItem("alwaysBounceHorizontal", alwaysBounceHorizontal, defaultScrollViewProps.alwaysBounceHorizontal),
debugStringConvertibleItem("alwaysBounceVertical", alwaysBounceVertical, defaultScrollViewProps.alwaysBounceVertical),
debugStringConvertibleItem("bounces", bounces, defaultScrollViewProps.bounces),
debugStringConvertibleItem("bouncesZoom", bouncesZoom, defaultScrollViewProps.bouncesZoom),
debugStringConvertibleItem("canCancelContentTouches", canCancelContentTouches, defaultScrollViewProps.canCancelContentTouches),
debugStringConvertibleItem("centerContent", centerContent, defaultScrollViewProps.centerContent),
debugStringConvertibleItem("automaticallyAdjustContentInsets", automaticallyAdjustContentInsets, defaultScrollViewProps.automaticallyAdjustContentInsets),
debugStringConvertibleItem("decelerationRate", decelerationRate, defaultScrollViewProps.decelerationRate),
debugStringConvertibleItem("directionalLockEnabled", directionalLockEnabled, defaultScrollViewProps.directionalLockEnabled),
debugStringConvertibleItem("indicatorStyle", indicatorStyle, defaultScrollViewProps.indicatorStyle),
debugStringConvertibleItem("keyboardDismissMode", keyboardDismissMode, defaultScrollViewProps.keyboardDismissMode),
debugStringConvertibleItem("maximumZoomScale", maximumZoomScale, defaultScrollViewProps.maximumZoomScale),
debugStringConvertibleItem("minimumZoomScale", minimumZoomScale, defaultScrollViewProps.minimumZoomScale),
debugStringConvertibleItem("scrollEnabled", scrollEnabled, defaultScrollViewProps.scrollEnabled),
debugStringConvertibleItem("pagingEnabled", pagingEnabled, defaultScrollViewProps.pagingEnabled),
debugStringConvertibleItem("pinchGestureEnabled", pinchGestureEnabled, defaultScrollViewProps.pinchGestureEnabled),
debugStringConvertibleItem("scrollsToTop", scrollsToTop, defaultScrollViewProps.scrollsToTop),
debugStringConvertibleItem("showsHorizontalScrollIndicator", showsHorizontalScrollIndicator, defaultScrollViewProps.showsHorizontalScrollIndicator),
debugStringConvertibleItem("showsVerticalScrollIndicator", showsVerticalScrollIndicator, defaultScrollViewProps.showsVerticalScrollIndicator),
debugStringConvertibleItem("scrollEventThrottle", scrollEventThrottle, defaultScrollViewProps.scrollEventThrottle),
debugStringConvertibleItem("zoomScale", zoomScale, defaultScrollViewProps.zoomScale),
debugStringConvertibleItem("contentInset", contentInset, defaultScrollViewProps.contentInset),
debugStringConvertibleItem("scrollIndicatorInsets", scrollIndicatorInsets, defaultScrollViewProps.scrollIndicatorInsets),
debugStringConvertibleItem("snapToInterval", snapToInterval, defaultScrollViewProps.snapToInterval),
debugStringConvertibleItem("snapToAlignment", snapToAlignment, defaultScrollViewProps.snapToAlignment),
};
}
} // namespace react
} // namespace facebook

View File

@ -0,0 +1,59 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#pragma once
#include <fabric/scrollview/primitives.h>
#include <fabric/view/ViewProps.h>
namespace facebook {
namespace react {
// TODO (T28334063): Consider for codegen.
class ScrollViewProps final:
public ViewProps {
public:
ScrollViewProps() = default;
ScrollViewProps(const ScrollViewProps &sourceProps, const RawProps &rawProps);
#pragma mark - Props
const bool alwaysBounceHorizontal {true};
const bool alwaysBounceVertical {true};
const bool bounces {true};
const bool bouncesZoom {true};
const bool canCancelContentTouches {true};
const bool centerContent {false};
const bool automaticallyAdjustContentInsets {false};
const Float decelerationRate {0.998};
const bool directionalLockEnabled {false};
const ScrollViewIndicatorStyle indicatorStyle {ScrollViewIndicatorStyle::Default};
const ScrollViewKeyboardDismissMode keyboardDismissMode {ScrollViewKeyboardDismissMode::None};
const Float maximumZoomScale {1.0};
const Float minimumZoomScale {1.0};
const bool scrollEnabled {true};
const bool pagingEnabled {false};
const bool pinchGestureEnabled {true};
const bool scrollsToTop {true};
const bool showsHorizontalScrollIndicator {true};
const bool showsVerticalScrollIndicator {true};
const Float scrollEventThrottle {0};
const Float zoomScale {1.0};
const EdgeInsets contentInset {};
const EdgeInsets scrollIndicatorInsets {};
const int snapToInterval {0};
const ScrollViewSnapToAlignment snapToAlignment {ScrollViewSnapToAlignment::Start};
#pragma mark - DebugStringConvertible
SharedDebugStringConvertibleList getDebugProps() const override;
};
} // namespace react
} // namespace facebook

View File

@ -0,0 +1,41 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#include "ScrollViewShadowNode.h"
#include <fabric/core/LayoutMetrics.h>
#include "ScrollViewLocalData.h"
namespace facebook {
namespace react {
ComponentName ScrollViewShadowNode::getComponentName() const {
return ComponentName("ScrollView");
}
void ScrollViewShadowNode::updateLocalData() {
ensureUnsealed();
Rect contentBoundingRect;
for (auto &&childNode : getLayoutableChildNodes()) {
contentBoundingRect.unionInPlace(childNode->getLayoutMetrics().frame);
}
auto &&localData = std::make_shared<const ScrollViewLocalData>(contentBoundingRect);
setLocalData(localData);
}
#pragma mark - LayoutableShadowNode
void ScrollViewShadowNode::layout(LayoutContext layoutContext) {
ConcreteViewShadowNode<ScrollViewProps>::layout(layoutContext);
updateLocalData();
}
} // namespace react
} // namespace facebook

View File

@ -0,0 +1,45 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#pragma once
#include <memory>
#include <fabric/core/LayoutContext.h>
#include <fabric/scrollview/ScrollViewProps.h>
#include <fabric/view/ConcreteViewShadowNode.h>
namespace facebook {
namespace react {
class ScrollViewShadowNode;
using SharedScrollViewShadowNode = std::shared_ptr<const ScrollViewShadowNode>;
/*
* `ShadowNode` for <ScrollView> component.
*/
class ScrollViewShadowNode final:
public ConcreteViewShadowNode<ScrollViewProps> {
public:
using ConcreteViewShadowNode::ConcreteViewShadowNode;
ComponentName getComponentName() const override;
#pragma mark - LayoutableShadowNode
void layout(LayoutContext layoutContext) override;
private:
void updateLocalData();
};
} // namespace react
} // namespace facebook

View File

@ -54,6 +54,8 @@ rn_xplat_cxx_library(
react_native_xplat_target("fabric/debug:debug"),
react_native_xplat_target("fabric/text:text"),
react_native_xplat_target("fabric/view:view"),
react_native_xplat_target("fabric/scrollview:scrollview"),
react_native_xplat_target("fabric/text:text"),
],
)