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;
}
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;
}
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;
}
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"));
}
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);
}
Aggregations