[PATCH 8/8] explorerframe/nstc: Implement expanding of nodes.
David Hedberg
david.hedberg at gmail.com
Thu Jul 29 14:26:07 CDT 2010
---
dlls/explorerframe/nstc.c | 160 +++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 160 insertions(+), 0 deletions(-)
diff --git a/dlls/explorerframe/nstc.c b/dlls/explorerframe/nstc.c
index a6793b0..ce04fa3 100644
--- a/dlls/explorerframe/nstc.c
+++ b/dlls/explorerframe/nstc.c
@@ -95,6 +95,22 @@ static HRESULT events_OnItemDeleted(NSTC2Impl *This, IShellItem *psi, BOOL fIsRo
This->pnstce, psi, fIsRoot);
}
+static HRESULT events_OnBeforeExpand(NSTC2Impl *This, IShellItem *psi)
+{
+ if(!This->pnstce)
+ return S_OK;
+ return INameSpaceTreeControlEvents_OnBeforeExpand(
+ This->pnstce, psi);
+}
+
+static HRESULT events_OnAfterExpand(NSTC2Impl *This, IShellItem *psi)
+{
+ if(!This->pnstce)
+ return S_OK;
+ return INameSpaceTreeControlEvents_OnAfterExpand(
+ This->pnstce, psi);
+}
+
/*************************************************************************
* NamespaceTree helper functions
*/
@@ -157,6 +173,25 @@ static IShellItem *shellitem_from_treeitem(NSTC2Impl *This, HTREEITEM hitem)
return (IShellItem*)tvi.lParam;
}
+static nstc_root *root_for_treeitem(NSTC2Impl *This, HTREEITEM hitem)
+{
+ HTREEITEM tmp, hroot = hitem;
+ nstc_root *root;
+
+ /* Work our way up the hierarchy */
+ for(tmp = hitem; tmp != NULL; hroot = tmp?tmp:hroot)
+ tmp = (HTREEITEM)SendMessageW(This->hwnd_tv, TVM_GETNEXTITEM,
+ TVGN_PARENT, (LPARAM)hroot);
+
+ /* Search through the list of roots for a match */
+ LIST_FOR_EACH_ENTRY(root, &This->roots, nstc_root, entry)
+ if(root->htreeitem == hroot)
+ break;
+
+ TRACE("root is %p\n", root);
+ return root;
+}
+
/* From brsfolder.c */
static int GetIcon(LPCITEMIDLIST lpi, UINT extra_flags)
{
@@ -222,6 +257,86 @@ static HTREEITEM insert_shellitem(NSTC2Impl *This, IShellItem *psi,
return hinserted;
}
+static void fill_sublevel(NSTC2Impl *This, HTREEITEM hitem)
+{
+ IShellItem *psiParent = shellitem_from_treeitem(This, hitem);
+ nstc_root *root = root_for_treeitem(This, hitem);
+ LPITEMIDLIST pidl_parent;
+ IShellFolder *psfDesktop, *psf;
+ IEnumIDList *peidl;
+ HRESULT hres;
+
+ hres = SHGetIDListFromObject((IUnknown*)psiParent, &pidl_parent);
+ if(FAILED(hres))
+ {
+ ERR("Failed to get pidl. \n");
+ return;
+ }
+
+ /* Bind to the ShellFolder for the item */
+ SHGetDesktopFolder(&psfDesktop);
+ hres = IShellFolder_BindToObject(psfDesktop, pidl_parent, NULL,
+ &IID_IShellFolder, (void**)&psf);
+ if(FAILED(hres))
+ {
+ LPITEMIDLIST pidl_desktop;
+ /* Check if the folder is the desktop folder */
+ SHGetIDListFromObject((IUnknown*)psfDesktop, &pidl_desktop);
+ if(ILIsEqual(pidl_desktop, pidl_parent))
+ {
+ psf = psfDesktop;
+ ILFree(pidl_desktop);
+ IShellFolder_AddRef(psf);
+ }
+ else
+ {
+ ERR("Failed to bind to ShellFolder.\n");
+ ILFree(pidl_desktop);
+ ILFree(pidl_parent);
+ IShellFolder_Release(psfDesktop);
+ return;
+ }
+ }
+ ILFree(pidl_parent);
+ IShellFolder_Release(psfDesktop);
+
+ /* Enumerate the objects in accordance with the settings for this root */
+ hres = IShellFolder_EnumObjects(psf, NULL, root->enum_flags, &peidl);
+ if(SUCCEEDED(hres))
+ {
+ LPITEMIDLIST pidl;
+ IShellItem *psi;
+ ULONG fetched;
+
+ while( S_OK == IEnumIDList_Next(peidl, 1, &pidl, &fetched) )
+ {
+ hres = SHCreateShellItem(NULL, psf , pidl, &psi);
+ ILFree(pidl);
+ if(SUCCEEDED(hres))
+ {
+ if(insert_shellitem(This, psi, hitem, NULL))
+ events_OnItemAdded(This, psi, FALSE);
+
+ IShellItem_Release(psi);
+ }
+ else
+ {
+ TRACE("Failed to create a shellitem.\n");
+ }
+ }
+ IEnumIDList_Release(peidl);
+ }
+ else
+ {
+ ERR("Failed to get IEnumIDList (%x)\n", hres);
+ return;
+ }
+
+ IShellFolder_Release(psf);
+
+ return;
+}
+
/*************************************************************************
* NamespaceTree Window Functions
*/
@@ -336,6 +451,49 @@ static LRESULT on_tvn_getdispinfow(NSTC2Impl *This, LPARAM lParam)
return FALSE;
}
+static BOOL treenode_has_subfolders(NSTC2Impl *This, HTREEITEM node)
+{
+ return SendMessageW(This->hwnd_tv, TVM_GETNEXTITEM, TVGN_CHILD, (LPARAM)node);
+}
+
+static LRESULT on_tvn_itemexpandingw(NSTC2Impl *This, LPARAM lParam)
+{
+ NMTREEVIEWW *nmtv = (NMTREEVIEWW*)lParam;
+ IShellItem *psi;
+ TRACE("%p\n", This);
+
+ psi = shellitem_from_treeitem(This, nmtv->itemNew.hItem);
+ events_OnBeforeExpand(This, psi);
+
+ if(!treenode_has_subfolders(This, nmtv->itemNew.hItem))
+ {
+ /* The node has no children, try to find some */
+ fill_sublevel(This, nmtv->itemNew.hItem);
+
+ if(!treenode_has_subfolders(This, nmtv->itemNew.hItem))
+ {
+ TVITEMEXW tvi;
+ /* Still no children, remove the expando (if any). */
+ tvi.hItem = nmtv->itemNew.hItem;
+ tvi.mask = TVIF_CHILDREN;
+ tvi.cChildren = 0;
+ SendMessageW(This->hwnd_tv, TVM_SETITEMW, 0, (LPARAM)&tvi);
+ }
+ }
+ return FALSE;
+}
+
+static LRESULT on_tvn_itemexpandedw(NSTC2Impl *This, LPARAM lParam)
+{
+ NMTREEVIEWW *nmtv = (NMTREEVIEWW*)lParam;
+ IShellItem *psi;
+ TRACE("%p\n", This);
+
+ psi = shellitem_from_treeitem(This, nmtv->itemNew.hItem);
+ events_OnAfterExpand(This, psi);
+ return TRUE;
+}
+
static LRESULT CALLBACK NSTC2_WndProc(HWND hWnd, UINT uMessage,
WPARAM wParam, LPARAM lParam)
{
@@ -353,6 +511,8 @@ static LRESULT CALLBACK NSTC2_WndProc(HWND hWnd, UINT uMessage,
{
case TVN_DELETEITEMW: return on_tvn_deleteitemw(This, lParam);
case TVN_GETDISPINFOW: return on_tvn_getdispinfow(This, lParam);
+ case TVN_ITEMEXPANDINGW: return on_tvn_itemexpandingw(This, lParam);
+ case TVN_ITEMEXPANDEDW: return on_tvn_itemexpandedw(This, lParam);
default: break;
}
break;
--
1.7.2
More information about the wine-patches
mailing list