NPE: XFramesView$StackFramesListBuilder.<init>
[fedora-idea.git] / platform / xdebugger-impl / src / com / intellij / xdebugger / impl / frame / XFramesView.java
blob45ec724f544f9487797afccad684212799e079ed
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.xdebugger.impl.frame;
18 import com.intellij.openapi.Disposable;
19 import com.intellij.openapi.application.ApplicationManager;
20 import com.intellij.ui.ScrollPaneFactory;
21 import com.intellij.util.containers.HashMap;
22 import com.intellij.xdebugger.XDebugSession;
23 import com.intellij.xdebugger.frame.XExecutionStack;
24 import com.intellij.xdebugger.frame.XStackFrame;
25 import com.intellij.xdebugger.frame.XSuspendContext;
26 import org.jetbrains.annotations.NotNull;
28 import javax.swing.*;
29 import javax.swing.event.ListSelectionEvent;
30 import javax.swing.event.ListSelectionListener;
31 import java.awt.*;
32 import java.awt.event.ItemEvent;
33 import java.awt.event.ItemListener;
34 import java.awt.event.MouseAdapter;
35 import java.awt.event.MouseEvent;
36 import java.util.ArrayList;
37 import java.util.Collections;
38 import java.util.List;
39 import java.util.Map;
41 /**
42 * @author nik
44 public class XFramesView extends XDebugViewBase {
45 private final JPanel myMainPanel;
46 private final XDebuggerFramesList myFramesList;
47 private final JComboBox myThreadComboBox;
48 private XExecutionStack mySelectedStack;
49 private boolean myListenersEnabled;
50 private final Map<XExecutionStack, StackFramesListBuilder> myBuilders = new HashMap<XExecutionStack, StackFramesListBuilder>();
52 public XFramesView(final XDebugSession session, final Disposable parentDisposable) {
53 super(session, parentDisposable);
55 myMainPanel = new JPanel(new BorderLayout());
57 myThreadComboBox = new JComboBox();
58 myThreadComboBox.setRenderer(new ThreadComboBoxRenderer());
59 myThreadComboBox.addItemListener(new MyItemListener());
60 myMainPanel.add(myThreadComboBox, BorderLayout.NORTH);
62 myFramesList = new XDebuggerFramesList();
63 myFramesList.addListSelectionListener(new ListSelectionListener() {
64 public void valueChanged(final ListSelectionEvent e) {
65 if (e.getValueIsAdjusting()) return;
66 processFrameSelection();
68 });
69 myFramesList.addMouseListener(new MouseAdapter() {
70 @Override
71 public void mousePressed(final MouseEvent e) {
72 int i = myFramesList.locationToIndex(e.getPoint());
73 if (i != -1 && myFramesList.isSelectedIndex(i)) {
74 processFrameSelection();
77 });
78 myMainPanel.add(ScrollPaneFactory.createScrollPane(myFramesList), BorderLayout.CENTER);
79 rebuildView(SessionEvent.RESUMED);
82 private StackFramesListBuilder getOrCreateBuilder(XExecutionStack executionStack) {
83 StackFramesListBuilder builder = myBuilders.get(executionStack);
84 if (builder == null) {
85 builder = new StackFramesListBuilder(executionStack);
86 myBuilders.put(executionStack, builder);
88 return builder;
91 protected void rebuildView(final SessionEvent event) {
92 if (event == SessionEvent.BEFORE_RESUME) return;
93 if (event == SessionEvent.FRAME_CHANGED) {
94 XStackFrame currentStackFrame = mySession.getCurrentStackFrame();
95 if (currentStackFrame != null) {
96 myFramesList.setSelectedValue(currentStackFrame, true);
98 return;
101 myListenersEnabled = false;
102 for (StackFramesListBuilder builder : myBuilders.values()) {
103 builder.dispose();
105 myBuilders.clear();
106 XSuspendContext suspendContext = mySession.getSuspendContext();
107 if (suspendContext == null) {
108 myThreadComboBox.removeAllItems();
109 myFramesList.clear();
110 return;
113 XExecutionStack[] executionStacks = suspendContext.getExecutionStacks();
114 for (XExecutionStack executionStack : executionStacks) {
115 myThreadComboBox.addItem(executionStack);
117 XExecutionStack activeExecutionStack = suspendContext.getActiveExecutionStack();
118 myThreadComboBox.setSelectedItem(activeExecutionStack);
119 myThreadComboBox.setVisible(executionStacks.length != 1);
120 updateFrames(activeExecutionStack);
121 myListenersEnabled = true;
124 private void updateFrames(final XExecutionStack executionStack) {
125 if (mySelectedStack == executionStack) {
126 return;
128 if (mySelectedStack != null) {
129 getOrCreateBuilder(mySelectedStack).stop();
132 mySelectedStack = executionStack;
133 if (executionStack != null) {
134 StackFramesListBuilder builder = getOrCreateBuilder(executionStack);
135 builder.initModel(myFramesList.getModel());
136 builder.start();
137 XStackFrame topFrame = executionStack.getTopFrame();
138 if (topFrame != null) {
139 myFramesList.setSelectedValue(topFrame, true);
140 onFrameSelected(topFrame);
145 public XDebuggerFramesList getFramesList() {
146 return myFramesList;
149 private void onFrameSelected(final @NotNull XStackFrame stackFrame) {
150 mySession.setCurrentStackFrame(stackFrame);
153 public JPanel getMainPanel() {
154 return myMainPanel;
157 private void processFrameSelection() {
158 if (!myListenersEnabled) return;
159 Object selected = myFramesList.getSelectedValue();
160 if (selected instanceof XStackFrame) {
161 onFrameSelected((XStackFrame)selected);
165 private class MyItemListener implements ItemListener {
166 public void itemStateChanged(final ItemEvent e) {
167 if (!myListenersEnabled) return;
169 if (e.getStateChange() == ItemEvent.SELECTED) {
170 Object item = e.getItem();
171 if (item instanceof XExecutionStack) {
172 updateFrames((XExecutionStack)item);
178 private class StackFramesListBuilder implements XExecutionStack.XStackFrameContainer {
179 private XExecutionStack myExecutionStack;
180 private final List<XStackFrame> myStackFrames;
181 private String myErrorMessage;
182 private int myNextFrameIndex;
183 private boolean myRunning;
184 private boolean myAllFramesLoaded;
186 private StackFramesListBuilder(final XExecutionStack executionStack) {
187 myExecutionStack = executionStack;
188 myStackFrames = new ArrayList<XStackFrame>();
189 myStackFrames.add(executionStack.getTopFrame());
190 myNextFrameIndex = 1;
193 public void addStackFrames(@NotNull final List<? extends XStackFrame> stackFrames, final boolean last) {
194 ApplicationManager.getApplication().invokeLater(new Runnable() {
195 public void run() {
196 myStackFrames.addAll(stackFrames);
197 addFrameListElements(stackFrames, last);
198 myNextFrameIndex += stackFrames.size();
199 myAllFramesLoaded = last;
200 if (last) {
201 myRunning = false;
207 private void addFrameListElements(final List<?> values, final boolean last) {
208 if (myExecutionStack != null && myExecutionStack == mySelectedStack) {
209 DefaultListModel model = myFramesList.getModel();
210 if (model.getElementAt(model.getSize() - 1) == null) {
211 model.removeElementAt(model.getSize() - 1);
213 for (Object value : values) {
214 model.addElement(value);
216 if (!last) {
217 model.addElement(null);
219 myFramesList.repaint();
223 public boolean isObsolete() {
224 return !myRunning;
227 public void errorOccured(final String errorMessage) {
228 ApplicationManager.getApplication().invokeLater(new Runnable() {
229 public void run() {
230 myErrorMessage = errorMessage;
231 addFrameListElements(Collections.singletonList(errorMessage), true);
232 myRunning = false;
237 public void dispose() {
238 myRunning = false;
239 myExecutionStack = null;
242 public void start() {
243 if (myExecutionStack == null) {
244 return;
246 myRunning = true;
247 myExecutionStack.computeStackFrames(myNextFrameIndex, this);
250 public void stop() {
251 myRunning = false;
254 public void initModel(final DefaultListModel model) {
255 model.removeAllElements();
256 for (XStackFrame stackFrame : myStackFrames) {
257 model.addElement(stackFrame);
259 if (myErrorMessage != null) {
260 model.addElement(myErrorMessage);
262 else if (!myAllFramesLoaded) {
263 model.addElement(null);