diff --git a/src/apps/debugger/user_interface/gui/team_window/StackTraceView.cpp b/src/apps/debugger/user_interface/gui/team_window/StackTraceView.cpp index bbce26ed50..7bb21dea01 100644 --- a/src/apps/debugger/user_interface/gui/team_window/StackTraceView.cpp +++ b/src/apps/debugger/user_interface/gui/team_window/StackTraceView.cpp @@ -1,6 +1,6 @@ /* * Copyright 2009-2012, Ingo Weinhold, ingo_weinhold@gmx.de. - * Copyright 2011-2013, Rene Gollent, rene@gollent.com. + * Copyright 2011-2014, Rene Gollent, rene@gollent.com. * Distributed under the terms of the MIT License. */ @@ -14,6 +14,8 @@ #include #include +#include + #include "table/TableColumns.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 @@ -109,6 +191,7 @@ StackTraceView::StackTraceView(Listener* listener) fFramesTable(NULL), fFramesTableModel(NULL), fTraceClearPending(false), + fSelectionInfoTable(NULL), fListener(listener) { SetName("Stack Trace"); @@ -120,6 +203,7 @@ StackTraceView::~StackTraceView() SetStackTrace(NULL); fFramesTable->SetTableModel(NULL); delete fFramesTableModel; + delete fSelectionInfoTable; } @@ -169,12 +253,25 @@ void StackTraceView::SetStackFrame(StackFrame* stackFrame) { if (fStackTrace != NULL && stackFrame != NULL) { - for (int32 i = 0; StackFrame* other = fStackTrace->FrameAt(i); i++) { - if (stackFrame == other) { - fFramesTable->SelectRow(i, false); - return; + int32 selectedIndex = -1; + StackTraceSelectionEntry* entry = fSelectionInfoTable->Lookup( + fStackTrace); + 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(); @@ -211,6 +308,11 @@ void StackTraceView::SetStackTraceClearPending() { 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) return; - StackFrame* frame - = fFramesTableModel->FrameAt(table->SelectionModel()->RowAt(0)); + int32 selectedIndex = 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 entryDeleter(entry); + if (fSelectionInfoTable->Insert(entry) != B_OK) + return; + + entryDeleter.Detach(); + } + + entry->SetSelectedFrameIndex(selectedIndex); fListener->StackFrameSelectionChanged(frame); } @@ -230,6 +347,13 @@ StackTraceView::TableSelectionChanged(Table* table) void 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); AddChild(fFramesTable->ToView()); fFramesTable->SetSortingEnabled(false); diff --git a/src/apps/debugger/user_interface/gui/team_window/StackTraceView.h b/src/apps/debugger/user_interface/gui/team_window/StackTraceView.h index 01cbdde833..e0199f7a42 100644 --- a/src/apps/debugger/user_interface/gui/team_window/StackTraceView.h +++ b/src/apps/debugger/user_interface/gui/team_window/StackTraceView.h @@ -1,4 +1,5 @@ /* + * Copyright 2014, Rene Gollent, rene@gollent.com. * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. * Distributed under the terms of the MIT License. */ @@ -7,6 +8,8 @@ #include +#include + #include "table/Table.h" #include "Team.h" @@ -37,6 +40,12 @@ public: private: class FramesTableModel; + struct StackTraceKey; + struct StackTraceSelectionEntry; + struct StackTraceSelectionEntryHashDefinition; + + typedef BOpenHashTable + StackTraceSelectionInfoTable; private: // TableListener @@ -49,6 +58,7 @@ private: Table* fFramesTable; FramesTableModel* fFramesTableModel; bool fTraceClearPending; + StackTraceSelectionInfoTable* fSelectionInfoTable; Listener* fListener; };