And integrated tabledraw.cpp. It works, barring some technical gltiches. It also makes me realize the alpha blending issue was my fault...
This commit is contained in:
parent
fda8f2fbae
commit
e6da33121e
|
@ -51,6 +51,7 @@ list(APPEND _LIBUI_SOURCES
|
|||
windows/stddialogs.cpp
|
||||
windows/tab.cpp
|
||||
windows/table.cpp
|
||||
windows/tabledraw.cpp
|
||||
windows/tableimages.cpp
|
||||
windows/tabletext.cpp
|
||||
windows/tabpage.cpp
|
||||
|
|
|
@ -78,6 +78,7 @@ void uiTableModelRowDeleted(uiTableModel *m, int oldIndex)
|
|||
|
||||
static LRESULT onLVN_GETDISPINFO(uiTable *t, NMLVDISPINFOW *nm)
|
||||
{
|
||||
// TODO remove static
|
||||
static uiprivTableColumnParams *p;
|
||||
HRESULT hr;
|
||||
|
||||
|
@ -94,131 +95,21 @@ static LRESULT onLVN_GETDISPINFO(uiTable *t, NMLVDISPINFOW *nm)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static COLORREF blend(COLORREF base, double r, double g, double b, double a)
|
||||
{
|
||||
double br, bg, bb;
|
||||
|
||||
// TODO find a better fix than this
|
||||
// TODO s listview already alphablending?
|
||||
// TODO find the right color here
|
||||
if (base == CLR_DEFAULT)
|
||||
base = GetSysColor(COLOR_WINDOW);
|
||||
br = ((double) GetRValue(base)) / 255.0;
|
||||
bg = ((double) GetGValue(base)) / 255.0;
|
||||
bb = ((double) GetBValue(base)) / 255.0;
|
||||
|
||||
br = (r * a) + (br * (1.0 - a));
|
||||
bg = (g * a) + (bg * (1.0 - a));
|
||||
bb = (b * a) + (bb * (1.0 - a));
|
||||
return RGB((BYTE) (br * 255),
|
||||
(BYTE) (bg * 255),
|
||||
(BYTE) (bb * 255));
|
||||
}
|
||||
|
||||
COLORREF uiprivTableBlendedColorFromModel(uiTable *t, NMLVCUSTOMDRAW *nm, int modelColumn, int fallbackSysColorID)
|
||||
{
|
||||
uiTableData *data;
|
||||
double r, g, b, a;
|
||||
|
||||
data = (*(t->model->mh->CellValue))(t->model->mh, t->model, nm->nmcd.dwItemSpec, modelColumn);
|
||||
if (data == NULL)
|
||||
return GetSysColor(fallbackSysColorID);
|
||||
uiTableDataColor(data, &r, &g, &b, &a);
|
||||
uiFreeTableData(data);
|
||||
return blend(nm->clrTextBk, r, g, b, a);
|
||||
}
|
||||
|
||||
static LRESULT onNM_CUSTOMDRAW(uiTable *t, NMLVCUSTOMDRAW *nm)
|
||||
{
|
||||
uiprivTableColumnParams *p;
|
||||
uiTableData *data;
|
||||
double r, g, b, a;
|
||||
uiprivSubitemDrawParams dp;
|
||||
LRESULT ret;
|
||||
HRESULT hr;
|
||||
|
||||
switch (nm->nmcd.dwDrawStage) {
|
||||
case CDDS_PREPAINT:
|
||||
return CDRF_NOTIFYITEMDRAW;
|
||||
case CDDS_ITEMPREPAINT:
|
||||
if (t->backgroundColumn != -1) {
|
||||
data = (*(t->model->mh->CellValue))(t->model->mh, t->model, nm->nmcd.dwItemSpec, t->backgroundColumn);
|
||||
if (data != NULL) {
|
||||
uiTableDataColor(data, &r, &g, &b, &a);
|
||||
uiFreeTableData(data);
|
||||
nm->clrTextBk = blend(nm->clrTextBk, r, g, b, a);
|
||||
}
|
||||
}
|
||||
{
|
||||
LRESULT state;
|
||||
HBRUSH b;
|
||||
bool freeBrush = false;
|
||||
|
||||
// note: nm->nmcd.uItemState CDIS_SELECTED is unreliable for the listview configuration we have
|
||||
state = SendMessageW(t->hwnd, LVM_GETITEMSTATE, nm->nmcd.dwItemSpec, LVIS_SELECTED);
|
||||
if ((state & LVIS_SELECTED) != 0)
|
||||
b = GetSysColorBrush(COLOR_HIGHLIGHT);
|
||||
else if (nm->clrTextBk != CLR_DEFAULT) {
|
||||
b = CreateSolidBrush(nm->clrTextBk);
|
||||
if (b == NULL)
|
||||
logLastError(L"CreateSolidBrush()");
|
||||
freeBrush = true;
|
||||
} else
|
||||
b = GetSysColorBrush(COLOR_WINDOW);
|
||||
// TODO check error
|
||||
FillRect(nm->nmcd.hdc, &(nm->nmcd.rc), b);
|
||||
if (freeBrush)
|
||||
if (DeleteObject(b) == 0)
|
||||
logLastError(L"DeleteObject()");
|
||||
}
|
||||
t->clrItemText = nm->clrText;
|
||||
return CDRF_NEWFONT | CDRF_NOTIFYSUBITEMDRAW;
|
||||
case CDDS_SUBITEM | CDDS_ITEMPREPAINT:
|
||||
p = (*(t->columns))[nm->iSubItem];
|
||||
// TODO none of this runs on the first item
|
||||
// we need this as previous subitems will persist their colors
|
||||
nm->clrText = t->clrItemText;
|
||||
if (p->textParams.ColorModelColumn != -1) {
|
||||
data = (*(t->model->mh->CellValue))(t->model->mh, t->model, nm->nmcd.dwItemSpec, p->textParams.ColorModelColumn);
|
||||
if (data != NULL) {
|
||||
uiTableDataColor(data, &r, &g, &b, &a);
|
||||
uiFreeTableData(data);
|
||||
nm->clrText = blend(nm->clrTextBk, r, g, b, a);
|
||||
}
|
||||
}
|
||||
// TODO draw background on image columns if needed
|
||||
ret = CDRF_SKIPDEFAULT | CDRF_NEWFONT;
|
||||
break;
|
||||
default:
|
||||
return CDRF_DODEFAULT;
|
||||
}
|
||||
|
||||
ZeroMemory(&dp, sizeof (uiprivSubitemDrawParams));
|
||||
hr = fillSubitemDrawParams(t, nm, &dp);
|
||||
if (hr != S_OK) {
|
||||
// TODO
|
||||
}
|
||||
hr = uiprivNM_CUSTOMDRAWImagesCheckboxes(t, nm, &dp);
|
||||
if (hr != S_OK) {
|
||||
// TODO
|
||||
}
|
||||
hr = uiprivNM_CUSTOMDRAWText(t, nm, p, &dp);
|
||||
if (hr != S_OK) {
|
||||
// TODO
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static BOOL onWM_NOTIFY(uiControl *c, HWND hwnd, NMHDR *nmhdr, LRESULT *lResult)
|
||||
{
|
||||
uiTable *t = uiTable(c);
|
||||
HRESULT hr;
|
||||
|
||||
switch (nmhdr->code) {
|
||||
case LVN_GETDISPINFO:
|
||||
*lResult = onLVN_GETDISPINFO(t, (NMLVDISPINFOW *) nmhdr);
|
||||
return TRUE;
|
||||
case NM_CUSTOMDRAW:
|
||||
*lResult = onNM_CUSTOMDRAW(t, (NMLVCUSTOMDRAW *) nmhdr);
|
||||
hr = uiprivTableHandleNM_CUSTOMDRAW(t, (NMLVCUSTOMDRAW *) nmhdr, lResult);
|
||||
if (hr != S_OK) {
|
||||
// TODO
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
|
|
|
@ -46,13 +46,14 @@ struct uiprivSubitemDrawParams {
|
|||
RECT icon;
|
||||
RECT label;
|
||||
};
|
||||
extern COLORREF uiprivTableBlendedColorFromModel(uiTable *t, NMLVCUSTOMDRAW *nm, int modelColumn, int fallbackSysColorID);
|
||||
|
||||
// tabletext.cpp
|
||||
extern HRESULT uiprivLVN_GETDISPINFOText(uiTable *t, NMLVDISPINFOW *nm, uiprivTableColumnParams *p);
|
||||
extern HRESULT uiprivNM_CUSTOMDRAWText(uiTable *t, NMLVCUSTOMDRAW *nm, uiprivTableColumnParams *p, uiprivSubitemDrawParams *dp);
|
||||
|
||||
// tableimages.cpp
|
||||
extern HRESULT uiprivLVN_GETDISPINFOImagesCheckboxes(uiTable *t, NMLVDISPINFOW *nm, uiprivTableColumnParams *p);
|
||||
extern HRESULT uiprivNM_CUSTOMDRAWImagesCheckboxes(uiTable *t, NMLVCUSTOMDRAW *nm, uiprivSubitemDrawParams *dp);
|
||||
extern HRESULT uiprivTableSetupImagesCheckboxes(uiTable *t);
|
||||
|
||||
// tabledraw.cpp
|
||||
extern HRESULT uiprivTableHandleNM_CUSTOMDRAW(uiTable *t, NMLVCUSTOMDRAW *nm, LRESULT *lResult);
|
||||
|
|
|
@ -17,10 +17,10 @@ struct drawState {
|
|||
|
||||
RECT itemBounds;
|
||||
RECT itemIcon;
|
||||
RECT itemText;
|
||||
RECT itemLabel;
|
||||
RECT subitemBounds;
|
||||
RECT subitemIcon;
|
||||
RECT subitemText;
|
||||
RECT subitemLabel;
|
||||
|
||||
COLORREF bgColor;
|
||||
HBRUSH bgBrush;
|
||||
|
@ -29,7 +29,7 @@ struct drawState {
|
|||
HBRUSH textBrush;
|
||||
BOOL freeTextBrush;
|
||||
|
||||
LRESULT bitmapMargins;
|
||||
LRESULT bitmapMargin;
|
||||
int cxIcon;
|
||||
int cyIcon;
|
||||
|
||||
|
@ -41,7 +41,7 @@ static HRESULT computeAndDrawTextRect(struct drawState *s)
|
|||
{
|
||||
RECT r;
|
||||
|
||||
r = s->subitemText;
|
||||
r = s->subitemLabel;
|
||||
if (!s->hasText && !s->hasImage)
|
||||
r = s->subitemBounds;
|
||||
|
||||
|
@ -104,11 +104,11 @@ static HRESULT drawTextPart(struct drawState *s)
|
|||
uiprivFree(wstr);
|
||||
|
||||
// TODO decide once and for all what to compare to here and with SelectObject()
|
||||
if (SetBkMode(nm->nmcd.hdc, prevMode) != TRANSPARENT) {
|
||||
if (SetBkMode(s->dc, prevMode) != TRANSPARENT) {
|
||||
logLastError(L"SetBkMode() prev");
|
||||
return E_FAIL;
|
||||
}
|
||||
if (SetTextColor(nm->nmcd.hdc, prevText) != color) {
|
||||
if (SetTextColor(s->dc, prevText) != s->textColor) {
|
||||
logLastError(L"SetTextColor() prev");
|
||||
return E_FAIL;
|
||||
}
|
||||
|
@ -120,21 +120,21 @@ static HRESULT freeDrawState(struct drawState *s)
|
|||
HRESULT hr, hrret;
|
||||
|
||||
hrret = S_OK;
|
||||
if (p->freeTextBrush) {
|
||||
if (DeleteObject(p->textBrush) == 0) {
|
||||
if (s->freeTextBrush) {
|
||||
if (DeleteObject(s->textBrush) == 0) {
|
||||
logLastError(L"DeleteObject()");
|
||||
hrret = E_FAIL;
|
||||
// continue cleaning up anyway
|
||||
}
|
||||
p->freeTextBrush = NO;
|
||||
s->freeTextBrush = FALSE;
|
||||
}
|
||||
if (p->freeBgBrush) {
|
||||
if (DeleteObject(p->bgBrush) == 0) {
|
||||
if (s->freeBgBrush) {
|
||||
if (DeleteObject(s->bgBrush) == 0) {
|
||||
logLastError(L"DeleteObject()");
|
||||
hrret = E_FAIL;
|
||||
// continue cleaning up anyway
|
||||
}
|
||||
p->freeBgBrush = NO;
|
||||
s->freeBgBrush = FALSE;
|
||||
}
|
||||
return hrret;
|
||||
}
|
||||
|
@ -153,6 +153,22 @@ static HRESULT itemRect(HRESULT hr, uiTable *t, UINT uMsg, WPARAM wParam, LONG l
|
|||
return S_OK;
|
||||
}
|
||||
|
||||
static COLORREF blend(COLORREF base, double r, double g, double b, double a)
|
||||
{
|
||||
double br, bg, bb;
|
||||
|
||||
br = ((double) GetRValue(base)) / 255.0;
|
||||
bg = ((double) GetGValue(base)) / 255.0;
|
||||
bb = ((double) GetBValue(base)) / 255.0;
|
||||
|
||||
br = (r * a) + (br * (1.0 - a));
|
||||
bg = (g * a) + (bg * (1.0 - a));
|
||||
bb = (b * a) + (bb * (1.0 - a));
|
||||
return RGB((BYTE) (br * 255),
|
||||
(BYTE) (bg * 255),
|
||||
(BYTE) (bb * 255));
|
||||
}
|
||||
|
||||
static HRESULT fillDrawState(struct drawState *s, uiTable *t, NMLVCUSTOMDRAW *nm, uiprivTableColumnParams *p)
|
||||
{
|
||||
LRESULT state;
|
||||
|
@ -172,19 +188,20 @@ static HRESULT fillDrawState(struct drawState *s, uiTable *t, NMLVCUSTOMDRAW *nm
|
|||
// nm->nmcd.uItemState CDIS_SELECTED is unreliable for the
|
||||
// listview configuration we have, so we must do this.
|
||||
state = SendMessageW(t->hwnd, LVM_GETITEMSTATE, nm->nmcd.dwItemSpec, LVIS_SELECTED);
|
||||
dp->selected = (state & LVIS_SELECTED) != 0;
|
||||
dp->focused = (nm->nmcd.uiTemState & CDIS_FOCUSED) != 0;
|
||||
s->selected = (state & LVIS_SELECTED) != 0;
|
||||
s->focused = (nm->nmcd.uItemState & CDIS_FOCUS) != 0;
|
||||
|
||||
hr = itemRect(S_OK, t, LVM_GETITEMRECT, LVIR_BOUNDS,
|
||||
0, &(s->itemBounds));
|
||||
hr = itemRect(hr, t, LVM_GETITEMRECT, LVIR_ICON,
|
||||
0, &(s->itemIcon));
|
||||
hr = itemRect(hr, t, LVM_GETITEMRECT, LVIR_LABEL,
|
||||
0, &(s->itemLabel));
|
||||
hr = itemRect(hr, t, LVM_GETSUBITEMRECT, LVIR_BOUNDS,
|
||||
s->iSubItem, &(s->subitemBounds));
|
||||
hr = itemRect(hr, t, LVM_GETSUBITEMRECT, LVIR_ICON,
|
||||
s->iSubItem, &(s->subitemIcon));
|
||||
// TODO check LRESULT bad parameters here
|
||||
hr = itemRect(S_OK, t, LVM_GETITEMRECT, s->iItem,
|
||||
LVIR_BOUNDS, 0, FALSE, &(s->itemBounds));
|
||||
hr = itemRect(hr, t, LVM_GETITEMRECT, s->iItem,
|
||||
LVIR_ICON, 0, FALSE, &(s->itemIcon));
|
||||
hr = itemRect(hr, t, LVM_GETITEMRECT, s->iItem,
|
||||
LVIR_LABEL, 0, FALSE, &(s->itemLabel));
|
||||
hr = itemRect(hr, t, LVM_GETSUBITEMRECT, s->iItem,
|
||||
LVIR_BOUNDS, s->iSubItem, 0, &(s->subitemBounds));
|
||||
hr = itemRect(hr, t, LVM_GETSUBITEMRECT, s->iItem,
|
||||
LVIR_ICON, s->iSubItem, 0, &(s->subitemIcon));
|
||||
if (hr != S_OK)
|
||||
goto fail;
|
||||
// LVM_GETSUBITEMRECT treats LVIR_LABEL as the same as
|
||||
|
@ -194,6 +211,12 @@ static HRESULT fillDrawState(struct drawState *s, uiTable *t, NMLVCUSTOMDRAW *nm
|
|||
// above.
|
||||
s->subitemLabel = s->subitemBounds;
|
||||
s->subitemLabel.left = s->subitemIcon.right;
|
||||
// And on iSubItem == 0, LVIF_GETSUBITEMRECT still includes
|
||||
// all the subitems, which we don't want.
|
||||
if (s->iSubItem == 0) {
|
||||
s->subitemBounds.right = s->itemLabel.right;
|
||||
s->subitemLabel.right = s->itemLabel.right;
|
||||
}
|
||||
|
||||
if (s->selected) {
|
||||
s->bgColor = GetSysColor(COLOR_HIGHLIGHT);
|
||||
|
@ -202,6 +225,7 @@ static HRESULT fillDrawState(struct drawState *s, uiTable *t, NMLVCUSTOMDRAW *nm
|
|||
s->textBrush = GetSysColorBrush(COLOR_HIGHLIGHTTEXT);
|
||||
} else {
|
||||
uiTableData *data;
|
||||
double r, g, b, a;
|
||||
|
||||
s->bgColor = GetSysColor(COLOR_WINDOW);
|
||||
s->bgBrush = GetSysColorBrush(COLOR_WINDOW);
|
||||
|
@ -211,7 +235,7 @@ static HRESULT fillDrawState(struct drawState *s, uiTable *t, NMLVCUSTOMDRAW *nm
|
|||
uiTableDataColor(data, &r, &g, &b, &a);
|
||||
uiFreeTableData(data);
|
||||
s->bgColor = blend(s->bgColor, r, g, b, a);
|
||||
s->bgBrush = CreateSolidBrush(s->bgBrush);
|
||||
s->bgBrush = CreateSolidBrush(s->bgColor);
|
||||
if (s->bgBrush == NULL) {
|
||||
logLastError(L"CreateSolidBrush()");
|
||||
hr = E_FAIL;
|
||||
|
@ -249,3 +273,44 @@ fail:
|
|||
freeDrawState(s);
|
||||
return hr;
|
||||
}
|
||||
|
||||
HRESULT uiprivTableHandleNM_CUSTOMDRAW(uiTable *t, NMLVCUSTOMDRAW *nm, LRESULT *lResult)
|
||||
{
|
||||
struct drawState s;
|
||||
uiprivTableColumnParams *p;
|
||||
HRESULT hr;
|
||||
|
||||
switch (nm->nmcd.dwDrawStage) {
|
||||
case CDDS_PREPAINT:
|
||||
*lResult = CDRF_NOTIFYITEMDRAW;
|
||||
return S_OK;
|
||||
case CDDS_ITEMPREPAINT:
|
||||
*lResult = CDRF_NOTIFYSUBITEMDRAW;
|
||||
return S_OK;
|
||||
case CDDS_SUBITEM | CDDS_ITEMPREPAINT:
|
||||
break;
|
||||
default:
|
||||
*lResult = CDRF_DODEFAULT;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
p = (*(t->columns))[nm->iSubItem];
|
||||
hr = fillDrawState(&s, t, nm, p);
|
||||
if (hr != S_OK)
|
||||
return hr;
|
||||
hr = computeAndDrawTextRect(&s);
|
||||
if (hr != S_OK)
|
||||
goto fail;
|
||||
hr = drawTextPart(&s);
|
||||
if (hr != S_OK)
|
||||
goto fail;
|
||||
hr = freeDrawState(&s);
|
||||
if (hr != S_OK) // TODO really error out here?
|
||||
return hr;
|
||||
*lResult = CDRF_SKIPDEFAULT;
|
||||
return S_OK;
|
||||
fail:
|
||||
// ignore error here
|
||||
freeDrawState(&s);
|
||||
return hr;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue