Search in sources :

Example 16 with ResourceItem

use of com.android.ide.common.res2.ResourceItem in project android by JetBrains.

the class ThemeEditorStyle method setValue.

/**
   * Sets the value of given attribute in all possible folders where this style is defined. If attribute or value can be used from certain API level,
   * folders below that level won't be modified, instead new folder with certain API will be created.
   * Note: {@link LocalResourceRepository}'s won't get updated immediately
   *
   * @param attribute the style attribute name
   * @param value     the style attribute value
   */
public void setValue(@NotNull final String attribute, @NotNull final String value) {
    if (!isProjectStyle()) {
        throw new UnsupportedOperationException("Non project styles can not be modified");
    }
    final Project project = myManager.getProject();
    int maxApi = Math.max(ResolutionUtils.getOriginalApiLevel(value, myManager.getProject()), ResolutionUtils.getOriginalApiLevel(attribute, project));
    int minSdk = ThemeEditorUtils.getMinApiLevel(myManager.getModule());
    // When api level of both attribute and value is not greater that Minimum SDK,
    // we should modify every FolderConfiguration, thus we set desiredApi to -1
    final int desiredApi = (maxApi <= minSdk) ? -1 : maxApi;
    new WriteCommandAction.Simple(project, "Setting value of " + attribute) {

        @Override
        protected void run() {
            // Makes the command global even if only one xml file is modified
            // That way, the Undo is always available from the theme editor
            CommandProcessor.getInstance().markCurrentCommandAsGlobal(project);
            Collection<FolderConfiguration> toBeCopied = findToBeCopied(desiredApi);
            for (FolderConfiguration configuration : toBeCopied) {
                XmlTag styleTag = findXmlTagFromConfiguration(configuration);
                assert styleTag != null;
                ThemeEditorUtils.copyTheme(desiredApi, styleTag);
            }
            if (!toBeCopied.isEmpty()) {
                // We need to refreshResource, to get all copied styles
                // Otherwise, LocalResourceRepositories won't get updated, so we won't get copied styles
                AndroidFacet facet = AndroidFacet.getInstance(myManager.getModule());
                if (facet != null) {
                    facet.refreshResources();
                    // This is because the ResourceFolderRepository may initialize through the file instead of Psi.
                    GradleBuildInvoker.saveAllFilesSafely();
                }
            }
            Collection<ResourceItem> styleItems = getStyleResourceItems();
            for (ResourceItem style : styleItems) {
                FolderConfiguration configuration = style.getConfiguration();
                int version = ThemeEditorUtils.getVersionFromConfiguration(configuration);
                // it means than we can modify 'attribute' to value 'value'.
                if (version >= desiredApi) {
                    setValue(configuration, attribute, value);
                }
            }
        }
    }.execute();
}
Also used : WriteCommandAction(com.intellij.openapi.command.WriteCommandAction) Project(com.intellij.openapi.project.Project) ImmutableCollection(com.google.common.collect.ImmutableCollection) Collection(java.util.Collection) FolderConfiguration(com.android.ide.common.resources.configuration.FolderConfiguration) ResourceItem(com.android.ide.common.res2.ResourceItem) AndroidFacet(org.jetbrains.android.facet.AndroidFacet) XmlTag(com.intellij.psi.xml.XmlTag)

Example 17 with ResourceItem

use of com.android.ide.common.res2.ResourceItem in project android by JetBrains.

the class ThemeEditorStyle method getParentName.

/**
   * @param configuration FolderConfiguration of the style to lookup
   * @return parent this style with a FolderConfiguration configuration
   */
@Nullable
public /*if there is no of this style*/
String getParentName(@NotNull FolderConfiguration configuration) {
    if (isFramework()) {
        IAndroidTarget target = myManager.getHighestApiTarget();
        assert target != null;
        com.android.ide.common.resources.ResourceItem styleItem = myManager.getResolverCache().getFrameworkResources(new FolderConfiguration(), target).getResourceItem(ResourceType.STYLE, getName());
        for (ResourceFile file : styleItem.getSourceFileList()) {
            if (file.getConfiguration().equals(configuration)) {
                StyleResourceValue style = (StyleResourceValue) file.getValue(ResourceType.STYLE, getName());
                return ResolutionUtils.getParentQualifiedName(style);
            }
        }
        throw new IllegalArgumentException("bad folder config " + configuration);
    }
    for (final ResourceItem styleItem : getStyleResourceItems()) {
        if (configuration.equals(styleItem.getConfiguration())) {
            StyleResourceValue style = (StyleResourceValue) styleItem.getResourceValue(false);
            assert style != null;
            return ResolutionUtils.getParentQualifiedName(style);
        }
    }
    throw new IllegalArgumentException("bad folder config " + configuration);
}
Also used : ResourceFile(com.android.ide.common.resources.ResourceFile) StyleResourceValue(com.android.ide.common.rendering.api.StyleResourceValue) IAndroidTarget(com.android.sdklib.IAndroidTarget) FolderConfiguration(com.android.ide.common.resources.configuration.FolderConfiguration) ResourceItem(com.android.ide.common.res2.ResourceItem) Nullable(org.jetbrains.annotations.Nullable)

