diff --git a/plugins/android/resources/messages/AndroidBundle.properties b/plugins/android/resources/messages/AndroidBundle.properties
index ebfbde4a815e..6fe79781fabd 100644
--- a/plugins/android/resources/messages/AndroidBundle.properties
+++ b/plugins/android/resources/messages/AndroidBundle.properties
@@ -412,4 +412,5 @@ deployment.target.settings.min.sdk.info.message=Only compatible AVDs are shown.
android.compilation.warning.circular.app.dependency=Generated fields in {0}.R class in module ''{1}'' won''t be final, because of circular dependency on module ''{2}''
cannot.find.zip.align=The zipalign tool was not found in the SDK.\n\nPlease update to the latest SDK and re-export your application\nor run zipalign manually.\n\nAligning applications allows Android to use application resources\nmore efficiently.
file.name.not.specified.error=File name is not specified
-root.element.not.specified.error=Root element is not specified
\ No newline at end of file
+root.element.not.specified.error=Root element is not specified
+directory.not.specified.error=Directory is not specified
\ No newline at end of file
diff --git a/plugins/android/src/META-INF/plugin.xml b/plugins/android/src/META-INF/plugin.xml
index 3315888cb0df..4700bd2e5eec 100644
--- a/plugins/android/src/META-INF/plugin.xml
+++ b/plugins/android/src/META-INF/plugin.xml
@@ -219,6 +219,8 @@
+
+
diff --git a/plugins/android/src/org/jetbrains/android/AndroidGotoDeclarationHandler.java b/plugins/android/src/org/jetbrains/android/AndroidGotoDeclarationHandler.java
index d73c45ffb5ab..9b23a4cc2c3a 100644
--- a/plugins/android/src/org/jetbrains/android/AndroidGotoDeclarationHandler.java
+++ b/plugins/android/src/org/jetbrains/android/AndroidGotoDeclarationHandler.java
@@ -19,7 +19,11 @@ import com.intellij.codeInsight.navigation.actions.GotoDeclarationHandler;
import com.intellij.navigation.NavigationItem;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.editor.Editor;
-import com.intellij.psi.*;
+import com.intellij.openapi.util.Pair;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiFile;
+import com.intellij.psi.PsiIdentifier;
+import com.intellij.psi.PsiReferenceExpression;
import com.intellij.psi.meta.PsiMetaOwner;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.xml.XmlAttributeValue;
@@ -27,7 +31,6 @@ import org.jetbrains.android.dom.wrappers.FileResourceElementWrapper;
import org.jetbrains.android.dom.wrappers.ValueResourceElementWrapper;
import org.jetbrains.android.facet.AndroidFacet;
import org.jetbrains.android.util.AndroidResourceUtil;
-import org.jetbrains.android.util.AndroidUtils;
import java.util.List;
@@ -51,47 +54,22 @@ public class AndroidGotoDeclarationHandler implements GotoDeclarationHandler {
return null;
}
- final String resFieldName = refExp.getReferenceName();
- if (resFieldName == null || resFieldName.length() == 0) {
- return null;
- }
-
- PsiExpression qExp = refExp.getQualifierExpression();
- if (!(qExp instanceof PsiReferenceExpression)) {
- return null;
- }
- final PsiReferenceExpression resClassReference = (PsiReferenceExpression)qExp;
-
- final String resClassName = resClassReference.getReferenceName();
- if (resClassName == null || resClassName.length() == 0) {
- return null;
- }
-
- qExp = resClassReference.getQualifierExpression();
- if (!(qExp instanceof PsiReferenceExpression)) {
- return null;
- }
-
- final PsiElement resolvedElement = ((PsiReferenceExpression)qExp).resolve();
- if (!(resolvedElement instanceof PsiClass) ||
- !AndroidUtils.R_CLASS_NAME.equals(((PsiClass)resolvedElement).getName())) {
- return null;
- }
-
- final PsiFile containingFile = resolvedElement.getContainingFile();
- if (containingFile == null || !AndroidResourceUtil.isRJavaFile(facet, containingFile)) {
+ final Pair pair = AndroidResourceUtil.getReferredResourceField(facet, refExp);
+ if (pair == null) {
return null;
}
+ final String resClassName = pair.getFirst();
+ final String resFieldName = pair.getSecond();
final List resourceList = facet.getLocalResourceManager().findResourcesByFieldName(resClassName, resFieldName);
final PsiElement[] resources = resourceList.toArray(new PsiElement[resourceList.size()]);
final PsiElement[] wrappedResources = new PsiElement[resources.length];
-
+
for (int i = 0; i < resources.length; i++) {
final PsiElement resource = resources[i];
-
- if (resource instanceof XmlAttributeValue &&
- resource instanceof PsiMetaOwner &&
+
+ if (resource instanceof XmlAttributeValue &&
+ resource instanceof PsiMetaOwner &&
resource instanceof NavigationItem) {
wrappedResources[i] = new ValueResourceElementWrapper((XmlAttributeValue)resource);
}
diff --git a/plugins/android/src/org/jetbrains/android/actions/AndroidCreateLayoutFileAction.java b/plugins/android/src/org/jetbrains/android/actions/AndroidCreateLayoutFileAction.java
index 77de2e06e5b0..3e11642979a6 100644
--- a/plugins/android/src/org/jetbrains/android/actions/AndroidCreateLayoutFileAction.java
+++ b/plugins/android/src/org/jetbrains/android/actions/AndroidCreateLayoutFileAction.java
@@ -16,6 +16,7 @@
package org.jetbrains.android.actions;
+import com.android.resources.ResourceFolderType;
import com.android.resources.ResourceType;
import com.intellij.CommonBundle;
import com.intellij.facet.ProjectFacetManager;
@@ -57,7 +58,7 @@ public class AndroidCreateLayoutFileAction extends CreateTypedResourceFileAction
private String myLastRootComponentName;
public AndroidCreateLayoutFileAction() {
- super("Layout", "layout", "LinearLayout", false, false);
+ super("Layout", ResourceFolderType.LAYOUT, false, false);
}
@NotNull
@@ -75,7 +76,7 @@ public class AndroidCreateLayoutFileAction extends CreateTypedResourceFileAction
@Override
protected PsiElement[] create(String newName, PsiDirectory directory) throws Exception {
assert myLastRootComponentName != null;
- return doCreate(newName, directory, myLastRootComponentName, false);
+ return doCreateAndNavigate(newName, directory, myLastRootComponentName, false);
}
@Override
diff --git a/plugins/android/src/org/jetbrains/android/actions/CreateResourceDialog.java b/plugins/android/src/org/jetbrains/android/actions/CreateResourceDialog.java
index 13239b7c5a48..68b7e5c6187a 100644
--- a/plugins/android/src/org/jetbrains/android/actions/CreateResourceDialog.java
+++ b/plugins/android/src/org/jetbrains/android/actions/CreateResourceDialog.java
@@ -73,15 +73,19 @@ public class CreateResourceDialog extends DialogWrapper {
private final Map myResType2ActionMap = new HashMap();
private final DeviceConfiguratorPanel myDeviceConfiguratorPanel;
private final AndroidFacet myFacet;
+ private final ResourceType myPredefinedResourceType;
public CreateResourceDialog(@NotNull AndroidFacet facet,
Collection actions,
@Nullable ResourceType predefinedResourceType,
@Nullable String predefinedFileName,
+ boolean chooseFileName,
@NotNull Module module,
boolean chooseModule) {
super(facet.getModule().getProject());
myFacet = facet;
+ myPredefinedResourceType = predefinedResourceType;
+
myResTypeLabel.setLabelFor(myResourceTypeCombo);
myResourceTypeCombo.registerUpDownHint(myFileNameField);
myUpDownHint.setIcon(PlatformIcons.UP_DOWN_ARROWS);
@@ -137,7 +141,7 @@ public class CreateResourceDialog extends DialogWrapper {
@Override
public void actionPerformed(ActionEvent e) {
myDeviceConfiguratorPanel.applyEditors();
- updateRootElementCombo();
+ updateRootElementTextField();
}
});
@@ -153,8 +157,10 @@ public class CreateResourceDialog extends DialogWrapper {
}
if (predefinedFileName != null) {
- myFileNameField.setVisible(false);
- myFileNameLabel.setVisible(false);
+ if (!chooseFileName) {
+ myFileNameField.setVisible(false);
+ myFileNameLabel.setVisible(false);
+ }
myFileNameField.setText(predefinedFileName);
}
@@ -183,11 +189,13 @@ public class CreateResourceDialog extends DialogWrapper {
myDeviceConfiguratorPanel.updateAll();
myDeviceConfiguratorWrapper.add(myDeviceConfiguratorPanel, BorderLayout.CENTER);
setOKActionEnabled(myDirectoryNameTextField.getText().length() > 0);
- updateRootElementCombo();
+ updateRootElementTextField();
init();
+
+ setTitle(AndroidBundle.message("new.resource.dialog.title"));
}
- private void updateRootElementCombo() {
+ private void updateRootElementTextField() {
final CreateTypedResourceFileAction action = getSelectedAction();
if (action != null) {
@@ -195,12 +203,19 @@ public class CreateResourceDialog extends DialogWrapper {
myRootElementField = new TextFieldWithAutoCompletion(
myFacet.getModule().getProject(), new TextFieldWithAutoCompletion.StringsCompletionProvider(allowedTagNames, null), true);
myRootElementField.setEnabled(allowedTagNames.size() > 1);
- myRootElementField.setText(!action.isChooseTagName() ? action.getDefaultRootTag() : "");
+ myRootElementField.setText(!action.isChooseTagName() && myPredefinedResourceType != ResourceType.LAYOUT
+ ? action.getDefaultRootTag()
+ : "");
myRootElementFieldWrapper.removeAll();
myRootElementFieldWrapper.add(myRootElementField, BorderLayout.CENTER);
}
}
+ @NotNull
+ public String getFileName() {
+ return myFileNameField.getText().trim();
+ }
+
private static boolean containsElement(@NotNull ListModel model, @NotNull Object objectToFind) {
for (int i = 0, n = model.getSize(); i < n; i++) {
if (objectToFind.equals(model.getElementAt(i))) {
@@ -232,7 +247,10 @@ public class CreateResourceDialog extends DialogWrapper {
}
final String subdirName = getSubdirName();
- assert subdirName.length() > 0;
+ if (subdirName.length() == 0) {
+ Messages.showErrorDialog(myPanel, AndroidBundle.message("directory.not.specified.error"), CommonBundle.getErrorTitle());
+ return;
+ }
myValidator = createValidator(subdirName);
if (myValidator == null || myValidator.checkInput(fileName) && myValidator.canClose(fileName)) {
super.doOKAction();
@@ -266,7 +284,7 @@ public class CreateResourceDialog extends DialogWrapper {
@Override
public JComponent getPreferredFocusedComponent() {
- if (myFileNameField.isVisible()) {
+ if (myFileNameField.getText().length() == 0) {
return myFileNameField;
}
else if (myResourceTypeCombo.isVisible()) {
@@ -275,7 +293,10 @@ public class CreateResourceDialog extends DialogWrapper {
else if (myModuleCombo.isVisible()) {
return myModuleCombo;
}
- return myDeviceConfiguratorPanel.getAvailableQualifiersList();
+ else if (myRootElementFieldWrapper.isVisible()) {
+ return myRootElementField;
+ }
+ return myDirectoryNameTextField;
}
public CreateTypedResourceFileAction getSelectedAction() {
diff --git a/plugins/android/src/org/jetbrains/android/actions/CreateResourceFileAction.java b/plugins/android/src/org/jetbrains/android/actions/CreateResourceFileAction.java
index ce3d080544ff..b8a3218f0e99 100644
--- a/plugins/android/src/org/jetbrains/android/actions/CreateResourceFileAction.java
+++ b/plugins/android/src/org/jetbrains/android/actions/CreateResourceFileAction.java
@@ -30,6 +30,7 @@ import com.intellij.openapi.fileTypes.StdFileTypes;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.InputValidator;
+import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.util.Computable;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.vfs.VirtualFile;
@@ -90,39 +91,48 @@ public class CreateResourceFileAction extends CreateElementActionBase {
});
}
- // must be invoked in a write action
- public static PsiElement[] createResourceFile(final Project project,
- @NotNull AndroidFacet facet,
+ @NotNull
+ public static PsiElement[] createFileResource(@NotNull AndroidFacet facet,
@NotNull final ResourceType resType,
@NotNull String resName,
- boolean chooseDirectory) {
+ boolean chooseResName) {
final CreateResourceFileAction action = getInstance();
- String subdirName = resType.getName();
- VirtualFile resourceDir = facet.getLocalResourceManager().getResourceDir();
-
- if (chooseDirectory) {
- final MyDialog dialog = new MyDialog(facet, action.mySubactions.values(), resType, resName, action, facet.getModule(), true);
- dialog.setTitle(AndroidBundle.message("new.resource.dialog.title"));
- dialog.show();
- if (!dialog.isOK()) {
- return PsiElement.EMPTY_ARRAY;
- }
- subdirName = dialog.getSubdirName();
- final AndroidFacet selectedFacet = AndroidFacet.getInstance(dialog.getSelectedModule());
- LOG.assertTrue(selectedFacet != null);
- resourceDir = selectedFacet.getLocalResourceManager().getResourceDir();
+ final MyDialog dialog =
+ new MyDialog(facet, action.mySubactions.values(), resType, resName, chooseResName, action, facet.getModule(), true);
+ dialog.show();
+ if (!dialog.isOK()) {
+ return PsiElement.EMPTY_ARRAY;
}
- if (resourceDir != null) {
- final PsiDirectory psiResDir = PsiManager.getInstance(project).findDirectory(resourceDir);
- if (psiResDir != null) {
- CreateElementActionBase.MyInputValidator validator = action.createValidator(project, psiResDir, subdirName);
- if (validator.checkInput(resName) && validator.canClose(resName)) {
- return validator.getCreatedElements();
- }
- }
+ if (chooseResName) {
+ resName = dialog.getFileName();
}
- return PsiElement.EMPTY_ARRAY;
+ final String subdirName = dialog.getSubdirName();
+ final AndroidFacet selectedFacet = AndroidFacet.getInstance(dialog.getSelectedModule());
+ LOG.assertTrue(selectedFacet != null);
+
+ final VirtualFile resourceDir = selectedFacet.getLocalResourceManager().getResourceDir();
+ final Project project = facet.getModule().getProject();
+ final PsiDirectory psiResDir = resourceDir != null ? PsiManager.getInstance(project).findDirectory(resourceDir) : null;
+
+ if (psiResDir == null) {
+ Messages.showErrorDialog(project, "Cannot find resource directory for module " + selectedFacet.getModule().getName(),
+ CommonBundle.getErrorTitle());
+ return PsiElement.EMPTY_ARRAY;
+ }
+ final String finalResName = resName;
+
+ final PsiElement[] elements = ApplicationManager.getApplication().runWriteAction(new Computable() {
+ @Nullable
+ @Override
+ public PsiElement[] compute() {
+ MyInputValidator validator = action.createValidator(project, psiResDir, subdirName);
+ return validator.checkInput(finalResName) && validator.canClose(finalResName)
+ ? validator.getCreatedElements()
+ : null;
+ }
+ });
+ return elements != null ? elements : PsiElement.EMPTY_ARRAY;
}
@NotNull
@@ -131,13 +141,13 @@ public class CreateResourceFileAction extends CreateElementActionBase {
final AndroidFacet facet = AndroidFacet.getInstance(directory);
LOG.assertTrue(facet != null);
- MyDialog dialog = new MyDialog(facet, mySubactions.values(), null, null, CreateResourceFileAction.this, facet.getModule(), false) {
+ final MyDialog dialog =
+ new MyDialog(facet, mySubactions.values(), null, null, true, CreateResourceFileAction.this, facet.getModule(), false) {
@Override
protected InputValidator createValidator(@NotNull String subdirName) {
return CreateResourceFileAction.this.createValidator(project, directory, subdirName);
}
};
- dialog.setTitle(AndroidBundle.message("new.resource.dialog.title"));
dialog.show();
return PsiElement.EMPTY_ARRAY;
}
@@ -159,8 +169,11 @@ public class CreateResourceFileAction extends CreateElementActionBase {
@Override
protected PsiElement[] create(String newName, PsiDirectory directory) throws Exception {
CreateTypedResourceFileAction action = getActionByDir(directory);
+ if (action == null) {
+ throw new IllegalArgumentException("Incorrect directory");
+ }
if (myRootElement != null && myRootElement.length() > 0) {
- return action.doCreate(newName, directory, myRootElement, false);
+ return action.doCreateAndNavigate(newName, directory, myRootElement, false);
}
return action.create(newName, directory);
}
@@ -204,10 +217,11 @@ public class CreateResourceFileAction extends CreateElementActionBase {
Collection actions,
@Nullable ResourceType predefinedResourceType,
@Nullable String predefinedFileName,
+ boolean chooseFileName,
@NotNull CreateResourceFileAction action,
@NotNull Module module,
boolean chooseModule) {
- super(facet, actions, predefinedResourceType, predefinedFileName, module, chooseModule);
+ super(facet, actions, predefinedResourceType, predefinedFileName, chooseFileName, module, chooseModule);
myAction = action;
}
diff --git a/plugins/android/src/org/jetbrains/android/actions/CreateResourceFileActionGroup.java b/plugins/android/src/org/jetbrains/android/actions/CreateResourceFileActionGroup.java
index 5024481ba13b..22c21899cf1a 100644
--- a/plugins/android/src/org/jetbrains/android/actions/CreateResourceFileActionGroup.java
+++ b/plugins/android/src/org/jetbrains/android/actions/CreateResourceFileActionGroup.java
@@ -16,6 +16,7 @@
package org.jetbrains.android.actions;
+import com.android.resources.ResourceFolderType;
import com.intellij.openapi.actionSystem.DefaultActionGroup;
import org.jetbrains.android.dom.animation.AndroidAnimationUtils;
import org.jetbrains.android.dom.animator.AndroidAnimatorUtil;
@@ -40,7 +41,7 @@ public class CreateResourceFileActionGroup extends DefaultActionGroup {
CreateResourceFileAction a = new CreateResourceFileAction();
a.add(new AndroidCreateLayoutFileAction());
- a.add(new CreateTypedResourceFileAction("XML", "xml", "PreferenceScreen", false, true) {
+ a.add(new CreateTypedResourceFileAction("XML", ResourceFolderType.XML, false, true) {
@NotNull
@Override
public List getAllowedTagNames(@NotNull AndroidFacet facet) {
@@ -48,7 +49,7 @@ public class CreateResourceFileActionGroup extends DefaultActionGroup {
}
});
- a.add(new CreateTypedResourceFileAction("Drawable", "drawable", "selector", false, true) {
+ a.add(new CreateTypedResourceFileAction("Drawable", ResourceFolderType.DRAWABLE, false, true) {
@NotNull
@Override
public List getAllowedTagNames(@NotNull AndroidFacet facet) {
@@ -56,11 +57,11 @@ public class CreateResourceFileActionGroup extends DefaultActionGroup {
}
});
- a.add(new CreateTypedResourceFileAction("Color", "color", "selector", false, false));
- a.add(new CreateTypedResourceFileAction("Values", "values", "resources", true, false));
- a.add(new CreateTypedResourceFileAction("Menu", "menu", "menu", false, false));
+ a.add(new CreateTypedResourceFileAction("Color", ResourceFolderType.COLOR, false, false));
+ a.add(new CreateTypedResourceFileAction("Values", ResourceFolderType.VALUES, true, false));
+ a.add(new CreateTypedResourceFileAction("Menu", ResourceFolderType.MENU, false, false));
- a.add(new CreateTypedResourceFileAction("Animation", "anim", "set", false, true) {
+ a.add(new CreateTypedResourceFileAction("Animation", ResourceFolderType.ANIM, false, true) {
@NotNull
@Override
public List getAllowedTagNames(@NotNull AndroidFacet facet) {
@@ -68,7 +69,7 @@ public class CreateResourceFileActionGroup extends DefaultActionGroup {
}
});
- a.add(new CreateTypedResourceFileAction("Animator", "animator", "set", false, true) {
+ a.add(new CreateTypedResourceFileAction("Animator", ResourceFolderType.ANIMATOR, false, true) {
@NotNull
@Override
public List getAllowedTagNames(@NotNull AndroidFacet facet) {
diff --git a/plugins/android/src/org/jetbrains/android/actions/CreateTypedResourceFileAction.java b/plugins/android/src/org/jetbrains/android/actions/CreateTypedResourceFileAction.java
index 5c32c6de9de6..f59644879537 100644
--- a/plugins/android/src/org/jetbrains/android/actions/CreateTypedResourceFileAction.java
+++ b/plugins/android/src/org/jetbrains/android/actions/CreateTypedResourceFileAction.java
@@ -16,11 +16,9 @@
package org.jetbrains.android.actions;
+import com.android.resources.ResourceFolderType;
import com.intellij.CommonBundle;
import com.intellij.ide.actions.CreateElementActionBase;
-import com.intellij.ide.fileTemplates.FileTemplate;
-import com.intellij.ide.fileTemplates.FileTemplateManager;
-import com.intellij.ide.fileTemplates.FileTemplateUtil;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.actionSystem.LangDataKeys;
import com.intellij.openapi.application.ApplicationManager;
@@ -38,7 +36,6 @@ import com.intellij.psi.xml.XmlFile;
import com.intellij.psi.xml.XmlTag;
import com.intellij.util.PsiNavigateUtil;
import com.intellij.xml.refactoring.XmlTagInplaceRenamer;
-import org.jetbrains.android.AndroidFileTemplateProvider;
import org.jetbrains.android.facet.AndroidFacet;
import org.jetbrains.android.util.AndroidBundle;
import org.jetbrains.android.util.AndroidResourceUtil;
@@ -48,36 +45,33 @@ import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
-import java.util.Properties;
/**
* @author Eugene.Kudelevsky
*/
public class CreateTypedResourceFileAction extends CreateElementActionBase {
- static final String ROOT_TAG_PROPERTY = "ROOT_TAG";
- private final String myResourceType;
+ private final ResourceFolderType myResourceType;
private final String myResourcePresentableName;
protected final String myDefaultRootTag;
private final boolean myValuesResourceFile;
private final boolean myChooseTagName;
public CreateTypedResourceFileAction(@NotNull String resourcePresentableName,
- @NotNull String resourceType,
- @NotNull String defaultRootTag,
+ @NotNull ResourceFolderType resourceFolderType,
boolean valuesResourceFile,
boolean chooseTagName) {
super(AndroidBundle.message("new.typed.resource.action.title", resourcePresentableName),
AndroidBundle.message("new.typed.resource.action.description", resourcePresentableName), StdFileTypes.XML.getIcon());
- myResourceType = resourceType;
+ myResourceType = resourceFolderType;
myResourcePresentableName = resourcePresentableName;
- myDefaultRootTag = defaultRootTag;
+ myDefaultRootTag = getDefaultRootTabByResourceType(resourceFolderType);
myValuesResourceFile = valuesResourceFile;
myChooseTagName = chooseTagName;
}
public String getResourceType() {
- return myResourceType;
+ return myResourceType.getName();
}
@NotNull
@@ -93,20 +87,12 @@ public class CreateTypedResourceFileAction extends CreateElementActionBase {
@NotNull
@Override
protected PsiElement[] create(String newName, PsiDirectory directory) throws Exception {
- return doCreate(newName, directory, myDefaultRootTag, myChooseTagName);
+ return doCreateAndNavigate(newName, directory, myDefaultRootTag, myChooseTagName);
}
- PsiElement[] doCreate(String newName, PsiDirectory directory, String rootTagName, boolean chooseTagName) throws Exception {
- FileTemplateManager manager = FileTemplateManager.getInstance();
- String templateName = getTemplateName();
- FileTemplate template = manager.getJ2eeTemplate(templateName);
- Properties properties = new Properties();
- if (!myValuesResourceFile) {
- properties.setProperty(ROOT_TAG_PROPERTY, rootTagName);
- }
- PsiElement createdElement = FileTemplateUtil.createFromTemplate(template, newName, properties, directory);
- assert createdElement instanceof XmlFile;
- final XmlFile file = (XmlFile)createdElement;
+ PsiElement[] doCreateAndNavigate(String newName, PsiDirectory directory, String rootTagName, boolean chooseTagName) throws Exception {
+ final XmlFile file = AndroidResourceUtil
+ .createFileResource(newName, directory, rootTagName, myResourceType.getName(), myValuesResourceFile);
doNavigate(file);
if (chooseTagName) {
@@ -124,26 +110,16 @@ public class CreateTypedResourceFileAction extends CreateElementActionBase {
}
}
}
- return new PsiElement[]{createdElement};
+ return new PsiElement[]{file};
}
protected void doNavigate(XmlFile file) {
PsiNavigateUtil.navigate(file);
}
- private String getTemplateName() {
- if (myValuesResourceFile) {
- return AndroidFileTemplateProvider.VALUE_RESOURCE_FILE_TEMPLATE;
- }
- if ("layout".equals(myResourceType)) {
- return AndroidFileTemplateProvider.LAYOUT_RESOURCE_FILE_TEMPLATE;
- }
- return AndroidFileTemplateProvider.RESOURCE_FILE_TEMPLATE;
- }
-
@Override
protected boolean isAvailable(DataContext context) {
- return super.isAvailable(context) && doIsAvailable(context, myResourceType);
+ return super.isAvailable(context) && doIsAvailable(context, myResourceType.getName());
}
public boolean isChooseTagName() {
@@ -202,4 +178,28 @@ public class CreateTypedResourceFileAction extends CreateElementActionBase {
public String toString() {
return myResourcePresentableName;
}
+
+ @NotNull
+ public static String getDefaultRootTabByResourceType(@NotNull ResourceFolderType resourceType) {
+ switch (resourceType) {
+ case XML:
+ return "PreferenceScreen";
+ case DRAWABLE:
+ return "selector";
+ case COLOR:
+ return "selector";
+ case VALUES:
+ return "resources";
+ case MENU:
+ return "menu";
+ case ANIM:
+ return "set";
+ case ANIMATOR:
+ return "set";
+ case LAYOUT:
+ return "LinearLayout";
+ default:
+ }
+ throw new IllegalArgumentException("Incorrect resource folder type");
+ }
}
diff --git a/plugins/android/src/org/jetbrains/android/actions/CreateXmlResourceDialog.java b/plugins/android/src/org/jetbrains/android/actions/CreateXmlResourceDialog.java
index ab2e43d7f575..227d9075738b 100644
--- a/plugins/android/src/org/jetbrains/android/actions/CreateXmlResourceDialog.java
+++ b/plugins/android/src/org/jetbrains/android/actions/CreateXmlResourceDialog.java
@@ -83,13 +83,16 @@ public class CreateXmlResourceDialog extends DialogWrapper {
public CreateXmlResourceDialog(@NotNull Module module,
@NotNull ResourceType resourceType,
@Nullable String predefinedName,
- @Nullable String predefinedValue) {
+ @Nullable String predefinedValue,
+ boolean chooseName) {
super(module.getProject());
myResourceType = resourceType;
if (predefinedName != null && predefinedName.length() > 0) {
- myNameLabel.setVisible(false);
- myNameField.setVisible(false);
+ if (!chooseName) {
+ myNameLabel.setVisible(false);
+ myNameField.setVisible(false);
+ }
myNameField.setText(predefinedName);
}
@@ -390,7 +393,7 @@ public class CreateXmlResourceDialog extends DialogWrapper {
@Override
public JComponent getPreferredFocusedComponent() {
- return myNameField.isVisible() ? myNameField : myValueField;
+ return myNameField.getText().length() == 0 ? myNameField : myValueField;
}
@Override
diff --git a/plugins/android/src/org/jetbrains/android/dom/converters/ResourceReferenceConverter.java b/plugins/android/src/org/jetbrains/android/dom/converters/ResourceReferenceConverter.java
index 2c97811d6614..af899538c7a6 100644
--- a/plugins/android/src/org/jetbrains/android/dom/converters/ResourceReferenceConverter.java
+++ b/plugins/android/src/org/jetbrains/android/dom/converters/ResourceReferenceConverter.java
@@ -15,38 +15,26 @@
*/
package org.jetbrains.android.dom.converters;
-import com.android.AndroidConstants;
import com.android.resources.ResourceType;
-import com.intellij.codeInsight.intention.IntentionAction;
import com.intellij.codeInspection.LocalQuickFix;
-import com.intellij.codeInspection.ProblemDescriptor;
-import com.intellij.openapi.application.ApplicationManager;
-import com.intellij.openapi.command.undo.UndoUtil;
import com.intellij.openapi.components.ServiceManager;
-import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.module.Module;
-import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VirtualFile;
-import com.intellij.psi.PsiDocumentManager;
import com.intellij.psi.PsiElement;
-import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiReference;
import com.intellij.psi.xml.XmlAttribute;
import com.intellij.psi.xml.XmlElement;
import com.intellij.psi.xml.XmlTag;
-import com.intellij.util.IncorrectOperationException;
import com.intellij.util.xml.*;
-import org.jetbrains.android.actions.CreateXmlResourceDialog;
import org.jetbrains.android.dom.AdditionalConverter;
import org.jetbrains.android.dom.AndroidResourceType;
-import org.jetbrains.android.dom.resources.Item;
-import org.jetbrains.android.dom.resources.ResourceElement;
import org.jetbrains.android.dom.resources.ResourceValue;
import org.jetbrains.android.facet.AndroidFacet;
+import org.jetbrains.android.inspections.CreateFileResourceQuickFix;
+import org.jetbrains.android.inspections.CreateValueResourceQuickFix;
import org.jetbrains.android.resourceManagers.LocalResourceManager;
import org.jetbrains.android.resourceManagers.ResourceManager;
-import org.jetbrains.android.util.AndroidBundle;
import org.jetbrains.android.util.AndroidCommonUtils;
import org.jetbrains.android.util.AndroidResourceUtil;
import org.jetbrains.annotations.NonNls;
@@ -61,11 +49,6 @@ import static org.jetbrains.android.util.AndroidUtils.SYSTEM_RESOURCE_PACKAGE;
* @author yole
*/
public class ResourceReferenceConverter extends ResolvingConverter implements CustomReferenceConverter {
- private static final Set XML_FILE_RESOURCE_TYPES = EnumSet.of(ResourceType.ANIM, ResourceType.ANIMATOR,
- ResourceType.INTERPOLATOR, ResourceType.LAYOUT,
- ResourceType.MENU, ResourceType.XML, ResourceType.COLOR,
- ResourceType.DRAWABLE);
-
private final List myResourceTypes;
private ResolvingConverter myAdditionalConverter;
private boolean myAdditionalConverterSoft = false;
@@ -313,10 +296,10 @@ public class ResourceReferenceConverter extends ResolvingConverter fixes = new ArrayList();
if (AndroidResourceUtil.VALUE_RESOURCE_TYPES.contains(resType)) {
- fixes.add(new MyCreateValueResourceQuickFix(facet, resType, resourceName, context.getFile()));
+ fixes.add(new CreateValueResourceQuickFix(facet, resType, resourceName, context.getFile(), false));
}
- if (XML_FILE_RESOURCE_TYPES.contains(resType)) {
- fixes.add(new MyCreateFileResourceQuickFix(facet, resType, resourceName, context.getFile()));
+ if (AndroidResourceUtil.XML_FILE_RESOURCE_TYPES.contains(resType)) {
+ fixes.add(new CreateFileResourceQuickFix(facet, resType, resourceName, context.getFile(), false));
}
return fixes.toArray(new LocalQuickFix[fixes.size()]);
}
@@ -350,163 +333,4 @@ public class ResourceReferenceConverter extends ResolvingConverter list = manager.findValueResources(myResourceType.getName(), myResourceName);
- if (list.size() == 1) {
- ResourceElement element = list.get(0);
- XmlTag tag = element.getXmlTag();
- tag.getValue().setText("");
- }
- }
- }
- UndoUtil.markPsiFileForUndo(myFile);
- }
- }
-
- public static class MyCreateFileResourceQuickFix implements LocalQuickFix, IntentionAction {
- private final AndroidFacet myFacet;
- private final ResourceType myResourceType;
- private final String myResourceName;
- private final PsiFile myFile;
-
- public MyCreateFileResourceQuickFix(@NotNull AndroidFacet facet,
- @NotNull ResourceType resourceType,
- @NotNull String resourceName,
- @NotNull PsiFile file) {
- myFacet = facet;
- myResourceType = resourceType;
- myResourceName = resourceName;
- myFile = file;
- }
-
- @NotNull
- public String getName() {
- return AndroidBundle.message("create.file.resource.quickfix.name", myResourceName,
- '\'' + myResourceType.getName() + "' directory");
- }
-
- @NotNull
- @Override
- public String getText() {
- return AndroidBundle.message("create.file.resource.intention.name", myResourceType, myResourceName + ".xml");
- }
-
- @NotNull
- public String getFamilyName() {
- return AndroidBundle.message("quick.fixes.family");
- }
-
- @Override
- public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) {
- return true;
- }
-
- @Override
- public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException {
- // simplified resource creating for batch mode
- myFacet.getLocalResourceManager().addResourceFileAndNavigate(myResourceName, myResourceType, true);
- UndoUtil.markPsiFileForUndo(myFile);
- }
-
- @Override
- public boolean startInWriteAction() {
- return true;
- }
-
- public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
- // simplified resource creating for batch mode
- myFacet.getLocalResourceManager().addResourceFileAndNavigate(myResourceName, myResourceType, false);
- UndoUtil.markPsiFileForUndo(myFile);
- }
- }
}
diff --git a/plugins/android/src/org/jetbrains/android/inspections/AndroidQuickFixProvider.java b/plugins/android/src/org/jetbrains/android/inspections/AndroidQuickFixProvider.java
new file mode 100644
index 000000000000..39ec81858ca8
--- /dev/null
+++ b/plugins/android/src/org/jetbrains/android/inspections/AndroidQuickFixProvider.java
@@ -0,0 +1,74 @@
+package org.jetbrains.android.inspections;
+
+import com.android.resources.ResourceType;
+import com.intellij.codeInsight.daemon.QuickFixActionRegistrar;
+import com.intellij.codeInsight.quickfix.UnresolvedReferenceQuickFixProvider;
+import com.intellij.openapi.module.Module;
+import com.intellij.openapi.module.ModuleUtil;
+import com.intellij.openapi.util.Pair;
+import com.intellij.psi.PsiFile;
+import com.intellij.psi.PsiReferenceExpression;
+import org.jetbrains.android.dom.manifest.Manifest;
+import org.jetbrains.android.facet.AndroidFacet;
+import org.jetbrains.android.util.AndroidResourceUtil;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author Eugene.Kudelevsky
+ */
+public class AndroidQuickFixProvider extends UnresolvedReferenceQuickFixProvider {
+ @Override
+ public void registerFixes(PsiReferenceExpression exp, QuickFixActionRegistrar registrar) {
+ final Module contextModule = ModuleUtil.findModuleForPsiElement(exp);
+ if (contextModule == null) {
+ return;
+ }
+
+ final AndroidFacet facet = AndroidFacet.getInstance(contextModule);
+ if (facet == null) {
+ return;
+ }
+
+ final Manifest manifest = facet.getManifest();
+ if (manifest == null) {
+ return;
+ }
+
+ final String aPackage = manifest.getPackage().getValue();
+ if (aPackage == null) {
+ return;
+ }
+
+ final PsiFile contextFile = exp.getContainingFile();
+ if (contextFile == null) {
+ return;
+ }
+
+ final Pair pair = AndroidResourceUtil.getReferredResourceField(facet, exp);
+ if (pair == null) {
+ return;
+ }
+ final String resClassName = pair.getFirst();
+ final String resFieldName = pair.getSecond();
+
+ final ResourceType resourceType = ResourceType.getEnum(resClassName);
+ if (resourceType == ResourceType.STYLEABLE || resourceType == ResourceType.ATTR) {
+ // todo: support
+ return;
+ }
+
+ if (AndroidResourceUtil.VALUE_RESOURCE_TYPES.contains(resourceType)) {
+ registrar
+ .register(new CreateValueResourceQuickFix(facet, resourceType, resFieldName, contextFile, true));
+ }
+ if (AndroidResourceUtil.XML_FILE_RESOURCE_TYPES.contains(resourceType)) {
+ registrar.register(new CreateFileResourceQuickFix(facet, resourceType, resFieldName, contextFile, true));
+ }
+ }
+
+ @NotNull
+ @Override
+ public Class getReferenceClass() {
+ return PsiReferenceExpression.class;
+ }
+}
diff --git a/plugins/android/src/org/jetbrains/android/inspections/CreateFileResourceQuickFix.java b/plugins/android/src/org/jetbrains/android/inspections/CreateFileResourceQuickFix.java
new file mode 100644
index 000000000000..03b559ddf87f
--- /dev/null
+++ b/plugins/android/src/org/jetbrains/android/inspections/CreateFileResourceQuickFix.java
@@ -0,0 +1,117 @@
+package org.jetbrains.android.inspections;
+
+import com.android.resources.ResourceFolderType;
+import com.android.resources.ResourceType;
+import com.intellij.codeInsight.intention.HighPriorityAction;
+import com.intellij.codeInsight.intention.IntentionAction;
+import com.intellij.codeInspection.LocalQuickFix;
+import com.intellij.codeInspection.ProblemDescriptor;
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.command.undo.UndoUtil;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.Computable;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.psi.PsiDirectory;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiFile;
+import com.intellij.psi.PsiManager;
+import com.intellij.util.IncorrectOperationException;
+import org.jetbrains.android.actions.CreateResourceFileAction;
+import org.jetbrains.android.actions.CreateTypedResourceFileAction;
+import org.jetbrains.android.facet.AndroidFacet;
+import org.jetbrains.android.util.AndroidBundle;
+import org.jetbrains.android.util.AndroidResourceUtil;
+import org.jetbrains.annotations.NotNull;
+
+/**
+* @author Eugene.Kudelevsky
+*/
+public class CreateFileResourceQuickFix implements LocalQuickFix, IntentionAction, HighPriorityAction {
+ private static final Logger LOG = Logger.getInstance("#org.jetbrains.android.inspections.CreateFileResourceQuickFix");
+
+ private final AndroidFacet myFacet;
+ private final ResourceType myResourceType;
+ private final String myResourceName;
+ private final PsiFile myFile;
+ private final boolean myChooseResName;
+
+ public CreateFileResourceQuickFix(@NotNull AndroidFacet facet,
+ @NotNull ResourceType resourceType,
+ @NotNull String resourceName,
+ @NotNull PsiFile file,
+ boolean chooseResName) {
+ myFacet = facet;
+ myResourceType = resourceType;
+ myResourceName = resourceName;
+ myFile = file;
+ myChooseResName = chooseResName;
+ }
+
+ @NotNull
+ public String getName() {
+ return AndroidBundle.message("create.file.resource.quickfix.name", myResourceName,
+ '\'' + myResourceType.getName() + "' directory");
+ }
+
+ @NotNull
+ @Override
+ public String getText() {
+ return AndroidBundle.message("create.file.resource.intention.name", myResourceType, myResourceName + ".xml");
+ }
+
+ @NotNull
+ public String getFamilyName() {
+ return AndroidBundle.message("quick.fixes.family");
+ }
+
+ @Override
+ public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) {
+ return true;
+ }
+
+ @Override
+ public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException {
+ final PsiElement[] createdElements =
+ CreateResourceFileAction.createFileResource(myFacet, myResourceType, myResourceName + ".xml", myChooseResName);
+ if (createdElements.length > 0) {
+ UndoUtil.markPsiFileForUndo(myFile);
+ }
+ }
+
+ @Override
+ public boolean startInWriteAction() {
+ return false;
+ }
+
+ public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
+ final VirtualFile resourceDir = myFacet.getLocalResourceManager().getResourceDir();
+ if (resourceDir == null) {
+ return;
+ }
+ final PsiDirectory psiResDir = PsiManager.getInstance(project).findDirectory(resourceDir);
+ if (psiResDir == null) {
+ return;
+ }
+ final String resDirName = myResourceType.getName();
+ PsiDirectory resSubdir = psiResDir.findSubdirectory(resDirName);
+
+ if (resSubdir == null) {
+ resSubdir = ApplicationManager.getApplication().runWriteAction(new Computable() {
+ public PsiDirectory compute() {
+ return psiResDir.createSubdirectory(resDirName);
+ }
+ });
+ }
+
+ try {
+ AndroidResourceUtil.createFileResource(myResourceName, resSubdir, CreateTypedResourceFileAction.getDefaultRootTabByResourceType(
+ ResourceFolderType.getFolderType(resDirName)), resDirName, false);
+ UndoUtil.markPsiFileForUndo(myFile);
+ }
+ catch (Exception e) {
+ LOG.error(e);
+ }
+ }
+}
diff --git a/plugins/android/src/org/jetbrains/android/inspections/CreateValueResourceQuickFix.java b/plugins/android/src/org/jetbrains/android/inspections/CreateValueResourceQuickFix.java
new file mode 100644
index 000000000000..2a4b02d71415
--- /dev/null
+++ b/plugins/android/src/org/jetbrains/android/inspections/CreateValueResourceQuickFix.java
@@ -0,0 +1,126 @@
+package org.jetbrains.android.inspections;
+
+import com.android.AndroidConstants;
+import com.android.resources.ResourceType;
+import com.intellij.codeInsight.intention.HighPriorityAction;
+import com.intellij.codeInsight.intention.IntentionAction;
+import com.intellij.codeInspection.LocalQuickFix;
+import com.intellij.codeInspection.ProblemDescriptor;
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.command.undo.UndoUtil;
+import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.module.Module;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.psi.PsiDocumentManager;
+import com.intellij.psi.PsiFile;
+import com.intellij.util.IncorrectOperationException;
+import org.jetbrains.android.actions.CreateXmlResourceDialog;
+import org.jetbrains.android.facet.AndroidFacet;
+import org.jetbrains.android.util.AndroidBundle;
+import org.jetbrains.android.util.AndroidResourceUtil;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.Collections;
+import java.util.List;
+
+/**
+* @author Eugene.Kudelevsky
+*/
+public class CreateValueResourceQuickFix implements LocalQuickFix, IntentionAction, HighPriorityAction {
+ private final AndroidFacet myFacet;
+ private final ResourceType myResourceType;
+ private final String myResourceName;
+ private final PsiFile myFile;
+ private final boolean myChooseName;
+
+ public CreateValueResourceQuickFix(@NotNull AndroidFacet facet,
+ @NotNull ResourceType resourceType,
+ @NotNull String resourceName,
+ @NotNull PsiFile file,
+ boolean chooseName) {
+ myFacet = facet;
+ myResourceType = resourceType;
+ myResourceName = resourceName;
+ myFile = file;
+ myChooseName = chooseName;
+ }
+
+ @NotNull
+ public String getName() {
+ return AndroidBundle.message("create.value.resource.quickfix.name", myResourceName,
+ AndroidResourceUtil.getDefaultResourceFileName(myResourceType.getName()));
+ }
+
+ @NotNull
+ @Override
+ public String getText() {
+ return AndroidBundle.message("create.value.resource.intention.name", myResourceType, myResourceName);
+ }
+
+ @NotNull
+ public String getFamilyName() {
+ return AndroidBundle.message("quick.fixes.family");
+ }
+
+ @Override
+ public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) {
+ return true;
+ }
+
+ @Override
+ public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException {
+ doInvoke();
+ }
+
+ protected boolean doInvoke() {
+ if (ApplicationManager.getApplication().isUnitTestMode()) {
+ final String fileName = AndroidResourceUtil.getDefaultResourceFileName(myResourceType.getName());
+ assert fileName != null;
+
+ if (!AndroidResourceUtil.createValueResource(myFacet.getModule(), myResourceName, myResourceType, fileName,
+ Collections.singletonList(AndroidConstants.FD_RES_VALUES), "a")) {
+ return false;
+ }
+ }
+ else {
+ final CreateXmlResourceDialog dialog = new CreateXmlResourceDialog(myFacet.getModule(), myResourceType, myResourceName, null,
+ myChooseName);
+ dialog.setTitle("New " + StringUtil.capitalize(myResourceType.getDisplayName()) + " Value Resource");
+ dialog.show();
+
+ if (!dialog.isOK()) {
+ return false;
+ }
+
+ final Module moduleToPlaceResource = dialog.getModule();
+ if (moduleToPlaceResource == null) {
+ return false;
+ }
+ final String fileName = dialog.getFileName();
+ final List dirNames = dialog.getDirNames();
+ final String resValue = dialog.getValue();
+ final String resName = dialog.getResourceName();
+ if (!AndroidResourceUtil.createValueResource(moduleToPlaceResource, resName, myResourceType, fileName, dirNames, resValue)) {
+ return false;
+ }
+ }
+ PsiDocumentManager.getInstance(myFile.getProject()).commitAllDocuments();
+ UndoUtil.markPsiFileForUndo(myFile);
+ ApplicationManager.getApplication().invokeLater(new Runnable() {
+ public void run() {
+ ApplicationManager.getApplication().saveAll();
+ }
+ });
+ return true;
+ }
+
+ @Override
+ public boolean startInWriteAction() {
+ return false;
+ }
+
+ public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
+ // todo: implement local fix
+ }
+}
diff --git a/plugins/android/src/org/jetbrains/android/intentions/AndroidAddStringResourceAction.java b/plugins/android/src/org/jetbrains/android/intentions/AndroidAddStringResourceAction.java
index 007223e7ce29..bb62b105fa65 100644
--- a/plugins/android/src/org/jetbrains/android/intentions/AndroidAddStringResourceAction.java
+++ b/plugins/android/src/org/jetbrains/android/intentions/AndroidAddStringResourceAction.java
@@ -35,10 +35,8 @@ import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.*;
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
-import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.util.InheritanceUtil;
import com.intellij.psi.util.PsiTreeUtil;
-import com.intellij.psi.util.PsiUtil;
import com.intellij.psi.xml.XmlAttribute;
import com.intellij.psi.xml.XmlAttributeValue;
import com.intellij.psi.xml.XmlFile;
@@ -180,7 +178,7 @@ public class AndroidAddStringResourceAction extends AbstractIntentionAction impl
}
if (resName == null) {
- final CreateXmlResourceDialog dialog = new CreateXmlResourceDialog(facet.getModule(), ResourceType.STRING, null, value);
+ final CreateXmlResourceDialog dialog = new CreateXmlResourceDialog(facet.getModule(), ResourceType.STRING, null, value, false);
dialog.setTitle("Extract String Resource");
dialog.show();
@@ -244,7 +242,7 @@ public class AndroidAddStringResourceAction extends AbstractIntentionAction impl
ApplicationManager.getApplication().invokeLater(new Runnable() {
@Override
public void run() {
- createStubResourceField(module, aPackage, resType, rJavaFieldName);
+ AndroidResourceUtil.createStubResourceField(module, aPackage, resType, rJavaFieldName);
}
});
@@ -292,37 +290,6 @@ public class AndroidAddStringResourceAction extends AbstractIntentionAction impl
});
}
- private static void createStubResourceField(final Module module,
- final String aPackage,
- final String resType,
- final String fieldName) {
- ApplicationManager.getApplication().runWriteAction(new Runnable() {
- @Override
- public void run() {
- final Project project = module.getProject();
- final PsiClass[] classes =
- JavaPsiFacade.getInstance(project).findClasses(aPackage + ".R", GlobalSearchScope.moduleScope(module));
- if (classes.length == 1) {
- final PsiClass aClass = classes[0];
- final PsiElementFactory factory = JavaPsiFacade.getElementFactory(project);
-
- PsiClass resTypeClass = aClass.findInnerClassByName(resType, false);
-
- if (resTypeClass == null) {
- resTypeClass = (PsiClass)aClass.add(factory.createClass(resType));
- }
- else if (resTypeClass.findFieldByName(fieldName, false) != null) {
- return;
- }
- final PsiField psiField = (PsiField)resTypeClass.add(factory.createField(fieldName, PsiType.INT));
- PsiUtil.setModifierProperty(psiField, PsiModifier.PUBLIC, true);
- PsiUtil.setModifierProperty(psiField, PsiModifier.STATIC, true);
- PsiUtil.setModifierProperty(psiField, PsiModifier.FINAL, true);
- }
- }
- });
- }
-
@Nullable
private static String getPackage(@NotNull AndroidFacet facet) {
Manifest manifest = facet.getManifest();
diff --git a/plugins/android/src/org/jetbrains/android/newProject/AndroidModuleBuilder.java b/plugins/android/src/org/jetbrains/android/newProject/AndroidModuleBuilder.java
index 9be9195012cf..7f2cdc9a7183 100644
--- a/plugins/android/src/org/jetbrains/android/newProject/AndroidModuleBuilder.java
+++ b/plugins/android/src/org/jetbrains/android/newProject/AndroidModuleBuilder.java
@@ -17,6 +17,7 @@
package org.jetbrains.android.newProject;
import com.android.AndroidConstants;
+import com.android.resources.ResourceType;
import com.android.sdklib.IAndroidTarget;
import com.android.sdklib.SdkConstants;
import com.intellij.CommonBundle;
@@ -78,6 +79,7 @@ import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.List;
import java.util.Properties;
@@ -425,7 +427,10 @@ public class AndroidModuleBuilder extends JavaModuleBuilder {
final String normalizedAppName = AndroidResourceUtil.normalizeXmlResourceValue(myApplicationName.replace("\\", "\\\\"));
if (appNameResElement == null) {
- manager.addValueResource("string", appNameResource, normalizedAppName);
+ final String fileName = AndroidResourceUtil.getDefaultResourceFileName(ResourceType.STRING.getName());
+ assert fileName != null;
+ AndroidResourceUtil.createValueResource(facet.getModule(), appNameResource, ResourceType.STRING, fileName, Collections
+ .singletonList(AndroidConstants.FD_RES_VALUES), normalizedAppName);
}
else {
appNameResElement.setStringValue(normalizedAppName);
diff --git a/plugins/android/src/org/jetbrains/android/resourceManagers/LocalResourceManager.java b/plugins/android/src/org/jetbrains/android/resourceManagers/LocalResourceManager.java
index f4067bb3593f..28159de08edd 100644
--- a/plugins/android/src/org/jetbrains/android/resourceManagers/LocalResourceManager.java
+++ b/plugins/android/src/org/jetbrains/android/resourceManagers/LocalResourceManager.java
@@ -22,10 +22,8 @@ import com.intellij.CommonBundle;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.module.Module;
-import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.util.Pair;
-import com.intellij.openapi.vfs.ReadonlyStatusHandler;
import com.intellij.openapi.vfs.VfsUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiElement;
@@ -33,13 +31,11 @@ import com.intellij.psi.PsiField;
import com.intellij.psi.PsiFile;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.xml.XmlFile;
-import com.intellij.util.IncorrectOperationException;
import com.intellij.util.containers.HashMap;
import com.intellij.util.containers.HashSet;
import com.intellij.util.indexing.FileBasedIndex;
import org.jetbrains.android.AndroidFileTemplateProvider;
import org.jetbrains.android.AndroidValueResourcesIndex;
-import org.jetbrains.android.actions.CreateResourceFileAction;
import org.jetbrains.android.dom.attrs.AttributeDefinitions;
import org.jetbrains.android.dom.resources.Attr;
import org.jetbrains.android.dom.resources.DeclareStyleable;
@@ -57,8 +53,6 @@ import org.jetbrains.annotations.Nullable;
import java.io.IOException;
import java.util.*;
-import static org.jetbrains.android.util.AndroidUtils.loadDomElement;
-
/**
* @author Eugene.Kudelevsky
*/
@@ -263,50 +257,6 @@ public class LocalResourceManager extends ResourceManager {
return result;
}
- // must be invoked in a write action
- @Nullable
- public VirtualFile addResourceFileAndNavigate(@NotNull final String fileOrResourceName,
- @NotNull ResourceType resType,
- boolean chooseDirectory) {
- Project project = myModule.getProject();
- PsiElement[] createdElements =
- CreateResourceFileAction.createResourceFile(project, myFacet, resType, fileOrResourceName, chooseDirectory);
- if (createdElements.length == 0) return null;
- assert createdElements.length == 1;
- PsiElement element = createdElements[0];
- assert element instanceof PsiFile;
- return ((PsiFile)element).getVirtualFile();
- }
-
- // must be invoked in a write action
- @Nullable
- public ResourceElement addValueResource(@NotNull final String type, @NotNull final String name, @Nullable final String value) {
- String resourceFileName = AndroidResourceUtil.getDefaultResourceFileName(type);
- if (resourceFileName == null) {
- throw new IllegalArgumentException("Incorrect resource type");
- }
- VirtualFile resFile = findOrCreateResourceFile(resourceFileName);
- if (resFile == null ||
- !ReadonlyStatusHandler.ensureFilesWritable(myModule.getProject(), resFile)) {
- return null;
- }
- final Resources resources = loadDomElement(myModule, resFile, Resources.class);
- if (resources == null) {
- if (ApplicationManager.getApplication().isUnitTestMode()) {
- throw new IncorrectOperationException("invalid strings.xml");
- }
- Messages.showErrorDialog(myModule.getProject(), AndroidBundle.message("not.resource.file.error", resourceFileName),
- CommonBundle.getErrorTitle());
- return null;
- }
- ResourceElement element = AndroidResourceUtil.addValueResource(type, resources);
- element.getName().setValue(name);
- if (value != null) {
- element.setStringValue(value);
- }
- return element;
- }
-
@Nullable
private VirtualFile findOrCreateChildDir(@NotNull final VirtualFile dir, @NotNull final String name) {
try {
diff --git a/plugins/android/src/org/jetbrains/android/util/AndroidResourceUtil.java b/plugins/android/src/org/jetbrains/android/util/AndroidResourceUtil.java
index dcbdc39a17a1..0fdc4a277520 100644
--- a/plugins/android/src/org/jetbrains/android/util/AndroidResourceUtil.java
+++ b/plugins/android/src/org/jetbrains/android/util/AndroidResourceUtil.java
@@ -21,6 +21,9 @@ import com.android.resources.ResourceType;
import com.android.sdklib.SdkConstants;
import com.intellij.CommonBundle;
import com.intellij.ide.actions.CreateElementActionBase;
+import com.intellij.ide.fileTemplates.FileTemplate;
+import com.intellij.ide.fileTemplates.FileTemplateManager;
+import com.intellij.ide.fileTemplates.FileTemplateUtil;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.module.Module;
@@ -30,13 +33,17 @@ import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.ModulePackageIndex;
import com.intellij.openapi.roots.ModuleRootManager;
import com.intellij.openapi.ui.Messages;
+import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.ReadonlyStatusHandler;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.*;
+import com.intellij.psi.search.GlobalSearchScope;
+import com.intellij.psi.util.PsiUtil;
import com.intellij.psi.xml.XmlAttribute;
import com.intellij.psi.xml.XmlAttributeValue;
+import com.intellij.psi.xml.XmlFile;
import com.intellij.psi.xml.XmlTag;
import com.intellij.util.ArrayUtil;
import com.intellij.util.IncorrectOperationException;
@@ -68,6 +75,11 @@ public class AndroidResourceUtil {
ResourceType.ID, ResourceType.BOOL, ResourceType.INTEGER);
public static final Set REFERRABLE_RESOURCE_TYPES = EnumSet.noneOf(ResourceType.class);
+ public static final Set XML_FILE_RESOURCE_TYPES = EnumSet.of(ResourceType.ANIM, ResourceType.ANIMATOR,
+ ResourceType.INTERPOLATOR, ResourceType.LAYOUT,
+ ResourceType.MENU, ResourceType.XML, ResourceType.COLOR,
+ ResourceType.DRAWABLE);
+ static final String ROOT_TAG_PROPERTY = "ROOT_TAG";
private AndroidResourceUtil() {
}
@@ -606,11 +618,11 @@ public class AndroidResourceUtil {
}
private static boolean addValueResource(@NotNull AndroidFacet facet,
- @NotNull String resourceName,
- @NotNull ResourceType resourceType,
+ @NotNull final String resourceName,
+ @NotNull final ResourceType resourceType,
@NotNull String fileName,
@NotNull List dirNames,
- @NotNull String value) throws Exception {
+ @NotNull final String value) throws Exception {
if (dirNames.size() == 0) {
return false;
}
@@ -638,14 +650,19 @@ public class AndroidResourceUtil {
resourcesElements[i] = resources;
}
- for (Resources resources : resourcesElements) {
- final ResourceElement element = addValueResource(resourceType.getName(), resources);
- element.getName().setValue(resourceName);
+ ApplicationManager.getApplication().runWriteAction(new Runnable() {
+ @Override
+ public void run() {
+ for (Resources resources : resourcesElements) {
+ final ResourceElement element = addValueResource(resourceType.getName(), resources);
+ element.getName().setValue(resourceName);
- if (value.length() > 0) {
- element.setStringValue(value);
+ if (value.length() > 0) {
+ element.setStringValue(value);
+ }
+ }
}
- }
+ });
return true;
}
@@ -691,4 +708,99 @@ public class AndroidResourceUtil {
Messages.showErrorDialog(project, message, CommonBundle.getErrorTitle());
}
}
+
+ @Nullable
+ public static Pair getReferredResourceField(@NotNull AndroidFacet facet, @NotNull PsiReferenceExpression exp) {
+ final String resFieldName = exp.getReferenceName();
+ if (resFieldName == null || resFieldName.length() == 0) {
+ return null;
+ }
+
+ PsiExpression qExp = exp.getQualifierExpression();
+ if (!(qExp instanceof PsiReferenceExpression)) {
+ return null;
+ }
+ final PsiReferenceExpression resClassReference = (PsiReferenceExpression)qExp;
+
+ final String resClassName = resClassReference.getReferenceName();
+ if (resClassName == null || resClassName.length() == 0) {
+ return null;
+ }
+
+ qExp = resClassReference.getQualifierExpression();
+ if (!(qExp instanceof PsiReferenceExpression)) {
+ return null;
+ }
+
+ final PsiElement resolvedElement = ((PsiReferenceExpression)qExp).resolve();
+ if (!(resolvedElement instanceof PsiClass) ||
+ !AndroidUtils.R_CLASS_NAME.equals(((PsiClass)resolvedElement).getName())) {
+ return null;
+ }
+
+ final PsiFile containingFile = resolvedElement.getContainingFile();
+ if (containingFile == null || !isRJavaFile(facet, containingFile)) {
+ return null;
+ }
+ return new Pair(resClassName, resFieldName);
+ }
+
+ public static void createStubResourceField(@NotNull final Module module,
+ @NotNull final String aPackage,
+ @NotNull final String resClassName,
+ @NotNull final String resFieldName) {
+ ApplicationManager.getApplication().runWriteAction(new Runnable() {
+ @Override
+ public void run() {
+ final Project project = module.getProject();
+ final PsiClass[] classes =
+ JavaPsiFacade.getInstance(project).findClasses(aPackage + ".R", GlobalSearchScope.moduleScope(module));
+ if (classes.length == 1) {
+ final PsiClass aClass = classes[0];
+ final PsiElementFactory factory = JavaPsiFacade.getElementFactory(project);
+
+ PsiClass resTypeClass = aClass.findInnerClassByName(resClassName, false);
+
+ if (resTypeClass == null) {
+ resTypeClass = (PsiClass)aClass.add(factory.createClass(resClassName));
+ }
+ else if (resTypeClass.findFieldByName(resFieldName, false) != null) {
+ return;
+ }
+ final PsiField psiField = (PsiField)resTypeClass.add(factory.createField(resFieldName, PsiType.INT));
+ PsiUtil.setModifierProperty(psiField, PsiModifier.PUBLIC, true);
+ PsiUtil.setModifierProperty(psiField, PsiModifier.STATIC, true);
+ PsiUtil.setModifierProperty(psiField, PsiModifier.FINAL, true);
+ }
+ }
+ });
+ }
+
+ @NotNull
+ public static XmlFile createFileResource(@NotNull String fileName,
+ @NotNull PsiDirectory resSubdir,
+ @NotNull String rootTagName,
+ @NotNull String resourceType,
+ boolean valuesResourceFile) throws Exception {
+ FileTemplateManager manager = FileTemplateManager.getInstance();
+ String templateName = getTemplateName(resourceType, valuesResourceFile);
+ FileTemplate template = manager.getJ2eeTemplate(templateName);
+ Properties properties = new Properties();
+ if (!valuesResourceFile) {
+ properties.setProperty(ROOT_TAG_PROPERTY, rootTagName);
+ }
+ PsiElement createdElement = FileTemplateUtil.createFromTemplate(template, fileName, properties, resSubdir);
+ assert createdElement instanceof XmlFile;
+ return (XmlFile)createdElement;
+ }
+
+ private static String getTemplateName(String resourceType, boolean valuesResourceFile) {
+ if (valuesResourceFile) {
+ return AndroidFileTemplateProvider.VALUE_RESOURCE_FILE_TEMPLATE;
+ }
+ if ("layout".equals(resourceType)) {
+ return AndroidFileTemplateProvider.LAYOUT_RESOURCE_FILE_TEMPLATE;
+ }
+ return AndroidFileTemplateProvider.RESOURCE_FILE_TEMPLATE;
+ }
}
diff --git a/plugins/android/testSrc/org/jetbrains/android/dom/AndroidLayoutDomTest.java b/plugins/android/testSrc/org/jetbrains/android/dom/AndroidLayoutDomTest.java
index de12c53a9e0b..d859ac793252 100644
--- a/plugins/android/testSrc/org/jetbrains/android/dom/AndroidLayoutDomTest.java
+++ b/plugins/android/testSrc/org/jetbrains/android/dom/AndroidLayoutDomTest.java
@@ -4,13 +4,12 @@ import com.android.sdklib.SdkConstants;
import com.intellij.codeInsight.TargetElementUtilBase;
import com.intellij.codeInsight.daemon.impl.HighlightInfo;
import com.intellij.codeInsight.intention.IntentionAction;
-import com.intellij.codeInspection.actions.CleanupInspectionIntention;
import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.*;
-import org.jetbrains.android.dom.converters.ResourceReferenceConverter;
+import org.jetbrains.android.inspections.CreateValueResourceQuickFix;
import java.io.IOException;
import java.util.ArrayList;
@@ -351,7 +350,7 @@ public class AndroidLayoutDomTest extends AndroidDomTest {
if (ranges != null) {
for (Pair pair : ranges) {
final IntentionAction action = pair.getFirst().getAction();
- if (action instanceof ResourceReferenceConverter.MyCreateValueResourceQuickFix) {
+ if (action instanceof CreateValueResourceQuickFix) {
actions.add(action);
}
}
@@ -368,44 +367,6 @@ public class AndroidLayoutDomTest extends AndroidDomTest {
myFixture.checkResultByFile("res/values/drawables.xml", testFolder + '/' + getTestName(true) + "_drawable_after.xml", true);
}
- public void testCreateResourceFromUsageCleanUp() throws Throwable {
- final VirtualFile virtualFile = copyFileToProject(getTestName(true) + ".xml");
- myFixture.configureFromExistingVirtualFile(virtualFile);
- final List infos = myFixture.doHighlighting();
-
- final List actions = new ArrayList();
-
- for (HighlightInfo info : infos) {
- final List> ranges = info.quickFixActionRanges;
-
- if (ranges != null) {
- for (Pair pair : ranges) {
- final HighlightInfo.IntentionActionDescriptor descriptor = pair.getFirst();
- if (descriptor.getAction() instanceof ResourceReferenceConverter.MyCreateValueResourceQuickFix) {
- final List options = descriptor.getOptions(myFixture.getFile(), myFixture.getEditor());
-
- if (options != null) {
- for (IntentionAction option : options) {
- if (option instanceof CleanupInspectionIntention) {
- actions.add(option);
- }
- }
- }
- }
- }
- }
- }
- assertEquals(1, actions.size());
-
- new WriteCommandAction.Simple(getProject()) {
- @Override
- protected void run() throws Throwable {
- actions.get(0).invoke(getProject(), myFixture.getEditor(), myFixture.getFile());
- }
- }.execute();
- myFixture.checkResultByFile("res/values/drawables.xml", testFolder + '/' + getTestName(true) + "_drawable_after.xml", true);
- }
-
public void testXsdFile1() throws Throwable {
final VirtualFile virtualFile = copyFileToProject("XsdFile.xsd", "res/raw/XsdFile.xsd");
myFixture.configureFromExistingVirtualFile(virtualFile);
diff --git a/plugins/android/testSrc/org/jetbrains/android/dom/AndroidValueResourcesTest.java b/plugins/android/testSrc/org/jetbrains/android/dom/AndroidValueResourcesTest.java
index 444486328e12..93c97fe11840 100644
--- a/plugins/android/testSrc/org/jetbrains/android/dom/AndroidValueResourcesTest.java
+++ b/plugins/android/testSrc/org/jetbrains/android/dom/AndroidValueResourcesTest.java
@@ -27,7 +27,7 @@ import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiReference;
import com.intellij.psi.xml.XmlAttributeValue;
-import org.jetbrains.android.dom.converters.ResourceReferenceConverter;
+import org.jetbrains.android.inspections.CreateValueResourceQuickFix;
import java.util.ArrayList;
import java.util.List;
@@ -199,7 +199,7 @@ public class AndroidValueResourcesTest extends AndroidDomTest {
if (ranges != null) {
for (Pair pair : ranges) {
final IntentionAction action = pair.getFirst().getAction();
- if (action instanceof ResourceReferenceConverter.MyCreateValueResourceQuickFix) {
+ if (action instanceof CreateValueResourceQuickFix) {
actions.add(action);
}
}