IDEA-50121
[fedora-idea.git] / java / java-impl / src / com / intellij / slicer / SliceManager.java
blob1eea7a00c8fc85183b78edbd990ead9d883e8af1
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.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;
41 @State(
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) {
64 myProject = project;
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() {
74 @Override
75 public void beforeChildAddition(PsiTreeChangeEvent event) {
76 cancel();
79 @Override
80 public void beforeChildRemoval(PsiTreeChangeEvent event) {
81 cancel();
84 @Override
85 public void beforeChildReplacement(PsiTreeChangeEvent event) {
86 cancel();
89 @Override
90 public void beforeChildMovement(PsiTreeChangeEvent event) {
91 cancel();
94 @Override
95 public void beforeChildrenChange(PsiTreeChangeEvent event) {
96 cancel();
99 @Override
100 public void beforePropertyChange(PsiTreeChangeEvent event) {
101 cancel();
103 }, project);
106 private void cancel() {
107 myCanceled = true;
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 {
168 if (myCanceled) {
169 throw new ProcessCanceledException();
173 public void runInterruptibly(Runnable runnable, Runnable onCancel, ProgressIndicator progress) throws ProcessCanceledException {
174 myCanceled = false;
175 try {
176 progress.checkCanceled();
177 ((ProgressManagerImpl)ProgressManager.getInstance()).executeProcessUnderProgress(runnable, progress);
179 catch (ProcessCanceledException e) {
180 cancel();
181 progress.cancel();
182 //reschedule for later
183 onCancel.run();
184 throw e;
188 public StoredSettingsBean getState() {
189 return myStoredSettings;
192 public void loadState(StoredSettingsBean state) {
193 myStoredSettings.analysisUIOptions.save(state.analysisUIOptions);