2 * Copyright 2000-2010 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.
16 package com.intellij.codeInsight.template;
18 import com.intellij.codeInsight.template.impl.TemplateImpl;
19 import com.intellij.codeInsight.template.impl.TemplateManagerImpl;
20 import com.intellij.codeInsight.template.impl.TemplateSettings;
21 import com.intellij.openapi.editor.Editor;
22 import com.intellij.openapi.fileTypes.FileType;
23 import com.intellij.openapi.project.Project;
24 import com.intellij.psi.PsiElement;
25 import com.intellij.psi.PsiFile;
26 import com.intellij.psi.PsiFileFactory;
27 import com.intellij.util.LocalTimeCounter;
28 import com.intellij.util.containers.HashMap;
29 import org.jetbrains.annotations.NotNull;
30 import org.jetbrains.annotations.Nullable;
32 import java.util.ArrayList;
33 import java.util.Collection;
34 import java.util.List;
38 * @author Eugene.Kudelevsky
40 public class CustomTemplateCallback {
41 private final TemplateManager myTemplateManager;
42 private final Editor myEditor;
43 private final PsiFile myFile;
44 private int myStartOffset;
45 private final Project myProject;
46 private LiveTemplateBuilder.Marker myEndOffsetMarker;
47 private final Map<Object, LiveTemplateBuilder.Marker> myCheckpoints = new HashMap<Object, LiveTemplateBuilder.Marker>();
49 private FileType myFileType;
51 private final LiveTemplateBuilder myBuilder = new LiveTemplateBuilder();
52 private int myOffset = 0;
54 public CustomTemplateCallback(Editor editor, PsiFile file) {
57 myProject = file.getProject();
58 myTemplateManager = TemplateManagerImpl.getInstance(myProject);
63 public PsiElement getContext() {
64 int offset = myStartOffset;
65 return myFile.findElementAt(offset > 0 ? offset - 1 : offset);
68 public void fixInitialState() {
69 myStartOffset = myEditor.getCaretModel().getOffset();
72 public void fixEndOffset() {
73 if (myEndOffsetMarker == null) {
74 myEndOffsetMarker = myBuilder.createMarker(myOffset);
78 public boolean isLiveTemplateApplicable(@NotNull String key) {
79 return findApplicableTemplate(key) != null;
83 public TemplateImpl findApplicableTemplate(@NotNull String key) {
84 List<TemplateImpl> templates = getMatchingTemplates(key);
85 templates = filterApplicableCandidates(templates);
86 return templates.size() > 0 ? templates.get(0) : null;
89 private List<TemplateImpl> filterApplicableCandidates(Collection<TemplateImpl> candidates) {
90 List<TemplateImpl> result = new ArrayList<TemplateImpl>();
91 for (TemplateImpl candidate : candidates) {
92 if (TemplateManagerImpl.isApplicable(myFile, myStartOffset, candidate)) {
93 result.add(candidate);
101 * @param predefinedVarValues
102 * @param listener @return returns if template invokation is finished
104 public void startTemplate(@NotNull String key,
105 Map<String, String> predefinedVarValues) {
106 List<TemplateImpl> templates = getMatchingTemplates(key);
107 templates = filterApplicableCandidates(templates);
108 if (templates.size() > 0) {
109 TemplateImpl template = templates.get(0);
110 startTemplate(template, predefinedVarValues);
114 public void startTemplate(@NotNull TemplateImpl template,
115 Map<String, String> predefinedVarValues) {
116 int offset = myBuilder.insertTemplate(myOffset, template, predefinedVarValues);
117 moveToOffset(offset);
120 public void fixStartOfTemplate(@NotNull Object key) {
121 LiveTemplateBuilder.Marker marker = myBuilder.createMarker(myOffset);
122 myCheckpoints.put(key, marker);
125 public void gotoEndOfTemplate(@NotNull Object key) {
126 moveToOffset(getEndOfTemplate(key));
129 public int getEndOfTemplate(@NotNull Object key) {
130 LiveTemplateBuilder.Marker marker = myCheckpoints.get(key);
131 if (marker == null) {
132 throw new IllegalArgumentException();
134 return marker.getEndOffset();
137 public int getStartOfTemplate(@NotNull Object key) {
138 LiveTemplateBuilder.Marker marker = myCheckpoints.get(key);
139 if (marker == null) {
140 throw new IllegalArgumentException();
142 return marker.getStartOffset();
145 public void gotoEndOffset() {
146 if (myEndOffsetMarker != null) {
147 moveToOffset(myEndOffsetMarker.getStartOffset());
151 public void finish() {
152 /*myEditor.getScrollingModel().scrollToCaret(ScrollType.MAKE_VISIBLE);
153 final CodeStyleManager style = CodeStyleManager.getInstance(myProject);
154 if (myGlobalMarker != null) {
155 style.reformatText(myFile, myGlobalMarker.getStartOffset(), myGlobalMarker.getEndOffset());
158 if (myOffset < myBuilder.getText().length()) {
159 myBuilder.insertVariableSegment(myOffset, TemplateImpl.END);
161 TemplateImpl template = myBuilder.buildTemplate();
162 myTemplateManager.startTemplate(myEditor, template, false, myBuilder.getPredefinedValues(), null);
165 private static List<TemplateImpl> getMatchingTemplates(@NotNull String templateKey) {
166 TemplateSettings settings = TemplateSettings.getInstance();
167 return settings.collectMatchingCandidates(templateKey, settings.getDefaultShortcutChar(), false);
171 public Editor getEditor() {
176 public FileType getFileType() {
177 if (myFileType == null) {
178 myFileType = myFile.getFileType();
183 public int getOffset() {
188 public PsiFile parseCurrentText(FileType fileType) {
189 return PsiFileFactory.getInstance(myProject)
190 .createFileFromText("dummy.xml", fileType, myBuilder.getText(), LocalTimeCounter.currentTime(), false);
193 public Project getProject() {
197 public void moveToOffset(int offset) {
201 public void insertString(int offset, String text) {
202 myBuilder.insertText(offset, text);