package fr.adrienbrault.idea.symfony2plugin.translation; import com.intellij.codeInsight.hint.HintManager; import com.intellij.codeInspection.IntentionAndQuickFixAction; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.command.CommandProcessor; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.popup.JBPopupFactory; import com.intellij.openapi.vfs.VfsUtil; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.PsiFile; import com.intellij.ui.components.JBList; import fr.adrienbrault.idea.symfony2plugin.translation.dict.TranslationUtil; import fr.adrienbrault.idea.symfony2plugin.translation.util.TranslationInsertUtil; import org.apache.commons.lang.StringUtils; import org.jetbrains.annotations.Nls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.yaml.psi.YAMLFile; import javax.swing.*; import java.awt.*; import java.util.ArrayList; import java.util.Collection; import java.util.List; /** * @author Daniel Espendiller <daniel@espendiller.net> */ public class TranslationKeyIntentionAndQuickFixAction extends IntentionAndQuickFixAction { @NotNull private final String key; @NotNull private final String domain; @NotNull private final DomainCollector domainCollector; public TranslationKeyIntentionAndQuickFixAction(@NotNull String key, @NotNull String domain) { this(key, domain, new AllDomainCollector()); } public TranslationKeyIntentionAndQuickFixAction(@NotNull String key, @NotNull String domain, @NotNull DomainCollector domainCollector) { this.key = key; this.domain = domain; this.domainCollector = domainCollector; } @NotNull @Override public String getName() { return "Symfony: add translations"; } @Nls @NotNull @Override public String getFamilyName() { return "Symfony"; } @NotNull private String getPresentableName(@NotNull Project project, @NotNull VirtualFile virtualFile) { // try to find suitable presentable filename String filename = virtualFile.getPath(); String relativePath = VfsUtil.getRelativePath(virtualFile, project.getBaseDir(), '/'); if(relativePath != null) { filename = relativePath; } return StringUtils.abbreviate(filename, 180); } @Override public void applyFix(@NotNull Project project, @NotNull PsiFile psiFile, @Nullable Editor editor) { if(editor == null) { return; } List<PsiFile> files = new ArrayList<>(); for(PsiFile translationPsiFile: this.domainCollector.collect(project, key, domain)) { if(translationPsiFile instanceof YAMLFile || TranslationUtil.isSupportedXlfFile(translationPsiFile)) { String relativePath = VfsUtil.getRelativePath(translationPsiFile.getVirtualFile(), project.getBaseDir(), '/'); // sort collection. eg vendor last if(relativePath != null && (relativePath.startsWith("app") || relativePath.startsWith("src"))) { files.add(0, translationPsiFile); } else { files.add(translationPsiFile); } } } if(files.size() == 0) { HintManager.getInstance().showErrorHint(editor, "Ops, no domain file found"); return; } JBList<PsiFile> list = new JBList<>(files); list.setCellRenderer(new JBList.StripedListCellRenderer() { @Override public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { Component renderer = super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); if (renderer instanceof JLabel && value instanceof PsiFile) { ((JLabel) renderer).setText(getPresentableName(project, ((PsiFile) value).getVirtualFile())); } return renderer; } }); JBPopupFactory.getInstance().createListPopupBuilder(list) .setTitle("Symfony: Translation files") .setItemChoosenCallback(() -> { PsiFile selectedFile = list.getSelectedValue(); CommandProcessor.getInstance().executeCommand(selectedFile.getProject(), () -> ApplicationManager.getApplication().runWriteAction(() -> { TranslationInsertUtil.invokeTranslation(selectedFile, key, domain); }), "Translation insert " + selectedFile.getName(), null); }) .createPopup() .showInBestPositionFor(editor); } public interface DomainCollector { @NotNull Collection<PsiFile> collect(@NotNull Project project, @NotNull String key, @NotNull String domain); } private static class AllDomainCollector implements DomainCollector { @Override @NotNull public Collection<PsiFile> collect(@NotNull Project project, @NotNull String key, @NotNull String domain) { return TranslationUtil.getDomainPsiFiles(project, domain); } } }