From c7555dcfd3aa22f7a662d546f58b9cd69685dbe2 Mon Sep 17 00:00:00 2001 From: Pietro Gagliardi Date: Sat, 16 Jun 2018 19:05:36 -0400 Subject: [PATCH] Started a more flexible indeterminate-state implementation. Now to build and test it. --- windows/table.cpp | 69 ++++++++++++++++++++++++++++++++++++++- windows/table.hpp | 4 ++- windows/tabledispinfo.cpp | 4 +-- windows/tabledraw.cpp | 8 ++--- windows/winapi.hpp | 1 + 5 files changed, 76 insertions(+), 10 deletions(-) diff --git a/windows/table.cpp b/windows/table.cpp index b3409907..5fcd7c6b 100644 --- a/windows/table.cpp +++ b/windows/table.cpp @@ -76,6 +76,68 @@ void uiTableModelRowDeleted(uiTableModel *m, int oldIndex) } } +static LRESULT CALLBACK tableSubProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIDSubclass, DWORD_PTR dwRefData) +{ + uiTable *t = (uiTable *) dwRefData; + + switch (uMsg) { + case WM_TIMER: + if (wParam != (WPARAM) t) + break; + for (auto &i : t->indeterminatePositions) { + i->second++; + // TODO check errors + SendMessageW(hwnd, LVM_UPDATE, (WPARAM) (i->first.first), 0); + } + return 0; + case WM_NCDESTROY: + if (RemoveWindowSubclass(hwnd, tableSubProc, uIDSubclass) == FALSE) + logLastError(L"RemoveWindowSubclass()"); + // fall through + } + return DefSubclassProc(hwnd, uMsg, wParam, lParam); +} + +int uiprivTableProgress(uiTable *t, int item, int subitem, int modelColumn, LONG *pos) +{ + uiTableData *data; + int progress; + std::pair p; + std::map, LONG>::iterator iter; + bool startTimer = false; + bool stopTimer = false; + + data = (*(t->model->mh->CellValue))(t->model->mh, t->model, item, modelColumn); + progress = uiTableModelInt(data); + uiFreeTableData(data); + + p.first = item; + p.second = subitem; + iter = t->indeterminatePositions->find(p); + if (iter == t->indeterminatePositions->end()) { + if (progress == -1) { + startTimer = t->indeterminatePositions->size() == 0; + (*(t->indeterminatePositions))[p] = 0; + if (pos != NULL) + *pos = 0; + } + } else + if (progress != -1) { + t->indeterminatePositions->erase(p); + stopTimer = t->indeterminatePositions->size() == 0; + } else if (pos != NULL) + *pos = iter->second; + + if (startTimer) + // the interval shown here is PBM_SETMARQUEE's default + // TODO should we pass a function here instead? it seems to be called by DispatchMessage(), not DefWindowProc(), but I'm still unsure + if (SetTimer(t->hwnd, (UINT_PTR) (&t), 30, NULL) == 0) + logLastError(L"SetTimer()"); + if (stopTimer) + if (KillTimer(t->hwnd, (UINT_PTR) (&t)) == 0) + logLastError(L"KillTimer()"); +} + static BOOL onWM_NOTIFY(uiControl *c, HWND hwnd, NMHDR *nmhdr, LRESULT *lResult) { uiTable *t = uiTable(c); @@ -119,7 +181,8 @@ static void uiTableDestroy(uiControl *c) for (auto col : *(t->columns)) uiprivFree(col); delete t->columns; - // t->smallImages will be automatically destroyed + // t->imagelist will be automatically destroyed + delete t->indeterminatePositions; uiFreeControl(uiControl(t)); } @@ -283,5 +346,9 @@ uiTable *uiNewTable(uiTableModel *model) // TODO } + t->indeterminatePositions = new std::map, LONG>; + if (SetWindowSubclass(t->hwnd, tableSubProc, 0, (DWORD_PTR) t) == FALSE) + logLastError(L"SetWindowSubclass()"); + return t; } diff --git a/windows/table.hpp b/windows/table.hpp index bab46f0e..bf55ef6f 100644 --- a/windows/table.hpp +++ b/windows/table.hpp @@ -31,8 +31,10 @@ struct uiTable { int backgroundColumn; // TODO make sure replacing images while selected in the listview is even allowed HIMAGELIST imagelist; - LONG indeterminatePosition; + // TODO document all this + std::map, LONG> *indeterminatePositions; }; +extern int uiprivTableProgress(uiTable *t, int item, int subitem, int modelColumn, LONG *pos); // tabledispinfo.cpp extern HRESULT uiprivTableHandleLVN_GETDISPINFO(uiTable *t, NMLVDISPINFOW *nm, LRESULT *lResult); diff --git a/windows/tabledispinfo.cpp b/windows/tabledispinfo.cpp index 2e8a06e2..33559bb3 100644 --- a/windows/tabledispinfo.cpp +++ b/windows/tabledispinfo.cpp @@ -32,9 +32,7 @@ static HRESULT handleLVIF_TEXT(uiTable *t, NMLVDISPINFOW *nm, uiprivTableColumnP } if (p->progressBarModelColumn != -1) { - data = (*(t->model->mh->CellValue))(t->model->mh, t->model, nm->item.iItem, p->progressBarModelColumn); - progress = uiTableDataInt(data); - uiFreeTableData(data); + progress = uiprivTableProgress(t, nm->item.iItem, p->progressBarModelColumn, NULL); if (progress == -1) { // TODO either localize this or replace it with something that's language-neutral diff --git a/windows/tabledraw.cpp b/windows/tabledraw.cpp index adaf5feb..59b9d90c 100644 --- a/windows/tabledraw.cpp +++ b/windows/tabledraw.cpp @@ -315,8 +315,8 @@ static HRESULT drawTextPart(struct drawState *s) static HRESULT drawProgressBarPart(struct drawState *s) { - uiTableData *data; int progress; + LONG indeterminatePos; HTHEME theme; RECT r; RECT rBorder, rFill[2]; @@ -327,9 +327,7 @@ static HRESULT drawProgressBarPart(struct drawState *s) if (s->p->progressBarModelColumn == -1) return S_OK; - data = (*(s->m->mh->CellValue))(s->m->mh, s->m, s->iItem, s->p->progressBarModelColumn); - progress = uiTableDataInt(data); - uiFreeTableData(data); + progress = uiprivTableProgress(s->t, s->iItem, s->p->progressBarModelColumn, &indeterminatePos); theme = OpenThemeData(s->t->hwnd, L"TODO"); @@ -381,7 +379,7 @@ static HRESULT drawProgressBarPart(struct drawState *s) rFill[1] = rFill[0]; // save in case we need it barWidth = rFill[0].right - rFill[0].left; pieceWidth = barWidth / indeterminateSegments; - rFill[0].left += s->t->indeterminatePosition % barWidth; + rFill[0].left += indeterminatePos % barWidth; if ((rFill[0].left + pieceWidth) >= rFill[0].right) { // make this piece wrap back around nFill++; diff --git a/windows/winapi.hpp b/windows/winapi.hpp index 19426844..92c08230 100644 --- a/windows/winapi.hpp +++ b/windows/winapi.hpp @@ -60,4 +60,5 @@ #include #include #include +#include #endif