com.taobao.weex.devtools.inspector.protocol.module.CSS.java Source code

Java tutorial

Introduction

Here is the source code for com.taobao.weex.devtools.inspector.protocol.module.CSS.java

Source

/*
 * Copyright (c) 2014-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.taobao.weex.devtools.inspector.protocol.module;

import com.taobao.weex.devtools.common.ListUtil;
import com.taobao.weex.devtools.common.LogUtil;
import com.taobao.weex.devtools.common.Util;
import com.taobao.weex.devtools.inspector.elements.Document;
import com.taobao.weex.devtools.inspector.elements.Origin;
import com.taobao.weex.devtools.inspector.elements.StyleAccumulator;
import com.taobao.weex.devtools.inspector.elements.W3CStyleConstants;
import com.taobao.weex.devtools.inspector.helper.ChromePeerManager;
import com.taobao.weex.devtools.inspector.helper.PeersRegisteredListener;
import com.taobao.weex.devtools.inspector.jsonrpc.JsonRpcPeer;
import com.taobao.weex.devtools.inspector.jsonrpc.JsonRpcResult;
import com.taobao.weex.devtools.inspector.protocol.ChromeDevtoolsDomain;
import com.taobao.weex.devtools.inspector.protocol.ChromeDevtoolsMethod;
import com.taobao.weex.devtools.json.ObjectMapper;
import com.taobao.weex.devtools.json.annotation.JsonProperty;

import org.json.JSONObject;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class CSS implements ChromeDevtoolsDomain {
    private final ChromePeerManager mPeerManager;
    private final Document mDocument;
    private final ObjectMapper mObjectMapper;

    public CSS(Document document) {
        mDocument = Util.throwIfNull(document);
        mObjectMapper = new ObjectMapper();
        mPeerManager = new ChromePeerManager();
        mPeerManager.setListener(new PeerManagerListener());
    }

    @ChromeDevtoolsMethod
    public void enable(JsonRpcPeer peer, JSONObject params) {
    }

    @ChromeDevtoolsMethod
    public void disable(JsonRpcPeer peer, JSONObject params) {
    }

    @ChromeDevtoolsMethod
    public JsonRpcResult getComputedStyleForNode(JsonRpcPeer peer, JSONObject params) {
        final GetComputedStyleForNodeRequest request = mObjectMapper.convertValue(params,
                GetComputedStyleForNodeRequest.class);

        final GetComputedStyleForNodeResult result = new GetComputedStyleForNodeResult();
        result.computedStyle = new ArrayList<>();

        mDocument.postAndWait(new Runnable() {
            @Override
            public void run() {
                Object element = mDocument.getElementForNodeId(request.nodeId);

                if (element == null) {
                    LogUtil.e("Tried to get the style of an element that does not exist, using nodeid="
                            + request.nodeId);

                    return;
                }

                // fix devtools not show the box
                mockStyleProperty(result.computedStyle, sProperties);
                mDocument.getElementStyles(element, new StyleAccumulator() {
                    @Override
                    public void store(String name, String value, boolean isDefault) {
                        if (!isDefault) {
                            CSSComputedStyleProperty property = new CSSComputedStyleProperty();
                            if (!name.startsWith("v-")) {
                                property.name = name;
                                property.value = value;
                                result.computedStyle.add(property);
                            }
                        }
                    }
                });
            }
        });

        return result;
    }

    private static final HashMap<String, String> sProperties = new HashMap<String, String>();

    static {
        sProperties.put(W3CStyleConstants.WIDTH, "");
        sProperties.put(W3CStyleConstants.HEIGHT, "");

        sProperties.put(W3CStyleConstants.PADDING_LEFT, "");
        sProperties.put(W3CStyleConstants.PADDING_TOP, "");
        sProperties.put(W3CStyleConstants.PADDING_RIGHT, "");
        sProperties.put(W3CStyleConstants.PADDING_BOTTOM, "");

        sProperties.put(W3CStyleConstants.BORDER_LEFT_WIDTH, "");
        sProperties.put(W3CStyleConstants.BORDER_TOP_WIDTH, "");
        sProperties.put(W3CStyleConstants.BORDER_RIGHT_WIDTH, "");
        sProperties.put(W3CStyleConstants.BORDER_BOTTOM_WIDTH, "");

        sProperties.put(W3CStyleConstants.MARGIN_LEFT, "");
        sProperties.put(W3CStyleConstants.MARGIN_TOP, "");
        sProperties.put(W3CStyleConstants.MARGIN_RIGHT, "");
        sProperties.put(W3CStyleConstants.MARGIN_BOTTOM, "");

        sProperties.put(W3CStyleConstants.LEFT, "");
        sProperties.put(W3CStyleConstants.TOP, "");
        sProperties.put(W3CStyleConstants.RIGHT, "");
        sProperties.put(W3CStyleConstants.BOTTOM, "");
    }

    private void mockStyleProperty(List<CSSComputedStyleProperty> computedStyle,
            HashMap<String, String> properties) {
        for (Map.Entry<String, String> entry : properties.entrySet()) {
            addStyleProperty(computedStyle, entry.getKey(), entry.getValue());
        }
    }

    private void addStyleProperty(List<CSSComputedStyleProperty> computedStyle, String name, String value) {
        CSSComputedStyleProperty property = new CSSComputedStyleProperty();
        property.name = name;
        property.value = value;
        computedStyle.add(property);
    }

    @ChromeDevtoolsMethod
    public JsonRpcResult getMatchedStylesForNode(JsonRpcPeer peer, JSONObject params) {
        final GetMatchedStylesForNodeRequest request = mObjectMapper.convertValue(params,
                GetMatchedStylesForNodeRequest.class);

        final GetMatchedStylesForNodeResult result = new GetMatchedStylesForNodeResult();
        List<RuleMatch> matches = new ArrayList<>();
        final RuleMatch localMatch = new RuleMatch();
        initMatch(localMatch, "local");
        matches.add(localMatch);
        final RuleMatch virtualMatch = new RuleMatch();
        if (!DOM.isNativeMode()) {
            initMatch(virtualMatch, "virtual");
            matches.add(virtualMatch);
        }

        result.matchedCSSRules = matches;// ListUtil.newImmutableList(match);

        mDocument.postAndWait(new Runnable() {
            @Override
            public void run() {
                Object elementForNodeId = mDocument.getElementForNodeId(request.nodeId);

                if (elementForNodeId == null) {
                    LogUtil.w("Failed to get style of an element that does not exist, nodeid=" + request.nodeId);
                    return;
                }

                mDocument.getElementStyles(elementForNodeId, new StyleAccumulator() {
                    @Override
                    public void store(String name, String value, boolean isDefault) {
                        if (!isDefault) {
                            CSSProperty property = new CSSProperty();
                            if (!name.startsWith(W3CStyleConstants.V_PREFIX)) {
                                property.name = name;
                                property.value = value;
                                localMatch.rule.style.cssProperties.add(property);
                            } else {
                                if (!DOM.isNativeMode()) {
                                    CSSProperty virtualProperty = new CSSProperty();
                                    virtualProperty.name = name;
                                    virtualProperty.value = value;
                                    virtualMatch.rule.style.cssProperties.add(virtualProperty);
                                }
                            }
                        }
                    }
                });
            }
        });

        result.inherited = Collections.emptyList();
        result.pseudoElements = Collections.emptyList();

        return result;
    }

    private final class PeerManagerListener extends PeersRegisteredListener {
        @Override
        protected synchronized void onFirstPeerRegistered() {
            mDocument.addRef();
        }

        @Override
        protected synchronized void onLastPeerUnregistered() {
            mDocument.release();
        }
    }

    private static class CSSComputedStyleProperty {
        @JsonProperty(required = true)
        public String name;

        @JsonProperty(required = true)
        public String value;
    }

    private static class RuleMatch {
        @JsonProperty
        public CSSRule rule;

        @JsonProperty
        public List<Integer> matchingSelectors;
    }

    private static class SelectorList {
        @JsonProperty
        public List<Selector> selectors;

        @JsonProperty
        public String text;
    }

    private static class SourceRange {
        @JsonProperty(required = true)
        public int startLine;

        @JsonProperty(required = true)
        public int startColumn;

        @JsonProperty(required = true)
        public int endLine;

        @JsonProperty(required = true)
        public int endColumn;
    }

    private static class Selector {
        @JsonProperty(required = true)
        public String text;

        @JsonProperty
        public SourceRange range;
    }

    private static class CSSRule {
        @JsonProperty
        public String styleSheetId;

        @JsonProperty(required = true)
        public SelectorList selectorList;

        @JsonProperty
        public Origin origin;

        @JsonProperty
        public CSSStyle style;
    }

    private static class CSSStyle {
        @JsonProperty
        public String styleSheetId;

        @JsonProperty(required = true)
        public List<CSSProperty> cssProperties;

        @JsonProperty
        public List<ShorthandEntry> shorthandEntries;

        @JsonProperty
        public String cssText;

        @JsonProperty
        public SourceRange range;
    }

    private static class ShorthandEntry {
        @JsonProperty(required = true)
        public String name;

        @JsonProperty(required = true)
        public String value;

        @JsonProperty
        public Boolean important;
    }

    private static class CSSProperty {
        @JsonProperty(required = true)
        public String name;

        @JsonProperty(required = true)
        public String value;

        @JsonProperty
        public Boolean important;

        @JsonProperty
        public Boolean implicit;

        @JsonProperty
        public String text;

        @JsonProperty
        public Boolean parsedOk;

        @JsonProperty
        public Boolean disabled;

        @JsonProperty
        public SourceRange range;
    }

    private static class PseudoIdMatches {
        @JsonProperty(required = true)
        public int pseudoId;

        @JsonProperty(required = true)
        public List<RuleMatch> matches;

        public PseudoIdMatches() {
            this.matches = new ArrayList<>();
        }
    }

    private static class GetComputedStyleForNodeRequest {
        @JsonProperty(required = true)
        public int nodeId;
    }

    private static class InheritedStyleEntry {
        @JsonProperty(required = true)
        public CSSStyle inlineStyle;

        @JsonProperty(required = true)
        public List<RuleMatch> matchedCSSRules;
    }

    private static class GetComputedStyleForNodeResult implements JsonRpcResult {
        @JsonProperty(required = true)
        public List<CSSComputedStyleProperty> computedStyle;
    }

    private static class GetMatchedStylesForNodeRequest {
        @JsonProperty(required = true)
        public int nodeId;

        @JsonProperty
        public Boolean excludePseudo;

        @JsonProperty
        public Boolean excludeInherited;
    }

    private static class GetMatchedStylesForNodeResult implements JsonRpcResult {
        @JsonProperty
        public List<RuleMatch> matchedCSSRules;

        @JsonProperty
        public List<PseudoIdMatches> pseudoElements;

        @JsonProperty
        public List<InheritedStyleEntry> inherited;
    }

    private void initMatch(RuleMatch match, String value) {
        match.matchingSelectors = ListUtil.newImmutableList(0);

        Selector selector = new Selector();
        selector.text = value;

        CSSRule rule = new CSSRule();

        rule.origin = Origin.REGULAR;
        rule.selectorList = new SelectorList();

        rule.selectorList.selectors = ListUtil.newImmutableList(selector);

        rule.style = new CSSStyle();
        rule.style.cssProperties = new ArrayList<>();

        match.rule = rule;

        rule.style.shorthandEntries = Collections.emptyList();
    }
}