Example 18 with ResourceItem

use of com.android.ide.common.res2.ResourceItem in project android by JetBrains.

the class ThemeEditorStyle method findToBeCopied.

/**
   * Finds best to be copied {@link FolderConfiguration}s
   * e.g if style is defined in "port-v8", "port-v18", "port-v22", "night-v20" and desiredApi = 21,
   * then result is {"port-v18", "night-v20"}
   *
   * @param desiredApi new api level of {@link FolderConfiguration}s after being copied
   * @return Collection of FolderConfigurations which are going to be copied to version desiredApi
   */
@NotNull
private ImmutableCollection<FolderConfiguration> findToBeCopied(int desiredApi) {
    // Keeps closest VersionQualifier to 'desiredApi'
    // e.g. desiredApi = 21, "en-port", "en-port-v18", "en-port-v19", "en-port-v22" then
    // bestVersionCopyFrom will contain {"en-port" -> v19}, as it is closest one to v21
    final HashMap<FolderConfiguration, VersionQualifier> bestVersionCopyFrom = Maps.newHashMap();
    for (ResourceItem styleItem : getStyleResourceItems()) {
        FolderConfiguration configuration = FolderConfiguration.copyOf(styleItem.getConfiguration());
        int styleItemVersion = ThemeEditorUtils.getVersionFromConfiguration(configuration);
        // We want to get the best from port-v19 port-v20 port-v23. so we need to remove the version qualifier to compare them
        configuration.setVersionQualifier(null);
        if (styleItemVersion > desiredApi) {
            // Thus, we don't need to copy it, we are going to just modify it.
            continue;
        }
        // If 'version' is closer to 'desiredApi' than we have found
        if (!bestVersionCopyFrom.containsKey(configuration) || bestVersionCopyFrom.get(configuration).getVersion() < styleItemVersion) {
            bestVersionCopyFrom.put(configuration, new VersionQualifier(styleItemVersion));
        }
    }
    ImmutableList.Builder<FolderConfiguration> toBeCopied = ImmutableList.builder();
    for (FolderConfiguration key : bestVersionCopyFrom.keySet()) {
        FolderConfiguration configuration = FolderConfiguration.copyOf(key);
        VersionQualifier version = bestVersionCopyFrom.get(key);
        if (version.getVersion() != -1) {
            configuration.setVersionQualifier(version);
        }
        // Version can't be bigger as we have filtered above
        if (version.getVersion() < desiredApi) {
            toBeCopied.add(configuration);
        }
    }
    return toBeCopied.build();
}
Also used : VersionQualifier(com.android.ide.common.resources.configuration.VersionQualifier) ImmutableList(com.google.common.collect.ImmutableList) FolderConfiguration(com.android.ide.common.resources.configuration.FolderConfiguration) ResourceItem(com.android.ide.common.res2.ResourceItem) NotNull(org.jetbrains.annotations.NotNull)

Example 19 with ResourceItem

use of com.android.ide.common.res2.ResourceItem in project android by JetBrains.

the class ThemeEditorStyle method removeAttribute.

/**
   * Deletes an attribute of that particular style from all the relevant xml files
   */
