Files
react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/ReactShadowNode.java
David Vacca d352c93487 Register ReactRootView into FabricUIManagerModule
Reviewed By: achen1

Differential Revision: D7043902

fbshipit-source-id: fecef5a019dadd3d2802baa20dd8a3711e566ed3
2018-02-22 23:06:19 -08:00

351 lines
11 KiB
Java

/**
* 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.
*/
package com.facebook.react.uimanager;
import com.facebook.yoga.YogaAlign;
import com.facebook.yoga.YogaBaselineFunction;
import com.facebook.yoga.YogaDirection;
import com.facebook.yoga.YogaDisplay;
import com.facebook.yoga.YogaFlexDirection;
import com.facebook.yoga.YogaJustify;
import com.facebook.yoga.YogaMeasureFunction;
import com.facebook.yoga.YogaNode;
import com.facebook.yoga.YogaOverflow;
import com.facebook.yoga.YogaPositionType;
import com.facebook.yoga.YogaValue;
import com.facebook.yoga.YogaWrap;
import javax.annotation.Nullable;
/**
* Base node class for representing virtual tree of React nodes. Shadow nodes are used primarily for
* layouting therefore it extends {@link YogaNode} to allow that. They also help with handling
* Common base subclass of {@link YogaNode} for all layout nodes for react-based view. It extends
* {@link YogaNode} by adding additional capabilities.
*
* <p>Instances of this class receive property updates from JS via @{link UIManagerModule}.
* Subclasses may use {@link #updateShadowNode} to persist some of the updated fields in the node
* instance that corresponds to a particular view type.
*
* <p>Subclasses of {@link ReactShadowNode} should be created only from {@link ViewManager} that
* corresponds to a certain type of native view. They will be updated and accessed only from JS
* thread. Subclasses of {@link ViewManager} may choose to use base class {@link ReactShadowNode} or
* custom subclass of it if necessary.
*
* <p>The primary use-case for {@link ReactShadowNode} nodes is to calculate layouting. Although
* this might be extended. For some examples please refer to ARTGroupYogaNode or ReactTextYogaNode.
*
* <p>This class allows for the native view hierarchy to not be an exact copy of the hierarchy
* received from JS by keeping track of both JS children (e.g. {@link #getChildCount()} and
* separately native children (e.g. {@link #getNativeChildCount()}). See {@link
* NativeViewHierarchyOptimizer} for more information.
*/
public interface ReactShadowNode<T extends ReactShadowNode> {
/**
* Nodes that return {@code true} will be treated as "virtual" nodes. That is, nodes that are not
* mapped into native views (e.g. nested text node). By default this method returns {@code false}.
*/
boolean isVirtual();
/**
* Nodes that return {@code true} will be treated as a root view for the virtual nodes tree. It
* means that {@link NativeViewHierarchyManager} will not try to perform {@code manageChildren}
* operation on such views. Good example is {@code InputText} view that may have children {@code
* Text} nodes but this whole hierarchy will be mapped to a single android {@link EditText} view.
*/
boolean isVirtualAnchor();
/**
* Nodes that return {@code true} will not manage (and and remove) child Yoga nodes. For example
* {@link ReactTextInputShadowNode} or {@link ReactTextShadowNode} have child nodes, which do not
* want Yoga to lay out, so in the eyes of Yoga it is a leaf node. Override this method in
* subclass to enforce this requirement.
*/
boolean isYogaLeafNode();
/**
* @return a mutable copy of the {@link ReactShadowNode}
*/
T mutableCopy();
String getViewClass();
boolean hasUpdates();
void markUpdateSeen();
void markUpdated();
boolean hasUnseenUpdates();
void dirty();
boolean isDirty();
void addChildAt(T child, int i);
T removeChildAt(int i);
int getChildCount();
T getChildAt(int i);
int indexOf(T child);
void removeAndDisposeAllChildren();
/**
* This method will be called by {@link UIManagerModule} once per batch, before calculating
* layout. Will be only called for nodes that are marked as updated with {@link #markUpdated()} or
* require layouting (marked with {@link #dirty()}).
*/
void onBeforeLayout();
void updateProperties(ReactStylesDiffMap props);
void onAfterUpdateTransaction();
/**
* Called after layout step at the end of the UI batch from {@link UIManagerModule}. May be used
* to enqueue additional ui operations for the native view. Will only be called on nodes marked as
* updated either with {@link #dirty()} or {@link #markUpdated()}.
*
* @param uiViewOperationQueue interface for enqueueing UI operations
*/
void onCollectExtraUpdates(UIViewOperationQueue uiViewOperationQueue);
/** @return true if layout (position or dimensions) changed, false otherwise. */
/* package */ boolean dispatchUpdates(
float absoluteX,
float absoluteY,
UIViewOperationQueue uiViewOperationQueue,
NativeViewHierarchyOptimizer nativeViewHierarchyOptimizer);
int getReactTag();
void setReactTag(int reactTag);
T getRootNode();
void setRootNode(T rootNode);
void setViewClassName(String viewClassName);
@Nullable
T getParent();
/**
* Get the {@link ThemedReactContext} associated with this {@link ReactShadowNode}. This will
* never change during the lifetime of a {@link ReactShadowNode} instance, but different instances
* can have different contexts; don't cache any calculations based on theme values globally.
*/
ThemedReactContext getThemedContext();
void setThemedContext(ThemedReactContext themedContext);
boolean shouldNotifyOnLayout();
void calculateLayout();
boolean hasNewLayout();
void markLayoutSeen();
/**
* Adds a child that the native view hierarchy will have at this index in the native view
* corresponding to this node.
*/
void addNativeChildAt(T child, int nativeIndex);
T removeNativeChildAt(int i);
void removeAllChildren();
void removeAllNativeChildren();
int getNativeChildCount();
int indexOfNativeChild(T nativeChild);
@Nullable
T getNativeParent();
/**
* Sets whether this node only contributes to the layout of its children without doing any drawing
* or functionality itself.
*/
void setIsLayoutOnly(boolean isLayoutOnly);
boolean isLayoutOnly();
int getTotalNativeChildren();
boolean isDescendantOf(T ancestorNode);
/*
* In some cases we need a way to specify some environmental data to shadow node
* to improve layout (or do something similar), so {@code localData} serves these needs.
* For example, any stateful embedded native views may benefit from this.
* Have in mind that this data is not supposed to interfere with the state of
* the shadow node.
* Please respect one-directional data flow of React.
* Use {@link UIManagerModule#setViewLocalData} to set this property
* (to provide local/environmental data for a shadow node) from the main thread.
*/
public void setLocalData(Object data);
/**
* Returns the offset within the native children owned by all layout-only nodes in the subtree
* rooted at this node for the given child. Put another way, this returns the number of native
* nodes (nodes not optimized out of the native tree) that are a) to the left (visited before by a
* DFS) of the given child in the subtree rooted at this node and b) do not have a native parent
* in this subtree (which means that the given child will be a sibling of theirs in the final
* native hierarchy since they'll get attached to the same native parent).
*
* <p>Basically, a view might have children that have been optimized away by {@link
* NativeViewHierarchyOptimizer}. Since those children will then add their native children to this
* view, we now have ranges of native children that correspond to single unoptimized children. The
* purpose of this method is to return the index within the native children that corresponds to
* the **start** of the native children that belong to the given child. Also, note that all of the
* children of a view might be optimized away, so this could return the same value for multiple
* different children.
*
* <p>Example. Native children are represented by (N) where N is the no-opt child they came from.
* If no children are optimized away it'd look like this: (0) (1) (2) (3) ... (n)
*
* <p>In case some children are optimized away, it might look like this: (0) (1) (1) (1) (3) (3)
* (4)
*
* <p>In that case: getNativeOffsetForChild(Node 0) => 0 getNativeOffsetForChild(Node 1) => 1
* getNativeOffsetForChild(Node 2) => 4 getNativeOffsetForChild(Node 3) => 4
*
* <p>getNativeOffsetForChild(Node 4) => 6
*/
int getNativeOffsetForChild(T child);
float getLayoutX();
float getLayoutY();
float getLayoutWidth();
float getLayoutHeight();
/** @return the x position of the corresponding view on the screen, rounded to pixels */
int getScreenX();
/** @return the y position of the corresponding view on the screen, rounded to pixels */
int getScreenY();
/** @return width corrected for rounding to pixels. */
int getScreenWidth();
/** @return height corrected for rounding to pixels. */
int getScreenHeight();
YogaDirection getLayoutDirection();
void setLayoutDirection(YogaDirection direction);
YogaValue getStyleWidth();
void setStyleWidth(float widthPx);
void setStyleWidthPercent(float percent);
void setStyleWidthAuto();
void setStyleMinWidth(float widthPx);
void setStyleMinWidthPercent(float percent);
void setStyleMaxWidth(float widthPx);
void setStyleMaxWidthPercent(float percent);
YogaValue getStyleHeight();
void setStyleHeight(float heightPx);
void setStyleHeightPercent(float percent);
void setStyleHeightAuto();
void setStyleMinHeight(float widthPx);
void setStyleMinHeightPercent(float percent);
void setStyleMaxHeight(float widthPx);
void setStyleMaxHeightPercent(float percent);
void setFlex(float flex);
void setFlexGrow(float flexGrow);
void setFlexShrink(float flexShrink);
void setFlexBasis(float flexBasis);
void setFlexBasisAuto();
void setFlexBasisPercent(float percent);
void setStyleAspectRatio(float aspectRatio);
void setFlexDirection(YogaFlexDirection flexDirection);
void setFlexWrap(YogaWrap wrap);
void setAlignSelf(YogaAlign alignSelf);
void setAlignItems(YogaAlign alignItems);
void setAlignContent(YogaAlign alignContent);
void setJustifyContent(YogaJustify justifyContent);
void setOverflow(YogaOverflow overflow);
void setDisplay(YogaDisplay display);
void setMargin(int spacingType, float margin);
void setMarginPercent(int spacingType, float percent);
void setMarginAuto(int spacingType);
float getPadding(int spacingType);
YogaValue getStylePadding(int spacingType);
void setDefaultPadding(int spacingType, float padding);
void setPadding(int spacingType, float padding);
void setPaddingPercent(int spacingType, float percent);
void setBorder(int spacingType, float borderWidth);
void setPosition(int spacingType, float position);
void setPositionPercent(int spacingType, float percent);
void setPositionType(YogaPositionType positionType);
void setShouldNotifyOnLayout(boolean shouldNotifyOnLayout);
void setBaselineFunction(YogaBaselineFunction baselineFunction);
void setMeasureFunction(YogaMeasureFunction measureFunction);
boolean isMeasureDefined();
void dispose();
}