|
|
//+-------------------------------------------------------------------------
//
// 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<SnapinToColSetIDMap>(new SnapinToColSetIDMap);
m_spColSetList = auto_ptr<ColSetDataList> (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<CColumnSetID *>(&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<GUID *>(&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; }
|