/**
* 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.stetho;
import android.graphics.Rect;
import android.view.View;
import com.facebook.litho.DebugComponent;
import com.facebook.litho.LithoView;
import com.facebook.stetho.common.Accumulator;
import com.facebook.stetho.inspector.elements.AttributeAccumulator;
import com.facebook.stetho.inspector.elements.ChainedDescriptor;
import com.facebook.stetho.inspector.elements.ComputedStyleAccumulator;
import com.facebook.stetho.inspector.elements.Descriptor;
import com.facebook.stetho.inspector.elements.NodeType;
import com.facebook.stetho.inspector.elements.StyleAccumulator;
import com.facebook.stetho.inspector.elements.StyleRuleNameAccumulator;
import com.facebook.stetho.inspector.elements.android.HighlightableDescriptor;
/**
* Exposes LithoView to the stetho elements inspector. It ensures that the view children
* of a LithoView are not exposed (as they would if we used the ViewGroupDescriptor) as
* they are an implementation detail of the framework (ComponentHost etc.).
*/
public final class LithoViewDescriptor
extends Descriptor<LithoView>
implements ChainedDescriptor<LithoView>, HighlightableDescriptor<LithoView> {
private Descriptor<? super LithoView> mSuper;
@Override
public void setSuper(Descriptor<? super LithoView> superDescriptor) {
if (superDescriptor == null) {
throw new IllegalArgumentException("Super descriptor must not be null.");
}
if (superDescriptor != mSuper) {
if (mSuper != null) {
throw new IllegalStateException("Super descriptor has already been set.");
}
mSuper = superDescriptor;
}
}
@Override
public void hook(LithoView element) {
verifyThreadAccess();
mSuper.hook(element);
}
@Override
public void unhook(LithoView element) {
verifyThreadAccess();
mSuper.unhook(element);
}
@Override
public NodeType getNodeType(LithoView element) {
return mSuper.getNodeType(element);
}
@Override
public String getNodeName(LithoView element) {
return mSuper.getNodeName(element);
}
@Override
public String getLocalName(LithoView element) {
return mSuper.getLocalName(element);
}
@Override
public String getNodeValue(LithoView element) {
return mSuper.getNodeValue(element);
}
@Override
public void getAttributes(LithoView element, AttributeAccumulator attributes) {
mSuper.getAttributes(element, attributes);
}
@Override
public void setAttributesAsText(LithoView element, String text) {
mSuper.setAttributesAsText(element, text);
}
@Override
public void getStyleRuleNames(LithoView element, StyleRuleNameAccumulator accumulator) {
mSuper.getStyleRuleNames(element, accumulator);
}
@Override
public void getStyles(LithoView element, String ruleName, StyleAccumulator accumulator) {
mSuper.getStyles(element, ruleName, accumulator);
}
@Override
public void setStyle(LithoView element, String ruleName, String name, String value) {
mSuper.setStyle(element, ruleName, name, value);
}
@Override
public void getComputedStyles(LithoView element, ComputedStyleAccumulator accumulator) {
mSuper.getComputedStyles(element, accumulator);
}
@Override
public void getChildren(LithoView element, Accumulator<Object> children) {
// LithoView is a view group but we explicitly do not want to call mSuper.getChildren()
// here as we don't want to render children of LithoView and instead want to render
// the component hierarchy. View children of LithoView are of type ComponentHost which is
// an implementation detail of the Components framework.
final DebugComponent component = DebugComponent.getRootInstance(element);
if (component != null) {
children.store(component);
}
}
@Override
public View getViewAndBoundsForHighlighting(LithoView element, Rect bounds) {
return element;
}
@Override
public Object getElementToHighlightAtPosition(LithoView element, int x, int y, Rect bounds) {
final StethoHitTestAccumulator hitTestAccumulator = new StethoHitTestAccumulator(bounds, x, y);
getChildren(element, hitTestAccumulator);
final Object childElement = hitTestAccumulator.getElement();
if (childElement != null) {
return childElement;
} else {
return element;
}
}
}