/** * Copyright (c) 2017-present, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the * LICENSE file in the root directory of this source tree. An additional grant * of patent rights can be found in the PATENTS file in the same directory. */ package com.facebook.litho.testing; import com.facebook.litho.Column; import com.facebook.yoga.YogaAlign; import com.facebook.yoga.YogaFlexDirection; import java.util.ArrayList; import java.util.List; import android.support.annotation.AttrRes; import android.support.annotation.StyleRes; import android.support.v4.util.Pools; import com.facebook.litho.Component; import com.facebook.litho.ComponentLayout; import com.facebook.litho.ComponentLifecycle; import com.facebook.litho.ComponentContext; import com.facebook.litho.Layout; public class TestLayoutComponent extends ComponentLifecycle { private static final List<TestLayoutComponent> sInstances = new ArrayList<>(); private static final Pools.SynchronizedPool<Builder> mBuilderPool = new Pools.SynchronizedPool<>(2); private final boolean mCallsShouldUpdateOnMount; private final boolean mIsPureRender; private final boolean mHasMountSpecChild; private final boolean mIsDelegate; private synchronized static TestLayoutComponent get( boolean callsShouldUpdateOnMount, boolean isPureRender, boolean hasMountSpecChild, boolean isDelegate) { for (TestLayoutComponent lifecycle : sInstances) { if (lifecycle.mCallsShouldUpdateOnMount == callsShouldUpdateOnMount && lifecycle.mIsPureRender == isPureRender && lifecycle.mHasMountSpecChild == hasMountSpecChild && lifecycle.mIsDelegate == isDelegate) { return lifecycle; } } final TestLayoutComponent lifecycle = new TestLayoutComponent( callsShouldUpdateOnMount, isPureRender, hasMountSpecChild, isDelegate); sInstances.add(lifecycle); return lifecycle; } private TestLayoutComponent( boolean callsShouldUpdateOnMount, boolean isPureRender, boolean hasMountSpecChild, boolean isDelegate) { super(); mCallsShouldUpdateOnMount = callsShouldUpdateOnMount; mIsPureRender = isPureRender; mHasMountSpecChild = hasMountSpecChild; mIsDelegate = isDelegate; } @Override public boolean shouldUpdate(Component previous, Component next) { return !next.equals(previous); } @Override protected boolean callsShouldUpdateOnMount() { return mCallsShouldUpdateOnMount; } @Override protected boolean isPureRender() { return mIsPureRender; } @Override protected ComponentLayout onCreateLayout(ComponentContext c, Component _stateObject) { super.onCreateLayout(c, _stateObject); final Component<?> mountSpecComponent = TestDrawableComponent.create(c, false, true, true, false, false).build(); if (mIsDelegate) { return Layout.create(c, mountSpecComponent).build(); } ComponentLayout.ContainerBuilder containerBuilder = Column.create(c); if (mHasMountSpecChild) { containerBuilder.child(mountSpecComponent); } return containerBuilder.build(); } @Override public MountType getMountType() { return MountType.NONE; } public static Builder create( ComponentContext context, @AttrRes int defStyleAttr, @StyleRes int defStyleRes) { return create(context, defStyleAttr, defStyleRes, true, true, false, false); } public static Builder create( ComponentContext context, @AttrRes int defStyleAttr, @StyleRes int defStyleRes, boolean callsShouldUpdateOnMount, boolean isPureRender, boolean hasMountSpecChild, boolean isDelegate) { return newBuilder( context, defStyleAttr, defStyleRes, new State(callsShouldUpdateOnMount, isPureRender, hasMountSpecChild, isDelegate)); } public static Builder create(ComponentContext context) { return create(context, 0, 0, true, true, false, false); } public static Builder create( ComponentContext context, boolean callsShouldUpdateOnMount, boolean isPureRender) { return create(context, 0, 0, callsShouldUpdateOnMount, isPureRender, false, false); } private static Builder newBuilder( ComponentContext context, @AttrRes int defStyleAttr, @StyleRes int defStyleRes, State state) { Builder builder = mBuilderPool.acquire(); if (builder == null) { builder = new Builder(); } builder.init(context, defStyleAttr, defStyleRes, state); return builder; } public static class State extends TestComponent<TestLayoutComponent> implements Cloneable { private State( boolean callsShouldUpdateOnMount, boolean isPureRender, boolean hasMountSpecChild, boolean isDelegate) { super(get(callsShouldUpdateOnMount, isPureRender, hasMountSpecChild, isDelegate)); } @Override public int hashCode() { return super.hashCode(); } @Override public boolean equals(Object o) { if (o == null) { return false; } if (!super.equals(o)) { return false; } if (o instanceof State) { return true; } return false; } } public static class Builder extends com.facebook.litho.Component.Builder<TestLayoutComponent> { State mState; private void init( ComponentContext context, @AttrRes int defStyleAttr, @StyleRes int defStyleRes, State state) { super.init(context, defStyleAttr, defStyleRes, state); mState = state; } public Builder unique() { mState.mIsUnique = true; return this; } @Override public Builder key(String key) { super.setKey(key); return this; } @Override public TestComponent<TestLayoutComponent> build() { State state = mState; release(); return state; } @Override protected void release() { super.release(); mState = null; mBuilderPool.release(this); } } }