/* * Copyright 2000-2012 JetBrains s.r.o. * * 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.intellij.android.designer.propertyTable.renderers; import com.android.tools.idea.rendering.ResourceHelper; import com.intellij.android.designer.model.RadModelBuilder; import com.intellij.designer.model.PropertiesContainer; import com.intellij.designer.model.PropertyContext; import com.intellij.designer.model.RadComponent; import com.intellij.designer.propertyTable.renderers.AbstractResourceRenderer; import com.intellij.designer.propertyTable.renderers.BooleanRenderer; import com.intellij.openapi.module.Module; import com.intellij.openapi.util.text.StringUtil; import com.intellij.ui.SimpleTextAttributes; import com.intellij.util.ArrayUtil; import org.jetbrains.android.dom.attrs.AttributeFormat; import org.jetbrains.android.dom.resources.ResourceElement; import org.jetbrains.android.facet.AndroidFacet; import org.jetbrains.android.resourceManagers.ResourceManager; import org.jetbrains.android.util.AndroidUtils; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.swing.*; import java.awt.*; import java.util.List; import java.util.Set; /** * @author Alexander Lobas */ public class ResourceRenderer extends AbstractResourceRenderer<String> { public static final String[] DIMENSIONS = {"dp", "sp", "pt", "px", "mm", "in"}; private static final String ANDROID_PREFIX = "@android:"; private BooleanRenderer myBooleanRenderer; private final Set<AttributeFormat> myFormats; public ResourceRenderer(Set<AttributeFormat> formats) { if (formats.contains(AttributeFormat.Boolean)) { myBooleanRenderer = new BooleanRenderer(); } myFormats = formats; } @NotNull @Override public JComponent getComponent(@Nullable PropertiesContainer container, PropertyContext context, @Nullable Object object, boolean selected, boolean hasFocus) { String value = (String)object; if (myBooleanRenderer != null && (StringUtil.isEmpty(value) || "false".equals(value) || "true".equals(value))) { return myBooleanRenderer.getComponent(container, context, "true".equals(value), selected, hasFocus); } return super.getComponent(container, context, object, selected, hasFocus); } @Override protected void formatValue(RadComponent component, String value) { if (!StringUtil.isEmpty(value)) { StringBuilder colorValue = new StringBuilder(); boolean system = false; int prefix = -1; if (value.startsWith("#")) { prefix = 1; } else if (value.startsWith(ANDROID_PREFIX)) { prefix = ANDROID_PREFIX.length(); system = true; } else if (value.startsWith("@")) { prefix = 1; } if (prefix != -1) { myColoredComponent.append(value.substring(0, prefix), SimpleTextAttributes.REGULAR_BOLD_ATTRIBUTES); myColoredComponent.append(value.substring(prefix), textStyle(component, value, system, colorValue)); } else if (myFormats.contains(AttributeFormat.Dimension)) { if (value.length() > 3 && value.endsWith("dip")) { myColoredComponent.append(value.substring(0, value.length() - 3)); myColoredComponent.append("dip", SimpleTextAttributes.REGULAR_BOLD_ATTRIBUTES); } else if (value.length() > 2) { int index = value.length() - 2; String dimension = value.substring(index); if (ArrayUtil.indexOf(DIMENSIONS, dimension) != -1) { myColoredComponent.append(value.substring(0, index)); myColoredComponent.append(dimension, SimpleTextAttributes.REGULAR_BOLD_ATTRIBUTES); } else { myColoredComponent.append(value); } } else { myColoredComponent.append(value); } } else { myColoredComponent.append(value); } if (colorValue.length() > 0) { value = colorValue.toString(); } if (myFormats.contains(AttributeFormat.Color) && value.startsWith("#")) { try { Color color = ResourceHelper.parseColor(value); if (color != null) { myColorIcon.setColor(color); myColoredComponent.setIcon(myColorIcon); } } catch (Throwable e) { } } } } private static SimpleTextAttributes textStyle(RadComponent component, String value, boolean system, StringBuilder colorValue) { if (value.startsWith("@") && !value.startsWith("@id/") && !value.startsWith("@+id/") && !value.startsWith("@android:id/")) { try { int start = system ? ANDROID_PREFIX.length() : 1; int index = value.indexOf('/', start + 1); String type = value.substring(start, index); String name = value.substring(index + 1); Module module = RadModelBuilder.getModule(component); if (module != null) { AndroidFacet facet = AndroidFacet.getInstance(module); if (facet != null) { ResourceManager manager = facet.getResourceManager(system ? AndroidUtils.SYSTEM_RESOURCE_PACKAGE : null); if (manager != null) { List<ResourceElement> resources = manager.findValueResources(type, name, false); if ("color".equalsIgnoreCase(type) && !resources.isEmpty()) { colorValue.append(resources.get(0).getRawText()); } if (resources.isEmpty() && manager.findResourceFiles(type, name, false).isEmpty()) { return SimpleTextAttributes.ERROR_ATTRIBUTES; } } } } } catch (Throwable e) { } } return SimpleTextAttributes.REGULAR_ATTRIBUTES; } @Override public void updateUI() { if (myBooleanRenderer != null) { SwingUtilities.updateComponentTreeUI(myBooleanRenderer); } super.updateUI(); } }