Search in sources :

Example 1 with StyleItem

use of org.jetbrains.android.dom.resources.StyleItem in project android by JetBrains.

the class StyleItemConverter method getConverter.

@Override
public Converter getConverter(@NotNull GenericDomValue element) {
    StyleItem item = (StyleItem) element;
    String name = item.getName().getValue();
    if (name != null) {
        String[] strs = name.split(":");
        if (strs.length == 1 || strs.length == 2) {
            AndroidFacet facet = AndroidFacet.getInstance(element);
            if (facet != null) {
                String namespacePrefix = strs.length == 2 ? strs[0] : null;
                String localName = strs[strs.length - 1];
                return findConverterForAttribute(namespacePrefix, localName, facet, element);
            }
        }
    }
    return null;
}
Also used : StyleItem(org.jetbrains.android.dom.resources.StyleItem) AndroidFacet(org.jetbrains.android.facet.AndroidFacet)

Example 2 with StyleItem

use of org.jetbrains.android.dom.resources.StyleItem in project android by JetBrains.

the class AndroidRefactoringUtil method computeAttributeMap.

@Nullable
static Map<AndroidAttributeInfo, String> computeAttributeMap(@NotNull Style style, @NotNull ErrorReporter errorReporter, @NotNull String errorReportTitle) {
    final Map<AndroidAttributeInfo, String> attributeValues = new HashMap<AndroidAttributeInfo, String>();
    for (StyleItem item : style.getItems()) {
        final String attributeName = item.getName().getStringValue();
        String attributeValue = item.getStringValue();
        if (attributeName == null || attributeName.length() <= 0 || attributeValue == null) {
            continue;
        }
        final int idx = attributeName.indexOf(':');
        final String localName = idx >= 0 ? attributeName.substring(idx + 1) : attributeName;
        final String nsPrefix = idx >= 0 ? attributeName.substring(0, idx) : null;
        if (nsPrefix != null) {
            if (!AndroidUtils.SYSTEM_RESOURCE_PACKAGE.equals(nsPrefix)) {
                errorReporter.report(RefactoringBundle.getCannotRefactorMessage("Unknown XML attribute prefix '" + nsPrefix + ":'"), errorReportTitle);
                return null;
            }
        } else {
            errorReporter.report(RefactoringBundle.getCannotRefactorMessage("The style contains attribute without 'android' prefix."), errorReportTitle);
            return null;
        }
        attributeValues.put(new AndroidAttributeInfo(localName, nsPrefix), attributeValue);
    }
    return attributeValues;
}
Also used : StyleItem(org.jetbrains.android.dom.resources.StyleItem) HashMap(com.intellij.util.containers.HashMap) Nullable(org.jetbrains.annotations.Nullable)

Example 3 with StyleItem

use of org.jetbrains.android.dom.resources.StyleItem in project android by JetBrains.

the class AndroidExtractStyleAction method doExtractStyle.

