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
.hint
;
18 import com
.intellij
.codeInsight
.CodeInsightActionHandler
;
19 import com
.intellij
.ide
.structureView
.StructureViewBuilder
;
20 import com
.intellij
.ide
.structureView
.StructureViewModel
;
21 import com
.intellij
.ide
.structureView
.TreeBasedStructureViewBuilder
;
22 import com
.intellij
.lang
.LanguageStructureViewBuilder
;
23 import com
.intellij
.openapi
.application
.ApplicationManager
;
24 import com
.intellij
.openapi
.editor
.Editor
;
25 import com
.intellij
.openapi
.editor
.LogicalPosition
;
26 import com
.intellij
.openapi
.project
.Project
;
27 import com
.intellij
.openapi
.util
.Key
;
28 import com
.intellij
.openapi
.util
.TextRange
;
29 import com
.intellij
.psi
.*;
30 import com
.intellij
.psi
.xml
.XmlFile
;
31 import com
.intellij
.psi
.xml
.XmlTag
;
32 import com
.intellij
.ui
.LightweightHint
;
33 import org
.jetbrains
.annotations
.NotNull
;
34 import org
.jetbrains
.annotations
.Nullable
;
37 import java
.lang
.ref
.WeakReference
;
39 public class ShowContainerInfoHandler
implements CodeInsightActionHandler
{
40 private static final Key
<WeakReference
<LightweightHint
>> MY_LAST_HINT_KEY
= Key
.create("MY_LAST_HINT_KEY");
41 private static final Key
<PsiElement
> CONTAINER_KEY
= Key
.create("CONTAINER_KEY");
43 public void invoke(@NotNull final Project project
, @NotNull final Editor editor
, @NotNull PsiFile file
) {
44 PsiDocumentManager
.getInstance(project
).commitAllDocuments();
46 PsiElement container
= null;
47 WeakReference
<LightweightHint
> ref
= editor
.getUserData(MY_LAST_HINT_KEY
);
49 LightweightHint hint
= ref
.get();
50 if (hint
!= null && hint
.isVisible()){
52 container
= hint
.getUserData(CONTAINER_KEY
);
53 if (!container
.isValid()){
59 if (container
== null){
60 int offset
= editor
.getCaretModel().getOffset();
61 container
= file
.findElementAt(offset
);
62 if (container
== null) return;
65 if (file
instanceof PsiJavaFile
|| file
instanceof XmlFile
) {
67 container
= findContainer(container
);
68 if (container
== null) return;
69 if (!isDeclarationVisible(container
, editor
)) break;
74 StructureViewBuilder builder
= LanguageStructureViewBuilder
.INSTANCE
.getStructureViewBuilder(file
);
75 if (builder
instanceof TreeBasedStructureViewBuilder
) {
76 StructureViewModel model
= ((TreeBasedStructureViewBuilder
) builder
).createStructureViewModel();
77 Object element
= model
.getCurrentEditorElement();
78 if (element
instanceof PsiElement
) {
79 container
= (PsiElement
) element
;
81 if (container
== null || container
instanceof PsiFile
) {
84 if (!isDeclarationVisible(container
, editor
)) {
88 container
= container
.getParent();
89 while(container
!= null && DeclarationRangeUtil
.getPossibleDeclarationAtRange(container
) == null) {
90 container
= container
.getParent();
91 if (container
instanceof PsiFile
) return;
96 if (container
== null) {
101 final TextRange range
= DeclarationRangeUtil
.getDeclarationRange(container
);
102 final PsiElement _container
= container
;
103 ApplicationManager
.getApplication().invokeLater(new Runnable() {
105 LightweightHint hint
= EditorFragmentComponent
.showEditorFragmentHint(editor
, range
, true);
106 hint
.putUserData(CONTAINER_KEY
, _container
);
107 editor
.putUserData(MY_LAST_HINT_KEY
, new WeakReference
<LightweightHint
>(hint
));
112 public boolean startInWriteAction() {
117 private static PsiElement
findContainer(PsiElement element
) {
118 PsiElement container
= element
.getParent();
120 if (container
instanceof PsiFile
) return null;
121 if (container
instanceof PsiMethod
|| container
instanceof PsiClass
|| container
instanceof PsiClassInitializer
) break;
122 if (container
instanceof XmlTag
) break;
123 container
= container
.getParent();
128 private static boolean isDeclarationVisible(PsiElement container
, Editor editor
) {
129 Rectangle viewRect
= editor
.getScrollingModel().getVisibleArea();
130 final TextRange range
= DeclarationRangeUtil
.getPossibleDeclarationAtRange(container
);
135 LogicalPosition pos
= editor
.offsetToLogicalPosition(range
.getStartOffset());
136 Point loc
= editor
.logicalPositionToXY(pos
);
137 return loc
.y
>= viewRect
.y
;