/***************************************************************************/
/* NOTE: */
/* This document is copyright (c) by Oz Solomonovich. All non-commercial */
/* use is allowed, as long as this document is not altered in any way, and */
/* due credit is given. */
/***************************************************************************/
// ResultsDlg.cpp : implementation file
//
#include "stdafx.h"
#include "LineCount.h"
#include "Parser.h"
#include "ResultsDlg.h"
#include "Config.h"
#include "Export.h"
#include "FileSummaryDlg.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
#define TOTAL_STR _T("*** TOTAL ***")
/////////////////////////////////////////////////////////////////////////////
// CResultsDlg dialog
CResultsDlg::CResultsDlg(proj_stats *pStats, WWhizInterface *pWWI,
CWnd* pParent /*=NULL*/) : CHHDialog(CResultsDlg::IDD, pParent),
m_pStats(pStats), m_pfi(pStats->pfi), m_pWWI(pWWI)
{
//{{AFX_DATA_INIT(CResultsDlg)
// NOTE: the ClassWizard will add member initialization here
//}}AFX_DATA_INIT
}
void CResultsDlg::DoDataExchange(CDataExchange* pDX)
{
CHHDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CResultsDlg)
DDX_Control(pDX, IDC_RESULTLIST, m_ListCtrl);
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CResultsDlg, CHHDialog)
//{{AFX_MSG_MAP(CResultsDlg)
ON_NOTIFY(LVN_COLUMNCLICK, IDC_RESULTLIST, OnColumnclickResultlist)
ON_BN_CLICKED(IDC_EXPORT, OnExport)
ON_BN_CLICKED(IDC_FILESUMMARY, OnFilesummary)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CResultsDlg message handlers
BOOL CResultsDlg::OnInitDialog()
{
CHHDialog::OnInitDialog();
int i;
LPCTSTR sColumns[] = {_T("File Name"), _T("Path"), _T("Lines"),
_T("Code Only"), _T("Comments Only"),
_T("Mixed"), _T("Blank")};
int lColumns[] = {50, 10, 25, 5, 5, 15, 15};
LVCOLUMN lvc;
#define NUM_COL_COMMENTS 4
#define NUM_COL_MIXED 5
#define NUM_COL_BLANK 6
m_ListCtrl.SendMessage(LVM_SETEXTENDEDLISTVIEWSTYLE, 0,
(LPARAM) LVS_EX_GRIDLINES | LVS_EX_HEADERDRAGDROP |
m_ListCtrl.SendMessage(LVM_GETEXTENDEDLISTVIEWSTYLE));
lvc.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM;
for(i = 0; i < countof(sColumns); i++)
{
lvc.iSubItem = i;
lvc.pszText = (char *)sColumns[i];
lvc.cx = m_ListCtrl.GetStringWidth(lvc.pszText) + lColumns[i] + 15;
if (lvc.cx < 40) lvc.cx = 40;
lvc.fmt = (i >= 2)? LVCFMT_RIGHT : LVCFMT_LEFT;
m_ListCtrl.InsertColumn(i, &lvc);
}
file_info *p = m_pfi;
int files, total, code, mixed, com, blank;
files = total = code = mixed = com = blank = 0;
while (!p->sName.IsEmpty())
{
total += p->lines;
com += p->commentlines;
mixed += p->mixedlines;
code += p->codelines;
blank += p->blanklines;
files++;
AddRow(*p);
p++;
}
p->sName = TOTAL_STR;
p->sPath = "";
p->lines = total;
p->commentlines = com;
p->codelines = code;
p->mixedlines = mixed;
p->blanklines = blank;
AddRow(*p);
CString msg, s;
s.Format("%d", files);
AfxFormatString1(msg, IDS_FILECOUNT, s);
GetDlgItem(IDC_FILECOUNT)->SetWindowText(msg);
SetPair(IDC_LINESC, IDC_LINESP, total, total);
SetPair(IDC_CODEC, IDC_CODEP, code, total);
SetPair(IDC_NETLINESC, IDC_NETLINESP, total - blank, total);
SetPair(IDC_NETCODEC, IDC_NETCODEP, code + mixed, total);
if (cfg_bProcessBlanks)
{
SetPair(IDC_BLANKC, IDC_BLANKP, blank, total);
}
if (cfg_bProcessCPPComments)
{
SetPair(IDC_COMMENTSC, IDC_COMMENTSP, com, total);
SetPair(IDC_MIXEDC, IDC_MIXEDP, mixed, total);
}
m_iLastSort = 2;
m_ListCtrl.SortItems(CompareFunc, (DWORD)m_iLastSort);
return TRUE;
}
void CResultsDlg::AddRow(file_info& fi)
{
LV_ITEM lvi;
CString cStr;
lvi.mask = LVIF_TEXT | LVIF_PARAM;
lvi.iItem = m_ListCtrl.GetItemCount();
lvi.lParam = (LPARAM)&fi;
lvi.iSubItem = 0;
lvi.pszText = (LPTSTR)(LPCTSTR)fi.sName;
m_ListCtrl.InsertItem(&lvi);
m_ListCtrl.SetItemText(lvi.iItem, 1, fi.sPath);
m_ListCtrl.SetItemText(lvi.iItem, 2, NumStr(fi.lines));
m_ListCtrl.SetItemText(lvi.iItem, 3, NumStr(fi.codelines));
cStr = cfg_bProcessBlanks? NumStr(fi.blanklines) : "n/a";
m_ListCtrl.SetItemText(lvi.iItem, 6, cStr);
if (!cfg_bProcessCPPComments)
cStr = "n/a";
if (cfg_bProcessCPPComments) cStr = NumStr(fi.commentlines);
m_ListCtrl.SetItemText(lvi.iItem, 4, cStr);
if (cfg_bProcessCPPComments) cStr = NumStr(fi.mixedlines);
m_ListCtrl.SetItemText(lvi.iItem, 5, cStr);
}
void CResultsDlg::OnColumnclickResultlist(NMHDR* pNMHDR, LRESULT* pResult)
{
NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
int col = pNMListView->iSubItem;
if (!cfg_bProcessCPPComments &&
(col == NUM_COL_MIXED || col == NUM_COL_COMMENTS))
return;
if (!cfg_bProcessBlanks && col == NUM_COL_BLANK)
return;
if (abs(m_iLastSort) == (pNMListView->iSubItem + 1))
{
m_iLastSort = -m_iLastSort;
}
else
{
m_iLastSort = (pNMListView->iSubItem + 1);
}
m_ListCtrl.SortItems(CompareFunc, (DWORD)m_iLastSort);
*pResult = 0;
}
int CALLBACK CResultsDlg::CompareFunc(LPARAM lParam1, LPARAM lParam2,
LPARAM lParamSort)
{
file_info* fi1 = (file_info *)(lParam1);
file_info* fi2 = (file_info *)(lParam2);
int iResult;
if (fi1 && fi2)
{
if (lstrcmp(fi1->sName, TOTAL_STR) == 0)
{
iResult = 1;
}
else
{
if (lstrcmp(fi2->sName, TOTAL_STR) == 0)
{
iResult = -1;
}
else
{
again:
switch (abs(lParamSort))
{
case 1: // sort by name
iResult = lstrcmpi(fi1->sName, fi2->sName);
if (iResult == 0)
{
lParamSort = 2; // subsort: path
goto again;
}
break;
case 2: // sort by path
iResult = lstrcmpi(fi1->sPath, fi2->sPath);
goto namesubsort;
case 3: // sory by line count
iResult = fi1->lines - fi2->lines;
goto namesubsort;
case 4: // sory by "code only" count
iResult = fi1->codelines - fi2->codelines;
goto namesubsort;
case 5: // sory by "comments only" count
iResult = fi1->commentlines - fi2->commentlines;
goto namesubsort;
case 6: // sory by "mixed lines" count
iResult = fi1->mixedlines - fi2->mixedlines;
goto namesubsort;
case 7: // sory by blank line count
iResult = fi1->blanklines - fi2->blanklines;
namesubsort:
if (iResult == 0)
{
lParamSort = 1; // subsort: name
goto again;
}
break;
default:
iResult = 0;
break;
}
if (lParamSort < 0)
iResult = -iResult;
}
}
}
else
{
iResult = 0;
}
return (iResult);
}
CString CResultsDlg::NumStr(int num)
{
CString cStr;
int pos;
cStr.Format("%d", num);
pos = cStr.GetLength() - 1;
while (pos >= 3)
{
cStr = cStr.Left(pos - 2) + "," + cStr.Mid(pos - 2);
pos -= 3;
}
return cStr;
}
void CResultsDlg::SetNum(int id, int num, TCHAR suffix)
{
CString cStr = NumStr(num);
if (suffix)
cStr += suffix;
GetDlgItem(id)->SetWindowText(cStr);
}
void CResultsDlg::SetPair(int idc, int idp, int count, int tot)
{
SetNum(idc, count);
if (tot)
SetNum(idp, (count * 100) / tot, '%');
else
SetNum(idp, 0);
}
void CResultsDlg::OnExport()
{
CFileDialog dlg(FALSE, NULL, NULL, OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT,
_T("All Files (*.*)|(*.*)||"));
if (dlg.DoModal() == IDOK && !dlg.GetFileName().IsEmpty())
{
ExportData(dlg.GetFileName(), m_pStats, m_pWWI);
}
}
void CResultsDlg::OnFilesummary()
{
CFileSummaryDlg dlg(m_pStats);
dlg.DoModal();
}