xdebug uses real Rerun action
[idea/community.git] / platform / xdebugger-impl / src / com / intellij / xdebugger / impl / ui / XDebugSessionTab.java
1 /*
2  * Copyright 2000-2014 JetBrains s.r.o.
3  *
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
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16 package com.intellij.xdebugger.impl.ui;
17
18 import com.intellij.debugger.ui.DebuggerContentInfo;
19 import com.intellij.execution.Executor;
20 import com.intellij.execution.configurations.RunProfile;
21 import com.intellij.execution.executors.DefaultDebugExecutor;
22 import com.intellij.execution.runners.ExecutionEnvironment;
23 import com.intellij.execution.runners.RunContentBuilder;
24 import com.intellij.execution.ui.ExecutionConsole;
25 import com.intellij.execution.ui.RunContentDescriptor;
26 import com.intellij.execution.ui.actions.CloseAction;
27 import com.intellij.execution.ui.layout.PlaceInGrid;
28 import com.intellij.execution.ui.layout.impl.ViewImpl;
29 import com.intellij.icons.AllIcons;
30 import com.intellij.ide.DataManager;
31 import com.intellij.ide.actions.ContextHelpAction;
32 import com.intellij.idea.ActionsBundle;
33 import com.intellij.openapi.actionSystem.*;
34 import com.intellij.openapi.application.ApplicationManager;
35 import com.intellij.openapi.util.Disposer;
36 import com.intellij.psi.search.GlobalSearchScope;
37 import com.intellij.ui.AppUIUtil;
38 import com.intellij.ui.content.Content;
39 import com.intellij.ui.content.ContentManagerAdapter;
40 import com.intellij.ui.content.ContentManagerEvent;
41 import com.intellij.ui.content.tabs.PinToolwindowTabAction;
42 import com.intellij.util.SystemProperties;
43 import com.intellij.xdebugger.XDebugSession;
44 import com.intellij.xdebugger.XDebuggerBundle;
45 import com.intellij.xdebugger.impl.XDebugSessionImpl;
46 import com.intellij.xdebugger.impl.actions.XDebuggerActions;
47 import com.intellij.xdebugger.impl.frame.*;
48 import com.intellij.xdebugger.impl.ui.tree.actions.SortValuesToggleAction;
49 import com.intellij.xdebugger.ui.XDebugTabLayouter;
50 import org.jetbrains.annotations.NonNls;
51 import org.jetbrains.annotations.NotNull;
52 import org.jetbrains.annotations.Nullable;
53
54 import javax.swing.*;
55 import java.util.ArrayList;
56 import java.util.List;
57
58 /**
59  * @author spleaner
60  */
61 public class XDebugSessionTab extends DebuggerSessionTabBase implements DataProvider {
62   private static final DataKey<XDebugSessionTab> TAB_KEY = DataKey.create("XDebugSessionTab");
63   public static final DataKey<XDebugSession> SESSION_KEY = DataKey.create("XDebugSessionTab.XDebugSession");
64
65   private XWatchesViewImpl myWatchesView;
66   private final List<XDebugView> myViews = new ArrayList<XDebugView>();
67
68   private XDebugSessionImpl session;
69
70   @NotNull
71   public static XDebugSessionTab create(@NotNull XDebugSessionImpl session,
72                                         @Nullable Icon icon,
73                                         @Nullable ExecutionEnvironment environment,
74                                         @Nullable RunContentDescriptor contentToReuse) {
75     if (contentToReuse != null && SystemProperties.getBooleanProperty("xdebugger.reuse.session.tab", false)) {
76       JComponent component = contentToReuse.getComponent();
77       if (component != null) {
78         XDebugSessionTab oldTab = TAB_KEY.getData(DataManager.getInstance().getDataContext(component));
79         if (oldTab != null) {
80           oldTab.setSession(session, environment, contentToReuse, icon);
81           oldTab.attachToSession();
82           return oldTab;
83         }
84       }
85     }
86     return new XDebugSessionTab(session, icon, environment, contentToReuse);
87   }
88
89   private XDebugSessionTab(@NotNull XDebugSessionImpl session,
90                           @Nullable Icon icon,
91                           @Nullable ExecutionEnvironment environment,
92                           @Nullable RunContentDescriptor contentToReuse) {
93     super(session.getProject(), "Debug", session.getSessionName(), GlobalSearchScope.allScope(session.getProject()));
94
95     setSession(session, environment, contentToReuse, icon);
96
97     myUi.addContent(createFramesContent(), 0, PlaceInGrid.left, false);
98     myUi.addContent(createVariablesContent(), 0, PlaceInGrid.center, false);
99     myUi.addContent(createWatchesContent(), 0, PlaceInGrid.right, false);
100
101     for (XDebugView view : myViews) {
102       Disposer.register(this, view);
103     }
104
105     attachToSession();
106
107     myUi.getContentManager().addDataProvider(this);
108
109     DefaultActionGroup focus = new DefaultActionGroup();
110     focus.add(ActionManager.getInstance().getAction(XDebuggerActions.FOCUS_ON_BREAKPOINT));
111     myUi.getOptions().setAdditionalFocusActions(focus);
112
113     myUi.addListener(new ContentManagerAdapter() {
114       @Override
115       public void selectionChanged(ContentManagerEvent event) {
116         Content content = event.getContent();
117         XDebugSessionImpl session = XDebugSessionTab.this.session;
118         if (session != null && content.isSelected() && DebuggerContentInfo.WATCHES_CONTENT.equals(ViewImpl.ID.get(content))) {
119           if (myWatchesView.rebuildNeeded()) {
120             myWatchesView.processSessionEvent(XDebugView.SessionEvent.SETTINGS_CHANGED, session);
121           }
122         }
123       }
124     }, this);
125
126     rebuildViews();
127   }
128
129   private void setSession(@NotNull XDebugSessionImpl session, @Nullable ExecutionEnvironment environment, @Nullable RunContentDescriptor contentToReuse, @Nullable Icon icon) {
130     if (environment != null) {
131       setEnvironment(environment);
132     }
133
134     this.session = session;
135     myConsole = session.getConsoleView();
136     myRunContentDescriptor = new RunContentDescriptor(myConsole, session.getDebugProcess().getProcessHandler(), myUi.getComponent(), session.getSessionName(), icon);
137     if (contentToReuse != null && contentToReuse.isReuseToolWindowActivation()) {
138       myRunContentDescriptor.setActivateToolWindowWhenAdded(contentToReuse.isActivateToolWindowWhenAdded());
139     }
140   }
141
142   @Nullable
143   @Override
144   public Object getData(@NonNls String dataId) {
145     if (XWatchesView.DATA_KEY.is(dataId)) {
146       return myWatchesView;
147     }
148     else if (TAB_KEY.is(dataId)) {
149       return this;
150     }
151     else if (LangDataKeys.RUN_PROFILE.is(dataId)) {
152       ExecutionEnvironment environment = getEnvironment();
153       return environment == null ? null : environment.getRunProfile();
154     }
155     else if (LangDataKeys.EXECUTION_ENVIRONMENT.is(dataId)) {
156       return getEnvironment();
157     }
158
159     if (session != null) {
160       if (SESSION_KEY.is(dataId)) {
161         return session;
162       }
163       else if (LangDataKeys.CONSOLE_VIEW.is(dataId)) {
164         return session.getConsoleView();
165       }
166       else if (XDebugSessionData.DATA_KEY.is(dataId)) {
167         return session.getSessionData();
168       }
169     }
170
171     return null;
172   }
173
174   private Content createVariablesContent() {
175     final XVariablesView variablesView = new XVariablesView(session);
176     myViews.add(variablesView);
177     Content result = myUi.createContent(DebuggerContentInfo.VARIABLES_CONTENT, variablesView.getPanel(),
178                                         XDebuggerBundle.message("debugger.session.tab.variables.title"),
179                                         AllIcons.Debugger.Value, null);
180     result.setCloseable(false);
181
182     ActionGroup group = getCustomizedActionGroup(XDebuggerActions.VARIABLES_TREE_TOOLBAR_GROUP);
183     result.setActions(group, ActionPlaces.DEBUGGER_TOOLBAR, variablesView.getTree());
184     return result;
185   }
186
187   private Content createWatchesContent() {
188     myWatchesView = new XWatchesViewImpl(session);
189     myViews.add(myWatchesView);
190     Content watchesContent = myUi.createContent(DebuggerContentInfo.WATCHES_CONTENT, myWatchesView.getMainPanel(),
191                                                 XDebuggerBundle.message("debugger.session.tab.watches.title"), AllIcons.Debugger.Watches, null);
192     watchesContent.setCloseable(false);
193     return watchesContent;
194   }
195
196   @NotNull
197   private Content createFramesContent() {
198     XFramesView framesView = new XFramesView(getProject());
199     myViews.add(framesView);
200     Content framesContent = myUi.createContent(DebuggerContentInfo.FRAME_CONTENT, framesView.getMainPanel(),
201                                                XDebuggerBundle.message("debugger.session.tab.frames.title"), AllIcons.Debugger.Frame, null);
202     framesContent.setCloseable(false);
203     return framesContent;
204   }
205
206   public ExecutionConsole getConsole() {
207     return myConsole;
208   }
209
210   public void rebuildViews() {
211     AppUIUtil.invokeLaterIfProjectAlive(getProject(), new Runnable() {
212       @Override
213       public void run() {
214         for (XDebugView view : myViews) {
215           if (session != null) {
216             view.processSessionEvent(XDebugView.SessionEvent.SETTINGS_CHANGED, session);
217           }
218         }
219       }
220     });
221   }
222
223   public XWatchesView getWatchesView() {
224     return myWatchesView;
225   }
226
227   private void attachToSession() {
228     for (XDebugView view : myViews) {
229       session.addSessionListener(new XDebugViewSessionListener(view, session), this);
230     }
231
232     XDebugTabLayouter layouter = session.getDebugProcess().createTabLayouter();
233     Content consoleContent = layouter.registerConsoleContent(myUi, myConsole);
234     attachNotificationTo(consoleContent);
235
236     layouter.registerAdditionalContent(myUi);
237     RunContentBuilder.addAdditionalConsoleEditorActions(myConsole, consoleContent);
238
239     if (ApplicationManager.getApplication().isUnitTestMode()) {
240       return;
241     }
242
243     DefaultActionGroup leftToolbar = new DefaultActionGroup();
244     final Executor debugExecutor = DefaultDebugExecutor.getDebugExecutorInstance();
245     ExecutionEnvironment environment = getEnvironment();
246     if (environment != null) {
247       List<AnAction> additionalRestartActions = session.getRestartActions();
248       if (!additionalRestartActions.isEmpty()) {
249         leftToolbar.addAll(additionalRestartActions);
250         leftToolbar.addSeparator();
251       }
252       leftToolbar.addAll(session.getExtraActions());
253     }
254     leftToolbar.addAll(getCustomizedActionGroup(XDebuggerActions.TOOL_WINDOW_LEFT_TOOLBAR_GROUP));
255
256     for (AnAction action : session.getExtraStopActions()) {
257       leftToolbar.add(action, new Constraints(Anchor.AFTER, IdeActions.ACTION_STOP_PROGRAM));
258     }
259
260     //group.addSeparator();
261     //addAction(group, DebuggerActions.EXPORT_THREADS);
262     leftToolbar.addSeparator();
263
264     leftToolbar.add(myUi.getOptions().getLayoutActions());
265     final AnAction[] commonSettings = myUi.getOptions().getSettingsActionsList();
266     final AnAction commonSettingsList = myUi.getOptions().getSettingsActions();
267
268     final DefaultActionGroup settings = new DefaultActionGroup("DebuggerSettings", commonSettings.length > 0) {
269       @Override
270       public void update(AnActionEvent e) {
271         e.getPresentation().setText(ActionsBundle.message("group.XDebugger.settings.text"));
272         e.getPresentation().setIcon(commonSettingsList.getTemplatePresentation().getIcon());
273       }
274
275       @Override
276       public boolean isDumbAware() {
277         return true;
278       }
279     };
280     for (AnAction each : commonSettings) {
281       settings.add(each);
282     }
283     if (commonSettings.length > 0) {
284       settings.addSeparator();
285     }
286     if (!session.getDebugProcess().isValuesCustomSorted()) {
287       settings.add(new ToggleSortValuesAction(commonSettings.length == 0));
288     }
289
290     leftToolbar.add(settings);
291
292     leftToolbar.addSeparator();
293
294     leftToolbar.add(PinToolwindowTabAction.getPinAction());
295     leftToolbar.add(new CloseAction(environment != null ? environment.getExecutor() : debugExecutor, myRunContentDescriptor, getProject()));
296     leftToolbar.add(new ContextHelpAction(debugExecutor.getHelpId()));
297
298     DefaultActionGroup topToolbar = new DefaultActionGroup();
299     topToolbar.addAll(getCustomizedActionGroup(XDebuggerActions.TOOL_WINDOW_TOP_TOOLBAR_GROUP));
300
301     session.getDebugProcess().registerAdditionalActions(leftToolbar, topToolbar);
302     myUi.getOptions().setLeftToolbar(leftToolbar, ActionPlaces.DEBUGGER_TOOLBAR);
303     myUi.getOptions().setTopToolbar(topToolbar, ActionPlaces.DEBUGGER_TOOLBAR);
304
305     if (environment != null) {
306       RunProfile runConfiguration = environment.getRunProfile();
307       registerFileMatcher(runConfiguration);
308       initLogConsoles(runConfiguration, myRunContentDescriptor.getProcessHandler(), myConsole);
309     }
310   }
311
312   public void detachFromSession() {
313     assert session != null;
314     session = null;
315   }
316
317   @Override
318   @Nullable
319   public RunContentDescriptor getRunContentDescriptor() {
320     return myRunContentDescriptor;
321   }
322
323   private static class ToggleSortValuesAction extends SortValuesToggleAction {
324     private final boolean myShowIcon;
325
326     private ToggleSortValuesAction(boolean showIcon) {
327       copyFrom(ActionManager.getInstance().getAction(XDebuggerActions.TOGGLE_SORT_VALUES));
328       myShowIcon = showIcon;
329     }
330
331     @Override
332     public void update(AnActionEvent e) {
333       super.update(e);
334       if (!myShowIcon) {
335         e.getPresentation().setIcon(null);
336       }
337     }
338   }
339 }