@Nullable
public static String doExtractStyle(@NotNull Module module, @NotNull final XmlTag viewTag, final boolean addStyleAttributeToTag, @Nullable MyTestConfig testConfig) {
    final PsiFile file = viewTag.getContainingFile();
    if (file == null) {
        return null;
    }
    final String dialogTitle = AndroidBundle.message("android.extract.style.title");
    final String fileName = AndroidResourceUtil.getDefaultResourceFileName(ResourceType.STYLE);
    assert fileName != null;
    final List<String> dirNames = Collections.singletonList(ResourceFolderType.VALUES.getName());
    final List<XmlAttribute> extractableAttributes = getExtractableAttributes(viewTag);
    final Project project = module.getProject();
    if (extractableAttributes.size() == 0) {
        AndroidUtils.reportError(project, "The tag doesn't contain any attributes that can be extracted", dialogTitle);
        return null;
    }
    final LayoutViewElement viewElement = getLayoutViewElement(viewTag);
    assert viewElement != null;
    final ResourceValue parentStyleValue = viewElement.getStyle().getValue();
    final String parentStyle;
    boolean supportImplicitParent = false;
    if (parentStyleValue != null) {
        parentStyle = parentStyleValue.getResourceName();
        if (ResourceType.STYLE != parentStyleValue.getType() || parentStyle == null || parentStyle.length() == 0) {
            AndroidUtils.reportError(project, "Invalid parent style reference " + parentStyleValue.toString(), dialogTitle);
            return null;
        }
        supportImplicitParent = parentStyleValue.getNamespace() == null;
    } else {
        parentStyle = null;
    }
    final String styleName;
    final List<XmlAttribute> styledAttributes;
    final VirtualFile chosenDirectory;
    final boolean searchStyleApplications;
    if (testConfig == null) {
        final ExtractStyleDialog dialog = new ExtractStyleDialog(module, fileName, supportImplicitParent ? parentStyle : null, dirNames, extractableAttributes);
        dialog.setTitle(dialogTitle);
        if (!dialog.showAndGet()) {
            return null;
        }
        searchStyleApplications = dialog.isToSearchStyleApplications();
        chosenDirectory = dialog.getResourceDirectory();
        if (chosenDirectory == null) {
            AndroidUtils.reportError(project, AndroidBundle.message("check.resource.dir.error", module.getName()));
            return null;
        }
        styledAttributes = dialog.getStyledAttributes();
        styleName = dialog.getStyleName();
    } else {
        testConfig.validate(extractableAttributes);
        chosenDirectory = testConfig.getResourceDirectory();
        styleName = testConfig.getStyleName();
        final Set<String> attrsToExtract = new HashSet<String>(Arrays.asList(testConfig.getAttributesToExtract()));
        styledAttributes = new ArrayList<XmlAttribute>();
        for (XmlAttribute attribute : extractableAttributes) {
            if (attrsToExtract.contains(attribute.getName())) {
                styledAttributes.add(attribute);
            }
        }
        searchStyleApplications = false;
    }
    final boolean[] success = { false };
    final Ref<Style> createdStyleRef = Ref.create();
    final boolean finalSupportImplicitParent = supportImplicitParent;
    new WriteCommandAction(project, "Extract Android Style '" + styleName + "'", file) {

        @Override
        protected void run(@NotNull final Result result) throws Throwable {
            final List<XmlAttribute> attributesToDelete = new ArrayList<XmlAttribute>();
            if (!AndroidResourceUtil.createValueResource(project, chosenDirectory, styleName, null, ResourceType.STYLE, fileName, dirNames, new Processor<ResourceElement>() {

                @Override
                public boolean process(ResourceElement element) {
                    assert element instanceof Style;
                    final Style style = (Style) element;
                    createdStyleRef.set(style);
                    for (XmlAttribute attribute : styledAttributes) {
                        if (SdkConstants.NS_RESOURCES.equals(attribute.getNamespace())) {
                            final StyleItem item = style.addItem();
                            item.getName().setStringValue("android:" + attribute.getLocalName());
                            item.setStringValue(attribute.getValue());
                            attributesToDelete.add(attribute);
                        }
                    }
                    if (parentStyleValue != null && (!finalSupportImplicitParent || !styleName.startsWith(parentStyle + "."))) {
                        final String aPackage = parentStyleValue.getNamespace();
                        style.getParentStyle().setStringValue((aPackage != null ? aPackage + ":" : "") + parentStyle);
                    }
                    return true;
                }
            })) {
                return;
            }
            ApplicationManager.getApplication().runWriteAction(new Runnable() {

                @Override
                public void run() {
                    for (XmlAttribute attribute : attributesToDelete) {
                        attribute.delete();
                    }
                    if (addStyleAttributeToTag) {
                        final LayoutViewElement viewElement = getLayoutViewElement(viewTag);
                        assert viewElement != null;
                        viewElement.getStyle().setStringValue("@style/" + styleName);
                    }
                }
            });
            success[0] = true;
        }

        @Override
        protected UndoConfirmationPolicy getUndoConfirmationPolicy() {
            return UndoConfirmationPolicy.REQUEST_CONFIRMATION;
        }
    }.execute();
    if (!success[0]) {
        return null;
    }
    final Style createdStyle = createdStyleRef.get();
    final XmlTag createdStyleTag = createdStyle != null ? createdStyle.getXmlTag() : null;
    if (createdStyleTag != null) {
        final AndroidFindStyleApplicationsAction.MyStyleData createdStyleData = AndroidFindStyleApplicationsAction.getStyleData(createdStyleTag);
        if (createdStyleData != null && searchStyleApplications) {
            ApplicationManager.getApplication().invokeLater(new Runnable() {

                @Override
                public void run() {
                    AndroidFindStyleApplicationsAction.doRefactoringForTag(createdStyleTag, createdStyleData, file, null);
                }
            });
        }
    }
    return styleName;
}
Also used : VirtualFile(com.intellij.openapi.vfs.VirtualFile) WriteCommandAction(com.intellij.openapi.command.WriteCommandAction) XmlAttribute(com.intellij.psi.xml.XmlAttribute) LayoutViewElement(org.jetbrains.android.dom.layout.LayoutViewElement) StyleItem(org.jetbrains.android.dom.resources.StyleItem) Result(com.intellij.openapi.application.Result) UndoConfirmationPolicy(com.intellij.openapi.command.UndoConfirmationPolicy) ResourceValue(org.jetbrains.android.dom.resources.ResourceValue) Style(org.jetbrains.android.dom.resources.Style) PsiFile(com.intellij.psi.PsiFile) HashSet(com.intellij.util.containers.HashSet) ResourceElement(org.jetbrains.android.dom.resources.ResourceElement) Project(com.intellij.openapi.project.Project) XmlTag(com.intellij.psi.xml.XmlTag) Nullable(org.jetbrains.annotations.Nullable)

