diff --git a/platform/structuralsearch/source/com/intellij/structuralsearch/plugin/ui/FileTypeInfo.java b/platform/structuralsearch/source/com/intellij/structuralsearch/plugin/ui/FileTypeInfo.java index 6d36aab6f817..9575c862748a 100644 --- a/platform/structuralsearch/source/com/intellij/structuralsearch/plugin/ui/FileTypeInfo.java +++ b/platform/structuralsearch/source/com/intellij/structuralsearch/plugin/ui/FileTypeInfo.java @@ -21,11 +21,19 @@ public class FileTypeInfo { private final FileType myFileType; private final Language myDialect; + private final String myContext; + private final boolean myEnabled; private final String myDescription; - public FileTypeInfo(@NotNull FileType fileType, @Nullable Language dialect, boolean duplicated) { + public FileTypeInfo(@NotNull FileType fileType, + @Nullable Language dialect, + @Nullable String context, + boolean enabled, + boolean duplicated) { myFileType = fileType; myDialect = dialect; + myContext = context; + myEnabled = enabled; myDescription = getDescription(fileType, duplicated); } @@ -39,8 +47,24 @@ public class FileTypeInfo { return myDialect; } + @Nullable + public String getContext() { + return myContext; + } + @NotNull public String getText() { + if (myDialect != null) { + return myDialect.getDisplayName(); + } + if (myContext != null) { + return myContext + " Context"; + } + return myFileType.getName(); + } + + @NotNull + public String getSearchText() { if (myDialect != null) { return myDialect.getDisplayName(); } @@ -49,14 +73,27 @@ public class FileTypeInfo { @NotNull public String getFullText() { - if (myDialect == null) { - return myDescription; + if (myDialect != null) { + return myDescription + " - " + myDialect.getDisplayName(); } - return myDescription + " - " + myDialect.getDisplayName(); + if (myContext != null) { + return myDescription + " - " + myContext + " Context"; + } + return myDescription; } - public boolean isDialect() { - return myDialect != null; + public boolean isNested() { + return myDialect != null || myContext != null; + } + + public boolean isEnabled() { + return myEnabled; + } + + public boolean isEqualTo(@NotNull FileType fileType, @Nullable Language dialect, @Nullable String context) { + return Objects.equals(myFileType, fileType) && + Objects.equals(myDialect, dialect) && + Objects.equals(myContext, context); } @NotNull @@ -75,11 +112,17 @@ public class FileTypeInfo { if (!(o instanceof FileTypeInfo)) return false; FileTypeInfo info = (FileTypeInfo)o; return Objects.equals(myFileType, info.myFileType) && - Objects.equals(myDialect, info.myDialect); + Objects.equals(myDialect, info.myDialect) && + Objects.equals(myContext, info.myContext); } @Override public int hashCode() { - return Objects.hash(myFileType, myDialect); + return Objects.hash(myFileType, myDialect, myContext); + } + + @Override + public String toString() { + return getFullText(); } } diff --git a/platform/structuralsearch/source/com/intellij/structuralsearch/plugin/ui/FileTypeSelector.java b/platform/structuralsearch/source/com/intellij/structuralsearch/plugin/ui/FileTypeSelector.java index 4ca8894ed2f6..184bf6d2e07c 100644 --- a/platform/structuralsearch/source/com/intellij/structuralsearch/plugin/ui/FileTypeSelector.java +++ b/platform/structuralsearch/source/com/intellij/structuralsearch/plugin/ui/FileTypeSelector.java @@ -6,6 +6,9 @@ import com.intellij.lang.LanguageUtil; import com.intellij.openapi.fileTypes.FileType; import com.intellij.openapi.fileTypes.LanguageFileType; import com.intellij.openapi.ui.ComboBox; +import com.intellij.structuralsearch.StructuralSearchProfile; +import com.intellij.structuralsearch.StructuralSearchProfileBase; +import com.intellij.structuralsearch.StructuralSearchUtil; import com.intellij.ui.ComboboxSpeedSearch; import com.intellij.ui.LayeredIcon; import com.intellij.ui.ListCellRendererWrapper; @@ -43,35 +46,65 @@ public class FileTypeSelector extends ComboBox { return info != null ? info.getFileType() : null; } - public void setSelectedItem(@NotNull FileType type, @Nullable Language dialect) { + public void setSelectedItem(@NotNull FileType type, @Nullable Language dialect, @Nullable String context) { DefaultComboBoxModel model = (DefaultComboBoxModel)getModel(); for (int i = 0; i < model.getSize(); i++) { FileTypeInfo info = model.getElementAt(i); - if (info.getFileType() == type && info.getDialect() == dialect) { + if (info.isEqualTo(type, dialect, context)) { setSelectedItem(info); return; } } } + @Override + public void setSelectedItem(Object anObject) { + if (anObject instanceof FileTypeInfo) { + final FileTypeInfo selectedInfo = (FileTypeInfo)anObject; + if (!selectedInfo.isEnabled()) { + final MyComboBoxModel model = (MyComboBoxModel)getModel(); + final int index = model.getIndexOf(selectedInfo); + if (index >= 0 && index + 1 < model.getSize()) { + final FileTypeInfo nextInfo = model.getElementAt(index + 1); + super.setSelectedItem(nextInfo); + return; + } + } + } + super.setSelectedItem(anObject); + } + @NotNull private static DefaultComboBoxModel createModel(List types) { final List infos = new ArrayList<>(); for (FileType fileType : types) { - boolean duplicated = isDuplicated(fileType, types); - infos.add(new FileTypeInfo(fileType, null, duplicated)); + final boolean duplicated = isDuplicated(fileType, types); + + final StructuralSearchProfile profile = StructuralSearchUtil.getProfileByFileType(fileType); + if (profile instanceof StructuralSearchProfileBase) { + final String[] contextNames = ((StructuralSearchProfileBase)profile).getContextNames(); + if (contextNames.length != 0) { + infos.add(new FileTypeInfo(fileType, null, null, false, duplicated)); + for (String contextName: contextNames) { + infos.add(new FileTypeInfo(fileType, null, contextName, true, duplicated)); + } + continue; // proceed with the next file type + } + } + + infos.add(new FileTypeInfo(fileType, null, null, true, duplicated)); if (fileType instanceof LanguageFileType) { final Language language = ((LanguageFileType)fileType).getLanguage(); final Language[] languageDialects = LanguageUtil.getLanguageDialects(language); Arrays.sort(languageDialects, Comparator.comparing(Language::getDisplayName)); for (Language dialect : languageDialects) { - infos.add(new FileTypeInfo(fileType, dialect, duplicated)); + infos.add(new FileTypeInfo(fileType, dialect, null, true, duplicated)); } } } - return new DefaultComboBoxModel<>(infos.toArray(FileTypeInfo.EMPTY_ARRAY)); + return new MyComboBoxModel(infos); } private static boolean isDuplicated(@NotNull FileType fileType, @NotNull List types) { @@ -84,13 +117,19 @@ public class FileTypeSelector extends ComboBox { return false; } + private static class MyComboBoxModel extends DefaultComboBoxModel { + public MyComboBoxModel(List infos) { + super(infos.toArray(FileTypeInfo.EMPTY_ARRAY)); + } + } + private static class MyCellRenderer extends ListCellRendererWrapper { private static final Icon EMPTY_ICON = EmptyIcon.ICON_18; private static final Icon WIDE_EMPTY_ICON = JBUI.scale(EmptyIcon.create(32, 18)); @Override public void customize(JList list, FileTypeInfo info, int index, boolean selected, boolean hasFocus) { - if (info.isDialect() && index >= 0) { + if (info.isNested() && index >= 0) { setIcon(WIDE_EMPTY_ICON); setText(info.getText()); } @@ -117,7 +156,7 @@ public class FileTypeSelector extends ComboBox { @Override protected String getElementText(Object element) { - return ((FileTypeInfo)element).getText(); + return ((FileTypeInfo)element).getSearchText(); } } } diff --git a/platform/structuralsearch/source/com/intellij/structuralsearch/plugin/ui/SearchDialog.java b/platform/structuralsearch/source/com/intellij/structuralsearch/plugin/ui/SearchDialog.java index d671fa215d35..fc60fae23438 100644 --- a/platform/structuralsearch/source/com/intellij/structuralsearch/plugin/ui/SearchDialog.java +++ b/platform/structuralsearch/source/com/intellij/structuralsearch/plugin/ui/SearchDialog.java @@ -22,7 +22,6 @@ import com.intellij.openapi.progress.ProcessCanceledException; import com.intellij.openapi.project.Project; import com.intellij.openapi.project.ProjectManager; import com.intellij.openapi.project.ProjectManagerListener; -import com.intellij.openapi.ui.ComboBox; import com.intellij.openapi.ui.DialogWrapper; import com.intellij.openapi.util.Disposer; import com.intellij.openapi.util.TextRange; @@ -68,7 +67,6 @@ public class SearchDialog extends DialogWrapper { private JCheckBox caseSensitiveMatch; private FileTypeSelector fileTypes; - private JComboBox contexts; private JLabel status; private JLabel statusText; @@ -210,31 +208,23 @@ public class SearchDialog extends DialogWrapper { Collections.sort(types, (o1, o2) -> o1.getName().compareToIgnoreCase(o2.getName())); fileTypes = new FileTypeSelector(types); - contexts = new ComboBox<>(60); final JLabel jLabel = new JLabel(SSRBundle.message("search.dialog.file.type.label")); - final JLabel jLabel2 = new JLabel(SSRBundle.message("search.dialog.context.label")); - searchOptions.add(UIUtil.createOptionLine(jLabel, fileTypes, jLabel2, contexts)); - + searchOptions.add(UIUtil.createOptionLine(jLabel, fileTypes)); jLabel.setLabelFor(fileTypes); - jLabel2.setLabelFor(contexts); detectFileTypeAndDialect(); - fileTypes.setSelectedItem(ourFtSearchVariant, ourDialect); + fileTypes.setSelectedItem(ourFtSearchVariant, ourDialect, ourContext); fileTypes.addItemListener(new ItemListener() { @Override public void itemStateChanged(ItemEvent e) { if (e.getStateChange() == ItemEvent.SELECTED) { - updateContexts(); updateEditor(); initiateValidation(); } } }); - contexts.setSelectedItem(ourContext); - - updateContexts(); } void updateEditor() { @@ -250,23 +240,6 @@ public class SearchDialog extends DialogWrapper { } } - void updateContexts() { - final FileType fileType = fileTypes.getSelectedFileType(); - final StructuralSearchProfile profile = StructuralSearchUtil.getProfileByFileType(fileType); - - if (profile instanceof StructuralSearchProfileBase) { - final String[] contextNames = ((StructuralSearchProfileBase)profile).getContextNames(); - if (contextNames.length > 0) { - contexts.setModel(new DefaultComboBoxModel<>(contextNames)); - contexts.setSelectedItem(contextNames[0]); - contexts.setEnabled(true); - return; - } - } - contexts.setSelectedItem(null); - contexts.setEnabled(false); - } - private void detectFileTypeAndDialect() { final PsiFile file = searchContext.getFile(); if (file != null) { @@ -321,10 +294,7 @@ public class SearchDialog extends DialogWrapper { recursiveMatching.setSelected(isRecursiveSearchEnabled() && matchOptions.isRecursiveSearch()); caseSensitiveMatch.setSelected(matchOptions.isCaseSensitiveMatch()); - fileTypes.setSelectedItem(matchOptions.getFileType(), matchOptions.getDialect()); - if (matchOptions.getPatternContext() != null) { - contexts.setSelectedItem(matchOptions.getPatternContext()); - } + fileTypes.setSelectedItem(matchOptions.getFileType(), matchOptions.getDialect(), matchOptions.getPatternContext()); searchCriteriaEdit.putUserData(SubstitutionShortInfoHandler.CURRENT_CONFIGURATION_KEY, myConfiguration); } @@ -706,7 +676,7 @@ public class SearchDialog extends DialogWrapper { final FileTypeInfo info = fileTypes.getSelectedItem(); ourFtSearchVariant = info != null ? info.getFileType() : null; ourDialect = info != null ? info.getDialect() : null; - ourContext = (String)contexts.getSelectedItem(); + ourContext = info != null ? info.getContext() : null; FileType fileType = ourFtSearchVariant; options.setFileType(fileType); options.setDialect(ourDialect); diff --git a/platform/structuralsearch/source/com/intellij/structuralsearch/plugin/ui/StructuralSearchDialog.java b/platform/structuralsearch/source/com/intellij/structuralsearch/plugin/ui/StructuralSearchDialog.java index 078c4fd6b723..801ff8ab9922 100644 --- a/platform/structuralsearch/source/com/intellij/structuralsearch/plugin/ui/StructuralSearchDialog.java +++ b/platform/structuralsearch/source/com/intellij/structuralsearch/plugin/ui/StructuralSearchDialog.java @@ -27,7 +27,6 @@ import com.intellij.openapi.progress.ProcessCanceledException; import com.intellij.openapi.project.Project; import com.intellij.openapi.project.ProjectManager; import com.intellij.openapi.project.ProjectManagerListener; -import com.intellij.openapi.ui.ComboBox; import com.intellij.openapi.ui.DialogWrapper; import com.intellij.openapi.util.Disposer; import com.intellij.openapi.util.Key; @@ -77,7 +76,6 @@ public class StructuralSearchDialog extends DialogWrapper { private JCheckBox caseSensitiveMatch; private FileTypeSelector fileTypes; - private JComboBox contexts; protected Configuration myConfiguration; private JCheckBox openInNewTab; @@ -223,23 +221,6 @@ public class StructuralSearchDialog extends DialogWrapper { } } - void updateContexts() { - final FileType fileType = fileTypes.getSelectedFileType(); - final StructuralSearchProfile profile = StructuralSearchUtil.getProfileByFileType(fileType); - - if (profile instanceof StructuralSearchProfileBase) { - final String[] contextNames = ((StructuralSearchProfileBase)profile).getContextNames(); - if (contextNames.length > 0) { - contexts.setModel(new DefaultComboBoxModel<>(contextNames)); - contexts.setSelectedItem(contextNames[0]); - contexts.setEnabled(true); - return; - } - } - contexts.setSelectedItem(null); - contexts.setEnabled(false); - } - private void detectFileTypeAndDialect() { final PsiFile file = searchContext.getFile(); if (file != null) { @@ -299,10 +280,7 @@ public class StructuralSearchDialog extends DialogWrapper { recursiveMatching.setSelected(isRecursiveSearchEnabled() && matchOptions.isRecursiveSearch()); caseSensitiveMatch.setSelected(matchOptions.isCaseSensitiveMatch()); - fileTypes.setSelectedItem(matchOptions.getFileType(), matchOptions.getDialect()); - if (matchOptions.getPatternContext() != null) { - contexts.setSelectedItem(matchOptions.getPatternContext()); - } + fileTypes.setSelectedItem(matchOptions.getFileType(), matchOptions.getDialect(), matchOptions.getPatternContext()); final Editor editor = searchCriteriaEdit.getEditor(); if (editor != null) { editor.putUserData(SubstitutionShortInfoHandler.CURRENT_CONFIGURATION_KEY, myConfiguration); @@ -402,12 +380,11 @@ public class StructuralSearchDialog extends DialogWrapper { Collections.sort(types, (o1, o2) -> o1.getName().compareToIgnoreCase(o2.getName())); fileTypes = new FileTypeSelector(types); fileTypes.setMinimumAndPreferredWidth(200); - fileTypes.setSelectedItem(ourFtSearchVariant, ourDialect); + fileTypes.setSelectedItem(ourFtSearchVariant, ourDialect, ourContext); fileTypes.addItemListener(new ItemListener() { @Override public void itemStateChanged(ItemEvent e) { if (e.getStateChange() == ItemEvent.SELECTED) { - updateContexts(); updateEditor(); initiateValidation(); } @@ -415,7 +392,6 @@ public class StructuralSearchDialog extends DialogWrapper { }); final JLabel fileTypeLabel = new JLabel(SSRBundle.message("search.dialog.file.type.label")); fileTypeLabel.setLabelFor(fileTypes); - contexts = new ComboBox<>(60); // todo remove me, dummy final DefaultActionGroup templateActionGroup = new DefaultActionGroup( new AnAction(SSRBundle.message("save.template.text.button")) { @@ -653,7 +629,7 @@ public class StructuralSearchDialog extends DialogWrapper { final FileTypeInfo info = fileTypes.getSelectedItem(); ourFtSearchVariant = info != null ? info.getFileType() : null; ourDialect = info != null ? info.getDialect() : null; - ourContext = (String)contexts.getSelectedItem(); + ourContext = info != null ? info.getContext() : null; FileType fileType = ourFtSearchVariant; options.setFileType(fileType); options.setDialect(ourDialect);