Commit 71be0944 authored by Vitaliy Margolen's avatar Vitaliy Margolen Committed by Alexandre Julliard

Don't redraw if no information has changed.

Fixed endless redraw loop if app using callback for images and/or text. Keep color changes made by app for the current draw cycle.
parent a8d8b52d
......@@ -241,6 +241,39 @@ TREEVIEW_GetItemIndex(TREEVIEW_INFO *infoPtr, HTREEITEM handle)
return DPA_GetPtrIndex(infoPtr->items, handle);
}
/* Checks if item has changed and needs to be redrawn */
static inline BOOL item_changed (TREEVIEW_ITEM *tiOld, TREEVIEW_ITEM *tiNew, LPTVITEMEXW tvChange)
{
/* Number of children has changed */
if ((tvChange->mask & TVIF_CHILDREN) && (tiOld->cChildren != tiNew->cChildren))
return TRUE;
/* Image has changed and it's not a callback */
if ((tvChange->mask & TVIF_IMAGE) && (tiOld->iImage != tiNew->iImage) &&
tiNew->iImage != I_IMAGECALLBACK)
return TRUE;
/* Selected image has changed and it's not a callback */
if ((tvChange->mask & TVIF_SELECTEDIMAGE) && (tiOld->iSelectedImage != tiNew->iSelectedImage) &&
tiNew->iSelectedImage != I_IMAGECALLBACK)
return TRUE;
/* Text has changed and it's not a callback */
if ((tvChange->mask & TVIF_TEXT) && (tiOld->pszText != tiNew->pszText) &&
tiNew->pszText != LPSTR_TEXTCALLBACKW)
return TRUE;
/* Indent has changed */
if ((tvChange->mask & TVIF_INTEGRAL) && (tiOld->iIntegral != tiNew->iIntegral))
return TRUE;
/* Item state has changed */
if ((tvChange->mask & TVIF_STATE) && ((tiOld->state ^ tiNew->state) & tvChange->stateMask ))
return TRUE;
return FALSE;
}
/***************************************************************************
* This method checks that handle is an item for this tree.
*/
......@@ -616,10 +649,10 @@ TREEVIEW_SendCustomDrawNotify(TREEVIEW_INFO *infoPtr, DWORD dwDrawStage,
static BOOL
TREEVIEW_SendCustomDrawItemNotify(TREEVIEW_INFO *infoPtr, HDC hdc,
TREEVIEW_ITEM *wineItem, UINT uItemDrawState)
TREEVIEW_ITEM *wineItem, UINT uItemDrawState,
NMTVCUSTOMDRAW *nmcdhdr)
{
HWND hwnd = infoPtr->hwnd;
NMTVCUSTOMDRAW nmcdhdr;
LPNMCUSTOMDRAW nmcd;
DWORD dwDrawStage, dwItemSpec;
UINT uItemState;
......@@ -635,7 +668,7 @@ TREEVIEW_SendCustomDrawItemNotify(TREEVIEW_INFO *infoPtr, HDC hdc,
if (wineItem == infoPtr->hotItem)
uItemState |= CDIS_HOT;
nmcd = &nmcdhdr.nmcd;
nmcd = &nmcdhdr->nmcd;
nmcd->hdr.hwndFrom = hwnd;
nmcd->hdr.idFrom = GetWindowLongPtrW(hwnd, GWLP_ID);
nmcd->hdr.code = NM_CUSTOMDRAW;
......@@ -645,9 +678,7 @@ TREEVIEW_SendCustomDrawItemNotify(TREEVIEW_INFO *infoPtr, HDC hdc,
nmcd->dwItemSpec = dwItemSpec;
nmcd->uItemState = uItemState;
nmcd->lItemlParam = wineItem->lParam;
nmcdhdr.clrText = infoPtr->clrText;
nmcdhdr.clrTextBk = infoPtr->clrBk;
nmcdhdr.iLevel = wineItem->iLevel;
nmcdhdr->iLevel = wineItem->iLevel;
TRACE("drawstage:%lx hdc:%p item:%lx, itemstate:%x, lItemlParam:%lx\n",
nmcd->dwDrawStage, nmcd->hdc, nmcd->dwItemSpec,
......@@ -655,7 +686,7 @@ TREEVIEW_SendCustomDrawItemNotify(TREEVIEW_INFO *infoPtr, HDC hdc,
retval = TREEVIEW_SendRealNotify(infoPtr,
(WPARAM)nmcd->hdr.idFrom,
(LPARAM)&nmcdhdr);
(LPARAM)nmcdhdr);
return (BOOL)retval;
}
......@@ -2114,9 +2145,8 @@ TREEVIEW_SetItemT(TREEVIEW_INFO *infoPtr, LPTVITEMEXW tvItem, BOOL isW)
/* The refresh updates everything, but we can't wait until then. */
TREEVIEW_ComputeItemInternalMetrics(infoPtr, wineItem);
/* if any of the items values changed, redraw the item */
if(memcmp(&originalItem, wineItem, sizeof(TREEVIEW_ITEM)) ||
(tvItem->stateMask & TVIS_BOLD))
/* if any of the item's values changed and it's not a callback, redraw the item */
if (item_changed(&originalItem, wineItem, tvItem))
{
if (tvItem->mask & TVIF_INTEGRAL)
{
......@@ -2265,10 +2295,14 @@ TREEVIEW_DrawItemLines(TREEVIEW_INFO *infoPtr, HDC hdc, TREEVIEW_ITEM *item)
BOOL lar = ((infoPtr->dwStyle
& (TVS_LINESATROOT|TVS_HASLINES|TVS_HASBUTTONS))
> TVS_LINESATROOT);
HBRUSH hbr, hbrOld;
if (!lar && item->iLevel == 0)
return;
hbr = CreateSolidBrush(infoPtr->clrBk);
hbrOld = SelectObject(hdc, hbr);
centerx = (item->linesOffset + item->stateOffset) / 2;
centery = (item->rect.top + item->rect.bottom) / 2;
......@@ -2335,15 +2369,10 @@ TREEVIEW_DrawItemLines(TREEVIEW_INFO *infoPtr, HDC hdc, TREEVIEW_ITEM *item)
HPEN hNewPen = CreatePen(PS_SOLID, 0, infoPtr->clrLine);
HPEN hOldPen = SelectObject(hdc, hNewPen);
HBRUSH hbr = CreateSolidBrush(infoPtr->clrBk);
HBRUSH hbrOld = SelectObject(hdc, hbr);
Rectangle(hdc, centerx - rectsize - 1, centery - rectsize - 1,
centerx + rectsize + 2, centery + rectsize + 2);
SelectObject(hdc, hbrOld);
DeleteObject(hbr);
SelectObject(hdc, hOldPen);
DeleteObject(hNewPen);
......@@ -2373,6 +2402,8 @@ TREEVIEW_DrawItemLines(TREEVIEW_INFO *infoPtr, HDC hdc, TREEVIEW_ITEM *item)
}
}
}
SelectObject(hdc, hbrOld);
DeleteObject(hbr);
}
static void
......@@ -2380,12 +2411,50 @@ TREEVIEW_DrawItem(TREEVIEW_INFO *infoPtr, HDC hdc, TREEVIEW_ITEM *wineItem)
{
INT cditem;
HFONT hOldFont;
COLORREF oldTextColor, oldTextBkColor;
int centery;
hOldFont = SelectObject(hdc, TREEVIEW_FontForItem(infoPtr, wineItem));
BOOL inFocus = (GetFocus() == infoPtr->hwnd);
NMTVCUSTOMDRAW nmcdhdr;
TREEVIEW_UpdateDispInfo(infoPtr, wineItem, CALLBACK_MASK_ALL);
/* - If item is drop target or it is selected and window is in focus -
* use blue background (COLOR_HIGHLIGHT).
* - If item is selected, window is not in focus, but it has style
* TVS_SHOWSELALWAYS - use grey background (COLOR_BTNFACE)
* - Otherwise - use background color
*/
if ((wineItem->state & TVIS_DROPHILITED) || ((wineItem == infoPtr->focusedItem) && !(wineItem->state & TVIS_SELECTED)) ||
((wineItem->state & TVIS_SELECTED) && (!infoPtr->focusedItem) &&
(inFocus || (infoPtr->dwStyle & TVS_SHOWSELALWAYS))))
{
if ((wineItem->state & TVIS_DROPHILITED) || inFocus)
{
nmcdhdr.clrTextBk = GetSysColor(COLOR_HIGHLIGHT);
nmcdhdr.clrText = GetSysColor(COLOR_HIGHLIGHTTEXT);
}
else
{
nmcdhdr.clrTextBk = GetSysColor(COLOR_BTNFACE);
if (infoPtr->clrText == -1)
nmcdhdr.clrText = GetSysColor(COLOR_WINDOWTEXT);
else
nmcdhdr.clrText = infoPtr->clrText;
}
}
else
{
nmcdhdr.clrTextBk = infoPtr->clrBk;
if ((infoPtr->dwStyle & TVS_TRACKSELECT) && (wineItem == infoPtr->hotItem))
nmcdhdr.clrText = comctl32_color.clrHighlight;
else if (infoPtr->clrText == -1)
nmcdhdr.clrText = GetSysColor(COLOR_WINDOWTEXT);
else
nmcdhdr.clrText = infoPtr->clrText;
}
hOldFont = SelectObject(hdc, TREEVIEW_FontForItem(infoPtr, wineItem));
/* The custom draw handler can query the text rectangle,
* so get ready. */
/* should already be known, set to 0 when changed */
......@@ -2397,7 +2466,7 @@ TREEVIEW_DrawItem(TREEVIEW_INFO *infoPtr, HDC hdc, TREEVIEW_ITEM *wineItem)
if (infoPtr->cdmode & CDRF_NOTIFYITEMDRAW)
{
cditem = TREEVIEW_SendCustomDrawItemNotify
(infoPtr, hdc, wineItem, CDDS_ITEMPREPAINT);
(infoPtr, hdc, wineItem, CDDS_ITEMPREPAINT, &nmcdhdr);
TRACE("prepaint:cditem-app returns 0x%x\n", cditem);
if (cditem & CDRF_SKIPDEFAULT)
......@@ -2412,6 +2481,10 @@ TREEVIEW_DrawItem(TREEVIEW_INFO *infoPtr, HDC hdc, TREEVIEW_ITEM *wineItem)
TREEVIEW_DrawItemLines(infoPtr, hdc, wineItem);
/* Set colors. Custom draw handler can change these so we do this after it. */
oldTextColor = SetTextColor(hdc, nmcdhdr.clrText);
oldTextBkColor = SetBkColor(hdc, nmcdhdr.clrTextBk);
centery = (wineItem->rect.top + wineItem->rect.bottom) / 2;
/*
......@@ -2469,87 +2542,31 @@ TREEVIEW_DrawItem(TREEVIEW_INFO *infoPtr, HDC hdc, TREEVIEW_ITEM *wineItem)
{
if (wineItem->pszText)
{
COLORREF oldTextColor = 0;
INT oldBkMode;
HBRUSH hbrBk = 0;
BOOL inFocus = (GetFocus() == infoPtr->hwnd);
RECT rcText;
oldBkMode = SetBkMode(hdc, TRANSPARENT);
/* - If item is drop target or it is selected and window is in focus -
* use blue background (COLOR_HIGHLIGHT).
* - If item is selected, window is not in focus, but it has style
* TVS_SHOWSELALWAYS - use grey background (COLOR_BTNFACE)
* - Otherwise - don't fill background
*/
if ((wineItem->state & TVIS_DROPHILITED) || ((wineItem == infoPtr->focusedItem) && !(wineItem->state & TVIS_SELECTED)) ||
((wineItem->state & TVIS_SELECTED) && (!infoPtr->focusedItem) &&
(inFocus || (infoPtr->dwStyle & TVS_SHOWSELALWAYS))))
{
if ((wineItem->state & TVIS_DROPHILITED) || inFocus)
{
hbrBk = CreateSolidBrush(GetSysColor(COLOR_HIGHLIGHT));
oldTextColor =
SetTextColor(hdc, GetSysColor(COLOR_HIGHLIGHTTEXT));
}
else
{
hbrBk = CreateSolidBrush(GetSysColor(COLOR_BTNFACE));
if (infoPtr->clrText == -1)
oldTextColor =
SetTextColor(hdc, GetSysColor(COLOR_WINDOWTEXT));
else
oldTextColor = SetTextColor(hdc, infoPtr->clrText);
}
}
else
{
if ((infoPtr->dwStyle & TVS_TRACKSELECT) && (wineItem == infoPtr->hotItem))
oldTextColor = SetTextColor(hdc, comctl32_color.clrHighlight);
else if (infoPtr->clrText == -1)
oldTextColor =
SetTextColor(hdc, GetSysColor(COLOR_WINDOWTEXT));
else
oldTextColor = SetTextColor(hdc, infoPtr->clrText);
}
rcText.top = wineItem->rect.top;
rcText.bottom = wineItem->rect.bottom;
rcText.left = wineItem->textOffset;
rcText.right = rcText.left + wineItem->textWidth + 4;
if (hbrBk)
{
FillRect(hdc, &rcText, hbrBk);
DeleteObject(hbrBk);
}
/* Draw the box around the selected item */
if ((wineItem == infoPtr->selectedItem) && inFocus)
{
DrawFocusRect(hdc,&rcText);
}
InflateRect(&rcText, -2, -1); /* allow for the focus rect */
TRACE("drawing text %s at (%ld,%ld)-(%ld,%ld)\n",
debugstr_w(wineItem->pszText),
rcText.left, rcText.top, rcText.right, rcText.bottom);
/* Draw it */
DrawTextW(hdc,
ExtTextOutW(hdc, rcText.left + 2, rcText.top + 1,
ETO_CLIPPED | ETO_OPAQUE,
&rcText,
wineItem->pszText,
lstrlenW(wineItem->pszText),
&rcText,
DT_CENTER | DT_VCENTER | DT_SINGLELINE | DT_NOPREFIX);
NULL);
/* Restore the hdc state */
SetTextColor(hdc, oldTextColor);
/* Draw the box around the selected item */
if ((wineItem == infoPtr->selectedItem) && inFocus)
{
DrawFocusRect(hdc,&rcText);
}
if (oldBkMode != TRANSPARENT)
SetBkMode(hdc, oldBkMode);
}
}
......@@ -2593,10 +2610,13 @@ TREEVIEW_DrawItem(TREEVIEW_INFO *infoPtr, HDC hdc, TREEVIEW_ITEM *wineItem)
if (cditem & CDRF_NOTIFYPOSTPAINT)
{
cditem = TREEVIEW_SendCustomDrawItemNotify
(infoPtr, hdc, wineItem, CDDS_ITEMPOSTPAINT);
(infoPtr, hdc, wineItem, CDDS_ITEMPOSTPAINT, &nmcdhdr);
TRACE("postpaint:cditem-app returns 0x%x\n", cditem);
}
/* Restore the hdc state */
SetTextColor(hdc, oldTextColor);
SetBkColor(hdc, oldTextBkColor);
SelectObject(hdc, hOldFont);
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment