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
.slicer
;
18 import com
.intellij
.analysis
.AnalysisUIOptions
;
19 import com
.intellij
.ide
.impl
.ContentManagerWatcher
;
20 import com
.intellij
.openapi
.components
.PersistentStateComponent
;
21 import com
.intellij
.openapi
.components
.ServiceManager
;
22 import com
.intellij
.openapi
.components
.State
;
23 import com
.intellij
.openapi
.components
.Storage
;
24 import com
.intellij
.openapi
.progress
.ProcessCanceledException
;
25 import com
.intellij
.openapi
.progress
.ProgressIndicator
;
26 import com
.intellij
.openapi
.progress
.ProgressManager
;
27 import com
.intellij
.openapi
.progress
.impl
.ProgressManagerImpl
;
28 import com
.intellij
.openapi
.project
.Project
;
29 import com
.intellij
.openapi
.util
.text
.StringUtil
;
30 import com
.intellij
.openapi
.wm
.ToolWindow
;
31 import com
.intellij
.openapi
.wm
.ToolWindowAnchor
;
32 import com
.intellij
.openapi
.wm
.ToolWindowManager
;
33 import com
.intellij
.psi
.*;
34 import com
.intellij
.refactoring
.util
.RefactoringDescriptionLocation
;
35 import com
.intellij
.ui
.content
.Content
;
36 import com
.intellij
.ui
.content
.ContentManager
;
37 import org
.jetbrains
.annotations
.NotNull
;
39 import java
.util
.regex
.Pattern
;
42 name
= "SliceManager",
43 storages
= {@Storage(id
= "other", file
= "$WORKSPACE_FILE$")}
45 public class SliceManager
implements PersistentStateComponent
<SliceManager
.StoredSettingsBean
> {
46 private final Project myProject
;
47 private final ContentManager myBackContentManager
;
48 private final ContentManager myForthContentManager
;
49 private volatile boolean myCanceled
;
50 private final StoredSettingsBean myStoredSettings
= new StoredSettingsBean();
51 private static final String BACK_TOOLWINDOW_ID
= "Analyze Dataflow to";
52 private static final String FORTH_TOOLWINDOW_ID
= "Analyze Dataflow from";
54 public static class StoredSettingsBean
{
55 public boolean showDereferences
= true; // to show in dataflow/from dialog
56 public AnalysisUIOptions analysisUIOptions
= new AnalysisUIOptions();
59 public static SliceManager
getInstance(@NotNull Project project
) {
60 return ServiceManager
.getService(project
, SliceManager
.class);
63 public SliceManager(@NotNull Project project
, @NotNull ToolWindowManager toolWindowManager
, final PsiManager psiManager
) {
65 ToolWindow backToolWindow
= toolWindowManager
.registerToolWindow(BACK_TOOLWINDOW_ID
, true, ToolWindowAnchor
.BOTTOM
, project
);
66 myBackContentManager
= backToolWindow
.getContentManager();
67 new ContentManagerWatcher(backToolWindow
, myBackContentManager
);
69 ToolWindow forthToolWindow
= toolWindowManager
.registerToolWindow(FORTH_TOOLWINDOW_ID
, true, ToolWindowAnchor
.BOTTOM
, project
);
70 myForthContentManager
= forthToolWindow
.getContentManager();
71 new ContentManagerWatcher(forthToolWindow
, myForthContentManager
);
73 psiManager
.addPsiTreeChangeListener(new PsiTreeChangeAdapter() {
75 public void beforeChildAddition(PsiTreeChangeEvent event
) {
80 public void beforeChildRemoval(PsiTreeChangeEvent event
) {
85 public void beforeChildReplacement(PsiTreeChangeEvent event
) {
90 public void beforeChildMovement(PsiTreeChangeEvent event
) {
95 public void beforeChildrenChange(PsiTreeChangeEvent event
) {
100 public void beforePropertyChange(PsiTreeChangeEvent event
) {
106 private void cancel() {
110 public void slice(@NotNull PsiElement element
, boolean dataFlowToThis
, SliceHandler handler
) {
111 String dialogTitle
= getElementDescription((dataFlowToThis ? BACK_TOOLWINDOW_ID
: FORTH_TOOLWINDOW_ID
) + " ", element
, null);
113 dialogTitle
= Pattern
.compile("<[^<>]*>").matcher(dialogTitle
).replaceAll("");
114 SliceAnalysisParams params
= handler
.askForParams(element
, dataFlowToThis
, myStoredSettings
, dialogTitle
);
115 if (params
== null) return;
117 SliceRootNode rootNode
= new SliceRootNode(myProject
, new DuplicateMap(), createRootUsage(element
, params
));
119 createToolWindow(dataFlowToThis
, rootNode
, false, getElementDescription(null, element
, null));
122 public void createToolWindow(final boolean dataFlowToThis
, final SliceRootNode rootNode
, boolean splitByLeafExpressions
, String displayName
) {
123 final SliceToolwindowSettings sliceToolwindowSettings
= SliceToolwindowSettings
.getInstance(myProject
);
124 final ContentManager contentManager
= dataFlowToThis ? myBackContentManager
: myForthContentManager
;
125 final Content
[] myContent
= new Content
[1];
126 final SlicePanel slicePanel
= new SlicePanel(myProject
, dataFlowToThis
, rootNode
, splitByLeafExpressions
) {
127 protected void close() {
128 contentManager
.removeContent(myContent
[0], true);
131 public boolean isAutoScroll() {
132 return sliceToolwindowSettings
.isAutoScroll();
135 public void setAutoScroll(boolean autoScroll
) {
136 sliceToolwindowSettings
.setAutoScroll(autoScroll
);
139 public boolean isPreview() {
140 return sliceToolwindowSettings
.isPreview();
143 public void setPreview(boolean preview
) {
144 sliceToolwindowSettings
.setPreview(preview
);
148 myContent
[0] = contentManager
.getFactory().createContent(slicePanel
, displayName
, true);
149 contentManager
.addContent(myContent
[0]);
150 contentManager
.setSelectedContent(myContent
[0]);
152 ToolWindowManager
.getInstance(myProject
).getToolWindow(dataFlowToThis ? BACK_TOOLWINDOW_ID
: FORTH_TOOLWINDOW_ID
).activate(null);
155 public static String
getElementDescription(String prefix
, PsiElement element
, String suffix
) {
156 PsiElement elementToSlice
= element
;
157 if (element
instanceof PsiReferenceExpression
) elementToSlice
= ((PsiReferenceExpression
)element
).resolve();
158 if (elementToSlice
== null) elementToSlice
= element
;
159 String desc
= ElementDescriptionUtil
.getElementDescription(elementToSlice
, RefactoringDescriptionLocation
.WITHOUT_PARENT
);
160 return "<html>"+ (prefix
== null ?
"" : prefix
) + StringUtil
.first(desc
, 100, true)+(suffix
== null ?
"" : suffix
) + "</html>";
163 public static SliceUsage
createRootUsage(@NotNull PsiElement element
, @NotNull SliceAnalysisParams params
) {
164 return new SliceUsage(element
, params
);
167 public void checkCanceled() throws ProcessCanceledException
{
169 throw new ProcessCanceledException();
173 public void runInterruptibly(Runnable runnable
, Runnable onCancel
, ProgressIndicator progress
) throws ProcessCanceledException
{
176 progress
.checkCanceled();
177 ((ProgressManagerImpl
)ProgressManager
.getInstance()).executeProcessUnderProgress(runnable
, progress
);
179 catch (ProcessCanceledException e
) {
182 //reschedule for later
188 public StoredSettingsBean
getState() {
189 return myStoredSettings
;
192 public void loadState(StoredSettingsBean state
) {
193 myStoredSettings
.analysisUIOptions
.save(state
.analysisUIOptions
);