| /* |
| * Copyright 2000-2013 JetBrains s.r.o. |
| * |
| * 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.plugins.javaFX.fxml.codeInsight.intentions; |
| |
| import com.intellij.codeInsight.FileModificationService; |
| import com.intellij.codeInsight.intention.PsiElementBaseIntentionAction; |
| import com.intellij.openapi.command.WriteCommandAction; |
| import com.intellij.openapi.diagnostic.Logger; |
| import com.intellij.openapi.editor.Editor; |
| import com.intellij.openapi.fileTypes.StdFileTypes; |
| import com.intellij.openapi.project.Project; |
| import com.intellij.openapi.roots.OrderEnumerator; |
| import com.intellij.openapi.ui.popup.JBPopupFactory; |
| import com.intellij.openapi.util.io.FileUtil; |
| import com.intellij.psi.PsiElement; |
| import com.intellij.psi.PsiFileFactory; |
| import com.intellij.psi.PsiParserFacade; |
| import com.intellij.psi.util.PsiTreeUtil; |
| import com.intellij.psi.xml.XmlDocument; |
| import com.intellij.psi.xml.XmlFile; |
| import com.intellij.psi.xml.XmlProcessingInstruction; |
| import com.intellij.psi.xml.XmlProlog; |
| import com.intellij.ui.components.JBList; |
| import com.intellij.util.IncorrectOperationException; |
| import com.intellij.util.containers.ContainerUtil; |
| import com.intellij.util.lang.UrlClassLoader; |
| import org.jetbrains.annotations.NotNull; |
| |
| import javax.script.ScriptEngine; |
| import javax.script.ScriptEngineFactory; |
| import javax.script.ScriptEngineManager; |
| import java.io.File; |
| import java.net.MalformedURLException; |
| import java.net.URL; |
| import java.util.*; |
| |
| /** |
| * User: anna |
| * Date: 4/8/13 |
| */ |
| public class JavaFxInjectPageLanguageIntention extends PsiElementBaseIntentionAction { |
| public static final Logger LOG = Logger.getInstance("#" + JavaFxInjectPageLanguageIntention.class.getName()); |
| |
| private static Set<String> getAvailableLanguages(Project project) { |
| final List<ScriptEngineFactory> engineFactories = new ScriptEngineManager(composeUserClassLoader(project)).getEngineFactories(); |
| |
| if (engineFactories != null) { |
| final Set<String> availableNames = new TreeSet<String>(); |
| for (ScriptEngineFactory factory : engineFactories) { |
| final String engineName = (String)factory.getParameter(ScriptEngine.NAME); |
| availableNames.add(engineName); |
| } |
| return availableNames; |
| } |
| |
| return null; |
| } |
| |
| private static UrlClassLoader composeUserClassLoader(Project project) { |
| final List<URL> urls = new ArrayList<URL>(); |
| final List<String> list = OrderEnumerator.orderEntries(project).recursively().runtimeOnly().getPathsList().getPathList(); |
| for (String path : list) { |
| try { |
| urls.add(new File(FileUtil.toSystemIndependentName(path)).toURI().toURL()); |
| } |
| catch (MalformedURLException e1) { |
| LOG.info(e1); |
| } |
| } |
| |
| return UrlClassLoader.build().urls(urls).get(); |
| } |
| |
| @Override |
| public void invoke(@NotNull final Project project, Editor editor, @NotNull PsiElement element) throws IncorrectOperationException { |
| if (!FileModificationService.getInstance().preparePsiElementsForWrite(element)) return; |
| final XmlFile containingFile = (XmlFile)element.getContainingFile(); |
| |
| final Set<String> availableLanguages = getAvailableLanguages(project); |
| if (availableLanguages.size() == 1) { |
| registerPageLanguage(project, containingFile, availableLanguages.iterator().next()); |
| } else { |
| final JBList list = new JBList(availableLanguages); |
| JBPopupFactory.getInstance().createListPopupBuilder(list) |
| .setItemChoosenCallback(new Runnable() { |
| @Override |
| public void run() { |
| registerPageLanguage(project, containingFile, (String)list.getSelectedValue()); |
| } |
| }).createPopup().showInBestPositionFor(editor); |
| } |
| } |
| |
| private void registerPageLanguage(final Project project, final XmlFile containingFile, final String languageName) { |
| new WriteCommandAction.Simple(project, getFamilyName()) { |
| @Override |
| protected void run() { |
| final PsiFileFactory factory = PsiFileFactory.getInstance(project); |
| final XmlFile dummyFile = (XmlFile)factory.createFileFromText("_Dummy_.fxml", StdFileTypes.XML, |
| "<?language " + languageName + "?>"); |
| final XmlDocument document = dummyFile.getDocument(); |
| if (document != null) { |
| final XmlProlog prolog = document.getProlog(); |
| final Collection<XmlProcessingInstruction> instructions = PsiTreeUtil.findChildrenOfType(prolog, XmlProcessingInstruction.class); |
| LOG.assertTrue(instructions.size() == 1); |
| final XmlDocument xmlDocument = containingFile.getDocument(); |
| if (xmlDocument != null) { |
| final XmlProlog xmlProlog = xmlDocument.getProlog(); |
| if (xmlProlog != null) { |
| final PsiElement element = xmlProlog.addBefore(instructions.iterator().next(), xmlProlog.getFirstChild()); |
| xmlProlog.addAfter(PsiParserFacade.SERVICE.getInstance(project).createWhiteSpaceFromText("\n\n"), element); |
| } |
| } |
| } |
| } |
| }.execute(); |
| } |
| |
| @Override |
| public boolean isAvailable(@NotNull Project project, Editor editor, @NotNull PsiElement element) { |
| if (ContainerUtil.isEmpty(getAvailableLanguages(project))) { |
| return false; |
| } |
| setText(getFamilyName()); |
| return element.isValid(); |
| } |
| |
| @NotNull |
| @Override |
| public String getFamilyName() { |
| return "Specify page language"; |
| } |
| |
| @Override |
| public boolean startInWriteAction() { |
| return false; |
| } |
| } |