//+------------------------------------------------------------------------- // // Microsoft Windows // // Copyright (C) Microsoft Corporation, 1999 - 1999 // // File: trobimpl.cpp // //-------------------------------------------------------------------------- // trobimpl.cpp : implementation file // #include "stdafx.h" #include "amc.h" #include "trobimpl.h" ///////////////////////////////////////////////////////////////////////////// // CTreeObserverTreeImpl CTreeObserverTreeImpl::CTreeObserverTreeImpl() : m_pTreeSrc(NULL), m_dwStyle(0), m_tidRoot(NULL) { } CTreeObserverTreeImpl::~CTreeObserverTreeImpl() { } HRESULT CTreeObserverTreeImpl::SetStyle(DWORD dwStyle) { ASSERT((dwStyle & ~(TOBSRV_HIDEROOT | TOBSRV_FOLDERSONLY)) == 0); m_dwStyle = dwStyle; return S_OK; } HRESULT CTreeObserverTreeImpl::SetTreeSource(CTreeSource* pTreeSrc) { // Window may be gone before source is disconnected if (IsWindow(m_hWnd)) DeleteAllItems(); m_pTreeSrc = pTreeSrc; if (pTreeSrc == NULL) return S_OK; // Must have window before populating tree ASSERT(IsWindow(m_hWnd)); // populate top level of tree TREEITEMID tidRoot = m_pTreeSrc->GetRootItem(); if (tidRoot != NULL) { // Trigger handler as though item were just added ItemAdded(tidRoot); } return S_OK; } TREEITEMID CTreeObserverTreeImpl::GetSelection() { HTREEITEM hti = GetSelectedItem(); if (hti) return static_cast(GetItemData(hti)); else return NULL; } void CTreeObserverTreeImpl::SetSelection(TREEITEMID tid) { ASSERT(m_pTreeSrc != NULL); HTREEITEM hti = FindHTI(tid, TRUE); ASSERT(hti != NULL); SelectItem(hti); EnsureVisible(hti); } void CTreeObserverTreeImpl::ExpandItem(TREEITEMID tid) { ASSERT(m_pTreeSrc != NULL); HTREEITEM hti = FindHTI(tid, TRUE); if (hti != NULL) Expand(hti, TVE_EXPAND); } BOOL CTreeObserverTreeImpl::IsItemExpanded(TREEITEMID tid) { ASSERT(m_pTreeSrc != NULL); HTREEITEM hti = FindHTI(tid, TRUE); return (IsItemExpanded(hti)); } HTREEITEM CTreeObserverTreeImpl::FindChildHTI(HTREEITEM htiParent, TREEITEMID tid) { HTREEITEM htiTemp; if (htiParent == TVI_ROOT) htiTemp = GetRootItem(); else htiTemp = GetChildItem(htiParent); while (htiTemp && GetItemData(htiTemp) != tid) { htiTemp = GetNextSiblingItem(htiTemp); } return htiTemp; } HTREEITEM CTreeObserverTreeImpl::FindHTI(TREEITEMID tid, BOOL bAutoExpand) { ASSERT(m_pTreeSrc != NULL); if (tid == NULL || (tid == m_tidRoot && RootHidden())) return TVI_ROOT; HTREEITEM htiParent = FindHTI(m_pTreeSrc->GetParentItem(tid), bAutoExpand); if (htiParent == NULL) return NULL; if (bAutoExpand && !WasItemExpanded(htiParent)) Expand(htiParent, TVE_EXPAND); return FindChildHTI(htiParent, tid); } HTREEITEM CTreeObserverTreeImpl::AddOneItem(HTREEITEM htiParent, HTREEITEM htiAfter, TREEITEMID tid) { ASSERT(m_pTreeSrc != NULL); TVINSERTSTRUCT insert; insert.hParent = htiParent; insert.hInsertAfter = htiAfter; insert.item.mask = TVIF_PARAM | TVIF_TEXT | TVIF_CHILDREN | TVIF_IMAGE | TVIF_SELECTEDIMAGE; insert.item.lParam = tid; insert.item.iImage = m_pTreeSrc->GetItemImage(tid); insert.item.iSelectedImage = insert.item.iImage; insert.item.cChildren = m_pTreeSrc->GetChildItem(tid) ? 1 : 0; TCHAR name[MAX_PATH]; m_pTreeSrc->GetItemName(tid, name, countof(name)); insert.item.pszText = name; return InsertItem(&insert); } void CTreeObserverTreeImpl::AddChildren(HTREEITEM hti) { ASSERT(m_pTreeSrc != NULL); TREEITEMID tidChild; // if adding top level item if (hti == TVI_ROOT) { if (RootHidden()) { // if root is hidden, add its children ASSERT(m_tidRoot != 0); tidChild = m_pTreeSrc->GetChildItem(m_tidRoot); } else { // else add root item itself tidChild = m_pTreeSrc->GetRootItem(); } } else { // convert to TID, then get its child TREEITEMID tid = static_cast(GetItemData(hti)); ASSERT(tid != 0); tidChild = m_pTreeSrc->GetChildItem(tid); } while (tidChild) { // Add visible items if (!ShowFoldersOnly() || m_pTreeSrc->IsFolderItem(tidChild)) AddOneItem(hti, TVI_LAST, tidChild); tidChild = m_pTreeSrc->GetNextSiblingItem(tidChild); } } void CTreeObserverTreeImpl::ItemAdded(TREEITEMID tid) { ASSERT(m_pTreeSrc != NULL); ASSERT(tid != 0); // if only folders visible, skip this item if (ShowFoldersOnly() && !m_pTreeSrc->IsFolderItem(tid)) return; // Get parent tree item TREEITEMID tidParent = m_pTreeSrc->GetParentItem(tid); // if this is the tree root and the root is not displayed if (tidParent == NULL && RootHidden()) { // Can only have one hidden root ASSERT(m_tidRoot == NULL); // Just save TID as the hidden root and return m_tidRoot = tid; // since root is hidden, add its children to the tree AddChildren(TVI_ROOT); return; } // Add new item to tree HTREEITEM htiParent = FindHTI(tidParent); // Parent exists and has been expanded if (WasItemExpanded(htiParent)) { // Determine previous tree item // Because the source doesn't support GetPrevSibling // we have to get the next TID then use our own tree to // back up to the previous item // HTREEITEM htiPrev; TREEITEMID tidNext = m_pTreeSrc->GetNextSiblingItem(tid); if (tidNext) { HTREEITEM htiNext = FindChildHTI(htiParent, tidNext); ASSERT(htiNext); htiPrev = GetPrevSiblingItem(htiNext); if (htiPrev == NULL) htiPrev = TVI_FIRST; } else { htiPrev = TVI_LAST; } // Insert the new tree item AddOneItem(htiParent, htiPrev, tid); } else if (htiParent) { // Set child count so parent can expand TV_ITEM item; item.mask = TVIF_CHILDREN; item.hItem = htiParent; item.cChildren = 1; SetItem(&item); } } void CTreeObserverTreeImpl::ItemRemoved(TREEITEMID tidParent, TREEITEMID tid) { ASSERT(m_pTreeSrc != NULL); ASSERT(tid != 0); // if deleting hidden root, clear tree and return if (tid == m_tidRoot) { DeleteAllItems(); m_tidRoot = NULL; return; } // Get parent tree item HTREEITEM htiParent = FindHTI(tidParent); if (WasItemExpanded(htiParent)) { // Find removed item HTREEITEM hti = FindChildHTI(htiParent, tid); // Remove the item DeleteItem(hti); } } void CTreeObserverTreeImpl::ItemChanged(TREEITEMID tid, DWORD dwAttrib) { ASSERT(m_pTreeSrc != NULL); ASSERT(tid != 0); if (dwAttrib & TIA_NAME) { // Get changed tree item HTREEITEM hti = FindHTI(tid); // Force item update if (hti != 0) { TCHAR name[MAX_PATH]; m_pTreeSrc->GetItemName(tid, name, countof(name)); TVITEM item; item.hItem = hti; item.mask = TVIF_TEXT; item.pszText = name; SetItem(&item); } } } void CTreeObserverTreeImpl::OnItemExpanding(NMHDR* pNMHDR, LRESULT* pResult) { NM_TREEVIEW* pNotify = (NM_TREEVIEW*)pNMHDR; ASSERT(pNotify != NULL); HTREEITEM hti = pNotify->itemNew.hItem; ASSERT(hti != NULL); // Enumerate the folders below this item if (pNotify->action == TVE_EXPAND) { // Only add children on first expansion if (!(pNotify->itemNew.state & TVIS_EXPANDEDONCE)) AddChildren(hti); } // Flip state of icon open/closed ASSERT(m_pTreeSrc != NULL); TREEITEMID tid = pNotify->itemNew.lParam; ASSERT(m_pTreeSrc->IsFolderItem(tid)); int iImage = (pNotify->action == TVE_EXPAND) ? m_pTreeSrc->GetItemOpenImage(tid) : m_pTreeSrc->GetItemImage(tid); TVITEM item; item.hItem = hti; item.mask = TVIF_IMAGE | TVIF_SELECTEDIMAGE; item.iImage = item.iSelectedImage = iImage; SetItem(&item); *pResult = 0; } void CTreeObserverTreeImpl::OnSingleExpand(NMHDR* pNMHDR, LRESULT* pResult) { *pResult = TVNRET_DEFAULT; } BEGIN_MESSAGE_MAP(CTreeObserverTreeImpl, CTreeCtrl) ON_NOTIFY_REFLECT(TVN_SINGLEEXPAND, OnSingleExpand) ON_NOTIFY_REFLECT(TVN_ITEMEXPANDING, OnItemExpanding) END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CFavoritesView message handlers