| /* |
| * Copyright 2001-2014 the original author or authors. |
| * |
| * 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.generate.tostring; |
| |
| import com.intellij.codeInsight.generation.PsiElementClassMember; |
| import com.intellij.codeInsight.hint.HintManager; |
| import com.intellij.ide.util.MemberChooser; |
| import com.intellij.ide.util.MemberChooserBuilder; |
| import com.intellij.openapi.Disposable; |
| import com.intellij.openapi.actionSystem.CommonDataKeys; |
| import com.intellij.openapi.actionSystem.DataContext; |
| import com.intellij.openapi.application.ApplicationManager; |
| import com.intellij.openapi.diagnostic.Logger; |
| import com.intellij.openapi.editor.Editor; |
| import com.intellij.openapi.editor.actionSystem.EditorWriteActionHandler; |
| import com.intellij.openapi.options.Configurable; |
| import com.intellij.openapi.options.ConfigurationException; |
| import com.intellij.openapi.options.ShowSettingsUtil; |
| import com.intellij.openapi.options.TabbedConfigurable; |
| 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.psi.*; |
| import com.intellij.psi.util.PsiTreeUtil; |
| import com.intellij.psi.util.PsiUtil; |
| import org.jetbrains.annotations.NotNull; |
| import org.jetbrains.annotations.Nullable; |
| import org.jetbrains.generate.tostring.config.Config; |
| import org.jetbrains.generate.tostring.template.TemplateResource; |
| import org.jetbrains.generate.tostring.template.TemplatesManager; |
| import org.jetbrains.generate.tostring.view.TemplatesPanel; |
| |
| import javax.swing.*; |
| import java.awt.*; |
| import java.awt.event.ActionEvent; |
| import java.awt.event.ActionListener; |
| import java.awt.event.KeyEvent; |
| import java.util.ArrayList; |
| import java.util.Collection; |
| import java.util.List; |
| |
| /** |
| * The action-handler that does the code generation. |
| */ |
| public class GenerateToStringActionHandlerImpl extends EditorWriteActionHandler implements GenerateToStringActionHandler { |
| private static final Logger logger = Logger.getInstance("#org.jetbrains.generate.tostring.GenerateToStringActionHandlerImpl"); |
| |
| public void executeWriteAction(Editor editor, DataContext dataContext) { |
| final Project project = CommonDataKeys.PROJECT.getData(dataContext); |
| assert project != null; |
| |
| PsiClass clazz = getSubjectClass(editor, dataContext); |
| assert clazz != null; |
| |
| doExecuteAction(project, clazz, editor); |
| } |
| |
| |
| public void executeActionQuickFix(final Project project, final PsiClass clazz) { |
| doExecuteAction(project, clazz, null); |
| } |
| |
| private static void doExecuteAction(@NotNull final Project project, @NotNull final PsiClass clazz, final Editor editor) { |
| logger.debug("+++ doExecuteAction - START +++"); |
| |
| if (logger.isDebugEnabled()) { |
| logger.debug("Current project " + project.getName()); |
| } |
| |
| final PsiElementClassMember[] dialogMembers = buildMembersToShow(clazz); |
| |
| final MemberChooserBuilder<PsiElementClassMember> builder = new MemberChooserBuilder<PsiElementClassMember>(project); |
| final MemberChooserHeaderPanel header = new MemberChooserHeaderPanel(clazz); |
| builder.setHeaderPanel(header); |
| builder.allowEmptySelection(true); |
| builder.overrideAnnotationVisible(PsiUtil.isLanguageLevel5OrHigher(clazz)); |
| builder.setTitle("Generate toString()"); |
| |
| logger.debug("Displaying member chooser dialog"); |
| ApplicationManager.getApplication().invokeLater(new Runnable() { |
| public void run() { |
| if (project.isDisposed()) return; |
| final MemberChooser<PsiElementClassMember> dialog = builder.createBuilder(dialogMembers); |
| dialog.setCopyJavadocVisible(false); |
| dialog.selectElements(dialogMembers); |
| header.setChooser(dialog); |
| dialog.show(); |
| |
| if (DialogWrapper.OK_EXIT_CODE == dialog.getExitCode()) { |
| Collection<PsiMember> selectedMembers = GenerateToStringUtils.convertClassMembersToPsiMembers(dialog.getSelectedElements()); |
| |
| final TemplateResource template = header.getSelectedTemplate(); |
| TemplatesManager.getInstance().setDefaultTemplate(template); |
| |
| if (template.isValidTemplate()) { |
| GenerateToStringWorker.executeGenerateActionLater(clazz, editor, selectedMembers, template, |
| dialog.isInsertOverrideAnnotation()); |
| } |
| else { |
| HintManager.getInstance().showErrorHint(editor, "toString() template '" + template.getFileName() + "' is invalid"); |
| } |
| } |
| } |
| }); |
| |
| logger.debug("+++ doExecuteAction - END +++"); |
| } |
| |
| public static void updateDialog(PsiClass clazz, MemberChooser<PsiElementClassMember> dialog) { |
| final PsiElementClassMember[] members = buildMembersToShow(clazz); |
| dialog.resetElements(members); |
| dialog.selectElements(members); |
| } |
| |
| private static PsiElementClassMember[] buildMembersToShow(PsiClass clazz) { |
| Config config = GenerateToStringContext.getConfig(); |
| PsiField[] filteredFields = GenerateToStringUtils.filterAvailableFields(clazz, config.getFilterPattern()); |
| if (logger.isDebugEnabled()) logger.debug("Number of fields after filtering: " + filteredFields.length); |
| PsiMethod[] filteredMethods; |
| if (config.enableMethods) { |
| // filter methods as it is enabled from config |
| filteredMethods = GenerateToStringUtils.filterAvailableMethods(clazz, config.getFilterPattern()); |
| if (logger.isDebugEnabled()) logger.debug("Number of methods after filtering: " + filteredMethods.length); |
| } else { |
| filteredMethods = PsiMethod.EMPTY_ARRAY; |
| } |
| |
| return GenerateToStringUtils.combineToClassMemberList(filteredFields, filteredMethods); |
| } |
| |
| @Override |
| public boolean isEnabled(Editor editor, DataContext dataContext) { |
| return getSubjectClass(editor, dataContext) != null; |
| } |
| |
| @Nullable |
| private static PsiClass getSubjectClass(Editor editor, DataContext dataContext) { |
| PsiFile file = CommonDataKeys.PSI_FILE.getData(dataContext); |
| if (file == null) return null; |
| |
| int offset = editor.getCaretModel().getOffset(); |
| PsiElement context = file.findElementAt(offset); |
| |
| if (context == null) return null; |
| |
| PsiClass clazz = PsiTreeUtil.getParentOfType(context, PsiClass.class, false); |
| if (clazz == null) { |
| return null; |
| } |
| |
| // must not be an interface |
| return clazz.isInterface() ? null : clazz; |
| } |
| |
| public static class MemberChooserHeaderPanel extends JPanel { |
| private MemberChooser<PsiElementClassMember> chooser; |
| private final JComboBox comboBox; |
| |
| public void setChooser(MemberChooser chooser) { |
| this.chooser = chooser; |
| } |
| |
| public MemberChooserHeaderPanel(final PsiClass clazz) { |
| super(new GridBagLayout()); |
| |
| final Collection<TemplateResource> templates = TemplatesManager.getInstance().getAllTemplates(); |
| final TemplateResource[] all = templates.toArray(new TemplateResource[templates.size()]); |
| |
| final JButton settingsButton = new JButton("Settings"); |
| settingsButton.setMnemonic(KeyEvent.VK_S); |
| |
| comboBox = new ComboBox(all); |
| settingsButton.addActionListener(new ActionListener() { |
| public void actionPerformed(ActionEvent e) { |
| final TemplatesPanel ui = new TemplatesPanel(); |
| Disposable disposable = Disposer.newDisposable(); |
| Configurable composite = new TabbedConfigurable(disposable) { |
| protected List<Configurable> createConfigurables() { |
| List<Configurable> res = new ArrayList<Configurable>(); |
| res.add(new GenerateToStringConfigurable(clazz.getProject())); |
| res.add(ui); |
| return res; |
| } |
| |
| public String getDisplayName() { |
| return "toString() Generation Settings"; |
| } |
| |
| public String getHelpTopic() { |
| return null; // TODO: |
| } |
| |
| @Override |
| public void apply() throws ConfigurationException { |
| super.apply(); |
| updateDialog(clazz, chooser); |
| |
| comboBox.removeAllItems(); |
| for (TemplateResource resource : TemplatesManager.getInstance().getAllTemplates()) { |
| comboBox.addItem(resource); |
| } |
| comboBox.setSelectedItem(TemplatesManager.getInstance().getDefaultTemplate()); |
| } |
| }; |
| |
| ShowSettingsUtil.getInstance().editConfigurable(MemberChooserHeaderPanel.this, composite, new Runnable() { |
| public void run() { |
| ui.selectItem(TemplatesManager.getInstance().getDefaultTemplate()); |
| } |
| }); |
| Disposer.dispose(disposable); |
| } |
| }); |
| |
| comboBox.setSelectedItem(TemplatesManager.getInstance().getDefaultTemplate()); |
| |
| final JLabel templatesLabel = new JLabel("Template: "); |
| templatesLabel.setDisplayedMnemonic('T'); |
| templatesLabel.setLabelFor(comboBox); |
| |
| final GridBagConstraints constraints = new GridBagConstraints(); |
| constraints.anchor = GridBagConstraints.BASELINE; |
| constraints.gridx = 0; |
| add(templatesLabel, constraints); |
| constraints.gridx = 1; |
| constraints.weightx = 1.0; |
| constraints.fill = GridBagConstraints.HORIZONTAL; |
| add(comboBox, constraints); |
| constraints.gridx = 2; |
| constraints.weightx = 0.0; |
| add(settingsButton, constraints); |
| } |
| |
| public TemplateResource getSelectedTemplate() { |
| return (TemplateResource) comboBox.getSelectedItem(); |
| } |
| } |
| } |