blob: c67f69ef04ddc1002faa5806f45d791a5237df28 [file] [log] [blame]
/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.tools.idea.debug;
import com.android.SdkConstants;
import com.android.tools.lint.checks.SupportAnnotationDetector;
import com.google.common.util.concurrent.Atomics;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.components.ServiceManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Computable;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.PsiAnnotation;
import com.intellij.util.ui.ColorIcon;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.awt.*;
import java.util.Locale;
import java.util.Map;
import java.util.concurrent.atomic.AtomicReference;
public class AnnotationsRenderer {
public static class Result {
@NotNull public final String label;
@Nullable public final Icon icon;
public Result(@NotNull String label, @Nullable Icon icon) {
this.label = label;
this.icon = icon;
}
}
@NotNull
public static Result render(@Nullable ResourceIdResolver resolver,
@NotNull PsiAnnotation annotation,
int value) {
String qualifiedName = getQualifiedName(annotation);
if (qualifiedName == null) {
return renderUnknown(null, value);
}
if (SupportAnnotationDetector.COLOR_INT_ANNOTATION.equals(qualifiedName)) {
return renderColorInt(value);
}
else if (qualifiedName.endsWith(SupportAnnotationDetector.RES_SUFFIX)) {
return renderResourceRefAnnotation(resolver, value, qualifiedName);
}
else if (qualifiedName.equals(SdkConstants.INT_DEF_ANNOTATION)) {
return renderIntDefAnnotation(annotation, value);
}
return renderUnknown(qualifiedName, value);
}
@NotNull
private static Result renderIntDefAnnotation(@NotNull final PsiAnnotation annotation, final int value) {
final AtomicReference<AndroidResolveHelper.IntDefResolution> valuesRef = Atomics.newReference();
ApplicationManager.getApplication().runReadAction(new Runnable() {
@Override
public void run() {
valuesRef.set(AndroidResolveHelper.resolveIntDef(annotation));
}
});
AndroidResolveHelper.IntDefResolution intDef = valuesRef.get();
if (intDef.valuesMap == null) {
renderUnknown("IntDef", value);
}
return new Result(String.format(Locale.US, "0x%1$08x {%2$s}", value, renderIntDef(value, intDef)), null);
}
@NotNull
static String renderIntDef(int value, AndroidResolveHelper.IntDefResolution intDef) {
if (intDef.valuesMap == null) {
return "";
}
if (!intDef.canBeOred) {
String name = intDef.valuesMap.get(value);
return StringUtil.notNullize(name);
}
StringBuilder sb = new StringBuilder(20);
for (Map.Entry<Integer,String> entry : intDef.valuesMap.entrySet()) {
int key = entry.getKey();
if ((value & key) != 0) {
if (sb.length() > 0) {
sb.append(" | ");
}
sb.append(entry.getValue());
}
}
return sb.toString();
}
@NotNull
private static Result renderResourceRefAnnotation(@Nullable ResourceIdResolver resolver, int value, String qualifiedName) {
String androidRes = null;
if (resolver != null) {
androidRes = resolver.getAndroidResourceName(value);
}
if (androidRes == null) {
return renderUnknown(qualifiedName, value);
} else {
String result = String.format(Locale.US, "0x%1$08x {%2$s}", value, androidRes);
return new Result(result, null);
}
}
@NotNull
private static Result renderColorInt(int value) {
int alpha = value >>> 24;
boolean hasAlpha = alpha != 0;
//noinspection UseJBColor
final Color color = new Color(value, hasAlpha);
String result = String.format(Locale.US, "0x%1$08x {a=%2$02d r=%3$02d g=%4$02d b=%5$02d}", value, color.getAlpha(), color.getRed(),
color.getGreen(), color.getBlue());
return new Result(result, new ColorIcon(16, 12, color, true));
}
@NotNull
private static Result renderUnknown(@Nullable String annotationName, int value) {
return new Result(String.format("0x%1$08x {@%2$s ?}", value, annotationName == null ? "" : getSimpleClassName(annotationName)), null);
}
@Nullable
private static String getQualifiedName(final PsiAnnotation annotation) {
return ApplicationManager.getApplication().runReadAction(new Computable<String>() {
@Override
public String compute() {
return annotation.getQualifiedName();
}
});
}
private static String getSimpleClassName(@NotNull String fqcn) {
int index = fqcn.lastIndexOf('.');
return (index < fqcn.length() - 1) ? fqcn.substring(index + 1) : fqcn;
}
}