update copyright
[fedora-idea.git] / java / java-impl / src / com / intellij / codeInsight / generation / GenerateMembersHandlerBase.java
bloba9755aa83b2d1cafdeb2163b81148863b78238b4
1 /*
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.
16 package com.intellij.codeInsight.generation;
18 import com.intellij.codeInsight.CodeInsightActionHandler;
19 import com.intellij.codeInsight.template.Template;
20 import com.intellij.codeInsight.template.TemplateEditingAdapter;
21 import com.intellij.codeInsight.template.TemplateManager;
22 import com.intellij.ide.util.MemberChooser;
23 import com.intellij.openapi.application.ApplicationManager;
24 import com.intellij.openapi.application.Result;
25 import com.intellij.openapi.command.WriteCommandAction;
26 import com.intellij.openapi.diagnostic.Logger;
27 import com.intellij.openapi.editor.Editor;
28 import com.intellij.openapi.editor.LogicalPosition;
29 import com.intellij.openapi.editor.ScrollType;
30 import com.intellij.openapi.editor.Document;
31 import com.intellij.openapi.editor.actions.EnterAction;
32 import com.intellij.openapi.fileEditor.FileDocumentManager;
33 import com.intellij.openapi.project.Project;
34 import com.intellij.openapi.util.TextRange;
35 import com.intellij.openapi.util.text.StringUtil;
36 import com.intellij.psi.PsiClass;
37 import com.intellij.psi.PsiDocumentManager;
38 import com.intellij.psi.PsiElement;
39 import com.intellij.psi.PsiFile;
40 import com.intellij.util.IncorrectOperationException;
41 import org.jetbrains.annotations.NotNull;
42 import org.jetbrains.annotations.Nullable;
44 import java.util.ArrayList;
45 import java.util.Arrays;
46 import java.util.List;
48 /**
51 public abstract class GenerateMembersHandlerBase implements CodeInsightActionHandler {
52 private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.generation.GenerateMembersHandlerBase");
54 private final String myChooserTitle;
55 protected boolean myToCopyJavaDoc = false;
57 public GenerateMembersHandlerBase(String chooserTitle) {
58 myChooserTitle = chooserTitle;
61 public final void invoke(@NotNull final Project project, @NotNull final Editor editor, @NotNull PsiFile file) {
62 if (!FileDocumentManager.getInstance().requestWriting(editor.getDocument(), project)) {
63 return;
65 final PsiClass aClass = OverrideImplementUtil.getContextClass(project, editor, file, false);
66 if (aClass == null || aClass.isInterface()) return; //?
67 LOG.assertTrue(aClass.isValid());
68 LOG.assertTrue(aClass.getContainingFile() != null);
70 try {
71 final ClassMember[] members = chooseOriginalMembers(aClass, project);
72 if (members == null) return;
74 ApplicationManager.getApplication().runWriteAction(new Runnable() {
75 public void run() {
76 doGenerate(project, editor, aClass, members);
78 });
80 finally {
81 cleanup();
85 protected void cleanup() {
88 private void doGenerate(final Project project, final Editor editor, PsiClass aClass, ClassMember[] members) {
89 int offset = editor.getCaretModel().getOffset();
91 int col = editor.getCaretModel().getLogicalPosition().column;
92 int line = editor.getCaretModel().getLogicalPosition().line;
93 final Document document = editor.getDocument();
94 int lineStartOffset = document.getLineStartOffset(line);
95 CharSequence docText = document.getCharsSequence();
96 String textBeforeCaret = docText.subSequence(lineStartOffset, offset).toString();
97 final String afterCaret = docText.subSequence(offset, document.getLineEndOffset(line)).toString();
98 if (textBeforeCaret.trim().length() > 0 && StringUtil.isEmptyOrSpaces(afterCaret) && !editor.getSelectionModel().hasSelection()) {
99 EnterAction.insertNewLineAtCaret(editor);
100 PsiDocumentManager.getInstance(project).commitDocument(document);
101 offset = editor.getCaretModel().getOffset();
102 col = editor.getCaretModel().getLogicalPosition().column;
103 line = editor.getCaretModel().getLogicalPosition().line;
106 editor.getCaretModel().moveToLogicalPosition(new LogicalPosition(0, 0));
108 List<? extends GenerationInfo> newMembers;
109 try{
110 List<? extends GenerationInfo> prototypes = generateMemberPrototypes(aClass, members);
111 newMembers = GenerateMembersUtil.insertMembersAtOffset(aClass.getContainingFile(), offset, prototypes);
113 catch(IncorrectOperationException e){
114 LOG.error(e);
115 return;
117 if (newMembers.isEmpty()) return;
119 editor.getCaretModel().moveToLogicalPosition(new LogicalPosition(line, col));
121 final ArrayList<TemplateGenerationInfo> templates = new ArrayList<TemplateGenerationInfo>();
122 for (GenerationInfo member : newMembers) {
123 if (member instanceof TemplateGenerationInfo) {
124 templates.add((TemplateGenerationInfo) member);
128 if (!templates.isEmpty()){
129 PsiDocumentManager.getInstance(project).doPostponedOperationsAndUnblockDocument(document);
130 runTemplates(project, editor, templates, 0);
132 else if (!newMembers.isEmpty()){
133 GenerateMembersUtil.positionCaret(editor, newMembers.get(0).getPsiMember(), false);
137 private static void runTemplates(final Project myProject, final Editor editor, final List<TemplateGenerationInfo> templates, final int index) {
138 TemplateGenerationInfo info = templates.get(index);
139 final Template template = info.getTemplate();
141 final PsiElement element = info.getPsiMember();
142 final TextRange range = element.getTextRange();
143 editor.getDocument().deleteString(range.getStartOffset(), range.getEndOffset());
144 int offset = range.getStartOffset();
145 editor.getCaretModel().moveToOffset(offset);
146 editor.getScrollingModel().scrollToCaret(ScrollType.CENTER);
147 TemplateManager.getInstance(myProject).startTemplate(editor, template, new TemplateEditingAdapter() {
148 public void templateFinished(Template template) {
149 if (index + 1 < templates.size()){
150 ApplicationManager.getApplication().invokeLater(new Runnable() {
151 public void run() {
152 new WriteCommandAction(myProject) {
153 protected void run(Result result) throws Throwable {
154 runTemplates(myProject, editor, templates, index + 1);
156 }.execute();
165 @Nullable
166 protected ClassMember[] chooseOriginalMembers(PsiClass aClass, Project project) {
167 ClassMember[] allMembers = getAllOriginalMembers(aClass);
168 return chooseMembers(allMembers, false, false, project);
171 @Nullable
172 protected final ClassMember[] chooseMembers(ClassMember[] members, boolean allowEmptySelection, boolean copyJavadocCheckbox, Project project) {
173 MemberChooser<ClassMember> chooser = new MemberChooser<ClassMember>(members, allowEmptySelection, true, project);
174 chooser.setTitle(myChooserTitle);
175 chooser.setCopyJavadocVisible(copyJavadocCheckbox);
176 chooser.show();
177 myToCopyJavaDoc = chooser.isCopyJavadoc();
178 final List<ClassMember> list = chooser.getSelectedElements();
179 return list == null ? null : list.toArray(new ClassMember[list.size()]);
182 @NotNull
183 protected List<? extends GenerationInfo> generateMemberPrototypes(PsiClass aClass, ClassMember[] members) throws IncorrectOperationException {
184 ArrayList<GenerationInfo> array = new ArrayList<GenerationInfo>();
185 for (ClassMember member : members) {
186 GenerationInfo[] prototypes = generateMemberPrototypes(aClass, member);
187 if (prototypes != null) {
188 array.addAll(Arrays.asList(prototypes));
191 return array;
194 protected abstract ClassMember[] getAllOriginalMembers(PsiClass aClass);
196 protected abstract GenerationInfo[] generateMemberPrototypes(PsiClass aClass, ClassMember originalMember) throws IncorrectOperationException;
198 public boolean startInWriteAction() {
199 return false;