/** * 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 java.util.Map; import android.graphics.Rect; import android.view.View; import com.facebook.litho.ComponentContext; import com.facebook.litho.ComponentsLogger; import com.facebook.litho.DebugComponent; import com.facebook.stetho.common.Accumulator; import com.facebook.stetho.inspector.elements.AbstractChainedDescriptor; import com.facebook.stetho.inspector.elements.StyleAccumulator; import com.facebook.stetho.inspector.elements.StyleRuleNameAccumulator; import com.facebook.stetho.inspector.elements.AttributeAccumulator; import com.facebook.stetho.inspector.elements.android.HighlightableDescriptor; import static com.facebook.litho.FrameworkLogEvents.EVENT_STETHO_INSPECT_COMPONENT; import static com.facebook.litho.FrameworkLogEvents.EVENT_STETHO_UPDATE_COMPONENT; public final class DebugComponentDescriptor extends AbstractChainedDescriptor<DebugComponent> implements HighlightableDescriptor<DebugComponent> { @Override protected String onGetNodeName(DebugComponent element) { return element.getName(); } @Override protected void onGetChildren(DebugComponent element, Accumulator<Object> children) { for (DebugComponent child : element.getChildComponents()) { children.store(child); } for (View child : element.getMountedViews()) { children.store(child); } } @Override protected void onGetAttributes(DebugComponent element, AttributeAccumulator attributes) { final String testKey = element.getTestKey(); if (testKey != null) { attributes.store("testKey", testKey); } final String key = element.getKey(); if (key != null) { attributes.store("key", key); } } @Override public View getViewAndBoundsForHighlighting(DebugComponent element, Rect bounds) { bounds.set(element.getBoundsInLithoView()); return element.getLithoView(); } @Override public Object getElementToHighlightAtPosition( DebugComponent 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; } } @Override protected void onGetStyleRuleNames( DebugComponent element, StyleRuleNameAccumulator accumulator) { if (!element.getState().isEmpty()) { accumulator.store("state", element.isLayoutNode()); } if (!element.getProps().isEmpty()) { accumulator.store("props", element.isLayoutNode()); } if (!element.getStyles().isEmpty()) { accumulator.store("layout", element.isLayoutNode()); } // This method is called once a node is inspected and not during tree creation like many of the // other lifecycle methods. logInspected(element.getContext()); } @Override protected void onGetStyles( DebugComponent element, String ruleName, StyleAccumulator accumulator) { if ("layout".equals(ruleName)) { final Map<String, String> styles = element.getStyles(); for (String key : styles.keySet()) { accumulator.store(key, styles.get(key), false); } } else if ("props".equals(ruleName)) { final Map<String, String> props = element.getProps(); for (String key : props.keySet()) { accumulator.store(key, props.get(key), false); } } else if ("state".equals(ruleName)) { final Map<String, String> state = element.getState(); for (String key : state.keySet()) { accumulator.store(key, state.get(key), false); } } } protected void onSetStyle( DebugComponent element, String ruleName, String name, String value) { if ("layout".equals(ruleName)) { element.setStyleOverride(name, value); logStyleUpdate(element.getContext()); } else if ("props".equals(ruleName)) { element.setPropOverride(name, value); logStyleUpdate(element.getContext()); } else if ("state".equals(ruleName)) { element.setStateOverride(name, value); logStyleUpdate(element.getContext()); } } private void logStyleUpdate(ComponentContext context) { final ComponentsLogger logger = context.getLogger(); if (logger != null) { logger.log(logger.newEvent(EVENT_STETHO_UPDATE_COMPONENT)); } } private void logInspected(ComponentContext context) { final ComponentsLogger logger = context.getLogger(); if (logger != null) { logger.log(logger.newEvent(EVENT_STETHO_INSPECT_COMPONENT)); } } }