Started a more flexible indeterminate-state implementation. Now to build and test it.

This commit is contained in:
Pietro Gagliardi 2018-06-16 19:05:36 -04:00
parent c978f6fece
commit c7555dcfd3
5 changed files with 76 additions and 10 deletions

View File

@ -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<int, int> p;
std::map<std::pair<int, int>, 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) static BOOL onWM_NOTIFY(uiControl *c, HWND hwnd, NMHDR *nmhdr, LRESULT *lResult)
{ {
uiTable *t = uiTable(c); uiTable *t = uiTable(c);
@ -119,7 +181,8 @@ static void uiTableDestroy(uiControl *c)
for (auto col : *(t->columns)) for (auto col : *(t->columns))
uiprivFree(col); uiprivFree(col);
delete t->columns; delete t->columns;
// t->smallImages will be automatically destroyed // t->imagelist will be automatically destroyed
delete t->indeterminatePositions;
uiFreeControl(uiControl(t)); uiFreeControl(uiControl(t));
} }
@ -283,5 +346,9 @@ uiTable *uiNewTable(uiTableModel *model)
// TODO // TODO
} }
t->indeterminatePositions = new std::map<std::pair<int, int>, LONG>;
if (SetWindowSubclass(t->hwnd, tableSubProc, 0, (DWORD_PTR) t) == FALSE)
logLastError(L"SetWindowSubclass()");
return t; return t;
} }

View File

@ -31,8 +31,10 @@ struct uiTable {
int backgroundColumn; int backgroundColumn;
// TODO make sure replacing images while selected in the listview is even allowed // TODO make sure replacing images while selected in the listview is even allowed
HIMAGELIST imagelist; HIMAGELIST imagelist;
LONG indeterminatePosition; // TODO document all this
std::map<std::pair<int, int>, LONG> *indeterminatePositions;
}; };
extern int uiprivTableProgress(uiTable *t, int item, int subitem, int modelColumn, LONG *pos);
// tabledispinfo.cpp // tabledispinfo.cpp
extern HRESULT uiprivTableHandleLVN_GETDISPINFO(uiTable *t, NMLVDISPINFOW *nm, LRESULT *lResult); extern HRESULT uiprivTableHandleLVN_GETDISPINFO(uiTable *t, NMLVDISPINFOW *nm, LRESULT *lResult);

View File

@ -32,9 +32,7 @@ static HRESULT handleLVIF_TEXT(uiTable *t, NMLVDISPINFOW *nm, uiprivTableColumnP
} }
if (p->progressBarModelColumn != -1) { if (p->progressBarModelColumn != -1) {
data = (*(t->model->mh->CellValue))(t->model->mh, t->model, nm->item.iItem, p->progressBarModelColumn); progress = uiprivTableProgress(t, nm->item.iItem, p->progressBarModelColumn, NULL);
progress = uiTableDataInt(data);
uiFreeTableData(data);
if (progress == -1) { if (progress == -1) {
// TODO either localize this or replace it with something that's language-neutral // TODO either localize this or replace it with something that's language-neutral

View File

@ -315,8 +315,8 @@ static HRESULT drawTextPart(struct drawState *s)
static HRESULT drawProgressBarPart(struct drawState *s) static HRESULT drawProgressBarPart(struct drawState *s)
{ {
uiTableData *data;
int progress; int progress;
LONG indeterminatePos;
HTHEME theme; HTHEME theme;
RECT r; RECT r;
RECT rBorder, rFill[2]; RECT rBorder, rFill[2];
@ -327,9 +327,7 @@ static HRESULT drawProgressBarPart(struct drawState *s)
if (s->p->progressBarModelColumn == -1) if (s->p->progressBarModelColumn == -1)
return S_OK; return S_OK;
data = (*(s->m->mh->CellValue))(s->m->mh, s->m, s->iItem, s->p->progressBarModelColumn); progress = uiprivTableProgress(s->t, s->iItem, s->p->progressBarModelColumn, &indeterminatePos);
progress = uiTableDataInt(data);
uiFreeTableData(data);
theme = OpenThemeData(s->t->hwnd, L"TODO"); 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 rFill[1] = rFill[0]; // save in case we need it
barWidth = rFill[0].right - rFill[0].left; barWidth = rFill[0].right - rFill[0].left;
pieceWidth = barWidth / indeterminateSegments; pieceWidth = barWidth / indeterminateSegments;
rFill[0].left += s->t->indeterminatePosition % barWidth; rFill[0].left += indeterminatePos % barWidth;
if ((rFill[0].left + pieceWidth) >= rFill[0].right) { if ((rFill[0].left + pieceWidth) >= rFill[0].right) {
// make this piece wrap back around // make this piece wrap back around
nFill++; nFill++;

View File

@ -60,4 +60,5 @@
#include <unordered_map> #include <unordered_map>
#include <sstream> #include <sstream>
#include <functional> #include <functional>
#include <utility>
#endif #endif