summaryrefslogtreecommitdiff
path: root/hammer/grouplist.cpp
diff options
context:
space:
mode:
authorFluorescentCIAAfricanAmerican <[email protected]>2020-04-22 12:56:21 -0400
committerFluorescentCIAAfricanAmerican <[email protected]>2020-04-22 12:56:21 -0400
commit3bf9df6b2785fa6d951086978a3e66f49427166a (patch)
tree2c0f1f0c63c4832882bc93814ebd2c2b1c6224e5 /hammer/grouplist.cpp
downloadarchived-source-engine-2018-hl2-src-master.tar.xz
archived-source-engine-2018-hl2-src-master.zip
Diffstat (limited to 'hammer/grouplist.cpp')
-rw-r--r--hammer/grouplist.cpp845
1 files changed, 845 insertions, 0 deletions
diff --git a/hammer/grouplist.cpp b/hammer/grouplist.cpp
new file mode 100644
index 0000000..57c5aab
--- /dev/null
+++ b/hammer/grouplist.cpp
@@ -0,0 +1,845 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose: Implements a list view for visgroups. Supports drag and drop, and
+// posts a registered windows message to the list view's parent window
+// when visgroups are hidden or shown.
+//
+//=============================================================================//
+
+#include "stdafx.h"
+#include "hammer.h"
+#include "GroupList.h"
+#include "MapDoc.h"
+#include "MapSolid.h"
+#include "MapWorld.h"
+#include "GlobalFunctions.h"
+#include "VisGroup.h"
+
+// memdbgon must be the last include file in a .cpp file!!!
+#include <tier0/memdbgon.h>
+
+//
+// Timer IDs.
+//
+enum
+{
+ TIMER_GROUP_DRAG_SCROLL = 1,
+};
+
+
+static const unsigned int g_uToggleStateMsg = ::RegisterWindowMessage(GROUPLIST_MSG_TOGGLE_STATE);
+static const unsigned int g_uLeftDragDropMsg = ::RegisterWindowMessage(GROUPLIST_MSG_LEFT_DRAG_DROP);
+static const unsigned int g_uRightDragDropMsg = ::RegisterWindowMessage(GROUPLIST_MSG_RIGHT_DRAG_DROP);
+static const unsigned int g_uSelChangeMsg = ::RegisterWindowMessage(GROUPLIST_MSG_SEL_CHANGE);
+
+
+BEGIN_MESSAGE_MAP(CGroupList, CTreeCtrl)
+ //{{AFX_MSG_MAP(CGroupList)
+ ON_NOTIFY_REFLECT(TVN_BEGINDRAG, OnBegindrag)
+ ON_NOTIFY_REFLECT(TVN_ENDLABELEDIT, OnEndlabeledit)
+ ON_NOTIFY_REFLECT(TVN_SELCHANGED, OnSelChange)
+ ON_WM_LBUTTONDOWN()
+ ON_WM_LBUTTONUP()
+ ON_WM_LBUTTONDBLCLK()
+ ON_WM_RBUTTONDOWN()
+ ON_WM_RBUTTONUP()
+ ON_WM_MOUSEMOVE()
+ ON_WM_TIMER()
+ ON_WM_CONTEXTMENU()
+ //}}AFX_MSG_MAP
+END_MESSAGE_MAP()
+
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+CGroupList::CGroupList(void)
+{
+ m_pDragImageList = NULL;
+ m_hDragItem = NULL;
+ m_bRButtonDown = false;
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+CGroupList::~CGroupList(void)
+{
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CGroupList::EnableChecks(void)
+{
+ if (!m_cNormalImageList.GetSafeHandle())
+ {
+ m_cNormalImageList.Create(IDB_VISGROUPSTATUS, 16, 1, RGB(255, 255, 255));
+ m_cNormalImageList.SetOverlayImage(1, 1);
+ m_cNormalImageList.SetOverlayImage(2, 2);
+ }
+
+ CTreeCtrl::SetImageList(&m_cNormalImageList, TVSIL_NORMAL);
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Input : pVisGroup -
+// hItemParent -
+//-----------------------------------------------------------------------------
+void CGroupList::AddVisGroupRecursive(CVisGroup *pVisGroup, HTREEITEM hItemParent)
+{
+ HTREEITEM hItem = InsertItem(pVisGroup->GetName(), hItemParent, TVI_LAST);
+ if (hItem != NULL)
+ {
+ SetItemData(hItem, (DWORD)pVisGroup);
+
+ // Add the item to our flattened list.
+// VisGroupTreeItem_t item;
+// item.pVisGroup = pVisGroup;
+// item.hItem = hItem;
+// m_TreeItems.AddToTail(item);
+ m_VisGroups.AddToTail(pVisGroup);
+
+ int nCount = pVisGroup->GetChildCount();
+ for (int i = 0; i < nCount; i++)
+ {
+ CVisGroup *pChild = pVisGroup->GetChild(i);
+ AddVisGroupRecursive(pChild, hItem);
+ }
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Input : pGroup -
+//-----------------------------------------------------------------------------
+void CGroupList::AddVisGroup(CVisGroup *pGroup)
+{
+ AddVisGroupRecursive(pGroup, TVI_ROOT);
+}
+
+
+static void UnsetItemData_R( CTreeCtrl *pCtrl, HTREEITEM hItem )
+{
+ pCtrl->SetItemData( hItem, 0 );
+
+ HTREEITEM hChildItem = pCtrl->GetChildItem( hItem );
+
+ while( hChildItem != NULL )
+ {
+ UnsetItemData_R( pCtrl, hChildItem );
+ hChildItem = pCtrl->GetNextItem(hChildItem, TVGN_NEXT);
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CGroupList::DeleteAllItems(void)
+{
+ // Un-set all item data because sometimes during a delete it'll trigger selection change notifications
+ // which might crash things later.
+ if ( GetSafeHwnd() && m_VisGroups.Count() > 0 )
+ {
+ UnsetItemData_R( this, TVI_ROOT );
+ }
+
+ DeleteItem(TVI_ROOT);
+ m_VisGroups.RemoveAll();
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CGroupList::EnsureVisible(CVisGroup *pVisGroup)
+{
+ //DBG("EnsureVisible: %s\n", pVisGroup->GetName());
+ HTREEITEM hItem = FindVisGroupItem(pVisGroup);
+ if (hItem)
+ {
+ CTreeCtrl::EnsureVisible(hItem);
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CGroupList::ExpandRecursive(HTREEITEM hItem)
+{
+ if (hItem)
+ {
+ Expand(hItem, TVE_EXPAND);
+
+ if (ItemHasChildren(hItem))
+ {
+ HTREEITEM hChildItem = GetChildItem(hItem);
+ while (hChildItem != NULL)
+ {
+ ExpandRecursive(hChildItem);
+ hChildItem = GetNextItem(hChildItem, TVGN_NEXT);
+ }
+ }
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CGroupList::ExpandAll(void)
+{
+ HTREEITEM hItem = GetRootItem();
+ while (hItem)
+ {
+ ExpandRecursive(hItem);
+ hItem = GetNextItem(hItem, TVGN_NEXT);
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Returns the tree item in the given subtree associated with the given
+// visgroup, NULL if none.
+//-----------------------------------------------------------------------------
+HTREEITEM CGroupList::FindVisGroupItemRecursive(HTREEITEM hItem, CVisGroup *pVisGroup)
+{
+ if (hItem)
+ {
+ CVisGroup *pVisGroupCheck = (CVisGroup *)GetItemData(hItem);
+ if (pVisGroupCheck == pVisGroup)
+ {
+ return hItem;
+ }
+
+ if (ItemHasChildren(hItem))
+ {
+ HTREEITEM hChildItem = GetChildItem(hItem);
+ while (hChildItem != NULL)
+ {
+ HTREEITEM hFoundItem = FindVisGroupItemRecursive(hChildItem, pVisGroup);
+ if (hFoundItem)
+ {
+ return hFoundItem;
+ }
+
+ hChildItem = GetNextItem(hChildItem, TVGN_NEXT);
+ }
+ }
+ }
+
+ return NULL;
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Returns the tree item associated with the given visgroup, NULL if none.
+//-----------------------------------------------------------------------------
+HTREEITEM CGroupList::FindVisGroupItem(CVisGroup *pVisGroup)
+{
+ HTREEITEM hItem = GetRootItem();
+ while (hItem)
+ {
+ HTREEITEM hFound = FindVisGroupItemRecursive(hItem, pVisGroup);
+ if (hFound)
+ {
+ return hFound;
+ }
+
+ hItem = GetNextItem(hItem, TVGN_NEXT);
+ }
+
+ return NULL;
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Returns the currently selected visgroup in the tree control.
+//-----------------------------------------------------------------------------
+CVisGroup *CGroupList::GetSelectedVisGroup(void)
+{
+ HTREEITEM hItem = GetSelectedItem();
+ if (hItem)
+ {
+ return (CVisGroup *)GetItemData(hItem);
+ }
+
+ return NULL;
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Input : nFlags -
+// point -
+//-----------------------------------------------------------------------------
+void CGroupList::OnLButtonDown(UINT nFlags, CPoint point)
+{
+ unsigned int uFlags;
+ HTREEITEM hItemHit = HitTest(point, &uFlags);
+ if (hItemHit != NULL)
+ {
+ if (uFlags & TVHT_ONITEMICON)
+ {
+ // Don't forward to the base if they clicked on the check box.
+ // This prevents undesired expansion/collapse of tree.
+ return;
+ }
+ }
+
+ CTreeCtrl::OnLButtonDown(nFlags, point);
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Input : nFlags -
+// point -
+//-----------------------------------------------------------------------------
+void CGroupList::OnLButtonUp(UINT nFlags, CPoint point)
+{
+ KillTimer(TIMER_GROUP_DRAG_SCROLL);
+ ReleaseCapture();
+
+ if (!m_hDragItem)
+ {
+ unsigned int uFlags;
+ HTREEITEM hItemHit = HitTest(point, &uFlags);
+ if (hItemHit != NULL)
+ {
+ if (uFlags & TVHT_ONITEMICON)
+ {
+ //
+ // Notify our parent window that this item's state has changed.
+ //
+ CWnd *pwndParent = GetParent();
+ if (pwndParent != NULL)
+ {
+ int nCheckState = GetCheck(hItemHit);
+ if (!nCheckState)
+ {
+ nCheckState = 1;
+ }
+ else
+ {
+ nCheckState = 0;
+ }
+
+ CVisGroup *pGroup = (CVisGroup *)GetItemData(hItemHit);
+ pwndParent->PostMessage(g_uToggleStateMsg, (WPARAM)pGroup, nCheckState);
+ }
+
+ // Don't forward to the base if they clicked on the check box.
+ // This prevents undesired expansion/collapse of tree.
+ return;
+ }
+ }
+
+ CTreeCtrl::OnLButtonUp(nFlags, point);
+ return;
+ }
+
+ Drop(DROP_LEFT, nFlags, point);
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Input : nFlags -
+// point -
+//-----------------------------------------------------------------------------
+void CGroupList::OnLButtonDblClk(UINT nFlags, CPoint point)
+{
+ unsigned int uFlags;
+ HTREEITEM hItemHit = HitTest(point, &uFlags);
+ if (hItemHit != NULL)
+ {
+ if (uFlags & TVHT_ONITEMICON)
+ {
+ // Don't forward to the base if they clicked on the check box.
+ // This prevents undesired expansion/collapse of tree.
+ return;
+ }
+ }
+
+ CTreeCtrl::OnLButtonDblClk(nFlags, point);
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Forwards selection change notifications to our parent window.
+// Input : pNMHDR -
+// pResult -
+//-----------------------------------------------------------------------------
+void CGroupList::OnSelChange(NMHDR *pNMHDR, LRESULT *pResult)
+{
+ CWnd *pwndParent = GetParent();
+ if (pwndParent != NULL)
+ {
+ pwndParent->PostMessage(g_uSelChangeMsg, 0, 0);
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Input : pNMHDR -
+// pResult -
+//-----------------------------------------------------------------------------
+void CGroupList::OnEndlabeledit(NMHDR *pNMHDR, LRESULT *pResult)
+{
+ NMTVDISPINFO *pInfo = (NMTVDISPINFO *)pNMHDR;
+ if (!pInfo->item.pszText)
+ return;
+
+ CVisGroup *pVisGroup = (CVisGroup *)GetItemData(pInfo->item.hItem);
+ Assert(pVisGroup);
+ if (!pVisGroup)
+ return;
+
+ pVisGroup->SetName(pInfo->item.pszText);
+ pResult[0] = TRUE;
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Begins dragging an item in the visgroup list. The drag image is
+// created and anchored relative to the mouse cursor.
+// Input : pNMHDR -
+// pResult -
+//-----------------------------------------------------------------------------
+void CGroupList::OnBegindrag(NMHDR *pNMHDR, LRESULT *pResult)
+{
+ NMTREEVIEW *ptv = (NMTREEVIEW *)pNMHDR;
+ BeginDrag(ptv->ptDrag, ptv->itemNew.hItem);
+ *pResult = 0;
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Input : pt -
+// hItem -
+//-----------------------------------------------------------------------------
+void CGroupList::BeginDrag(CPoint point, HTREEITEM hItem)
+{
+ m_hDragItem = hItem;
+ if (m_hDragItem)
+ {
+ m_pDragImageList = CreateDragImage(m_hDragItem);
+ if (m_pDragImageList)
+ {
+ CPoint ptHotSpot(0, 0);
+ m_pDragImageList->BeginDrag(0, ptHotSpot);
+ m_pDragImageList->DragEnter(this, point);
+ SelectDropTarget(NULL);
+ }
+
+ // Timer handles scrolling the list control when dragging outside the window bounds.
+ SetTimer(TIMER_GROUP_DRAG_SCROLL, 300, NULL);
+
+ SetCapture();
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Input : nFlags -
+// point -
+//-----------------------------------------------------------------------------
+void CGroupList::OnRButtonDown(UINT nFlags, CPoint point)
+{
+ m_bRButtonDown = true;
+ m_ptRButtonDown = point;
+ m_hDragItem = NULL;
+ SetCapture();
+
+ // Chaining to the base class causes us never to receive the button up message
+ // for a right click without drag, so we don't do that.
+ //CTreeCtrl::OnRButtonDown(nFlags, point);
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Input : pWnd -
+// point -
+//-----------------------------------------------------------------------------
+void CGroupList::OnContextMenu(CWnd *pWnd, CPoint point)
+{
+ KillTimer(TIMER_GROUP_DRAG_SCROLL);
+ ReleaseCapture();
+
+ m_bRButtonDown = false;
+
+ if (!m_hDragItem)
+ {
+ CTreeCtrl::OnContextMenu(pWnd, point);
+ return;
+ }
+
+ Drop(DROP_RIGHT, 0, point);
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Input : nFlags -
+// point -
+//-----------------------------------------------------------------------------
+void CGroupList::OnRButtonUp(UINT nFlags, CPoint point)
+{
+ KillTimer(TIMER_GROUP_DRAG_SCROLL);
+ ReleaseCapture();
+
+ m_bRButtonDown = false;
+
+ if (!m_hDragItem)
+ {
+ CTreeCtrl::OnRButtonUp(nFlags, point);
+ return;
+ }
+
+ Drop(DROP_RIGHT, nFlags, point);
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Input : eDropType -
+// nFlags -
+// point -
+//-----------------------------------------------------------------------------
+void CGroupList::Drop(DropType_t eDropType, UINT nFlags, CPoint point)
+{
+ SelectDropTarget(NULL);
+
+ HTREEITEM hDragItem = m_hDragItem;
+ m_hDragItem = NULL;
+
+ //
+ // We are dragging. Drop!
+ //
+ if (m_pDragImageList)
+ {
+ m_pDragImageList->DragLeave(this);
+ m_pDragImageList->EndDrag();
+ delete m_pDragImageList;
+ m_pDragImageList = NULL;
+ }
+
+ //
+ // Get the group that we were dragging.
+ //
+ CVisGroup *pDragGroup = (CVisGroup *)GetItemData(hDragItem);
+
+ //
+ // Determine what group was dropped onto.
+ //
+ HTREEITEM hDropItem = HitTest(point);
+ if (hDropItem == hDragItem)
+ {
+ return;
+ }
+
+ CVisGroup *pDropGroup = NULL;
+ if (hDropItem)
+ {
+ pDropGroup = (CVisGroup *)GetItemData(hDropItem);
+ }
+
+ if (pDragGroup == pDropGroup)
+ {
+ // Shouldn't happen, but just in case.
+ return;
+ }
+
+ CWnd *pwndParent = GetParent();
+ if (pwndParent != NULL)
+ {
+ if (eDropType == DROP_LEFT)
+ {
+ pwndParent->PostMessage(g_uLeftDragDropMsg, (WPARAM)pDragGroup, (LPARAM)pDropGroup);
+ }
+ else
+ {
+ pwndParent->PostMessage(g_uRightDragDropMsg, (WPARAM)pDragGroup, (LPARAM)pDropGroup);
+ }
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Input : nIDEvent -
+//-----------------------------------------------------------------------------
+void CGroupList::OnTimer(UINT nIDEvent)
+{
+ //DBG("OnTimer\n");
+ switch (nIDEvent)
+ {
+ case TIMER_GROUP_DRAG_SCROLL:
+ {
+ CPoint point;
+ GetCursorPos(&point);
+
+ CRect rect;
+ GetWindowRect(&rect);
+
+ if (!rect.PtInRect(point))
+ {
+ if (point.y > rect.bottom)
+ {
+ // scroll down
+ int nCount = GetVisibleCount();
+ HTREEITEM hItem = GetFirstVisibleItem();
+ for (int i = 1; i < nCount; i++)
+ {
+ hItem = GetNextVisibleItem(hItem);
+ }
+
+ hItem = GetNextVisibleItem(hItem);
+
+ if (hItem)
+ {
+ CTreeCtrl::EnsureVisible(hItem);
+ }
+ }
+ else if (point.y < rect.top)
+ {
+ HTREEITEM hItem = GetFirstVisibleItem();
+ HTREEITEM hPrevVisible = this->GetPrevVisibleItem(hItem);
+ if (hPrevVisible)
+ {
+ // scroll up
+ CTreeCtrl::EnsureVisible(hPrevVisible);
+ }
+ }
+ }
+
+ break;
+ }
+
+ default:
+ {
+ CTreeCtrl::OnTimer(nIDEvent);
+ }
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Input : nFlags -
+// point -
+//-----------------------------------------------------------------------------
+void CGroupList::OnMouseMove(UINT nFlags, CPoint point)
+{
+ CTreeCtrl::OnMouseMove(nFlags, point);
+
+ if (m_bRButtonDown && !m_hDragItem && (point.x != m_ptRButtonDown.x) && (point.y != m_ptRButtonDown.y))
+ {
+ // First mouse move since a right button down. Start dragging.
+ HTREEITEM hItem = HitTest(m_ptRButtonDown);
+ BeginDrag(point, hItem);
+ }
+
+ if (!m_hDragItem)
+ {
+ return;
+ }
+
+ if (m_pDragImageList)
+ {
+ m_pDragImageList->DragMove(point);
+ }
+
+ //
+ // Highlight the item we hit.
+ //
+ HTREEITEM hItem = HitTest(point);
+ if (hItem == GetDropHilightItem())
+ {
+ return;
+ }
+
+ // hide image first
+ if (m_pDragImageList)
+ {
+ m_pDragImageList->DragLeave(this);
+ m_pDragImageList->DragShowNolock(FALSE);
+ }
+
+ SelectDropTarget(hItem);
+
+ if (m_pDragImageList)
+ {
+ m_pDragImageList->DragEnter(this, point);
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CGroupList::SelectVisGroup(CVisGroup *pVisGroup)
+{
+ //DBG("SelectVisGroup: %s\n", pVisGroup->GetName());
+ HTREEITEM hItem = FindVisGroupItem(pVisGroup);
+ if (hItem)
+ {
+ Select(hItem, TVGN_CARET);
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Sets the check status for the given group.
+// Input : pVisGroup -
+// nCheckState - 0=not checked, 1=checked, -1=gray check (undefined)
+//-----------------------------------------------------------------------------
+void CGroupList::SetCheck(CVisGroup *pVisGroup, int nCheckState)
+{
+ HTREEITEM hItem = FindVisGroupItem(pVisGroup);
+ if (hItem)
+ {
+ UINT uState = INDEXTOOVERLAYMASK(0);
+ if (nCheckState == 1)
+ {
+ uState = INDEXTOOVERLAYMASK(1);
+ }
+ else if (nCheckState != 0)
+ {
+ uState = INDEXTOOVERLAYMASK(2);
+ }
+
+ SetItemState(hItem, uState, TVIS_OVERLAYMASK);
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Returns the check state for the given visgroup.
+// Input : pVisGroup -
+//-----------------------------------------------------------------------------
+int CGroupList::GetCheck(CVisGroup *pVisGroup)
+{
+ HTREEITEM hItem = FindVisGroupItem(pVisGroup);
+ if (hItem)
+ {
+ return GetCheck(hItem);
+ }
+
+ return 0;
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+int CGroupList::GetCheck(HTREEITEM hItem)
+{
+ UINT uState = (GetItemState(hItem, TVIS_OVERLAYMASK) & TVIS_OVERLAYMASK);
+ if (uState == INDEXTOOVERLAYMASK(1))
+ {
+ return 1;
+ }
+ else if (uState == INDEXTOOVERLAYMASK(0))
+ {
+ return 0;
+ }
+
+ return -1;
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Returns the number of visgroups in the whole tree.
+//-----------------------------------------------------------------------------
+int CGroupList::GetVisGroupCount()
+{
+ return m_VisGroups.Count();
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+CVisGroup *CGroupList::GetVisGroup(int nIndex)
+{
+ return m_VisGroups.Element(nIndex);
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Updates the tree control item text with the new group name.
+//-----------------------------------------------------------------------------
+void CGroupList::UpdateVisGroup(CVisGroup *pVisGroup)
+{
+ HTREEITEM hItem = FindVisGroupItem(pVisGroup);
+ if (hItem)
+ {
+ SetItemText(hItem, pVisGroup->GetName());
+ }
+}
+
+int CGroupList::GetGroupPairCount(void)
+{
+ return m_GroupPairs.Count();
+}
+
+void CGroupList::SaveVisGroupExpandStates()
+{
+ for ( int i = 0; i < GetVisGroupCount(); i++ )
+ {
+ CVisGroup *thisGroup = GetVisGroup(i);
+ GroupListPair newPair;
+ for ( int j = 0; j < GetGroupPairCount(); j++ )
+ {
+ GroupListPair thisPair = m_GroupPairs.Element( j );
+ if ( thisGroup == thisPair.pVisGroup )
+ {
+ m_GroupPairs.Remove( j );
+ break;
+ }
+ }
+
+ HTREEITEM thisItem = FindVisGroupItem( thisGroup );
+ newPair.pVisGroup = thisGroup;
+ newPair.bExpanded = false;
+ if ( thisItem && (GetItemState( thisItem, TVIS_EXPANDED) & TVIS_EXPANDED) )
+ {
+ newPair.bExpanded = true;
+ }
+ m_GroupPairs.AddToTail( newPair );
+ }
+}
+
+void CGroupList::RestoreVisGroupExpandStates()
+{
+ ExpandAll();
+ for ( int i = 0; i < GetGroupPairCount(); i++ )
+ {
+ GroupListPair thisPair = m_GroupPairs.Element( i );
+ HTREEITEM thisItem = FindVisGroupItem( thisPair.pVisGroup );
+ if ( thisItem )
+ {
+ if ( thisPair.bExpanded )
+ {
+ Expand(thisItem, TVE_EXPAND);
+ }
+ else
+ {
+ Expand( thisItem, TVE_COLLAPSE );
+ }
+ }
+ }
+}