debugger: make symbol list virtualized

This commit is contained in:
Crementif 2026-05-16 14:08:48 +02:00
parent 25cd379aaa
commit 1263e20bae
2 changed files with 50 additions and 63 deletions

View File

@ -38,13 +38,12 @@ SymbolListCtrl::SymbolListCtrl(wxWindow* parent, const wxWindowID& id, const wxP
m_list_filter.Clear();
OnGameLoaded();
SetItemCount(m_data.size());
}
void SymbolListCtrl::OnGameLoaded()
{
m_data.clear();
m_visible_items.clear();
const auto symbol_map = rplSymbolStorage_lockSymbolMap();
for (auto const& [address, symbol_info] : symbol_map)
{
@ -56,48 +55,30 @@ void SymbolListCtrl::OnGameLoaded()
wxString searchNameWX = libNameWX + symbolNameWX;
searchNameWX.MakeLower();
auto new_entry = m_data.try_emplace(
symbol_info->address,
symbolNameWX,
m_data.try_emplace(
address,
symbolNameWX,
libNameWX,
searchNameWX,
false
searchNameWX
);
if (m_list_filter.IsEmpty())
new_entry.first->second.visible = true;
else if (new_entry.first->second.searchName.Contains(m_list_filter))
new_entry.first->second.visible = true;
}
rplSymbolStorage_unlockSymbolMap();
SetItemCount(m_data.size());
if (m_data.size() > 0)
RefreshItems(GetTopItem(), std::min<long>(m_data.size() - 1, GetTopItem() + GetCountPerPage() + 1));
RebuildVisibleItems();
}
wxString SymbolListCtrl::OnGetItemText(long item, long column) const
{
if (item >= GetItemCount())
if (item < 0 || item >= static_cast<long>(m_visible_items.size()))
return wxEmptyString;
long visible_idx = 0;
for (const auto& [address, symbol] : m_data)
{
if (!symbol.visible)
continue;
if (item == visible_idx)
{
if (column == ColumnName)
return wxString(symbol.name);
if (column == ColumnAddress)
return wxString::Format("%08x", address);
if (column == ColumnModule)
return wxString(symbol.libName);
}
visible_idx++;
}
const auto& [address, symbol] = *m_visible_items[item];
if (column == ColumnName)
return symbol.name;
if (column == ColumnAddress)
return wxString::Format("%08x", address);
if (column == ColumnModule)
return symbol.libName;
return wxEmptyString;
}
@ -106,10 +87,9 @@ wxString SymbolListCtrl::OnGetItemText(long item, long column) const
void SymbolListCtrl::OnLeftDClick(wxListEvent& event)
{
long selected = GetFirstSelected();
if (selected == wxNOT_FOUND)
if (selected == wxNOT_FOUND || selected >= static_cast<long>(m_visible_items.size()))
return;
const auto text = GetItemText(selected, ColumnAddress);
const auto address = std::stoul(text.ToStdString(), nullptr, 16);
const auto address = m_visible_items[selected]->first;
if (address == 0)
return;
debugger_jumpToAddressInDisasm(address);
@ -118,10 +98,9 @@ void SymbolListCtrl::OnLeftDClick(wxListEvent& event)
void SymbolListCtrl::OnRightClick(wxListEvent& event)
{
long selected = GetFirstSelected();
if (selected == wxNOT_FOUND)
if (selected == wxNOT_FOUND || selected >= static_cast<long>(m_visible_items.size()))
return;
auto text = GetItemText(selected, ColumnAddress);
text = "0x" + text;
auto text = wxString::Format("0x%08x", m_visible_items[selected]->first);
#if BOOST_OS_WINDOWS
if (OpenClipboard(nullptr))
{
@ -140,24 +119,31 @@ void SymbolListCtrl::OnRightClick(wxListEvent& event)
#endif
}
void SymbolListCtrl::RebuildVisibleItems()
{
m_visible_items.clear();
m_visible_items.reserve(m_data.size());
const bool has_filter = !m_list_filter.IsEmpty();
for (auto it = m_data.cbegin(); it != m_data.cend(); ++it)
{
if (has_filter && !it->second.searchName.Contains(m_list_filter))
continue;
m_visible_items.emplace_back(it);
}
SetItemCount(static_cast<long>(m_visible_items.size()));
if (!m_visible_items.empty())
{
const auto top_item = std::min<long>(GetTopItem(), static_cast<long>(m_visible_items.size() - 1));
RefreshItems(top_item, std::min<long>(static_cast<long>(m_visible_items.size() - 1), top_item + GetCountPerPage() + 1));
}
else
Refresh();
}
void SymbolListCtrl::ChangeListFilter(wxString filter)
{
m_list_filter = filter.MakeLower();
size_t visible_entries = m_data.size();
for (auto& [address, symbol] : m_data)
{
if (m_list_filter.IsEmpty())
symbol.visible = true;
else if (symbol.searchName.Contains(m_list_filter))
symbol.visible = true;
else
{
visible_entries--;
symbol.visible = false;
}
}
SetItemCount(visible_entries);
if (visible_entries > 0)
RefreshItems(GetTopItem(), std::min<long>(visible_entries - 1, GetTopItem() + GetCountPerPage() + 1));
RebuildVisibleItems();
}

View File

@ -10,22 +10,23 @@ public:
void ChangeListFilter(wxString filter);
private:
private:
struct SymbolItem {
SymbolItem() = default;
SymbolItem(wxString name, wxString libName, wxString searchName, bool visible) : name(name), libName(libName), searchName(searchName), visible(visible) {}
SymbolItem() = default;
SymbolItem(const wxString& name, const wxString& libName, const wxString& searchName) : name(name), libName(libName), searchName(searchName) {}
wxString name;
wxString libName;
wxString searchName;
bool visible;
};
using SymbolMap = std::map<MPTR, SymbolItem>;
std::map<MPTR, SymbolItem> m_data;
SymbolMap m_data;
wxString m_list_filter;
std::vector<SymbolMap::const_iterator> m_visible_items;
wxString OnGetItemText(long item, long column) const;
wxString OnGetItemText(long item, long column) const override;
void RebuildVisibleItems();
void OnLeftDClick(wxListEvent& event);
void OnRightClick(wxListEvent& event);
};