Click here to Skip to main content
15,891,951 members
Articles / Programming Languages / C++

Project Line Counter Add-In v2.10 for VS.NET and VC6

Rate me:
Please Sign up or sign in to vote.
4.92/5 (38 votes)
29 Jun 2003 449.5K   5.3K   142  
Get statistics about your source code with a click of a button
/***************************************************************************/
/* NOTE:                                                                   */
/* This document is copyright (c) by Oz Solomonovich, and is bound by the  */
/* MIT open source license (www.opensource.org/licenses/mit-license.html). */
/* See License.txt for more information.                                   */
/***************************************************************************/

// ResultsDlg.cpp : implementation file
//

#include "stdafx.h"
#include "LineCount.h"
#include "ResultsDlg.h"
#include "Config.h"
#include "Export.h"
#include "FileSummaryDlg.h"
#include "Options.h"
#include "AboutDialog.h"
#include "PrjStats.h"
#include "WorkspaceInfo.h"
#include "Help\HelpIDs.h"
#include "Utils.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

#define TOTAL_STR   _T("*** TOTAL ***")

struct ColumnInfo
{
    LPCTSTR     name;
    SORT_TYPE   sortType;
    SORT_STATE  sortState;
    int         lengthExtension;
    int         fmt;
};

static ColumnInfo columns[] =
{
    { _T("File Name"),  TYPE_TEXT,    DESCENDING, 40 },
    { _T("Extension"),  TYPE_TEXT,    DESCENDING, 10 },
    { _T("Path"),       TYPE_TEXT,    DESCENDING, 20 },
    { _T("Lines"),      TYPE_NUMERIC, DESCENDING, 15 },
    { _T("Code"),       TYPE_NUMERIC, DESCENDING, 5  },
    { _T("Comments"),   TYPE_NUMERIC, DESCENDING, 5  },
    { _T("Mixed"),      TYPE_NUMERIC, DESCENDING, 15 },
    { _T("Blank"),      TYPE_NUMERIC, DESCENDING, 15 }
};


/////////////////////////////////////////////////////////////////////////////
// CResultsDlg dialog


CResultsDlg::CResultsDlg(IWorkspaceInfo *pWI,
    CWnd* pParent /*=NULL*/) : CResizableDialog(CResultsDlg::IDD, pParent), 
    m_pWI(pWI)
{
    m_iHelpID = IDH_DLG_MAIN;
	//{{AFX_DATA_INIT(CResultsDlg)
	//}}AFX_DATA_INIT
}



void CResultsDlg::DoDataExchange(CDataExchange* pDX)
{
	CResizableDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CResultsDlg)
	DDX_Control(pDX, IDC_FILTER, m_Filter);
	DDX_Control(pDX, IDC_RESULTLIST, m_ListCtrl);
	//}}AFX_DATA_MAP
}


BEGIN_MESSAGE_MAP(CResultsDlg, CResizableDialog)
	//{{AFX_MSG_MAP(CResultsDlg)
	ON_COMMAND(IDC_EXPORT, OnExport)
	ON_COMMAND(IDC_OPTIONS, OnOptions)
	ON_COMMAND(IDC_ABOUT, OnAbout)
	ON_UPDATE_COMMAND_UI(IDC_FILESUMMARY, OnUpdateStatsCommand)
	ON_UPDATE_COMMAND_UI(IDC_EXPORT, OnUpdateStatsCommand)
	ON_CBN_SELCHANGE(IDC_FILTER, OnSelchangeFilter)
	ON_COMMAND(IDC_DOWNLOADS, OnDownloads)
	ON_COMMAND(IDC_HOMEPAGE, OnHomepage)
	ON_COMMAND(IDC_FILESUMMARY, OnFileSummary)
	//}}AFX_MSG_MAP
	ON_COMMAND_RANGE(ID_STATISTICS_FILTER1, ID_STATISTICS_FILTER99, OnStatisticsFilterProjects)
	ON_UPDATE_COMMAND_UI_RANGE(ID_STATISTICS_FILTER1, ID_STATISTICS_FILTER99, OnUpdateStatisticsFilterProjects)
	ON_WM_INITMENUPOPUP()
END_MESSAGE_MAP()