Example 4 with StyleItem

use of org.jetbrains.android.dom.resources.StyleItem in project android by JetBrains.

the class DimensionConverterTest method test.

public void test() {
    DimensionConverter converter = new DimensionConverter();
    StyleItem element = createElement("<item>10dp</item>", StyleItem.class);
    DomInvocationHandler handler = DomManagerImpl.getDomInvocationHandler(element);
    assertNotNull(handler);
    ConvertContext context = ConvertContextFactory.createConvertContext(handler);
    List<String> variants = new ArrayList<>(converter.getVariants(context));
    Collections.sort(variants);
    assertEquals(Arrays.asList("10dp", "10in", "10mm", "10pt", "10px", "10sp"), variants);
    // Valid units
    assertEquals("1dip", converter.fromString("1dip", context));
    assertEquals("1dp", converter.fromString("1dp", context));
    assertEquals("1px", converter.fromString("1px", context));
    assertEquals("1in", converter.fromString("1in", context));
    assertEquals("1mm", converter.fromString("1mm", context));
    assertEquals("1sp", converter.fromString("1sp", context));
    assertEquals("1pt", converter.fromString("1pt", context));
    // Invalid dimensions (missing units)
    assertNull(converter.fromString("not_a_dimension", context));
    assertNull(converter.fromString("", context));
    assertEquals("Cannot resolve symbol ''", converter.getErrorMessage("", context));
    assertNull(converter.fromString("1", context));
    assertEquals("Cannot resolve symbol '1'", converter.getErrorMessage("1", context));
    assertNull(converter.fromString("1.5", context));
    assertEquals("Cannot resolve symbol '1.5'", converter.getErrorMessage("1.5", context));
    // Unknown units
    assertNull(converter.fromString("15d", context));
    assertEquals("Unknown unit 'd'", converter.getErrorMessage("15d", context));
    assertNull(converter.fromString("15wrong", context));
    assertEquals("Unknown unit 'wrong'", converter.getErrorMessage("15wrong", context));
    // Normal conversions
    assertEquals("15px", converter.fromString("15px", context));
    assertEquals("15", DimensionConverter.getIntegerPrefix("15px"));
    assertEquals("px", DimensionConverter.getUnitFromValue("15px"));
    // Make sure negative numbers work
    assertEquals("-10px", converter.fromString("-10px", context));
    assertEquals("-10", DimensionConverter.getIntegerPrefix("-10px"));
    assertEquals("px", DimensionConverter.getUnitFromValue("-10px"));
    // Make sure decimals work
    assertEquals("1.5sp", converter.fromString("1.5sp", context));
    assertEquals("1.5", DimensionConverter.getIntegerPrefix("1.5sp"));
    assertEquals("sp", DimensionConverter.getUnitFromValue("1.5sp"));
    assertEquals(".5sp", converter.fromString(".5sp", context));
    assertEquals(".5", DimensionConverter.getIntegerPrefix(".5sp"));
    assertEquals("sp", DimensionConverter.getUnitFromValue(".5sp"));
    // Make sure the right type of decimal separator is used
    assertNull(converter.fromString("1,5sp", context));
    assertEquals("Use a dot instead of a comma as the decimal mark", converter.getErrorMessage("1,5sp", context));
    // Documentation
    assertEquals("<html><body>" + "<b>Density-independent Pixels</b> - an abstract unit that is based on the physical density of the screen." + "</body></html>", converter.getDocumentation("1dp"));
    assertEquals("<html><body>" + "<b>Pixels</b> - corresponds to actual pixels on the screen. Not recommended." + "</body></html>", converter.getDocumentation("-10px"));
    assertEquals("<html><body>" + "<b>Scale-independent Pixels</b> - this is like the dp unit, but " + "it is also scaled by the user's font size preference." + "</body></html>", converter.getDocumentation("1.5sp"));
}
Also used : StyleItem(org.jetbrains.android.dom.resources.StyleItem) ArrayList(java.util.ArrayList) DomInvocationHandler(com.intellij.util.xml.impl.DomInvocationHandler) ConvertContext(com.intellij.util.xml.ConvertContext)

Example 5 with StyleItem

use of org.jetbrains.android.dom.resources.StyleItem in project android by JetBrains.

the class ParentStyleUsageData method inline.

@Override
public void inline(@NotNull Map<AndroidAttributeInfo, String> attributeValues, @Nullable StyleRefData parentStyleRef) {
    final Map<String, String> id2Value = toId2ValueMap(attributeValues);
    for (StyleItem item : myStyle.getItems()) {
        final String name = item.getName().getStringValue();
        if (name != null) {
            id2Value.remove(name);
        }
    }
    for (Map.Entry<String, String> entry : id2Value.entrySet()) {
        final StyleItem newItem = myStyle.addItem();
        newItem.getName().setStringValue(entry.getKey());
        newItem.setStringValue(entry.getValue());
    }
    final String styleName = myStyle.getName().getStringValue();
    final boolean implicitInheritance = parentStyleRef != null && parentStyleRef.getStylePackage() == null && styleName != null && (styleName.startsWith(parentStyleRef.getStyleName() + ".") || styleName.equals(parentStyleRef.getStyleName()));
    myStyle.getParentStyle().setValue(parentStyleRef != null && !implicitInheritance ? ResourceValue.referenceTo((char) 0, parentStyleRef.getStylePackage(), null, parentStyleRef.getStyleName()) : null);
}
Also used : StyleItem(org.jetbrains.android.dom.resources.StyleItem) HashMap(com.intellij.util.containers.HashMap) Map(java.util.Map)

Aggregations

StyleItem (org.jetbrains.android.dom.resources.StyleItem)6 Result (com.intellij.openapi.application.Result)2 WriteCommandAction (com.intellij.openapi.command.WriteCommandAction)2 HashMap (com.intellij.util.containers.HashMap)2 ResourceElement (org.jetbrains.android.dom.resources.ResourceElement)2 Style (org.jetbrains.android.dom.resources.Style)2 Nullable (org.jetbrains.annotations.Nullable)2 ConfiguredThemeEditorStyle (com.android.tools.idea.editors.theme.datamodels.ConfiguredThemeEditorStyle)1 EditedStyleItem (com.android.tools.idea.editors.theme.datamodels.EditedStyleItem)1 UndoConfirmationPolicy (com.intellij.openapi.command.UndoConfirmationPolicy)1 Project (com.intellij.openapi.project.Project)1 VirtualFile (com.intellij.openapi.vfs.VirtualFile)1 PsiFile (com.intellij.psi.PsiFile)1 XmlAttribute (com.intellij.psi.xml.XmlAttribute)1 XmlTag (com.intellij.psi.xml.XmlTag)1 Processor (com.intellij.util.Processor)1 HashSet (com.intellij.util.containers.HashSet)1 ConvertContext (com.intellij.util.xml.ConvertContext)1 DomInvocationHandler (com.intellij.util.xml.impl.DomInvocationHandler)1 ArrayList (java.util.ArrayList)1