/**
* 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 java.util.ArrayList;
import java.util.List;
import android.support.annotation.AttrRes;
import android.support.annotation.StyleRes;
import android.support.v4.util.Pools;
import android.view.View;
import com.facebook.litho.Component;
import com.facebook.litho.ComponentLayout;
import com.facebook.litho.ComponentLifecycle;
import com.facebook.litho.ComponentContext;
import com.facebook.litho.Size;
import com.facebook.litho.SizeSpec;
public class TestViewComponent extends ComponentLifecycle {
private static final List<TestViewComponent> 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 mCanMeasure;
private final boolean mCanMountIncrementally;
private synchronized static TestViewComponent get(
boolean callsShouldUpdateOnMount,
boolean isPureRender,
boolean canMeasure,
boolean canMountIncrementally) {
for (TestViewComponent lifecycle : sInstances) {
if (lifecycle.mCallsShouldUpdateOnMount == callsShouldUpdateOnMount &&
lifecycle.mIsPureRender == isPureRender &&
lifecycle.mCanMeasure == canMeasure &&
lifecycle.mCanMountIncrementally == canMountIncrementally) {
return lifecycle;
}
}
final TestViewComponent lifecycle = new TestViewComponent(
callsShouldUpdateOnMount,
isPureRender,
canMeasure,
canMountIncrementally);
sInstances.add(lifecycle);
return lifecycle;
}
private TestViewComponent(
boolean callsShouldUpdateOnMount,
boolean isPureRender,
boolean canMeasure,
boolean canMountIncrementally) {
super();
mCallsShouldUpdateOnMount = callsShouldUpdateOnMount;
mIsPureRender = isPureRender;
mCanMeasure = canMeasure;
mCanMountIncrementally = canMountIncrementally;
}
@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 boolean canMountIncrementally() {
return mCanMountIncrementally;
}
@Override
protected Object onCreateMountContent(ComponentContext c) {
if (c instanceof TestComponentContextWithView) {
return ((TestComponentContextWithView) c).getTestView();
}
return new View(c);
}
@Override
protected void onMount(ComponentContext c, Object convertView, Component _stateObject) {
State state = (State) _stateObject;
state.onMountCalled();
}
@Override
protected void onUnmount(ComponentContext c, Object mountedContent, Component<?> component) {
State state = (State) component;
state.onUnmountCalled();
}
@Override
protected boolean canMeasure() {
return mCanMeasure;
}
@Override
protected void onMeasure(
ComponentContext c,
ComponentLayout layout,
int widthSpec,
int heightSpec,
Size size,
Component<?> component) {
int width = SizeSpec.getSize(widthSpec);
int height = SizeSpec.getSize(heightSpec);
size.height = height;
size.width = width;
State state = (State) component;
state.onMeasureCalled();
}
@Override
protected void onBoundsDefined(
ComponentContext c,
ComponentLayout layout,
Component<?> component) {
State state = (State) component;
state.onDefineBoundsCalled();
}
@Override
protected void onBind(ComponentContext c, Object mountedContent, Component<?> component) {
State state = (State) component;
state.onBindCalled();
}
@Override
protected void onUnbind(ComponentContext c, Object mountedContent, Component<?> component) {
State state = (State) component;
state.onUnbindCalled();
}
@Override
public MountType getMountType() {
return MountType.VIEW;
}
public static Builder create(
ComponentContext context,
@AttrRes int defStyleAttr,
@StyleRes int defStyleRes) {
return create(context, defStyleAttr, defStyleRes, true, true, true, true);
}
public static Builder create(
ComponentContext context,
@AttrRes int defStyleAttr,
@StyleRes int defStyleRes,
boolean callsShouldUpdateOnMount,
boolean isPureRender,
boolean canMeasure,
boolean canMountIncrementally) {
return newBuilder(
context,
defStyleAttr,
defStyleRes,
new State(callsShouldUpdateOnMount, isPureRender, canMeasure, canMountIncrementally));
}
public static Builder create(ComponentContext context) {
return create(context, 0, 0, true, true, true, true);
}
public static Builder create(
ComponentContext context,
boolean callsShouldUpdateOnMount,
boolean isPureRender,
boolean canMeasure,
boolean canMountIncrementally) {
return create(
context,
0,
0,
callsShouldUpdateOnMount,
isPureRender,
canMeasure,
canMountIncrementally);
}
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;
}
private static class State extends TestComponent<TestViewComponent> implements Cloneable {
private State(
boolean callsShouldUpdateOnMount,
boolean isPureRender,
boolean canMeasure,
boolean canMountIncrementally) {
super(get(callsShouldUpdateOnMount, isPureRender, canMeasure, canMountIncrementally));
}
@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<TestViewComponent> {
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 TestComponent<TestViewComponent> build() {
State state = mState;
release();
return state;
}
@Override
protected void release() {
super.release();
mState = null;
mBuilderPool.release(this);
}
public Builder key(String key) {
super.setKey(key);
return this;
}
}
}