blob: 17abd385fb077cf4476a119dbf197b3c94710805 [file] [log] [blame]
package org.jetbrains.android.formatter;
import com.intellij.formatting.*;
import com.intellij.lang.ASTNode;
import com.intellij.lang.xml.XmlFormattingModelBuilder;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.codeStyle.CodeStyleSettings;
import com.intellij.psi.formatter.xml.XmlBlock;
import com.intellij.psi.formatter.xml.XmlPolicy;
import com.intellij.psi.formatter.xml.XmlTagBlock;
import com.intellij.psi.xml.XmlFile;
import com.intellij.util.xml.DomFileDescription;
import com.intellij.util.xml.DomManager;
import org.jetbrains.android.dom.AndroidResourceDomFileDescription;
import org.jetbrains.android.dom.color.ColorDomFileDescription;
import org.jetbrains.android.dom.drawable.DrawableStateListDomFileDescription;
import org.jetbrains.android.dom.layout.LayoutDomFileDescription;
import org.jetbrains.android.dom.manifest.ManifestDomFileDescription;
import org.jetbrains.android.dom.resources.ResourcesDomFileDescription;
import org.jetbrains.android.facet.AndroidFacet;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* @author Eugene.Kudelevsky
*/
public class AndroidXmlFormattingModelBuilder implements CustomFormattingModelBuilder {
private final XmlFormattingModelBuilder myXmlFormattingModelBuilder = new XmlFormattingModelBuilder();
@Override
public boolean isEngagedToFormat(PsiElement context) {
return getContextSpecificSettings(context) != null;
}
@NotNull
@Override
public FormattingModel createModel(PsiElement element, CodeStyleSettings settings) {
final FormattingModel baseModel = myXmlFormattingModelBuilder.createModel(element, settings);
final AndroidXmlCodeStyleSettings baseSettings = AndroidXmlCodeStyleSettings.getInstance(settings);
if (!baseSettings.USE_CUSTOM_SETTINGS) {
return baseModel;
}
final ContextSpecificSettingsProviders.Provider provider = getContextSpecificSettings(element);
final AndroidXmlCodeStyleSettings.MySettings s = provider != null ? provider.getSettings(baseSettings) : null;
return s != null ? new DelegatingFormattingModel(baseModel, createDelegatingBlock(baseModel, s, settings)) : baseModel;
}
private static Block createDelegatingBlock(FormattingModel model,
AndroidXmlCodeStyleSettings.MySettings customSettings,
CodeStyleSettings settings) {
final Block block = model.getRootBlock();
if (block instanceof XmlBlock) {
final XmlBlock b = (XmlBlock)block;
final XmlPolicy policy = customSettings.createXmlPolicy(settings, model.getDocumentModel());
return new XmlBlock(b.getNode(), b.getWrap(), b.getAlignment(), policy, b.getIndent(), b.getTextRange()) {
@Override
protected XmlTagBlock createTagBlock(ASTNode child, Indent indent, Wrap wrap, Alignment alignment) {
return new XmlTagBlock(child, wrap, alignment, myXmlFormattingPolicy,
indent != null ? indent : Indent.getNoneIndent(),
isPreserveSpace());
}
};
}
else {
return block;
}
}
@Nullable
@Override
public TextRange getRangeAffectingIndent(PsiFile file, int offset, ASTNode elementAtOffset) {
return myXmlFormattingModelBuilder.getRangeAffectingIndent(file, offset, elementAtOffset);
}
@Nullable
private static ContextSpecificSettingsProviders.Provider getContextSpecificSettings(PsiElement context) {
final PsiFile file = context.getContainingFile();
if (!(file instanceof XmlFile) ||
AndroidFacet.getInstance(file) == null) {
return null;
}
final DomFileDescription<?> description = DomManager.getDomManager(
context.getProject()).getDomFileDescription((XmlFile)file);
if (description instanceof LayoutDomFileDescription) {
return ContextSpecificSettingsProviders.LAYOUT;
}
else if (description instanceof ManifestDomFileDescription) {
return ContextSpecificSettingsProviders.MANIFEST;
}
else if (description instanceof ResourcesDomFileDescription ||
description instanceof DrawableStateListDomFileDescription ||
description instanceof ColorDomFileDescription) {
return ContextSpecificSettingsProviders.VALUE_RESOURCE_FILE;
}
else if (description instanceof AndroidResourceDomFileDescription) {
return ContextSpecificSettingsProviders.OTHER;
}
return null;
}
}