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.
17 package com
.intellij
.codeInsight
.generation
.surroundWith
;
19 import com
.intellij
.codeInsight
.CodeInsightActionHandler
;
20 import com
.intellij
.codeInsight
.CodeInsightBundle
;
21 import com
.intellij
.codeInsight
.template
.TemplateManager
;
22 import com
.intellij
.lang
.Language
;
23 import com
.intellij
.lang
.LanguageSurrounders
;
24 import com
.intellij
.lang
.surroundWith
.SurroundDescriptor
;
25 import com
.intellij
.lang
.surroundWith
.Surrounder
;
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
.extensions
.Extensions
;
31 import com
.intellij
.openapi
.fileEditor
.FileDocumentManager
;
32 import com
.intellij
.openapi
.project
.Project
;
33 import com
.intellij
.openapi
.util
.TextRange
;
34 import com
.intellij
.psi
.PsiDocumentManager
;
35 import com
.intellij
.psi
.PsiElement
;
36 import com
.intellij
.psi
.PsiFile
;
37 import com
.intellij
.util
.IncorrectOperationException
;
38 import org
.jetbrains
.annotations
.NotNull
;
40 import java
.util
.ArrayList
;
41 import java
.util
.List
;
43 public class SurroundWithHandler
implements CodeInsightActionHandler
{
44 private static final Logger LOG
= Logger
.getInstance("#com.intellij.codeInsight.generation.surroundWith.SurroundWithHandler");
45 private static final String CHOOSER_TITLE
= CodeInsightBundle
.message("surround.with.chooser.title");
47 public void invoke(@NotNull final Project project
, @NotNull final Editor editor
, @NotNull PsiFile file
){
48 invoke(project
, editor
, file
, null);
51 public boolean startInWriteAction() {
55 public static void invoke(final Project project
, final Editor editor
, PsiFile file
, Surrounder surrounder
){
56 if (!editor
.getSelectionModel().hasSelection()) {
57 editor
.getSelectionModel().selectLineAtCaret();
59 int startOffset
= editor
.getSelectionModel().getSelectionStart();
60 int endOffset
= editor
.getSelectionModel().getSelectionEnd();
62 PsiDocumentManager
.getInstance(project
).commitAllDocuments();
64 PsiElement element1
= file
.findElementAt(startOffset
);
65 PsiElement element2
= file
.findElementAt(endOffset
- 1);
67 if (element1
== null || element2
== null) return;
69 TextRange textRange
= new TextRange(startOffset
, endOffset
);
70 for(SurroundWithRangeAdjuster adjuster
: Extensions
.getExtensions(SurroundWithRangeAdjuster
.EP_NAME
)) {
71 textRange
= adjuster
.adjustSurroundWithRange(file
, textRange
);
72 if (textRange
== null) return;
74 startOffset
= textRange
.getStartOffset();
75 endOffset
= textRange
.getEndOffset();
76 element1
= file
.findElementAt(startOffset
);
78 final Language baseLanguage
= file
.getViewProvider().getBaseLanguage();
79 final Language l
= element1
.getParent().getLanguage();
80 List
<SurroundDescriptor
> surroundDescriptors
= new ArrayList
<SurroundDescriptor
>();
82 surroundDescriptors
.addAll(LanguageSurrounders
.INSTANCE
.allForLanguage(l
));
83 if (l
!= baseLanguage
) surroundDescriptors
.addAll(LanguageSurrounders
.INSTANCE
.allForLanguage(baseLanguage
));
85 for (SurroundDescriptor descriptor
: surroundDescriptors
) {
86 final PsiElement
[] elements
= descriptor
.getElementsToSurround(file
, startOffset
, endOffset
);
87 if (elements
.length
> 0) {
88 if (surrounder
== null) { //production
89 PopupActionChooser popupActionChooser
= new PopupActionChooser(CHOOSER_TITLE
);
90 popupActionChooser
.invoke(project
, editor
, file
, descriptor
.getSurrounders(), elements
);
91 if (popupActionChooser
.isHasEnabledSurrounders()) return;
94 doSurround(project
, editor
, surrounder
, elements
);
100 if (surrounder
== null) { //if only templates are available
101 PopupActionChooser popupActionChooser
= new PopupActionChooser(CHOOSER_TITLE
);
102 popupActionChooser
.invoke(project
, editor
, file
, new Surrounder
[0], new PsiElement
[0]);
106 static void doSurround(final Project project
, final Editor editor
, final Surrounder surrounder
, final PsiElement
[] elements
) {
107 final PsiFile file
= PsiDocumentManager
.getInstance(project
).getPsiFile(editor
.getDocument());
108 if (!FileDocumentManager
.getInstance().requestWriting(editor
.getDocument(), project
)){
113 PsiDocumentManager
.getInstance(project
).commitAllDocuments();
114 int col
= editor
.getCaretModel().getLogicalPosition().column
;
115 int line
= editor
.getCaretModel().getLogicalPosition().line
;
116 LogicalPosition pos
= new LogicalPosition(0, 0);
117 editor
.getCaretModel().moveToLogicalPosition(pos
);
118 TextRange range
= surrounder
.surroundElements(project
, editor
, elements
);
119 if (TemplateManager
.getInstance(project
).getActiveTemplate(editor
) == null) {
120 LogicalPosition pos1
= new LogicalPosition(line
, col
);
121 editor
.getCaretModel().moveToLogicalPosition(pos1
);
124 int offset
= range
.getStartOffset();
125 editor
.getCaretModel().moveToOffset(offset
);
126 editor
.getScrollingModel().scrollToCaret(ScrollType
.RELATIVE
);
127 editor
.getSelectionModel().setSelection(range
.getStartOffset(), range
.getEndOffset());
130 catch (IncorrectOperationException e
) {