diff options
Diffstat (limited to 'platform/structuralsearch/source/com/intellij/structuralsearch/plugin/ui/SearchDialog.java')
-rw-r--r-- | platform/structuralsearch/source/com/intellij/structuralsearch/plugin/ui/SearchDialog.java | 995 |
1 files changed, 995 insertions, 0 deletions
diff --git a/platform/structuralsearch/source/com/intellij/structuralsearch/plugin/ui/SearchDialog.java b/platform/structuralsearch/source/com/intellij/structuralsearch/plugin/ui/SearchDialog.java new file mode 100644 index 000000000000..a3bee702563e --- /dev/null +++ b/platform/structuralsearch/source/com/intellij/structuralsearch/plugin/ui/SearchDialog.java @@ -0,0 +1,995 @@ +package com.intellij.structuralsearch.plugin.ui; + +import com.intellij.codeInsight.daemon.DaemonCodeAnalyzer; +import com.intellij.codeInsight.template.impl.Variable; +import com.intellij.find.FindBundle; +import com.intellij.find.FindProgressIndicator; +import com.intellij.find.FindSettings; +import com.intellij.ide.IdeBundle; +import com.intellij.ide.util.scopeChooser.ScopeChooserCombo; +import com.intellij.lang.Language; +import com.intellij.lang.LanguageUtil; +import com.intellij.openapi.application.Result; +import com.intellij.openapi.application.WriteAction; +import com.intellij.openapi.command.WriteCommandAction; +import com.intellij.openapi.editor.Document; +import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.editor.EditorFactory; +import com.intellij.openapi.editor.SelectionModel; +import com.intellij.openapi.editor.event.DocumentEvent; +import com.intellij.openapi.editor.event.DocumentListener; +import com.intellij.openapi.fileEditor.FileEditorManager; +import com.intellij.openapi.fileTypes.FileType; +import com.intellij.openapi.fileTypes.LanguageFileType; +import com.intellij.openapi.fileTypes.impl.FileTypeRenderer; +import com.intellij.openapi.progress.ProgressIndicator; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.ui.ComboBox; +import com.intellij.openapi.ui.DialogWrapper; +import com.intellij.openapi.util.Disposer; +import com.intellij.openapi.util.Factory; +import com.intellij.openapi.util.TextRange; +import com.intellij.openapi.wm.ToolWindow; +import com.intellij.openapi.wm.ToolWindowId; +import com.intellij.openapi.wm.ToolWindowManager; +import com.intellij.psi.PsiDocumentManager; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiFile; +import com.intellij.psi.codeStyle.CodeStyleManager; +import com.intellij.psi.search.GlobalSearchScope; +import com.intellij.psi.search.SearchScope; +import com.intellij.structuralsearch.*; +import com.intellij.structuralsearch.impl.matcher.MatcherImpl; +import com.intellij.structuralsearch.plugin.StructuralSearchPlugin; +import com.intellij.ui.ComboboxSpeedSearch; +import com.intellij.ui.IdeBorderFactory; +import com.intellij.ui.ListCellRendererWrapper; +import com.intellij.ui.TitledSeparator; +import com.intellij.usages.*; +import com.intellij.util.Alarm; +import com.intellij.util.Processor; +import org.jetbrains.annotations.NonNls; +import org.jetbrains.annotations.NotNull; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ItemEvent; +import java.awt.event.ItemListener; +import java.util.*; +import java.util.List; + +/** + * Class to show the user the request for search + */ +@SuppressWarnings({"RefusedBequest", "AssignmentToStaticFieldFromInstanceMethod"}) +public class SearchDialog extends DialogWrapper implements ConfigurationCreator { + protected SearchContext searchContext; + + // text for search + protected Editor searchCriteriaEdit; + + // options of search scope + private ScopeChooserCombo myScopeChooserCombo; + + private JCheckBox recursiveMatching; + private JCheckBox caseSensitiveMatch; + + private JComboBox fileTypes; + private JComboBox contexts; + private JComboBox dialects; + private JLabel status; + private JLabel statusText; + + protected SearchModel model; + private JCheckBox openInNewTab; + private final Alarm myAlarm = new Alarm(Alarm.ThreadToUse.SHARED_THREAD); + + public static final String USER_DEFINED = SSRBundle.message("new.template.defaultname"); + protected final ExistingTemplatesComponent existingTemplatesComponent; + + private boolean useLastConfiguration; + + private static boolean ourOpenInNewTab; + + @NonNls private FileType ourFtSearchVariant = StructuralSearchUtil.getDefaultFileType(); + private static Language ourDialect = null; + private static String ourContext = null; + + private final boolean myShowScopePanel; + private final boolean myRunFindActionOnClose; + private boolean myDoingOkAction; + + private String mySavedEditorText; + private JPanel myContentPanel; + private JComponent myEditorPanel; + + public SearchDialog(SearchContext searchContext) { + this(searchContext, true, true); + } + + public SearchDialog(SearchContext searchContext, boolean showScope, boolean runFindActionOnClose) { + super(searchContext.getProject(), true); + + if (showScope) setModal(false); + myShowScopePanel = showScope; + myRunFindActionOnClose = runFindActionOnClose; + this.searchContext = (SearchContext)searchContext.clone(); + setTitle(getDefaultTitle()); + + if (runFindActionOnClose) { + setOKButtonText(FindBundle.message("find.dialog.find.button")); + } + + existingTemplatesComponent = ExistingTemplatesComponent.getInstance(this.searchContext.getProject()); + model = new SearchModel(createConfiguration()); + + init(); + } + + protected UsageViewContext createUsageViewContext(Configuration configuration) { + return new UsageViewContext(searchContext, configuration); + } + + public void setUseLastConfiguration(boolean useLastConfiguration) { + this.useLastConfiguration = useLastConfiguration; + } + + public void setSearchPattern(final Configuration config) { + model.setShadowConfig(config); + setValuesFromConfig(config); + initiateValidation(); + } + + protected Editor createEditor(final SearchContext searchContext, String text) { + Editor editor = null; + + if (fileTypes != null) { + final FileType fileType = (FileType)fileTypes.getSelectedItem(); + final Language dialect = (Language)dialects.getSelectedItem(); + + final StructuralSearchProfile profile = StructuralSearchUtil.getProfileByFileType(fileType); + if (profile != null) { + editor = profile.createEditor(searchContext, fileType, dialect, text, useLastConfiguration); + } + } + + if (editor == null) { + final EditorFactory factory = EditorFactory.getInstance(); + final Document document = factory.createDocument(""); + editor = factory.createEditor(document, searchContext.getProject()); + editor.getSettings().setFoldingOutlineShown(false); + } + + editor.getDocument().addDocumentListener(new DocumentListener() { + @Override + public void beforeDocumentChange(final DocumentEvent event) { + } + + @Override + public void documentChanged(final DocumentEvent event) { + initiateValidation(); + } + }); + + return editor; + } + + private void initiateValidation() { + myAlarm.cancelAllRequests(); + myAlarm.addRequest(new Runnable() { + + @Override + public void run() { + try { + new WriteAction(){ + @Override + protected void run(Result result) throws Throwable { + if (!isValid()) { + getOKAction().setEnabled(false); + } + else { + getOKAction().setEnabled(true); + reportMessage(null, null); + } + } + }.execute(); + } + catch (Exception e) { + e.printStackTrace(); + } + } + }, 500); + } + + protected void buildOptions(JPanel searchOptions) { + recursiveMatching = new JCheckBox(SSRBundle.message("recursive.matching.checkbox"), true); + if (isRecursiveSearchEnabled()) { + searchOptions.add(UIUtil.createOptionLine(recursiveMatching)); + } + + caseSensitiveMatch = new JCheckBox(FindBundle.message("find.options.case.sensitive"), true); + searchOptions.add(UIUtil.createOptionLine(caseSensitiveMatch)); + + final List<FileType> types = new ArrayList<FileType>(); + + for (FileType fileType : StructuralSearchUtil.getSuitableFileTypes()) { + if (StructuralSearchUtil.getProfileByFileType(fileType) != null) { + types.add(fileType); + } + } + Collections.sort(types, new Comparator<FileType>() { + @Override + public int compare(FileType o1, FileType o2) { + return o1.getName().compareToIgnoreCase(o2.getName()); + } + }); + + final DefaultComboBoxModel comboBoxModel = new DefaultComboBoxModel(types.toArray(new FileType[types.size()])); + comboBoxModel.setSelectedItem(ourFtSearchVariant); + fileTypes = new ComboBox(comboBoxModel); + fileTypes.setRenderer(new FileTypeRenderer()); + new ComboboxSpeedSearch(fileTypes) { + @Override + protected String getElementText(Object element) { + return ((FileType)element).getName(); + } + }; + fileTypes.addItemListener(new ItemListener() { + @Override + public void itemStateChanged(ItemEvent e) { + updateDialectsAndContexts(); + updateEditor(); + } + }); + + contexts = new JComboBox(new DefaultComboBoxModel()); + contexts.setPreferredSize(new Dimension(60, -1)); + + dialects = new JComboBox(new DefaultComboBoxModel()); + dialects.setRenderer(new ListCellRendererWrapper() { + @Override + public void customize(JList list, Object value, int index, boolean selected, boolean hasFocus) { + if (value == null) { + setText("None"); + } + else if (value instanceof Language) { + setText(((Language)value).getDisplayName()); + } + } + }); + dialects.addItemListener(new ItemListener() { + @Override + public void itemStateChanged(ItemEvent e) { + updateEditor(); + } + }); + new ComboboxSpeedSearch(dialects); + dialects.setPreferredSize(new Dimension(120, -1)); + + final JLabel jLabel = new JLabel(SSRBundle.message("search.dialog.file.type.label")); + final JLabel jLabel2 = new JLabel(SSRBundle.message("search.dialog.context.label")); + final JLabel jLabel3 = new JLabel(SSRBundle.message("search.dialog.file.dialect.label")); + searchOptions.add( + UIUtil.createOptionLine( + new JComponent[]{ + jLabel, + fileTypes, + (JComponent)Box.createHorizontalStrut(8), + jLabel2, + contexts, + (JComponent)Box.createHorizontalStrut(8), + jLabel3, + dialects, + } + ) + ); + + jLabel.setLabelFor(fileTypes); + jLabel2.setLabelFor(contexts); + jLabel3.setLabelFor(dialects); + + detectFileTypeAndDialect(); + + fileTypes.setSelectedItem(ourFtSearchVariant); + fileTypes.addItemListener(new ItemListener() { + @Override + public void itemStateChanged(ItemEvent e) { + if (e.getStateChange() == ItemEvent.SELECTED) initiateValidation(); + } + }); + + dialects.setSelectedItem(ourDialect); + contexts.setSelectedItem(ourContext); + + updateDialectsAndContexts(); + } + + private void updateEditor() { + if (myContentPanel != null) { + if (myEditorPanel != null) { + myContentPanel.remove(myEditorPanel); + } + disposeEditorContent(); + myEditorPanel = createEditorContent(); + myContentPanel.add(myEditorPanel, BorderLayout.CENTER); + myContentPanel.revalidate(); + } + } + + private void updateDialectsAndContexts() { + final FileType fileType = (FileType)fileTypes.getSelectedItem(); + if (fileType instanceof LanguageFileType) { + Language language = ((LanguageFileType)fileType).getLanguage(); + Language[] languageDialects = LanguageUtil.getLanguageDialects(language); + Arrays.sort(languageDialects, new Comparator<Language>() { + @Override + public int compare(Language o1, Language o2) { + return o1.getDisplayName().compareTo(o2.getDisplayName()); + } + }); + Language[] variants = new Language[languageDialects.length + 1]; + variants[0] = null; + System.arraycopy(languageDialects, 0, variants, 1, languageDialects.length); + dialects.setModel(new DefaultComboBoxModel(variants)); + dialects.setEnabled(variants.length > 1); + } + + 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) { + PsiElement context = null; + + if (searchContext.getEditor() != null) { + context = file.findElementAt(searchContext.getEditor().getCaretModel().getOffset()); + if (context != null) { + context = context.getParent(); + } + } + if (context == null) { + context = file; + } + + FileType detectedFileType = null; + + StructuralSearchProfile profile = StructuralSearchUtil.getProfileByPsiElement(context); + if (profile != null) { + FileType fileType = profile.detectFileType(context); + if (fileType != null) { + detectedFileType = fileType; + } + } + + if (detectedFileType == null) { + for (FileType fileType : StructuralSearchUtil.getSuitableFileTypes()) { + if (fileType instanceof LanguageFileType && ((LanguageFileType)fileType).getLanguage().equals(context.getLanguage())) { + detectedFileType = fileType; + break; + } + } + } + + ourFtSearchVariant = detectedFileType != null ? + detectedFileType : + StructuralSearchUtil.getDefaultFileType(); + + // todo: detect dialect + + /*if (file.getLanguage() == StdLanguages.HTML || + (file.getFileType() == StdFileTypes.JSP && + contextLanguage == StdLanguages.HTML + ) + ) { + ourFileType = "html"; + } + else if (file.getLanguage() == StdLanguages.XHTML || + (file.getFileType() == StdFileTypes.JSPX && + contextLanguage == StdLanguages.HTML + )) { + ourFileType = "xml"; + } + else { + ourFileType = DEFAULT_TYPE_NAME; + }*/ + } + } + + protected boolean isRecursiveSearchEnabled() { + return true; + } + + public void setValuesFromConfig(Configuration configuration) { + //searchCriteriaEdit.putUserData(SubstitutionShortInfoHandler.CURRENT_CONFIGURATION_KEY, configuration); + + setDialogTitle(configuration); + final MatchOptions matchOptions = configuration.getMatchOptions(); + + UIUtil.setContent( + searchCriteriaEdit, + matchOptions.getSearchPattern(), + 0, + searchCriteriaEdit.getDocument().getTextLength(), + searchContext.getProject() + ); + + model.getConfig().getMatchOptions().setSearchPattern( + matchOptions.getSearchPattern() + ); + + recursiveMatching.setSelected( + isRecursiveSearchEnabled() && matchOptions.isRecursiveSearch() + ); + + caseSensitiveMatch.setSelected( + matchOptions.isCaseSensitiveMatch() + ); + + model.getConfig().getMatchOptions().clearVariableConstraints(); + if (matchOptions.hasVariableConstraints()) { + for (Iterator<String> i = matchOptions.getVariableConstraintNames(); i.hasNext(); ) { + final MatchVariableConstraint constraint = (MatchVariableConstraint)matchOptions.getVariableConstraint(i.next()).clone(); + model.getConfig().getMatchOptions().addVariableConstraint(constraint); + } + } + + MatchOptions options = configuration.getMatchOptions(); + StructuralSearchProfile profile = StructuralSearchUtil.getProfileByFileType(options.getFileType()); + assert profile != null; + fileTypes.setSelectedItem(options.getFileType()); + dialects.setSelectedItem(options.getDialect()); + if (options.getPatternContext() != null) { + contexts.setSelectedItem(options.getPatternContext()); + } + } + + private void setDialogTitle(final Configuration configuration) { + setTitle(getDefaultTitle() + " - " + configuration.getName()); + } + + @Override + public Configuration createConfiguration() { + SearchConfiguration configuration = new SearchConfiguration(); + configuration.setName(USER_DEFINED); + return configuration; + } + + protected void addOrReplaceSelection(final String selection) { + addOrReplaceSelectionForEditor(selection, searchCriteriaEdit); + } + + protected final void addOrReplaceSelectionForEditor(final String selection, Editor editor) { + final Project project = searchContext.getProject(); + UIUtil.setContent(editor, selection, 0, -1, project); + final Document document = editor.getDocument(); + editor.getSelectionModel().setSelection(0, document.getTextLength()); + final PsiDocumentManager documentManager = PsiDocumentManager.getInstance(project); + documentManager.commitDocument(document); + final PsiFile file = documentManager.getPsiFile(document); + if (file == null) return; + + new WriteCommandAction(project, file) { + @Override protected void run(@NotNull Result result) throws Throwable { + CodeStyleManager.getInstance(project).adjustLineIndent(file, new TextRange(0, document.getTextLength())); + } + }.execute(); + } + + protected void runAction(final Configuration config, final SearchContext searchContext) { + createUsageView(searchContext, config); + } + + protected void createUsageView(final SearchContext searchContext, final Configuration config) { + UsageViewManager manager = UsageViewManager.getInstance(searchContext.getProject()); + + final UsageViewContext context = createUsageViewContext(config); + final UsageViewPresentation presentation = new UsageViewPresentation(); + presentation.setOpenInNewTab(openInNewTab.isSelected()); + presentation.setScopeText(config.getMatchOptions().getScope().getDisplayName()); + context.configure(presentation); + + final FindUsagesProcessPresentation processPresentation = new FindUsagesProcessPresentation(presentation); + processPresentation.setShowNotFoundMessage(true); + processPresentation.setShowPanelIfOnlyOneUsage(true); + + processPresentation.setProgressIndicatorFactory( + new Factory<ProgressIndicator>() { + @Override + public ProgressIndicator create() { + return new FindProgressIndicator(searchContext.getProject(), presentation.getScopeText()) { + @Override + public void cancel() { + context.getCommand().stopAsyncSearch(); + super.cancel(); + } + }; + } + } + ); + + PsiDocumentManager.getInstance(getProject()).commitAllDocuments(); + + manager.searchAndShowUsages( + new UsageTarget[]{ + context.getTarget() + }, + new Factory<UsageSearcher>() { + @Override + public UsageSearcher create() { + return new UsageSearcher() { + @Override + public void generate(@NotNull final Processor<Usage> processor) { + context.getCommand().findUsages(processor); + } + }; + } + }, + processPresentation, + presentation, + new UsageViewManager.UsageViewStateListener() { + @Override + public void usageViewCreated(@NotNull UsageView usageView) { + context.setUsageView(usageView); + context.configureActions(); + } + + @Override + public void findingUsagesFinished(final UsageView usageView) { + } + } + ); + } + + protected String getDefaultTitle() { + return SSRBundle.message("structural.search.title"); + } + + protected JComponent createEditorContent() { + JPanel result = new JPanel(new BorderLayout()); + + result.add(BorderLayout.NORTH, new JLabel(SSRBundle.message("search.template"))); + searchCriteriaEdit = createEditor(searchContext, mySavedEditorText != null ? mySavedEditorText : ""); + result.add(BorderLayout.CENTER, searchCriteriaEdit.getComponent()); + result.setMinimumSize(new Dimension(150, 100)); + + return result; + } + + protected int getRowsCount() { + return 4; + } + + @Override + protected JComponent createCenterPanel() { + myContentPanel = new JPanel(new BorderLayout()); + myEditorPanel = createEditorContent(); + myContentPanel.add(BorderLayout.CENTER, myEditorPanel); + myContentPanel.add(BorderLayout.SOUTH, Box.createVerticalStrut(8)); + JComponent centerPanel = new JPanel(new BorderLayout()); + { + JPanel panel = new JPanel(new BorderLayout()); + panel.add(BorderLayout.CENTER, myContentPanel); + panel.add(BorderLayout.SOUTH, createTemplateManagementButtons()); + centerPanel.add(BorderLayout.CENTER, panel); + } + + JPanel optionsContent = new JPanel(new BorderLayout()); + centerPanel.add(BorderLayout.SOUTH, optionsContent); + + JPanel searchOptions = new JPanel(); + searchOptions.setLayout(new GridLayout(getRowsCount(), 1, 0, 0)); + searchOptions.setBorder(IdeBorderFactory.createTitledBorder(SSRBundle.message("ssdialog.options.group.border"), + true)); + + myScopeChooserCombo = new ScopeChooserCombo( + searchContext.getProject(), + true, + false, + FindSettings.getInstance().getDefaultScopeName() + ); + Disposer.register(myDisposable, myScopeChooserCombo); + JPanel allOptions = new JPanel(new BorderLayout()); + if (myShowScopePanel) { + JPanel scopePanel = new JPanel(new GridBagLayout()); + + TitledSeparator separator = new TitledSeparator(SSRBundle.message("search.dialog.scope.label"), myScopeChooserCombo.getComboBox()); + scopePanel.add(separator, new GridBagConstraints(0, 0, 1, 1, 1, 1, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, + new Insets(5, 0, 0, 0), 0, 0)); + + scopePanel.add(myScopeChooserCombo, new GridBagConstraints(0, 1, 1, 1, 1, 1, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, + new Insets(0, 10, 0, 0), 0, 0)); + + allOptions.add( + scopePanel, + BorderLayout.SOUTH + ); + + myScopeChooserCombo.getComboBox().addItemListener(new ItemListener() { + @Override + public void itemStateChanged(ItemEvent e) { + initiateValidation(); + } + }); + } + + buildOptions(searchOptions); + + allOptions.add(searchOptions, BorderLayout.CENTER); + optionsContent.add(allOptions, BorderLayout.CENTER); + + if (myRunFindActionOnClose) { + JPanel panel = new JPanel(new BorderLayout()); + panel.setBorder(BorderFactory.createEmptyBorder(0, 4, 0, 0)); + openInNewTab = new JCheckBox(FindBundle.message("find.open.in.new.tab.checkbox")); + openInNewTab.setSelected(ourOpenInNewTab); + ToolWindow findWindow = ToolWindowManager.getInstance(searchContext.getProject()).getToolWindow(ToolWindowId.FIND); + openInNewTab.setEnabled(findWindow != null && findWindow.isAvailable()); + panel.add(openInNewTab, BorderLayout.EAST); + + optionsContent.add(BorderLayout.SOUTH, panel); + } + + updateEditor(); + return centerPanel; + } + + + @Override + protected JComponent createSouthPanel() { + final JPanel statusPanel = new JPanel(new BorderLayout(5, 0)); + statusPanel.add(super.createSouthPanel(), BorderLayout.NORTH); + statusPanel.add(statusText = new JLabel(SSRBundle.message("status.message")), BorderLayout.WEST); + statusPanel.add(status = new JLabel(), BorderLayout.CENTER); + return statusPanel; + } + + private JPanel createTemplateManagementButtons() { + JPanel panel = new JPanel(null); + panel.setLayout(new BoxLayout(panel, BoxLayout.X_AXIS)); + panel.add(Box.createHorizontalGlue()); + + panel.add( + createJButtonForAction(new AbstractAction() { + { + putValue(NAME, SSRBundle.message("save.template.text.button")); + } + + @Override + public void actionPerformed(ActionEvent e) { + String name = showSaveTemplateAsDialog(); + + if (name != null) { + final Project project = searchContext.getProject(); + final ConfigurationManager configurationManager = StructuralSearchPlugin.getInstance(project).getConfigurationManager(); + final Collection<Configuration> configurations = configurationManager.getConfigurations(); + + if (configurations != null) { + name = ConfigurationManager.findAppropriateName(configurations, name, project); + if (name == null) return; + } + + model.getConfig().setName(name); + setValuesToConfig(model.getConfig()); + setDialogTitle(model.getConfig()); + + if (model.getShadowConfig() == null || + model.getShadowConfig().isPredefined()) { + existingTemplatesComponent.addConfigurationToUserTemplates(model.getConfig()); + } + else { // ??? + setValuesToConfig(model.getShadowConfig()); + model.getShadowConfig().setName(name); + } + } + } + }) + ); + + panel.add( + Box.createHorizontalStrut(8) + ); + + panel.add( + createJButtonForAction( + new AbstractAction() { + { + putValue(NAME, SSRBundle.message("edit.variables.button")); + } + + @Override + public void actionPerformed(ActionEvent e) { + EditVarConstraintsDialog.setProject(searchContext.getProject()); + new EditVarConstraintsDialog( + searchContext.getProject(), + model, getVariablesFromListeners(), + isReplaceDialog(), + (FileType)fileTypes.getSelectedItem() + ).show(); + initiateValidation(); + EditVarConstraintsDialog.setProject(null); + } + } + ) + ); + + panel.add( + Box.createHorizontalStrut(8) + ); + + panel.add( + createJButtonForAction( + new AbstractAction() { + { + putValue(NAME, SSRBundle.message("history.button")); + } + + @Override + public void actionPerformed(ActionEvent e) { + SelectTemplateDialog dialog = new SelectTemplateDialog(searchContext.getProject(), true, isReplaceDialog()); + dialog.show(); + + if (!dialog.isOK()) { + return; + } + Configuration[] configurations = dialog.getSelectedConfigurations(); + if (configurations.length == 1) { + setSearchPattern(configurations[0]); + } + } + } + ) + ); + + panel.add( + Box.createHorizontalStrut(8) + ); + + panel.add( + createJButtonForAction( + new AbstractAction() { + { + putValue(NAME, SSRBundle.message("copy.existing.template.button")); + } + + @Override + public void actionPerformed(ActionEvent e) { + SelectTemplateDialog dialog = new SelectTemplateDialog(searchContext.getProject(), false, isReplaceDialog()); + dialog.show(); + + if (!dialog.isOK()) { + return; + } + Configuration[] configurations = dialog.getSelectedConfigurations(); + if (configurations.length == 1) { + setSearchPattern(configurations[0]); + } + } + } + ) + ); + + return panel; + } + + protected List<Variable> getVariablesFromListeners() { + return getVarsFrom(searchCriteriaEdit); + } + + protected static ArrayList<Variable> getVarsFrom(Editor searchCriteriaEdit) { + SubstitutionShortInfoHandler handler = searchCriteriaEdit.getUserData(UIUtil.LISTENER_KEY); + return new ArrayList<Variable>(handler.getVariables()); + } + + public final Project getProject() { + return searchContext.getProject(); + } + + public String showSaveTemplateAsDialog() { + return ConfigurationManager.showSaveTemplateAsDialog( + model.getShadowConfig() != null ? model.getShadowConfig().getName() : SSRBundle.message("user.defined.category"), + searchContext.getProject() + ); + } + + protected boolean isReplaceDialog() { + return false; + } + + @Override + public void show() { + StructuralSearchPlugin.getInstance(getProject()).setDialogVisible(true); + Configuration.setActiveCreator(this); + searchCriteriaEdit.putUserData( + SubstitutionShortInfoHandler.CURRENT_CONFIGURATION_KEY, + model.getConfig() + ); + + if (!useLastConfiguration) { + final Editor editor = FileEditorManager.getInstance(searchContext.getProject()).getSelectedTextEditor(); + boolean setSomeText = false; + + if (editor != null) { + final SelectionModel selectionModel = editor.getSelectionModel(); + + if (selectionModel.hasSelection()) { + addOrReplaceSelection(selectionModel.getSelectedText()); + existingTemplatesComponent.getPatternTree().setSelectionPath(null); + existingTemplatesComponent.getHistoryList().setSelectedIndex(-1); + setSomeText = true; + } + } + + if (!setSomeText) { + int selection = existingTemplatesComponent.getHistoryList().getSelectedIndex(); + if (selection != -1) { + setValuesFromConfig( + (Configuration)existingTemplatesComponent.getHistoryList().getSelectedValue() + ); + } + } + } + + initiateValidation(); + + super.show(); + } + + @Override + public JComponent getPreferredFocusedComponent() { + return searchCriteriaEdit.getContentComponent(); + } + + // Performs ok action + @Override + protected void doOKAction() { + SearchScope selectedScope = getSelectedScope(); + if (selectedScope == null) return; + + myDoingOkAction = true; + boolean result = isValid(); + myDoingOkAction = false; + if (!result) return; + + myAlarm.cancelAllRequests(); + super.doOKAction(); + if (!myRunFindActionOnClose) return; + + FindSettings.getInstance().setDefaultScopeName(selectedScope.getDisplayName()); + ourOpenInNewTab = openInNewTab.isSelected(); + + try { + if (model.getShadowConfig() != null) { + if (model.getShadowConfig().isPredefined()) { + model.getConfig().setName( + model.getShadowConfig().getName() + ); + } //else { + // // user template, save it + // setValuesToConfig(model.getShadowConfig()); + //} + } + existingTemplatesComponent.addConfigurationToHistory(model.getConfig()); + + runAction(model.getConfig(), searchContext); + } + catch (MalformedPatternException ex) { + reportMessage("this.pattern.is.malformed.message", searchCriteriaEdit, ex.getMessage()); + } + } + + public Configuration getConfiguration() { + return model.getConfig(); + } + + private SearchScope getSelectedScope() { + return myScopeChooserCombo.getSelectedScope(); + } + + protected boolean isValid() { + setValuesToConfig(model.getConfig()); + boolean result = true; + + try { + MatcherImpl.validate(searchContext.getProject(), model.getConfig().getMatchOptions()); + } + catch (MalformedPatternException ex) { + if (myRunFindActionOnClose) { + reportMessage( + "this.pattern.is.malformed.message", + searchCriteriaEdit, + ex.getMessage() != null ? ex.getMessage() : "" + ); + result = false; + } + } + catch (UnsupportedPatternException ex) { + reportMessage("this.pattern.is.unsupported.message", searchCriteriaEdit, ex.getMessage()); + result = false; + } + + //getOKAction().setEnabled(result); + return result; + } + + protected void reportMessage(@NonNls String messageId, Editor editor, Object... params) { + final String message = messageId != null ? SSRBundle.message(messageId, params) : ""; + status.setText(message); + status.setToolTipText(message); + status.revalidate(); + statusText.setLabelFor(editor != null ? editor.getContentComponent() : null); + } + + protected void setValuesToConfig(Configuration config) { + + MatchOptions options = config.getMatchOptions(); + + boolean searchWithinHierarchy = IdeBundle.message("scope.class.hierarchy").equals(myScopeChooserCombo.getSelectedScopeName()); + // We need to reset search within hierarchy scope during online validation since the scope works with user participation + options.setScope( + searchWithinHierarchy && !myDoingOkAction ? GlobalSearchScope.projectScope(getProject()) : myScopeChooserCombo.getSelectedScope()); + options.setLooseMatching(true); + options.setRecursiveSearch(isRecursiveSearchEnabled() && recursiveMatching.isSelected()); + + ourFtSearchVariant = (FileType)fileTypes.getSelectedItem(); + ourDialect = (Language)dialects.getSelectedItem(); + ourContext = (String)contexts.getSelectedItem(); + FileType fileType = ourFtSearchVariant; + options.setFileType(fileType); + options.setDialect(ourDialect); + options.setPatternContext(ourContext); + + options.setSearchPattern(searchCriteriaEdit.getDocument().getText()); + options.setCaseSensitiveMatch(caseSensitiveMatch.isSelected()); + } + + @Override + protected String getDimensionServiceKey() { + return "#com.intellij.structuralsearch.plugin.ui.SearchDialog"; + } + + @Override + public void dispose() { + Configuration.setActiveCreator(null); + disposeEditorContent(); + + myAlarm.cancelAllRequests(); + + super.dispose(); + StructuralSearchPlugin.getInstance(getProject()).setDialogVisible(false); + } + + protected void disposeEditorContent() { + mySavedEditorText = searchCriteriaEdit.getDocument().getText(); + + // this will remove from myExcludedSet + final PsiFile file = PsiDocumentManager.getInstance(searchContext.getProject()).getPsiFile(searchCriteriaEdit.getDocument()); + if (file != null) { + DaemonCodeAnalyzer.getInstance(searchContext.getProject()).setHighlightingEnabled(file, true); + } + + EditorFactory.getInstance().releaseEditor(searchCriteriaEdit); + } + + @Override + protected String getHelpId() { + return "find.structuredSearch"; + } + + public SearchContext getSearchContext() { + return searchContext; + } +} |