2 * Copyright 2000-2009 JetBrains s.r.o.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
18 * Created by IntelliJ IDEA.
22 * To change template for new class use
23 * Code Style | Class Templates options (Tools | IDE Options).
25 package com.intellij.codeInsight.template.actions;
27 import com.intellij.codeInsight.CodeInsightBundle;
28 import com.intellij.codeInsight.template.TemplateContextType;
29 import com.intellij.codeInsight.template.impl.EditTemplateDialog;
30 import com.intellij.codeInsight.template.impl.TemplateImpl;
31 import com.intellij.codeInsight.template.impl.TemplateOptionalProcessor;
32 import com.intellij.codeInsight.template.impl.TemplateSettings;
33 import com.intellij.openapi.actionSystem.*;
34 import com.intellij.openapi.application.ApplicationManager;
35 import com.intellij.openapi.command.CommandProcessor;
36 import com.intellij.openapi.editor.Document;
37 import com.intellij.openapi.editor.Editor;
38 import com.intellij.openapi.editor.EditorFactory;
39 import com.intellij.openapi.editor.RangeMarker;
40 import com.intellij.openapi.extensions.Extensions;
41 import com.intellij.openapi.fileTypes.FileType;
42 import com.intellij.openapi.fileTypes.FileTypeManager;
43 import com.intellij.openapi.project.Project;
44 import com.intellij.openapi.util.TextRange;
45 import com.intellij.psi.*;
46 import com.intellij.psi.util.PsiElementFilter;
47 import com.intellij.psi.util.PsiTreeUtil;
48 import com.intellij.util.containers.HashMap;
53 public class SaveAsTemplateAction extends AnAction {
55 public void actionPerformed(AnActionEvent e) {
56 DataContext dataContext = e.getDataContext();
57 final Editor editor = PlatformDataKeys.EDITOR.getData(dataContext);
58 PsiFile file = LangDataKeys.PSI_FILE.getData(dataContext);
60 final Project project = file.getProject();
61 PsiDocumentManager.getInstance(project).commitAllDocuments();
63 final TextRange selection = new TextRange(editor.getSelectionModel().getSelectionStart(),
64 editor.getSelectionModel().getSelectionEnd());
65 PsiElement current = file.findElementAt(selection.getStartOffset());
66 int startOffset = selection.getStartOffset();
67 while (current instanceof PsiWhiteSpace) {
68 current = current.getNextSibling();
69 if (current == null) break;
70 startOffset = current.getTextRange().getStartOffset();
73 if (startOffset >= selection.getEndOffset()) startOffset = selection.getStartOffset();
75 final PsiElement[] psiElements = PsiTreeUtil.collectElements(file, new PsiElementFilter() {
76 public boolean isAccepted(PsiElement element) {
77 return selection.contains(element.getTextRange()) && element.getReferences().length > 0;
81 final Document document = EditorFactory.getInstance().createDocument(editor.getDocument().getText().
82 substring(startOffset,
83 selection.getEndOffset()));
84 final int offsetDelta = startOffset;
85 CommandProcessor.getInstance().executeCommand(project, new Runnable() {
87 ApplicationManager.getApplication().runWriteAction(new Runnable() {
89 Map<RangeMarker, String> rangeToText = new HashMap<RangeMarker, String>();
91 for (PsiElement element : psiElements) {
92 for (PsiReference reference : element.getReferences()) {
93 if (!(reference instanceof PsiQualifiedReference) || ((PsiQualifiedReference) reference).getQualifier() == null) {
94 String canonicalText = reference.getCanonicalText();
95 TextRange referenceRange = reference.getRangeInElement();
96 TextRange range = element.getTextRange().cutOut(referenceRange).shiftRight(-offsetDelta);
97 final String oldText = range.substring(document.getText());
98 if (!canonicalText.equals(oldText)) {
99 rangeToText.put(document.createRangeMarker(range), canonicalText);
105 for (Map.Entry<RangeMarker, String> entry : rangeToText.entrySet()) {
106 document.replaceString(entry.getKey().getStartOffset(), entry.getKey().getEndOffset(), entry.getValue());
113 TemplateSettings templateSettings = TemplateSettings.getInstance();
115 TemplateImpl template = new TemplateImpl("", document.getText(), TemplateSettings.USER_GROUP_NAME);
117 FileType fileType = FileTypeManager.getInstance().getFileTypeByFile(file.getVirtualFile());
118 for(TemplateContextType contextType: Extensions.getExtensions(TemplateContextType.EP_NAME)) {
119 template.getTemplateContext().setEnabled(contextType, contextType.isInContext(fileType));
122 if (editTemplate(template, editor.getComponent(), true)) return;
123 templateSettings.addTemplate(template);
126 public static boolean editTemplate(TemplateImpl template, JComponent component, final boolean newTemplate) {
128 TemplateSettings templateSettings = TemplateSettings.getInstance();
129 String defaultShortcut = "";
130 if (templateSettings.getDefaultShortcutChar() == TemplateSettings.ENTER_CHAR) {
131 defaultShortcut = CodeInsightBundle.message("template.shortcut.enter");
133 if (templateSettings.getDefaultShortcutChar() == TemplateSettings.TAB_CHAR) {
134 defaultShortcut = CodeInsightBundle.message("template.shortcut.tab");
136 if (templateSettings.getDefaultShortcutChar() == TemplateSettings.SPACE_CHAR) {
137 defaultShortcut = CodeInsightBundle.message("template.shortcut.space");
140 Map<TemplateOptionalProcessor, Boolean> options = template.createOptions();
141 Map<TemplateContextType, Boolean> context = template.createContext();
143 EditTemplateDialog dialog = new EditTemplateDialog(
145 CodeInsightBundle.message("dialog.edit.live.template.title"),
147 templateSettings.getTemplateGroups(),
148 defaultShortcut, options, context, newTemplate);
150 if (!dialog.isOK()) {
154 template.applyOptions(options);
155 template.applyContext(context);
156 templateSettings.setLastSelectedTemplateKey(template.getKey());
160 public void update(AnActionEvent e) {
161 DataContext dataContext = e.getDataContext();
162 Editor editor = PlatformDataKeys.EDITOR.getData(dataContext);
163 PsiFile file = LangDataKeys.PSI_FILE.getData(dataContext);
165 if (file == null || editor == null) {
166 e.getPresentation().setEnabled(false);
169 e.getPresentation().setEnabled(editor.getSelectionModel().hasSelection());