BEGIN_HELP_IDS(CResultsDlg)
    IDC_MENU_SEP,     0,

    IDC_NOPROJ_TEXT,  0,
    IDC_NOPROJ_NOTE,  0,
    IDC_NOPROJ_FRAME, 0,

    IDC_TXT_TOTAL,    0,
    IDC_TXT_C,        0,
    IDC_TXT_P,        0,

    IDC_TXT_FILTER,   IDC_FILTER,
                    
    IDC_TIP_ICON,     0,
    IDC_TIP_TEXT,     0,

    IDC_LINESC,       IDC_LINEST,
    IDC_LINESP,       IDC_LINEST,

    IDC_CODEC,        IDC_CODET,
    IDC_CODEP,        IDC_CODET,

    IDC_COMMENTSC,    IDC_COMMENTST,
    IDC_COMMENTSP,    IDC_COMMENTST,

    IDC_MIXEDC,       IDC_MIXEDT,
    IDC_MIXEDP,       IDC_MIXEDT,

    IDC_BLANKC,       IDC_BLANKT,
    IDC_BLANKP,       IDC_BLANKT,

    IDC_NETLINESC,    IDC_NETLINEST,
    IDC_NETLINESP,    IDC_NETLINEST
END_HELP_IDS()

/////////////////////////////////////////////////////////////////////////////
// CResultsDlg message handlers

BOOL CResultsDlg::OnInitDialog() 
{
	CResizableDialog::OnInitDialog();

    SetIcon(AfxGetApp()->LoadIcon(IDI_TITLE), FALSE);
    
    int         i;
    LVCOLUMN    lvc;

    m_ListCtrl.SendMessage(LVM_SETEXTENDEDLISTVIEWSTYLE, 0, (LPARAM) 
        LVS_EX_GRIDLINES | LVS_EX_HEADERDRAGDROP | LVS_EX_FULLROWSELECT |
        m_ListCtrl.SendMessage(LVM_GETEXTENDEDLISTVIEWSTYLE));

    lvc.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM;

    for(i = 0; i < countof(columns); i++)
    {
        lvc.iSubItem = i;
        lvc.pszText = (char *)columns[i].name;
        lvc.cx = m_ListCtrl.GetStringWidth(lvc.pszText) + 
            columns[i].lengthExtension + 15;
        if (lvc.cx < 40) lvc.cx = 40;
        lvc.fmt = columns[i].fmt;
        m_ListCtrl.InsertColumn(i, columns[i].sortType, columns[i].sortState, 
            &lvc);
    }

	m_ListCtrl.SortColumn( 2, false );
	m_ListCtrl.SortColumn( 1, true );
	m_ListCtrl.SortColumn( 0, true );

	m_ListCtrl.SetUniqueName( "ResultsListCtrl" );
	m_ListCtrl.LoadColumnWidths();
    m_ListCtrl.LoadColumnOrder();
    m_ListCtrl.LoadColumnSort();

	//resizable dlg
    AddAnchor(IDC_MENU_SEP, TOP_LEFT, TOP_RIGHT);

    AddAnchor(IDC_RESULTLIST, TOP_LEFT, BOTTOM_RIGHT);

    AddAnchor(IDC_NOPROJ_FRAME, TOP_LEFT,    BOTTOM_RIGHT);
    AddAnchor(IDC_NOPROJ_TEXT,  TOP_LEFT,    BOTTOM_RIGHT);
    AddAnchor(IDC_NOPROJ_NOTE,  BOTTOM_LEFT, BOTTOM_RIGHT);

    AddAnchor(IDC_TXT_TOTAL, BOTTOM_LEFT);
	AddAnchor(IDC_TXT_P, BOTTOM_LEFT);
	AddAnchor(IDC_TXT_C, BOTTOM_LEFT);
	
	AddAnchor(IDC_LINEST, BOTTOM_LEFT);
	AddAnchor(IDC_LINESC, BOTTOM_LEFT);
	AddAnchor(IDC_LINESP, BOTTOM_LEFT);
	
	AddAnchor(IDC_CODET, BOTTOM_LEFT);
	AddAnchor(IDC_CODEC, BOTTOM_LEFT);
	AddAnchor(IDC_CODEP, BOTTOM_LEFT);
	
	AddAnchor(IDC_COMMENTST, BOTTOM_LEFT);
	AddAnchor(IDC_COMMENTSC, BOTTOM_LEFT);
	AddAnchor(IDC_COMMENTSP, BOTTOM_LEFT);
	
	AddAnchor(IDC_MIXEDT, BOTTOM_LEFT);
	AddAnchor(IDC_MIXEDC, BOTTOM_LEFT);
	AddAnchor(IDC_MIXEDP, BOTTOM_LEFT);

	AddAnchor(IDC_BLANKT, BOTTOM_LEFT);
	AddAnchor(IDC_BLANKC, BOTTOM_LEFT);
	AddAnchor(IDC_BLANKP, BOTTOM_LEFT);
	
	AddAnchor(IDC_NETLINEST, BOTTOM_LEFT);
	AddAnchor(IDC_NETLINESC, BOTTOM_LEFT);
	AddAnchor(IDC_NETLINESP, BOTTOM_LEFT);
	
	AddAnchor(IDC_NETLINEST, BOTTOM_LEFT);
	AddAnchor(IDC_NETLINESC, BOTTOM_LEFT);
	AddAnchor(IDC_NETLINESP, BOTTOM_LEFT);
	
	AddAnchor(IDC_TXT_FILTER, BOTTOM_LEFT);
	AddAnchor(IDC_FILTER, BOTTOM_LEFT);
    AddAnchor(IDC_TIP_ICON, BOTTOM_LEFT);
    AddAnchor(IDC_TIP_TEXT, BOTTOM_LEFT);
    AddAnchor(IDOK, BOTTOM_RIGHT);

    EnableSaveRestore("ResultsDlg");

    InitStats();

    return TRUE;  
}