public void removeAttribute(@NotNull final String attribute) {
    if (!isProjectStyle()) {
        throw new UnsupportedOperationException("Non project styles can not be modified");
    }
    final Project project = myManager.getProject();
    Collection<PsiFile> toBeEdited = new HashSet<PsiFile>();
    final Collection<XmlTag> toBeRemoved = new HashSet<XmlTag>();
    for (ResourceItem resourceItem : getStyleResourceItems()) {
        final XmlTag sourceXml = LocalResourceRepository.getItemTag(project, resourceItem);
        assert sourceXml != null;
        final XmlTag tag = getValueTag(sourceXml, attribute);
        if (tag != null) {
            toBeEdited.add(tag.getContainingFile());
            toBeRemoved.add(tag);
        }
    }
    new WriteCommandAction.Simple(project, "Removing " + attribute, toBeEdited.toArray(new PsiFile[toBeEdited.size()])) {

        @Override
        protected void run() {
            // Makes the command global even if only one xml file is modified
            // That way, the Undo is always available from the theme editor
            CommandProcessor.getInstance().markCurrentCommandAsGlobal(project);
            for (XmlTag tag : toBeRemoved) {
                tag.delete();
            }
        }
    }.execute();
}
Also used : WriteCommandAction(com.intellij.openapi.command.WriteCommandAction) Project(com.intellij.openapi.project.Project) PsiFile(com.intellij.psi.PsiFile) ResourceItem(com.android.ide.common.res2.ResourceItem) HashSet(com.intellij.util.containers.HashSet) XmlTag(com.intellij.psi.xml.XmlTag)

Example 20 with ResourceItem

use of com.android.ide.common.res2.ResourceItem in project android by JetBrains.

the class ThemeEditorStyle method getValues.

/**
   * @param configuration FolderConfiguration of the style to lookup
   * @return all values defined in this style with a FolderConfiguration configuration
   */
@NotNull
public Collection<ItemResourceValue> getValues(@NotNull FolderConfiguration configuration) {
    if (isFramework()) {
        IAndroidTarget target = myManager.getHighestApiTarget();
        assert target != null;
        com.android.ide.common.resources.ResourceItem styleItem = myManager.getResolverCache().getFrameworkResources(new FolderConfiguration(), target).getResourceItem(ResourceType.STYLE, getName());
        for (ResourceFile file : styleItem.getSourceFileList()) {
            if (file.getConfiguration().equals(configuration)) {
                StyleResourceValue style = (StyleResourceValue) file.getValue(ResourceType.STYLE, getName());
                return style.getValues();
            }
        }
        throw new IllegalArgumentException("bad folder config " + configuration);
    }
    for (final ResourceItem styleItem : getStyleResourceItems()) {
        if (configuration.equals(styleItem.getConfiguration())) {
            StyleResourceValue style = (StyleResourceValue) styleItem.getResourceValue(false);
            if (style == null) {
                // style might be null if the value fails to parse
                continue;
            }
            return style.getValues();
        }
    }
    throw new IllegalArgumentException("bad folder config " + configuration);
}
Also used : ResourceFile(com.android.ide.common.resources.ResourceFile) StyleResourceValue(com.android.ide.common.rendering.api.StyleResourceValue) IAndroidTarget(com.android.sdklib.IAndroidTarget) FolderConfiguration(com.android.ide.common.resources.configuration.FolderConfiguration) ResourceItem(com.android.ide.common.res2.ResourceItem) NotNull(org.jetbrains.annotations.NotNull)

Aggregations

ResourceItem (com.android.ide.common.res2.ResourceItem)83 VirtualFile (com.intellij.openapi.vfs.VirtualFile)44 PsiFile (com.intellij.psi.PsiFile)35 Document (com.intellij.openapi.editor.Document)26 PsiDocumentManager (com.intellij.psi.PsiDocumentManager)26 ResourceValue (com.android.ide.common.rendering.api.ResourceValue)11 FolderConfiguration (com.android.ide.common.resources.configuration.FolderConfiguration)11 XmlTag (com.intellij.psi.xml.XmlTag)11 NotNull (org.jetbrains.annotations.NotNull)11 IOException (java.io.IOException)10 AbstractResourceRepository (com.android.ide.common.res2.AbstractResourceRepository)8 AndroidFacet (org.jetbrains.android.facet.AndroidFacet)8 StyleResourceValue (com.android.ide.common.rendering.api.StyleResourceValue)7 ResourceFile (com.android.ide.common.res2.ResourceFile)7 ResourceType (com.android.resources.ResourceType)7 WriteCommandAction (com.intellij.openapi.command.WriteCommandAction)7 Nullable (org.jetbrains.annotations.Nullable)7 LocalResourceRepository (com.android.tools.idea.res.LocalResourceRepository)6 Project (com.intellij.openapi.project.Project)6 File (java.io.File)6