From 0598d7a0af4507d4debf6c88466c0765b9ebb5b3 Mon Sep 17 00:00:00 2001 From: greg Date: Tue, 4 Aug 2009 17:54:39 +0400 Subject: [PATCH] add/edit actions --- .../plugins/intelliLang/InjectionsSettingsUI.java | 180 ++++++++++++++------- ....java => AbstractLanguageInjectionSupport.java} | 43 ++--- .../plugins/intelliLang/inject/InjectorUtils.java | 8 +- .../inject/LanguageInjectionSupport.java | 12 +- .../inject/config/ui/MethodParameterPanel.java | 100 +++++++----- .../groovy/GroovyLanguageInjectionSupport.java | 33 +--- .../inject/java/JavaLanguageInjectionSupport.java | 116 ++++++++++--- .../inject/xml/XmlLanguageInjectionSupport.java | 175 +++++++++++++------- 8 files changed, 447 insertions(+), 220 deletions(-) copy plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/{groovy/GroovyLanguageInjectionSupport.java => AbstractLanguageInjectionSupport.java} (64%) diff --git a/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/InjectionsSettingsUI.java b/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/InjectionsSettingsUI.java index 1b173d51d1..c9e2d2a607 100644 --- a/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/InjectionsSettingsUI.java +++ b/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/InjectionsSettingsUI.java @@ -27,25 +27,31 @@ import com.intellij.openapi.options.Configurable; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.Messages; import com.intellij.openapi.ui.SplitterProportionsData; +import com.intellij.openapi.ui.popup.JBPopupFactory; import com.intellij.openapi.util.Comparing; -import com.intellij.openapi.util.IconLoader; import com.intellij.openapi.util.Condition; +import com.intellij.openapi.util.Factory; +import com.intellij.openapi.util.IconLoader; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.peer.PeerFactory; import com.intellij.ui.*; import com.intellij.ui.table.TableView; import com.intellij.ui.tabs.BetterJTable; +import com.intellij.util.Consumer; import com.intellij.util.Function; import com.intellij.util.Icons; import com.intellij.util.Processor; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.ui.ColumnInfo; import com.intellij.util.ui.ListTableModel; +import gnu.trove.THashMap; import org.intellij.plugins.intelliLang.inject.InjectedLanguage; import org.intellij.plugins.intelliLang.inject.InjectorUtils; +import org.intellij.plugins.intelliLang.inject.LanguageInjectionSupport; import org.intellij.plugins.intelliLang.inject.config.BaseInjection; import org.jetbrains.annotations.Nls; +import org.jetbrains.annotations.Nullable; import javax.swing.*; import javax.swing.table.TableCellRenderer; @@ -53,8 +59,6 @@ import java.awt.*; import java.awt.event.KeyEvent; import java.util.*; import java.util.List; -import java.util.regex.Matcher; -import java.util.regex.Pattern; /** * @author Gregory.Shrago @@ -69,6 +73,10 @@ public class InjectionsSettingsUI implements Configurable { private final JPanel myRoot; private final InjectionsTable myInjectionsTable; + private final Map mySupports = new THashMap(); + private final Map myEditActions = new THashMap(); + private final List myAddActions = new ArrayList(); + private ActionToolbar myToolbar; public InjectionsSettingsUI(final Project project, final Configuration configuration) { myProject = project; @@ -84,16 +92,7 @@ public class InjectionsSettingsUI implements Configurable { }); } }); - Collections.sort(myOriginalInjections, new Comparator() { - public int compare(final BaseInjection o1, final BaseInjection o2) { - final int support = Comparing.compare(o1.getSupportId(), o2.getSupportId()); - if (support != 0) return support; - final int lang = Comparing.compare(o1.getInjectedLanguageId(), o2.getInjectedLanguageId()); - if (lang != 0) return lang; - final int name = Comparing.compare(o1.getDisplayName(), o2.getDisplayName()); - return name; - } - }); + sortInjections(myOriginalInjections); myInjections = new ArrayList(); for (BaseInjection injection : myOriginalInjections) { myInjections.add(injection.copy()); @@ -107,19 +106,77 @@ public class InjectionsSettingsUI implements Configurable { tablePanel.add(BetterJTable.createStripedJScrollPane(myInjectionsTable), BorderLayout.CENTER); tablePanel.add(Box.createVerticalStrut(10), BorderLayout.SOUTH); + final DefaultActionGroup group = createActions(); + + myToolbar = ActionManager.getInstance().createActionToolbar(ActionPlaces.UNKNOWN, group, true); + myToolbar.setTargetComponent(myInjectionsTable); + myRoot.add(myToolbar.getComponent(), BorderLayout.NORTH); + myRoot.add(tablePanel, BorderLayout.CENTER); + } + + private DefaultActionGroup createActions() { + final Consumer consumer = new Consumer() { + public void consume(final BaseInjection injection) { + addInjection(injection); + } + }; + final Factory producer = new Factory() { + public BaseInjection create() { + return getSelectedInjection(); + } + }; + for (LanguageInjectionSupport support : InjectorUtils.getActiveInjectionSupports()) { + myAddActions.addAll(Arrays.asList(support.createAddActions(myProject, consumer))); + ContainerUtil.putIfNotNull(support.getId(), support.createEditAction(myProject, producer), myEditActions); + mySupports.put(support.getId(), support); + } + final DefaultActionGroup group = new DefaultActionGroup(); - group.add(new AnAction("Add", "Add", Icons.ADD_ICON) { + final AnAction addAction = new AnAction("Add", "Add", Icons.ADD_ICON) { + @Override + public void update(final AnActionEvent e) { + e.getPresentation().setEnabled(!myAddActions.isEmpty()); + } + @Override public void actionPerformed(final AnActionEvent e) { performAdd(e); } - }); - group.add(new AnAction("Remove", "Remove", Icons.DELETE_ICON) { + }; + final AnAction removeAction = new AnAction("Remove", "Remove", Icons.DELETE_ICON) { + @Override + public void update(final AnActionEvent e) { + e.getPresentation().setEnabled(!getSelectedInjections().isEmpty()); + } + @Override public void actionPerformed(final AnActionEvent e) { performRemove(); } - }); + }; + + final AnAction editAction = new AnAction("Edit", "Edit", Icons.PROPERTIES_ICON) { + @Override + public void update(final AnActionEvent e) { + final AnAction action = getEditAction(); + e.getPresentation().setEnabled(action != null); + if (action != null) action.update(e); + } + + @Override + public void actionPerformed(final AnActionEvent e) { + final AnAction action = getEditAction(); + action.actionPerformed(e); + } + }; + group.add(addAction); + group.add(removeAction); + group.add(editAction); + + addAction.registerCustomShortcutSet(CommonShortcuts.INSERT, myInjectionsTable); + removeAction.registerCustomShortcutSet(CommonShortcuts.DELETE, myInjectionsTable); + editAction.registerCustomShortcutSet(CommonShortcuts.ENTER, myInjectionsTable); + group.add(new AnAction("Import", "Import", IconLoader.getIcon("/actions/install.png")) { @Override public void actionPerformed(final AnActionEvent e) { @@ -146,9 +203,34 @@ public class InjectionsSettingsUI implements Configurable { performToggleAction(); } }.registerCustomShortcutSet(new CustomShortcutSet(KeyStroke.getKeyStroke(KeyEvent.VK_SPACE, 0)), myInjectionsTable); + return group; + } - myRoot.add(ActionManager.getInstance().createActionToolbar(ActionPlaces.UNKNOWN, group, true).getComponent(), BorderLayout.NORTH); - myRoot.add(tablePanel, BorderLayout.CENTER); + private AnAction getEditAction() { + final BaseInjection injection = getSelectedInjection(); + final String supportId = injection == null? null : injection.getSupportId(); + return supportId == null? null : myEditActions.get(supportId); + } + + private void addInjection(final BaseInjection injection) { + injection.initializePlaces(true); + myInjections.add(injection); + sortInjections(myInjections); + final int index = myInjections.indexOf(injection); + ((ListTableModel)myInjectionsTable.getModel()).fireTableDataChanged(); + myInjectionsTable.getSelectionModel().setSelectionInterval(index, index); + } + + private void sortInjections(final List injections) { + Collections.sort(injections, new Comparator() { + public int compare(final BaseInjection o1, final BaseInjection o2) { + final int support = Comparing.compare(o1.getSupportId(), o2.getSupportId()); + if (support != 0) return support; + final int lang = Comparing.compare(o1.getInjectedLanguageId(), o2.getInjectedLanguageId()); + if (lang != 0) return lang; + return Comparing.compare(o1.getDisplayName(), o2.getDisplayName()); + } + }); } public JComponent createComponent() { @@ -197,8 +279,9 @@ public class InjectionsSettingsUI implements Configurable { final int selectedRow = myInjectionsTable.getSelectedRow(); if (selectedRow < 0) return; myInjections.removeAll(getSelectedInjections()); - myInjectionsTable.updateUI(); - myInjectionsTable.getSelectionModel().setLeadSelectionIndex(Math.min(myInjections.size()-1, selectedRow)); + ((ListTableModel)myInjectionsTable.getModel()).fireTableDataChanged(); + final int index = Math.min(myInjections.size() - 1, selectedRow); + myInjectionsTable.getSelectionModel().setSelectionInterval(index, index); } private List getSelectedInjections() { @@ -209,9 +292,20 @@ public class InjectionsSettingsUI implements Configurable { return toRemove; } - private void performAdd(final AnActionEvent button) { - // todo add popup - Messages.showInfoMessage(myProject, "Unfortunately this functionality is not yet implemented.\nUse in place \'Inject language\' intention action.", "Add Injection"); + @Nullable + private BaseInjection getSelectedInjection() { + final int row = myInjectionsTable.getSelectedRow(); + return row < 0? null : (BaseInjection)myInjectionsTable.getItems().get(row); + } + + private void performAdd(final AnActionEvent e) { + final DefaultActionGroup group = new DefaultActionGroup(); + for (AnAction action : myAddActions) { + group.add(action); + } + + JBPopupFactory.getInstance().createActionGroupPopup(null, group, e.getDataContext(), JBPopupFactory.ActionSelectionAid.NUMBERING, true) + .showUnderneathOf(myToolbar.getComponent()); } @Nls @@ -272,7 +366,7 @@ public class InjectionsSettingsUI implements Configurable { } - private static ColumnInfo[] createInjectionColumnInfos() { + private ColumnInfo[] createInjectionColumnInfos() { final TableCellRenderer booleanCellRenderer = createBooleanCellRenderer(); final TableCellRenderer displayNameCellRenderer = createDisplayNameCellRenderer(); final TableCellRenderer languageCellRenderer = createLanguageCellRenderer(); @@ -378,29 +472,21 @@ public class InjectionsSettingsUI implements Configurable { }; } - private static TableCellRenderer createDisplayNameCellRenderer() { + private TableCellRenderer createDisplayNameCellRenderer() { return new TableCellRenderer() { final SimpleColoredComponent myLabel = new SimpleColoredComponent(); - final Pattern myPattern = Pattern.compile("(.+)(\\(\\S+(?:\\.\\S+)+\\))"); + final SimpleColoredText myText = new SimpleColoredText(); public Component getTableCellRendererComponent(final JTable table, final Object value, final boolean isSelected, final boolean hasFocus, final int row, final int column) { myLabel.clear(); - final BaseInjection injection = (BaseInjection)value; - myLabel.append(injection.getSupportId(), SimpleTextAttributes.GRAY_ATTRIBUTES); - myLabel.append(": ", SimpleTextAttributes.GRAY_ATTRIBUTES); - - final String text = injection.getDisplayName(); - final Matcher matcher = myPattern.matcher(text); - if (matcher.matches()) { - myLabel.append(matcher.group(1), SimpleTextAttributes.REGULAR_ATTRIBUTES); - myLabel.append(matcher.group(2), SimpleTextAttributes.GRAYED_ATTRIBUTES); - } - else { - myLabel.append(text, SimpleTextAttributes.REGULAR_ATTRIBUTES); - } + final SimpleTextAttributes grayAttrs = isSelected ? SimpleTextAttributes.REGULAR_ATTRIBUTES : SimpleTextAttributes.GRAY_ATTRIBUTES; + myText.append(injection.getSupportId() + ": ", grayAttrs); + mySupports.get(injection.getSupportId()).setupPresentation(injection, myText, isSelected); + myText.appendToComponent(myLabel); + myText.clear(); setLabelColors(myLabel, table, isSelected, row); return myLabel; } @@ -413,23 +499,9 @@ public class InjectionsSettingsUI implements Configurable { } label.setForeground(isSelected ? table.getSelectionForeground() : table.getForeground()); label.setBackground(isSelected ? table.getSelectionBackground() : table.getBackground()); - //if (row % 2 != 0 && !isSelected) { - // label.setBackground(darken(table.getBackground())); - //} - //else { - // label.setBackground(isSelected ? table.getSelectionBackground() : table.getBackground()); - //} return label; } - - //private static final double FACTOR = 0.92; - //public static Color darken(Color color) { - // return new Color(Math.max((int)(color.getRed() * FACTOR), 0), Math.max((int)(color.getGreen() * FACTOR), 0), - // Math.max((int)(color.getBlue() * FACTOR), 0)); - //} - - private void doImportAction(final DataContext dataContext) { final FileChooserDescriptor descriptor = new FileChooserDescriptor(true, false, true, false, true, false) { @Override diff --git a/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/groovy/GroovyLanguageInjectionSupport.java b/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/AbstractLanguageInjectionSupport.java similarity index 64% copy from plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/groovy/GroovyLanguageInjectionSupport.java copy to plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/AbstractLanguageInjectionSupport.java index ffd1fc8ce0..bb3a600c02 100644 --- a/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/groovy/GroovyLanguageInjectionSupport.java +++ b/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/AbstractLanguageInjectionSupport.java @@ -14,40 +14,29 @@ * limitations under the License. */ -package org.intellij.plugins.intelliLang.inject.groovy; +package org.intellij.plugins.intelliLang.inject; import com.intellij.lang.Language; +import com.intellij.openapi.actionSystem.AnAction; import com.intellij.openapi.options.Configurable; import com.intellij.openapi.project.Project; -import com.intellij.psi.PsiLanguageInjectionHost; +import com.intellij.openapi.util.Factory; import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiLanguageInjectionHost; +import com.intellij.ui.SimpleColoredText; +import com.intellij.ui.SimpleTextAttributes; +import com.intellij.util.Consumer; import org.intellij.plugins.intelliLang.Configuration; -import org.intellij.plugins.intelliLang.inject.LanguageInjectionSupport; import org.intellij.plugins.intelliLang.inject.config.BaseInjection; import org.jdom.Element; -import org.jetbrains.annotations.NonNls; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.plugins.groovy.lang.psi.patterns.GroovyPatterns; -import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElement; /** * @author Gregory.Shrago */ -public class GroovyLanguageInjectionSupport implements LanguageInjectionSupport { - @NonNls private static final String SUPPORT_ID = "groovy"; - - @NotNull - public String getId() { - return SUPPORT_ID; - } - - @NotNull - public Class[] getPatternClasses() { - return new Class[] {GroovyPatterns.class}; - } +public abstract class AbstractLanguageInjectionSupport implements LanguageInjectionSupport { public boolean useDefaultInjector(final PsiElement host) { - return host instanceof GroovyPsiElement; + return false; } public boolean addInjectionInPlace(final Language language, final PsiLanguageInjectionHost psiElement) { @@ -63,10 +52,22 @@ public class GroovyLanguageInjectionSupport implements LanguageInjectionSupport } public BaseInjection createInjection(final Element element) { - return new BaseInjection(SUPPORT_ID); + return new BaseInjection(getId()); + } + + public void setupPresentation(final BaseInjection injection, final SimpleColoredText presentation, final boolean isSelected) { + presentation.append(injection.getDisplayName(), SimpleTextAttributes.REGULAR_ATTRIBUTES); } public Configurable[] createSettings(final Project project, final Configuration configuration) { return new Configurable[0]; } + + public AnAction[] createAddActions(final Project project, final Consumer consumer) { + return AnAction.EMPTY_ARRAY; + } + + public AnAction createEditAction(final Project project, final Factory producer) { + return null; + } } diff --git a/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/InjectorUtils.java b/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/InjectorUtils.java index 159336441f..2aa1090f86 100644 --- a/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/InjectorUtils.java +++ b/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/InjectorUtils.java @@ -149,7 +149,7 @@ public class InjectorUtils { @NotNull public static Set getActiveInjectionSupportIds() { - return ContainerUtil.map2Set(Extensions.getExtensions(LanguageInjectionSupport.EP_NAME), new NotNullFunction() { + return ContainerUtil.map2Set(getActiveInjectionSupports(), new NotNullFunction() { @NotNull public String fun(final LanguageInjectionSupport support) { return support.getId(); @@ -157,9 +157,13 @@ public class InjectorUtils { }); } + public static LanguageInjectionSupport[] getActiveInjectionSupports() { + return Extensions.getExtensions(LanguageInjectionSupport.EP_NAME); + } + @Nullable public static LanguageInjectionSupport findInjectionSupport(final String id) { - return ContainerUtil.find(Extensions.getExtensions(LanguageInjectionSupport.EP_NAME), new Condition() { + return ContainerUtil.find(getActiveInjectionSupports(), new Condition() { public boolean value(final LanguageInjectionSupport support) { return support.getId().equals(id); } diff --git a/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/LanguageInjectionSupport.java b/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/LanguageInjectionSupport.java index 8de58ff265..607994f3b2 100644 --- a/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/LanguageInjectionSupport.java +++ b/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/LanguageInjectionSupport.java @@ -1,12 +1,16 @@ package org.intellij.plugins.intelliLang.inject; import com.intellij.lang.Language; +import com.intellij.openapi.actionSystem.AnAction; import com.intellij.openapi.extensions.ExtensionPointName; import com.intellij.openapi.options.Configurable; import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.Factory; import com.intellij.openapi.util.Key; -import com.intellij.psi.PsiLanguageInjectionHost; import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiLanguageInjectionHost; +import com.intellij.ui.SimpleColoredText; +import com.intellij.util.Consumer; import org.intellij.plugins.intelliLang.Configuration; import org.intellij.plugins.intelliLang.inject.config.BaseInjection; import org.jdom.Element; @@ -41,7 +45,11 @@ public interface LanguageInjectionSupport { BaseInjection createInjection(final Element element); - //void setupPresentation(final Injection injection, final SimpleColoredText presentation); + void setupPresentation(final BaseInjection injection, final SimpleColoredText presentation, final boolean isSelected); Configurable[] createSettings(final Project project, final Configuration configuration); + + AnAction[] createAddActions(final Project project, final Consumer consumer); + + AnAction createEditAction(final Project project, final Factory producer); } diff --git a/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/config/ui/MethodParameterPanel.java b/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/config/ui/MethodParameterPanel.java index 38af3ec65b..e5e459c42f 100644 --- a/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/config/ui/MethodParameterPanel.java +++ b/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/config/ui/MethodParameterPanel.java @@ -17,17 +17,14 @@ package org.intellij.plugins.intelliLang.inject.config.ui; import com.intellij.ide.util.TreeClassChooser; import com.intellij.ide.util.TreeClassChooserFactory; -import com.intellij.openapi.actionSystem.DataKey; -import com.intellij.openapi.actionSystem.DataSink; -import com.intellij.openapi.actionSystem.LangDataKeys; -import com.intellij.openapi.actionSystem.TypeSafeDataProvider; +import com.intellij.openapi.actionSystem.*; +import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.event.DocumentAdapter; import com.intellij.openapi.editor.event.DocumentEvent; import com.intellij.openapi.project.Project; -import com.intellij.openapi.util.Condition; import com.intellij.openapi.util.Computable; -import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.util.Condition; import com.intellij.peer.PeerFactory; import com.intellij.psi.*; import com.intellij.psi.search.GlobalSearchScope; @@ -37,14 +34,14 @@ import com.intellij.ui.ColoredTreeCellRenderer; import com.intellij.ui.ReferenceEditorWithBrowseButton; import com.intellij.ui.SimpleTextAttributes; import com.intellij.ui.dualView.TreeTableView; +import com.intellij.ui.treeStructure.treetable.ListTreeTableModelOnColumns; +import com.intellij.ui.treeStructure.treetable.TreeColumnInfo; import com.intellij.util.Function; import com.intellij.util.Icons; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.Convertor; import com.intellij.util.ui.ColumnInfo; import com.intellij.util.ui.tree.TreeUtil; -import com.intellij.ui.treeStructure.treetable.ListTreeTableModelOnColumns; -import com.intellij.ui.treeStructure.treetable.TreeColumnInfo; import gnu.trove.THashMap; import org.intellij.plugins.intelliLang.inject.config.MethodParameterInjection; import org.intellij.plugins.intelliLang.util.PsiUtilEx; @@ -58,6 +55,7 @@ import javax.swing.tree.TreePath; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; +import java.awt.event.KeyEvent; import java.util.*; import java.util.List; @@ -131,6 +129,29 @@ public class MethodParameterPanel extends AbstractInjectionPanel selectedInjections = myParamsTable.getSelection(); + boolean enabledExists = false; + boolean disabledExists = false; + for (DefaultMutableTreeNode node : selectedInjections) { + final Boolean nodeSelected = isNodeSelected(node); + if (Boolean.TRUE == nodeSelected) enabledExists = true; + else if (Boolean.FALSE == nodeSelected) disabledExists = true; + if (enabledExists && disabledExists) break; + } + boolean allEnabled = !enabledExists && disabledExists; + for (DefaultMutableTreeNode node : selectedInjections) { + setNodeSelected(node, allEnabled); + } + myParamsTable.updateUI(); } @Nullable @@ -291,26 +312,46 @@ public class MethodParameterPanel extends AbstractInjectionPanel(" ") { // "" for the first column's name isn't a good idea final BooleanTableCellRenderer myRenderer = new BooleanTableCellRenderer(); public Boolean valueOf(DefaultMutableTreeNode o) { - final Object userObject = o.getUserObject(); - if (userObject instanceof PsiMethod) { - final PsiMethod method = (PsiMethod)userObject; - return MethodParameterInjection.isInjectable(method.getReturnType(), method.getProject()) ? - myData.get(method).isReturnFlag() : null; - } - else if (userObject instanceof PsiParameter) { - final PsiMethod method = getMethod(o); - final PsiParameter parameter = (PsiParameter)userObject; - final int index = method.getParameterList().getParameterIndex(parameter); - return MethodParameterInjection.isInjectable(parameter.getType(), method.getProject()) ? - myData.get(method).getParamFlags()[index] : null; - } - return null; + return isNodeSelected(o); } public int getWidth(JTable table) { @@ -327,15 +368,7 @@ public class MethodParameterPanel extends AbstractInjectionPanel getColumnClass() { @@ -346,11 +379,6 @@ public class MethodParameterPanel extends AbstractInjectionPanel newInjections = + newInjection.isEnabled() ? Collections.singletonList(newInjection) : Collections.emptyList(); + Configuration.getInstance().replaceInjectionsWithUndo(project, newInjections, Collections.singletonList(originalInjection), + Collections.emptyList()); + } + return true; + + } + + private BaseInjection showInjectionUI(final Project project, final MethodParameterInjection methodParameterInjection) { final MethodParameterInjection savedCopy = methodParameterInjection.copy(); final AbstractInjectionPanel panel = new MethodParameterPanel(methodParameterInjection, project); panel.reset(); @@ -138,15 +161,9 @@ public class JavaLanguageInjectionSupport implements LanguageInjectionSupport { methodParameterInjection.initializePlaces(false); savedCopy.initializePlaces(false); methodParameterInjection.mergeOriginalPlacesFrom(savedCopy, false); - final BaseInjection newInjection = new BaseInjection(methodParameterInjection.getSupportId()).copyFrom(methodParameterInjection); - newInjection.mergeOriginalPlacesFrom(originalInjection, true); - final List newInjections = - newInjection.isEnabled()? Collections.singletonList(newInjection) : Collections.emptyList(); - Configuration.getInstance().replaceInjectionsWithUndo(project, newInjections, Collections.singletonList(originalInjection), - Collections.emptyList()); + return new BaseInjection(methodParameterInjection.getSupportId()).copyFrom(methodParameterInjection); } - return true; - + return null; } public BaseInjection createInjection(final Element element) { @@ -288,7 +305,7 @@ public class JavaLanguageInjectionSupport implements LanguageInjectionSupport { final Configuration configuration = Configuration.getInstance(); template.initializePlaces(false); final BaseInjection baseTemplate = new BaseInjection(template.getSupportId()).copyFrom(template); - final MethodParameterInjection allMethodParameterInjection = createMethodParameterInjection(baseTemplate, contextMethod, true); + final MethodParameterInjection allMethodParameterInjection = createMethodParameterInjection(project, baseTemplate, contextMethod, true); allMethodParameterInjection.initializePlaces(false); // find existing injection for this class. final BaseInjection originalInjection = configuration.findExistingInjection(allMethodParameterInjection); @@ -301,7 +318,7 @@ public class JavaLanguageInjectionSupport implements LanguageInjectionSupport { final InjectionPlace currentPlace = template.getInjectionPlaces().get(0); final String text = currentPlace.getText(); originalCopy.setPlaceEnabled(text, true); - methodParameterInjection = createMethodParameterInjection(originalCopy, contextMethod, false); + methodParameterInjection = createMethodParameterInjection(project, originalCopy, contextMethod, false); } if (InjectLanguageAction.doEditConfigurable(project, new MethodParameterInjectionConfigurable(methodParameterInjection, null, project))) { methodParameterInjection.initializePlaces(false); @@ -329,10 +346,25 @@ public class JavaLanguageInjectionSupport implements LanguageInjectionSupport { }, host); } - private static MethodParameterInjection createMethodParameterInjection(final BaseInjection injection, + private static MethodParameterInjection createMethodParameterInjection(final Project project, + final BaseInjection injection, final PsiMethod contextMethod, final boolean includeAllPlaces) { - final PsiClass containingClass = contextMethod.getContainingClass(); + final PsiClass containingClass; + if (contextMethod != null) { + containingClass = contextMethod.getContainingClass(); + } + else { + String found = null; + final Pattern pattern = Pattern.compile(".*definedInClass\\(\"([^\"]*)\"\\)+"); + for (InjectionPlace place : injection.getInjectionPlaces()) { + final Matcher matcher = pattern.matcher(place.getText()); + if (matcher.matches()) { + found = matcher.group(1); + } + } + containingClass = found != null? JavaPsiFacade.getInstance(project).findClass(found, GlobalSearchScope.allScope(project)) : null; + } final String className = containingClass == null ? "" : StringUtil.notNullize(containingClass.getQualifiedName()); final MethodParameterInjection result = new MethodParameterInjection(); result.copyFrom(injection); @@ -375,4 +407,48 @@ public class JavaLanguageInjectionSupport implements LanguageInjectionSupport { final String signature = MethodParameterInjection.createMethodInfo(method).getMethodSignature(); return PatternBasedInjectionHelper.getPatternStringForJavaPlace(method.getName(), PatternBasedInjectionHelper.getParameterTypesString(signature), parameterIndex, className); } + + @Override + public AnAction[] createAddActions(final Project project, final Consumer consumer) { + return new AnAction[] { + new AnAction("Java Parameter", null, Icons.PARAMETER_ICON) { + @Override + public void actionPerformed(final AnActionEvent e) { + final BaseInjection injection = showInjectionUI(project, new MethodParameterInjection()); + if (injection != null) consumer.consume(injection); + } + } + }; + } + + @Override + public AnAction createEditAction(final Project project, final Factory producer) { + return new AnAction() { + @Override + public void actionPerformed(final AnActionEvent e) { + final BaseInjection originalInjection = producer.create(); + final MethodParameterInjection injection = createMethodParameterInjection(project, originalInjection, null, false); + if (injection != null) { + final BaseInjection newInjection = showInjectionUI(project, injection); + if (newInjection != null) { + originalInjection.copyFrom(newInjection); + originalInjection.initializePlaces(true); + } + } + } + }; + } + + private final Pattern myPattern = Pattern.compile("(.+)(\\(\\S+(?:\\.\\S+)+\\))"); + @Override + public void setupPresentation(final BaseInjection injection, final SimpleColoredText presentation, final boolean isSelected) { + final Matcher matcher = myPattern.matcher(injection.getDisplayName()); + if (matcher.matches()) { + presentation.append(matcher.group(1), SimpleTextAttributes.REGULAR_ATTRIBUTES); + presentation.append(matcher.group(2), isSelected ? SimpleTextAttributes.REGULAR_ATTRIBUTES : SimpleTextAttributes.GRAY_ATTRIBUTES); + } + else { + super.setupPresentation(injection, presentation, isSelected); + } + } } \ No newline at end of file diff --git a/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/xml/XmlLanguageInjectionSupport.java b/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/xml/XmlLanguageInjectionSupport.java index cbba4bf999..d1aeecf144 100644 --- a/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/xml/XmlLanguageInjectionSupport.java +++ b/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/xml/XmlLanguageInjectionSupport.java @@ -17,10 +17,15 @@ package org.intellij.plugins.intelliLang.inject.xml; import com.intellij.lang.Language; +import com.intellij.openapi.actionSystem.AnAction; +import com.intellij.openapi.actionSystem.AnActionEvent; +import com.intellij.openapi.options.Configurable; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.DialogBuilder; import com.intellij.openapi.ui.DialogWrapper; -import com.intellij.openapi.options.Configurable; +import com.intellij.openapi.util.Factory; +import com.intellij.openapi.util.Pair; +import com.intellij.openapi.util.text.StringUtil; import com.intellij.patterns.XmlPatterns; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiLanguageInjectionHost; @@ -29,30 +34,32 @@ import com.intellij.psi.xml.XmlAttribute; import com.intellij.psi.xml.XmlAttributeValue; import com.intellij.psi.xml.XmlTag; import com.intellij.psi.xml.XmlText; +import com.intellij.util.Consumer; +import com.intellij.util.Icons; import com.intellij.util.containers.ContainerUtil; import org.intellij.plugins.intelliLang.Configuration; +import org.intellij.plugins.intelliLang.inject.AbstractLanguageInjectionSupport; +import org.intellij.plugins.intelliLang.inject.EditInjectionSettingsAction; +import org.intellij.plugins.intelliLang.inject.InjectLanguageAction; import org.intellij.plugins.intelliLang.inject.config.*; import org.intellij.plugins.intelliLang.inject.config.ui.AbstractInjectionPanel; import org.intellij.plugins.intelliLang.inject.config.ui.XmlAttributePanel; import org.intellij.plugins.intelliLang.inject.config.ui.XmlTagPanel; import org.intellij.plugins.intelliLang.inject.config.ui.configurables.XmlAttributeInjectionConfigurable; import org.intellij.plugins.intelliLang.inject.config.ui.configurables.XmlTagInjectionConfigurable; -import org.intellij.plugins.intelliLang.inject.LanguageInjectionSupport; -import org.intellij.plugins.intelliLang.inject.EditInjectionSettingsAction; -import org.intellij.plugins.intelliLang.inject.InjectLanguageAction; import org.jdom.Element; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.ArrayList; import java.util.Collections; -import java.util.regex.Pattern; import java.util.regex.Matcher; +import java.util.regex.Pattern; /** * @author Gregory.Shrago */ -public class XmlLanguageInjectionSupport implements LanguageInjectionSupport { +public class XmlLanguageInjectionSupport extends AbstractLanguageInjectionSupport { private static boolean isMine(final PsiLanguageInjectionHost host) { if (host instanceof XmlAttributeValue) { @@ -111,21 +118,29 @@ public class XmlLanguageInjectionSupport implements LanguageInjectionSupport { if (injections.isEmpty()) return false; final Project project = host.getProject(); final BaseInjection originalInjection = injections.get(0); - final BaseInjection xmlInjection; + final BaseInjection xmlInjection = createFrom(originalInjection, host); + if (xmlInjection == null) return false; + final AbstractTagInjection newInjection = showInjectionUI(project, xmlInjection); + if (newInjection != null) { + newInjection.mergeOriginalPlacesFrom(originalInjection, true); + Configuration.getInstance().replaceInjectionsWithUndo( + project, Collections.singletonList(xmlInjection), + Collections.singletonList(originalInjection), + Collections.emptyList()); + } + return true; + } + @Nullable + private AbstractTagInjection showInjectionUI(final Project project, final BaseInjection xmlInjection) { final AbstractInjectionPanel panel; - if (host instanceof XmlText) { - xmlInjection = createFrom(originalInjection, (XmlText)host); + if (xmlInjection instanceof XmlTagInjection) { panel = new XmlTagPanel((XmlTagInjection)xmlInjection, project); } - else if (host instanceof XmlAttributeValue) { - xmlInjection = createFrom(originalInjection, (XmlAttributeValue)host); + else if (xmlInjection instanceof XmlAttributeInjection) { panel = new XmlAttributePanel((XmlAttributeInjection)xmlInjection, project); } - else { - return false; - } - if (xmlInjection == null) return false; + else throw new AssertionError(); panel.reset(); final DialogBuilder builder = new DialogBuilder(project); builder.addOkAction(); @@ -140,57 +155,70 @@ public class XmlLanguageInjectionSupport implements LanguageInjectionSupport { }); if (builder.show() == DialogWrapper.OK_EXIT_CODE) { xmlInjection.initializePlaces(false); - final AbstractTagInjection newInjection = new AbstractTagInjection().copyFrom(xmlInjection); - newInjection.mergeOriginalPlacesFrom(originalInjection, true); - Configuration.getInstance().replaceInjectionsWithUndo( - project, Collections.singletonList(xmlInjection), - Collections.singletonList(originalInjection), - Collections.emptyList()); + return new AbstractTagInjection().copyFrom(xmlInjection); } - return true; + return null; } @Nullable - private static BaseInjection createFrom(final BaseInjection injection, final XmlAttributeValue attributeValue) { - final XmlAttributeInjection result = new XmlAttributeInjection().copyFrom(injection); - result.getInjectionPlaces().clear(); - final PsiElement parent = attributeValue.getParent(); - if (!(parent instanceof XmlAttribute)) return null; - final XmlAttribute attribute = (XmlAttribute)parent; + private static BaseInjection createFrom(final BaseInjection injection, final PsiLanguageInjectionHost host) { + final PsiElement element; + AbstractTagInjection result; + if (host instanceof XmlText) { + final XmlTag xmlTag = ((XmlText)host).getParentTag(); + if (xmlTag == null) return null; + element = xmlTag; + result = new XmlTagInjection().copyFrom(injection); + } + else if (host instanceof XmlAttributeValue) { + final PsiElement parent = host.getParent(); + if (!(parent instanceof XmlAttribute)) return null; + element = parent; + result = new XmlAttributeInjection().copyFrom(injection); + } + else { + result = null; + element = null; + } + final Pattern pattern = Pattern.compile("withLocalName[^\"]*\"([^\"]*)\"\\)+(?:\\.withNamespace[^\"]*\"([^\"]*)\")?"); for (InjectionPlace place : injection.getInjectionPlaces()) { - if (place.isEnabled() && place.getElementPattern() != null && place.getElementPattern().accepts(attribute)) { - final Matcher matcher = Pattern.compile("withLocalName[^\"]*\"([^\"]*)\".*withNamespace[^\"]*\"([^\"]*)\"").matcher(place.getText()); + if (place.isEnabled() && place.getElementPattern() != null && (element == null || place.getElementPattern().accepts(element))) { + final Matcher matcher = pattern.matcher(place.getText()); if (matcher.find()) { - result.setAttributeName(matcher.group(1)); - result.setAttributeNamespace(matcher.group(2)); - if (matcher.find(matcher.end(2))) { - result.setTagName(matcher.group(1)); - result.setTagNamespace(matcher.group(2)); + final Pair pair1 = Pair.create(matcher.group(1), matcher.group(2)); + final Pair pair2; + if (matcher.find(Math.max(matcher.end(1), matcher.end(2)))) { + pair2 = Pair.create(matcher.group(1), matcher.group(2)); } - } - } - } - return result; - } + else pair2 = null; - @Nullable - private static BaseInjection createFrom(final BaseInjection injection, final XmlText xmlText) { - final XmlTagInjection result = new XmlTagInjection().copyFrom(injection); - result.getInjectionPlaces().clear(); - final XmlTag xmlTag = xmlText.getParentTag(); - if (xmlTag == null) return null; - for (InjectionPlace place : injection.getInjectionPlaces()) { - if (place.isEnabled() && place.getElementPattern() != null && place.getElementPattern().accepts(xmlTag)) { - final Matcher matcher = Pattern.compile("withLocalName[^\"]*\"([^\"]*)\".*withNamespace[^\"]*\"([^\"]*)\"").matcher(place.getText()); - if (matcher.find()) { - result.setTagName(matcher.group(1)); - result.setTagNamespace(matcher.group(2)); - } - if (injection instanceof AbstractTagInjection) { - result.setApplyToSubTagTexts(((AbstractTagInjection)injection).isApplyToSubTagTexts()); + if (result == null) { + if (place.getText().startsWith("xmlTag")) result = new XmlTagInjection().copyFrom(injection); + if (place.getText().startsWith("xmlAttribute")) result = new XmlAttributeInjection().copyFrom(injection); + else continue; + } + if (result instanceof XmlAttributeInjection) { + ((XmlAttributeInjection)result).setAttributeName(pair1.first); + ((XmlAttributeInjection)result).setAttributeNamespace(StringUtil.notNullize(pair1.second)); + if (pair2 != null) { + result.setTagName(pair2.first); + result.setTagNamespace(pair2.second); + } + } + else if (result instanceof XmlTagInjection) { + result.setTagName(pair1.first); + result.setTagNamespace(StringUtil.notNullize(pair1.second)); + } + else continue; + // for debugging + //result.initializePlaces(false); + //if (!place.getText().equals(result.getInjectionPlaces().get(0).getText())) { + //} + break; } } } + if (result != null) result.getInjectionPlaces().clear(); return result; } @@ -275,4 +303,41 @@ public class XmlLanguageInjectionSupport implements LanguageInjectionSupport { return result; } + @Override + public AnAction[] createAddActions(final Project project, final Consumer consumer) { + return new AnAction[] { + new AnAction("XML Tag Injection", null, Icons.XML_TAG_ICON) { + @Override + public void actionPerformed(final AnActionEvent e) { + final AbstractTagInjection newInjection = showInjectionUI(project, new XmlTagInjection()); + if (newInjection != null) consumer.consume(newInjection); + } + }, + new AnAction("XML Attribute Injection", null, Icons.ANNOTATION_TYPE_ICON) { + @Override + public void actionPerformed(final AnActionEvent e) { + final AbstractTagInjection injection = showInjectionUI(project, new XmlAttributeInjection()); + if (injection != null) consumer.consume(injection); + } + } + }; + } + + @Override + public AnAction createEditAction(final Project project, final Factory producer) { + return new AnAction() { + @Override + public void actionPerformed(final AnActionEvent e) { + final BaseInjection originalInjection = producer.create(); + final BaseInjection injection = createFrom(originalInjection, null); + if (injection != null) { + final AbstractTagInjection newInjection = showInjectionUI(project, injection); + if (newInjection != null) { + originalInjection.copyFrom(newInjection); + originalInjection.initializePlaces(true); + } + } + } + }; + } } -- 2.11.4.GIT