I know I said the last one was the end of the rectangle work, but I do get ideas while I sleep... :) ChangeLog Factor out the computation of item position, so it can be used idependently of the rectagles. --- dlls/comctl32/listview.c.M2 Tue Oct 8 01:55:47 2002 +++ dlls/comctl32/listview.c Tue Oct 8 09:34:54 2002 @@ -1247,6 +1247,49 @@ FIXME(" LVS_SORTDESCENDING\n"); } + +/*** + * DESCRIPTION: [INTERNAL] + * Computes an item's (left,top) corner, relative to rcView. + * That is, the position has NOT been made relative to the Origin. + * This is deliberate, to avoid computing the Origin over, and + * over again, when this function is call in a loop. Instead, + * one ca factor the computation of the Origin before the loop, + * and offset the value retured by this function, on every iteration. + * + * PARAMETER(S): + * [I] infoPtr : valid pointer to the listview structure + * [I] nItem : item number + * [O] lpptOrig : item top, left corner + * + * RETURN: + * TRUE if computations OK + * FALSE otherwise + */ +static BOOL LISTVIEW_GetItemListOrigin(LISTVIEW_INFO *infoPtr, INT nItem, LPPOINT lpptPosition) +{ + UINT uView = infoPtr->dwStyle & LVS_TYPEMASK; + + if ((uView == LVS_SMALLICON) || (uView == LVS_ICON)) + { + lpptPosition->x = (LONG)DPA_GetPtr(infoPtr->hdpaPosX, nItem); + lpptPosition->y = (LONG)DPA_GetPtr(infoPtr->hdpaPosY, nItem); + } + else if (uView == LVS_LIST) + { + INT nCountPerColumn = LISTVIEW_GetCountPerColumn(infoPtr); + lpptPosition->x = nItem / nCountPerColumn * infoPtr->nItemWidth; + lpptPosition->y = nItem % nCountPerColumn * infoPtr->nItemHeight; + } + else /* LVS_REPORT */ + { + lpptPosition->x = REPORT_MARGINX; + lpptPosition->y = nItem * infoPtr->nItemHeight; + } + + return TRUE; +} + /*** * DESCRIPTION: [INTERNAL] * Compute the rectangles of an item. This is to localize all @@ -1288,12 +1331,9 @@ BOOL doIcon = FALSE, doLabel = FALSE, oversizedBox = FALSE; WCHAR szDispText[DISP_TEXT_SIZE] = { '\0' }; RECT Box, Icon, Label; - POINT Origin; + POINT Position, Origin; LVITEMW lvItem; - /* This should be very cheap to compute */ - if (!LISTVIEW_GetOrigin(infoPtr, &Origin)) return FALSE; - /* Be smart and try to figure out the minimum we have to do */ if (lprcBounds) { @@ -1306,30 +1346,6 @@ if (lprcLabel) doLabel = TRUE; if (doLabel || lprcIcon) doIcon = TRUE; - /************************************************************/ - /* compute the box rectangle (it should be cheap to do) */ - /************************************************************/ - if ((uView == LVS_SMALLICON) || (uView == LVS_ICON)) - { - Box.left = (LONG)DPA_GetPtr(infoPtr->hdpaPosX, nItem); - Box.top = (LONG)DPA_GetPtr(infoPtr->hdpaPosY, nItem); - } - else if (uView == LVS_LIST) - { - INT nCountPerColumn = LISTVIEW_GetCountPerColumn(infoPtr); - Box.left = nItem / nCountPerColumn * infoPtr->nItemWidth; - Box.top = nItem % nCountPerColumn * infoPtr->nItemHeight; - } - else /* LVS_REPORT */ - { - Box.left = REPORT_MARGINX; - Box.top = nItem * infoPtr->nItemHeight; - } - Box.left += Origin.x; - Box.top += Origin.y; - Box.right = Box.left + infoPtr->nItemWidth; - Box.bottom = Box.top + infoPtr->nItemHeight; - /* get what we need from the item before hand, so we make * only one request. This can speed up things, if data * is stored on the app side */ @@ -1346,6 +1362,16 @@ } /************************************************************/ + /* compute the box rectangle (it should be cheap to do) */ + /************************************************************/ + if (!LISTVIEW_GetItemListOrigin(infoPtr, nItem, &Position)) return FALSE; + if (!LISTVIEW_GetOrigin(infoPtr, &Origin)) return FALSE; + Box.left = Position.x + Origin.x; + Box.top = Position.y + Origin.y; + Box.right = Box.left + infoPtr->nItemWidth; + Box.bottom = Box.top + infoPtr->nItemHeight; + + /************************************************************/ /* compute ICON bounding box (ala LVM_GETITEMRECT) */ /************************************************************/ if (doIcon) @@ -4958,22 +4984,21 @@ static BOOL LISTVIEW_GetItemPosition(LISTVIEW_INFO *infoPtr, INT nItem, LPPOINT lpptPosition) { UINT uView = infoPtr->dwStyle & LVS_TYPEMASK; - RECT Box; + POINT Origin; TRACE("(nItem=%d, lpptPosition=%p)\n", nItem, lpptPosition); if (!lpptPosition || nItem < 0 || nItem >= infoPtr->nItemCount) return FALSE; + if (!LISTVIEW_GetItemListOrigin(infoPtr, nItem, lpptPosition)) return FALSE; + if (!LISTVIEW_GetOrigin(infoPtr, &Origin)) return FALSE; - /* These should be very cheap to compute */ - if (!LISTVIEW_GetItemMeasures(infoPtr, nItem, &Box, NULL, NULL, NULL)) return FALSE; - - lpptPosition->x = Box.left; - lpptPosition->y = Box.top; if (uView == LVS_ICON) { lpptPosition->x += (infoPtr->iconSpacing.cx - infoPtr->iconSize.cx) / 2; lpptPosition->y += ICON_TOP_PADDING; } + lpptPosition->x += Origin.x; + lpptPosition->y += Origin.y; TRACE (" lpptPosition=%s\n", debugpoint(lpptPosition)); return TRUE;