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:
@@ -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;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user