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)
{
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<std::pair<int, int>, LONG>;
if (SetWindowSubclass(t->hwnd, tableSubProc, 0, (DWORD_PTR) t) == FALSE)
logLastError(L"SetWindowSubclass()");
return t;
}

View File

@ -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<std::pair<int, int>, 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);

View File

@ -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

View File

@ -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++;

View File

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