Implementation of TVM_SORTCHILDRENCB.
Implementation of TVI_SORT insertion. Fix display problem when TVIF_IMAGE|TVIF_SELECTEDIMAGE were not set. Fix problems related to TVIS_EXPANDEDONCE.
This commit is contained in:
parent
3ff06f613e
commit
99b118a216
|
@ -190,6 +190,7 @@ static TREEVIEW_ITEM *TREEVIEW_GetNextListItem(
|
||||||
if ((tvItem->firstChild) && (tvItem->state & TVIS_EXPANDED))
|
if ((tvItem->firstChild) && (tvItem->state & TVIS_EXPANDED))
|
||||||
return (& infoPtr->items[(INT)tvItem->firstChild]);
|
return (& infoPtr->items[(INT)tvItem->firstChild]);
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* try to get the sibling
|
* try to get the sibling
|
||||||
*/
|
*/
|
||||||
|
@ -493,6 +494,8 @@ TREEVIEW_GetTextColor (HWND hwnd)
|
||||||
/* cdmode: custom draw mode as received from app. in first NMCUSTOMDRAW
|
/* cdmode: custom draw mode as received from app. in first NMCUSTOMDRAW
|
||||||
notification */
|
notification */
|
||||||
|
|
||||||
|
#define TREEVIEW_LEFT_MARGIN 8
|
||||||
|
|
||||||
static void
|
static void
|
||||||
TREEVIEW_DrawItem (HWND hwnd, HDC hdc, TREEVIEW_ITEM *wineItem)
|
TREEVIEW_DrawItem (HWND hwnd, HDC hdc, TREEVIEW_ITEM *wineItem)
|
||||||
|
|
||||||
|
@ -528,9 +531,15 @@ TREEVIEW_DrawItem (HWND hwnd, HDC hdc, TREEVIEW_ITEM *wineItem)
|
||||||
/*
|
/*
|
||||||
* Set drawing starting points
|
* Set drawing starting points
|
||||||
*/
|
*/
|
||||||
r = wineItem->rect; /* this item rectangle */
|
r = wineItem->rect; /* this item rectangle */
|
||||||
center = (r.top+r.bottom)/2; /* this item vertical center */
|
center = (r.top+r.bottom)/2; /* this item vertical center */
|
||||||
xpos = r.left + 8; /* horizontal starting point */
|
xpos = r.left + TREEVIEW_LEFT_MARGIN;/* horizontal starting point */
|
||||||
|
|
||||||
|
TRACE(treeview, "Left %3d, Top %3d, Right %3d, Bottom %3d\n",
|
||||||
|
r.left,
|
||||||
|
r.top,
|
||||||
|
r.right,
|
||||||
|
r.bottom);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Display the tree hierarchy
|
* Display the tree hierarchy
|
||||||
|
@ -577,9 +586,7 @@ TREEVIEW_DrawItem (HWND hwnd, HDC hdc, TREEVIEW_ITEM *wineItem)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
points[2].x = points[1].x = 8 + (20*wineItem->iLevel);
|
points[2].x = points[1].x = 8 + (20*wineItem->iLevel);
|
||||||
points[2].y = ((upNode->cChildren == 0) ?
|
points[2].y = ((upNode->cChildren == 0) ? upRect.top : upRect.bottom-1);
|
||||||
upRect.top :
|
|
||||||
upRect.bottom-3);
|
|
||||||
points[1].y = points[0].y = center;
|
points[1].y = points[0].y = center;
|
||||||
points[0].x = points[1].x + 10;
|
points[0].x = points[1].x + 10;
|
||||||
}
|
}
|
||||||
|
@ -623,19 +630,28 @@ TREEVIEW_DrawItem (HWND hwnd, HDC hdc, TREEVIEW_ITEM *wineItem)
|
||||||
/*
|
/*
|
||||||
* Display the (+/-) signs
|
* Display the (+/-) signs
|
||||||
*/
|
*/
|
||||||
wineItem->expandBox.left = 0; /* Initialize the expandBox */
|
if (wineItem->iLevel != 0)/* update position only for non root node */
|
||||||
wineItem->expandBox.top = 0;
|
xpos+=(5*wineItem->iLevel);
|
||||||
wineItem->expandBox.right = 0;
|
|
||||||
wineItem->expandBox.bottom = 0;
|
|
||||||
if (( GetWindowLongA( hwnd, GWL_STYLE) & TVS_HASBUTTONS) &&
|
if (( GetWindowLongA( hwnd, GWL_STYLE) & TVS_HASBUTTONS) &&
|
||||||
( GetWindowLongA( hwnd, GWL_STYLE) & TVS_HASLINES))
|
( GetWindowLongA( hwnd, GWL_STYLE) & TVS_HASLINES))
|
||||||
{
|
{
|
||||||
if (wineItem->cChildren)
|
if ( (wineItem->cChildren) ||
|
||||||
|
(wineItem->cChildren == I_CHILDRENCALLBACK))
|
||||||
{
|
{
|
||||||
if (wineItem->parent)
|
/* Setup expand box coordinate to facilitate the LMBClick handling */
|
||||||
xpos+=5; /* update position only for nodes that have a parent */
|
wineItem->expandBox.left = xpos-4;
|
||||||
|
wineItem->expandBox.top = center-4;
|
||||||
Rectangle (hdc, xpos-4, center-4, xpos+5, center+5);
|
wineItem->expandBox.right = xpos+5;
|
||||||
|
wineItem->expandBox.bottom = center+5;
|
||||||
|
|
||||||
|
Rectangle (
|
||||||
|
hdc,
|
||||||
|
wineItem->expandBox.left,
|
||||||
|
wineItem->expandBox.top ,
|
||||||
|
wineItem->expandBox.right,
|
||||||
|
wineItem->expandBox.bottom);
|
||||||
|
|
||||||
MoveToEx (hdc, xpos-2, center, NULL);
|
MoveToEx (hdc, xpos-2, center, NULL);
|
||||||
LineTo (hdc, xpos+3, center);
|
LineTo (hdc, xpos+3, center);
|
||||||
|
|
||||||
|
@ -643,26 +659,16 @@ TREEVIEW_DrawItem (HWND hwnd, HDC hdc, TREEVIEW_ITEM *wineItem)
|
||||||
MoveToEx (hdc, xpos, center-2, NULL);
|
MoveToEx (hdc, xpos, center-2, NULL);
|
||||||
LineTo (hdc, xpos, center+3);
|
LineTo (hdc, xpos, center+3);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Setup expand box coordinate to facilitate the LMBClick handling */
|
|
||||||
wineItem->expandBox.left = xpos-4;
|
|
||||||
wineItem->expandBox.top = center-4;
|
|
||||||
wineItem->expandBox.right = xpos+5;
|
|
||||||
wineItem->expandBox.bottom = center+5;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
xpos+=(5*wineItem->iLevel);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Display the image assiciated with this item
|
* Display the image assiciated with this item
|
||||||
*/
|
*/
|
||||||
|
xpos += 13; /* update position */
|
||||||
if (wineItem->mask & (TVIF_IMAGE|TVIF_SELECTEDIMAGE)) {
|
if (wineItem->mask & (TVIF_IMAGE|TVIF_SELECTEDIMAGE)) {
|
||||||
INT imageIndex;
|
INT imageIndex;
|
||||||
HIMAGELIST *himlp = NULL;
|
HIMAGELIST *himlp = NULL;
|
||||||
xpos += 13; /* update position */
|
|
||||||
|
|
||||||
if (infoPtr->himlNormal)
|
if (infoPtr->himlNormal)
|
||||||
himlp=&infoPtr->himlNormal; /* get the image list */
|
himlp=&infoPtr->himlNormal; /* get the image list */
|
||||||
|
@ -712,7 +718,9 @@ TREEVIEW_DrawItem (HWND hwnd, HDC hdc, TREEVIEW_ITEM *wineItem)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Display the text assiciated with this item
|
||||||
|
*/
|
||||||
r.left=xpos;
|
r.left=xpos;
|
||||||
if ((wineItem->mask & TVIF_TEXT) && (wineItem->pszText))
|
if ((wineItem->mask & TVIF_TEXT) && (wineItem->pszText))
|
||||||
{
|
{
|
||||||
|
@ -1230,7 +1238,242 @@ TREEVIEW_GetCount (HWND hwnd, WPARAM wParam, LPARAM lParam)
|
||||||
return (LRESULT) infoPtr->uNumItems;
|
return (LRESULT) infoPtr->uNumItems;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/***************************************************************************
|
||||||
|
* This method does the chaining of the insertion of a treeview item
|
||||||
|
* before an item.
|
||||||
|
*/
|
||||||
|
static void TREEVIEW_InsertBefore(
|
||||||
|
TREEVIEW_INFO *infoPtr,
|
||||||
|
TREEVIEW_ITEM *newItem,
|
||||||
|
TREEVIEW_ITEM *sibling,
|
||||||
|
TREEVIEW_ITEM *parent)
|
||||||
|
{
|
||||||
|
HTREEITEM siblingHandle = 0;
|
||||||
|
HTREEITEM upSiblingHandle = 0;
|
||||||
|
TREEVIEW_ITEM *upSibling = NULL;
|
||||||
|
|
||||||
|
if (newItem == NULL)
|
||||||
|
ERR(treeview, "NULL newItem, impossible condition\n");
|
||||||
|
|
||||||
|
if (parent == NULL)
|
||||||
|
ERR(treeview, "NULL parent, impossible condition\n");
|
||||||
|
|
||||||
|
if (sibling != NULL) /* Insert before this sibling for this parent */
|
||||||
|
{
|
||||||
|
/* Store the new item sibling up sibling and sibling tem handle */
|
||||||
|
siblingHandle = sibling->hItem;
|
||||||
|
upSiblingHandle = sibling->upsibling;
|
||||||
|
/* As well as a pointer to the upsibling sibling object */
|
||||||
|
if ( (INT)sibling->upsibling != 0 )
|
||||||
|
upSibling = &infoPtr->items[(INT)sibling->upsibling];
|
||||||
|
|
||||||
|
/* Adjust the sibling pointer */
|
||||||
|
sibling->upsibling = newItem->hItem;
|
||||||
|
|
||||||
|
/* Adjust the new item pointers */
|
||||||
|
newItem->upsibling = upSiblingHandle;
|
||||||
|
newItem->sibling = siblingHandle;
|
||||||
|
|
||||||
|
/* Adjust the up sibling pointer */
|
||||||
|
if ( upSibling != NULL )
|
||||||
|
upSibling->sibling = newItem->hItem;
|
||||||
|
else
|
||||||
|
/* this item is the first child of this parent, adjust parent pointers */
|
||||||
|
parent->firstChild = newItem->hItem;
|
||||||
|
}
|
||||||
|
else /* Insert as first child of this parent */
|
||||||
|
parent->firstChild = newItem->hItem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/***************************************************************************
|
||||||
|
* This method does the chaining of the insertion of a treeview item
|
||||||
|
* after an item.
|
||||||
|
*/
|
||||||
|
static void TREEVIEW_InsertAfter(
|
||||||
|
TREEVIEW_INFO *infoPtr,
|
||||||
|
TREEVIEW_ITEM *newItem,
|
||||||
|
TREEVIEW_ITEM *upSibling,
|
||||||
|
TREEVIEW_ITEM *parent)
|
||||||
|
{
|
||||||
|
HTREEITEM upSiblingHandle = 0;
|
||||||
|
HTREEITEM siblingHandle = 0;
|
||||||
|
TREEVIEW_ITEM *sibling = NULL;
|
||||||
|
|
||||||
|
if (newItem == NULL)
|
||||||
|
ERR(treeview, "NULL newItem, impossible condition\n");
|
||||||
|
|
||||||
|
if (parent == NULL)
|
||||||
|
ERR(treeview, "NULL parent, impossible condition\n");
|
||||||
|
|
||||||
|
if (upSibling != NULL) /* Insert after this upsibling for this parent */
|
||||||
|
{
|
||||||
|
/* Store the new item up sibling and sibling item handle */
|
||||||
|
upSiblingHandle = upSibling->hItem;
|
||||||
|
siblingHandle = upSibling->sibling;
|
||||||
|
/* As well as a pointer to the upsibling sibling object */
|
||||||
|
if ( (INT)upSibling->sibling != 0 )
|
||||||
|
sibling = &infoPtr->items[(INT)upSibling->sibling];
|
||||||
|
|
||||||
|
/* Adjust the up sibling pointer */
|
||||||
|
upSibling->sibling = newItem->hItem;
|
||||||
|
|
||||||
|
/* Adjust the new item pointers */
|
||||||
|
newItem->upsibling = upSiblingHandle;
|
||||||
|
newItem->sibling = siblingHandle;
|
||||||
|
|
||||||
|
/* Adjust the sibling pointer */
|
||||||
|
if ( sibling != NULL )
|
||||||
|
sibling->upsibling = newItem->hItem;
|
||||||
|
/*
|
||||||
|
else
|
||||||
|
newItem is the last of the level, nothing else to do
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
else /* Insert as first child of this parent */
|
||||||
|
parent->firstChild = newItem->hItem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/***************************************************************************
|
||||||
|
* This method is used to abstract the comparaison of two items during
|
||||||
|
* the insertion or a request for a sort.
|
||||||
|
*/
|
||||||
|
static INT TREEVIEW_CompareItems(
|
||||||
|
TREEVIEW_INFO *infoPtr,
|
||||||
|
TREEVIEW_ITEM *first,
|
||||||
|
TREEVIEW_ITEM *second)
|
||||||
|
{
|
||||||
|
|
||||||
|
if ((first == NULL) || (second == NULL))
|
||||||
|
ERR( treeview,
|
||||||
|
"Invalid parameters passed infoPtr=%p, first=%p, second=%p.\n",
|
||||||
|
infoPtr,
|
||||||
|
first,
|
||||||
|
second);
|
||||||
|
|
||||||
|
if (infoPtr->pCallBackSort == NULL)
|
||||||
|
{
|
||||||
|
/* Simply sort based on the label comparaison */
|
||||||
|
return strcmp(first->pszText, second->pszText);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* use the callback method setup in tree view struct */
|
||||||
|
if( (first->lParam == 0) || (second->lParam == 0))
|
||||||
|
ERR( treeview, "Invalid lParam, first=%08lx, second=%08lx.\n",
|
||||||
|
first->lParam,
|
||||||
|
second->lParam);
|
||||||
|
|
||||||
|
return (infoPtr->pCallBackSort->lpfnCompare)(
|
||||||
|
first->lParam,
|
||||||
|
second->lParam,
|
||||||
|
infoPtr->pCallBackSort->lParam);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/***************************************************************************
|
||||||
|
* Forward the DPA local callback to the treeview owner callback
|
||||||
|
*/
|
||||||
|
static INT TREEVIEW_CallBackCompare(
|
||||||
|
LPVOID first,
|
||||||
|
LPVOID second,
|
||||||
|
LPARAM tvInfoPtr)
|
||||||
|
{
|
||||||
|
/* Forward the call to the client define callback */
|
||||||
|
TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr((HWND)tvInfoPtr);
|
||||||
|
return (infoPtr->pCallBackSort->lpfnCompare)(
|
||||||
|
((TREEVIEW_ITEM*)first)->lParam,
|
||||||
|
((TREEVIEW_ITEM*)second)->lParam,
|
||||||
|
infoPtr->pCallBackSort->lParam);
|
||||||
|
}
|
||||||
|
|
||||||
|
/***************************************************************************
|
||||||
|
* Setup the treeview structure with regards of the sort method
|
||||||
|
* and sort the children of the TV item specified in lParam
|
||||||
|
*/
|
||||||
|
LRESULT WINAPI TREEVIEW_SortChildrenCB(
|
||||||
|
HWND hwnd,
|
||||||
|
WPARAM wParam,
|
||||||
|
LPARAM lParam)
|
||||||
|
{
|
||||||
|
TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(hwnd);
|
||||||
|
TREEVIEW_ITEM *sortMe = NULL; /* Node for which we sort the children */
|
||||||
|
|
||||||
|
/* Obtain the TVSORTBC struct */
|
||||||
|
infoPtr->pCallBackSort = (LPTVSORTCB)lParam;
|
||||||
|
|
||||||
|
/* Obtain the parent node to sort */
|
||||||
|
sortMe = &infoPtr->items[ (INT)infoPtr->pCallBackSort->hParent ];
|
||||||
|
|
||||||
|
/* Make sure there is something to sort */
|
||||||
|
if ( sortMe->cChildren > 1 )
|
||||||
|
{
|
||||||
|
/* pointer organization */
|
||||||
|
HDPA sortList = DPA_Create(sortMe->cChildren);
|
||||||
|
HTREEITEM itemHandle = sortMe->firstChild;
|
||||||
|
TREEVIEW_ITEM *itemPtr = & infoPtr->items[ (INT)itemHandle ];
|
||||||
|
|
||||||
|
/* TREEVIEW_ITEM rechaining */
|
||||||
|
INT count = 0;
|
||||||
|
VOID *item = 0;
|
||||||
|
VOID *nextItem = 0;
|
||||||
|
VOID *prevItem = 0;
|
||||||
|
|
||||||
|
/* Build the list of item to sort */
|
||||||
|
do
|
||||||
|
{
|
||||||
|
DPA_InsertPtr(
|
||||||
|
sortList, /* the list */
|
||||||
|
sortMe->cChildren+1, /* force the insertion to be an append */
|
||||||
|
itemPtr); /* the ptr to store */
|
||||||
|
|
||||||
|
/* Get the next sibling */
|
||||||
|
itemHandle = itemPtr->sibling;
|
||||||
|
itemPtr = & infoPtr->items[ (INT)itemHandle ];
|
||||||
|
} while ( itemHandle != NULL );
|
||||||
|
|
||||||
|
/* let DPA perform the sort activity */
|
||||||
|
DPA_Sort(
|
||||||
|
sortList, /* what */
|
||||||
|
TREEVIEW_CallBackCompare, /* how */
|
||||||
|
hwnd); /* owner */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Reorganized TREEVIEW_ITEM structures.
|
||||||
|
* Note that we know we have at least two elements.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Get the first item and get ready to start... */
|
||||||
|
item = DPA_GetPtr(sortList, count++);
|
||||||
|
while ( (nextItem = DPA_GetPtr(sortList, count++)) != NULL )
|
||||||
|
{
|
||||||
|
/* link the two current item toghether */
|
||||||
|
((TREEVIEW_ITEM*)item)->sibling = ((TREEVIEW_ITEM*)nextItem)->hItem;
|
||||||
|
((TREEVIEW_ITEM*)nextItem)->upsibling = ((TREEVIEW_ITEM*)item)->hItem;
|
||||||
|
|
||||||
|
if (prevItem == NULL) /* this is the first item, update the parent */
|
||||||
|
{
|
||||||
|
sortMe->firstChild = ((TREEVIEW_ITEM*)item)->hItem;
|
||||||
|
((TREEVIEW_ITEM*)item)->upsibling = NULL;
|
||||||
|
}
|
||||||
|
else /* fix the back chaining */
|
||||||
|
{
|
||||||
|
((TREEVIEW_ITEM*)item)->upsibling = ((TREEVIEW_ITEM*)prevItem)->hItem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* get ready for the next one */
|
||||||
|
prevItem = item;
|
||||||
|
item = nextItem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* the last item is pointed to by item and never has a sibling */
|
||||||
|
((TREEVIEW_ITEM*)item)->sibling = NULL;
|
||||||
|
|
||||||
|
DPA_Destroy(sortList);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* the method used below isn't the most memory-friendly, but it avoids
|
/* the method used below isn't the most memory-friendly, but it avoids
|
||||||
|
@ -1247,7 +1490,8 @@ TREEVIEW_InsertItemA (HWND hwnd, WPARAM wParam, LPARAM lParam)
|
||||||
TVITEMEXA *tvItem;
|
TVITEMEXA *tvItem;
|
||||||
TREEVIEW_ITEM *wineItem, *parentItem, *prevsib, *sibItem;
|
TREEVIEW_ITEM *wineItem, *parentItem, *prevsib, *sibItem;
|
||||||
INT iItem,listItems,i,len;
|
INT iItem,listItems,i,len;
|
||||||
|
|
||||||
|
/* Item to insert */
|
||||||
ptdi = (LPTVINSERTSTRUCTA) lParam;
|
ptdi = (LPTVINSERTSTRUCTA) lParam;
|
||||||
|
|
||||||
/* check if memory is available */
|
/* check if memory is available */
|
||||||
|
@ -1259,6 +1503,9 @@ TREEVIEW_InsertItemA (HWND hwnd, WPARAM wParam, LPARAM lParam)
|
||||||
infoPtr->TopRootItem=(HTREEITEM)1;
|
infoPtr->TopRootItem=(HTREEITEM)1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Reallocate contiguous space for items
|
||||||
|
*/
|
||||||
if (infoPtr->uNumItems == (infoPtr->uNumPtrsAlloced-1) ) {
|
if (infoPtr->uNumItems == (infoPtr->uNumPtrsAlloced-1) ) {
|
||||||
TREEVIEW_ITEM *oldItems = infoPtr->items;
|
TREEVIEW_ITEM *oldItems = infoPtr->items;
|
||||||
INT *oldfreeList = infoPtr->freeList;
|
INT *oldfreeList = infoPtr->freeList;
|
||||||
|
@ -1276,47 +1523,90 @@ TREEVIEW_InsertItemA (HWND hwnd, WPARAM wParam, LPARAM lParam)
|
||||||
COMCTL32_Free (oldfreeList);
|
COMCTL32_Free (oldfreeList);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Reset infoPtr structure with new stat according to current TV picture
|
||||||
|
*/
|
||||||
iItem=0;
|
iItem=0;
|
||||||
infoPtr->uNumItems++;
|
infoPtr->uNumItems++;
|
||||||
|
|
||||||
if ((INT)infoPtr->uMaxHandle==(infoPtr->uNumItems-1)) {
|
if ((INT)infoPtr->uMaxHandle==(infoPtr->uNumItems-1)) {
|
||||||
iItem=infoPtr->uNumItems;
|
iItem=infoPtr->uNumItems;
|
||||||
infoPtr->uMaxHandle = (HTREEITEM)((INT)infoPtr->uMaxHandle + 1);
|
infoPtr->uMaxHandle = (HTREEITEM)((INT)infoPtr->uMaxHandle + 1);
|
||||||
} else { /* check freelist */
|
} else { /* check freelist */
|
||||||
for (i=0; i<infoPtr->uNumPtrsAlloced>>5; i++) {
|
for (i=0; i<infoPtr->uNumPtrsAlloced>>5; i++) {
|
||||||
if (infoPtr->freeList[i]) {
|
if (infoPtr->freeList[i]) {
|
||||||
iItem=ffs (infoPtr->freeList[i])-1;
|
iItem=ffs (infoPtr->freeList[i])-1;
|
||||||
tv_clear_bit(iItem,&infoPtr->freeList[i]);
|
tv_clear_bit(iItem,&infoPtr->freeList[i]);
|
||||||
iItem+=i<<5;
|
iItem+=i<<5;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* little performace enhancement... */
|
||||||
|
if (TRACE_ON(treeview)) {
|
||||||
|
for (i=0; i<infoPtr->uNumPtrsAlloced>>5; i++)
|
||||||
|
TRACE (treeview,"%8x\n",infoPtr->freeList[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i=0; i<infoPtr->uNumPtrsAlloced>>5; i++)
|
|
||||||
TRACE (treeview,"%8x\n",infoPtr->freeList[i]);
|
|
||||||
|
|
||||||
if (!iItem) ERR (treeview, "Argh -- can't find free item.\n");
|
if (!iItem) ERR (treeview, "Argh -- can't find free item.\n");
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Find the parent item of the new item
|
||||||
|
*/
|
||||||
tvItem= & ptdi->DUMMYUNIONNAME.itemex;
|
tvItem= & ptdi->DUMMYUNIONNAME.itemex;
|
||||||
wineItem=& infoPtr->items[iItem];
|
wineItem=& infoPtr->items[iItem];
|
||||||
|
|
||||||
if ((ptdi->hParent==TVI_ROOT) || (ptdi->hParent==0)) {
|
if ((ptdi->hParent==TVI_ROOT) || (ptdi->hParent==0)) {
|
||||||
parentItem=NULL;
|
parentItem = NULL;
|
||||||
wineItem->parent=0;
|
wineItem->parent = 0;
|
||||||
sibItem=&infoPtr->items [(INT)infoPtr->TopRootItem];
|
sibItem = &infoPtr->items [(INT)infoPtr->TopRootItem];
|
||||||
listItems=infoPtr->uNumItems;
|
listItems = infoPtr->uNumItems;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
parentItem= &infoPtr->items[(INT)ptdi->hParent];
|
parentItem = &infoPtr->items[(INT)ptdi->hParent];
|
||||||
if (!parentItem->firstChild)
|
|
||||||
parentItem->firstChild=(HTREEITEM)iItem;
|
/* Do the insertion here it if it's the only item of this parent */
|
||||||
wineItem->parent=ptdi->hParent;
|
if (!parentItem->firstChild)
|
||||||
sibItem=&infoPtr->items [(INT)parentItem->firstChild];
|
parentItem->firstChild=(HTREEITEM)iItem;
|
||||||
parentItem->cChildren++;
|
|
||||||
listItems=parentItem->cChildren;
|
wineItem->parent = ptdi->hParent;
|
||||||
|
sibItem = &infoPtr->items [(INT)parentItem->firstChild];
|
||||||
|
parentItem->cChildren++;
|
||||||
|
listItems = parentItem->cChildren;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* NOTE: I am moving some setup of the wineItem object that was initialy
|
||||||
|
* done at the end of the function since some of the values are
|
||||||
|
* required by the Callback sorting
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (tvItem->mask & TVIF_TEXT)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Setup the item text stuff here since it's required by the Sort method
|
||||||
|
* when the insertion are ordered
|
||||||
|
*/
|
||||||
|
if (tvItem->pszText!=LPSTR_TEXTCALLBACKA)
|
||||||
|
{
|
||||||
|
TRACE (treeview,"(%p,%s)\n", &tvItem->pszText, tvItem->pszText);
|
||||||
|
len = lstrlenA (tvItem->pszText)+1;
|
||||||
|
wineItem->pszText= COMCTL32_Alloc (len+1);
|
||||||
|
lstrcpyA (wineItem->pszText, tvItem->pszText);
|
||||||
|
wineItem->cchTextMax=len;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
TRACE (treeview,"LPSTR_TEXTCALLBACK\n");
|
||||||
|
wineItem->pszText = LPSTR_TEXTCALLBACKA;
|
||||||
|
wineItem->cchTextMax = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tvItem->mask & TVIF_PARAM)
|
||||||
|
wineItem->lParam=tvItem->lParam;
|
||||||
|
|
||||||
|
|
||||||
wineItem->upsibling=0; /* needed in case we're the first item in a list */
|
wineItem->upsibling=0; /* needed in case we're the first item in a list */
|
||||||
wineItem->sibling=0;
|
wineItem->sibling=0;
|
||||||
wineItem->firstChild=0;
|
wineItem->firstChild=0;
|
||||||
|
@ -1324,6 +1614,7 @@ TREEVIEW_InsertItemA (HWND hwnd, WPARAM wParam, LPARAM lParam)
|
||||||
|
|
||||||
if (listItems>1) {
|
if (listItems>1) {
|
||||||
prevsib=NULL;
|
prevsib=NULL;
|
||||||
|
|
||||||
switch ((INT)ptdi->hInsertAfter) {
|
switch ((INT)ptdi->hInsertAfter) {
|
||||||
case TVI_FIRST:
|
case TVI_FIRST:
|
||||||
if (wineItem->parent) {
|
if (wineItem->parent) {
|
||||||
|
@ -1335,6 +1626,65 @@ TREEVIEW_InsertItemA (HWND hwnd, WPARAM wParam, LPARAM lParam)
|
||||||
}
|
}
|
||||||
sibItem->upsibling=(HTREEITEM)iItem;
|
sibItem->upsibling=(HTREEITEM)iItem;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case TVI_SORT:
|
||||||
|
if (sibItem==wineItem)
|
||||||
|
/*
|
||||||
|
* This item is the first child of the level and it
|
||||||
|
* has already been inserted
|
||||||
|
*/
|
||||||
|
break;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
TREEVIEW_ITEM *aChild =
|
||||||
|
&infoPtr->items[(INT)parentItem->firstChild];
|
||||||
|
|
||||||
|
TREEVIEW_ITEM *previousChild = NULL;
|
||||||
|
BOOL bItemInserted = FALSE;
|
||||||
|
|
||||||
|
/* Iterate the parent children to see where we fit in */
|
||||||
|
while ( aChild != NULL )
|
||||||
|
{
|
||||||
|
INT comp = strcmp(wineItem->pszText, aChild->pszText);
|
||||||
|
if ( comp < 0 ) /* we are smaller than the current one */
|
||||||
|
{
|
||||||
|
TREEVIEW_InsertBefore(infoPtr, wineItem, aChild, parentItem);
|
||||||
|
bItemInserted = TRUE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if ( comp > 0 ) /* we are bigger than the current one */
|
||||||
|
{
|
||||||
|
previousChild = aChild;
|
||||||
|
aChild = (aChild->sibling == 0) /* This will help us to exit */
|
||||||
|
? NULL /* if there is no more sibling */
|
||||||
|
: &infoPtr->items[(INT)aChild->sibling];
|
||||||
|
|
||||||
|
/* Look at the next item */
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else if ( comp == 0 )
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* An item with this name is already existing, therefore,
|
||||||
|
* we add after the one we found
|
||||||
|
*/
|
||||||
|
TREEVIEW_InsertAfter(infoPtr, wineItem, aChild, parentItem);
|
||||||
|
bItemInserted = TRUE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* we reach the end of the child list and the item as not
|
||||||
|
* yet been inserted, therefore, insert it after the last child.
|
||||||
|
*/
|
||||||
|
if ( (! bItemInserted ) && (aChild == NULL) )
|
||||||
|
TREEVIEW_InsertAfter(infoPtr, wineItem, previousChild, parentItem);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
case TVI_LAST:
|
case TVI_LAST:
|
||||||
if (sibItem==wineItem) break;
|
if (sibItem==wineItem) break;
|
||||||
while (sibItem->sibling) {
|
while (sibItem->sibling) {
|
||||||
|
@ -1344,9 +1694,6 @@ TREEVIEW_InsertItemA (HWND hwnd, WPARAM wParam, LPARAM lParam)
|
||||||
sibItem->sibling=(HTREEITEM)iItem;
|
sibItem->sibling=(HTREEITEM)iItem;
|
||||||
wineItem->upsibling=sibItem->hItem;
|
wineItem->upsibling=sibItem->hItem;
|
||||||
break;
|
break;
|
||||||
case TVI_SORT:
|
|
||||||
FIXME (treeview, "Sorted insert not implemented yet\n");
|
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
while ((sibItem->sibling) && (sibItem->hItem!=ptdi->hInsertAfter))
|
while ((sibItem->sibling) && (sibItem->hItem!=ptdi->hInsertAfter))
|
||||||
{
|
{
|
||||||
|
@ -1384,6 +1731,10 @@ TREEVIEW_InsertItemA (HWND hwnd, WPARAM wParam, LPARAM lParam)
|
||||||
FIXME (treeview," I_CHILDRENCALLBACK not supported\n");
|
FIXME (treeview," I_CHILDRENCALLBACK not supported\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
wineItem->expandBox.left = 0; /* Initialize the expandBox */
|
||||||
|
wineItem->expandBox.top = 0;
|
||||||
|
wineItem->expandBox.right = 0;
|
||||||
|
wineItem->expandBox.bottom = 0;
|
||||||
|
|
||||||
if (tvItem->mask & TVIF_IMAGE)
|
if (tvItem->mask & TVIF_IMAGE)
|
||||||
wineItem->iImage=tvItem->iImage;
|
wineItem->iImage=tvItem->iImage;
|
||||||
|
@ -1394,9 +1745,6 @@ TREEVIEW_InsertItemA (HWND hwnd, WPARAM wParam, LPARAM lParam)
|
||||||
if (tvItem->mask & TVIF_INTEGRAL)
|
if (tvItem->mask & TVIF_INTEGRAL)
|
||||||
wineItem->iIntegral=tvItem->iIntegral;
|
wineItem->iIntegral=tvItem->iIntegral;
|
||||||
|
|
||||||
if (tvItem->mask & TVIF_PARAM)
|
|
||||||
wineItem->lParam=tvItem->lParam;
|
|
||||||
|
|
||||||
if (tvItem->mask & TVIF_SELECTEDIMAGE)
|
if (tvItem->mask & TVIF_SELECTEDIMAGE)
|
||||||
wineItem->iSelectedImage=tvItem->iSelectedImage;
|
wineItem->iSelectedImage=tvItem->iSelectedImage;
|
||||||
|
|
||||||
|
@ -1405,20 +1753,6 @@ TREEVIEW_InsertItemA (HWND hwnd, WPARAM wParam, LPARAM lParam)
|
||||||
wineItem->stateMask=tvItem->stateMask;
|
wineItem->stateMask=tvItem->stateMask;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tvItem->mask & TVIF_TEXT) {
|
|
||||||
if (tvItem->pszText!=LPSTR_TEXTCALLBACKA) {
|
|
||||||
TRACE (treeview,"(%p,%s)\n", &tvItem->pszText, tvItem->pszText);
|
|
||||||
len = lstrlenA (tvItem->pszText)+1;
|
|
||||||
wineItem->pszText= COMCTL32_Alloc (len+1);
|
|
||||||
lstrcpyA (wineItem->pszText, tvItem->pszText);
|
|
||||||
wineItem->cchTextMax=len;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
TRACE (treeview,"LPSTR_TEXTCALLBACK\n");
|
|
||||||
wineItem->pszText = LPSTR_TEXTCALLBACKA;
|
|
||||||
wineItem->cchTextMax = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TREEVIEW_QueueRefresh (hwnd);
|
TREEVIEW_QueueRefresh (hwnd);
|
||||||
|
|
||||||
|
@ -1649,6 +1983,7 @@ TREEVIEW_Create (HWND hwnd, WPARAM wParam, LPARAM lParam)
|
||||||
infoPtr->selectedItem=0;
|
infoPtr->selectedItem=0;
|
||||||
infoPtr->clrText=-1; /* use system color */
|
infoPtr->clrText=-1; /* use system color */
|
||||||
infoPtr->dropItem=0;
|
infoPtr->dropItem=0;
|
||||||
|
infoPtr->pCallBackSort=NULL;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
infoPtr->hwndNotify = GetParent32 (hwnd);
|
infoPtr->hwndNotify = GetParent32 (hwnd);
|
||||||
|
@ -2055,19 +2390,21 @@ TREEVIEW_Expand (HWND hwnd, WPARAM wParam, LPARAM lParam)
|
||||||
if (!wineItem->state & TVIS_EXPANDED)
|
if (!wineItem->state & TVIS_EXPANDED)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
wineItem->state &= ~(TVIS_EXPANDEDONCE | TVIS_EXPANDED);
|
wineItem->state &= ~TVIS_EXPANDED;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TVE_EXPAND:
|
case TVE_EXPAND:
|
||||||
if (wineItem->state & TVIS_EXPANDED)
|
if (wineItem->state & TVIS_EXPANDED)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (!(wineItem->state & TVIS_EXPANDEDONCE))
|
|
||||||
{
|
if (!(wineItem->state & TVIS_EXPANDEDONCE))
|
||||||
|
{
|
||||||
|
/* this item has never been expanded */
|
||||||
if (TREEVIEW_SendTreeviewNotify (
|
if (TREEVIEW_SendTreeviewNotify (
|
||||||
hwnd,
|
hwnd,
|
||||||
TVN_ITEMEXPANDING,
|
TVN_ITEMEXPANDING,
|
||||||
0,
|
TVE_EXPAND,
|
||||||
0,
|
0,
|
||||||
(HTREEITEM)expand))
|
(HTREEITEM)expand))
|
||||||
return FALSE; /* FIXME: OK? */
|
return FALSE; /* FIXME: OK? */
|
||||||
|
@ -2076,11 +2413,15 @@ TREEVIEW_Expand (HWND hwnd, WPARAM wParam, LPARAM lParam)
|
||||||
TREEVIEW_SendTreeviewNotify (
|
TREEVIEW_SendTreeviewNotify (
|
||||||
hwnd,
|
hwnd,
|
||||||
TVN_ITEMEXPANDED,
|
TVN_ITEMEXPANDED,
|
||||||
0,
|
TVE_EXPAND,
|
||||||
0,
|
0,
|
||||||
(HTREEITEM)expand);
|
(HTREEITEM)expand);
|
||||||
}
|
}
|
||||||
wineItem->state |= TVIS_EXPANDED;
|
else
|
||||||
|
{
|
||||||
|
/* this item has already been expanded */
|
||||||
|
wineItem->state |= TVIS_EXPANDED;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TVE_EXPANDPARTIAL:
|
case TVE_EXPANDPARTIAL:
|
||||||
|
@ -2197,8 +2538,7 @@ TREEVIEW_LButtonDoubleClick (HWND hwnd, WPARAM wParam, LPARAM lParam)
|
||||||
TRACE (treeview,"item %d \n",(INT)wineItem->hItem);
|
TRACE (treeview,"item %d \n",(INT)wineItem->hItem);
|
||||||
|
|
||||||
if (TREEVIEW_SendSimpleNotify (hwnd, NM_DBLCLK)!=TRUE) { /* FIXME!*/
|
if (TREEVIEW_SendSimpleNotify (hwnd, NM_DBLCLK)!=TRUE) { /* FIXME!*/
|
||||||
wineItem->state &= ~TVIS_EXPANDEDONCE;
|
TREEVIEW_Expand (hwnd, (WPARAM) TVE_TOGGLE, (LPARAM) wineItem->hItem);
|
||||||
TREEVIEW_Expand (hwnd, (WPARAM) TVE_TOGGLE, (LPARAM) wineItem->hItem);
|
|
||||||
}
|
}
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
@ -2738,7 +3078,6 @@ TREEVIEW_KeyDown (HWND hwnd, WPARAM wParam, LPARAM lParam)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
LRESULT WINAPI
|
LRESULT WINAPI
|
||||||
TREEVIEW_WindowProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
TREEVIEW_WindowProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
||||||
{
|
{
|
||||||
|
@ -2823,8 +3162,7 @@ TREEVIEW_WindowProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
case TVM_SORTCHILDRENCB:
|
case TVM_SORTCHILDRENCB:
|
||||||
FIXME (treeview, "Unimplemented msg TVM_SORTCHILDRENCB\n");
|
return TREEVIEW_SortChildrenCB(hwnd, wParam, lParam);
|
||||||
return 0;
|
|
||||||
|
|
||||||
case TVM_ENDEDITLABELNOW:
|
case TVM_ENDEDITLABELNOW:
|
||||||
FIXME (treeview, "Unimplemented msg TVM_ENDEDITLABELNOW\n");
|
FIXME (treeview, "Unimplemented msg TVM_ENDEDITLABELNOW\n");
|
||||||
|
|
|
@ -8,6 +8,8 @@
|
||||||
#ifndef __WINE_TREEVIEW_H
|
#ifndef __WINE_TREEVIEW_H
|
||||||
#define __WINE_TREEVIEW_H
|
#define __WINE_TREEVIEW_H
|
||||||
|
|
||||||
|
#include "commctrl.h"
|
||||||
|
|
||||||
#define MINIMUM_INDENT 10
|
#define MINIMUM_INDENT 10
|
||||||
#define TV_REFRESH_DELAY 100 /* 100 ms delay between two refreshes */
|
#define TV_REFRESH_DELAY 100 /* 100 ms delay between two refreshes */
|
||||||
#define TV_DEFAULTITEMHEIGHT 16
|
#define TV_DEFAULTITEMHEIGHT 16
|
||||||
|
@ -75,6 +77,7 @@ typedef struct tagTREEVIEW_INFO
|
||||||
WNDPROC wpEditOrig; /* needed for subclassing edit control */
|
WNDPROC wpEditOrig; /* needed for subclassing edit control */
|
||||||
HIMAGELIST himlNormal;
|
HIMAGELIST himlNormal;
|
||||||
HIMAGELIST himlState;
|
HIMAGELIST himlState;
|
||||||
|
LPTVSORTCB pCallBackSort; /* ptr to TVSORTCB struct for callback sorting */
|
||||||
TREEVIEW_ITEM *items; /* itemlist */
|
TREEVIEW_ITEM *items; /* itemlist */
|
||||||
INT *freeList; /* bitmap indicating which elements are valid */
|
INT *freeList; /* bitmap indicating which elements are valid */
|
||||||
/* 1=valid, 0=free; */
|
/* 1=valid, 0=free; */
|
||||||
|
|
Loading…
Reference in New Issue