diff --git a/windows/CMakeLists.txt b/windows/CMakeLists.txt index d074ca87..5a15459c 100644 --- a/windows/CMakeLists.txt +++ b/windows/CMakeLists.txt @@ -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 diff --git a/windows/table.cpp b/windows/table.cpp index e1eb011d..89276fee 100644 --- a/windows/table.cpp +++ b/windows/table.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); diff --git a/windows/table.hpp b/windows/table.hpp index 4e33d70c..42eb04be 100644 --- a/windows/table.hpp +++ b/windows/table.hpp @@ -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); diff --git a/windows/tabledispinfo.cpp b/windows/tabledispinfo.cpp new file mode 100644 index 00000000..87cdd0d1 --- /dev/null +++ b/windows/tabledispinfo.cpp @@ -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; +} diff --git a/windows/tableimages.cpp b/windows/tableimages.cpp deleted file mode 100644 index 7f163ec0..00000000 --- a/windows/tableimages.cpp +++ /dev/null @@ -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; -} diff --git a/windows/tabletext.cpp b/windows/tabletext.cpp deleted file mode 100644 index d1feb336..00000000 --- a/windows/tabletext.cpp +++ /dev/null @@ -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; -}