//+------------------------------------------------------------------------- // // Microsoft Windows // Copyright (C) Microsoft Corporation, 1992 - 1999 // // File: colwidth.cpp // // Contents: Column Persistence data structures and property pages // implementation. // // History: 16-Oct-98 AnandhaG Created // //-------------------------------------------------------------------------- #include "stdafx.h" #include "colwidth.h" #include "macros.h" #include "comdbg.h" #include "columninfo.h" #define MAX_COLUMNS_PERSISTED 50 //+------------------------------------------------------------------- // // Class: ViewToColSetDataMapPersistor (wrapper, helper) // // Purpose: wraps ViewToColSetDataMap implementing XML persistence // map is persisted as linear list // // see "Data structures used to persist column information" comment // int file colwidth.h for more information //-------------------------------------------------------------------- class ViewToColSetDataMapPersistor : public XMLListCollectionBase { public: ViewToColSetDataMapPersistor(ViewToColSetDataMap &map, ColSetDataList &list) : m_map(map), m_list(list) {} DEFINE_XML_TYPE(XML_TAG_COLUMN_SET); virtual void Persist(CPersistor &persistor); virtual void OnNewElement(CPersistor& persistor); private: ViewToColSetDataMap &m_map; // wrapped map ColSetDataList &m_list; // value list to persist actual information }; //+------------------------------------------------------------------- // // Class: ColSetIDToViewTableMapPersistor (wrapper, helper) // // Purpose: wraps ColSetIDToViewTableMap implementing XML persistence // map is persisted as linear list // // see "Data structures used to persist column information" comment // int file colwidth.h for more information //-------------------------------------------------------------------- class ColSetIDToViewTableMapPersistor : public XMLListCollectionBase { public: ColSetIDToViewTableMapPersistor(ColSetIDToViewTableMap &map, ColSetDataList &list) : m_map(map), m_list(list) {} DEFINE_XML_TYPE(XML_TAG_COLUMN_PERIST_ENTRY); virtual void Persist(CPersistor &persistor); virtual void OnNewElement(CPersistor& persistor); private: ColSetIDToViewTableMap &m_map; // wrapped map ColSetDataList &m_list; // value list to persist actual information }; //+------------------------------------------------------------------- // // Class: SnapinToColSetIDMapPersistor (wrapper, helper) // // Purpose: wraps SnapinToColSetIDMap implementing XML persistence // map is persisted as linear list // // see "Data structures used to persist column information" comment // int file colwidth.h for more information //-------------------------------------------------------------------- class SnapinToColSetIDMapPersistor : public XMLListCollectionBase { public: SnapinToColSetIDMapPersistor(SnapinToColSetIDMap &map, ColSetDataList &list) : m_map(map), m_list(list) {} DEFINE_XML_TYPE(XML_TAG_COLUMN_PERIST_ENTRY); virtual void Persist(CPersistor &persistor); virtual void OnNewElement(CPersistor& persistor); // prior-to-save cleanup SC ScPurgeUnusedColumnData(); private: SnapinToColSetIDMap &m_map; // wrapped map ColSetDataList &m_list; // value list to persist actual information }; //+------------------------------------------------------------------- // // Member: ReadSerialObject // // Synopsis: Read the given version of CColumnSortInfo object from // the given stream. // // Arguments: [stm] - The input stream. // [nVersion] - version of CColumnSortInfo to be read. // // The format is : // INT column index // DWORD Sort options // ULONG_PTR Any user (snapin) param // //-------------------------------------------------------------------- HRESULT CColumnSortInfo::ReadSerialObject(IStream &stm, UINT nVersion /*,LARGE_INTEGER nBytes*/) { HRESULT hr = S_FALSE; // assume bad version if (GetVersion() >= nVersion) { try { stm >> m_nCol; // In version we stored just ascending or descending flag if (1 == nVersion) { BYTE bAscend; stm >> bAscend; m_dwSortOptions |= (bAscend ? 0 : RSI_DESCENDING); } else if (nVersion > 1) { // Versions greater than 1 has these sort data which // includes ascend/descend flags and a user param. stm >> m_dwSortOptions; stm >> m_lpUserParam; } hr = S_OK; } catch (_com_error& err) { hr = err.Error(); ASSERT (false && "Caught _com_error"); } } return (hr); } //+------------------------------------------------------------------- // // Member: CColumnSortInfo::Persist // // Synopsis: Persists object data // // Arguments: // // History: 10-10-1999 AudriusZ Created // //-------------------------------------------------------------------- void CColumnSortInfo::Persist(CPersistor &persistor) { persistor.PersistAttribute(XML_ATTR_COLUMN_SORT_INFO_COLMN, m_nCol) ; static const EnumLiteral sortOptions[] = { { RSI_DESCENDING, XML_BITFLAG_COL_SORT_DESCENDING }, { RSI_NOSORTICON, XML_BITFLAG_COL_SORT_NOSORTICON }, }; CXMLBitFlags optionPersistor(m_dwSortOptions, sortOptions, countof(sortOptions)); persistor.PersistAttribute(XML_ATTR_COLUMN_SORT_INFO_OPTNS, optionPersistor) ; } //+------------------------------------------------------------------- // // Member: ReadSerialObject // // Synopsis: Reads CColumnSortList data from stream. // // Format: number of columns : each CColumnSortInfo entry. // // Arguments: [stm] - The input stream. // [nVersion] - Version of CColumnSortList to be read. // // //-------------------------------------------------------------------- HRESULT CColumnSortList::ReadSerialObject (IStream &stm, UINT nVersion /*,LARGE_INTEGER nBytes*/) { HRESULT hr = S_FALSE; // assume bad version if (GetVersion() == nVersion) { try { // Number of columns. DWORD dwCols; stm >> dwCols; clear(); for (int i = 0; i < dwCols; i++) { CColumnSortInfo colSortEntry; // Read data into colSortEntry structure. if (colSortEntry.Read(stm) != S_OK) continue; push_back(colSortEntry); } hr = S_OK; } catch (_com_error& err) { hr = err.Error(); ASSERT (false && "Caught _com_error"); } } return (hr); } /***************************************************************************\ * * METHOD: CColumnSortList::Persist * * PURPOSE: persists object to XML * * PARAMETERS: * CPersistor& persistor [in/out] persistor to persist under * * RETURNS: * void * \***************************************************************************/ void CColumnSortList::PersistSortList(CPersistor& persistor) { DECLARE_SC(sc, TEXT("CColumnSortList::PersistSortList")); if (persistor.IsLoading()) { clear(); CColumnSortInfo sortInfo; if (persistor.HasElement(sortInfo.GetXMLType(), NULL)) { persistor.Persist(sortInfo); insert(end(), sortInfo); } } else { if (size() > 1) sc.Throw(E_UNEXPECTED); else if (size()) persistor.Persist(*begin()); } } //+------------------------------------------------------------------- // // Member: ReadSerialObject // // Synopsis: Read CColumnSetData data from the stream. // // Arguments: [stm] - The input stream. // [nVersion] - Version of CColumnSetData structure. // // Format : CColumnInfoList : CColumnSortList // // //-------------------------------------------------------------------- HRESULT CColumnSetData::ReadSerialObject (IStream &stm, UINT nVersion /*,LARGE_INTEGER nBytes*/) { HRESULT hr = S_FALSE; // assume bad version if (GetVersion() == nVersion) { try { do // not a loop { // Read the rank stm >> m_dwRank; // Read the CColumnInfoList hr = get_ColumnInfoList()->Read(stm); if (hr != S_OK) break; // Read the CColumnSortList hr = get_ColumnSortList()->Read(stm); if (hr != S_OK) break; ASSERT (hr == S_OK); } while (false); } catch (_com_error& err) { hr = err.Error(); ASSERT (false && "Caught _com_error"); } } return (hr); } //+------------------------------------------------------------------- // // Member: CColumnSetData::Persist // // Synopsis: Persists object data // // Arguments: // // History: 10-10-1999 AudriusZ Created // //-------------------------------------------------------------------- void CColumnSetData::Persist(CPersistor &persistor) { DECLARE_SC(sc, TEXT("CColumnSetData::Persist")); sc = ScCheckPointers(get_ColumnInfoList(), get_ColumnSortList()); if (sc) sc.Throw(); persistor.PersistAttribute(XML_ATTR_COLUMN_SET_RANK, m_dwRank); // Write CColumnInfoList persistor.Persist(*get_ColumnInfoList()); // Write CColumnSortList get_ColumnSortList()->PersistSortList(persistor); } //------------------------------------------------------------------ // class CColumnPersistInfo //------------------------------------------------------------------ CColumnPersistInfo::CColumnPersistInfo() : m_bInitialized(FALSE), m_dwMaxItems(MAX_COLUMNS_PERSISTED), m_bDirty(FALSE) { } CColumnPersistInfo::~CColumnPersistInfo() { } //+------------------------------------------------------------------- // // Member: RetrieveColumnData // // Synopsis: Copy and return the persisted column information // for given column id and view id. // // Arguments: [refSnapinCLSID] - Snapin Guid // [SColumnSetID] - Column Set Identifier. // [nViewID] - View ID. // [columnSetData] - CColumnSetData, used to return the // persisted column information. // // Returns: TRUE - Loaded successfully. // // History: 10-16-1998 AnandhaG Created // //-------------------------------------------------------------------- BOOL CColumnPersistInfo::RetrieveColumnData( const CLSID& refSnapinCLSID, const SColumnSetID& colID, INT nViewID, CColumnSetData& columnSetData) { BOOL bFound = FALSE; // Make sure we are initialized. if (!m_bInitialized && !Init()) { ASSERT(FALSE); return bFound; } // Construct CColumnSetID. CColumnSetID colSetID(colID); // Use the snapin clsid to get the ColSetIDToViewTableMap. SnapinToColSetIDMap::iterator itSnapins; itSnapins = m_spSnapinsMap->find(refSnapinCLSID); if (itSnapins == m_spSnapinsMap->end()) return bFound; // The ColSetIDToViewTableMap is a simple map. ColSetIDToViewTableMap::iterator itColSetIDMap; ColSetIDToViewTableMap& colSetIDMap = itSnapins->second; // Get the data for colSetID. itColSetIDMap = colSetIDMap.find(colSetID); if (colSetIDMap.end() == itColSetIDMap) return bFound; ViewToColSetDataMap& viewData = itColSetIDMap->second; ViewToColSetDataMap::iterator itViews; // See if our view is present. itViews = viewData.find(nViewID); if (viewData.end() != itViews) { // Found the item. bFound = TRUE; ItColSetDataList itColSetData = itViews->second; // Copy the data. columnSetData = *itColSetData; // So move this item to the top of the queue. m_spColSetList->erase(itColSetData); itColSetData = m_spColSetList->insert(m_spColSetList->begin(), columnSetData); itViews->second = itColSetData; } return bFound; } //+------------------------------------------------------------------- // // Member: SaveColumnData // // Synopsis: Save/Modify the column information for persistence into // CColumnPersistInfo. // // Arguments: // [refSnapinCLSID] - Snapin Guid. // [SColumnSetID] - Column Set Identifier. // [nViewID] - View ID. // [columnSetData] - CColumnSetData, Column data. // // Returns: TRUE - Saved successfully. // // History: 10-16-1998 AnandhaG Created // //-------------------------------------------------------------------- BOOL CColumnPersistInfo::SaveColumnData( const CLSID& refSnapinCLSID, const SColumnSetID& colID, INT nViewID, CColumnSetData& columnSetData) { // Make sure we are init if (!m_bInitialized && !Init()) { ASSERT(FALSE); return FALSE; } // Construct the CColumnSetID. CColumnSetID colSetID(colID); // Garbage collect if the number of items in the list is 40% more then pre-set limit. if (m_spColSetList->size() >= (m_dwMaxItems * (1 + COLUMNS_MAXLIMIT)) ) GarbageCollectItems(); // Insert this item to the top of the queue. ItColSetDataList itColData; itColData = m_spColSetList->insert(m_spColSetList->begin(), columnSetData); SnapinToColSetIDMap::iterator itSnapins; itSnapins = m_spSnapinsMap->find(refSnapinCLSID); if (itSnapins != m_spSnapinsMap->end()) { // Snapin is already in the map. // Look if the col-id is already inserted. ColSetIDToViewTableMap::iterator itColSetIDMap; ColSetIDToViewTableMap& colSetIDMap = itSnapins->second; // Get the data for the colSetID. itColSetIDMap = colSetIDMap.find(colSetID); if (colSetIDMap.end() == itColSetIDMap) { // The column-id not found. // So insert new one. // Construct the view-id to column-data map ViewToColSetDataMap viewIDMap; viewIDMap.insert( ViewToColSetDataVal(nViewID, itColData) ); colSetIDMap.insert(ColSetIDToViewTableVal(colSetID, viewIDMap) ); } else { // The data for Col-ID exists. // find if the given view exists in the map. ViewToColSetDataMap::iterator itViewIDMap; ViewToColSetDataMap& viewIDMap = itColSetIDMap->second; itViewIDMap = viewIDMap.find(nViewID); if (viewIDMap.end() != itViewIDMap) { // The map from ViewID to column list exists. // So delete the old data and insert new data // at the top of the queue. m_spColSetList->erase(itViewIDMap->second); itViewIDMap->second = itColData; } else { // This view is not found. // So insert new one. viewIDMap.insert( ViewToColSetDataVal(nViewID, itColData) ); } } } else { // Insert the snapin into the map. // Construct the ViewID to column-data map. ViewToColSetDataMap viewIDMap; viewIDMap.insert( ViewToColSetDataVal(nViewID, itColData) ); // Insert the above into the col-id map. ColSetIDToViewTableMap colIDMap; colIDMap.insert( ColSetIDToViewTableVal(colSetID, viewIDMap) ); // Insert into the snapins map. m_spSnapinsMap->insert( SnapinToColSetIDVal(refSnapinCLSID, colIDMap) ); } // Set dirty after modifying the column-data. m_bDirty = TRUE; return TRUE; } //+------------------------------------------------------------------- // // Member: DeleteColumnData // // Synopsis: Delete the persisted column information for the given // snapin, col-id and view id. // // Arguments: // [refSnapinCLSID] - Snapin Guid. // [SColumnSetID] - Column Set Identifier. // [nViewID] - View ID. // // Returns: None. // // History: 02-13-1999 AnandhaG Created // //-------------------------------------------------------------------- VOID CColumnPersistInfo::DeleteColumnData( const CLSID& refSnapinCLSID, const SColumnSetID& colID, INT nViewID) { // Make sure we are initialized. if (!m_bInitialized && !Init()) { ASSERT(FALSE); return; } // Construct CColumnSetID. CColumnSetID colSetID(colID); // Use the snapin clsid to get the ColSetIDToViewTableMap. SnapinToColSetIDMap::iterator itSnapins; itSnapins = m_spSnapinsMap->find(refSnapinCLSID); if (itSnapins == m_spSnapinsMap->end()) return; // The ColSetIDToViewTableMap is a simple map. ColSetIDToViewTableMap::iterator itColSetIDMap; ColSetIDToViewTableMap& colSetIDMap = itSnapins->second; // Get the data for colSetID. itColSetIDMap = colSetIDMap.find(colSetID); if (colSetIDMap.end() == itColSetIDMap) return; ViewToColSetDataMap& viewData = itColSetIDMap->second; ViewToColSetDataMap::iterator itViews; // See if our view is present. itViews = viewData.find(nViewID); if (viewData.end() == itViews) return; ItColSetDataList itColSetData = itViews->second; itColSetData->m_bInvalid = TRUE; // Delete the invalid items. DeleteMarkedItems(); return; } //+------------------------------------------------------------------- // // Member: DeleteColumnDataOfSnapin // // Synopsis: Delete the column data of given snapin. // // Arguments: [refSnapinCLSID] - Snapin Guid. // // Returns: TRUE - Data removed successfully. // // History: 02-11-1999 AnandhaG Created // //-------------------------------------------------------------------- BOOL CColumnPersistInfo::DeleteColumnDataOfSnapin( const CLSID& refSnapinCLSID) { // Make sure we are init if (!m_bInitialized) { return FALSE; } SnapinToColSetIDMap::iterator itSnapinsMap; itSnapinsMap = m_spSnapinsMap->find(refSnapinCLSID); // Find the given snapin. // Iterate thro all the col-ids of this snapin and // all the views of those col-id and set the data // to be invalid. if (m_spSnapinsMap->end() != itSnapinsMap) { ColSetIDToViewTableMap& colSets = itSnapinsMap->second; // Iterate thro' all colset ids of this snapin. ColSetIDToViewTableMap::iterator itColumnSetIDMap; for (itColumnSetIDMap = colSets.begin(); itColumnSetIDMap != colSets.end(); ++itColumnSetIDMap) { // Get the view map ViewToColSetDataMap& viewIDMap = itColumnSetIDMap->second; ViewToColSetDataMap::iterator itViewIDMap; // Iterate thro' all views and set the data invalid. for (itViewIDMap = viewIDMap.begin(); itViewIDMap != viewIDMap.end(); ++itViewIDMap) { ItColSetDataList itColSetData = itViewIDMap->second; itColSetData->m_bInvalid = TRUE; } } } // Delete the invalid items. DeleteMarkedItems(); return TRUE; } //+------------------------------------------------------------------- // // Member: DeleteColumnDataOfView // // Synopsis: Delete the column data of given view. // // Arguments: [nViewID] - View ID. // // Returns: TRUE - Data removed successfully. // // History: 02-11-1999 AnandhaG Created // //-------------------------------------------------------------------- BOOL CColumnPersistInfo::DeleteColumnDataOfView( int nViewID) { // Make sure we are init if (!m_bInitialized) { return FALSE; } // Iterate thro all snapins, col-ids and find the matching // view and set data to be invalid. SnapinToColSetIDMap::iterator itSnapinsMap; // Iterate thro all snapins. for (itSnapinsMap = m_spSnapinsMap->begin(); m_spSnapinsMap->end() != itSnapinsMap; ++itSnapinsMap) { ColSetIDToViewTableMap& colSets = itSnapinsMap->second; ColSetIDToViewTableMap::iterator itColumnSetIDMap; // Iterate thro' all colset ids of this snapin. for (itColumnSetIDMap = colSets.begin(); itColumnSetIDMap != colSets.end(); ++itColumnSetIDMap) { // Get the view map ViewToColSetDataMap& viewIDMap = itColumnSetIDMap->second; ViewToColSetDataMap::iterator itViewIDMap; // Find the matching views and mark them to be deleted. for (itViewIDMap = viewIDMap.begin(); itViewIDMap != viewIDMap.end(); ++itViewIDMap) { if (nViewID == itViewIDMap->first) { ItColSetDataList itColSetData = itViewIDMap->second; itColSetData->m_bInvalid = TRUE; } } } } // Delete the invalid items. DeleteMarkedItems(); return TRUE; } //+------------------------------------------------------------------- // // Member: Init // // Synopsis: Create the Map and the list for CColumnSetData. // // Returns: TRUE - for success. // // History: 10-16-1998 AnandhaG Created // //-------------------------------------------------------------------- BOOL CColumnPersistInfo::Init() { // Create the data structures to store column data. m_spSnapinsMap = auto_ptr(new SnapinToColSetIDMap); m_spColSetList = auto_ptr (new ColSetDataList); // Now the objects are created, so now set initialized to true. m_bInitialized = TRUE; // Now read the registry to see if m_dwMaxItems is specified. // Check if the settings key exists. CRegKeyEx rSettingsKey; if (rSettingsKey.ScOpen (HKEY_LOCAL_MACHINE, SETTINGS_KEY, KEY_READ).IsError()) return m_bInitialized; // Read the values for MaxColDataPersisted. if (rSettingsKey.IsValuePresent(g_szMaxColumnDataPersisted)) { DWORD dwType = REG_DWORD; DWORD dwSize = sizeof(DWORD); SC sc = rSettingsKey.ScQueryValue (g_szMaxColumnDataPersisted, &dwType, &m_dwMaxItems, &dwSize); if (sc) sc.TraceAndClear(); } return m_bInitialized; } //+------------------------------------------------------------------- // // Member: GarbageCollectItems // // Synopsis: Free least used column data. // // Arguments: None. // // History: 02-11-1999 AnandhaG Created // //-------------------------------------------------------------------- VOID CColumnPersistInfo::GarbageCollectItems() { INT nItemsToBeRemoved = COLUMNS_MAXLIMIT * m_dwMaxItems; // Go thro' the list and set the nItemsToBeRemoved that was least recently // accessed to be invalid. INT nIndex = 0; ItColSetDataList itColList; // Skip first m_dwMaxItems. for (itColList = m_spColSetList->begin(); ( (itColList != m_spColSetList->end()) && (nIndex <= m_dwMaxItems) ); ++itColList, nIndex++) { nIndex++; } // Mark rest of the items to be garbage. while (itColList != m_spColSetList->end()) { itColList->m_bInvalid = TRUE; ++itColList; } // Delete the invalid items. DeleteMarkedItems(); return; } //+------------------------------------------------------------------- // // Member: DeleteMarkedItems // // Synopsis: Delete invalidated items. This involves iterating thro // the maps to find the invalid items. Then deleting the // items. If the map becomes empty then delete the map. // // History: 02-11-1999 AnandhaG Created // //-------------------------------------------------------------------- VOID CColumnPersistInfo::DeleteMarkedItems() { SnapinToColSetIDMap::iterator itSnapinsMap, itSnapinsMapNew; // Now iterate thro the map and remove those elements. itSnapinsMap = m_spSnapinsMap->begin(); while (itSnapinsMap != m_spSnapinsMap->end()) { ColSetIDToViewTableMap& colSets = itSnapinsMap->second; ColSetIDToViewTableMap::iterator itColumnSetIDMap; // Iterate thro this snapins col-ids. itColumnSetIDMap = colSets.begin(); while (itColumnSetIDMap != colSets.end()) { // Get the view map ViewToColSetDataMap& viewIDMap = itColumnSetIDMap->second; ViewToColSetDataMap::iterator itViewIDMap; // Iterate thro all the views. itViewIDMap = viewIDMap.begin(); while (itViewIDMap != viewIDMap.end()) { ItColSetDataList itColSetData = itViewIDMap->second; if (itColSetData->m_bInvalid) { // Delete the item ref from the map. // Erase returns iterator to next item. itViewIDMap = viewIDMap.erase(itViewIDMap); // Delete the item from the list. m_spColSetList->erase(itColSetData); } else // Item is valid item. ++itViewIDMap; } // If the view has zero items we need to remove this // view map. (ColID to ViewMap). if (0 == viewIDMap.size()) { // Delete the col-id map. // Erase returns iterator to next item. itColumnSetIDMap = colSets.erase(itColumnSetIDMap); } else ++itColumnSetIDMap; } // If there are no col-id's remove the // Snapin to this col-id map. if (0 == colSets.size()) { // Delete this snapin map. // Erase returns iterator to next item. itSnapinsMap = m_spSnapinsMap->erase(itSnapinsMap); } else ++itSnapinsMap; } return; } //+------------------------------------------------------------------- // // Member: Load // // Synopsis: Load the persisted column information. // // Arguments: [pStream]- ISteam from which column widths to be loaded. // // Returns: S_OK - Loaded successfully. // // History: 10-16-1998 AnandhaG Created // //-------------------------------------------------------------------- STDMETHODIMP CColumnPersistInfo::Load (IStream* pStream) { HRESULT hr = E_FAIL; if (!m_bInitialized && !Init()) { ASSERT(FALSE); return hr; } // read the column width information. try { do { // Read the version. If it did not match return INT nVersion = 0; *pStream >> nVersion; if (COLPersistenceVersion != nVersion) return S_FALSE; // Read the # of Snapins DWORD dwSnapins = 0; *pStream >> dwSnapins; m_spColSetList->clear(); m_spSnapinsMap->clear(); // For each snapin... for (int nSnapIdx = 0; nSnapIdx < dwSnapins; nSnapIdx++) { // Read snapin CLSID. CLSID clsidSnapin; *pStream >> clsidSnapin; // Read the number of col-ids for this snapin. DWORD dwColIDs = 0; *pStream >> dwColIDs; ColSetIDToViewTableMap colSetsMap; // For each col-id... for (int nColIDIdx = 0; nColIDIdx < dwColIDs; nColIDIdx++) { // Read the col-id CColumnSetID colSetID; *pStream >> colSetID; // Read the number of views. DWORD dwNumViews = 0; *pStream >> dwNumViews; ViewToColSetDataMap ViewIDMap; // For each view... for (int nViewIdx = 0; nViewIdx < dwNumViews; nViewIdx++) { // Read view id. DWORD dwViewID; *pStream >> dwViewID; // Read the CColumnSetData. CColumnSetData ColData; ColData.Read(*pStream); // Insert the data into the global linked list. ItColSetDataList itColSetData; itColSetData = m_spColSetList->insert(m_spColSetList->begin(), ColData); // Insert the pointer to the data in to view map. ViewIDMap.insert(ViewToColSetDataVal(dwViewID, itColSetData)); } // Insert the view map into the col-id map. colSetsMap.insert(ColSetIDToViewTableVal(colSetID, ViewIDMap)); } // Insert the col-id map into the snapin map. m_spSnapinsMap->insert(SnapinToColSetIDVal(clsidSnapin, colSetsMap)); } // Now sort the list. m_spColSetList->sort(); } while (FALSE); } catch (_com_error& err) { hr = err.Error(); } catch (...) { ASSERT (0 && "Unexpected exception"); throw; } return S_OK; } //+------------------------------------------------------------------- // // Member: Save // // Synopsis: Persist the column information. // // Arguments: [pStream]- IStream in which column widths are to be saved. // // Returns: S_OK - Saved successfully. // // History: 10-16-1998 AnandhaG Created // //-------------------------------------------------------------------- STDMETHODIMP CColumnPersistInfo::Save (IStream* pStream, BOOL bClearDirty) { // absolete method. // this method is left here since we use IPersistStream to export // persistence to CONUI side and need to implement it. // But this interface will never be called to save data // [we will use CPersistor-based XML saving instead] // so the method will always fail. ASSERT(FALSE && "Should never come here"); return E_NOTIMPL; } //+------------------------------------------------------------------- // // Member: Persist // // Synopsis: Persists the column information. // // Arguments: [persistor]- CPersistor in/from which column widths are persisted. // // Returns: void. // // History: 10-08-1999 AudriusZ Created // //-------------------------------------------------------------------- void CColumnPersistInfo::Persist(CPersistor &persistor) { DECLARE_SC(sc, TEXT("CColumnPersistInfo::Persist")); if (!m_bInitialized && !Init()) sc.Throw(E_FAIL); sc = ScCheckPointers(m_spColSetList.get(), m_spSnapinsMap.get(), E_UNEXPECTED); if (sc) sc.Throw(); if (persistor.IsStoring()) { // Give ranking to each column data. ItColSetDataList itColList; DWORD dwRank = 0; for (itColList = m_spColSetList->begin(); itColList != m_spColSetList->end(); ++itColList) { itColList->m_dwRank = dwRank++; } } else // if (persistor.IsLoading()) { m_spColSetList->clear(); m_spSnapinsMap->clear(); } SnapinToColSetIDMapPersistor childPersisot(*m_spSnapinsMap, *m_spColSetList); childPersisot.Persist(persistor); if (persistor.IsStoring()) m_bDirty = FALSE; } //+------------------------------------------------------------------- // // Member: OnInitDialog // // Synopsis: Initialize the Columns dialog. // // Arguments: // // History: 11-16-1998 AnandhaG Created // //-------------------------------------------------------------------- LRESULT CColumnsDlg::OnInitDialog (UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) { m_btnAdd = ::GetDlgItem(m_hWnd, IDC_ADD_COLUMNS); m_btnRemove = ::GetDlgItem(m_hWnd, IDC_REMOVE_COLUMNS); m_btnRestoreDefaultColumns = ::GetDlgItem(m_hWnd, IDC_RESTORE_DEFAULT_COLUMNS); m_btnMoveUp = ::GetDlgItem(m_hWnd, IDC_MOVEUP_COLUMN); m_btnMoveDown = ::GetDlgItem(m_hWnd, IDC_MOVEDOWN_COLUMN); m_HiddenColList.Attach(::GetDlgItem(m_hWnd, IDC_HIDDEN_COLUMNS)); m_DisplayedColList.Attach(::GetDlgItem(m_hWnd, IDC_DISPLAYED_COLUMNS)); m_bUsingDefaultColumnSettings = (*m_pColumnInfoList == m_DefaultColumnInfoList); InitializeLists(); EnableUIObjects(); return 0; } //+------------------------------------------------------------------- // // Member: OnOK // // Synopsis: Get the hidden and visible columns. // // Arguments: // // History: 11-16-1998 AnandhaG Created // //-------------------------------------------------------------------- LRESULT CColumnsDlg::OnOK (WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled) { if (! m_bDirty) // column settings are not modified { EndDialog (IDCANCEL); return 1; } if (m_bUsingDefaultColumnSettings) { EndDialog(IDC_RESTORE_DEFAULT_COLUMNS); return 1; } ASSERT(NULL != m_pColumnInfoList); if (NULL == m_pColumnInfoList) return 0; WTL::CString strColumnName; CColumnInfoList::iterator it; CColumnInfo colinfo; // Get the strings from Hidden_List_Box. // These cols are to be hidden. So put them first in the list. int cItems = m_HiddenColList.GetCount(); for (int i = 0; i < cItems; i++) { // Get the text from list box int nRet = m_HiddenColList.GetText(i, strColumnName); if (LB_ERR == nRet) { ASSERT(FALSE); break; } // Use the string to get the actual index of the column. int nIndex = GetColIndex(strColumnName); if (0 > nIndex ) { ASSERT(FALSE); break; } // With the index get the column and insert it at beginning. it = find_if(m_pColumnInfoList->begin(), m_pColumnInfoList->end(), bind2nd(ColPosCompare(), nIndex)); if (it == m_pColumnInfoList->end()) { ASSERT(FALSE); break; } // Set the *it flag to be hidden. Insert it at beginning. colinfo = *it; colinfo.SetColHidden(); // Move the item to the head of the list m_pColumnInfoList->erase(it); m_pColumnInfoList->push_front(colinfo); } // Then get the strings from DisplayedColumns_List_Box. cItems = m_DisplayedColList.GetCount(); for (i = 0; i < cItems; i++) { // Get the text from list box int nRet = m_DisplayedColList.GetText(i, strColumnName); if (LB_ERR == nRet) { ASSERT(FALSE); break; } // Use the column name to get the column index. int nIndex = GetColIndex(strColumnName); if (0 > nIndex ) { ASSERT(FALSE); break; } // Get the CColumnInfo and insert at end. it = find_if(m_pColumnInfoList->begin(), m_pColumnInfoList->end(), bind2nd(ColPosCompare(), nIndex)); if (it == m_pColumnInfoList->end()) break; colinfo = *it; if (colinfo.IsColHidden()) { // If hidden column is made visible // reset the hidden flag and set the width // to auto_width. colinfo.SetColHidden(false); if (colinfo.GetColWidth() <= 0) colinfo.SetColWidth(AUTO_WIDTH); } // Move it to the end of the list. m_pColumnInfoList->erase(it); m_pColumnInfoList->push_back(colinfo); } EndDialog (IDOK); return 1; } LRESULT CColumnsDlg::OnCancel (WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled) { EndDialog (IDCANCEL); return 0; } LRESULT CColumnsDlg::OnMoveUp (WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled) { MoveItem(TRUE); return 0; } LRESULT CColumnsDlg::OnMoveDown (WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled) { MoveItem(FALSE); return 0; } //+------------------------------------------------------------------- // // Member: OnAdd // // Synopsis: Adds a column to displayed columns list by removing // the currently selected column from hidden column list. // // Arguments: // //-------------------------------------------------------------------- LRESULT CColumnsDlg::OnAdd (WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled) { // First remove from hidden column list. int nCurSel = m_HiddenColList.GetCurSel(); WTL::CString strColumnName; int nRet = m_HiddenColList.GetText(nCurSel, strColumnName); if (LB_ERR == nRet) { ASSERT(FALSE); return 0; } m_HiddenColList.DeleteString(nCurSel); // now add it to Displayed column list. m_DisplayedColList.AddString(strColumnName); SetDirty(); if (nCurSel > m_HiddenColList.GetCount()-1) nCurSel = m_HiddenColList.GetCount()-1; m_HiddenColList.SetCurSel(nCurSel); m_DisplayedColList.SelectString(0, strColumnName); SetListBoxHScrollSize(); EnableUIObjects(); return 0; } //+------------------------------------------------------------------- // // Member: OnRemove // // Synopsis: Removes the currently selected column from displayed // columns list by removing and adds it to hidden column list. // // Arguments: // //-------------------------------------------------------------------- LRESULT CColumnsDlg::OnRemove (WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled) { // Get the currently selected item in Displayed Columns list. int nCurSel = m_DisplayedColList.GetCurSel(); WTL::CString strColumnName; int nRet = m_DisplayedColList.GetText(nCurSel, strColumnName); if (LB_ERR == nRet) { ASSERT(FALSE); return 0; } // If column zero do not hide it. if (0 == GetColIndex(strColumnName)) return 0; m_DisplayedColList.DeleteString(nCurSel); // Add it to hidden column list. m_HiddenColList.AddString(strColumnName); SetDirty(); if (nCurSel > m_DisplayedColList.GetCount()-1) nCurSel = m_DisplayedColList.GetCount()-1; m_DisplayedColList.SetCurSel(nCurSel); m_HiddenColList.SelectString(0, strColumnName); EnableUIObjects(); SetListBoxHScrollSize(); return 0; } LRESULT CColumnsDlg::OnRestoreDefaultColumns (WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled) { DECLARE_SC(sc, TEXT("CColumnsDlg::OnRestoreDefaultColumns")); // Get the default data and populate the columns dialog. *m_pColumnInfoList = m_DefaultColumnInfoList; SetUsingDefaultColumnSettings(); InitializeLists(); EnableUIObjects(); // Button is disabled so put the focus on the dialog. SetFocus(); return 0; } LRESULT CColumnsDlg::OnSelChange (WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled) { EnableUIObjects(); return 0; } //+------------------------------------------------------------------- // // Member: MoveItem // // Synopsis: Moves an item in the displayed columns list up or down. // The up down order is same as column visible order from // left to right. // // Arguments: [BOOL] - up or down. // //-------------------------------------------------------------------- void CColumnsDlg::MoveItem (BOOL bMoveUp) { int nCurSel = m_DisplayedColList.GetCurSel(); WTL::CString strColumnName; int nRet = m_DisplayedColList.GetText(nCurSel, strColumnName); if (LB_ERR == nRet) { ASSERT(FALSE); return; } m_DisplayedColList.DeleteString(nCurSel); if (bMoveUp) m_DisplayedColList.InsertString(nCurSel-1, strColumnName); else m_DisplayedColList.InsertString(nCurSel+1, strColumnName); m_DisplayedColList.SelectString(0, strColumnName); SetDirty(); EnableUIObjects(); return; } //+------------------------------------------------------------------- // // Member: EnableControl // // Synopsis: Enable or Disable a window. If this window has to be // disabled and it has focus, shift the focus to next // enabled item in the tab-sequence. // // Arguments: hwnd - window to be enabled or disabled. // bEnable - enable or disable. // //-------------------------------------------------------------------- bool CColumnsDlg::EnableControl(HWND hwnd, bool bEnable) { // If disabling and this window has focus then // put focus on next enabled window. if ( (!bEnable) && (hwnd == ::GetFocus()) ) { HWND hwndWindowToFocus = GetNextDlgTabItem(hwnd); if (hwndWindowToFocus) ::SetFocus(hwndWindowToFocus); } // Now enable or disable the control. return ::EnableWindow(hwnd, bEnable); } //+------------------------------------------------------------------- // // Member: EnableUIObjects // // Synopsis: Enable/Disable the UI objects in the dialog. // // Arguments: // //-------------------------------------------------------------------- void CColumnsDlg::EnableUIObjects() { int curselAvailable = m_HiddenColList.GetCurSel(); int curselShow = m_DisplayedColList.GetCurSel(); int cItems = m_HiddenColList.GetCount(); BOOL bEnableAdd = ((curselAvailable != LB_ERR) && (curselAvailable || cItems)) ? TRUE: FALSE; BOOL bEnableRemove = ((curselShow != LB_ERR)) ? TRUE: FALSE; BOOL bEnableMoveUp = ((curselShow != LB_ERR) && curselShow) ? TRUE: FALSE; cItems = m_DisplayedColList.GetCount(); BOOL bEnableMoveDown = cItems && (curselShow != LB_ERR) && (cItems!=curselShow+1); BOOL bRet = FALSE; HWND hHwnFocussed = ::GetFocus(); bRet = EnableControl(m_btnAdd, bEnableAdd); bRet = EnableControl(m_btnRemove, bEnableRemove); bRet = EnableControl(m_btnMoveUp, bEnableMoveUp); bRet = EnableControl(m_btnMoveDown, bEnableMoveDown); // Enable restore defaults only if columns are already customized before bringing the dialog bRet = EnableControl(m_btnRestoreDefaultColumns, (!m_bUsingDefaultColumnSettings)); // Disable Remove/Move Up/Move Down buttons for Col zero. int nCurSel = m_DisplayedColList.GetCurSel(); WTL::CString strColumnName; int nRet = m_DisplayedColList.GetText(nCurSel, strColumnName); if (LB_ERR == nRet) { ASSERT(FALSE); return; } if (0 == GetColIndex(strColumnName)) // Column 0 EnableControl(m_btnRemove, FALSE); } int CColumnsDlg::GetColIndex(LPCTSTR lpszColName) { TStringVector::iterator itStrVec1; USES_CONVERSION; itStrVec1 = find(m_pStringVector->begin(), m_pStringVector->end(), lpszColName); if (m_pStringVector->end() != itStrVec1) return (itStrVec1 - m_pStringVector->begin()); else // Unknown column return -1; } //+------------------------------------------------------------------- // // Member: SetListBoxHorizontalScrollbar // // Synopsis: For the given list box enumerate the strings added and find // the largest string. Calculate scrollbar size for this string // and set it. // // Arguments: [listBox] - Given list box. // //-------------------------------------------------------------------- void CColumnsDlg::SetListBoxHorizontalScrollbar(WTL::CListBox& listBox) { int dx=0; WTL::CDC dc(listBox.GetWindowDC()); if (dc.IsNull()) return; // Find the longest string in the list box. for (int i=0;i < listBox.GetCount();i++) { WTL::CString str; int nRet = listBox.GetText( i, str ); if (nRet == LB_ERR) return; WTL::CSize sz; if (! dc.GetTextExtent(str, str.GetLength(), &sz)) return; if (sz.cx > dx) dx = sz.cx; } // Set the horizontal extent so every character of all strings // can be scrolled to. listBox.SetHorizontalExtent(dx); return; } /* CColumnsDlg::InitializeLists * * PURPOSE: * * PARAMETERS: * * RETURNS: * void */ void CColumnsDlg::InitializeLists() { CColumnInfoList::iterator it; int j = 0; if (!m_pColumnInfoList) { ASSERT(FALSE); return; } m_HiddenColList.ResetContent(); m_DisplayedColList.ResetContent(); USES_CONVERSION; for (it = m_pColumnInfoList->begin(); it != m_pColumnInfoList->end(); ++it) { if (it->IsColHidden()) { m_HiddenColList.AddString(m_pStringVector->at(it->GetColIndex()).data()); } else { m_DisplayedColList.InsertString(j++, m_pStringVector->at(it->GetColIndex()).data()); } } m_DisplayedColList.SetCurSel(m_DisplayedColList.GetCount()-1); m_HiddenColList.SetCurSel(m_HiddenColList.GetCount()-1); SetListBoxHScrollSize(); } //+------------------------------------------------------------------- // // Member: CColumnSetID::Persist // // Synopsis: Persists object data // // Arguments: // // History: 10-10-1999 AudriusZ Created // //-------------------------------------------------------------------- void CColumnSetID::Persist(CPersistor &persistor) { DECLARE_SC(sc, TEXT("CColumnSetID::Persist")); CXMLAutoBinary binary; if (persistor.IsStoring() && m_vID.size()) // fill only if have data { sc = binary.ScAlloc(m_vID.size()); if (sc) sc.Throw(); CXMLBinaryLock sLock(binary); // will unlock in destructor LPBYTE pData = NULL; sc = sLock.ScLock(&pData); if (sc) sc.Throw(); sc = ScCheckPointers(pData, E_UNEXPECTED); if (sc) sc.Throw(); std::copy(m_vID.begin(), m_vID.end(), pData); } persistor.PersistAttribute(XML_ATTR_COLUMN_SET_ID_PATH, binary); if (persistor.IsLoading()) { m_vID.clear(); if (binary.GetSize()) { CXMLBinaryLock sLock(binary); // will unlock in destructor LPBYTE pData = NULL; sc = sLock.ScLock(&pData); if (sc) sc.Throw(); sc = ScCheckPointers(pData, E_UNEXPECTED); if (sc) sc.Throw(); m_vID.insert(m_vID.end(), pData, pData + binary.GetSize()); } } persistor.PersistAttribute(XML_ATTR_COLUMN_SET_ID_FLAGS, m_dwFlags); } /***************************************************************************\ * * METHOD: ViewToColSetDataMapPersistor::Persist * * PURPOSE: called by the base class to create and persist the new element * * PARAMETERS: * CPersistor& persistor - [in] persistor from which to persist new element * * RETURNS: * void * * see "Data structures used to persist column information" comment * int file colwidth.h for more information \***************************************************************************/ void ViewToColSetDataMapPersistor::Persist(CPersistor &persistor) { if (persistor.IsStoring()) { // iterate and save all elements as linear list ViewToColSetDataMap::iterator it; for (it = m_map.begin(); it != m_map.end(); ++it) { // we will sneak under child's element to persist the KEY value as an attribute // of the child element. To do that we use tag got from _GetXMLType() of the child CPersistor persistorChild(persistor, it->second->GetXMLType()); int view_id = it->first; // just to cast constness out (we do not have const Persist) persistorChild.PersistAttribute(XML_ATTR_COLUMN_SET_ID_VIEW, view_id); // note: we are asking the child to persist on the same level. // thats to save on depth it->second->Persist(persistorChild); } } else { // use base class to read. it will call OnNewElement for each found m_map.clear(); XMLListCollectionBase::Persist(persistor); } } /***************************************************************************\ * * METHOD: ViewToColSetDataMapPersistor::OnNewElement * * PURPOSE: called by the base class to create and persist the new element * * PARAMETERS: * CPersistor& persistor - [in] persistor from which to persist new element * * RETURNS: * void * * see "Data structures used to persist column information" comment * int file colwidth.h for more information \***************************************************************************/ void ViewToColSetDataMapPersistor::OnNewElement(CPersistor& persistor) { // we will sneak under child's element to persist the KEY value as an attribute // of the child element. To do that we use tag got from GetXMLType() of the child CColumnSetData setData; CPersistor persistorChild(persistor, setData.GetXMLType()); // read the key value from the child element int view_id = 0; persistorChild.PersistAttribute(XML_ATTR_COLUMN_SET_ID_VIEW, view_id); // insert value to the list ColSetDataList::iterator it = m_list.insert(m_list.end(), setData); // ad list iterator to the map m_map[view_id] = it; // persist contents of the list item it->Persist(persistorChild); } /***************************************************************************\ * * METHOD: ColSetIDToViewTableMapPersistor::Persist * * PURPOSE: called as a request for the object to persist it's data * * PARAMETERS: * CPersistor &persistor [in] persistor to persist to/from * * RETURNS: * void * * see "Data structures used to persist column information" comment * int file colwidth.h for more information \***************************************************************************/ void ColSetIDToViewTableMapPersistor::Persist(CPersistor &persistor) { if (persistor.IsStoring()) { // iterate and save all elements as linear list ColSetIDToViewTableMap::iterator it; for (it = m_map.begin(); it != m_map.end(); ++it) { // we will sneak under child's element to persist the KEY value as an attribute // of the child element. To do that we use tag got from _GetXMLType() of the child CPersistor persistorChild(persistor, ViewToColSetDataMapPersistor::_GetXMLType()); CColumnSetID& rID = *const_cast(&it->first); rID.Persist(persistorChild); // note: we are asking the child to persist on the same level. // thats to save on depth ViewToColSetDataMapPersistor mapPersistor(it->second, m_list); mapPersistor.Persist(persistorChild); } } else { // use base class to read. it will call OnNewElement for each found m_map.clear(); XMLListCollectionBase::Persist(persistor); } } /***************************************************************************\ * * METHOD: ColSetIDToViewTableMapPersistor::OnNewElement * * PURPOSE: called by the base class to create and persist the new element * * PARAMETERS: * CPersistor& persistor - [in] persistor from which to persist new element * * RETURNS: * void * * see "Data structures used to persist column information" comment * int file colwidth.h for more information \***************************************************************************/ void ColSetIDToViewTableMapPersistor::OnNewElement(CPersistor& persistor) { // we will sneak under child's element to persist the KEY value as an attribute // of the child element. To do that we use tag got from _GetXMLType() of the child CPersistor persistorChild(persistor, ViewToColSetDataMapPersistor::_GetXMLType()); // read the key value from the child element // note that we are forcing CColumnSetID to share the same element, // therefore we are not using persistor.Persist() CColumnSetID ID; ID.Persist(persistorChild); // insert the new element into the map ViewToColSetDataMap &rMap = m_map[ID]; // create the wrapper on inserted map value // (pass a list to wrapper. we actually have it [list] for this only reason) ViewToColSetDataMapPersistor mapPersistor(m_map[ID], m_list); // ask wrapper to read the rest mapPersistor.Persist(persistorChild); } /***************************************************************************\ * * METHOD: SnapinToColSetIDMapPersistor::Persist * * PURPOSE: * * PARAMETERS: * CPersistor &persistor * * RETURNS: * void * * see "Data structures used to persist column information" comment * int file colwidth.h for more information \***************************************************************************/ void SnapinToColSetIDMapPersistor::Persist(CPersistor &persistor) { DECLARE_SC(sc, TEXT("SnapinToColSetIDMapPersistor::Persist")); if (persistor.IsStoring()) { // prior-to-save cleanup sc = ScPurgeUnusedColumnData(); if (sc) sc.Throw(); // iterate and save all elements as linear list SnapinToColSetIDMap::iterator it; for (it = m_map.begin(); it != m_map.end(); ++it) { // we will sneak under child's element to persist the KEY value as an attribute // of the child element. To do that we use tag got from _GetXMLType() of the child CPersistor persistorChild(persistor, ColSetIDToViewTableMapPersistor::_GetXMLType()); // write the key value. // just to cast constness out (we do not have const Persist) GUID& guid = *const_cast(&it->first); persistorChild.PersistAttribute(XML_ATTR_COLUMN_INFO_SNAPIN, guid); // create a wrapper on the value (which is also a map) // (pass a list to wrapper. though it's not used for storing) ColSetIDToViewTableMapPersistor mapPersistor(it->second, m_list); // persist the wrapper mapPersistor.Persist(persistorChild); } } else { // use base class to read. it will call OnNewElement for each found m_map.clear(); XMLListCollectionBase::Persist(persistor); } } /***************************************************************************\ * * METHOD: SnapinToColSetIDMapPersistor::OnNewElement * * PURPOSE: called by the base class to create and persist the new element * * PARAMETERS: * CPersistor& persistor - [in] persistor from which to persist new element * * RETURNS: * void * * see "Data structures used to persist column information" comment * int file colwidth.h for more information \***************************************************************************/ void SnapinToColSetIDMapPersistor::OnNewElement(CPersistor& persistor) { // we will sneak under child's element to persist the KEY value as an attribute // of the child element. To do that we use tag got from _GetXMLType() of the child CPersistor persistorChild(persistor, ColSetIDToViewTableMapPersistor::_GetXMLType()); GUID guid; // read the key value persistorChild.PersistAttribute(XML_ATTR_COLUMN_INFO_SNAPIN, guid); // insert the new element into the map ColSetIDToViewTableMap &rMap = m_map[guid]; // create the wrapper on inserted map value // (pass a list to wrapper. we actually have it [list] for this only reason) ColSetIDToViewTableMapPersistor mapPersistor(rMap, m_list); // ask wrapper to read the rest mapPersistor.Persist(persistorChild); } /***************************************************************************\ * * METHOD: SnapinToColSetIDMapPersistor::ScPurgeUnusedColumnData * * PURPOSE: prior-to-save cleanup. removes unused snapin entries * * PARAMETERS: * * RETURNS: * SC - result code * \***************************************************************************/ SC SnapinToColSetIDMapPersistor::ScPurgeUnusedColumnData() { DECLARE_SC(sc, TEXT("SnapinToColSetIDMapPersistor::ScPurgeUnusedColumnData")); // get the scopetree pointer CScopeTree *pScopeTree = CScopeTree::GetScopeTree(); // check it sc = ScCheckPointers(pScopeTree, E_UNEXPECTED); if (sc) return sc; // iterate and remove unused entries SnapinToColSetIDMap::iterator it = m_map.begin(); while (it != m_map.end()) { // ask the scope tree if snapin is in use BOOL bInUse = FALSE; sc = pScopeTree->IsSnapinInUse(it->first, &bInUse); if (sc) return sc; // act depending on usage if (bInUse) { ++it; // skip also the stuff currently in use } else { // to the trash can ColSetIDToViewTableMap& colSets = it->second; // Iterate thro' all colset ids of this snapin. ColSetIDToViewTableMap::iterator itColumnSetIDMap = colSets.begin(); while(itColumnSetIDMap != colSets.end()) { // Get the view map ViewToColSetDataMap& viewIDMap = itColumnSetIDMap->second; ViewToColSetDataMap::iterator itViewIDMap = viewIDMap.begin(); // Iterate thro' all views and remove entries while (itViewIDMap != viewIDMap.end()) { m_list.erase(/*(ItColSetDataList)*/itViewIDMap->second); itViewIDMap = viewIDMap.erase(itViewIDMap); } itColumnSetIDMap = colSets.erase(itColumnSetIDMap); } it = m_map.erase(it); } } return sc; }