From 2b7a601c17cc4f9b71d8f7ccec55ff942de74ffa Mon Sep 17 00:00:00 2001 From: Kingcom Date: Thu, 13 Feb 2014 10:24:42 +0100 Subject: [PATCH] Add checkboxes to GenericListControl, use them in CtrlBreakpointList --- Windows/Debugger/Debugger_Lists.cpp | 54 +++++++++++++++++++------- Windows/Debugger/Debugger_Lists.h | 1 + Windows/GEDebugger/TabDisplayLists.cpp | 12 +++++- Windows/GEDebugger/TabState.cpp | 6 ++- Windows/GEDebugger/TabVertices.cpp | 12 +++++- Windows/W32Util/Misc.cpp | 50 +++++++++++++++++++++--- Windows/W32Util/Misc.h | 17 +++++++- 7 files changed, 127 insertions(+), 25 deletions(-) diff --git a/Windows/Debugger/Debugger_Lists.cpp b/Windows/Debugger/Debugger_Lists.cpp index 9f5cb18e9d..964258c2e8 100644 --- a/Windows/Debugger/Debugger_Lists.cpp +++ b/Windows/Debugger/Debugger_Lists.cpp @@ -13,7 +13,7 @@ static const int numCPUs = 1; enum { TL_NAME, TL_PROGRAMCOUNTER, TL_ENTRYPOINT, TL_PRIORITY, TL_STATE, TL_WAITTYPE, TL_COLUMNCOUNT }; -enum { BPL_TYPE, BPL_OFFSET, BPL_SIZELABEL, BPL_OPCODE, BPL_CONDITION, BPL_HITS, BPL_ENABLED, BPL_COLUMNCOUNT }; +enum { BPL_ENABLED, BPL_TYPE, BPL_OFFSET, BPL_SIZELABEL, BPL_OPCODE, BPL_CONDITION, BPL_HITS, BPL_COLUMNCOUNT }; enum { SF_ENTRY, SF_ENTRYNAME, SF_CURPC, SF_CUROPCODE, SF_CURSP, SF_FRAMESIZE, SF_COLUMNCOUNT }; enum { ML_NAME, ML_ADDRESS, ML_SIZE, ML_ACTIVE, ML_COLUMNCOUNT }; @@ -26,14 +26,22 @@ GenericListViewColumn threadColumns[TL_COLUMNCOUNT] = { { L"Wait type", 0.20f } }; +GenericListViewDef threadListDef = { + threadColumns, ARRAY_SIZE(threadColumns), NULL, false +}; + GenericListViewColumn breakpointColumns[BPL_COLUMNCOUNT] = { - { L"Type", 0.12f }, + { L"", 0.03f }, // enabled + { L"Type", 0.15f }, { L"Offset", 0.12f }, - { L"Size/Label", 0.18f }, + { L"Size/Label", 0.20f }, { L"Opcode", 0.28f }, { L"Condition", 0.17f }, { L"Hits", 0.05f }, - { L"Enabled", 0.08f } +}; + +GenericListViewDef breakpointListDef = { + breakpointColumns, ARRAY_SIZE(breakpointColumns), NULL, true }; GenericListViewColumn stackTraceColumns[SF_COLUMNCOUNT] = { @@ -45,6 +53,10 @@ GenericListViewColumn stackTraceColumns[SF_COLUMNCOUNT] = { { L"Frame Size", 0.12f } }; +GenericListViewDef stackTraceListDef = { + stackTraceColumns, ARRAY_SIZE(stackTraceColumns), NULL, false +}; + GenericListViewColumn moduleListColumns[ML_COLUMNCOUNT] = { { L"Name", 0.25f }, { L"Address", 0.25f }, @@ -52,6 +64,10 @@ GenericListViewColumn moduleListColumns[ML_COLUMNCOUNT] = { { L"Active", 0.25f }, }; +GenericListViewDef moduleListDef = { + moduleListColumns, ARRAY_SIZE(moduleListColumns), NULL, false +}; + const int POPUP_SUBMENU_ID_BREAKPOINTLIST = 5; const int POPUP_SUBMENU_ID_THREADLIST = 6; const int POPUP_SUBMENU_ID_NEWBREAKPOINT = 7; @@ -60,7 +76,7 @@ const int POPUP_SUBMENU_ID_NEWBREAKPOINT = 7; // CtrlThreadList // -CtrlThreadList::CtrlThreadList(HWND hwnd): GenericListControl(hwnd,threadColumns,TL_COLUMNCOUNT) +CtrlThreadList::CtrlThreadList(HWND hwnd): GenericListControl(hwnd,threadListDef) { Update(); } @@ -245,7 +261,7 @@ const char* CtrlThreadList::getCurrentThreadName() // CtrlBreakpointList::CtrlBreakpointList(HWND hwnd, DebugInterface* cpu, CtrlDisAsmView* disasm) - : GenericListControl(hwnd,breakpointColumns,BPL_COLUMNCOUNT),cpu(cpu),disasm(disasm) + : GenericListControl(hwnd,breakpointListDef),cpu(cpu),disasm(disasm) { SetSendInvalidRows(true); Update(); @@ -299,6 +315,17 @@ void CtrlBreakpointList::reloadBreakpoints() displayedBreakPoints_ = CBreakPoints::GetBreakpoints(); displayedMemChecks_= CBreakPoints::GetMemChecks(); Update(); + + for (int i = 0; i < GetRowCount(); i++) + { + bool isMemory; + int index = getBreakpointIndex(i, isMemory); + + if (isMemory) + SetCheckState(i,(displayedMemChecks_[index].result & MEMCHECK_BREAK) != 0); + else + SetCheckState(i,displayedBreakPoints_[index].enabled); + } } void CtrlBreakpointList::editBreakpoint(int itemIndex) @@ -521,11 +548,7 @@ void CtrlBreakpointList::GetColumnText(wchar_t* dest, int row, int col) break; case BPL_ENABLED: { - if (isMemory) { - wsprintf(dest,displayedMemChecks_[index].result & MEMCHECK_BREAK ? L"True" : L"False"); - } else { - wsprintf(dest,displayedBreakPoints_[index].enabled ? L"True" : L"False"); - } + wsprintf(dest,L"\xFFFE"); } break; } @@ -541,6 +564,11 @@ void CtrlBreakpointList::OnRightClick(int itemIndex, int column, const POINT& po showBreakpointMenu(itemIndex,point); } +void CtrlBreakpointList::OnToggle(int item, bool newValue) +{ + toggleEnabled(item); +} + void CtrlBreakpointList::showBreakpointMenu(int itemIndex, const POINT &pt) { POINT screenPt(pt); @@ -604,7 +632,7 @@ void CtrlBreakpointList::showBreakpointMenu(int itemIndex, const POINT &pt) // CtrlStackTraceView::CtrlStackTraceView(HWND hwnd, DebugInterface* cpu, CtrlDisAsmView* disasm) - : GenericListControl(hwnd,stackTraceColumns,SF_COLUMNCOUNT),cpu(cpu),disasm(disasm) + : GenericListControl(hwnd,stackTraceListDef),cpu(cpu),disasm(disasm) { Update(); } @@ -709,7 +737,7 @@ void CtrlStackTraceView::loadStackTrace() // CtrlModuleList::CtrlModuleList(HWND hwnd, DebugInterface* cpu) - : GenericListControl(hwnd,moduleListColumns,ML_COLUMNCOUNT),cpu(cpu) + : GenericListControl(hwnd,moduleListDef),cpu(cpu) { Update(); } diff --git a/Windows/Debugger/Debugger_Lists.h b/Windows/Debugger/Debugger_Lists.h index 3480e3b88b..43dd834a44 100644 --- a/Windows/Debugger/Debugger_Lists.h +++ b/Windows/Debugger/Debugger_Lists.h @@ -38,6 +38,7 @@ protected: virtual int GetRowCount() { return getTotalBreakpointCount(); }; virtual void OnDoubleClick(int itemIndex, int column); virtual void OnRightClick(int itemIndex, int column, const POINT& point); + virtual void OnToggle(int item, bool newValue); private: std::vector displayedBreakPoints_; std::vector displayedMemChecks_; diff --git a/Windows/GEDebugger/TabDisplayLists.cpp b/Windows/GEDebugger/TabDisplayLists.cpp index 6ad1b1fdc7..041051a9ab 100644 --- a/Windows/GEDebugger/TabDisplayLists.cpp +++ b/Windows/GEDebugger/TabDisplayLists.cpp @@ -25,7 +25,11 @@ const GenericListViewColumn displayListStackColumns[3] = { { L"Offset", 0.33f }, }; -CtrlDisplayListStack::CtrlDisplayListStack(HWND hwnd): GenericListControl(hwnd,displayListStackColumns,DLS_COLUMNCOUNT) +GenericListViewDef displayListStackListDef = { + displayListStackColumns, ARRAY_SIZE(displayListStackColumns), NULL, false +}; + +CtrlDisplayListStack::CtrlDisplayListStack(HWND hwnd): GenericListControl(hwnd,displayListStackListDef) { list.stackptr = 0; Update(); @@ -73,7 +77,11 @@ const GenericListViewColumn allDisplayListsColumns[ADL_COLUMNCOUNT] = { { L"Interrupted", 0.15f }, }; -CtrlAllDisplayLists::CtrlAllDisplayLists(HWND hwnd): GenericListControl(hwnd,allDisplayListsColumns,ADL_COLUMNCOUNT) +GenericListViewDef allDisplayListsListDef = { + allDisplayListsColumns, ARRAY_SIZE(allDisplayListsColumns), NULL, false +}; + +CtrlAllDisplayLists::CtrlAllDisplayLists(HWND hwnd): GenericListControl(hwnd,allDisplayListsListDef) { Update(); } diff --git a/Windows/GEDebugger/TabState.cpp b/Windows/GEDebugger/TabState.cpp index 714279ed87..252194d3e1 100644 --- a/Windows/GEDebugger/TabState.cpp +++ b/Windows/GEDebugger/TabState.cpp @@ -30,6 +30,10 @@ static const GenericListViewColumn stateValuesCols[] = { { L"Value", 0.50f }, }; +GenericListViewDef stateValuesListDef = { + stateValuesCols, ARRAY_SIZE(stateValuesCols), NULL, false +}; + enum StateValuesCols { STATEVALUES_COL_NAME, STATEVALUES_COL_VALUE, @@ -257,7 +261,7 @@ static const TabStateRow stateSettingsRows[] = { // GE_CMD_UNKNOWN_* CtrlStateValues::CtrlStateValues(const TabStateRow *rows, int rowCount, HWND hwnd) - : GenericListControl(hwnd, stateValuesCols, ARRAY_SIZE(stateValuesCols)), + : GenericListControl(hwnd, stateValuesListDef), rows_(rows), rowCount_(rowCount) { Update(); } diff --git a/Windows/GEDebugger/TabVertices.cpp b/Windows/GEDebugger/TabVertices.cpp index ebc3ec6517..b383f1a89f 100644 --- a/Windows/GEDebugger/TabVertices.cpp +++ b/Windows/GEDebugger/TabVertices.cpp @@ -34,6 +34,10 @@ static const GenericListViewColumn vertexListCols[] = { // TODO: Normal, weight, morph? }; +GenericListViewDef vertexListDef = { + vertexListCols, ARRAY_SIZE(vertexListCols), NULL, false +}; + enum VertexListCols { VERTEXLIST_COL_X, VERTEXLIST_COL_Y, @@ -51,6 +55,10 @@ static const GenericListViewColumn matrixListCols[] = { { L"3", 0.19f }, }; +GenericListViewDef matrixListDef = { + matrixListCols, ARRAY_SIZE(matrixListCols), NULL, false +}; + enum MatrixListCols { MATRIXLIST_COL_NAME, MATRIXLIST_COL_0, @@ -104,7 +112,7 @@ enum MatrixListRows { }; CtrlVertexList::CtrlVertexList(HWND hwnd) - : GenericListControl(hwnd, vertexListCols, ARRAY_SIZE(vertexListCols)), raw_(false) { + : GenericListControl(hwnd, vertexListDef), raw_(false) { decoder = new VertexDecoder(); Update(); } @@ -330,7 +338,7 @@ BOOL TabVertices::DlgProc(UINT message, WPARAM wParam, LPARAM lParam) { } CtrlMatrixList::CtrlMatrixList(HWND hwnd) - : GenericListControl(hwnd, matrixListCols, ARRAY_SIZE(matrixListCols)) { + : GenericListControl(hwnd, matrixListDef) { Update(); } diff --git a/Windows/W32Util/Misc.cpp b/Windows/W32Util/Misc.cpp index e835701fd2..beea5de3bf 100644 --- a/Windows/W32Util/Misc.cpp +++ b/Windows/W32Util/Misc.cpp @@ -21,7 +21,7 @@ namespace W32Util GetWindowRect(hwnd, &rect); GetWindowRect(hwndParent, &rectP); - + width = rect.right - rect.left; height = rect.bottom - rect.top; @@ -30,7 +30,7 @@ namespace W32Util screenwidth = GetSystemMetrics(SM_CXSCREEN); screenheight = GetSystemMetrics(SM_CYSCREEN); - + //make sure that the dialog box never moves outside of //the screen if(x < 0) x = 0; @@ -94,8 +94,9 @@ namespace W32Util -GenericListControl::GenericListControl(HWND hwnd, const GenericListViewColumn* _columns, int _columnCount) - : handle(hwnd), columns(_columns),columnCount(_columnCount),valid(false) +GenericListControl::GenericListControl(HWND hwnd, const GenericListViewDef& def) + : handle(hwnd), columns(def.columns),columnCount(def.columnCount),valid(false), + inResizeColumns(false),updating(false) { DWORD style = GetWindowLong(handle,GWL_STYLE) | LVS_REPORT; SetWindowLong(handle, GWL_STYLE, style); @@ -103,12 +104,14 @@ GenericListControl::GenericListControl(HWND hwnd, const GenericListViewColumn* _ SetWindowLongPtr(handle,GWLP_USERDATA,(LONG_PTR)this); oldProc = (WNDPROC) SetWindowLongPtr(handle,GWLP_WNDPROC,(LONG_PTR)wndProc); - SendMessage(handle, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, LVS_EX_FULLROWSELECT); + auto exStyle = LVS_EX_FULLROWSELECT; + if (def.checkbox) + exStyle |= LVS_EX_CHECKBOXES; + SendMessage(handle, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, exStyle); LVCOLUMN lvc; lvc.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM; lvc.iSubItem = 0; - lvc.fmt = LVCFMT_LEFT; RECT rect; GetClientRect(handle,&rect); @@ -117,9 +120,18 @@ GenericListControl::GenericListControl(HWND hwnd, const GenericListViewColumn* _ for (int i = 0; i < columnCount; i++) { lvc.cx = columns[i].size * totalListSize; lvc.pszText = columns[i].name; + + if (columns[i].flags & GLVC_CENTERED) + lvc.fmt = LVCFMT_CENTER; + else + lvc.fmt = LVCFMT_LEFT; + ListView_InsertColumn(handle, i, &lvc); } + if (def.columnOrder != NULL) + ListView_SetColumnOrderArray(handle,columnCount,def.columnOrder); + SetSendInvalidRows(false); valid = true; } @@ -157,10 +169,27 @@ void GenericListControl::HandleNotify(LPARAM lParam) dispInfo->item.pszText = stringBuffer; return; } + + // handle checkboxes + if (mhdr->code == LVN_ITEMCHANGED && updating == false) + { + NMLISTVIEW* item = (NMLISTVIEW*) lParam; + if (item->iItem != -1 && (item->uChanged & LVIF_STATE) != 0) + { + // image is 1 if unchcked, 2 if checked + int oldImage = (item->uOldState & LVIS_STATEIMAGEMASK) >> 12; + int newImage = (item->uNewState & LVIS_STATEIMAGEMASK) >> 12; + if (oldImage != newImage) + OnToggle(item->iItem,newImage == 2); + } + + return; + } } void GenericListControl::Update() { + updating = true; int newRows = GetRowCount(); int items = ListView_GetItemCount(handle); @@ -188,6 +217,15 @@ void GenericListControl::Update() InvalidateRect(handle,NULL,true); UpdateWindow(handle); + updating = false; +} + + +void GenericListControl::SetCheckState(int item, bool state) +{ + updating = true; + ListView_SetCheckState(handle,item,state ? TRUE : FALSE); + updating = false; } void GenericListControl::ResizeColumns() diff --git a/Windows/W32Util/Misc.h b/Windows/W32Util/Misc.h index cd065b3612..1d3295a61d 100644 --- a/Windows/W32Util/Misc.h +++ b/Windows/W32Util/Misc.h @@ -16,8 +16,20 @@ struct GenericListViewColumn { wchar_t *name; float size; + int flags; }; +struct GenericListViewDef +{ + const GenericListViewColumn* columns; + int columnCount; + int* columnOrder; + bool checkbox; // the first column will always have the checkbox. specify a custom order to change its position +}; + +#define GLVC_CENTERED 1 + + // the most significant bit states whether the key is currently down. // simply checking if it's != 0 is not enough, as bit0 is set if // the key was pressed between the last call to GetAsyncKeyState @@ -29,7 +41,7 @@ inline bool KeyDownAsync(int vkey) class GenericListControl { public: - GenericListControl(HWND hwnd, const GenericListViewColumn* _columns, int _columnCount); + GenericListControl(HWND hwnd, const GenericListViewDef& def); virtual ~GenericListControl() { }; void HandleNotify(LPARAM lParam); void Update(); @@ -37,12 +49,14 @@ public: HWND GetHandle() { return handle; }; void SetSendInvalidRows(bool enabled) { sendInvalidRows = enabled; }; protected: + void SetCheckState(int item, bool state); virtual bool WindowMessage(UINT msg, WPARAM wParam, LPARAM lParam, LRESULT& returnValue) = 0; virtual void GetColumnText(wchar_t* dest, int row, int col) = 0; virtual int GetRowCount() = 0; virtual void OnDoubleClick(int itemIndex, int column) { }; virtual void OnRightClick(int itemIndex, int column, const POINT& point) { }; virtual void CopyRows(int start, int size); + virtual void OnToggle(int item, bool newValue) { }; private: static LRESULT CALLBACK wndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam); void ResizeColumns(); @@ -58,4 +72,5 @@ private: bool sendInvalidRows; // Used for hacky workaround to fix a rare hang (see issue #5184) volatile bool inResizeColumns; + volatile bool updating; }; \ No newline at end of file