/** * Marks root node as updated to trigger a StateBuilder pass to collect DrawCommands for the node * tree. Use it when FlatShadowNode is updated but doesn't require a layout pass (e.g. background * color is changed). */ protected final void invalidate() { FlatShadowNode node = this; while (true) { if (node.mountsToView()) { if (node.mIsUpdated) { // already updated return; } node.mIsUpdated = true; } ReactShadowNode parent = node.getParent(); if (parent == null) { // not attached to a hierarchy yet return; } node = (FlatShadowNode) parent; } }
@Override protected ReactShadowNode createRootShadowNode() { if (mRCTImageViewManager != null) { // This is not the best place to initialize DraweeRequestHelper, but order of module // initialization is undefined, and this is pretty much the earliest when we are guarantied // that Fresco is initalized and DraweeControllerBuilder can be queried. This also happens // relatively rarely to have any performance considerations. mReactContext.getNativeModule(FrescoModule.class); // initialize Fresco DraweeRequestHelper.setDraweeControllerBuilder( mRCTImageViewManager.getDraweeControllerBuilder()); mRCTImageViewManager = null; } ReactShadowNode node = new FlatRootShadowNode(); I18nUtil sharedI18nUtilInstance = I18nUtil.getInstance(); if (sharedI18nUtilInstance.isRTL(mReactContext)) { node.setLayoutDirection(YogaDirection.RTL); } return node; }
@Override protected void handleCreateView( ReactShadowNode cssNode, int rootViewTag, @Nullable ReactStylesDiffMap styles) { if (cssNode instanceof FlatShadowNode) { FlatShadowNode node = (FlatShadowNode) cssNode; if (styles != null) { node.handleUpdateProperties(styles); } if (node.mountsToView()) { mStateBuilder.enqueueCreateOrUpdateView(node, styles); } } else { super.handleCreateView(cssNode, rootViewTag, styles); } }
@Override protected void handleUpdateView( ReactShadowNode cssNode, String className, ReactStylesDiffMap styles) { if (cssNode instanceof FlatShadowNode) { FlatShadowNode node = (FlatShadowNode) cssNode; node.handleUpdateProperties(styles); if (node.mountsToView()) { mStateBuilder.enqueueCreateOrUpdateView(node, styles); } } else { super.handleUpdateView(cssNode, className, styles); } }
@Override public void manageChildren( int viewTag, @Nullable ReadableArray moveFrom, @Nullable ReadableArray moveTo, @Nullable ReadableArray addChildTags, @Nullable ReadableArray addAtIndices, @Nullable ReadableArray removeFrom) { ReactShadowNode parentNode = resolveShadowNode(viewTag); // moveFrom and removeFrom are defined in original order before any mutations. removeChildren(parentNode, moveFrom, moveTo, removeFrom); // moveTo and addAtIndices are defined in final order after all the mutations applied. addChildren(parentNode, addChildTags, addAtIndices); }
@Override public void setJSResponder(int possiblyVirtualReactTag, boolean blockNativeResponder) { ReactShadowNode node = resolveShadowNode(possiblyVirtualReactTag); while (node.isVirtual()) { node = node.getParent(); } int tag = node.getReactTag(); // if the node in question doesn't mount to a View, find the first parent that does mount to // a View. without this, we'll crash when we try to set the JSResponder, since part of that // is to find the parent view and ask it to not intercept touch events. while (node instanceof FlatShadowNode && !((FlatShadowNode) node).mountsToView()) { node = node.getParent(); } FlatUIViewOperationQueue operationsQueue = mStateBuilder.getOperationsQueue(); operationsQueue.enqueueSetJSResponder( node == null ? tag : node.getReactTag(), possiblyVirtualReactTag, blockNativeResponder); }
/** * We need to set the styleWidth and styleHeight of the one child (represented by the <View/> * within the <RCTModalHostView/> in Modal.js. This needs to fill the entire window. */ @Override @TargetApi(16) public void addChildAt(ReactShadowNode child, int i) { super.addChildAt(child, i); Context context = getThemedContext(); WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); Display display = wm.getDefaultDisplay(); // getCurrentSizeRange will return the min and max width and height that the window can be display.getCurrentSizeRange(mMinPoint, mMaxPoint); int width, height; int rotation = display.getRotation(); if (rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_180) { // If we are vertical the width value comes from min width and height comes from max height width = mMinPoint.x; height = mMaxPoint.y; } else { // If we are horizontal the width value comes from max width and height comes from min height width = mMaxPoint.x; height = mMinPoint.y; } child.setStyleWidth(width); child.setStyleHeight(height); }
NativeViewWrapper(ViewManager viewManager) { ReactShadowNode reactShadowNode = viewManager.createShadowNodeInstance(); if (reactShadowNode instanceof YogaMeasureFunction) { mReactShadowNode = reactShadowNode; setMeasureFunction((YogaMeasureFunction) reactShadowNode); } else { mReactShadowNode = null; } if (viewManager instanceof ViewGroupManager) { ViewGroupManager viewGroupManager = (ViewGroupManager) viewManager; mNeedsCustomLayoutForChildren = viewGroupManager.needsCustomLayoutForChildren(); mForceMountGrandChildrenToView = viewGroupManager.shouldPromoteGrandchildren(); } else { mNeedsCustomLayoutForChildren = false; } forceMountToView(); forceMountChildrenToView(); }
@android.support.annotation.Nullable GroupShadowNode getTextRoot() { VirtualNode node = this; if (mTextRoot == null) { while (node != null) { if (node instanceof GroupShadowNode && ((GroupShadowNode) node).getGlyphContext() != null) { mTextRoot = (GroupShadowNode)node; break; } ReactShadowNode parent = node.getParent(); if (!(parent instanceof VirtualNode)) { node = null; } else { node = (VirtualNode)parent; } } } return mTextRoot; }
SvgViewShadowNode getSvgShadowNode() { if (mSvgShadowNode != null) { return mSvgShadowNode; } ReactShadowNode parent = getParent(); if (parent instanceof SvgViewShadowNode) { mSvgShadowNode = (SvgViewShadowNode)parent; } else if (parent instanceof VirtualNode) { mSvgShadowNode = ((VirtualNode) parent).getSvgShadowNode(); } else { FLog.e(ReactConstants.TAG, "RNSVG: " + getClass().getName() + " should be descendant of a SvgViewShadow."); } return mSvgShadowNode; }
AlignmentBaseline getAlignmentBaseline() { if (mAlignmentBaseline == null) { ReactShadowNode parent = this.getParent(); while (parent != null) { if (parent instanceof TextShadowNode) { TextShadowNode node = (TextShadowNode)parent; final AlignmentBaseline baseline = node.mAlignmentBaseline; if (baseline != null) { mAlignmentBaseline = baseline; return baseline; } } parent = parent.getParent(); } } if (mAlignmentBaseline == null) { mAlignmentBaseline = AlignmentBaseline.baseline; } return mAlignmentBaseline; }
String getBaselineShift() { if (mBaselineShift == null) { ReactShadowNode parent = this.getParent(); while (parent != null) { if (parent instanceof TextShadowNode) { TextShadowNode node = (TextShadowNode)parent; final String baselineShift = node.mBaselineShift; if (baselineShift != null) { mBaselineShift = baselineShift; return baselineShift; } } parent = parent.getParent(); } } return mBaselineShift; }
final void forceMountChildrenToView() { if (mForceMountChildrenToView) { return; } mForceMountChildrenToView = true; for (int i = 0, childCount = getChildCount(); i != childCount; ++i) { ReactShadowNode child = getChildAt(i); if (child instanceof FlatShadowNode) { ((FlatShadowNode) child).forceMountToView(); } } }
@Override public void addChildAt(ReactShadowNode child, int i) { super.addChildAt(child, i); if (mForceMountChildrenToView && child instanceof FlatShadowNode) { ((FlatShadowNode) child).forceMountToView(); } }
@Override protected ReactShadowNode createShadowNode(String className) { ReactShadowNode cssNode = super.createShadowNode(className); if (cssNode instanceof FlatShadowNode || cssNode.isVirtual()) { return cssNode; } ViewManager viewManager = resolveViewManager(className); return new NativeViewWrapper(viewManager); }
@Override public void setChildren( int viewTag, ReadableArray children) { ReactShadowNode parentNode = resolveShadowNode(viewTag); for (int i = 0; i < children.size(); i++) { ReactShadowNode addToChild = resolveShadowNode(children.getInt(i)); addChildAt(parentNode, addToChild, i, i - 1); } }
private void dropNativeViews(ReactShadowNode child, ReactShadowNode parentNode) { if (child instanceof FlatShadowNode) { FlatShadowNode node = (FlatShadowNode) child; if (node.mountsToView() && node.isBackingViewCreated()) { int tag = -1; // this tag is used to remove the reference to this dropping view if it it's clipped. // we need to figure out the correct "view parent" tag to do this. note that this is // not necessarily getParent().getReactTag(), since getParent() may represent something // that's not a View - we need to find the first View (what would represent // view.getParent() on the ui thread), which is what this code is finding. ReactShadowNode tmpNode = parentNode; while (tmpNode != null) { if (tmpNode instanceof FlatShadowNode) { FlatShadowNode flatTmpNode = (FlatShadowNode) tmpNode; if (flatTmpNode.mountsToView() && flatTmpNode.isBackingViewCreated() && flatTmpNode.getParent() != null) { tag = flatTmpNode.getReactTag(); break; } } tmpNode = tmpNode.getParent(); } // this will recursively drop all subviews mStateBuilder.dropView(node, tag); return; } } for (int i = 0, childCount = child.getChildCount(); i != childCount; ++i) { dropNativeViews(child.getChildAt(i), child); } }
/** * Removes a child from parent, verifying that we are removing in descending order. */ private static ReactShadowNode removeChildAt( ReactShadowNode parentNode, int index, int prevIndex) { if (index >= prevIndex) { throw new RuntimeException( "Invariant failure, needs sorting! " + index + " >= " + prevIndex); } return parentNode.removeChildAt(index); }
/** * Adds a child to parent, verifying that we are adding in ascending order. */ private static void addChildAt( ReactShadowNode parentNode, ReactShadowNode childNode, int index, int prevIndex) { if (index <= prevIndex) { throw new RuntimeException( "Invariant failure, needs sorting! " + index + " <= " + prevIndex); } parentNode.addChildAt(childNode, index); }
@Override protected void applyUpdatesRecursive( ReactShadowNode cssNode, float absoluteX, float absoluteY) { mStateBuilder.applyUpdates((FlatRootShadowNode) cssNode); }
private void markChildrenUpdatesSeen(ReactShadowNode shadowNode) { for (int i = 0; i < shadowNode.getChildCount(); i++) { ReactShadowNode child = shadowNode.getChildAt(i); child.markUpdateSeen(); markChildrenUpdatesSeen(child); } }
/** * Propagates changes up to RCTText without dirtying current node. */ protected void notifyChanged(boolean shouldRemeasure) { ReactShadowNode parent = getParent(); if (parent instanceof FlatTextShadowNode) { ((FlatTextShadowNode) parent).notifyChanged(shouldRemeasure); } }
@Override public void addChildAt(ReactShadowNode child, int i) { super.addChildAt(child, i); if (mForceMountGrandChildrenToView && child instanceof FlatShadowNode) { ((FlatShadowNode) child).forceMountChildrenToView(); } }
@Override public ReactShadowNode createShadowNodeInstance() { if (CLASS_GROUP.equals(mClassName)) { return new ARTGroupShadowNode(); } else if (CLASS_SHAPE.equals(mClassName)) { return new ARTShapeShadowNode(); } else if (CLASS_TEXT.equals(mClassName)) { return new ARTTextShadowNode(); } else { throw new IllegalStateException("Unexpected type " + mClassName); } }
@Override public Class<? extends ReactShadowNode> getShadowNodeClass() { if (CLASS_GROUP.equals(mClassName)) { return ARTGroupShadowNode.class; } else if (CLASS_SHAPE.equals(mClassName)) { return ARTShapeShadowNode.class; } else if (CLASS_TEXT.equals(mClassName)) { return ARTTextShadowNode.class; } else { throw new IllegalStateException("Unexpected type " + mClassName); } }
/** * We need to set the styleWidth and styleHeight of the one child (represented by the <View/> * within the <RCTModalHostView/> in Modal.js. This needs to fill the entire window. */ @Override public void addChildAt(ReactShadowNode child, int i) { super.addChildAt(child, i); Point modalSize = ModalHostHelper.getModalHostSize(getThemedContext()); child.setStyleWidth(modalSize.x); child.setStyleHeight(modalSize.y); }