Separate item metrics computation from positioning
Add support for computing state icon metrics.
This commit is contained in:
parent
65442cd763
commit
f1f447931e
|
@ -1378,11 +1378,13 @@ static BOOL LISTVIEW_GetItemListOrigin(LISTVIEW_INFO *infoPtr, INT nItem, LPPOIN
|
||||||
*
|
*
|
||||||
* PARAMETER(S):
|
* PARAMETER(S):
|
||||||
* [I] infoPtr : valid pointer to the listview structure
|
* [I] infoPtr : valid pointer to the listview structure
|
||||||
* [I] nItem : item number
|
* [I] lpLVItem : item to compute the measures for
|
||||||
* [O] lprcBox : ptr to Box rectangle
|
* [O] lprcBox : ptr to Box rectangle
|
||||||
* The internal LVIR_BOX rectangle
|
* The internal LVIR_BOX rectangle
|
||||||
* [O] lprcBounds : ptr to Bounds rectangle
|
* [O] lprcBounds : ptr to Bounds rectangle
|
||||||
* Same as LVM_GETITEMRECT with LVIR_BOUNDS
|
* Same as LVM_GETITEMRECT with LVIR_BOUNDS
|
||||||
|
* [0] lprcState : ptr to State icon rectangle
|
||||||
|
* The internal LVIR_STATE rectangle
|
||||||
* [O] lprcIcon : ptr to Icon rectangle
|
* [O] lprcIcon : ptr to Icon rectangle
|
||||||
* Same as LVM_GETITEMRECT with LVIR_ICON
|
* Same as LVM_GETITEMRECT with LVIR_ICON
|
||||||
* [O] lprcLabel : ptr to Label rectangle
|
* [O] lprcLabel : ptr to Label rectangle
|
||||||
|
@ -1392,54 +1394,73 @@ static BOOL LISTVIEW_GetItemListOrigin(LISTVIEW_INFO *infoPtr, INT nItem, LPPOIN
|
||||||
* TRUE if computations OK
|
* TRUE if computations OK
|
||||||
* FALSE otherwise
|
* FALSE otherwise
|
||||||
*/
|
*/
|
||||||
static BOOL LISTVIEW_GetItemMeasures(LISTVIEW_INFO *infoPtr, INT nItem,
|
static BOOL LISTVIEW_GetItemMetrics(LISTVIEW_INFO *infoPtr, LVITEMW *lpLVItem,
|
||||||
LPRECT lprcBox, LPRECT lprcBounds,
|
LPRECT lprcBox, LPRECT lprcBounds,
|
||||||
LPRECT lprcIcon, LPRECT lprcLabel)
|
LPRECT lprcState, LPRECT lprcIcon, LPRECT lprcLabel)
|
||||||
{
|
{
|
||||||
UINT uView = infoPtr->dwStyle & LVS_TYPEMASK;
|
UINT uView = infoPtr->dwStyle & LVS_TYPEMASK;
|
||||||
BOOL doIcon = FALSE, doLabel = FALSE, oversizedBox = FALSE;
|
BOOL doState = FALSE, doIcon = FALSE, doLabel = FALSE, oversizedBox = FALSE;
|
||||||
WCHAR szDispText[DISP_TEXT_SIZE] = { '\0' };
|
RECT Box, State, Icon, Label;
|
||||||
RECT Box, Icon, Label;
|
|
||||||
POINT Position, Origin;
|
|
||||||
LVITEMW lvItem;
|
|
||||||
|
|
||||||
|
ERR("(lpLVItem=%s)\n", debuglvitem_t(lpLVItem, TRUE));
|
||||||
|
|
||||||
/* Be smart and try to figure out the minimum we have to do */
|
/* Be smart and try to figure out the minimum we have to do */
|
||||||
if (lprcBounds)
|
if (lprcBounds)
|
||||||
{
|
{
|
||||||
if (uView == LVS_REPORT) doIcon = TRUE;
|
if (uView == LVS_REPORT) doIcon = TRUE;
|
||||||
else doLabel = TRUE;
|
else doLabel = TRUE;
|
||||||
}
|
}
|
||||||
if (uView == LVS_ICON && infoPtr->bFocus &&
|
if (uView == LVS_ICON && (lprcBox || lprcBounds || lprcLabel))
|
||||||
!(infoPtr->dwStyle & LVS_OWNERDRAWFIXED) &&
|
{
|
||||||
LISTVIEW_GetItemState(infoPtr, nItem, LVIS_FOCUSED))
|
if (!(lpLVItem->mask & LVIF_STATE) ||
|
||||||
oversizedBox = doLabel = TRUE;
|
!(lpLVItem->stateMask & LVIS_FOCUSED))
|
||||||
|
return FALSE;
|
||||||
|
if ((lpLVItem->state & LVIS_FOCUSED) &&
|
||||||
|
!(infoPtr->dwStyle & LVS_OWNERDRAWFIXED))
|
||||||
|
oversizedBox = doLabel = TRUE;
|
||||||
|
}
|
||||||
if (lprcLabel) doLabel = TRUE;
|
if (lprcLabel) doLabel = TRUE;
|
||||||
if (doLabel || lprcIcon) doIcon = TRUE;
|
if (doLabel || lprcIcon) doIcon = TRUE;
|
||||||
|
if (doIcon || lprcState) doState = TRUE;
|
||||||
|
|
||||||
/* 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 */
|
|
||||||
if (doLabel || (doIcon && uView == LVS_REPORT))
|
|
||||||
{
|
|
||||||
lvItem.mask = 0;
|
|
||||||
if (doIcon) lvItem.mask |= LVIF_INDENT;
|
|
||||||
if (doLabel) lvItem.mask |= LVIF_TEXT;
|
|
||||||
lvItem.iItem = nItem;
|
|
||||||
lvItem.iSubItem = 0;
|
|
||||||
lvItem.pszText = szDispText;
|
|
||||||
lvItem.cchTextMax = DISP_TEXT_SIZE;
|
|
||||||
if (!LISTVIEW_GetItemW(infoPtr, &lvItem)) return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/************************************************************/
|
/************************************************************/
|
||||||
/* compute the box rectangle (it should be cheap to do) */
|
/* compute the box rectangle (it should be cheap to do) */
|
||||||
/************************************************************/
|
/************************************************************/
|
||||||
if (!LISTVIEW_GetItemListOrigin(infoPtr, nItem, &Position)) return FALSE;
|
Box.left = 0;
|
||||||
if (!LISTVIEW_GetOrigin(infoPtr, &Origin)) return FALSE;
|
Box.top = 0;
|
||||||
Box.left = Position.x + Origin.x;
|
Box.right = infoPtr->nItemWidth;
|
||||||
Box.top = Position.y + Origin.y;
|
Box.bottom = infoPtr->nItemHeight;
|
||||||
Box.right = Box.left + infoPtr->nItemWidth;
|
|
||||||
Box.bottom = Box.top + infoPtr->nItemHeight;
|
/************************************************************/
|
||||||
|
/* compute STATEICON bounding box */
|
||||||
|
/************************************************************/
|
||||||
|
if (doState)
|
||||||
|
{
|
||||||
|
if (uView == LVS_ICON)
|
||||||
|
{
|
||||||
|
State.left = Box.left - infoPtr->iconStateSize.cx + 10;
|
||||||
|
if (infoPtr->himlNormal)
|
||||||
|
State.left += (infoPtr->iconSpacing.cx - infoPtr->iconSize.cx) / 2 - ICON_LR_HALF;
|
||||||
|
State.top = Box.top + infoPtr->iconSize.cy - infoPtr->iconStateSize.cy + 4;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* we need the ident in report mode, if we don't have it, we fail */
|
||||||
|
if (uView == LVS_REPORT && !(lpLVItem->mask & LVIF_INDENT)) return FALSE;
|
||||||
|
State.left = Box.left;
|
||||||
|
if (uView == LVS_REPORT) State.left += infoPtr->iconSize.cx * lpLVItem->iIndent;
|
||||||
|
State.top = Box.top;
|
||||||
|
}
|
||||||
|
State.right = State.left;
|
||||||
|
State.bottom = State.top;
|
||||||
|
if (infoPtr->himlState)
|
||||||
|
{
|
||||||
|
State.right += infoPtr->iconStateSize.cx;
|
||||||
|
State.bottom += infoPtr->iconStateSize.cy;
|
||||||
|
}
|
||||||
|
if (lprcState) *lprcState = State;
|
||||||
|
TRACE(" - state=%s\n", debugrect(&State));
|
||||||
|
}
|
||||||
|
|
||||||
/************************************************************/
|
/************************************************************/
|
||||||
/* compute ICON bounding box (ala LVM_GETITEMRECT) */
|
/* compute ICON bounding box (ala LVM_GETITEMRECT) */
|
||||||
|
@ -1462,17 +1483,15 @@ static BOOL LISTVIEW_GetItemMeasures(LISTVIEW_INFO *infoPtr, INT nItem,
|
||||||
}
|
}
|
||||||
else /* LVS_SMALLICON, LVS_LIST or LVS_REPORT */
|
else /* LVS_SMALLICON, LVS_LIST or LVS_REPORT */
|
||||||
{
|
{
|
||||||
/* do indent */
|
Icon.left = State.right;
|
||||||
Icon.left = Box.left;
|
if (infoPtr->himlState) Icon.left += IMAGE_PADDING;
|
||||||
if (uView == LVS_REPORT) Icon.left += infoPtr->iconSize.cx * lvItem.iIndent;
|
|
||||||
if (infoPtr->himlState) Icon.left += infoPtr->iconStateSize.cx;
|
|
||||||
Icon.top = Box.top;
|
Icon.top = Box.top;
|
||||||
Icon.right = Icon.left;
|
Icon.right = Icon.left;
|
||||||
if (infoPtr->himlSmall) Icon.right += infoPtr->iconSize.cx;
|
if (infoPtr->himlSmall) Icon.right += infoPtr->iconSize.cx;
|
||||||
Icon.bottom = Icon.top + infoPtr->nItemHeight;
|
Icon.bottom = Icon.top + infoPtr->nItemHeight;
|
||||||
}
|
}
|
||||||
if(lprcIcon) *lprcIcon = Icon;
|
if(lprcIcon) *lprcIcon = Icon;
|
||||||
TRACE("hwnd=%x, item=%d, icon=%s\n", infoPtr->hwndSelf, nItem, debugrect(&Icon));
|
TRACE(" - icon=%s\n", debugrect(&Icon));
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************/
|
/************************************************************/
|
||||||
|
@ -1481,13 +1500,16 @@ static BOOL LISTVIEW_GetItemMeasures(LISTVIEW_INFO *infoPtr, INT nItem,
|
||||||
if (doLabel)
|
if (doLabel)
|
||||||
{
|
{
|
||||||
SIZE labelSize = { 0, 0 };
|
SIZE labelSize = { 0, 0 };
|
||||||
|
|
||||||
|
/* we need the text in non owner draw mode */
|
||||||
|
if (!(infoPtr->dwStyle & LVS_OWNERDRAWFIXED) && !(lpLVItem->mask & LVIF_TEXT)) return FALSE;
|
||||||
|
|
||||||
if (infoPtr->dwStyle & LVS_OWNERDRAWFIXED)
|
if (infoPtr->dwStyle & LVS_OWNERDRAWFIXED)
|
||||||
{
|
{
|
||||||
labelSize.cx = infoPtr->nItemWidth;
|
labelSize.cx = infoPtr->nItemWidth;
|
||||||
labelSize.cy = infoPtr->nItemHeight;
|
labelSize.cy = infoPtr->nItemHeight;
|
||||||
}
|
}
|
||||||
else if (is_textT(lvItem.pszText, TRUE))
|
else if (is_textT(lpLVItem->pszText, TRUE))
|
||||||
{
|
{
|
||||||
HFONT hFont = infoPtr->hFont ? infoPtr->hFont : infoPtr->hDefaultFont;
|
HFONT hFont = infoPtr->hFont ? infoPtr->hFont : infoPtr->hDefaultFont;
|
||||||
HDC hdc = GetDC(infoPtr->hwndSelf);
|
HDC hdc = GetDC(infoPtr->hwndSelf);
|
||||||
|
@ -1508,7 +1530,7 @@ static BOOL LISTVIEW_GetItemMeasures(LISTVIEW_INFO *infoPtr, INT nItem,
|
||||||
else
|
else
|
||||||
uFormat = LV_SL_DT_FLAGS;
|
uFormat = LV_SL_DT_FLAGS;
|
||||||
|
|
||||||
DrawTextW (hdc, lvItem.pszText, -1, &rcText, uFormat | DT_CALCRECT);
|
DrawTextW (hdc, lpLVItem->pszText, -1, &rcText, uFormat | DT_CALCRECT);
|
||||||
|
|
||||||
labelSize.cx = min(rcText.right - rcText.left + TRAILING_PADDING, infoPtr->nItemWidth);
|
labelSize.cx = min(rcText.right - rcText.left + TRAILING_PADDING, infoPtr->nItemWidth);
|
||||||
labelSize.cy = rcText.bottom - rcText.top;
|
labelSize.cy = rcText.bottom - rcText.top;
|
||||||
|
@ -1540,15 +1562,15 @@ static BOOL LISTVIEW_GetItemMeasures(LISTVIEW_INFO *infoPtr, INT nItem,
|
||||||
else /* LVS_SMALLICON, LVS_LIST or LVS_REPORT */
|
else /* LVS_SMALLICON, LVS_LIST or LVS_REPORT */
|
||||||
{
|
{
|
||||||
Label.left = Icon.right;
|
Label.left = Icon.right;
|
||||||
|
if (infoPtr->himlSmall) Label.left += IMAGE_PADDING;
|
||||||
Label.top = Box.top;
|
Label.top = Box.top;
|
||||||
Label.right = Label.left + labelSize.cx;
|
Label.right = Label.left + labelSize.cx;
|
||||||
if (infoPtr->himlSmall) Label.right += IMAGE_PADDING;
|
|
||||||
if (Label.right > Box.right) Label.right = Box.right;
|
if (Label.right > Box.right) Label.right = Box.right;
|
||||||
Label.bottom = Label.top + infoPtr->nItemHeight;
|
Label.bottom = Label.top + infoPtr->nItemHeight;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lprcLabel) *lprcLabel = Label;
|
if (lprcLabel) *lprcLabel = Label;
|
||||||
TRACE("hwnd=%x, item=%d, label=%s\n", infoPtr->hwndSelf, nItem, debugrect(&Label));
|
TRACE(" - label=%s\n", debugrect(&Label));
|
||||||
}
|
}
|
||||||
|
|
||||||
/***********************************************************/
|
/***********************************************************/
|
||||||
|
@ -1566,12 +1588,87 @@ static BOOL LISTVIEW_GetItemMeasures(LISTVIEW_INFO *infoPtr, INT nItem,
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
UnionRect(lprcBounds, &Icon, &Label);
|
UnionRect(lprcBounds, &Icon, &Label);
|
||||||
TRACE("hwnd=%x, item=%d, bounds=%s\n", infoPtr->hwndSelf, nItem, debugrect(lprcBounds));
|
TRACE(" - bounds=%s\n", debugrect(lprcBounds));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (oversizedBox) UnionRect(lprcBox, &Box, &Label);
|
if (oversizedBox) UnionRect(lprcBox, &Box, &Label);
|
||||||
else if (lprcBox) *lprcBox = Box;
|
else if (lprcBox) *lprcBox = Box;
|
||||||
TRACE("hwnd=%x, item=%d, box=%s\n", infoPtr->hwndSelf, nItem, debugrect(&Box));
|
TRACE(" - box=%s\n", debugrect(&Box));
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/***
|
||||||
|
* DESCRIPTION: [INTERNAL]
|
||||||
|
*
|
||||||
|
* PARAMETER(S):
|
||||||
|
* [I] infoPtr : valid pointer to the listview structure
|
||||||
|
* [I] nItem : item number
|
||||||
|
* [O] lprcBox : ptr to Box rectangle
|
||||||
|
* The internal LVIR_BOX rectangle
|
||||||
|
* [O] lprcBounds : ptr to Bounds rectangle
|
||||||
|
* Same as LVM_GETITEMRECT with LVIR_BOUNDS
|
||||||
|
* [O] lprcIcon : ptr to Icon rectangle
|
||||||
|
* Same as LVM_GETITEMRECT with LVIR_ICON
|
||||||
|
* [O] lprcLabel : ptr to Label rectangle
|
||||||
|
* Same as LVM_GETITEMRECT with LVIR_LABEL
|
||||||
|
*
|
||||||
|
* RETURN:
|
||||||
|
* TRUE if computations OK
|
||||||
|
* FALSE otherwise
|
||||||
|
*/
|
||||||
|
static BOOL LISTVIEW_GetItemMeasures(LISTVIEW_INFO *infoPtr, INT nItem,
|
||||||
|
LPRECT lprcBox, LPRECT lprcBounds,
|
||||||
|
LPRECT lprcIcon, LPRECT lprcLabel)
|
||||||
|
{
|
||||||
|
UINT uView = infoPtr->dwStyle & LVS_TYPEMASK;
|
||||||
|
WCHAR szDispText[DISP_TEXT_SIZE] = { '\0' };
|
||||||
|
BOOL doIcon = FALSE, doLabel = FALSE, oversizedBox = FALSE;
|
||||||
|
POINT Position, Origin;
|
||||||
|
LVITEMW lvItem;
|
||||||
|
|
||||||
|
if (!LISTVIEW_GetItemListOrigin(infoPtr, nItem, &Position)) return FALSE;
|
||||||
|
if (!LISTVIEW_GetOrigin(infoPtr, &Origin)) return FALSE;
|
||||||
|
|
||||||
|
/* Be smart and try to figure out the minimum we have to do */
|
||||||
|
if (lprcBounds)
|
||||||
|
{
|
||||||
|
if (uView == LVS_REPORT) doIcon = TRUE;
|
||||||
|
else doLabel = TRUE;
|
||||||
|
}
|
||||||
|
if (uView == LVS_ICON && (lprcBox || lprcBounds || lprcLabel) &&
|
||||||
|
infoPtr->bFocus && !(infoPtr->dwStyle & LVS_OWNERDRAWFIXED) &&
|
||||||
|
LISTVIEW_GetItemState(infoPtr, nItem, LVIS_FOCUSED))
|
||||||
|
oversizedBox = doLabel = TRUE;
|
||||||
|
if (lprcLabel) doLabel = TRUE;
|
||||||
|
if (doLabel || lprcIcon) doIcon = TRUE;
|
||||||
|
|
||||||
|
/* 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 */
|
||||||
|
lvItem.mask = 0;
|
||||||
|
if (doIcon && uView == LVS_REPORT) lvItem.mask |= LVIF_INDENT;
|
||||||
|
if (doLabel) lvItem.mask |= LVIF_TEXT;
|
||||||
|
lvItem.iItem = nItem;
|
||||||
|
lvItem.iSubItem = 0;
|
||||||
|
lvItem.pszText = szDispText;
|
||||||
|
lvItem.cchTextMax = DISP_TEXT_SIZE;
|
||||||
|
if (lvItem.mask && !LISTVIEW_GetItemW(infoPtr, &lvItem)) return FALSE;
|
||||||
|
if (uView == LVS_ICON && (lprcBox || lprcBounds || lprcLabel))
|
||||||
|
{
|
||||||
|
lvItem.mask |= LVIF_STATE;
|
||||||
|
lvItem.stateMask = LVIS_FOCUSED;
|
||||||
|
lvItem.state = (oversizedBox ? LVIS_FOCUSED : 0);
|
||||||
|
}
|
||||||
|
if (!LISTVIEW_GetItemMetrics(infoPtr, &lvItem, lprcBox, lprcBounds, 0, lprcIcon, lprcLabel)) return FALSE;
|
||||||
|
|
||||||
|
Position.x += Origin.x;
|
||||||
|
Position.y += Origin.y;
|
||||||
|
|
||||||
|
if (lprcBox) OffsetRect(lprcBox, Position.x, Position.y);
|
||||||
|
if (lprcBounds) OffsetRect(lprcBounds, Position.x, Position.y);
|
||||||
|
if (lprcIcon) OffsetRect(lprcIcon, Position.x, Position.y);
|
||||||
|
if (lprcLabel) OffsetRect(lprcLabel, Position.x, Position.y);
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
@ -2131,6 +2228,7 @@ static BOOL remove_selection_range(LISTVIEW_INFO *infoPtr, INT lower, INT upper,
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/***
|
/***
|
||||||
* Helper function for LISTVIEW_AddSelectionRange, and LISTVIEW_SetItem.
|
* Helper function for LISTVIEW_AddSelectionRange, and LISTVIEW_SetItem.
|
||||||
*/
|
*/
|
||||||
|
|
Loading…
Reference in New Issue