bool FindMenuItem(CMenu *pMenu, UINT nIDToFind, CMenu *& pOutMenu, int& iOutIndex)
{
    for (UINT i = 0; i < pMenu->GetMenuItemCount(); ++i)
    {
        UINT nID = pMenu->GetMenuItemID(i);
        if (nID == nIDToFind)
        {
            pOutMenu = pMenu;
            iOutIndex = i;
            return true;
        }
        if (nID == (unsigned)-1)
        {
            // submenu
            if (FindMenuItem(pMenu->GetSubMenu(i), nIDToFind, pOutMenu, iOutIndex))
            {
                return true;
            }
        }
    }
    pOutMenu = NULL;
    iOutIndex = -1;
    return false;
}

void CResultsDlg::InitStats()
{
	ASSERT(m_pWI != NULL);

    ::ResetStats();

	int i;

    m_iContext = 0;

    CMenu *pMenuStatsFilter;
    VERIFY(FindMenuItem(GetMenu(), ID_STATISTICS_FILTER1,
        pMenuStatsFilter, i));

	// delete all items except for first one (leave it temporarily so
	// sub menu is never empty)
    while (pMenuStatsFilter->GetMenuItemCount() > 1)
    {
        pMenuStatsFilter->DeleteMenu(
            pMenuStatsFilter->GetMenuItemCount() - 1, MF_BYPOSITION);
    }

    m_nWorkspaceFilters = m_pWI->GetWorkspaceFilterCount();
    ASSERT(m_nWorkspaceFilters > 0);
    for (i = 0; i < m_nWorkspaceFilters; ++i)
    {
        CString cStr;
        cStr = m_pWI->GetWorkspaceFilterName(i);
        cStr.Insert(0, '<');
        cStr += '>';

        AddFilter(cStr, ID_STATISTICS_FILTER1 + i);
    	pMenuStatsFilter->AppendMenu(MF_STRING, 
            ID_STATISTICS_FILTER1 + i, cStr);
    }
	pMenuStatsFilter->DeleteMenu(0, MF_BYPOSITION);

    m_pWI->Refresh();

    const int cProjects = m_pWI->GetProjectCount();
    if (cProjects == 0)
    {
        m_Filter.EnableWindow(FALSE);
        m_ListCtrl.ShowWindow(SW_HIDE);
        m_bHasProject = false;

        // this note only regards the Workspace Whiz! Interface & VC6
        if (RUNNING_IN_DOT_NET())
        {
            GetDlgItem(IDC_NOPROJ_NOTE)->ShowWindow(SW_HIDE);
        }
    }
    else
    {
        GetDlgItem(IDC_NOPROJ_FRAME)->ShowWindow(SW_HIDE);
        GetDlgItem(IDC_NOPROJ_TEXT)->ShowWindow(SW_HIDE);
        GetDlgItem(IDC_NOPROJ_NOTE)->ShowWindow(SW_HIDE);

        pMenuStatsFilter->AppendMenu(MF_SEPARATOR, 0, (LPCTSTR)0);
        for (i = 0; i < cProjects; ++i)
        {
            IWorkspaceProject *pPrj = m_pWI->GetProject(i);
            CString prjName = pPrj->GetName();
            delete pPrj;
            int p = prjName.ReverseFind('\\');
            if (p > 0) prjName = prjName.Mid(p + 1);
            CString strTemp = prjName;
            strTemp.MakeLower();
            if (strTemp.Find(".dsw") < 0)  // don't add .dsw files
            {
                int id = ID_STATISTICS_FILTER1 + i + m_nWorkspaceFilters;
                AddFilter(prjName, id);
                pMenuStatsFilter->AppendMenu(MF_STRING, id, prjName);
            }
        }
        m_bHasProject = true;
    }
    UpdateDialogControls(this, TRUE);
    RedrawWindow();

    // select last filter, or default
    int iFilter = 0;
    CString s;
    for (i = 0; i < m_Filter.GetCount(); ++i)
    {
        m_Filter.GetLBText(i, s);
        if (s.CompareNoCase(cfg_sLastFilter) == 0)
        {
            iFilter = i;
            break;
        }
        else
        {
            if ((int)(m_Filter.GetItemData(i) - ID_STATISTICS_FILTER1) == 
                cfg_iDefaultFilter)
            {
                iFilter = i;
            }
        }
    }
    if (iFilter > m_Filter.GetCount())
    {
        iFilter = 0;
    }
    SetFilter(iFilter);
}

void CResultsDlg::RefreshStats()
{
    if (!m_bHasProject) return;

    int files, total, code, mixed, com, blank;
    files = total = code = mixed = com = blank = 0;

    m_ListCtrl.SetRedraw(FALSE);
    m_ListCtrl.DeleteAllItems();
    ++m_iContext;

    // read the N/A string
    if (m_sNA.IsEmpty())
    {
        GetDlgItem(IDC_BLANKC)->GetWindowText(m_sNA);
    }
                        
    ProjectList projects;
    ProjectListFromFilter(m_iFilterIndex, projects);
    POSITION p = projects.GetHeadPosition();
    while (p)
    {
        IWorkspaceProject *pPrj = projects.GetNext(p);
        const int cFiles = pPrj->GetFileCount();
        IProjectFile *pFile = NULL;
        for (int f = 0; f < cFiles; ++f)
        {
            delete pFile;
            pFile = pPrj->GetFile(f);
            CFileInfo& fi = ::GetStats(pFile->GetPath());

            if (fi.m_stat == CFileInfo::filtered  &&  
                !CHK_FLAG(cfg_ShowFiltered, SF_GRID))
            {
                // not showing filtered files in the grid
                continue;
            }

            if (fi.m_stat != CFileInfo::full  &&  
                !CHK_FLAG(cfg_ShowBadFiles, SF_GRID))
            {
                // not showing bad files in the grid
                continue;
            }

            if (fi.m_iContext < m_iContext)
            {
                // this will prevent us from counting the same file twice
                fi.m_iContext = m_iContext;

                if (fi.m_stat == CFileInfo::full)
                {
                    total += fi.m_iTotalLines;
                    com   += fi.m_iLinesWithComments;
                    code  += fi.m_iLinesWithCode;
                    blank += fi.m_iBlankLines;
                    mixed += CalculateMixedLines(fi.m_iTotalLines,
                        fi.m_iLinesWithCode, fi.m_iLinesWithComments, 
                        fi.m_iBlankLines);
                }
                ++files;
                AddRow(fi);
            }
        }
        delete pFile;
    }

    CFileInfo fiTotal;
    fiTotal.m_sFileName          = TOTAL_STR;    
    fiTotal.m_iBlankLines        = blank;
    fiTotal.m_iLinesWithCode     = code;
    fiTotal.m_iLinesWithComments = com;
    fiTotal.m_iTotalLines        = total;
    fiTotal.m_stat               = CFileInfo::full;
    
	int nRowTotal = AddRow(fiTotal);

	if( -1 != nRowTotal )
	{
		//mark the line with the summary info
		m_ListCtrl.SetItemData(nRowTotal, DWORD(-1));
	}

    CString msg, s;
    s.Format("%d", files);
    AfxFormatString1(msg, IDS_FILECOUNT, s);
    SetWindowText(msg);

    if (!cfg_bProcessBlanks)
    {
        blank = -1;
    }
    if (!cfg_bProcessComments)
    {
        com = mixed = -1;
    }

    SetPair(IDC_LINESC,    IDC_LINESP,      total,          total);
    SetPair(IDC_CODEC,     IDC_CODEP,       code,           total);
    SetPair(IDC_NETLINESC, IDC_NETLINESP,   total - blank,  total);
    SetPair(IDC_BLANKC,    IDC_BLANKP,      blank,          total);
    SetPair(IDC_COMMENTSC, IDC_COMMENTSP,   com,            total);
    SetPair(IDC_MIXEDC,    IDC_MIXEDP,      mixed,          total);

    m_ListCtrl.SortCombinedColumns(true);

    m_ListCtrl.SetRedraw(TRUE);
    m_ListCtrl.RedrawWindow();
}

