xref: /haiku/src/apps/debugger/user_interface/gui/team_window/StackTraceView.cpp (revision 4a55cc230cf7566cadcbb23b1928eefff8aea9a2)
1 /*
2  * Copyright 2009-2012, Ingo Weinhold, ingo_weinhold@gmx.de.
3  * Copyright 2011-2013, Rene Gollent, rene@gollent.com.
4  * Distributed under the terms of the MIT License.
5  */
6 
7 
8 #include "StackTraceView.h"
9 
10 #include <stdio.h>
11 
12 #include <new>
13 
14 #include <ControlLook.h>
15 #include <Window.h>
16 
17 #include "table/TableColumns.h"
18 
19 #include "FunctionInstance.h"
20 #include "GuiSettingsUtils.h"
21 #include "Image.h"
22 #include "StackTrace.h"
23 #include "TargetAddressTableColumn.h"
24 #include "UiUtils.h"
25 
26 
27 // #pragma mark - FramesTableModel
28 
29 
30 class StackTraceView::FramesTableModel : public TableModel {
31 public:
32 	FramesTableModel()
33 		:
34 		fStackTrace(NULL)
35 	{
36 	}
37 
38 	~FramesTableModel()
39 	{
40 		SetStackTrace(NULL);
41 	}
42 
43 	void SetStackTrace(StackTrace* stackTrace)
44 	{
45 		// unset old frames
46 		if (fStackTrace != NULL && fStackTrace->CountFrames())
47 			NotifyRowsRemoved(0, fStackTrace->CountFrames());
48 
49 		fStackTrace = stackTrace;
50 
51 		// set new frames
52 		if (fStackTrace != NULL && fStackTrace->CountFrames() > 0)
53 			NotifyRowsAdded(0, fStackTrace->CountFrames());
54 	}
55 
56 	virtual int32 CountColumns() const
57 	{
58 		return 3;
59 	}
60 
61 	virtual int32 CountRows() const
62 	{
63 		return fStackTrace != NULL ? fStackTrace->CountFrames() : 0;
64 	}
65 
66 	virtual bool GetValueAt(int32 rowIndex, int32 columnIndex, BVariant& value)
67 	{
68 		StackFrame* frame
69 			= fStackTrace != NULL ? fStackTrace->FrameAt(rowIndex) : NULL;
70 		if (frame == NULL)
71 			return false;
72 
73 		switch (columnIndex) {
74 			case 0:
75 				value.SetTo(frame->FrameAddress());
76 				return true;
77 			case 1:
78 				value.SetTo(frame->InstructionPointer());
79 				return true;
80 			case 2:
81 			{
82 				char buffer[512];
83 				value.SetTo(UiUtils::FunctionNameForFrame(frame, buffer,
84 						sizeof(buffer)));
85 				return true;
86 			}
87 			default:
88 				return false;
89 		}
90 	}
91 
92 	StackFrame* FrameAt(int32 index) const
93 	{
94 		return fStackTrace != NULL ? fStackTrace->FrameAt(index) : NULL;
95 	}
96 
97 private:
98 	StackTrace*				fStackTrace;
99 };
100 
101 
102 // #pragma mark - StackTraceView
103 
104 
105 StackTraceView::StackTraceView(Listener* listener)
106 	:
107 	BGroupView(B_VERTICAL),
108 	fStackTrace(NULL),
109 	fFramesTable(NULL),
110 	fFramesTableModel(NULL),
111 	fTraceClearPending(false),
112 	fListener(listener)
113 {
114 	SetName("Stack Trace");
115 }
116 
117 
118 StackTraceView::~StackTraceView()
119 {
120 	SetStackTrace(NULL);
121 	fFramesTable->SetTableModel(NULL);
122 	delete fFramesTableModel;
123 }
124 
125 
126 /*static*/ StackTraceView*
127 StackTraceView::Create(Listener* listener)
128 {
129 	StackTraceView* self = new StackTraceView(listener);
130 
131 	try {
132 		self->_Init();
133 	} catch (...) {
134 		delete self;
135 		throw;
136 	}
137 
138 	return self;
139 }
140 
141 
142 void
143 StackTraceView::UnsetListener()
144 {
145 	fListener = NULL;
146 }
147 
148 
149 void
150 StackTraceView::SetStackTrace(StackTrace* stackTrace)
151 {
152 	fTraceClearPending = false;
153 	if (stackTrace == fStackTrace)
154 		return;
155 
156 	if (fStackTrace != NULL)
157 		fStackTrace->ReleaseReference();
158 
159 	fStackTrace = stackTrace;
160 
161 	if (fStackTrace != NULL)
162 		fStackTrace->AcquireReference();
163 
164 	fFramesTableModel->SetStackTrace(fStackTrace);
165 }
166 
167 
168 void
169 StackTraceView::SetStackFrame(StackFrame* stackFrame)
170 {
171 	if (fStackTrace != NULL && stackFrame != NULL) {
172 		for (int32 i = 0; StackFrame* other = fStackTrace->FrameAt(i); i++) {
173 			if (stackFrame == other) {
174 				fFramesTable->SelectRow(i, false);
175 				return;
176 			}
177 		}
178 	}
179 
180 	fFramesTable->DeselectAllRows();
181 }
182 
183 
184 void
185 StackTraceView::LoadSettings(const BMessage& settings)
186 {
187 	BMessage tableSettings;
188 	if (settings.FindMessage("framesTable", &tableSettings) == B_OK) {
189 		GuiSettingsUtils::UnarchiveTableSettings(tableSettings,
190 			fFramesTable);
191 	}
192 }
193 
194 
195 status_t
196 StackTraceView::SaveSettings(BMessage& settings)
197 {
198 	settings.MakeEmpty();
199 
200 	BMessage tableSettings;
201 	status_t result = GuiSettingsUtils::ArchiveTableSettings(tableSettings,
202 		fFramesTable);
203 	if (result == B_OK)
204 		result = settings.AddMessage("framesTable", &tableSettings);
205 
206 	return result;
207 }
208 
209 
210 void
211 StackTraceView::SetStackTraceClearPending()
212 {
213 	fTraceClearPending = true;
214 }
215 
216 
217 void
218 StackTraceView::TableSelectionChanged(Table* table)
219 {
220 	if (fListener == NULL || fTraceClearPending)
221 		return;
222 
223 	StackFrame* frame
224 		= fFramesTableModel->FrameAt(table->SelectionModel()->RowAt(0));
225 
226 	fListener->StackFrameSelectionChanged(frame);
227 }
228 
229 
230 void
231 StackTraceView::_Init()
232 {
233 	fFramesTable = new Table("stack trace", 0, B_FANCY_BORDER);
234 	fFramesTable->SetFont(B_FONT_ROW, be_fixed_font);
235 	AddChild(fFramesTable->ToView());
236 	fFramesTable->SetSortingEnabled(false);
237 
238 	float addressWidth = be_fixed_font->StringWidth("0xffffffff00000000")
239 		+ be_control_look->DefaultLabelSpacing();
240 
241 	// columns
242 	fFramesTable->AddColumn(new TargetAddressTableColumn(0, "Frame",
243 		addressWidth, 40, 1000, B_TRUNCATE_END, B_ALIGN_RIGHT));
244 	fFramesTable->AddColumn(new TargetAddressTableColumn(1, "IP", addressWidth,
245 		40, 1000, B_TRUNCATE_END, B_ALIGN_RIGHT));
246 	fFramesTable->AddColumn(new StringTableColumn(2, "Function", 300, 100, 1000,
247 		B_TRUNCATE_END, B_ALIGN_LEFT));
248 
249 	fFramesTableModel = new FramesTableModel();
250 	fFramesTable->SetTableModel(fFramesTableModel);
251 
252 	fFramesTable->SetSelectionMode(B_SINGLE_SELECTION_LIST);
253 	fFramesTable->AddTableListener(this);
254 }
255 
256 
257 // #pragma mark - Listener
258 
259 
260 StackTraceView::Listener::~Listener()
261 {
262 }
263