Debugger: Implement #10671.

- The stack trace view now remembers the last selected frame index for stopped
  threads when switching between them.
This commit is contained in:
Rene Gollent
2014-11-14 21:03:16 -05:00
parent 46593adfbc
commit 02c7127cb9
2 changed files with 141 additions and 7 deletions
@@ -1,6 +1,6 @@
/* /*
* Copyright 2009-2012, Ingo Weinhold, [email protected]. * Copyright 2009-2012, Ingo Weinhold, [email protected].
* Copyright 2011-2013, Rene Gollent, [email protected]. * Copyright 2011-2014, Rene Gollent, [email protected].
* Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
*/ */
@@ -14,6 +14,8 @@
#include <ControlLook.h> #include <ControlLook.h>
#include <Window.h> #include <Window.h>
#include <AutoDeleter.h>
#include "table/TableColumns.h" #include "table/TableColumns.h"
#include "FunctionInstance.h" #include "FunctionInstance.h"
@@ -99,6 +101,86 @@ private:
}; };
// #pragma mark - StackTraceKey
struct StackTraceView::StackTraceKey {
StackTrace* stackTrace;
StackTraceKey(StackTrace* stackTrace)
:
stackTrace(stackTrace)
{
}
uint32 HashValue() const
{
return (uint32)stackTrace;
}
bool operator==(const StackTraceKey& other) const
{
return stackTrace == other.stackTrace;
}
};
// #pragma mark - StackTraceSelectionEntry
struct StackTraceView::StackTraceSelectionEntry : StackTraceKey {
StackTraceSelectionEntry* next;
int32 selectedFrameIndex;
StackTraceSelectionEntry(StackTrace* stackTrace)
:
StackTraceKey(stackTrace),
selectedFrameIndex(0)
{
}
inline int32 SelectedFrameIndex() const
{
return selectedFrameIndex;
}
void SetSelectedFrameIndex(int32 index)
{
selectedFrameIndex = index;
}
};
// #pragma mark - StackTraceSelectionEntryHashDefinition
struct StackTraceView::StackTraceSelectionEntryHashDefinition {
typedef StackTraceKey KeyType;
typedef StackTraceSelectionEntry ValueType;
size_t HashKey(const StackTraceKey& key) const
{
return key.HashValue();
}
size_t Hash(const StackTraceSelectionEntry* value) const
{
return value->HashValue();
}
bool Compare(const StackTraceKey& key,
const StackTraceSelectionEntry* value) const
{
return key == *value;
}
StackTraceSelectionEntry*& GetLink(StackTraceSelectionEntry* value) const
{
return value->next;
}
};
// #pragma mark - StackTraceView // #pragma mark - StackTraceView
@@ -109,6 +191,7 @@ StackTraceView::StackTraceView(Listener* listener)
fFramesTable(NULL), fFramesTable(NULL),
fFramesTableModel(NULL), fFramesTableModel(NULL),
fTraceClearPending(false), fTraceClearPending(false),
fSelectionInfoTable(NULL),
fListener(listener) fListener(listener)
{ {
SetName("Stack Trace"); SetName("Stack Trace");
@@ -120,6 +203,7 @@ StackTraceView::~StackTraceView()
SetStackTrace(NULL); SetStackTrace(NULL);
fFramesTable->SetTableModel(NULL); fFramesTable->SetTableModel(NULL);
delete fFramesTableModel; delete fFramesTableModel;
delete fSelectionInfoTable;
} }
@@ -169,12 +253,25 @@ void
StackTraceView::SetStackFrame(StackFrame* stackFrame) StackTraceView::SetStackFrame(StackFrame* stackFrame)
{ {
if (fStackTrace != NULL && stackFrame != NULL) { if (fStackTrace != NULL && stackFrame != NULL) {
for (int32 i = 0; StackFrame* other = fStackTrace->FrameAt(i); i++) { int32 selectedIndex = -1;
if (stackFrame == other) { StackTraceSelectionEntry* entry = fSelectionInfoTable->Lookup(
fFramesTable->SelectRow(i, false); fStackTrace);
return; if (entry != NULL)
selectedIndex = entry->SelectedFrameIndex();
else {
for (int32 i = 0; StackFrame* other = fStackTrace->FrameAt(i);
i++) {
if (stackFrame == other) {
selectedIndex = i;
break;
}
} }
} }
if (selectedIndex >= 0) {
fFramesTable->SelectRow(selectedIndex, false);
return;
}
} }
fFramesTable->DeselectAllRows(); fFramesTable->DeselectAllRows();
@@ -211,6 +308,11 @@ void
StackTraceView::SetStackTraceClearPending() StackTraceView::SetStackTraceClearPending()
{ {
fTraceClearPending = true; fTraceClearPending = true;
StackTraceSelectionEntry* entry = fSelectionInfoTable->Lookup(fStackTrace);
if (entry != NULL) {
fSelectionInfoTable->Remove(entry);
delete entry;
}
} }
@@ -220,8 +322,23 @@ StackTraceView::TableSelectionChanged(Table* table)
if (fListener == NULL || fTraceClearPending) if (fListener == NULL || fTraceClearPending)
return; return;
StackFrame* frame int32 selectedIndex = table->SelectionModel()->RowAt(0);
= fFramesTableModel->FrameAt(table->SelectionModel()->RowAt(0)); StackFrame* frame = fFramesTableModel->FrameAt(selectedIndex);
StackTraceSelectionEntry* entry = fSelectionInfoTable->Lookup(fStackTrace);
if (entry == NULL) {
entry = new(std::nothrow) StackTraceSelectionEntry(fStackTrace);
if (entry == NULL)
return;
ObjectDeleter<StackTraceSelectionEntry> entryDeleter(entry);
if (fSelectionInfoTable->Insert(entry) != B_OK)
return;
entryDeleter.Detach();
}
entry->SetSelectedFrameIndex(selectedIndex);
fListener->StackFrameSelectionChanged(frame); fListener->StackFrameSelectionChanged(frame);
} }
@@ -230,6 +347,13 @@ StackTraceView::TableSelectionChanged(Table* table)
void void
StackTraceView::_Init() StackTraceView::_Init()
{ {
fSelectionInfoTable = new StackTraceSelectionInfoTable;
if (fSelectionInfoTable->Init() != B_OK) {
delete fSelectionInfoTable;
fSelectionInfoTable = NULL;
throw std::bad_alloc();
}
fFramesTable = new Table("stack trace", 0, B_FANCY_BORDER); fFramesTable = new Table("stack trace", 0, B_FANCY_BORDER);
AddChild(fFramesTable->ToView()); AddChild(fFramesTable->ToView());
fFramesTable->SetSortingEnabled(false); fFramesTable->SetSortingEnabled(false);
@@ -1,4 +1,5 @@
/* /*
* Copyright 2014, Rene Gollent, [email protected].
* Copyright 2009, Ingo Weinhold, [email protected]. * Copyright 2009, Ingo Weinhold, [email protected].
* Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
*/ */
@@ -7,6 +8,8 @@
#include <GroupView.h> #include <GroupView.h>
#include <util/OpenHashTable.h>
#include "table/Table.h" #include "table/Table.h"
#include "Team.h" #include "Team.h"
@@ -37,6 +40,12 @@ public:
private: private:
class FramesTableModel; class FramesTableModel;
struct StackTraceKey;
struct StackTraceSelectionEntry;
struct StackTraceSelectionEntryHashDefinition;
typedef BOpenHashTable<StackTraceSelectionEntryHashDefinition>
StackTraceSelectionInfoTable;
private: private:
// TableListener // TableListener
@@ -49,6 +58,7 @@ private:
Table* fFramesTable; Table* fFramesTable;
FramesTableModel* fFramesTableModel; FramesTableModel* fFramesTableModel;
bool fTraceClearPending; bool fTraceClearPending;
StackTraceSelectionInfoTable* fSelectionInfoTable;
Listener* fListener; Listener* fListener;
}; };