void CResultsDlg::AddFilter(const char *pszFilter, int data)
{
    int i = m_Filter.AddString(pszFilter);
    m_Filter.SetItemData(i, data);
}

int CResultsDlg::AddRow(const CFileInfo& fi)
{
	int nRes = -1;

    LV_ITEM lvi;

    lvi.mask = LVIF_TEXT | LVIF_PARAM;
    lvi.iItem = m_ListCtrl.GetItemCount();
    lvi.lParam = (LPARAM)&fi;

    lvi.iSubItem = 0;
    lvi.pszText = (LPTSTR)(LPCTSTR)fi.m_sFileName;
    nRes = m_ListCtrl.InsertItem(&lvi);

    int iSubItem = 0;
    m_ListCtrl.SetItemText(lvi.iItem, ++iSubItem, fi.m_sFileExt);
    m_ListCtrl.SetItemText(lvi.iItem, ++iSubItem, fi.m_sFilePath);
    m_ListCtrl.SetItemText(lvi.iItem, ++iSubItem, fi.GetTotalLinesStr());
    m_ListCtrl.SetItemText(lvi.iItem, ++iSubItem, fi.GetLinesWithCodeStr());
    m_ListCtrl.SetItemText(lvi.iItem, ++iSubItem, fi.GetLinesWithCommentsStr());
    m_ListCtrl.SetItemText(lvi.iItem, ++iSubItem, fi.GetMixedLinesStr());
    m_ListCtrl.SetItemText(lvi.iItem, ++iSubItem, fi.GetBlankLinesStr());

	return nRes;
}

void CResultsDlg::SetNum(int id, int num, TCHAR suffix)
{
    CString cStr = NumberWithCommas(num);
    if (suffix)
        cStr += suffix;
    GetDlgItem(id)->SetWindowText(cStr);
}

void CResultsDlg::SetPair(int idc, int idp, int count, int tot)
{
    if (count < 0)
    {
        GetDlgItem(idc)->SetWindowText(m_sNA);
        GetDlgItem(idp)->SetWindowText(m_sNA);
        return;
    }

    SetNum(idc, count);

    if (tot)
        SetNum(idp, (count * 100) / tot, '%');
    else
        SetNum(idp, 0, '%');
}

static const TCHAR *FILTERS =
        _T("Comma Separated Values (*.csv)|*.csv|")
        _T("XML Data (*.xml)|*.xml|")
        _T("|");
const int NUM_FILTERS = 2;

void CResultsDlg::OnExport() 
{
    if (cfg_iDefaultExportType <= 0  ||  cfg_iDefaultExportType > NUM_FILTERS)
    {
        cfg_iDefaultExportType = 1;
    }
    CFileDialog dlg(FALSE, "", NULL, 
        OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT, FILTERS);
    dlg.m_ofn.nFilterIndex = cfg_iDefaultExportType;
    if (dlg.DoModal() == IDOK  &&  !dlg.GetPathName().IsEmpty())
    {
        CWaitCursor wc;

        cfg_iDefaultExportType = dlg.m_ofn.nFilterIndex;

        bool bSuccess = false;
        ProjectList projects;
        ProjectListFromFilter(m_iFilterIndex, projects);
        if (dlg.m_ofn.nFilterIndex <= 1)
        {
            bSuccess = ExportAsCSV(dlg.GetPathName(), projects);
        }
        else
        {
            bSuccess = ExportAsXML(dlg.GetPathName(), projects,
                m_pWI->GetWorkspaceName());
        }

        wc.Restore();
        if (bSuccess)
        {
            AfxMessageBox(IDS_MSG_GOODEXPORT, MB_OK | MB_ICONINFORMATION);
        }
    }
}


void CResultsDlg::OnOptions() 
{
    COptionsSheet dlg;
    if (dlg.DoModal() == IDOK)
    {
        ::ResetStats();
        int iCurrFilter = m_iFilterIndex;
        m_iFilterIndex = -1;
        SetFilter(iCurrFilter);
    }
}

void CResultsDlg::OnAbout() 
{
    CAboutDialog dlg;
    dlg.DoModal();
}


// this code is based on CFrameWnd::OnInitMenuPopup
void CResultsDlg::OnInitMenuPopup(CMenu* pMenu, UINT nIndex, BOOL bSysMenu)
{
	if (bSysMenu)
		return;     // don't support system menu

	ASSERT(pMenu != NULL);
	// check the enabled state of various menu items

	CCmdUI state;
	state.m_pMenu = pMenu;
	ASSERT(state.m_pOther == NULL);
	ASSERT(state.m_pParentMenu == NULL);

	// determine if menu is popup in top-level menu and set m_pOther to
	//  it if so (m_pParentMenu == NULL indicates that it is secondary popup)
	HMENU hParentMenu;
	if (AfxGetThreadState()->m_hTrackingMenu == pMenu->m_hMenu)
		state.m_pParentMenu = pMenu;    // parent == child for tracking popup
	else if ((hParentMenu = ::GetMenu(m_hWnd)) != NULL)
	{
		CWnd* pParent = GetTopLevelParent();
			// child windows don't have menus -- need to go to the top!
		if (pParent != NULL &&
			(hParentMenu = ::GetMenu(pParent->m_hWnd)) != NULL)
		{
			int nIndexMax = ::GetMenuItemCount(hParentMenu);
			for (int nIndex = 0; nIndex < nIndexMax; nIndex++)
			{
				if (::GetSubMenu(hParentMenu, nIndex) == pMenu->m_hMenu)
				{
					// when popup is found, m_pParentMenu is containing menu
					state.m_pParentMenu = CMenu::FromHandle(hParentMenu);
					break;
				}
			}
		}
	}

	state.m_nIndexMax = pMenu->GetMenuItemCount();
	for (state.m_nIndex = 0; state.m_nIndex < state.m_nIndexMax;
	  state.m_nIndex++)
	{
		state.m_nID = pMenu->GetMenuItemID(state.m_nIndex);
		if (state.m_nID == 0)
			continue; // menu separator or invalid cmd - ignore it

		ASSERT(state.m_pOther == NULL);
		ASSERT(state.m_pMenu != NULL);
		if (state.m_nID == (UINT)-1)
		{
			// possibly a popup menu, route to first item of that popup
			state.m_pSubMenu = pMenu->GetSubMenu(state.m_nIndex);
			if (state.m_pSubMenu == NULL ||
				(state.m_nID = state.m_pSubMenu->GetMenuItemID(0)) == 0 ||
				state.m_nID == (UINT)-1)
			{
				continue;       // first item of popup can't be routed to
			}
			state.DoUpdate(this, FALSE);    // popups are never auto disabled
		}
		else
		{
			// normal menu item
			// Auto enable/disable if frame window has 'm_bAutoMenuEnable'
			//    set and command is _not_ a system command.
			state.m_pSubMenu = NULL;
			state.DoUpdate(this, state.m_nID < 0xF000);
		}

		// adjust for menu deletions and additions
		UINT nCount = pMenu->GetMenuItemCount();
		if (nCount < state.m_nIndexMax)
		{
			state.m_nIndex -= (state.m_nIndexMax - nCount);
			while (state.m_nIndex < nCount &&
				pMenu->GetMenuItemID(state.m_nIndex) == state.m_nID)
			{
				state.m_nIndex++;
			}
		}
		state.m_nIndexMax = nCount;
	}
}

