And consolidated the LVN_DISPINFO handlers. Everything's a lot cleaner now too, woo!
This commit is contained in:
parent
b9289c93a6
commit
bcab521311
|
@ -51,9 +51,8 @@ list(APPEND _LIBUI_SOURCES
|
|||
windows/stddialogs.cpp
|
||||
windows/tab.cpp
|
||||
windows/table.cpp
|
||||
windows/tabledispinfo.cpp
|
||||
windows/tabledraw.cpp
|
||||
windows/tableimages.cpp
|
||||
windows/tabletext.cpp
|
||||
windows/tabpage.cpp
|
||||
windows/text.cpp
|
||||
windows/utf16.cpp
|
||||
|
|
|
@ -76,25 +76,6 @@ void uiTableModelRowDeleted(uiTableModel *m, int oldIndex)
|
|||
}
|
||||
}
|
||||
|
||||
static LRESULT onLVN_GETDISPINFO(uiTable *t, NMLVDISPINFOW *nm)
|
||||
{
|
||||
// TODO remove static
|
||||
static uiprivTableColumnParams *p;
|
||||
HRESULT hr;
|
||||
|
||||
p = (*(t->columns))[nm->item.iSubItem];
|
||||
hr = uiprivLVN_GETDISPINFOText(t, nm, p);
|
||||
if (hr != S_OK) {
|
||||
// TODO
|
||||
}
|
||||
hr = uiprivLVN_GETDISPINFOImagesCheckboxes(t, nm, p);
|
||||
if (hr != S_OK) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static BOOL onWM_NOTIFY(uiControl *c, HWND hwnd, NMHDR *nmhdr, LRESULT *lResult)
|
||||
{
|
||||
uiTable *t = uiTable(c);
|
||||
|
@ -102,7 +83,11 @@ static BOOL onWM_NOTIFY(uiControl *c, HWND hwnd, NMHDR *nmhdr, LRESULT *lResult)
|
|||
|
||||
switch (nmhdr->code) {
|
||||
case LVN_GETDISPINFO:
|
||||
*lResult = onLVN_GETDISPINFO(t, (NMLVDISPINFOW *) nmhdr);
|
||||
hr = uiprivTableHandleLVN_GETDISPINFO(t, (NMLVDISPINFOW *) nmhdr, lResult);
|
||||
if (hr != S_OK) {
|
||||
// TODO
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
case NM_CUSTOMDRAW:
|
||||
hr = uiprivTableHandleNM_CUSTOMDRAW(t, (NMLVCUSTOMDRAW *) nmhdr, lResult);
|
||||
|
|
|
@ -32,21 +32,9 @@ struct uiTable {
|
|||
// TODO make sure replacing images while selected in the listview is even allowed
|
||||
HIMAGELIST imagelist;
|
||||
};
|
||||
typedef struct uiprivSubitemDrawParams uiprivSubitemDrawParams;
|
||||
struct uiprivSubitemDrawParams {
|
||||
bool selected;
|
||||
LRESULT bitmapMargin;
|
||||
RECT bounds;
|
||||
RECT icon;
|
||||
RECT label;
|
||||
};
|
||||
|
||||
// tabletext.cpp
|
||||
extern HRESULT uiprivLVN_GETDISPINFOText(uiTable *t, NMLVDISPINFOW *nm, uiprivTableColumnParams *p);
|
||||
|
||||
// tableimages.cpp
|
||||
extern HRESULT uiprivLVN_GETDISPINFOImagesCheckboxes(uiTable *t, NMLVDISPINFOW *nm, uiprivTableColumnParams *p);
|
||||
extern HRESULT uiprivNM_CUSTOMDRAWImagesCheckboxes(uiTable *t, NMLVCUSTOMDRAW *nm, uiprivSubitemDrawParams *dp);
|
||||
// tabledispinfo.cpp
|
||||
extern HRESULT uiprivTableHandleLVN_GETDISPINFO(uiTable *t, NMLVDISPINFOW *nm, LRESULT *lResult);
|
||||
|
||||
// tabledraw.cpp
|
||||
extern HRESULT uiprivTableHandleNM_CUSTOMDRAW(uiTable *t, NMLVCUSTOMDRAW *nm, LRESULT *lResult);
|
||||
|
|
|
@ -0,0 +1,73 @@
|
|||
// 13 june 2018
|
||||
#include "uipriv_windows.hpp"
|
||||
#include "table.hpp"
|
||||
|
||||
static HRESULT handleLVIF_TEXT(uiTable *t, NMLVDISPINFOW *nm, uiprivTableColumnParams *p)
|
||||
{
|
||||
uiTableData *data;
|
||||
WCHAR *wstr;
|
||||
HRESULT hr;
|
||||
|
||||
if ((nm->item.mask & LVIF_TEXT) == 0)
|
||||
return S_OK;
|
||||
if (p->textModelColumn != -1)
|
||||
return S_OK;
|
||||
|
||||
data = (*(t->model->mh->CellValue))(t->model->mh, t->model, nm->item.iItem, p->textModelColumn);
|
||||
wstr = toUTF16(uiTableDataString(data));
|
||||
uiFreeTableData(data);
|
||||
// We *could* just make pszText into a freshly allocated
|
||||
// conversion and avoid the limitation of cchTextMax.
|
||||
// But then, we would have to keep things around for some
|
||||
// amount of time (some pages on MSDN say 2 additional
|
||||
// LVN_GETDISPINFO messages). And in practice, anything
|
||||
// that results in extra LVN_GETDISPINFO messages (such as
|
||||
// LVN_GETITEMRECT with LVIR_LABEL) will break this
|
||||
// counting.
|
||||
// TODO make it so we don't have to make a copy; instead we can convert directly into pszText (this will also avoid the risk of having a dangling surrogate pair at the end)
|
||||
wcsncpy(nm->item.pszText, wstr, nm->item.cchTextMax);
|
||||
nm->item.pszText[nm->item.cchTextMax - 1] = L'\0';
|
||||
uiprivFree(wstr);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static HRESULT handleLVIF_IMAGE(uiTable *t, NMLVDISPINFOW *nm, uiprivTableColumnParams *p)
|
||||
{
|
||||
uiTableData *data;
|
||||
HRESULT hr;
|
||||
|
||||
if (nm->item.iSubItem == 0 && p->imageModelColumn == -1 && p->checkboxModelColumn == -1) {
|
||||
// Having an image list always leaves space for an image
|
||||
// on the main item :|
|
||||
// Other places on the internet imply that you should be
|
||||
// able to do this but that it shouldn't work, but it works
|
||||
// perfectly (and pixel-perfectly too) for me, so...
|
||||
nm->item.mask |= LVIF_INDENT;
|
||||
nm->item.iIndent = -1;
|
||||
}
|
||||
if ((nm->item.mask & LVIF_IMAGE) == 0)
|
||||
return S_OK; // nothing to do here
|
||||
|
||||
// TODO see if the -1 part is correct
|
||||
// TODO see if we should use state instead of images for checkbox data
|
||||
nm->item.iImage = -1;
|
||||
if (p->imageModelColumn != -1 || p->checkboxModelColumn != -1)
|
||||
nm->item.iImage = 0;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT uiprivTableHandleLVN_GETDISPINFO(uiTable *t, NMLVDISPINFOW *nm, LRESULT *lResult)
|
||||
{
|
||||
uiprivTableColumnParams *p;
|
||||
HRESULT hr;
|
||||
|
||||
p = (*(t->columns))[nm->item.iSubItem];
|
||||
hr = handleLVIF_TEXT(t, nm, p);
|
||||
if (hr != S_OK)
|
||||
return hr;
|
||||
hr = handleLVIF_IMAGE(t, nm, p);
|
||||
if (hr != S_OK)
|
||||
return hr;
|
||||
*lResult = 0;
|
||||
return S_OK;
|
||||
}
|
|
@ -1,68 +0,0 @@
|
|||
// 10 june 2018
|
||||
#include "uipriv_windows.hpp"
|
||||
#include "table.hpp"
|
||||
|
||||
/*
|
||||
This file handles both images and checkboxes in tables.
|
||||
|
||||
For images, we'll do a similar thing to what text columns do: cycle out images from the small image list every few LVN_GETDISPINFO notifications.
|
||||
|
||||
For checkboxes, the native list view checkbox functionality uses state images, but those are only supported on the main item, not on subitems. So instead, we'll do them on normal images instead.
|
||||
TODO will this affect accessibility?
|
||||
|
||||
We'll use the small image list. For this, the first few items will be reserved for checkboxes, and the last few for cell images.
|
||||
*/
|
||||
|
||||
// checkboxes TODOs:
|
||||
// - see if we need to get rid of the extra margin in subitems
|
||||
// - get rid of the extra bitmap margin space before text
|
||||
// - get rid of extra whitespace before text on subitems (this might not be necessary if we can fill the background of images AND this amount is the same as on the first column; it is a hardcoded 2 logical units in the real list view code)
|
||||
|
||||
#define nCheckboxImages 4
|
||||
|
||||
HRESULT uiprivLVN_GETDISPINFOImagesCheckboxes(uiTable *t, NMLVDISPINFOW *nm, uiprivTableColumnParams *p)
|
||||
{
|
||||
uiTableData *data;
|
||||
HRESULT hr;
|
||||
|
||||
if (nm->item.iSubItem == 0 && p->imageModelColumn == -1 && p->checkboxModelColumn == -1) {
|
||||
// having an image list always leaves space for an image on the main item :|
|
||||
// other places on the internet imply that you should be able to do this but that it shouldn't work
|
||||
// but it works perfectly (and pixel-perfectly too) for me, so...
|
||||
nm->item.mask |= LVIF_INDENT;
|
||||
nm->item.iIndent = -1;
|
||||
}
|
||||
if ((nm->item.mask & LVIF_IMAGE) == 0)
|
||||
return S_OK; // nothing to do here
|
||||
|
||||
// TODO
|
||||
nm->item.iImage = -1;
|
||||
if (p->imageModelColumn != -1 || p->checkboxModelColumn != -1)
|
||||
nm->item.iImage = 0;
|
||||
return S_OK;
|
||||
|
||||
if (p->imageModelColumn != -1) {
|
||||
nm->item.iImage = 0;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
if (p->checkboxModelColumn != -1) {
|
||||
#if 0
|
||||
// TODO handle enabled
|
||||
data = (*(t->model->mh->CellValue))(t->model->mh, t->model, nm->item.iItem, p->textModelColumn);
|
||||
checked = uiTableDataInt(data) != 0;
|
||||
uiFreeTableData(data);
|
||||
nm->item.iImage = 0;
|
||||
if (checked)
|
||||
nm->item.iImage = 1;
|
||||
nm->item.mask |= LVIF_IMAGE;
|
||||
#endif
|
||||
nm->item.mask |= LVIF_IMAGE;
|
||||
nm->item.iImage = nm->item.iItem % 4;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
// TODO see if this is correct
|
||||
nm->item.iImage = -1;
|
||||
return S_OK;
|
||||
}
|
|
@ -1,29 +0,0 @@
|
|||
// 13 june 2018
|
||||
#include "uipriv_windows.hpp"
|
||||
#include "table.hpp"
|
||||
|
||||
// This file handles text in tables.
|
||||
|
||||
HRESULT uiprivLVN_GETDISPINFOText(uiTable *t, NMLVDISPINFOW *nm, uiprivTableColumnParams *p)
|
||||
{
|
||||
uiTableData *data;
|
||||
WCHAR *wstr;
|
||||
HRESULT hr;
|
||||
|
||||
if ((nm->item.mask & LVIF_TEXT) == 0)
|
||||
return S_OK;
|
||||
if (p->textModelColumn != -1)
|
||||
return S_OK;
|
||||
|
||||
data = (*(t->model->mh->CellValue))(t->model->mh, t->model, nm->item.iItem, p->textModelColumn);
|
||||
wstr = toUTF16(uiTableDataString(data));
|
||||
uiFreeTableData(data);
|
||||
// we could just make pszText into a freshly allocated conversion and avoid the limitation of cchTextMax
|
||||
// but then we would have to keep things around for some amount of time (some pages on MSDN say 2 additional LVN_GETDISPINFO messages)
|
||||
// and in practice, anything that results in extra LVN_GETDISPINFO messages (such as fillSubitemDrawParams() below) will break this counting
|
||||
// TODO make it so we don't have to make a copy; instead we can convert directly into pszText (this will also avoid the risk of having a dangling surrogate pair at the end)
|
||||
wcsncpy(nm->item.pszText, wstr, nm->item.cchTextMax);
|
||||
nm->item.pszText[nm->item.cchTextMax - 1] = L'\0';
|
||||
uiprivFree(wstr);
|
||||
return S_OK;
|
||||
}
|
Loading…
Reference in New Issue