com.facebook.react.uimanager.ReactShadowNode.java Source code

Java tutorial

Introduction

Here is the source code for com.facebook.react.uimanager.ReactShadowNode.java

Source

/*
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * 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 androidx.annotation.Nullable;
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;

/**
 * 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 or Yoga nodes (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 all of its descendants will be "virtual" nodes. 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();

    /**
     * When constructing the native tree, nodes that return {@code true} will be treated as leaves.
     * Instead of adding this view's native children as subviews of it, they will be added as subviews
     * of an ancestor. In other words, this view wants to support native children but it cannot host
     * them itself (e.g. it isn't a ViewGroup).
     */
    boolean hoistNativeChildren();

    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(NativeViewHierarchyOptimizer nativeViewHierarchyOptimizer);

    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);

    int getRootTag();

    void setRootTag(int rootTag);

    void setViewClassName(String viewClassName);

    @Nullable
    T getParent();

    // Returns the node that is responsible for laying out this node.
    @Nullable
    T getLayoutParent();

    void setLayoutParent(@Nullable T layoutParent);

    /**
     * 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();

    void calculateLayout(float width, float height);

    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 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();

    NativeKind getNativeKind();

    int getTotalNativeChildren();

    boolean isDescendantOf(T ancestorNode);

    /**
     * @return a {@link String} representation of the Yoga hierarchy of this {@link ReactShadowNode}
     */
    String getHierarchyInfo();

    /*
     * 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.
     */
    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();

    void setMeasureSpecs(int widthMeasureSpec, int heightMeasureSpec);

    Integer getWidthMeasureSpec();

    Integer getHeightMeasureSpec();

    Iterable<? extends ReactShadowNode> calculateLayoutOnChildren();
}