Search in sources :

Example 1 with ItemResourceValue

use of com.android.ide.common.rendering.api.ItemResourceValue in project kotlin by JetBrains.

the class LintUtils method getStyleAttributes.

/**
     * Looks up the resource values for the given attribute given a style. Note that
     * this only looks project-level style values, it does not resume into the framework
     * styles.
     */
@Nullable
public static List<ResourceValue> getStyleAttributes(@NonNull Project project, @NonNull LintClient client, @NonNull String styleUrl, @NonNull String namespace, @NonNull String attribute) {
    if (!client.supportsProjectResources()) {
        return null;
    }
    AbstractResourceRepository resources = client.getProjectResources(project, true);
    if (resources == null) {
        return null;
    }
    ResourceUrl style = ResourceUrl.parse(styleUrl);
    if (style == null || style.framework) {
        return null;
    }
    List<ResourceValue> result = null;
    Queue<ResourceValue> queue = new ArrayDeque<ResourceValue>();
    queue.add(new ResourceValue(style.type, style.name, false));
    Set<String> seen = Sets.newHashSet();
    int count = 0;
    boolean isFrameworkAttribute = ANDROID_URI.equals(namespace);
    while (count < 30 && !queue.isEmpty()) {
        ResourceValue front = queue.remove();
        String name = front.getName();
        seen.add(name);
        List<ResourceItem> items = resources.getResourceItem(front.getResourceType(), name);
        if (items != null) {
            for (ResourceItem item : items) {
                ResourceValue rv = item.getResourceValue(false);
                if (rv instanceof StyleResourceValue) {
                    StyleResourceValue srv = (StyleResourceValue) rv;
                    ItemResourceValue value = srv.getItem(attribute, isFrameworkAttribute);
                    if (value != null) {
                        if (result == null) {
                            result = Lists.newArrayList();
                        }
                        if (!result.contains(value)) {
                            result.add(value);
                        }
                    }
                    String parent = srv.getParentStyle();
                    if (parent != null && !parent.startsWith(ANDROID_PREFIX)) {
                        ResourceUrl p = ResourceUrl.parse(parent);
                        if (p != null && !p.framework && !seen.contains(p.name)) {
                            seen.add(p.name);
                            queue.add(new ResourceValue(ResourceType.STYLE, p.name, false));
                        }
                    }
                    int index = name.lastIndexOf('.');
                    if (index > 0) {
                        String parentName = name.substring(0, index);
                        if (!seen.contains(parentName)) {
                            seen.add(parentName);
                            queue.add(new ResourceValue(ResourceType.STYLE, parentName, false));
                        }
                    }
                }
            }
        }
        count++;
    }
    return result;
}
Also used : StyleResourceValue(com.android.ide.common.rendering.api.StyleResourceValue) AbstractResourceRepository(com.android.ide.common.res2.AbstractResourceRepository) ItemResourceValue(com.android.ide.common.rendering.api.ItemResourceValue) StyleResourceValue(com.android.ide.common.rendering.api.StyleResourceValue) ItemResourceValue(com.android.ide.common.rendering.api.ItemResourceValue) ResourceValue(com.android.ide.common.rendering.api.ResourceValue) ResourceItem(com.android.ide.common.res2.ResourceItem) ResourceUrl(com.android.ide.common.resources.ResourceUrl) Nullable(com.android.annotations.Nullable)

Example 2 with ItemResourceValue

use of com.android.ide.common.rendering.api.ItemResourceValue in project android by JetBrains.

the class ThemeEditorUtils method getGoodContrastPreviewBackground.

/**
   * Returns the color that should be used for the background of the preview panel depending on the background color
   * of the theme being displayed, so as to always keep some contrast between the two.
   */