void CResultsDlg::OnUpdateStatisticsFilterProjects(CCmdUI* pCmdUI) 
{
    pCmdUI->Enable(m_bHasProject);
    pCmdUI->SetCheck(m_Filter.GetItemData(m_Filter.GetCurSel()) == 
        (DWORD)(pCmdUI->m_nID));
}

void CResultsDlg::ProjectListFromFilter(int iFilterIndex, ProjectList& projects)
{
    iFilterIndex = m_Filter.GetItemData(iFilterIndex) - ID_STATISTICS_FILTER1;
    if (iFilterIndex < m_nWorkspaceFilters)
    {
        const int cFilters = 
            m_pWI->GetWorkspaceFilterProjectCount(iFilterIndex);
        for (int i = 0; i < cFilters; ++i)
        {
            IWorkspaceProject *pPrj = 
                m_pWI->GetWorkspaceFilterProject(iFilterIndex, i);
            ASSERT(pPrj);
            if (pPrj)
            {
                projects.AddTail(pPrj);
            }
        }
    }
    else
    {
        const int iPrj = iFilterIndex - m_nWorkspaceFilters;
        ASSERT(m_pWI->GetProjectCount() > iPrj);
        IWorkspaceProject *pPrj = m_pWI->GetProject(iPrj);
        if (pPrj)
        {
            projects.AddTail(pPrj);
        }
    }
}


void CResultsDlg::SetFilter(int iIndex)
{
    ASSERT(iIndex >= 0  &&  iIndex < m_Filter.GetCount());

    if (iIndex == m_iFilterIndex  &&  m_ListCtrl.GetItemCount() > 0)
    {
        return;
    }

    CWnd *pFocusedWnd = GetFocus();

    m_Filter.SetCurSel(iIndex);

    // update the stats based on the new filter
    if (m_bHasProject)
    {
        ProjectList projects;
        ProjectListFromFilter(iIndex, projects);
        if (::UpdateStats(m_pWI, projects))
        {
            m_iFilterIndex = iIndex;
            RefreshStats();

            m_Filter.GetWindowText(cfg_sLastFilter);
        }
    }

    if (m_iFilterIndex >= 0)
    {
        // this is necessary if user cancels the file scan:
        m_Filter.SetCurSel(m_iFilterIndex);  // reset to old index
    }

    if (pFocusedWnd)
    {
        pFocusedWnd->SetFocus();
    }
}

void CResultsDlg::OnStatisticsFilterProjects(UINT iCmd) 
{
    // combo box is sorted - find actual index for this command
    for (int i = 0; i < m_Filter.GetCount(); ++i)
    {
        if (m_Filter.GetItemData(i) == (DWORD)iCmd)
        {
            SetFilter(i);
            return;
        }
    }
}

void CResultsDlg::OnSelchangeFilter() 
{
    int iCmd = m_Filter.GetItemData(m_Filter.GetCurSel());
    PostMessage(WM_COMMAND, iCmd, 0);
}

void CResultsDlg::OnDownloads() 
{
    CHyperLink::GotoURL("http://www.wndtabs.com/downloads/", SW_SHOW);
}

void CResultsDlg::OnHomepage() 
{
    CHyperLink::GotoURL("http://www.wndtabs.com/plc/", SW_SHOW);
}

void CResultsDlg::OnFileSummary() 
{
    ProjectList projects;
    ProjectListFromFilter(m_iFilterIndex, projects);
    CFileSummaryDlg dlg(projects);
    dlg.DoModal();
}

void CResultsDlg::OnUpdateStatsCommand(CCmdUI* pCmdUI) 
{
    pCmdUI->Enable(m_bHasProject);
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Experion
Canada Canada
You may know Oz from his WndTabs days. Oz has long since left client side development to work on web technologies and to consult in the R&D management field.

Comments and Discussions