mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
IDEA-86604 improve "create layout" and "create resource" actions: choosing root element, opening new layouts in last used editor
This commit is contained in:
+1
-1
@@ -879,7 +879,7 @@ public class FileEditorManagerImpl extends FileEditorManagerEx implements Projec
|
||||
});
|
||||
}
|
||||
|
||||
private void setSelectedEditor(VirtualFile file, String fileEditorProviderId) {
|
||||
public void setSelectedEditor(VirtualFile file, String fileEditorProviderId) {
|
||||
EditorWithProviderComposite composite = getCurrentEditorWithProviderComposite(file);
|
||||
if (composite == null) {
|
||||
final List<EditorWithProviderComposite> composites = getEditorComposites(file);
|
||||
|
||||
@@ -407,4 +407,6 @@ android.facet.settings.include.system.proguard=Include system proguard file
|
||||
file.already.exists.error=File {0} already exists
|
||||
deployment.target.settings.min.sdk.info.message=Only compatible AVDs are shown. See 'uses-sdk' tag in AndroidManifest.xml
|
||||
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.
|
||||
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
|
||||
@@ -19,12 +19,10 @@ import com.intellij.codeInsight.completion.CompletionContributor;
|
||||
import com.intellij.codeInsight.completion.CompletionParameters;
|
||||
import com.intellij.codeInsight.completion.CompletionResultSet;
|
||||
import com.intellij.codeInsight.lookup.LookupElementBuilder;
|
||||
import com.intellij.psi.PsiClass;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.xml.XmlFile;
|
||||
import com.intellij.psi.xml.XmlTag;
|
||||
import org.jetbrains.android.dom.AndroidDomExtender;
|
||||
import org.jetbrains.android.dom.animation.AndroidAnimationUtils;
|
||||
import org.jetbrains.android.dom.animation.AnimationDomFileDescription;
|
||||
import org.jetbrains.android.dom.animator.AndroidAnimatorUtil;
|
||||
@@ -32,17 +30,16 @@ import org.jetbrains.android.dom.animator.AnimatorDomFileDescription;
|
||||
import org.jetbrains.android.dom.color.ColorDomFileDescription;
|
||||
import org.jetbrains.android.dom.drawable.AndroidDrawableDomUtil;
|
||||
import org.jetbrains.android.dom.drawable.DrawableStateListDomFileDescription;
|
||||
import org.jetbrains.android.dom.layout.AndroidLayoutUtil;
|
||||
import org.jetbrains.android.dom.layout.LayoutDomFileDescription;
|
||||
import org.jetbrains.android.dom.manifest.ManifestDomFileDescription;
|
||||
import org.jetbrains.android.dom.xml.AndroidXmlResourcesUtil;
|
||||
import org.jetbrains.android.dom.xml.XmlResourceDomFileDescription;
|
||||
import org.jetbrains.android.facet.AndroidFacet;
|
||||
import org.jetbrains.android.util.AndroidUtils;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author coyote
|
||||
@@ -68,15 +65,7 @@ public class AndroidCompletionContributor extends CompletionContributor {
|
||||
return false;
|
||||
}
|
||||
else if (LayoutDomFileDescription.isLayoutFile(xmlFile)) {
|
||||
resultSet.addElement(LookupElementBuilder.create("view"));
|
||||
resultSet.addElement(LookupElementBuilder.create("merge"));
|
||||
Map<String, PsiClass> viewClassMap = AndroidDomExtender.getViewClassMap(facet);
|
||||
for (String tagName : viewClassMap.keySet()) {
|
||||
final PsiClass viewClass = viewClassMap.get(tagName);
|
||||
if (!AndroidUtils.isAbstract(viewClass)) {
|
||||
resultSet.addElement(LookupElementBuilder.create(tagName));
|
||||
}
|
||||
}
|
||||
addAll(AndroidLayoutUtil.getPossibleRoots(facet), resultSet);
|
||||
return false;
|
||||
}
|
||||
else if (AnimationDomFileDescription.isAnimationFile(xmlFile)) {
|
||||
|
||||
@@ -0,0 +1,188 @@
|
||||
/*
|
||||
* Copyright 2000-2010 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.android.actions;
|
||||
|
||||
import com.android.resources.ResourceType;
|
||||
import com.intellij.CommonBundle;
|
||||
import com.intellij.facet.ProjectFacetManager;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.fileEditor.FileEditorManager;
|
||||
import com.intellij.openapi.fileEditor.FileEditorProvider;
|
||||
import com.intellij.openapi.fileEditor.impl.EditorHistoryManager;
|
||||
import com.intellij.openapi.fileEditor.impl.FileEditorManagerImpl;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.ui.DialogWrapper;
|
||||
import com.intellij.openapi.ui.InputValidator;
|
||||
import com.intellij.openapi.ui.Messages;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.PsiDirectory;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.xml.XmlFile;
|
||||
import com.intellij.ui.TextFieldWithAutoCompletion;
|
||||
import com.intellij.ui.components.JBLabel;
|
||||
import com.intellij.util.containers.HashSet;
|
||||
import org.jetbrains.android.dom.layout.AndroidLayoutUtil;
|
||||
import org.jetbrains.android.facet.AndroidFacet;
|
||||
import org.jetbrains.android.facet.AndroidRootUtil;
|
||||
import org.jetbrains.android.util.AndroidBundle;
|
||||
import org.jetbrains.android.util.AndroidCommonUtils;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author Eugene.Kudelevsky
|
||||
*/
|
||||
public class AndroidCreateLayoutFileAction extends CreateTypedResourceFileAction {
|
||||
private static final Logger LOG = Logger.getInstance("#org.jetbrains.android.actions.AndroidCreateLayoutFileAction");
|
||||
|
||||
private String myLastRootComponentName;
|
||||
|
||||
public AndroidCreateLayoutFileAction() {
|
||||
super("Layout", "layout", "LinearLayout", false, false);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
protected PsiElement[] invokeDialog(Project project, PsiDirectory directory) {
|
||||
final AndroidFacet facet = AndroidFacet.getInstance(directory);
|
||||
LOG.assertTrue(facet != null);
|
||||
MyInputValidator validator = new MyInputValidator(project, directory);
|
||||
final MyDialog dialog = new MyDialog(facet, validator);
|
||||
dialog.show();
|
||||
return PsiElement.EMPTY_ARRAY;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
protected PsiElement[] create(String newName, PsiDirectory directory) throws Exception {
|
||||
assert myLastRootComponentName != null;
|
||||
return doCreate(newName, directory, myLastRootComponentName, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doNavigate(XmlFile file) {
|
||||
final Project project = file.getProject();
|
||||
final String preferredEditorProviderId = computePreferredEditorForLayoutFiles(project);
|
||||
super.doNavigate(file);
|
||||
|
||||
if (preferredEditorProviderId != null) {
|
||||
final FileEditorManager manager = FileEditorManager.getInstance(project);
|
||||
if (manager instanceof FileEditorManagerImpl) {
|
||||
final VirtualFile vFile = file.getVirtualFile();
|
||||
if (vFile != null) {
|
||||
((FileEditorManagerImpl)manager).setSelectedEditor(vFile, preferredEditorProviderId);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public List<String> getAllowedTagNames(@NotNull AndroidFacet facet) {
|
||||
return AndroidLayoutUtil.getPossibleRoots(facet);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static String computePreferredEditorForLayoutFiles(Project project) {
|
||||
final EditorHistoryManager manager = EditorHistoryManager.getInstance(project);
|
||||
final Set<VirtualFile> resourceDirs = new HashSet<VirtualFile>();
|
||||
final List<AndroidFacet> facets = ProjectFacetManager.getInstance(project).getFacets(AndroidFacet.ID);
|
||||
|
||||
for (AndroidFacet facet : facets) {
|
||||
final VirtualFile resourceDir = AndroidRootUtil.getResourceDir(facet);
|
||||
if (resourceDir != null) {
|
||||
resourceDirs.add(resourceDir);
|
||||
}
|
||||
}
|
||||
|
||||
final VirtualFile[] files = manager.getFiles();
|
||||
for (int i = files.length - 1; i >= 0; i--) {
|
||||
final VirtualFile file = files[i];
|
||||
final VirtualFile parent = file.getParent();
|
||||
|
||||
if (parent != null) {
|
||||
final String resType = AndroidCommonUtils.getResourceTypeByDirName(parent.getName());
|
||||
|
||||
if (ResourceType.LAYOUT.getName().equals(resType) && resourceDirs.contains(parent.getParent())) {
|
||||
final FileEditorProvider provider = manager.getSelectedProvider(file);
|
||||
|
||||
if (provider != null) {
|
||||
return provider.getEditorTypeId();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public class MyDialog extends DialogWrapper {
|
||||
private final InputValidator myValidator;
|
||||
|
||||
private JTextField myFileNameField;
|
||||
private TextFieldWithAutoCompletion<String> myRootElementField;
|
||||
private JPanel myPanel;
|
||||
private JPanel myRootElementFieldWrapper;
|
||||
private JBLabel myRootElementLabel;
|
||||
|
||||
protected MyDialog(@NotNull AndroidFacet facet, @Nullable InputValidator validator) {
|
||||
super(facet.getModule().getProject());
|
||||
myValidator = validator;
|
||||
setTitle(AndroidBundle.message("new.typed.resource.dialog.title", "Layout"));
|
||||
final List<String> tagNames = getSortedAllowedTagNames(facet);
|
||||
myRootElementField = new TextFieldWithAutoCompletion<String>(
|
||||
facet.getModule().getProject(), new TextFieldWithAutoCompletion.StringsCompletionProvider(tagNames, null), true);
|
||||
myRootElementField.setText(myDefaultRootTag);
|
||||
myRootElementFieldWrapper.add(myRootElementField, BorderLayout.CENTER);
|
||||
myRootElementLabel.setLabelFor(myRootElementField);
|
||||
init();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected JComponent createCenterPanel() {
|
||||
return myPanel;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JComponent getPreferredFocusedComponent() {
|
||||
return myFileNameField;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doOKAction() {
|
||||
final String fileName = myFileNameField.getText().trim();
|
||||
myLastRootComponentName = myRootElementField.getText().trim();
|
||||
|
||||
if (fileName.length() == 0) {
|
||||
Messages.showErrorDialog(myPanel, AndroidBundle.message("file.name.not.specified.error"), CommonBundle.getErrorTitle());
|
||||
return;
|
||||
}
|
||||
if (myLastRootComponentName.length() == 0) {
|
||||
Messages.showErrorDialog(myPanel, AndroidBundle.message("root.element.not.specified.error"), CommonBundle.getErrorTitle());
|
||||
return;
|
||||
}
|
||||
if (myValidator == null ||
|
||||
myValidator.checkInput(fileName) && myValidator.canClose(fileName)) {
|
||||
super.doOKAction();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="org.jetbrains.android.actions.AndroidCreateLayoutFileAction.MyDialog">
|
||||
<grid id="27dc6" binding="myPanel" layout-manager="GridLayoutManager" row-count="3" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
||||
<margin top="0" left="0" bottom="0" right="0"/>
|
||||
<constraints>
|
||||
<xy x="20" y="20" width="500" height="400"/>
|
||||
</constraints>
|
||||
<properties/>
|
||||
<border type="none"/>
|
||||
<children>
|
||||
<component id="5f781" class="com.intellij.ui.components.JBLabel">
|
||||
<constraints>
|
||||
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<labelFor value="1dac9"/>
|
||||
<text value="&File name:"/>
|
||||
</properties>
|
||||
</component>
|
||||
<vspacer id="59f15">
|
||||
<constraints>
|
||||
<grid row="2" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
</vspacer>
|
||||
<component id="1dac9" class="javax.swing.JTextField" binding="myFileNameField">
|
||||
<constraints>
|
||||
<grid row="0" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="8" fill="1" indent="0" use-parent-layout="false">
|
||||
<preferred-size width="150" height="-1"/>
|
||||
</grid>
|
||||
</constraints>
|
||||
<properties/>
|
||||
</component>
|
||||
<component id="f57b7" class="com.intellij.ui.components.JBLabel" binding="myRootElementLabel">
|
||||
<constraints>
|
||||
<grid row="1" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<text value="&Root element:"/>
|
||||
</properties>
|
||||
</component>
|
||||
<grid id="2457e" binding="myRootElementFieldWrapper" layout-manager="BorderLayout" hgap="0" vgap="0">
|
||||
<constraints>
|
||||
<grid row="1" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties/>
|
||||
<border type="none"/>
|
||||
<children/>
|
||||
</grid>
|
||||
</children>
|
||||
</grid>
|
||||
</form>
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="org.jetbrains.android.actions.CreateResourceDialog">
|
||||
<grid id="27dc6" binding="myPanel" layout-manager="GridLayoutManager" row-count="5" column-count="4" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
||||
<grid id="27dc6" binding="myPanel" layout-manager="GridLayoutManager" row-count="6" column-count="4" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
||||
<margin top="0" left="0" bottom="0" right="0"/>
|
||||
<constraints>
|
||||
<xy x="20" y="20" width="417" height="188"/>
|
||||
@@ -54,7 +54,7 @@
|
||||
</component>
|
||||
<grid id="8653" binding="myDeviceConfiguratorWrapper" layout-manager="BorderLayout" hgap="0" vgap="0">
|
||||
<constraints>
|
||||
<grid row="3" column="0" row-span="1" col-span="3" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
|
||||
<grid row="4" column="0" row-span="1" col-span="3" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties/>
|
||||
<border type="none"/>
|
||||
@@ -62,13 +62,13 @@
|
||||
</grid>
|
||||
<component id="f676e" class="com.intellij.ui.components.JBLabel" binding="myErrorLabel">
|
||||
<constraints>
|
||||
<grid row="4" column="0" row-span="1" col-span="3" vsize-policy="0" hsize-policy="0" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
|
||||
<grid row="5" column="0" row-span="1" col-span="3" vsize-policy="0" hsize-policy="0" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties/>
|
||||
</component>
|
||||
<component id="fda57" class="com.intellij.ui.components.JBLabel">
|
||||
<constraints>
|
||||
<grid row="2" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
|
||||
<grid row="3" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<labelFor value="90507"/>
|
||||
@@ -77,7 +77,7 @@
|
||||
</component>
|
||||
<component id="90507" class="javax.swing.JTextField" binding="myDirectoryNameTextField">
|
||||
<constraints>
|
||||
<grid row="2" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="8" fill="1" indent="0" use-parent-layout="false">
|
||||
<grid row="3" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="8" fill="1" indent="0" use-parent-layout="false">
|
||||
<preferred-size width="150" height="-1"/>
|
||||
</grid>
|
||||
</constraints>
|
||||
@@ -85,6 +85,22 @@
|
||||
<enabled value="false"/>
|
||||
</properties>
|
||||
</component>
|
||||
<component id="be58a" class="com.intellij.ui.components.JBLabel" binding="myRootElementLabel">
|
||||
<constraints>
|
||||
<grid row="2" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<text value="Root &element:"/>
|
||||
</properties>
|
||||
</component>
|
||||
<grid id="5b73f" binding="myRootElementFieldWrapper" layout-manager="BorderLayout" hgap="0" vgap="0">
|
||||
<constraints>
|
||||
<grid row="2" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties/>
|
||||
<border type="none"/>
|
||||
<children/>
|
||||
</grid>
|
||||
</children>
|
||||
</grid>
|
||||
</form>
|
||||
|
||||
@@ -18,25 +18,27 @@ package org.jetbrains.android.actions;
|
||||
|
||||
import com.android.ide.common.resources.configuration.FolderConfiguration;
|
||||
import com.android.resources.ResourceFolderType;
|
||||
import com.intellij.CommonBundle;
|
||||
import com.intellij.ide.actions.TemplateKindCombo;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.ui.DialogWrapper;
|
||||
import com.intellij.openapi.ui.InputValidator;
|
||||
import com.intellij.openapi.ui.Messages;
|
||||
import com.intellij.ui.TextFieldWithAutoCompletion;
|
||||
import com.intellij.ui.components.JBLabel;
|
||||
import com.intellij.util.PlatformIcons;
|
||||
import com.intellij.util.containers.HashMap;
|
||||
import org.jetbrains.android.facet.AndroidFacet;
|
||||
import org.jetbrains.android.uipreview.DeviceConfiguratorPanel;
|
||||
import org.jetbrains.android.uipreview.InvalidOptionValueException;
|
||||
import org.jetbrains.android.util.AndroidBundle;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Comparator;
|
||||
import java.util.Map;
|
||||
import java.util.*;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by IntelliJ IDEA.
|
||||
@@ -54,13 +56,18 @@ public abstract class CreateResourceDialog extends DialogWrapper {
|
||||
private JPanel myDeviceConfiguratorWrapper;
|
||||
private JBLabel myErrorLabel;
|
||||
private JTextField myDirectoryNameTextField;
|
||||
private JPanel myRootElementFieldWrapper;
|
||||
private JBLabel myRootElementLabel;
|
||||
private TextFieldWithAutoCompletion<String> myRootElementField;
|
||||
private InputValidator myValidator;
|
||||
|
||||
private final Map<String, CreateTypedResourceFileAction> myResType2ActionMap = new HashMap<String, CreateTypedResourceFileAction>();
|
||||
private final DeviceConfiguratorPanel myDeviceConfiguratorPanel;
|
||||
private final AndroidFacet myFacet;
|
||||
|
||||
public CreateResourceDialog(Project project, Collection<CreateTypedResourceFileAction> actions, CreateTypedResourceFileAction selected) {
|
||||
super(project);
|
||||
public CreateResourceDialog(@NotNull AndroidFacet facet, Collection<CreateTypedResourceFileAction> actions) {
|
||||
super(facet.getModule().getProject());
|
||||
myFacet = facet;
|
||||
myResTypeLabel.setLabelFor(myResourceTypeCombo);
|
||||
myResourceTypeCombo.registerUpDownHint(myFileNameField);
|
||||
myUpDownHint.setIcon(PlatformIcons.UP_DOWN_ARROWS);
|
||||
@@ -111,22 +118,57 @@ public abstract class CreateResourceDialog extends DialogWrapper {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
myDeviceConfiguratorPanel.applyEditors();
|
||||
updateRootElementCombo();
|
||||
}
|
||||
});
|
||||
|
||||
myDeviceConfiguratorPanel.updateAll();
|
||||
myDeviceConfiguratorWrapper.add(myDeviceConfiguratorPanel, BorderLayout.CENTER);
|
||||
setOKActionEnabled(myDirectoryNameTextField.getText().length() > 0);
|
||||
|
||||
updateRootElementCombo();
|
||||
init();
|
||||
}
|
||||
|
||||
private void updateRootElementCombo() {
|
||||
final CreateTypedResourceFileAction action = getSelectedAction();
|
||||
|
||||
if (action != null) {
|
||||
final List<String> allowedTagNames = action.getSortedAllowedTagNames(myFacet);
|
||||
myRootElementField = new TextFieldWithAutoCompletion<String>(
|
||||
myFacet.getModule().getProject(), new TextFieldWithAutoCompletion.StringsCompletionProvider(allowedTagNames, null), true);
|
||||
myRootElementField.setEnabled(allowedTagNames.size() > 1);
|
||||
myRootElementField.setText(!action.isChooseTagName() ? action.getDefaultRootTag() : "");
|
||||
myRootElementFieldWrapper.removeAll();
|
||||
myRootElementFieldWrapper.add(myRootElementField, BorderLayout.CENTER);
|
||||
}
|
||||
}
|
||||
|
||||
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))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
protected abstract InputValidator createValidator(@NotNull String subdirName);
|
||||
|
||||
@Override
|
||||
protected void doOKAction() {
|
||||
String fileName = myFileNameField.getText();
|
||||
assert getSelectedAction() != null;
|
||||
String fileName = myFileNameField.getText().trim();
|
||||
final CreateTypedResourceFileAction action = getSelectedAction();
|
||||
assert action != null;
|
||||
|
||||
if (fileName.length() == 0) {
|
||||
Messages.showErrorDialog(myPanel, AndroidBundle.message("file.name.not.specified.error"), CommonBundle.getErrorTitle());
|
||||
return;
|
||||
}
|
||||
|
||||
if (!action.isChooseTagName() && getRootElement().length() == 0) {
|
||||
Messages.showErrorDialog(myPanel, AndroidBundle.message("root.element.not.specified.error"), CommonBundle.getErrorTitle());
|
||||
return;
|
||||
}
|
||||
|
||||
final String subdirName = myDirectoryNameTextField.getText();
|
||||
assert subdirName != null && subdirName.length() > 0;
|
||||
@@ -137,6 +179,12 @@ public abstract class CreateResourceDialog extends DialogWrapper {
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
protected String getRootElement() {
|
||||
final String item = myRootElementField.getText().trim();
|
||||
return item != null ? item.trim() : "";
|
||||
}
|
||||
|
||||
public InputValidator getValidator() {
|
||||
return myValidator;
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@ import com.intellij.openapi.actionSystem.AnAction;
|
||||
import com.intellij.openapi.actionSystem.DataContext;
|
||||
import com.intellij.openapi.actionSystem.DataKeys;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.fileTypes.StdFileTypes;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.ui.InputValidator;
|
||||
@@ -33,6 +34,7 @@ import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.PsiDirectory;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiManager;
|
||||
import org.jetbrains.android.facet.AndroidFacet;
|
||||
import org.jetbrains.android.util.AndroidBundle;
|
||||
import org.jetbrains.android.util.AndroidResourceUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -47,7 +49,10 @@ import java.util.Map;
|
||||
* @author Eugene.Kudelevsky
|
||||
*/
|
||||
public class CreateResourceFileAction extends CreateElementActionBase {
|
||||
private static final Logger LOG = Logger.getInstance("#org.jetbrains.android.actions.CreateResourceFileAction");
|
||||
|
||||
private final Map<String, CreateTypedResourceFileAction> mySubactions = new HashMap<String, CreateTypedResourceFileAction>();
|
||||
private String myRootElement;
|
||||
|
||||
@NotNull
|
||||
public static CreateResourceFileAction getInstance() {
|
||||
@@ -101,20 +106,24 @@ public class CreateResourceFileAction extends CreateElementActionBase {
|
||||
@NotNull
|
||||
@Override
|
||||
protected PsiElement[] invokeDialog(final Project project, final PsiDirectory directory) {
|
||||
CreateTypedResourceFileAction createLayoutAction = mySubactions.get("layout");
|
||||
CreateResourceDialog dialog = new CreateResourceDialog(project, mySubactions.values(), createLayoutAction) {
|
||||
final AndroidFacet facet = AndroidFacet.getInstance(directory);
|
||||
LOG.assertTrue(facet != null);
|
||||
|
||||
CreateResourceDialog dialog = new CreateResourceDialog(facet, mySubactions.values()) {
|
||||
@Override
|
||||
protected InputValidator createValidator(@NotNull String subdirName) {
|
||||
return CreateResourceFileAction.this.createValidator(project, directory, subdirName);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doOKAction() {
|
||||
myRootElement = getRootElement();
|
||||
super.doOKAction();
|
||||
}
|
||||
};
|
||||
dialog.setTitle(AndroidBundle.message("new.resource.dialog.title"));
|
||||
dialog.show();
|
||||
InputValidator validator = dialog.getValidator();
|
||||
if (validator == null) {
|
||||
return PsiElement.EMPTY_ARRAY;
|
||||
}
|
||||
return ((MyInputValidator)validator).getCreatedElements();
|
||||
return PsiElement.EMPTY_ARRAY;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -134,6 +143,9 @@ public class CreateResourceFileAction extends CreateElementActionBase {
|
||||
@Override
|
||||
protected PsiElement[] create(String newName, PsiDirectory directory) throws Exception {
|
||||
CreateTypedResourceFileAction action = getActionByDir(directory);
|
||||
if (myRootElement != null && myRootElement.length() > 0) {
|
||||
return action.doCreate(newName, directory, myRootElement, false);
|
||||
}
|
||||
return action.create(newName, directory);
|
||||
}
|
||||
|
||||
|
||||
+42
-5
@@ -17,8 +17,15 @@
|
||||
package org.jetbrains.android.actions;
|
||||
|
||||
import com.intellij.openapi.actionSystem.DefaultActionGroup;
|
||||
import org.jetbrains.android.dom.animation.AndroidAnimationUtils;
|
||||
import org.jetbrains.android.dom.animator.AndroidAnimatorUtil;
|
||||
import org.jetbrains.android.dom.drawable.AndroidDrawableDomUtil;
|
||||
import org.jetbrains.android.dom.xml.AndroidXmlResourcesUtil;
|
||||
import org.jetbrains.android.facet.AndroidFacet;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by IntelliJ IDEA.
|
||||
* User: Eugene.Kudelevsky
|
||||
@@ -31,14 +38,44 @@ public class CreateResourceFileActionGroup extends DefaultActionGroup {
|
||||
|
||||
public CreateResourceFileActionGroup() {
|
||||
CreateResourceFileAction a = new CreateResourceFileAction();
|
||||
a.add(new CreateTypedResourceFileAction("Layout", "layout", "LinearLayout"));
|
||||
a.add(new CreateTypedResourceFileAction("XML", "xml", "PreferenceScreen"));
|
||||
a.add(new CreateTypedResourceFileAction("Drawable", "drawable", "selector"));
|
||||
a.add(new AndroidCreateLayoutFileAction());
|
||||
|
||||
a.add(new CreateTypedResourceFileAction("XML", "xml", "PreferenceScreen", false, true) {
|
||||
@NotNull
|
||||
@Override
|
||||
public List<String> getAllowedTagNames(@NotNull AndroidFacet facet) {
|
||||
return AndroidXmlResourcesUtil.getPossibleRoots(facet);
|
||||
}
|
||||
});
|
||||
|
||||
a.add(new CreateTypedResourceFileAction("Drawable", "drawable", "selector", false, true) {
|
||||
@NotNull
|
||||
@Override
|
||||
public List<String> getAllowedTagNames(@NotNull AndroidFacet facet) {
|
||||
return AndroidDrawableDomUtil.getPossibleRoots();
|
||||
}
|
||||
});
|
||||
|
||||
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("Animation", "anim", "set"));
|
||||
a.add(new CreateTypedResourceFileAction("Animator", "animator", "set"));
|
||||
|
||||
a.add(new CreateTypedResourceFileAction("Animation", "anim", "set", false, true) {
|
||||
@NotNull
|
||||
@Override
|
||||
public List<String> getAllowedTagNames(@NotNull AndroidFacet facet) {
|
||||
return AndroidAnimationUtils.getPossibleChildren(facet);
|
||||
}
|
||||
});
|
||||
|
||||
a.add(new CreateTypedResourceFileAction("Animator", "animator", "set", false, true) {
|
||||
@NotNull
|
||||
@Override
|
||||
public List<String> getAllowedTagNames(@NotNull AndroidFacet facet) {
|
||||
return AndroidAnimatorUtil.getPossibleChildren();
|
||||
}
|
||||
});
|
||||
|
||||
myMajorAction = a;
|
||||
add(a);
|
||||
for (CreateTypedResourceFileAction subaction : a.getSubactions()) {
|
||||
|
||||
+46
-14
@@ -22,7 +22,7 @@ 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.DataKeys;
|
||||
import com.intellij.openapi.actionSystem.LangDataKeys;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.editor.CaretModel;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
@@ -39,29 +39,29 @@ 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;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
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 {
|
||||
private static final String ROOT_TAG_PROPERTY = "ROOT_TAG";
|
||||
static final String ROOT_TAG_PROPERTY = "ROOT_TAG";
|
||||
|
||||
private final String myResourceType;
|
||||
private final String myResourcePresentableName;
|
||||
private final String myDefaultRootTag;
|
||||
protected final String myDefaultRootTag;
|
||||
private final boolean myValuesResourceFile;
|
||||
private final boolean myChooseTagName;
|
||||
|
||||
public CreateTypedResourceFileAction(@NotNull String presentableName, @NotNull String resourceType, @NotNull String defaultRootTag) {
|
||||
this(presentableName, resourceType, defaultRootTag, false, true);
|
||||
}
|
||||
|
||||
public CreateTypedResourceFileAction(@NotNull String resourcePresentableName,
|
||||
@NotNull String resourceType,
|
||||
@NotNull String defaultRootTag,
|
||||
@@ -87,24 +87,29 @@ public class CreateTypedResourceFileAction extends CreateElementActionBase {
|
||||
Messages.showInputDialog(project, AndroidBundle.message("new.file.dialog.text"),
|
||||
AndroidBundle.message("new.typed.resource.dialog.title", myResourcePresentableName),
|
||||
Messages.getQuestionIcon(), "", validator);
|
||||
return validator.getCreatedElements();
|
||||
return PsiElement.EMPTY_ARRAY;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
protected PsiElement[] create(String newName, PsiDirectory directory) throws Exception {
|
||||
return doCreate(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, myDefaultRootTag);
|
||||
properties.setProperty(ROOT_TAG_PROPERTY, rootTagName);
|
||||
}
|
||||
PsiElement createdElement = FileTemplateUtil.createFromTemplate(template, newName, properties, directory);
|
||||
assert createdElement instanceof XmlFile;
|
||||
final XmlFile file = (XmlFile)createdElement;
|
||||
PsiNavigateUtil.navigate(file);
|
||||
if (myChooseTagName) {
|
||||
doNavigate(file);
|
||||
|
||||
if (chooseTagName) {
|
||||
XmlDocument document = file.getDocument();
|
||||
if (document != null) {
|
||||
XmlTag rootTag = document.getRootTag();
|
||||
@@ -122,6 +127,10 @@ public class CreateTypedResourceFileAction extends CreateElementActionBase {
|
||||
return new PsiElement[]{createdElement};
|
||||
}
|
||||
|
||||
protected void doNavigate(XmlFile file) {
|
||||
PsiNavigateUtil.navigate(file);
|
||||
}
|
||||
|
||||
private String getTemplateName() {
|
||||
if (myValuesResourceFile) {
|
||||
return AndroidFileTemplateProvider.VALUE_RESOURCE_FILE_TEMPLATE;
|
||||
@@ -134,13 +143,36 @@ public class CreateTypedResourceFileAction extends CreateElementActionBase {
|
||||
|
||||
@Override
|
||||
protected boolean isAvailable(DataContext context) {
|
||||
if (!super.isAvailable(context)) return false;
|
||||
final PsiElement element = (PsiElement)context.getData(DataKeys.PSI_ELEMENT.getName());
|
||||
return super.isAvailable(context) && doIsAvailable(context, myResourceType);
|
||||
}
|
||||
|
||||
public boolean isChooseTagName() {
|
||||
return myChooseTagName;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public List<String> getAllowedTagNames(@NotNull AndroidFacet facet) {
|
||||
return Collections.singletonList(getDefaultRootTag());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
protected final List<String> getSortedAllowedTagNames(@NotNull AndroidFacet facet) {
|
||||
final List<String> result = new ArrayList<String>(getAllowedTagNames(facet));
|
||||
Collections.sort(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
public String getDefaultRootTag() {
|
||||
return myDefaultRootTag;
|
||||
}
|
||||
|
||||
static boolean doIsAvailable(DataContext context, final String resourceType) {
|
||||
final PsiElement element = (PsiElement)context.getData(LangDataKeys.PSI_ELEMENT.getName());
|
||||
return ApplicationManager.getApplication().runReadAction(new Computable<Boolean>() {
|
||||
public Boolean compute() {
|
||||
PsiElement e = element;
|
||||
while (e != null) {
|
||||
if (e instanceof PsiDirectory && AndroidResourceUtil.isResourceSubdirectory((PsiDirectory)e, myResourceType)) {
|
||||
if (e instanceof PsiDirectory && AndroidResourceUtil.isResourceSubdirectory((PsiDirectory)e, resourceType)) {
|
||||
return true;
|
||||
}
|
||||
e = e.getParent();
|
||||
|
||||
@@ -48,10 +48,7 @@ import org.jetbrains.android.util.AndroidUtils;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.*;
|
||||
|
||||
import static org.jetbrains.android.util.AndroidUtils.SYSTEM_RESOURCE_PACKAGE;
|
||||
|
||||
@@ -328,4 +325,22 @@ public class AndroidDomUtil {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static Collection<String> removeUnambigiousNames(@NotNull Map<String, PsiClass> viewClassMap) {
|
||||
final Map<String, String> class2Name = new HashMap<String, String>();
|
||||
|
||||
for (String tagName : viewClassMap.keySet()) {
|
||||
final PsiClass viewClass = viewClassMap.get(tagName);
|
||||
if (!AndroidUtils.isAbstract(viewClass)) {
|
||||
final String qName = viewClass.getQualifiedName();
|
||||
final String prevTagName = class2Name.get(qName);
|
||||
|
||||
if (prevTagName == null || tagName.indexOf('.') == -1) {
|
||||
class2Name.put(qName, tagName);
|
||||
}
|
||||
}
|
||||
}
|
||||
return class2Name.values();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
package org.jetbrains.android.dom.layout;
|
||||
|
||||
import org.jetbrains.android.dom.AndroidDomExtender;
|
||||
import org.jetbrains.android.dom.AndroidDomUtil;
|
||||
import org.jetbrains.android.facet.AndroidFacet;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Eugene.Kudelevsky
|
||||
*/
|
||||
public class AndroidLayoutUtil {
|
||||
private AndroidLayoutUtil() {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static List<String> getPossibleRoots(@NotNull AndroidFacet facet) {
|
||||
final List<String> result = new ArrayList<String>();
|
||||
result.add("view");
|
||||
result.add("merge");
|
||||
result.addAll(AndroidDomUtil.removeUnambigiousNames(
|
||||
AndroidDomExtender.getViewClassMap(facet)));
|
||||
result.remove("View");
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -18,6 +18,7 @@ package org.jetbrains.android.dom.xml;
|
||||
|
||||
import com.intellij.util.containers.HashMap;
|
||||
import org.jetbrains.android.dom.AndroidDomExtender;
|
||||
import org.jetbrains.android.dom.AndroidDomUtil;
|
||||
import org.jetbrains.android.facet.AndroidFacet;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -68,7 +69,8 @@ public class AndroidXmlResourcesUtil {
|
||||
@NotNull
|
||||
public static List<String> getPossibleRoots(@NotNull AndroidFacet facet) {
|
||||
List<String> result = new ArrayList<String>();
|
||||
result.addAll(AndroidDomExtender.getPreferencesClassMap(facet).keySet());
|
||||
result.addAll(AndroidDomUtil.removeUnambigiousNames(
|
||||
AndroidDomExtender.getPreferencesClassMap(facet)));
|
||||
result.addAll(Arrays.asList(ROOT_TAGS));
|
||||
|
||||
return result;
|
||||
|
||||
Reference in New Issue
Block a user