public static JBColor getGoodContrastPreviewBackground(@NotNull ConfiguredThemeEditorStyle theme, @NotNull ResourceResolver resourceResolver) {
    ItemResourceValue themeColorBackgroundItem = resolveItemFromParents(theme, "colorBackground", true);
    ResourceValue backgroundResourceValue = resourceResolver.resolveResValue(themeColorBackgroundItem);
    if (backgroundResourceValue != null) {
        String colorBackgroundValue = backgroundResourceValue.getValue();
        Color colorBackground = ResourceHelper.parseColor(colorBackgroundValue);
        if (colorBackground != null) {
            float backgroundDistance = MaterialColorUtils.colorDistance(colorBackground, ThemeEditorComponent.PREVIEW_BACKGROUND);
            if (backgroundDistance < ThemeEditorComponent.COLOR_DISTANCE_THRESHOLD && backgroundDistance < MaterialColorUtils.colorDistance(colorBackground, ThemeEditorComponent.ALT_PREVIEW_BACKGROUND)) {
                return ThemeEditorComponent.ALT_PREVIEW_BACKGROUND;
            }
        }
    }
    return ThemeEditorComponent.PREVIEW_BACKGROUND;
}
Also used : ItemResourceValue(com.android.ide.common.rendering.api.ItemResourceValue) JBColor(com.intellij.ui.JBColor) ItemResourceValue(com.android.ide.common.rendering.api.ItemResourceValue) ResourceValue(com.android.ide.common.rendering.api.ResourceValue)

Example 3 with ItemResourceValue

use of com.android.ide.common.rendering.api.ItemResourceValue in project android by JetBrains.

the class ThemeEditorUtils method getResourceDialog.

@NotNull
public static ChooseResourceDialog getResourceDialog(@NotNull EditedStyleItem item, @NotNull ThemeEditorContext context, EnumSet<ResourceType> allowedTypes) {
    Module module = context.getModuleForResources();
    ItemResourceValue itemSelectedValue = item.getSelectedValue();
    String value = itemSelectedValue.getValue();
    boolean isFrameworkValue = itemSelectedValue.isFramework();
    String nameSuggestion = value;
    ResourceUrl url = ResourceUrl.parse(value, isFrameworkValue);
    if (url != null) {
        nameSuggestion = url.name;
    }
    nameSuggestion = getDefaultResourceName(context, nameSuggestion);
    ChooseResourceDialog.ResourceNameVisibility resourceNameVisibility = ChooseResourceDialog.ResourceNameVisibility.FORCE;
    if (nameSuggestion.startsWith("#")) {
        nameSuggestion = null;
        resourceNameVisibility = ChooseResourceDialog.ResourceNameVisibility.SHOW;
    }
    ChooseResourceDialog dialog = ChooseResourceDialog.builder().setModule(module).setTypes(allowedTypes).setCurrentValue(value).setIsFrameworkValue(isFrameworkValue).setResourceNameVisibility(resourceNameVisibility).setResourceNameSuggestion(nameSuggestion).build();
    dialog.setUseGlobalUndo(true);
    return dialog;
}
Also used : ItemResourceValue(com.android.ide.common.rendering.api.ItemResourceValue) ChooseResourceDialog(com.android.tools.idea.ui.resourcechooser.ChooseResourceDialog) Module(com.intellij.openapi.module.Module) ResourceUrl(com.android.ide.common.resources.ResourceUrl) NotNull(org.jetbrains.annotations.NotNull)

Example 4 with ItemResourceValue

use of com.android.ide.common.rendering.api.ItemResourceValue in project android by JetBrains.

the class ThemeAttributeResolver method resolveFromInheritance.

private void resolveFromInheritance(@NotNull ThemeEditorStyle themeEditorStyle, @NotNull FolderConfiguration configuration, @NotNull RestrictedConfiguration restricted, @NotNull Set<String> seenAttributes) {
    RestrictedConfiguration styleRestricted = getRestrictedConfiguration(themeEditorStyle, configuration);
    if (styleRestricted == null) {
        LOG.warn(configuration + " is unreachable");
        return;
    }
    styleRestricted = restricted.intersect(styleRestricted);
    if (styleRestricted == null) {
        return;
    }
    Set<String> newSeenAttributes = new HashSet<String>(seenAttributes);
    for (ItemResourceValue item : themeEditorStyle.getValues(configuration)) {
        String itemName = ResolutionUtils.getQualifiedItemName(item);
        if (!newSeenAttributes.contains(itemName)) {
            myItemValueMap.putValue(itemName, ConfiguredElement.create(styleRestricted.getAny(), item));
            newSeenAttributes.add(itemName);
        }
    }
    String parentName = themeEditorStyle.getParentName(configuration);
    if (parentName == null) {
        // We have reached the top of the theme hierarchy (i.e "android:Theme")
        return;
    }
    ThemeEditorStyle parent = new ThemeEditorStyle(myManager, parentName);
    for (FolderConfiguration folder : parent.getFolders()) {
        resolveFromInheritance(parent, folder, styleRestricted, newSeenAttributes);
    }
}
Also used : ItemResourceValue(com.android.ide.common.rendering.api.ItemResourceValue) ThemeEditorStyle(com.android.tools.idea.editors.theme.datamodels.ThemeEditorStyle) ConfiguredThemeEditorStyle(com.android.tools.idea.editors.theme.datamodels.ConfiguredThemeEditorStyle) FolderConfiguration(com.android.ide.common.resources.configuration.FolderConfiguration) RestrictedConfiguration(com.android.tools.idea.editors.theme.qualifiers.RestrictedConfiguration)

Example 5 with ItemResourceValue

use of com.android.ide.common.rendering.api.ItemResourceValue in project android by JetBrains.

the class ThemeEditorComponent method createNewThemeWithAttributeValue.

/**
   * Sets a new value to the passed attribute. It will also trigger the reload if a change happened.
   * @param rv The attribute to set, including the current value.
   * @param strValue The new value.
   */
private void createNewThemeWithAttributeValue(@NotNull final EditedStyleItem rv, @NotNull final String strValue) {
    if (strValue.equals(rv.getValue())) {
        // No modification required.
        return;
    }
    ConfiguredThemeEditorStyle selectedStyle = getUsedStyle();
    if (selectedStyle == null) {
        LOG.error("No style/theme selected.");
        return;
    }
    // The current style is R/O so we need to propagate this change a new style.
    boolean isSubStyleSelected = isSubStyleSelected();
    String message = String.format("<html>The %1$s '<code>%2$s</code>' is Read-Only.<br/>A new %1$s will be created to modify '<code>%3$s</code>'.<br/></html>", isSubStyleSelected ? "style" : "theme", selectedStyle.getQualifiedName(), rv.getName());
    final ItemResourceValue originalValue = rv.getSelectedValue();
    ParentRendererEditor.ThemeParentChangedListener themeListener = new ParentRendererEditor.ThemeParentChangedListener() {

        private ConfiguredThemeEditorStyle myModifiedTheme;

        @Override
        public void themeChanged(@NotNull String name) {
            if (myModifiedTheme != null) {
                myModifiedTheme.getStyleResourceValue().addItem(originalValue);
            }
            myModifiedTheme = myThemeEditorContext.getThemeResolver().getTheme(name);
            assert myModifiedTheme != null;
            ItemResourceValue newSelectedValue = new ItemResourceValue(originalValue.getName(), originalValue.isFrameworkAttr(), strValue, false, null);
            myModifiedTheme.getStyleResourceValue().addItem(newSelectedValue);
            myPreviewThemeName = null;
            refreshPreviewPanel(name);
        }

        @Override
        public void reset() {
            myModifiedTheme.getStyleResourceValue().addItem(originalValue);
            reload(myThemeName);
        }
    };
    final String newStyleName = ThemeEditorUtils.showCreateNewStyleDialog(selectedStyle, myThemeEditorContext, !isSubStyleSelected, false, message, isSubStyleSelected ? null : themeListener);
    if (!isSubStyleSelected) {
        themeListener.reset();
    }
    if (newStyleName == null) {
        return;
    }
    // Need invokeLater to wait for the theme resolver to be aware of the newly created style through the resource change listener
    ApplicationManager.getApplication().invokeLater(new Runnable() {

        @Override
        public void run() {
            myThemeEditorContext.updateThemeResolver();
            ConfiguredThemeEditorStyle newStyle = myThemeEditorContext.getThemeResolver().getTheme(newStyleName);
            assert newStyle != null;
            newStyle.setValue(rv.getQualifiedName(), strValue);
        }
    });
    if (!isSubStyleSelected) {
        // We changed a theme, so we are done.
        // We don't need to call reload, because myResourceChangeListener will take care of it
        myThemeName = newStyleName;
        mySubStyleName = null;
        return;
    }
    ConfiguredThemeEditorStyle selectedTheme = getSelectedTheme();
    if (selectedTheme == null) {
        LOG.error("No theme selected.");
        return;
    }
    // Decide what property we need to modify.
    // If the modified style was pointed by a theme attribute, we need to use that theme attribute value
    // as property. Otherwise, just update the original property name with the new style.
    final String sourcePropertyName = mySubStyleSourceAttribute.isAttr() ? mySubStyleSourceAttribute.getAttrPropertyName() : mySubStyleSourceAttribute.getQualifiedName();
    // We've modified a sub-style so we need to modify the attribute that was originally pointing to this.
    if (selectedTheme.isReadOnly()) {
        // The theme pointing to the new style is r/o so create a new theme and then write the value.
        message = String.format("<html>The style '%1$s' which references to '%2$s' is also Read-Only.<br/>" + "A new theme will be created to point to the modified style '%3$s'.<br/></html>", selectedTheme.getQualifiedName(), rv.getName(), newStyleName);
        final String newThemeName = ThemeEditorUtils.showCreateNewStyleDialog(selectedTheme, myThemeEditorContext, true, false, message, themeListener);
        themeListener.reset();
        if (newThemeName != null) {
            // We don't need to call reload, because myResourceChangeListener will take care of it
            myThemeName = newThemeName;
            mySubStyleName = newStyleName;
            // Need invokeLater to wait for the theme resolver to be aware of the newly created theme through the resource change listener
            ApplicationManager.getApplication().invokeLater(new Runnable() {

                @Override
                public void run() {
                    myThemeEditorContext.updateThemeResolver();
                    ConfiguredThemeEditorStyle newTheme = myThemeEditorContext.getThemeResolver().getTheme(newThemeName);
                    assert newTheme != null;
                    newTheme.setValue(sourcePropertyName, newStyleName);
                }
            });
        }
    } else {
        selectedTheme.setValue(sourcePropertyName, newStyleName);
        // We don't need to call reload, because myResourceChangeListener will take care of it
        mySubStyleName = newStyleName;
    }
}
Also used : ItemResourceValue(com.android.ide.common.rendering.api.ItemResourceValue) ParentRendererEditor(com.android.tools.idea.editors.theme.attributes.editors.ParentRendererEditor) NotNull(org.jetbrains.annotations.NotNull) ConfiguredThemeEditorStyle(com.android.tools.idea.editors.theme.datamodels.ConfiguredThemeEditorStyle)

Aggregations

ItemResourceValue (com.android.ide.common.rendering.api.ItemResourceValue)28 ConfiguredThemeEditorStyle (com.android.tools.idea.editors.theme.datamodels.ConfiguredThemeEditorStyle)11 VirtualFile (com.intellij.openapi.vfs.VirtualFile)10 NotNull (org.jetbrains.annotations.NotNull)8 FolderConfiguration (com.android.ide.common.resources.configuration.FolderConfiguration)7 Configuration (com.android.tools.idea.configurations.Configuration)7 StyleResourceValue (com.android.ide.common.rendering.api.StyleResourceValue)5 ResourceValue (com.android.ide.common.rendering.api.ResourceValue)4 EditedStyleItem (com.android.tools.idea.editors.theme.datamodels.EditedStyleItem)4 ResourceItem (com.android.ide.common.res2.ResourceItem)3 ResourceResolver (com.android.ide.common.resources.ResourceResolver)3 ResourceType (com.android.resources.ResourceType)3 ResourceUrl (com.android.ide.common.resources.ResourceUrl)2 ThemeEditorStyle (com.android.tools.idea.editors.theme.datamodels.ThemeEditorStyle)2 RestrictedConfiguration (com.android.tools.idea.editors.theme.qualifiers.RestrictedConfiguration)2 Nullable (org.jetbrains.annotations.Nullable)2 Nullable (com.android.annotations.Nullable)1 AbstractResourceRepository (com.android.ide.common.res2.AbstractResourceRepository)1 ResourceFile (com.android.ide.common.resources.ResourceFile)1 Configurable (com.android.ide.common.resources.configuration.Configurable)1