clean up
[idea/community.git] / platform / lang-impl / src / com / intellij / codeInsight / template / CustomTemplateCallback.java
1 /*
2  * Copyright 2000-2010 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.codeInsight.template;
17
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;
31
32 import java.util.ArrayList;
33 import java.util.Collection;
34 import java.util.List;
35 import java.util.Map;
36
37 /**
38  * @author Eugene.Kudelevsky
39  */
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>();
48
49   private FileType myFileType;
50
51   private final LiveTemplateBuilder myBuilder = new LiveTemplateBuilder();
52   private int myOffset = 0;
53
54   public CustomTemplateCallback(Editor editor, PsiFile file) {
55     myEditor = editor;
56     myFile = file;
57     myProject = file.getProject();
58     myTemplateManager = TemplateManagerImpl.getInstance(myProject);
59     fixInitialState();
60   }
61
62   @Nullable
63   public PsiElement getContext() {
64     int offset = myStartOffset;
65     return myFile.findElementAt(offset > 0 ? offset - 1 : offset);
66   }
67
68   public void fixInitialState() {
69     myStartOffset = myEditor.getCaretModel().getOffset();
70   }
71
72   public void fixEndOffset() {
73     if (myEndOffsetMarker == null) {
74       myEndOffsetMarker = myBuilder.createMarker(myOffset);
75     }
76   }
77
78   public boolean isLiveTemplateApplicable(@NotNull String key) {
79     return findApplicableTemplate(key) != null;
80   }
81
82   @Nullable
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;
87   }
88
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);
94       }
95     }
96     return result;
97   }
98
99   /**
100    * @param key
101    * @param predefinedVarValues
102    * @param listener            @return returns if template invokation is finished
103    */
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);
111     }
112   }
113
114   public void startTemplate(@NotNull TemplateImpl template,
115                             Map<String, String> predefinedVarValues) {
116     int offset = myBuilder.insertTemplate(myOffset, template, predefinedVarValues);
117     moveToOffset(offset);
118   }
119
120   public void fixStartOfTemplate(@NotNull Object key) {
121     LiveTemplateBuilder.Marker marker = myBuilder.createMarker(myOffset);
122     myCheckpoints.put(key, marker);
123   }
124
125   public void gotoEndOfTemplate(@NotNull Object key) {
126     moveToOffset(getEndOfTemplate(key));
127   }
128
129   public int getEndOfTemplate(@NotNull Object key) {
130     LiveTemplateBuilder.Marker marker = myCheckpoints.get(key);
131     if (marker == null) {
132       throw new IllegalArgumentException();
133     }
134     return marker.getEndOffset();
135   }
136
137   public int getStartOfTemplate(@NotNull Object key) {
138     LiveTemplateBuilder.Marker marker = myCheckpoints.get(key);
139     if (marker == null) {
140       throw new IllegalArgumentException();
141     }
142     return marker.getStartOffset();
143   }
144
145   public void gotoEndOffset() {
146     if (myEndOffsetMarker != null) {
147       moveToOffset(myEndOffsetMarker.getStartOffset());
148     }
149   }
150
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());
156     }*/
157     gotoEndOffset();
158     if (myOffset < myBuilder.getText().length()) {
159       myBuilder.insertVariableSegment(myOffset, TemplateImpl.END);
160     }
161     TemplateImpl template = myBuilder.buildTemplate();
162     myTemplateManager.startTemplate(myEditor, template, false, myBuilder.getPredefinedValues(), null);
163   }
164
165   private static List<TemplateImpl> getMatchingTemplates(@NotNull String templateKey) {
166     TemplateSettings settings = TemplateSettings.getInstance();
167     return settings.collectMatchingCandidates(templateKey, settings.getDefaultShortcutChar(), false);
168   }
169
170   @NotNull
171   public Editor getEditor() {
172     return myEditor;
173   }
174
175   @NotNull
176   public FileType getFileType() {
177     if (myFileType == null) {
178       myFileType = myFile.getFileType();
179     }
180     return myFileType;
181   }
182
183   public int getOffset() {
184     return myOffset;
185   }
186
187   @NotNull
188   public PsiFile parseCurrentText(FileType fileType) {
189     return PsiFileFactory.getInstance(myProject)
190       .createFileFromText("dummy.xml", fileType, myBuilder.getText(), LocalTimeCounter.currentTime(), false);
191   }
192
193   public Project getProject() {
194     return myProject;
195   }
196
197   public void moveToOffset(int offset) {
198     myOffset = offset;
199   }
200
201   public void insertString(int offset, String text) {
202     myBuilder.insertText(offset, text);
203   }
204 }