cleanup
[idea/community.git] / spellchecker / src / com / intellij / spellchecker / actions / SpellingPopupActionGroup.java
1 /*
2  * Copyright 2000-2009 JetBrains s.r.o.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package com.intellij.spellchecker.actions;
17
18 import com.intellij.codeInsight.daemon.impl.HighlightInfo;
19 import com.intellij.codeInsight.daemon.impl.ShowIntentionsPass;
20 import com.intellij.codeInsight.intention.IntentionAction;
21 import com.intellij.codeInspection.LocalQuickFix;
22 import com.intellij.codeInspection.ex.QuickFixWrapper;
23 import com.intellij.openapi.actionSystem.*;
24 import com.intellij.openapi.application.ApplicationManager;
25 import com.intellij.openapi.command.CommandProcessor;
26 import com.intellij.openapi.diagnostic.Logger;
27 import com.intellij.openapi.editor.Editor;
28 import com.intellij.openapi.project.Project;
29 import com.intellij.psi.PsiFile;
30 import com.intellij.spellchecker.quickfixes.SpellCheckerQuickFix;
31 import com.intellij.util.IncorrectOperationException;
32 import org.jetbrains.annotations.NotNull;
33 import org.jetbrains.annotations.Nullable;
34
35 import java.util.ArrayList;
36 import java.util.HashMap;
37 import java.util.List;
38 import java.util.Map;
39
40 /**
41  * Spelling action group.
42  */
43 public final class SpellingPopupActionGroup extends ActionGroup {
44   public SpellingPopupActionGroup() {
45   }
46
47   public SpellingPopupActionGroup(String shortName, boolean popup) {
48     super(shortName, popup);
49   }
50
51   @NotNull
52   public AnAction[] getChildren(@Nullable AnActionEvent e) {
53     if (e != null) {
54       AnAction[] children = findActions(e);
55       // No actions
56       if (children.length == 0) {
57         e.getPresentation().setEnabled(false);
58       }
59       return children;
60     }
61     return AnAction.EMPTY_ARRAY;
62   }
63
64   @NotNull
65   private static AnAction[] findActions(@NotNull AnActionEvent e) {
66     PsiFile psiFile = e.getData(CommonDataKeys.PSI_FILE);
67     Project project = e.getData(LangDataKeys.PROJECT);
68     Editor editor = e.getData(LangDataKeys.EDITOR);
69     if (psiFile != null && project != null && editor != null) {
70       List<HighlightInfo.IntentionActionDescriptor> quickFixes = ShowIntentionsPass.getAvailableFixes(editor, psiFile, -1);
71       Map<Anchor, List<AnAction>> children = new HashMap<>();
72       ArrayList<AnAction> first = new ArrayList<>();
73       children.put(Anchor.FIRST, first);
74       ArrayList<AnAction> last = new ArrayList<>();
75       children.put(Anchor.LAST, last);
76       extractActions(quickFixes, children);
77       if (first.size() > 0 && last.size() > 0) {
78         first.add(new Separator());
79       }
80       first.addAll(last);
81       if (first.size() > 0) {
82         return first.toArray(new AnAction[first.size()]);
83       }
84     }
85
86     return AnAction.EMPTY_ARRAY;
87   }
88
89   private static void extractActions(List<HighlightInfo.IntentionActionDescriptor> descriptors, Map<Anchor, List<AnAction>> actions) {
90     for (HighlightInfo.IntentionActionDescriptor actionDescriptor : descriptors) {
91       IntentionAction action = actionDescriptor.getAction();
92       if (action instanceof QuickFixWrapper) {
93         QuickFixWrapper wrapper = (QuickFixWrapper)action;
94         LocalQuickFix localQuickFix = wrapper.getFix();
95         if (localQuickFix instanceof SpellCheckerQuickFix) {
96           SpellCheckerQuickFix spellCheckerQuickFix = (SpellCheckerQuickFix)localQuickFix;
97           Anchor anchor = spellCheckerQuickFix.getPopupActionAnchor();
98           SpellCheckerIntentionAction popupAction = new SpellCheckerIntentionAction(action);
99           List<AnAction> list = actions.get(anchor);
100           if (list != null) {
101             list.add(popupAction);
102           }
103         }
104       }
105     }
106   }
107
108   public void update(AnActionEvent e) {
109     super.update(e);
110     if (e != null) {
111       if (e.getPresentation().isVisible() && findActions(e).length == 0) {
112         e.getPresentation().setVisible(false);
113       }
114     }
115   }
116
117   private static class SpellCheckerIntentionAction extends AnAction {
118     private static final Logger LOGGER = Logger.getInstance("#SpellCheckerAction");
119     private final IntentionAction intention;
120
121     public SpellCheckerIntentionAction(IntentionAction intention) {
122       super(intention.getText());
123       this.intention = intention;
124     }
125
126     public void actionPerformed(final AnActionEvent e) {
127       final PsiFile psiFile = e.getData(CommonDataKeys.PSI_FILE);
128       final Project project = e.getData(LangDataKeys.PROJECT);
129       final Editor editor = e.getData(LangDataKeys.EDITOR);
130       if (psiFile != null && project != null && editor != null) {
131         final Runnable runnable = () -> CommandProcessor.getInstance().executeCommand(project, () -> {
132           try {
133             intention.invoke(project, editor, psiFile);
134           }
135           catch (IncorrectOperationException ex) {
136             LOGGER.error(ex);
137           }
138         }, e.getPresentation().getText(), e.getActionManager().getId(this));
139         if (intention.startInWriteAction()) {
140           ApplicationManager.getApplication().runWriteAction(runnable);
141         }
142         else {
143           runnable.run();
144         }
145       }
146     }
147   }
148 }