Listview O0
Dimitrie O. Paun
dpaun at rogers.com
Thu Oct 10 23:30:59 CDT 2002
Separate item metrics computation from positioning.
ChangeLog
Separate item metrics computation from positioning
Add support for computing state icon metrics.
Index: dlls/comctl32/listview.c
===================================================================
RCS file: /var/cvs/wine/dlls/comctl32/listview.c,v
retrieving revision 1.215
diff -u -r1.215 listview.c
--- dlls/comctl32/listview.c 11 Oct 2002 04:19:20 -0000 1.215
+++ dlls/comctl32/listview.c 11 Oct 2002 04:29:43 -0000
@@ -1378,11 +1378,13 @@
*
* PARAMETER(S):
* [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
* The internal LVIR_BOX rectangle
* [O] lprcBounds : ptr to Bounds rectangle
* 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
* Same as LVM_GETITEMRECT with LVIR_ICON
* [O] lprcLabel : ptr to Label rectangle
@@ -1392,54 +1394,73 @@
* TRUE if computations OK
* 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 lprcIcon, LPRECT lprcLabel)
+ LPRECT lprcState, LPRECT lprcIcon, LPRECT lprcLabel)
{
UINT uView = infoPtr->dwStyle & LVS_TYPEMASK;
- BOOL doIcon = FALSE, doLabel = FALSE, oversizedBox = FALSE;
- WCHAR szDispText[DISP_TEXT_SIZE] = { '\0' };
- RECT Box, Icon, Label;
- POINT Position, Origin;
- LVITEMW lvItem;
+ BOOL doState = FALSE, doIcon = FALSE, doLabel = FALSE, oversizedBox = FALSE;
+ RECT Box, State, Icon, Label;
+ ERR("(lpLVItem=%s)\n", debuglvitem_t(lpLVItem, TRUE));
+
/* 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 && infoPtr->bFocus &&
- !(infoPtr->dwStyle & LVS_OWNERDRAWFIXED) &&
- LISTVIEW_GetItemState(infoPtr, nItem, LVIS_FOCUSED))
- oversizedBox = doLabel = TRUE;
+ if (uView == LVS_ICON && (lprcBox || lprcBounds || lprcLabel))
+ {
+ if (!(lpLVItem->mask & LVIF_STATE) ||
+ !(lpLVItem->stateMask & LVIS_FOCUSED))
+ return FALSE;
+ if ((lpLVItem->state & LVIS_FOCUSED) &&
+ !(infoPtr->dwStyle & LVS_OWNERDRAWFIXED))
+ oversizedBox = doLabel = TRUE;
+ }
if (lprcLabel) doLabel = 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) */
/************************************************************/
- 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;
+ Box.left = 0;
+ Box.top = 0;
+ Box.right = infoPtr->nItemWidth;
+ Box.bottom = 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) */
@@ -1462,17 +1483,15 @@
}
else /* LVS_SMALLICON, LVS_LIST or LVS_REPORT */
{
- /* do indent */
- Icon.left = Box.left;
- if (uView == LVS_REPORT) Icon.left += infoPtr->iconSize.cx * lvItem.iIndent;
- if (infoPtr->himlState) Icon.left += infoPtr->iconStateSize.cx;
+ Icon.left = State.right;
+ if (infoPtr->himlState) Icon.left += IMAGE_PADDING;
Icon.top = Box.top;
Icon.right = Icon.left;
if (infoPtr->himlSmall) Icon.right += infoPtr->iconSize.cx;
Icon.bottom = Icon.top + infoPtr->nItemHeight;
}
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 @@
if (doLabel)
{
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)
{
labelSize.cx = infoPtr->nItemWidth;
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;
HDC hdc = GetDC(infoPtr->hwndSelf);
@@ -1508,7 +1530,7 @@
else
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.cy = rcText.bottom - rcText.top;
@@ -1540,15 +1562,15 @@
else /* LVS_SMALLICON, LVS_LIST or LVS_REPORT */
{
Label.left = Icon.right;
+ if (infoPtr->himlSmall) Label.left += IMAGE_PADDING;
Label.top = Box.top;
Label.right = Label.left + labelSize.cx;
- if (infoPtr->himlSmall) Label.right += IMAGE_PADDING;
if (Label.right > Box.right) Label.right = Box.right;
Label.bottom = Label.top + infoPtr->nItemHeight;
}
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 @@
}
else
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);
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;
}
@@ -2131,6 +2228,7 @@
return TRUE;
}
+
/***
* Helper function for LISTVIEW_AddSelectionRange, and LISTVIEW_SetItem.
*/
More information about the wine-patches
mailing list