/*++ Copyright (c) 1998 Microsoft Corporation Module Name: FTMan File Name: FTListVw.cpp Abstract: Implementation of the CFTListView class. It is a list view displaying all members of a logical volume Author: Cristian Teodorescu October 20, 1998 Notes: Revision History: --*/ #include "stdafx.h" #include "Actions.h" #include "FTDoc.h" #include "FTListVw.h" #include "FTTreeVw.h" #include "Item.h" #include "MainFrm.h" #include "LogVol.h" #include "PhPart.h" #include "Resource.h" #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif // This is the configuration of the list-view columns LV_COLUMN_CONFIG ColumnsConfig[COLUMNS_NUMBER] = { { LVC_Name, IDS_COLUMN_NAME, LVCFMT_LEFT, 20 }, { LVC_Type, IDS_COLUMN_TYPE, LVCFMT_LEFT, 20 }, { LVC_DiskNumber, IDS_COLUMN_DISKS, LVCFMT_RIGHT, 10 }, { LVC_Size, IDS_COLUMN_SIZE, LVCFMT_RIGHT, 15 }, { LVC_Offset, IDS_COLUMN_OFFSET, LVCFMT_RIGHT, 15 }, { LVC_VolumeID, IDS_COLUMN_VOLUMEID,LVCFMT_RIGHT, 20 } }; ///////////////////////////////////////////////////////////////////////////// // CFTListView IMPLEMENT_DYNCREATE(CFTListView, CListView) BEGIN_MESSAGE_MAP(CFTListView, CListView) //{{AFX_MSG_MAP(CFTListView) ON_WM_DESTROY() ON_NOTIFY_REFLECT(NM_DBLCLK, OnDblclk) ON_COMMAND(ID_ITEM_EXPAND, OnItemExpand) ON_NOTIFY_REFLECT(NM_RCLICK, OnRclick) ON_COMMAND(ID_ACTION_ASSIGN, OnActionAssign) ON_UPDATE_COMMAND_UI(ID_ACTION_ASSIGN, OnUpdateActionAssign) ON_COMMAND(ID_ACTION_FTBREAK, OnActionFtbreak) ON_UPDATE_COMMAND_UI(ID_ACTION_FTBREAK, OnUpdateActionFtbreak) ON_COMMAND(ID_ACTION_CREATE_EXTENDED_PARTITION, OnActionCreateExtendedPartition) ON_UPDATE_COMMAND_UI(ID_ACTION_CREATE_EXTENDED_PARTITION, OnUpdateActionCreateExtendedPartition) ON_COMMAND(ID_ACTION_CREATE_PARTITION, OnActionCreatePartition) ON_UPDATE_COMMAND_UI(ID_ACTION_CREATE_PARTITION, OnUpdateActionCreatePartition) ON_COMMAND(ID_ACTION_DELETE, OnActionDelete) ON_UPDATE_COMMAND_UI(ID_ACTION_DELETE, OnUpdateActionDelete) ON_COMMAND(ID_ACTION_FTINIT, OnActionFtinit) ON_UPDATE_COMMAND_UI(ID_ACTION_FTINIT, OnUpdateActionFtinit) ON_COMMAND(ID_ACTION_FTMIRROR, OnActionFtmirror) ON_UPDATE_COMMAND_UI(ID_ACTION_FTMIRROR, OnUpdateActionFtmirror) ON_COMMAND(ID_ACTION_FTSTRIPE, OnActionFtstripe) ON_UPDATE_COMMAND_UI(ID_ACTION_FTSTRIPE, OnUpdateActionFtstripe) ON_COMMAND(ID_ACTION_FTSWAP, OnActionFtswap) ON_UPDATE_COMMAND_UI(ID_ACTION_FTSWAP, OnUpdateActionFtswap) ON_COMMAND(ID_ACTION_FTSWP, OnActionFtswp) ON_UPDATE_COMMAND_UI(ID_ACTION_FTSWP, OnUpdateActionFtswp) ON_COMMAND(ID_ACTION_FTVOLSET, OnActionFtvolset) ON_UPDATE_COMMAND_UI(ID_ACTION_FTVOLSET, OnUpdateActionFtvolset) //}}AFX_MSG_MAP END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CFTListView construction/destruction CFTListView::CFTListView() : m_pParentData(NULL) { // TODO: add construction code here } CFTListView::~CFTListView() { } BOOL CFTListView::PreCreateWindow(CREATESTRUCT& cs) { // TODO: Modify the Window class or styles here by modifying // the CREATESTRUCT cs return CListView::PreCreateWindow(cs); } ///////////////////////////////////////////////////////////////////////////// // CFTListView drawing void CFTListView::OnDraw(CDC* pDC) { // TODO: add draw code for native data here } void CFTListView::OnInitialUpdate() { MY_TRY CListView::OnInitialUpdate(); // fill in image list for normal icons CImageList* pImageList = new CImageList(); if( pImageList->Create( IDB_IMAGELIST_LARGE, 32, 32, RGB( 255, 0, 255 ) ) ) GetListCtrl().SetImageList(pImageList, LVSIL_NORMAL); else AfxMessageBox( IDS_ERR_CREATE_IMAGELIST, MB_ICONSTOP ); // fill in image list for small icons pImageList = new CImageList(); if( pImageList->Create( IDB_IMAGELIST_SMALL, 16, 16, RGB( 255, 0, 255 ) ) ) GetListCtrl().SetImageList(pImageList, LVSIL_SMALL); else AfxMessageBox( IDS_ERR_CREATE_IMAGELIST, MB_ICONSTOP ); // insert columns (REPORT mode) and modify the new header items CRect rect; GetListCtrl().GetWindowRect(&rect); for( int i = 0; i < COLUMNS_NUMBER; i++ ) { PLV_COLUMN_CONFIG pColumn = &(ColumnsConfig[i]); CString str; if( !str.LoadString(pColumn->dwTitleID) ) ASSERT(FALSE); GetListCtrl().InsertColumn( i, str, pColumn->nFormat , rect.Width() * pColumn->wWidthPercent/100, pColumn->iSubItem); } // Set the list-view style ModifyStyle(LVS_TYPEMASK, LVS_REPORT | LVS_SHOWSELALWAYS ); // Load the popup menu m_menuPopup.LoadMenu(IDM_POPUP); // TODO: You may populate your ListView with items by directly accessing // its list control through a call to GetListCtrl(). MY_CATCH_AND_REPORT } int CFTListView::GetFocusedItem() const { return GetListCtrl().GetNextItem(-1, LVNI_FOCUSED ); } BOOL CFTListView::SetFocusedItem( int iItem ) { // The old focused item must loose the focus GetListCtrl().SetItemState(GetFocusedItem(), 0, LVNI_FOCUSED); // The new item receive focus return GetListCtrl().SetItemState(iItem, LVNI_FOCUSED, LVNI_FOCUSED); } BOOL CFTListView::SelectItem( int iItem, BOOL bSelect /* =TRUE */ ) { return GetListCtrl().SetItemState( iItem, bSelect ? LVNI_SELECTED : 0, LVNI_SELECTED ); } CItemData* CFTListView::GetItemData( int iItem ) { LVITEM lvItem; lvItem.iItem = iItem; lvItem.iSubItem = LVC_Name; lvItem.mask = LVIF_PARAM; if( !GetListCtrl().GetItem(&lvItem) ) return NULL; return (CItemData*)(lvItem.lParam); } BOOL CFTListView::AddItem( CItemData* pData ) { MY_TRY LVITEM lvitem; CString strDisplay; // Just in case if( pData == NULL ) return FALSE; BOOL bReportStyle = ( GetWindowLong( GetListCtrl().GetSafeHwnd(), GWL_STYLE ) & LVS_REPORT ); // 1. Insert the item lvitem.iItem = GetListCtrl().GetItemCount(); ASSERT(LVC_Name==0); // The first SubItem must be zero lvitem.iSubItem = LVC_Name; if( bReportStyle ) pData->GetDisplayName(strDisplay); else pData->GetDisplayExtendedName(strDisplay); lvitem.pszText = (LPTSTR)(LPCTSTR)strDisplay; lvitem.iImage = pData->GetImageIndex(); lvitem.lParam = (LPARAM)pData; lvitem.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_PARAM ; int iActualItem = GetListCtrl().InsertItem( &lvitem ); if( iActualItem < 0 ) return FALSE; // The items must appear in the list exactly in the order we added them ASSERT( iActualItem == lvitem.iItem ); pData->SetListItem( iActualItem ); // 2. Set all subitems lvitem.iItem = iActualItem; lvitem.mask = LVIF_TEXT; // Type lvitem.iSubItem = LVC_Type; pData->GetDisplayType(strDisplay); lvitem.pszText = (LPTSTR)(LPCTSTR)strDisplay; GetListCtrl().SetItem( &lvitem ); // Disks set lvitem.iSubItem = LVC_DiskNumber; pData->GetDisplayDisksSet(strDisplay); lvitem.pszText = (LPTSTR)(LPCTSTR)strDisplay; GetListCtrl().SetItem( &lvitem ); // Size lvitem.iSubItem = LVC_Size; pData->GetDisplaySize(strDisplay); lvitem.pszText = (LPTSTR)(LPCTSTR)strDisplay; GetListCtrl().SetItem( &lvitem ); // Offset lvitem.iSubItem = LVC_Offset; pData->GetDisplayOffset(strDisplay); lvitem.pszText = (LPTSTR)(LPCTSTR)strDisplay; GetListCtrl().SetItem( &lvitem ); // Volume ID lvitem.iSubItem = LVC_VolumeID; pData->GetDisplayVolumeID(strDisplay); lvitem.pszText = (LPTSTR)(LPCTSTR)strDisplay; GetListCtrl().SetItem( &lvitem ); return TRUE; MY_CATCH_REPORT_AND_RETURN_FALSE } BOOL CFTListView::RefreshItem( int iItem ) { MY_TRY LVITEM lvitem; CString strDisplay; BOOL bReportStyle = ( GetWindowLong( GetListCtrl().GetSafeHwnd(), GWL_STYLE ) & LVS_REPORT ); // 1. Get the item data lvitem.iItem = iItem; ASSERT(LVC_Name==0); // The first SubItem must be zero lvitem.iSubItem = LVC_Name; lvitem.mask = LVIF_PARAM ; if( !GetListCtrl().GetItem( &lvitem ) ) return FALSE; CItemData* pData = (CItemData*)(lvitem.lParam); ASSERT( pData ); ASSERT( pData->GetListItem() == iItem ); // 2. Now refresh the name and the image of the item if( bReportStyle ) pData->GetDisplayName( strDisplay ); else pData->GetDisplayExtendedName( strDisplay ); lvitem.pszText = (LPTSTR)(LPCTSTR)strDisplay; lvitem.iImage = pData->GetImageIndex(); lvitem.mask = LVIF_TEXT | LVIF_IMAGE; return GetListCtrl().SetItem( &lvitem ); MY_CATCH_REPORT_AND_RETURN_FALSE } BOOL CFTListView::AddMembersFromTree() { MY_TRY GetListCtrl().DeleteAllItems(); if( !m_pParentData ) return TRUE; CMainFrame* pFrame = STATIC_DOWNCAST(CMainFrame, GetParentFrame() ); CFTTreeView* pLeftView = (CFTTreeView*)(pFrame->GetLeftPane()); ASSERT( pLeftView ); CTreeCtrl& rTreeCtrl = pLeftView->GetTreeCtrl(); ASSERT( m_pParentData->AreMembersInserted() ); HTREEITEM hItem = m_pParentData->GetTreeItem(); ASSERT(hItem); // For each member of the item add a new item to the list view HTREEITEM hChild = rTreeCtrl.GetChildItem(hItem); while( hChild != NULL ) { TVITEM tvItem; tvItem.hItem = hChild; tvItem.mask = TVIF_PARAM; if( rTreeCtrl.GetItem(&tvItem) ) { ASSERT(tvItem.lParam); if( !AddItem( (CItemData*)(tvItem.lParam) ) ) return FALSE; } else ASSERT(FALSE); hChild = rTreeCtrl.GetNextSiblingItem(hChild); } SelectItem(0); SetFocusedItem(0); return TRUE; MY_CATCH_REPORT_AND_RETURN_FALSE } // This method fills the list view with all members of the given item // It causes also the expandation of the parent item in the tree view ( if it is not expanded ) BOOL CFTListView::ExpandItem( int iItem) { MY_TRY if( iItem < 0 ) return FALSE; // Now get the CItemData structure of the selected item CItemData* pData = GetItemData(iItem); if( !pData ) return FALSE; // TODO: Add your control notification handler code here ASSERT( m_pParentData ); // Double-clicking a member of the list is equivalent with two actions in the tree: // 1. Expand the selected item ( if not expanded ) // 2. Select a member of it CMainFrame* pFrame = STATIC_DOWNCAST(CMainFrame, GetParentFrame() ); CFTTreeView* pLeftView = (CFTTreeView*)(pFrame->GetLeftPane()); ASSERT(pLeftView); CTreeCtrl& rTreeCtrl = pLeftView->GetTreeCtrl(); // First expand the parent tree item HTREEITEM hItem = m_pParentData->GetTreeItem(); ASSERT( hItem ); TVITEM tvItem; tvItem.hItem = hItem; tvItem.stateMask = TVIS_EXPANDED; tvItem.mask = TVIF_STATE; rTreeCtrl.GetItem(&tvItem); // If the parent node is not expanded then expand it if( !(tvItem.state & TVIS_EXPANDED ) ) { // Reset the ExpandedOnce flag; so the tree view will receive the OnItemExpanding notification tvItem.stateMask = TVIS_EXPANDEDONCE; tvItem.state = 0; rTreeCtrl.SetItem(&tvItem); // Before expanding the tree we must take a copy of pData ( because the expandation causes // all list-view items to be refreshed i.e. the old CItemData structures to be deleted CItemData* pOldData; if( pData->GetItemType() == IT_LogicalVolume ) pOldData = new CLogicalVolumeData( *((CLogicalVolumeData*)pData) ); else if( pData->GetItemType() == IT_PhysicalPartition ) pOldData = new CPhysicalPartitionData( *((CPhysicalPartitionData*)pData) ); else ASSERT(FALSE); rTreeCtrl.Expand( hItem, TVE_EXPAND ); // Now we must find the old member among the new refreshed members int i; for( i=0, pData = NULL; ( i < GetListCtrl().GetItemCount() ) && !pData; i++ ) { CItemData* pItemData = GetItemData(i); if( *pOldData == *pItemData ) pData = pItemData; } // It is possible to don't find our member anymore // That means something happened with it outside our application if( !pData ) { CString strDisplayName, str; pOldData->GetDisplayExtendedName(strDisplayName); AfxFormatString1(str, IDS_ERR_MEMBER_NOT_FOUND_ANYMORE, strDisplayName); AfxMessageBox(str,MB_ICONSTOP); delete pOldData; return FALSE; } delete pOldData; } // Then mark the double-clicked item as selected in the tree ASSERT( pData->GetTreeItem() ); //rTreeCtrl.EnsureVisible( pData->GetTreeItem() ); return rTreeCtrl.SelectItem( pData->GetTreeItem() ); MY_CATCH_REPORT_AND_RETURN_FALSE } //////////////////////////////////////////////////////////////////////////////////////////////// // Public methods void CFTListView::GetSnapshot( LIST_SNAPSHOT& snapshot ) { MY_TRY CWaitCursor wc; snapshot.setSelectedItems.RemoveAll(); int iItem = GetListCtrl().GetNextItem( -1, LVNI_SELECTED ); while (iItem >= 0) { CItemData* pData = GetItemData(iItem); ASSERT(pData); CItemID idItem( *pData ); snapshot.setSelectedItems.Add(idItem); iItem = GetListCtrl().GetNextItem( iItem, LVNI_SELECTED ); } MY_CATCH_AND_REPORT } void CFTListView::SetSnapshot( LIST_SNAPSHOT& snapshot ) { MY_TRY CWaitCursor wc; for ( int i = 0; i < GetListCtrl().GetItemCount(); i++ ) { CItemData* pData = GetItemData(i); ASSERT( pData ); CItemID idItem( *pData ); if( snapshot.setSelectedItems.InSet(idItem ) ) { SelectItem( i, TRUE ); SetFocusedItem(i); } else SelectItem( i, FALSE ); } MY_CATCH_AND_REPORT } BOOL CFTListView::SynchronizeMembersWithTree( CItemData* pParentData ) { m_pParentData = pParentData; return AddMembersFromTree(); } void CFTListView::GetSelectedItems( CObArray& arrSelectedItems ) { MY_TRY arrSelectedItems.RemoveAll(); int iItem = GetListCtrl().GetNextItem( -1, LVNI_SELECTED ); while (iItem >= 0) { CItemData* pData = GetItemData(iItem); ASSERT(pData); arrSelectedItems.Add(pData); iItem = GetListCtrl().GetNextItem( iItem, LVNI_SELECTED ); } MY_CATCH_AND_REPORT } void CFTListView::DisplayItemsExtendedNames( BOOL bExtended /* = TRUE */ ) { MY_TRY for( int i = 0; i < GetListCtrl().GetItemCount(); i++ ) { CItemData* pData = (CItemData*)(GetListCtrl().GetItemData(i)); ASSERT( pData ); CString strDisplayName; if( bExtended ) pData->GetDisplayExtendedName( strDisplayName ); else pData->GetDisplayName( strDisplayName ); GetListCtrl().SetItemText( i, LVC_Name, strDisplayName ); } MY_CATCH_AND_REPORT } ///////////////////////////////////////////////////////////////////////////// // CFTListView diagnostics #ifdef _DEBUG void CFTListView::AssertValid() const { CListView::AssertValid(); } void CFTListView::Dump(CDumpContext& dc) const { CListView::Dump(dc); } CFTDocument* CFTListView::GetDocument() // non-debug version is inline { ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CFTDocument))); return (CFTDocument*)m_pDocument; } #endif //_DEBUG ///////////////////////////////////////////////////////////////////////////// // CFTListView message handlers void CFTListView::OnStyleChanged(int nStyleType, LPSTYLESTRUCT lpStyleStruct) { //TODO: add code to react to the user changing the view style of your window } void CFTListView::OnDestroy() { GetListCtrl().DeleteAllItems(); // Delete the image list CImageList* pImageList = GetListCtrl().GetImageList(LVSIL_NORMAL); if( pImageList ) { pImageList->DeleteImageList(); delete pImageList; } pImageList = GetListCtrl().GetImageList(LVSIL_SMALL); if( pImageList ) { pImageList->DeleteImageList(); delete pImageList; } // Destroy the popup menu m_menuPopup.DestroyMenu(); CListView::OnDestroy(); // TODO: Add your message handler code here } void CFTListView::OnDblclk(NMHDR* pNMHDR, LRESULT* pResult) { LPNMLISTVIEW pNMLV = (LPNMLISTVIEW) pNMHDR; *pResult = 0; ExpandItem( pNMLV->iItem ); } void CFTListView::OnItemExpand() { // TODO: Add your command handler code here int iItem = GetFocusedItem(); ExpandItem(iItem); } void CFTListView::OnRclick(NMHDR* pNMHDR, LRESULT* pResult) { // TODO: Add your control notification handler code here *pResult = 0; LPNMLISTVIEW lpnmlv = (LPNMLISTVIEW) pNMHDR; if( lpnmlv->iItem < 0 ) return ; ClientToScreen( &(lpnmlv->ptAction) ); // We want to display in fact only the first popup of the menu m_menuPopup CMenu* pPopup = m_menuPopup.GetSubMenu(0); if( pPopup != NULL ) pPopup->TrackPopupMenu( TPM_LEFTALIGN, lpnmlv->ptAction.x, lpnmlv->ptAction.y, AfxGetMainWnd(), NULL); } /////////////////////////////////////////////////////////////////////////////////////////////////////////// // FT Actions void CFTListView::OnActionAssign() { CObArray arrSelectedItems; GetSelectedItems( arrSelectedItems ); ActionAssign( arrSelectedItems ); } void CFTListView::OnUpdateActionAssign(CCmdUI* pCmdUI) { CObArray arrSelectedItems; GetSelectedItems( arrSelectedItems ); UpdateActionAssign( pCmdUI, arrSelectedItems ); } void CFTListView::OnActionFtbreak() { CObArray arrSelectedItems; GetSelectedItems( arrSelectedItems ); ActionFtbreak( arrSelectedItems ); } void CFTListView::OnUpdateActionFtbreak(CCmdUI* pCmdUI) { CObArray arrSelectedItems; GetSelectedItems( arrSelectedItems ); UpdateActionFtbreak( pCmdUI, arrSelectedItems ); } void CFTListView::OnActionCreateExtendedPartition() { CObArray arrSelectedItems; GetSelectedItems( arrSelectedItems ); ActionCreateExtendedPartition( arrSelectedItems ); } void CFTListView::OnUpdateActionCreateExtendedPartition(CCmdUI* pCmdUI) { CObArray arrSelectedItems; GetSelectedItems( arrSelectedItems ); UpdateActionCreateExtendedPartition( pCmdUI, arrSelectedItems ); } void CFTListView::OnActionCreatePartition() { CObArray arrSelectedItems; GetSelectedItems( arrSelectedItems ); ActionCreatePartition( arrSelectedItems ); } void CFTListView::OnUpdateActionCreatePartition(CCmdUI* pCmdUI) { CObArray arrSelectedItems; GetSelectedItems( arrSelectedItems ); UpdateActionCreatePartition( pCmdUI, arrSelectedItems ); } void CFTListView::OnActionDelete() { CObArray arrSelectedItems; GetSelectedItems( arrSelectedItems ); ActionDelete( arrSelectedItems ); } void CFTListView::OnUpdateActionDelete(CCmdUI* pCmdUI) { CObArray arrSelectedItems; GetSelectedItems( arrSelectedItems ); UpdateActionDelete( pCmdUI, arrSelectedItems ); } void CFTListView::OnActionFtinit() { CObArray arrSelectedItems; GetSelectedItems( arrSelectedItems ); ActionFtinit( arrSelectedItems ); } void CFTListView::OnUpdateActionFtinit(CCmdUI* pCmdUI) { CObArray arrSelectedItems; GetSelectedItems( arrSelectedItems ); UpdateActionFtinit( pCmdUI, arrSelectedItems ); } void CFTListView::OnActionFtmirror() { CObArray arrSelectedItems; GetSelectedItems( arrSelectedItems ); ActionFtmirror( arrSelectedItems ); } void CFTListView::OnUpdateActionFtmirror(CCmdUI* pCmdUI) { CObArray arrSelectedItems; GetSelectedItems( arrSelectedItems ); UpdateActionFtmirror( pCmdUI, arrSelectedItems ); } void CFTListView::OnActionFtstripe() { CObArray arrSelectedItems; GetSelectedItems( arrSelectedItems ); ActionFtstripe( arrSelectedItems ); } void CFTListView::OnUpdateActionFtstripe(CCmdUI* pCmdUI) { CObArray arrSelectedItems; GetSelectedItems( arrSelectedItems ); UpdateActionFtstripe( pCmdUI, arrSelectedItems ); } void CFTListView::OnActionFtswap() { CObArray arrSelectedItems; GetSelectedItems( arrSelectedItems ); ActionFtswap( arrSelectedItems ); } void CFTListView::OnUpdateActionFtswap(CCmdUI* pCmdUI) { CObArray arrSelectedItems; GetSelectedItems( arrSelectedItems ); UpdateActionFtswap( pCmdUI, arrSelectedItems ); } void CFTListView::OnActionFtswp() { CObArray arrSelectedItems; GetSelectedItems( arrSelectedItems ); ActionFtswp( arrSelectedItems ); } void CFTListView::OnUpdateActionFtswp(CCmdUI* pCmdUI) { CObArray arrSelectedItems; GetSelectedItems( arrSelectedItems ); UpdateActionFtswp( pCmdUI, arrSelectedItems ); } void CFTListView::OnActionFtvolset() { CObArray arrSelectedItems; GetSelectedItems( arrSelectedItems ); ActionFtvolset( arrSelectedItems ); } void CFTListView::OnUpdateActionFtvolset(CCmdUI* pCmdUI) { CObArray arrSelectedItems; GetSelectedItems( arrSelectedItems ); UpdateActionFtvolset( pCmdUI, arrSelectedItems ); }