use of org.jetbrains.android.dom.wrappers.ValueResourceElementWrapper in project android by JetBrains.
the class NlIdPropertyItem method setValue.
@Override
public void setValue(Object value) {
String newId = value != null ? stripIdPrefix(value.toString()) : "";
String oldId = getValue();
XmlTag tag = getTag();
if (ourRefactoringChoice != REFACTOR_NO && oldId != null && !oldId.isEmpty() && !newId.isEmpty() && !oldId.equals(newId) && tag != null && tag.isValid()) {
// Offer rename refactoring?
XmlAttribute attribute = tag.getAttribute(SdkConstants.ATTR_ID, SdkConstants.ANDROID_URI);
if (attribute != null) {
Module module = getModel().getModule();
Project project = module.getProject();
XmlAttributeValue valueElement = attribute.getValueElement();
if (valueElement != null && valueElement.isValid()) {
// Exact replace only, no comment/text occurrence changes since it is non-interactive
ValueResourceElementWrapper wrapper = new ValueResourceElementWrapper(valueElement);
RenameProcessor processor = new RenameProcessor(project, wrapper, NEW_ID_PREFIX + newId, false, /*comments*/
false);
processor.setPreviewUsages(false);
// Do a quick usage search to see if we need to ask about renaming
UsageInfo[] usages = processor.findUsages();
if (usages.length > 0) {
int choice = ourRefactoringChoice;
if (choice == REFACTOR_ASK) {
DialogBuilder builder = createDialogBuilder(project);
builder.setTitle("Update Usages?");
// UGH!
JPanel panel = new JPanel(new BorderLayout());
JLabel label = new JLabel("<html>" + "Update usages as well?<br>" + "This will update all XML references and Java R field references.<br>" + "<br>" + "</html>");
panel.add(label, BorderLayout.CENTER);
JBCheckBox checkBox = new JBCheckBox("Don't ask again during this session");
panel.add(checkBox, BorderLayout.SOUTH);
builder.setCenterPanel(panel);
builder.setDimensionServiceKey("idPropertyDimension");
builder.removeAllActions();
DialogBuilder.CustomizableAction yesAction = builder.addOkAction();
yesAction.setText(Messages.YES_BUTTON);
builder.addActionDescriptor(dialogWrapper -> new AbstractAction(Messages.NO_BUTTON) {
@Override
public void actionPerformed(ActionEvent actionEvent) {
dialogWrapper.close(DialogWrapper.NEXT_USER_EXIT_CODE);
}
});
builder.addCancelAction();
int exitCode = builder.show();
choice = exitCode == DialogWrapper.OK_EXIT_CODE ? REFACTOR_YES : exitCode == DialogWrapper.NEXT_USER_EXIT_CODE ? REFACTOR_NO : ourRefactoringChoice;
//noinspection AssignmentToStaticFieldFromInstanceMethod
ourRefactoringChoice = checkBox.isSelected() ? choice : REFACTOR_ASK;
if (exitCode == DialogWrapper.CANCEL_EXIT_CODE) {
return;
}
}
if (choice == REFACTOR_YES) {
processor.run();
return;
}
}
}
}
}
super.setValue(!StringUtil.isEmpty(newId) ? NEW_ID_PREFIX + newId : null);
}
use of org.jetbrains.android.dom.wrappers.ValueResourceElementWrapper in project android by JetBrains.
the class AndroidRenameHandler method performValueResourceRenaming.
private static void performValueResourceRenaming(Project project, Editor editor, DataContext dataContext, XmlTag tag) {
final XmlAttribute nameAttribute = tag.getAttribute("name");
if (nameAttribute == null) {
return;
}
final XmlAttributeValue attributeValue = nameAttribute.getValueElement();
if (attributeValue == null) {
return;
}
RenameDialog.showRenameDialog(dataContext, new RenameDialog(project, new ValueResourceElementWrapper(attributeValue), null, editor));
}
use of org.jetbrains.android.dom.wrappers.ValueResourceElementWrapper in project android by JetBrains.
the class AndroidResourceRenameResourceProcessor method prepareResourceFieldRenaming.
private static void prepareResourceFieldRenaming(PsiField field, String newName, Map<PsiElement, String> allRenames) {
new RenameJavaVariableProcessor().prepareRenaming(field, newName, allRenames);
List<PsiElement> resources = AndroidResourceUtil.findResourcesByField(field);
PsiElement res = resources.get(0);
final String newResName;
if (res instanceof PsiFile) {
// Resource comes from XML file, don't need to suggest change underscores to dots
newResName = newName;
} else if (res instanceof XmlAttributeValue) {
newResName = getResourceName(field.getProject(), newName, ((XmlAttributeValue) res).getValue());
} else {
// AndroidResourceUtil.findResourcesByField supposed to return a list of PsiElements that are
// either PsiFile or XmlAttributeValue. Previous version of this code doesn't handle other
// possibilities at all and would crash with ClassCastException, having an explicit error message
// seems to be a slightly better option.
Logger.getInstance(AndroidResourceRenameResourceProcessor.class).error(String.format("%s: res is neither PsiFile nor XmlAttributeValue", AndroidResourceRenameResourceProcessor.class.getSimpleName()));
newResName = newName;
}
for (PsiElement resource : resources) {
if (resource instanceof PsiFile) {
PsiFile file = (PsiFile) resource;
String extension = FileUtilRt.getExtension(file.getName());
allRenames.put(resource, newResName + '.' + extension);
} else if (resource instanceof XmlAttributeValue) {
XmlAttributeValue value = (XmlAttributeValue) resource;
final String s = AndroidResourceUtil.isIdDeclaration(value) ? NEW_ID_PREFIX + newResName : newResName;
allRenames.put(new ValueResourceElementWrapper(value), s);
// we have to rename not just R.styleable.Foo but the also R.styleable.Foo_* attributes
if (value.getParent() instanceof XmlAttribute) {
XmlAttribute parent = (XmlAttribute) value.getParent();
XmlTag tag = parent.getParent();
if (tag.getName().equals(TAG_DECLARE_STYLEABLE)) {
AndroidFacet facet = AndroidFacet.getInstance(tag);
String oldName = tag.getAttributeValue(ATTR_NAME);
if (facet != null && oldName != null) {
for (XmlTag attr : tag.getSubTags()) {
if (attr.getName().equals(TAG_ATTR)) {
String name = attr.getAttributeValue(ATTR_NAME);
if (name != null) {
String oldAttributeName = oldName + '_' + name;
PsiField[] fields = AndroidResourceUtil.findResourceFields(facet, STYLEABLE.getName(), oldAttributeName, true);
if (fields.length > 0) {
String newAttributeName = newName + '_' + name;
for (PsiField f : fields) {
allRenames.put(f, newAttributeName);
}
}
}
}
}
}
}
}
}
}
}
use of org.jetbrains.android.dom.wrappers.ValueResourceElementWrapper in project android by JetBrains.
the class ThemeEditorStyle method getNamePsiElement.
/**
* Returns a PsiElement of the name attribute for this theme
* made from a RANDOM sourceXml
*/
@Nullable
public PsiElement getNamePsiElement() {
Collection<ResourceItem> resources = getStyleResourceItems();
if (resources.isEmpty()) {
return null;
}
// Any sourceXml will do to get the name attribute from
final XmlTag sourceXml = LocalResourceRepository.getItemTag(myManager.getProject(), resources.iterator().next());
assert sourceXml != null;
final XmlAttribute nameAttribute = sourceXml.getAttribute("name");
if (nameAttribute == null) {
return null;
}
XmlAttributeValue attributeValue = nameAttribute.getValueElement();
if (attributeValue == null) {
return null;
}
return new ValueResourceElementWrapper(attributeValue);
}
use of org.jetbrains.android.dom.wrappers.ValueResourceElementWrapper in project android by JetBrains.
the class AndroidResourceRenameResourceProcessor method prepareValueResourceRenaming.
private static void prepareValueResourceRenaming(PsiElement element, String newName, Map<PsiElement, String> allRenames, final AndroidFacet facet) {
ResourceManager manager = facet.getLocalResourceManager();
XmlTag tag = PsiTreeUtil.getParentOfType(element, XmlTag.class);
assert tag != null;
String type = manager.getValueResourceType(tag);
assert type != null;
Project project = tag.getProject();
DomElement domElement = DomManager.getDomManager(project).getDomElement(tag);
assert domElement instanceof ResourceElement;
String name = ((ResourceElement) domElement).getName().getValue();
assert name != null;
List<ResourceElement> resources = manager.findValueResources(type, name);
for (ResourceElement resource : resources) {
XmlElement xmlElement = resource.getName().getXmlAttributeValue();
if (!element.getManager().areElementsEquivalent(element, xmlElement)) {
allRenames.put(xmlElement, newName);
}
}
if (getResourceType(element) == ResourceType.STYLE) {
// For styles, try also to find child styles defined by name (i.e. "ParentName.StyleName") and add them
// to the rename list. This will allow the rename processor to also handle the references to those. For example,
// If you rename "MyTheme" and your manifest theme is "MyTheme.NoActionBar", this will make sure that
// the reference from the manifest is also updated by adding "MyTheme.NoActionBar" to the rename list.
// We iterate the styles in order to cascade any changes to children down the hierarchy.
// List of styles that will be renamed.
HashSet<String> renamedStyles = Sets.newHashSet();
renamedStyles.add(name);
final String stylePrefix = name + ".";
Collection<String> renameCandidates;
ResourceType resourceType = ResourceType.getEnum(type);
if (resourceType == null) {
renameCandidates = Collections.emptyList();
} else {
renameCandidates = Collections2.filter(manager.getResourceNames(resourceType), new Predicate<String>() {
@Override
public boolean apply(String input) {
return input.startsWith(stylePrefix);
}
});
}
for (String resourceName : ORDER_BY_LENGTH.sortedCopy(renameCandidates)) {
// resourceName.lastIndexOf will never return -1 because we've filtered all names that
// do not contain stylePrefix
String parentName = resourceName.substring(0, resourceName.lastIndexOf('.'));
if (!renamedStyles.contains(parentName)) {
// This resource's parent wasn't affected by the rename
continue;
}
for (ResourceElement resource : manager.findValueResources(type, resourceName)) {
if (!(resource instanceof Style) || ((Style) resource).getParentStyle().getXmlAttributeValue() != null) {
// This element is not a style or does have an explicit parent so we do not rename it.
continue;
}
XmlAttributeValue xmlElement = resource.getName().getXmlAttributeValue();
if (xmlElement != null) {
String newStyleName = newName + StringUtil.trimStart(resourceName, name);
allRenames.put(new ValueResourceElementWrapper(xmlElement), newStyleName);
renamedStyles.add(resourceName);
}
}
}
}
PsiField[] resFields = AndroidResourceUtil.findResourceFieldsForValueResource(tag, false);
for (PsiField resField : resFields) {
String escaped = AndroidResourceUtil.getFieldNameByResourceName(newName);
allRenames.put(resField, escaped);
}
// Also rename the dependent fields, e.g. if you rename <declare-styleable name="Foo">,
// we have to rename not just R.styleable.Foo but the also R.styleable.Foo_* attributes
PsiField[] styleableFields = AndroidResourceUtil.findStyleableAttributeFields(tag, false);
if (styleableFields.length > 0) {
String tagName = tag.getName();
boolean isDeclareStyleable = tagName.equals(TAG_DECLARE_STYLEABLE);
boolean isAttr = !isDeclareStyleable && tagName.equals(TAG_ATTR) && tag.getParentTag() != null;
assert isDeclareStyleable || isAttr;
String style = isAttr ? tag.getParentTag().getAttributeValue(ATTR_NAME) : null;
for (PsiField resField : styleableFields) {
String fieldName = resField.getName();
String newAttributeName;
if (isDeclareStyleable && fieldName.startsWith(name)) {
newAttributeName = newName + fieldName.substring(name.length());
} else if (isAttr && style != null) {
newAttributeName = style + '_' + newName;
} else {
newAttributeName = name;
}
String escaped = AndroidResourceUtil.getFieldNameByResourceName(newAttributeName);
allRenames.put(resField, escaped);
}
}
}
Aggregations