Implements +/-, PgUp/PgDown, Home/End, Left/Right, Up/Down.
This commit is contained in:
parent
923b66dbe7
commit
49c1ca28d4
|
@ -97,10 +97,12 @@ TREEVIEW_Edit_SubclassProc (HWND hwnd, UINT uMsg, WPARAM wParam,
|
|||
FIXME: check other failures.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
static TREEVIEW_ITEM *
|
||||
TREEVIEW_ValidItem (TREEVIEW_INFO *infoPtr,HTREEITEM handle)
|
||||
/***************************************************************************
|
||||
* This method returns the TREEVIEW_ITEM object given the handle
|
||||
*/
|
||||
static TREEVIEW_ITEM* TREEVIEW_ValidItem(
|
||||
TREEVIEW_INFO *infoPtr,
|
||||
HTREEITEM handle)
|
||||
{
|
||||
|
||||
if ((!handle) || (handle>infoPtr->uMaxHandle)) return NULL;
|
||||
|
@ -109,75 +111,159 @@ TREEVIEW_ValidItem (TREEVIEW_INFO *infoPtr,HTREEITEM handle)
|
|||
return & infoPtr->items[(INT)handle];
|
||||
}
|
||||
|
||||
|
||||
|
||||
static TREEVIEW_ITEM *TREEVIEW_GetPrevListItem (TREEVIEW_INFO *infoPtr,
|
||||
TREEVIEW_ITEM *tvItem)
|
||||
/***************************************************************************
|
||||
* This method returns the last expanded child item of a tree node
|
||||
*/
|
||||
static TREEVIEW_ITEM *TREEVIEW_GetLastListItem(
|
||||
TREEVIEW_INFO *infoPtr,
|
||||
TREEVIEW_ITEM *tvItem)
|
||||
|
||||
{
|
||||
TREEVIEW_ITEM *wineItem;
|
||||
TREEVIEW_ITEM *wineItem = tvItem;
|
||||
|
||||
if (tvItem->upsibling) {
|
||||
wineItem=& infoPtr->items[(INT)tvItem->upsibling];
|
||||
if ((wineItem->firstChild) && (wineItem->state & TVIS_EXPANDED)) {
|
||||
wineItem=& infoPtr->items[(INT)wineItem->firstChild];
|
||||
while (wineItem->sibling)
|
||||
wineItem= & infoPtr->items[(INT)wineItem->sibling];
|
||||
}
|
||||
return wineItem;
|
||||
}
|
||||
/*
|
||||
* Get this item last sibling
|
||||
*/
|
||||
while (wineItem->sibling)
|
||||
wineItem=& infoPtr->items [(INT)wineItem->sibling];
|
||||
|
||||
wineItem=tvItem;
|
||||
while (wineItem->parent) {
|
||||
wineItem=& infoPtr->items[(INT)wineItem->parent];
|
||||
if (wineItem->upsibling)
|
||||
return (& infoPtr->items[(INT)wineItem->upsibling]);
|
||||
}
|
||||
/*
|
||||
* If the last sibling has expanded children, restart.
|
||||
*/
|
||||
if ( ( wineItem->cChildren > 0 ) && ( wineItem->state & TVIS_EXPANDED) )
|
||||
return TREEVIEW_GetLastListItem(
|
||||
infoPtr,
|
||||
&(infoPtr->items[(INT)wineItem->firstChild]));
|
||||
|
||||
return wineItem;
|
||||
return wineItem;
|
||||
}
|
||||
|
||||
/***************************************************************************
|
||||
* This method returns the previous physical item in the list not
|
||||
* considering the tree hierarchy.
|
||||
*/
|
||||
static TREEVIEW_ITEM *TREEVIEW_GetPrevListItem(
|
||||
TREEVIEW_INFO *infoPtr,
|
||||
TREEVIEW_ITEM *tvItem)
|
||||
{
|
||||
if (tvItem->upsibling)
|
||||
{
|
||||
/*
|
||||
* This item has a upsibling, get the last item. Since, GetLastListItem
|
||||
* first looks at siblings, we must feed it with the first child.
|
||||
*/
|
||||
TREEVIEW_ITEM *upItem = &infoPtr->items[(INT)tvItem->upsibling];
|
||||
|
||||
if ( ( upItem->cChildren > 0 ) && ( upItem->state & TVIS_EXPANDED) )
|
||||
return TREEVIEW_GetLastListItem(
|
||||
infoPtr,
|
||||
&infoPtr->items[(INT)upItem->firstChild]);
|
||||
else
|
||||
return upItem;
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
* this item does not have a upsibling, get the parent
|
||||
*/
|
||||
if (tvItem->parent)
|
||||
return &infoPtr->items[(INT)tvItem->parent];
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
static TREEVIEW_ITEM *TREEVIEW_GetNextListItem (TREEVIEW_INFO *infoPtr,
|
||||
TREEVIEW_ITEM *tvItem)
|
||||
|
||||
/***************************************************************************
|
||||
* This method returns the next physical item in the treeview not
|
||||
* considering the tree hierarchy.
|
||||
*/
|
||||
static TREEVIEW_ITEM *TREEVIEW_GetNextListItem(
|
||||
TREEVIEW_INFO *infoPtr,
|
||||
TREEVIEW_ITEM *tvItem)
|
||||
{
|
||||
TREEVIEW_ITEM *wineItem;
|
||||
TREEVIEW_ITEM *wineItem = NULL;
|
||||
|
||||
/*
|
||||
* If this item has children and is expanded, return the first child
|
||||
*/
|
||||
if ((tvItem->firstChild) && (tvItem->state & TVIS_EXPANDED))
|
||||
return (& infoPtr->items[(INT)tvItem->firstChild]);
|
||||
|
||||
|
||||
if (tvItem->sibling)
|
||||
/*
|
||||
* try to get the sibling
|
||||
*/
|
||||
if (tvItem->sibling)
|
||||
return (& infoPtr->items[(INT)tvItem->sibling]);
|
||||
|
||||
wineItem=tvItem;
|
||||
while (wineItem->parent) {
|
||||
wineItem=& infoPtr->items [(INT)wineItem->parent];
|
||||
if (wineItem->sibling)
|
||||
return (& infoPtr->items [(INT)wineItem->sibling]);
|
||||
}
|
||||
/*
|
||||
* Otherwise, get the parent's sibling.
|
||||
*/
|
||||
wineItem=tvItem;
|
||||
while (wineItem->parent) {
|
||||
wineItem=& infoPtr->items [(INT)wineItem->parent];
|
||||
if (wineItem->sibling)
|
||||
return (& infoPtr->items [(INT)wineItem->sibling]);
|
||||
}
|
||||
|
||||
return NULL; /* was wineItem */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static TREEVIEW_ITEM *TREEVIEW_GetLastListItem (TREEVIEW_INFO *infoPtr,
|
||||
TREEVIEW_ITEM *tvItem)
|
||||
|
||||
/***************************************************************************
|
||||
* This method returns the nth item starting at the given item. It returns
|
||||
* the last item (or first) we we run out of items.
|
||||
*
|
||||
* Will scroll backward if count is <0.
|
||||
* forward if count is >0.
|
||||
*/
|
||||
static TREEVIEW_ITEM *TREEVIEW_GetListItem(
|
||||
TREEVIEW_INFO *infoPtr,
|
||||
TREEVIEW_ITEM *tvItem,
|
||||
LONG count)
|
||||
{
|
||||
TREEVIEW_ITEM *wineItem;
|
||||
TREEVIEW_ITEM *previousItem = NULL;
|
||||
TREEVIEW_ITEM *wineItem = tvItem;
|
||||
LONG iter = 0;
|
||||
|
||||
wineItem=tvItem;
|
||||
while (wineItem->sibling)
|
||||
wineItem=& infoPtr->items [(INT)wineItem->sibling];
|
||||
if (count > 0)
|
||||
{
|
||||
/* Find count item downward */
|
||||
while ((iter++ < count) && (wineItem != NULL))
|
||||
{
|
||||
/* Keep a pointer to the previous in case we ask for more than we got */
|
||||
previousItem = wineItem;
|
||||
wineItem = TREEVIEW_GetNextListItem(infoPtr, wineItem);
|
||||
}
|
||||
|
||||
return wineItem;
|
||||
if (wineItem == NULL)
|
||||
wineItem = previousItem;
|
||||
}
|
||||
else if (count < 0)
|
||||
{
|
||||
/* Find count item upward */
|
||||
while ((iter-- > count) && (wineItem != NULL))
|
||||
{
|
||||
/* Keep a pointer to the previous in case we ask for more than we got */
|
||||
previousItem = wineItem;
|
||||
wineItem = TREEVIEW_GetPrevListItem(infoPtr, wineItem);
|
||||
}
|
||||
|
||||
if (wineItem == NULL)
|
||||
wineItem = previousItem;
|
||||
}
|
||||
else
|
||||
wineItem = NULL;
|
||||
|
||||
return wineItem;
|
||||
}
|
||||
|
||||
|
||||
static void TREEVIEW_RemoveAllChildren (HWND hwnd,
|
||||
TREEVIEW_ITEM *parentItem)
|
||||
|
||||
/***************************************************************************
|
||||
* This method
|
||||
*/
|
||||
static void TREEVIEW_RemoveAllChildren(
|
||||
HWND hwnd,
|
||||
TREEVIEW_ITEM *parentItem)
|
||||
{
|
||||
TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(hwnd);
|
||||
TREEVIEW_ITEM *killItem;
|
||||
|
@ -722,8 +808,6 @@ TREEVIEW_GetItemRect (HWND hwnd, WPARAM wParam, LPARAM lParam)
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static LRESULT
|
||||
TREEVIEW_GetVisibleCount (HWND hwnd, WPARAM wParam, LPARAM lParam)
|
||||
|
||||
|
@ -1481,25 +1565,20 @@ TREEVIEW_Size (HWND hwnd, WPARAM wParam, LPARAM lParam)
|
|||
|
||||
{
|
||||
TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(hwnd);
|
||||
RECT parent_rect;
|
||||
UINT cx,cy;
|
||||
HWND parent;
|
||||
|
||||
if (infoPtr->bAutoSize) {
|
||||
if (infoPtr->bAutoSize)
|
||||
{
|
||||
infoPtr->bAutoSize = FALSE;
|
||||
return 0;
|
||||
}
|
||||
infoPtr->bAutoSize = TRUE;
|
||||
}
|
||||
infoPtr->bAutoSize = TRUE;
|
||||
|
||||
if (!wParam) {
|
||||
parent = GetParent (hwnd);
|
||||
GetClientRect(parent, &parent_rect);
|
||||
cx=LOWORD (lParam);
|
||||
cy=HIWORD (lParam);
|
||||
SetWindowPos (hwnd, 0, parent_rect.left, parent_rect.top,
|
||||
cx, cy, SWP_NOZORDER);
|
||||
} else {
|
||||
FIXME (treeview,"WM_SIZE flag %x %lx not handled\n", wParam, lParam);
|
||||
if (wParam == SIZE_RESTORED)
|
||||
{
|
||||
infoPtr->uTotalWidth = LOWORD (lParam);
|
||||
infoPtr->uTotalHeight = HIWORD (lParam);
|
||||
} else {
|
||||
FIXME (treeview,"WM_SIZE flag %x %lx not handled\n", wParam, lParam);
|
||||
}
|
||||
|
||||
TREEVIEW_QueueRefresh (hwnd);
|
||||
|
@ -1931,7 +2010,6 @@ TREEVIEW_SendCustomDrawItemNotify (HWND hwnd, HDC hdc,
|
|||
know if it also applies here.
|
||||
*/
|
||||
|
||||
|
||||
static LRESULT
|
||||
TREEVIEW_Expand (HWND hwnd, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
|
@ -1955,7 +2033,7 @@ TREEVIEW_Expand (HWND hwnd, WPARAM wParam, LPARAM lParam)
|
|||
return 0;
|
||||
}
|
||||
|
||||
if (flag & TVE_TOGGLE) { /* FIXME: check exact behaviour here */
|
||||
if (flag == TVE_TOGGLE) { /* FIXME: check exact behaviour here */
|
||||
flag &= ~TVE_TOGGLE; /* ie: bitwise ops or 'case' ops */
|
||||
if (wineItem->state & TVIS_EXPANDED)
|
||||
flag |= TVE_COLLAPSE;
|
||||
|
@ -1977,7 +2055,7 @@ TREEVIEW_Expand (HWND hwnd, WPARAM wParam, LPARAM lParam)
|
|||
if (!wineItem->state & TVIS_EXPANDED)
|
||||
return 0;
|
||||
|
||||
wineItem->state &= ~TVIS_EXPANDED;
|
||||
wineItem->state &= ~(TVIS_EXPANDEDONCE | TVIS_EXPANDED);
|
||||
break;
|
||||
|
||||
case TVE_EXPAND:
|
||||
|
@ -2018,8 +2096,6 @@ TREEVIEW_Expand (HWND hwnd, WPARAM wParam, LPARAM lParam)
|
|||
|
||||
|
||||
|
||||
|
||||
|
||||
static TREEVIEW_ITEM *
|
||||
TREEVIEW_HitTestPoint (HWND hwnd, POINT pt)
|
||||
{
|
||||
|
@ -2426,65 +2502,6 @@ TREEVIEW_SetFont (HWND hwnd, WPARAM wParam, LPARAM lParam)
|
|||
}
|
||||
|
||||
|
||||
/* FIXME: does KEYDOWN also send notifications?? If so, use
|
||||
TREEVIEW_DoSelectItem.
|
||||
*/
|
||||
|
||||
|
||||
static LRESULT
|
||||
TREEVIEW_KeyDown (HWND hwnd, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(hwnd);
|
||||
TREEVIEW_ITEM *prevItem,*newItem;
|
||||
int prevSelect;
|
||||
|
||||
|
||||
TRACE (treeview,"%x %lx\n",wParam, lParam);
|
||||
prevSelect=(INT)infoPtr->selectedItem;
|
||||
if (!prevSelect) return FALSE;
|
||||
|
||||
prevItem= TREEVIEW_ValidItem (infoPtr, (HTREEITEM)prevSelect);
|
||||
|
||||
newItem=NULL;
|
||||
switch (wParam) {
|
||||
case VK_UP:
|
||||
newItem=TREEVIEW_GetPrevListItem (infoPtr, prevItem);
|
||||
if (!newItem)
|
||||
newItem=& infoPtr->items[(INT)infoPtr->TopRootItem];
|
||||
break;
|
||||
case VK_DOWN:
|
||||
newItem=TREEVIEW_GetNextListItem (infoPtr, prevItem);
|
||||
if (!newItem) newItem=prevItem;
|
||||
break;
|
||||
case VK_HOME:
|
||||
newItem=& infoPtr->items[(INT)infoPtr->TopRootItem];
|
||||
break;
|
||||
case VK_END:
|
||||
newItem=& infoPtr->items[(INT)infoPtr->TopRootItem];
|
||||
newItem=TREEVIEW_GetLastListItem (infoPtr, newItem);
|
||||
break;
|
||||
case VK_PRIOR:
|
||||
case VK_NEXT:
|
||||
case VK_BACK:
|
||||
case VK_RETURN:
|
||||
FIXME (treeview, "%x not implemented\n", wParam);
|
||||
break;
|
||||
}
|
||||
|
||||
if (!newItem) return FALSE;
|
||||
|
||||
if (prevItem!=newItem) {
|
||||
prevItem->state &= ~TVIS_SELECTED;
|
||||
newItem->state |= TVIS_SELECTED;
|
||||
infoPtr->selectedItem=newItem->hItem;
|
||||
TREEVIEW_QueueRefresh (hwnd);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static LRESULT
|
||||
TREEVIEW_VScroll (HWND hwnd, WPARAM wParam, LPARAM lParam)
|
||||
|
@ -2577,6 +2594,149 @@ TREEVIEW_HScroll (HWND hwnd, WPARAM wParam, LPARAM lParam)
|
|||
}
|
||||
|
||||
|
||||
/* FIXME: does KEYDOWN also send notifications?? If so, use
|
||||
TREEVIEW_DoSelectItem.
|
||||
*/
|
||||
static LRESULT
|
||||
TREEVIEW_KeyDown (HWND hwnd, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(hwnd);
|
||||
TREEVIEW_ITEM *prevItem,*newItem;
|
||||
int prevSelect;
|
||||
|
||||
|
||||
TRACE (treeview,"%x %lx\n",wParam, lParam);
|
||||
prevSelect=(INT)infoPtr->selectedItem;
|
||||
if (!prevSelect) return FALSE;
|
||||
|
||||
prevItem= TREEVIEW_ValidItem (infoPtr, (HTREEITEM)prevSelect);
|
||||
|
||||
newItem=NULL;
|
||||
switch (wParam) {
|
||||
case VK_UP:
|
||||
newItem=TREEVIEW_GetPrevListItem (infoPtr, prevItem);
|
||||
|
||||
if (!newItem)
|
||||
newItem=& infoPtr->items[(INT)infoPtr->TopRootItem];
|
||||
|
||||
if (! newItem->visible)
|
||||
TREEVIEW_VScroll(hwnd, SB_LINEUP, 0);
|
||||
|
||||
break;
|
||||
|
||||
case VK_DOWN:
|
||||
newItem=TREEVIEW_GetNextListItem (infoPtr, prevItem);
|
||||
|
||||
if (!newItem)
|
||||
newItem=prevItem;
|
||||
|
||||
if (! newItem->visible)
|
||||
TREEVIEW_VScroll(hwnd, SB_LINEDOWN, 0);
|
||||
break;
|
||||
|
||||
case VK_HOME:
|
||||
newItem=& infoPtr->items[(INT)infoPtr->TopRootItem];
|
||||
infoPtr->cy = 0;
|
||||
break;
|
||||
|
||||
case VK_END:
|
||||
newItem=& infoPtr->items[(INT)infoPtr->TopRootItem];
|
||||
newItem=TREEVIEW_GetLastListItem (infoPtr, newItem);
|
||||
|
||||
if (! newItem->visible)
|
||||
infoPtr->cy = infoPtr->uTotalHeight-infoPtr->uVisibleHeight;
|
||||
|
||||
break;
|
||||
|
||||
case VK_LEFT:
|
||||
if ( (prevItem->cChildren > 0) && (prevItem->state & TVIS_EXPANDED) )
|
||||
{
|
||||
TREEVIEW_Expand(hwnd, TVE_COLLAPSE, prevSelect );
|
||||
}
|
||||
else if ((INT)prevItem->parent)
|
||||
{
|
||||
newItem = (& infoPtr->items[(INT)prevItem->parent]);
|
||||
if (! newItem->visible)
|
||||
/* FIXME find a way to make this item the first visible... */
|
||||
newItem = NULL;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case VK_RIGHT:
|
||||
if ( ( prevItem->cChildren > 0) ||
|
||||
( prevItem->cChildren == I_CHILDRENCALLBACK))
|
||||
{
|
||||
if (! (prevItem->state & TVIS_EXPANDED))
|
||||
TREEVIEW_Expand(hwnd, TVE_EXPAND, prevSelect );
|
||||
else
|
||||
newItem = (& infoPtr->items[(INT)prevItem->firstChild]);
|
||||
}
|
||||
break;
|
||||
|
||||
case VK_ADD:
|
||||
if (! (prevItem->state & TVIS_EXPANDED))
|
||||
TREEVIEW_Expand(hwnd, TVE_EXPAND, prevSelect );
|
||||
break;
|
||||
|
||||
case VK_SUBTRACT:
|
||||
if (prevItem->state & TVIS_EXPANDED)
|
||||
TREEVIEW_Expand(hwnd, TVE_COLLAPSE, prevSelect );
|
||||
break;
|
||||
|
||||
case VK_PRIOR:
|
||||
|
||||
newItem=TREEVIEW_GetListItem(
|
||||
infoPtr,
|
||||
prevItem,
|
||||
-1*(TREEVIEW_GetVisibleCount(hwnd,0,0)-3));
|
||||
if (!newItem)
|
||||
newItem=prevItem;
|
||||
|
||||
if (! newItem->visible)
|
||||
TREEVIEW_VScroll(hwnd, SB_PAGEUP, 0);
|
||||
|
||||
break;
|
||||
|
||||
case VK_NEXT:
|
||||
newItem=TREEVIEW_GetListItem(
|
||||
infoPtr,
|
||||
prevItem,
|
||||
TREEVIEW_GetVisibleCount(hwnd,0,0)-3);
|
||||
|
||||
if (!newItem)
|
||||
newItem=prevItem;
|
||||
|
||||
if (! newItem->visible)
|
||||
TREEVIEW_VScroll(hwnd, SB_PAGEDOWN, 0);
|
||||
|
||||
break;
|
||||
|
||||
case VK_BACK:
|
||||
|
||||
case VK_RETURN:
|
||||
|
||||
default:
|
||||
FIXME (treeview, "%x not implemented\n", wParam);
|
||||
break;
|
||||
}
|
||||
|
||||
if (!newItem) return FALSE;
|
||||
|
||||
if (prevItem!=newItem) {
|
||||
prevItem->state &= ~TVIS_SELECTED;
|
||||
newItem->state |= TVIS_SELECTED;
|
||||
infoPtr->selectedItem=newItem->hItem;
|
||||
TREEVIEW_QueueRefresh (hwnd);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
LRESULT WINAPI
|
||||
|
|
Loading…
Reference in New Issue