// LineCounterBrowser is from the CodeProject article // "Line Counter - Writing a Visual Studio 2005 Add-In" by Jon Rista // http://www.codeproject.com/useritems/LineCounterAddin.asp using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Diagnostics; using System.Drawing; using System.IO; using System.Text; using System.Windows.Forms; using ICSharpCode.Core; using ICSharpCode.SharpDevelop.Project; using ICSharpCode.SharpDevelop; namespace LineCounterAddin { /// /// Line Counter add-in user interface. /// public partial class LineCounterBrowser : UserControl { #region Nested Classes abstract class ListViewItemComparer : System.Collections.IComparer { public abstract int Compare(ListViewItem item1, ListViewItem item2); public ListView SortingList; public int Column; #region IComparer Members int System.Collections.IComparer.Compare(object x, object y) { if (x is ListViewItem && y is ListViewItem) { int diff = Compare((ListViewItem)x, (ListViewItem)y); if (SortingList.Sorting == SortOrder.Descending) diff *= -1; return diff; } else { throw new ArgumentException("One or both of the arguments are not ListViewItem objects."); } } #endregion } /// /// Compares items based on file name. /// class FileNameComparer : ListViewItemComparer { public override int Compare(ListViewItem item1, ListViewItem item2) { return String.Compare(item1.Text, item2.Text, false); } } /// /// Compares items based on total lines primarily, and /// the filename secondarily. /// class FileLinesComparer : ListViewItemComparer { public override int Compare(ListViewItem item1, ListViewItem item2) { string string1 = item1.SubItems[Column].Text; string string2 = item2.SubItems[Column].Text; if (string1 != null && string2 != null) { int total1 = int.Parse(string1); int total2 = int.Parse(string2); // Compare the totals... int diff = total1 - total2; // If totals are equal... if (diff == 0) { // Compare the filenames diff = String.Compare(item1.Text, item2.Text, false); } return diff; } return 0; } } /// /// Compares items based on file extension. /// class FileExtensionComparer : ListViewItemComparer { public override int Compare(ListViewItem item1, ListViewItem item2) { string string1 = item1.SubItems[4].Text; string string2 = item2.SubItems[4].Text; return String.Compare(string1, string2, true); } } #endregion #region Constructor /// /// Construct the line counter user interface and /// the countable file type mappings (to icons and /// counting algorithms). /// public LineCounterBrowser() { InitializeComponent(); #if IMPR1 projectImageListHelper = new ImageListHelper(imgProjectTypes); fileImageListHelper = new ImageListHelper(imgFileTypes); #endif // Map project types to icons for use in the projects list m_projIconMappings = new Dictionary(); m_projIconMappings.Add("{00000000-0000-0000-0000-000000000000}", 0); m_projIconMappings.Add("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}", 1); // C# m_projIconMappings.Add("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}", 2); // VB m_projIconMappings.Add("{00000001-0000-0000-0000-000000000000}", 5); // List all the countable file types (so we don't try to count .dll's, // images, executables, etc. m_countableTypes = new System.Collections.Specialized.StringCollection(); #if IMPR2 countingAlgorithms = AddInTree.BuildItems ("/AddIns/LineCounter/CountingAlgorithms", this); // Iterate through algorithms to fill list of known countable types foreach (CountingAlgorithmDescriptor desc in countingAlgorithms) { m_countableTypes.AddRange(desc.extensions); } #else m_countableTypes.Add("*"); m_countableTypes.Add(".cs"); m_countableTypes.Add(".vb"); m_countableTypes.Add(".vj"); m_countableTypes.Add(".cpp"); m_countableTypes.Add(".cc"); m_countableTypes.Add(".cxx"); m_countableTypes.Add(".c"); m_countableTypes.Add(".hpp"); m_countableTypes.Add(".hh"); m_countableTypes.Add(".hxx"); m_countableTypes.Add(".h"); m_countableTypes.Add(".js"); m_countableTypes.Add(".cd"); m_countableTypes.Add(".resx"); m_countableTypes.Add(".res"); m_countableTypes.Add(".css"); m_countableTypes.Add(".htm"); m_countableTypes.Add(".html"); m_countableTypes.Add(".xml"); m_countableTypes.Add(".xsl"); m_countableTypes.Add(".xslt"); m_countableTypes.Add(".xsd"); m_countableTypes.Add(".config"); m_countableTypes.Add(".asax"); m_countableTypes.Add(".ascx"); m_countableTypes.Add(".asmx"); m_countableTypes.Add(".aspx"); m_countableTypes.Add(".ashx"); m_countableTypes.Add(".idl"); m_countableTypes.Add(".odl"); m_countableTypes.Add(".txt"); m_countableTypes.Add(".sql"); #endif // Map file extensions to icons for use in the file list m_fileIconMappings = new Dictionary(33); m_fileIconMappings.Add("*", 0); m_fileIconMappings.Add(".cs", 1); m_fileIconMappings.Add(".vb", 2); m_fileIconMappings.Add(".vj", 3); m_fileIconMappings.Add(".cpp", 4); m_fileIconMappings.Add(".cc", 4); m_fileIconMappings.Add(".cxx", 4); m_fileIconMappings.Add(".c", 5); m_fileIconMappings.Add(".hpp", 6); m_fileIconMappings.Add(".hh", 6); m_fileIconMappings.Add(".hxx", 6); m_fileIconMappings.Add(".h", 6); m_fileIconMappings.Add(".js", 7); m_fileIconMappings.Add(".cd", 8); m_fileIconMappings.Add(".resx", 9); m_fileIconMappings.Add(".res", 9); m_fileIconMappings.Add(".css", 10); m_fileIconMappings.Add(".htm", 11); m_fileIconMappings.Add(".html", 11); m_fileIconMappings.Add(".xml", 12); m_fileIconMappings.Add(".xsl", 13); m_fileIconMappings.Add(".xslt", 13); m_fileIconMappings.Add(".xsd", 14); m_fileIconMappings.Add(".config", 15); m_fileIconMappings.Add(".asax", 16); m_fileIconMappings.Add(".ascx", 17); m_fileIconMappings.Add(".asmx", 18); m_fileIconMappings.Add(".aspx", 19); m_fileIconMappings.Add(".ashx", 0); m_fileIconMappings.Add(".idl", 0); m_fileIconMappings.Add(".odl", 0); m_fileIconMappings.Add(".txt", 0); m_fileIconMappings.Add(".sql", 0); // Prepare counting algorithm mappings CountLines countLinesGeneric = new CountLines(CountLinesGeneric); CountLines countLinesCStyle = new CountLines(CountLinesCStyle); CountLines countLinesVBStyle = new CountLines(CountLinesVBStyle); CountLines countLinesXMLStyle = new CountLines(CountLinesXMLStyle); m_countAlgorithms = new Dictionary(33); m_countAlgorithms.Add("*", countLinesGeneric); m_countAlgorithms.Add(".cs", countLinesCStyle); m_countAlgorithms.Add(".vb", countLinesVBStyle); m_countAlgorithms.Add(".vj", countLinesCStyle); m_countAlgorithms.Add(".js", countLinesCStyle); m_countAlgorithms.Add(".cpp", countLinesCStyle); m_countAlgorithms.Add(".cc", countLinesCStyle); m_countAlgorithms.Add(".cxx", countLinesCStyle); m_countAlgorithms.Add(".c", countLinesCStyle); m_countAlgorithms.Add(".hpp", countLinesCStyle); m_countAlgorithms.Add(".hh", countLinesCStyle); m_countAlgorithms.Add(".hxx", countLinesCStyle); m_countAlgorithms.Add(".h", countLinesCStyle); m_countAlgorithms.Add(".idl", countLinesCStyle); m_countAlgorithms.Add(".odl", countLinesCStyle); m_countAlgorithms.Add(".txt", countLinesGeneric); m_countAlgorithms.Add(".xml", countLinesXMLStyle); m_countAlgorithms.Add(".xsl", countLinesXMLStyle); m_countAlgorithms.Add(".xslt", countLinesXMLStyle); m_countAlgorithms.Add(".xsd", countLinesXMLStyle); m_countAlgorithms.Add(".config", countLinesXMLStyle); m_countAlgorithms.Add(".res", countLinesGeneric); m_countAlgorithms.Add(".resx", countLinesXMLStyle); m_countAlgorithms.Add(".aspx", countLinesXMLStyle); m_countAlgorithms.Add(".ascx", countLinesXMLStyle); m_countAlgorithms.Add(".ashx", countLinesXMLStyle); m_countAlgorithms.Add(".asmx", countLinesXMLStyle); m_countAlgorithms.Add(".asax", countLinesXMLStyle); m_countAlgorithms.Add(".htm", countLinesXMLStyle); m_countAlgorithms.Add(".html", countLinesXMLStyle); m_countAlgorithms.Add(".css", countLinesCStyle); m_countAlgorithms.Add(".sql", countLinesGeneric); m_countAlgorithms.Add(".cd", countLinesGeneric); } #endregion #region Variables private List m_summaryList; private Dictionary m_projIconMappings; private Dictionary m_fileIconMappings; private Dictionary m_countAlgorithms; private System.Collections.Specialized.StringCollection m_countableTypes; #if IMPR1 ImageListHelper fileImageListHelper; ImageListHelper projectImageListHelper; #endif #if IMPR2 List countingAlgorithms; #endif #endregion #region Handlers private int lastSortColumn = -1; // Track the last clicked column /// /// Sorts the ListView by the clicked column, automatically /// reversing the sort order on subsequent clicks of the /// same column. /// /// /// Provides the index of the clicked column. private void lvFileList_ColumnClick(object sender, ColumnClickEventArgs e) { // Define a variable of the abstract (generic) comparer ListViewItemComparer comparer = null; // Create an instance of the specific comparer in the 'comparer' // variable. Since each of the explicit comparer classes is // derived from the abstract case class, polymorphism applies. switch (e.Column) { // Line count columns case 1: case 2: case 3: comparer = new FileLinesComparer(); break; // The file extension column case 4: comparer = new FileExtensionComparer(); break; // All other columns sort by file name default: comparer = new FileNameComparer(); break; } // Set the sorting order if (lastSortColumn == e.Column) { if (lvFileList.Sorting == SortOrder.Ascending) { lvFileList.Sorting = SortOrder.Descending; } else { lvFileList.Sorting = SortOrder.Ascending; } } else { lvFileList.Sorting = SortOrder.Ascending; } lastSortColumn = e.Column; // Send the comparer the list view and column being sorted comparer.SortingList = lvFileList; comparer.Column = e.Column; // Attach the comparer to the list view and sort lvFileList.ListViewItemSorter = comparer; lvFileList.Sort(); } /// /// Sets the file listing mode to No Grouping, /// and recounts. /// /// /// /// FIX THIS: Add a helper to simply repopulate /// the list view with existing count data if it exists!!! private void tsmiNoGrouping_Click(object sender, EventArgs e) { tsmiGroupByProj.Checked = false; tsmiGroupByType.Checked = false; SumSolution(); } /// /// Sets the file listing mode to Group by Project, /// and recounts. /// /// /// /// FIX THIS: Add a helper to simply repopulate /// the list view with existing count data if it exists!!! private void tsmiGroupByProj_Click(object sender, EventArgs e) { tsmiGroupByType.Checked = false; tsmiNoGrouping.Checked = false; SumSolution(); } /// /// Sets the file listing mode to Group by Type, /// and recounts. /// /// /// /// FIX THIS: Add a helper to simply repopulate /// the list view with existing count data if it exists!!! private void tsmiGroupByType_Click(object sender, EventArgs e) { tsmiGroupByProj.Checked = false; tsmiNoGrouping.Checked = false; SumSolution(); } /// /// Forces a recount of all files in all projects, and /// updates the view. /// /// /// private void tsmiRecalculate_FileList_Click(object sender, EventArgs e) { ScanSolution(); SumSolution(); } #endregion #region Helpers #region Line Counting Methods /// /// Count each line in a text file, logging /// blank lines. /// /// The file information data to use. internal static void CountLinesGeneric(LineCountInfo info) { StreamReader sr = new StreamReader(info.FileName); string line; while ((line = sr.ReadLine()) != null) { info.LineCountInfoDetails.Add("TotalLines", 1); if (line.Trim() == string.Empty) { info.LineCountInfoDetails.Add("BlankLines", 1); } info.SumMode = "Generic"; } sr.Close(); } /// /// Count each line in a c-style source file, scanning /// for single and multi-line comments, code, and blank lines. /// /// The file information data to use. /// This algorithm was originally created by Oz Solomon, /// for his PLC line counter add-in for Visual Studio 2002/2003. internal static void CountLinesCStyle(LineCountInfo info) { try { StreamReader reader = new StreamReader(info.FileName); string line; bool multiLineComment = false; bool hasCode = false; bool hasComments = false; while ((line = reader.ReadLine()) != null) { ParseCLine(line, ref multiLineComment, ref hasCode, ref hasComments); if (hasComments) { info.LineCountInfoDetails.Add("normcmtlines", 1); } if (hasCode) { info.LineCountInfoDetails.Add("codelines", 1); } if (!hasCode && !hasComments) { info.LineCountInfoDetails.Add("blanklines", 1); } info.LineCountInfoDetails.Add("totallines", 1); } reader.Close(); info.SumMode = "C-Style"; } catch { } } /// /// Count each line in a vb-style source file, scanning /// for comments, code, and blank lines. /// /// The file information data to use. /// This algorithm was originally created by Oz Solomon, /// for his PLC line counter add-in for Visual Studio 2002/2003. internal static void CountLinesVBStyle(LineCountInfo info) { try { StreamReader reader = new StreamReader(info.FileName); string line; bool multiLineComment = false; bool hasCode = false; bool hasComments = false; while ((line = reader.ReadLine()) != null) { ParseVBLine(line, ref multiLineComment, ref hasCode, ref hasComments); if (hasComments) { info.LineCountInfoDetails.Add("normcmtlines", 1); } if (hasCode) { info.LineCountInfoDetails.Add("codelines", 1); } if (!hasCode && !hasComments) { info.LineCountInfoDetails.Add("blanklines", 1); } info.LineCountInfoDetails.Add("totallines", 1); } reader.Close(); info.SumMode = "Visual Basic"; } catch { } } /// /// Count each line in an xml source file, scanning /// for comments, code, and blank lines. /// /// The file information data to use. /// This algorithm is based on one created by Oz Solomon, /// for his PLC line counter add-in for Visual Studio 2002/2003. internal static void CountLinesXMLStyle(LineCountInfo info) { try { StreamReader reader = new StreamReader(info.FileName); string line; bool multiLineComment = false; bool hasCode = false; bool hasComments = false; while ((line = reader.ReadLine()) != null) { ParseXMLLine(line, ref multiLineComment, ref hasCode, ref hasComments); if (hasComments) { info.LineCountInfoDetails.Add("normcmtlines", 1); } if (hasCode) { info.LineCountInfoDetails.Add("codelines", 1); } if (!hasCode && !hasComments) { info.LineCountInfoDetails.Add("blanklines", 1); } info.LineCountInfoDetails.Add("totallines", 1); } reader.Close(); info.SumMode = "XML"; } catch { } } /// /// Determines if the two input characters ch and chNext /// match the given pair of characters a and b. /// /// First char requirement. /// Second char requirement. /// First char to test. /// Second char to test. /// private static bool IsPair(char a, char b, char ch, char chNext) { return (ch == a && chNext == b); } /// /// Parses a c-style code line for comments, code, and blanks. /// /// /// /// /// /// This algorithm was originally created by Oz Solomon, /// for his PLC line counter add-in for Visual Studio 2002/2003. private static void ParseCLine(string line, ref bool multiLineComment, ref bool hasCode, ref bool hasComments) { bool inString = false; bool inTwoPairSequence = false; hasComments = multiLineComment; hasCode = false; for (int i = 0; i < line.Length; i++) { char ch = line[i]; char chNext = (i < line.Length - 1 ? line[i + 1] : '\0'); // Process a single-line comment if (IsPair('/', '/', ch, chNext) && !multiLineComment && !inString) { hasComments = true; return; } // Process start of a multiline comment else if (IsPair('/', '*', ch, chNext) && !multiLineComment && !inString) { multiLineComment = true; hasComments = true; ++i; } // Process end of a multiline comment else if (IsPair('*', '/', ch, chNext) && !inString) { multiLineComment = false; ++i; } // Process escaped character else if (ch == '\\' && !multiLineComment) { ++i; hasCode = true; } // Process string else if (ch == '"' && !multiLineComment) { inString = !inString; hasCode = true; } else if (!multiLineComment) { if (!Char.IsWhiteSpace(ch)) { hasCode = true; } } } } /// /// Parses a vb-style code line for comments, code and blanks. /// /// /// /// /// /// This algorithm was originally created by Oz Solomon, /// for his PLC line counter add-in for Visual Studio 2002/2003. private static void ParseVBLine(string line, ref bool multiLineComment, ref bool hasCode, ref bool hasComments) { bool inString = false; bool inTwoPairSequence = false; multiLineComment = false; line = line.Trim(); if (line.Length == 0) { hasCode = false; hasComments = false; return; } if (line[0] == '\'') { hasCode = false; hasComments = true; return; } if (line.IndexOf('\'') != -1) { hasCode = true; hasComments = true; return; } hasCode = true; hasComments = true; } /// /// Parses an xml-style code line for comments, markup, and blanks. /// /// /// /// /// /// This algorithm is based on one created by Oz Solomon, /// for his PLC line counter add-in for Visual Studio 2002/2003. private static void ParseXMLLine(string line, ref bool multiLineComment, ref bool hasCode, ref bool hasComments) { bool inString = false; bool inTwoPairSequence = false; hasComments = multiLineComment; hasCode = false; for (int i = 0; i < line.Length; i++) { char ch1 = line[i]; char ch2 = (i < line.Length-1 ? line[i + 1] : '\0'); char ch3 = (i+1 < line.Length-1 ? line[i + 2] : '\0'); char ch4 = (i+2 < line.Length-1 ? line[i + 3] : '\0'); // Process start of XML comment if (IsPair('<', '!', ch1, ch2) && IsPair('-', '-', ch3, ch4) && !multiLineComment && !inString) { multiLineComment = true; hasComments = true; i += 3; } // Process end of XML comment else if (IsPair('-', '-', ch1, ch2) && ch3 == '>' && !inString) { multiLineComment = false; i += 2; } // Process string else if (ch3 == '"' && !multiLineComment) { inString = !inString; hasCode = true; } else if (!multiLineComment) { if (!Char.IsWhiteSpace(ch1)) { hasCode = true; } } } } #endregion #region Scanning and Summation Methods /// /// Scans the solution and creates a hierarchy of /// support objects for each project and file /// within each project. /// private void ScanSolution() { if (m_summaryList == null) m_summaryList = new List(); m_summaryList.Clear(); Solution solution = ProjectService.OpenSolution; if (solution != null) // OpenSolution is null when no solution is opened { FileInfo fiSolution = new FileInfo(solution.FileName); LineCountSummary summary = new LineCountSummary("All Projects", m_projIconMappings["{00000000-0000-0000-0000-000000000000}"]); m_summaryList.Add(summary); // Configure progress bars tsprgTotal.Minimum = 0; tsprgTotal.Step = 1; tsprgTask.Minimum = 0; tsprgTask.Step = 1; List projects = new List(solution.Projects); tsprgTotal.Maximum = projects.Count; tsprgTask.Value = 0; foreach (IProject fiProject in projects) { tsprgTotal.PerformStep(); string projName, lang; if (fiProject.FileName.IndexOf("://") != -1) { projName = fiProject.FileName; // this is a web project lang = "{00000001-0000-0000-0000-000000000000}"; } else { projName = fiProject.Name; lang = fiProject.TypeGuid; } int iconIndex; #if IMPR1 iconIndex = projectImageListHelper.GetIndex(IconService.GetImageForProjectType(fiProject.Language ?? "defaultLanguageName")); #else m_projIconMappings.TryGetValue(lang, out iconIndex); // default icon 0 #endif summary = new LineCountSummary(projName, iconIndex); m_summaryList.Add(summary); tsprgTask.Maximum = 0; tsprgTotal.Value = 0; ScanProjectItems(fiProject.Items, summary); } tsprgTask.Value = tsprgTask.Maximum; tsprgTotal.Value = tsprgTotal.Maximum; } else { MessageBox.Show("There is no solution open in SharpDevelop.", "Line Counter"); } } /// /// Scans the project items (files, usually) of /// a project's ProjectItems collection. /// /// The ProjectItems collection to scan. /// The root summary data object that these /// files belong to. private void ScanProjectItems(IList projectItems, LineCountSummary summary) { tsprgTask.Maximum += projectItems.Count; foreach (ProjectItem projectItem in projectItems) { tsprgTask.PerformStep(); if (!(projectItem is FileProjectItem)) { // Skip references and other special MSBuild things continue; } string projectFile = projectItem.FileName; if (!Directory.Exists(projectFile)) { int iconIndex = 0; #if IMPR1 iconIndex = fileImageListHelper.GetIndex(IconService.GetImageForFile(projectFile)); #else m_fileIconMappings.TryGetValue(Path.GetExtension(projectFile), out iconIndex); #endif summary.FileLineCountInfo.Add(new LineCountInfo(projectFile, iconIndex, summary)); } } } /// /// Performs a complete counting and summation of all lines /// in all projects and files. /// private void SumSolution() { try { // Clean the list lvSummary.Items.Clear(); lvFileList.Items.Clear(); lvFileList.Groups.Clear(); // Configure progress bars tsprgTotal.Minimum = 0; tsprgTotal.Step = 1; tsprgTask.Minimum = 0; tsprgTask.Step = 1; // Skip if there are no projects if (m_summaryList == null || (m_summaryList != null && m_summaryList.Count == 1)) { MessageBox.Show("There are no projects loaded to summarize.", "Line Counter"); return; } // Get all projects summary LineCountSummary allProjects = m_summaryList[0]; allProjects.LineCountSummaryDetails.Reset(); AddSummaryListItem(allProjects, lvSummary.Groups["lvgAllProj"]); tsprgTotal.Maximum = m_summaryList.Count; tsprgTotal.Value = 0; for (int s = 1; s < m_summaryList.Count; s++) { tsprgTotal.PerformStep(); LineCountSummary summary = m_summaryList[s]; summary.LineCountSummaryDetails.Reset(); AddSummaryListItem(summary, lvSummary.Groups["lvgEachProj"]); tsprgTask.Maximum = summary.FileLineCountInfo.Count; tsprgTask.Value = 0; for (int i = 0; i < summary.FileLineCountInfo.Count; i++) { tsprgTask.PerformStep(); LineCountInfo info = summary.FileLineCountInfo[i]; if (m_countableTypes.Contains(info.FileType)) { info.LineCountInfoDetails.Reset(); #if IMPR2 foreach (CountingAlgorithmDescriptor desc in countingAlgorithms) { if (desc.CanCountLines(info)) { desc.GetAlgorithm().CountLines(info); break; } } #else try { CountLines counter = m_countAlgorithms[info.FileType]; counter(info); } catch (Exception ex) { Console.WriteLine(ex.Message); Console.WriteLine(ex.StackTrace); } #endif info.LineCountInfoDetails.Summarize(); allProjects.LineCountSummaryDetails.Add(info.LineCountInfoDetails); summary.LineCountSummaryDetails.Add(info.LineCountInfoDetails); tstxtLinesCounted.Text = allProjects.LineCountSummaryDetails.TotalLines.ToString(); AddFileListItem(info); } } summary.LineCountSummaryDetails.Summarize(); LineCountDetails details = summary.LineCountSummaryDetails; summary.LinkedListViewItem.SubItems[1].Text = details.TotalLines.ToString(); summary.LinkedListViewItem.SubItems[2].Text = details.CodeLines.ToString(); summary.LinkedListViewItem.SubItems[3].Text = details.CommentLines.ToString(); summary.LinkedListViewItem.SubItems[4].Text = details.BlankLines.ToString(); summary.LinkedListViewItem.SubItems[5].Text = details.NetLines.ToString(); details = null; } allProjects.LineCountSummaryDetails.Summarize(); LineCountDetails totals = allProjects.LineCountSummaryDetails; allProjects.LinkedListViewItem.SubItems[1].Text = totals.TotalLines.ToString(); allProjects.LinkedListViewItem.SubItems[2].Text = totals.CodeLines.ToString(); allProjects.LinkedListViewItem.SubItems[3].Text = totals.CommentLines.ToString(); allProjects.LinkedListViewItem.SubItems[4].Text = totals.BlankLines.ToString(); allProjects.LinkedListViewItem.SubItems[5].Text = totals.NetLines.ToString(); } catch (Exception ex) { Debug.WriteLine(ex.Message); Debug.WriteLine(ex.StackTrace); } tsprgTotal.Value = tsprgTotal.Maximum; } /// /// Obsolete. Useless. Dissapeared. /// private void PrepareFileListGroups() { lvFileList.Groups.Clear(); if (tsmiGroupByType.Checked) { } else if (tsmiGroupByProj.Checked) { } } /// /// Adds a summary item to the projects list view. /// /// The summary data object to reference. /// The summary list view group this item /// should be listed under. private void AddSummaryListItem(LineCountSummary summary, ListViewGroup group) { ListViewItem lvi = new ListViewItem(); lvi.Text = summary.ProjectName; lvi.SubItems.Add("0"); lvi.SubItems.Add("0"); lvi.SubItems.Add("0"); lvi.SubItems.Add("0"); lvi.SubItems.Add("0"); lvi.Tag = summary; lvi.ImageIndex = summary.IconIndex; //lvi.StateImageIndex = summary.IconIndex; lvi.Group = group; summary.LinkedListViewItem = lvi; lvSummary.Items.Add(lvi); } /// /// Adds a file information item to the file list view. /// /// The file information data object. private void AddFileListItem(LineCountInfo info) { FileInfo fileInfo = new FileInfo(info.FileName); ListViewItem lvi = new ListViewItem(); lvi.Text = fileInfo.Name; lvi.SubItems.Add(info.LineCountInfoDetails.TotalLines.ToString()); lvi.SubItems.Add(info.LineCountInfoDetails.CodeLines.ToString()); lvi.SubItems.Add(info.LineCountInfoDetails.CommentLines.ToString()); lvi.SubItems.Add(info.FileType); lvi.SubItems.Add(info.SumMode); lvi.Tag = info; lvi.ImageIndex = info.IconIndex; //lvi.StateImageIndex = iconIndex; if (tsmiGroupByType.Checked) { ListViewGroup group = lvFileList.Groups["groupType" + info.FileType.Substring(1)]; if (group == null) { group = new ListViewGroup("groupType" + info.FileType.Substring(1), info.FileType.Substring(1).ToUpper() + " Files"); lvFileList.Groups.Add(group); } lvi.Group = group; } else if (tsmiGroupByProj.Checked) { ListViewGroup group = lvFileList.Groups["groupProj" + info.ProjectSummary.ProjectName]; if (group == null) { group = new ListViewGroup("groupProj" + info.ProjectSummary.ProjectName, info.ProjectSummary.ProjectName + " Files"); lvFileList.Groups.Add(group); } lvi.Group = group; } lvFileList.Items.Add(lvi); } #endregion #endregion } #region Support Structures // Delegate for pluggable line counting methods delegate void CountLines(LineCountInfo info); /// /// Encapsulates line count sum details. /// public class LineCountDetails { public LineCountDetails() { Reset(); } private int m_totalLines; private int m_codeLines; private int m_commentLines; private int m_doccmtLines; private int m_normcmtLines; private int m_blankLines; private int m_netLines; public int TotalLines { get { return m_totalLines; } } public int CodeLines { get { return m_codeLines; } } public int CommentLines { get { return m_commentLines; } } public int DocCommentLines { get { return m_doccmtLines; } } public int NormalCommentLines { get { return m_normcmtLines; } } public int BlankLines { get { return m_blankLines; } } public int NetLines { get { return m_netLines; } } public void Reset() { m_totalLines = 0; m_codeLines = 0; m_commentLines = 0; m_doccmtLines = 0; m_normcmtLines = 0; m_blankLines = 0; m_netLines = 0; } public void Summarize() { m_commentLines = m_doccmtLines + m_normcmtLines; m_netLines = m_totalLines - m_blankLines; } public void Add(string toWhat, int amount) { if (toWhat == null) toWhat = "totallines"; toWhat = toWhat.ToLower(); switch (toWhat) { case "totallines": m_totalLines += amount; break; case "codelines": m_codeLines += amount; break; case "doccmtlines": m_doccmtLines += amount; break; case "normcmtlines": m_normcmtLines += amount; break; case "blanklines": m_blankLines += amount; break; } } public void Add(LineCountDetails details) { m_totalLines += details.m_totalLines; m_codeLines += details.m_codeLines; m_doccmtLines += details.m_doccmtLines; m_normcmtLines += details.m_normcmtLines; m_blankLines += details.m_blankLines; } } /// /// Wraps a project and the line count total detail /// for that project. Enumerates all of the files /// within that project. /// public class LineCountSummary { public LineCountSummary(string projName, int iconIndex) { m_fileLineCountInfo = new List(); m_lineCountSummaryDetails = new LineCountDetails(); m_projectName = projName; m_iconIndex = iconIndex; } private List m_fileLineCountInfo; private LineCountDetails m_lineCountSummaryDetails; private string m_projectName; private int m_iconIndex; internal ListViewItem LinkedListViewItem; public string ProjectName { get { return m_projectName; } } public int IconIndex { get { return m_iconIndex; } } public LineCountDetails LineCountSummaryDetails { get { return m_lineCountSummaryDetails; } } public List FileLineCountInfo { get { return m_fileLineCountInfo; } } } /// /// Wraps a project source code file and the line /// count info for that file. Also provides details /// about the file type and what icon should be shown /// for the file in the UI. /// public class LineCountInfo { public LineCountInfo(string fileName, int iconIndex) { m_fileName = fileName; m_fileType = Path.GetExtension(fileName); m_iconIndex = iconIndex; m_sumMode = "Generic"; m_lineCountInfoDetails = new LineCountDetails(); } public LineCountInfo(string fileName, int iconIndex, LineCountSummary projectSummary) : this(fileName, iconIndex) { m_projectSummary = projectSummary; } private LineCountDetails m_lineCountInfoDetails; private string m_fileName; private string m_fileType; private int m_iconIndex; private LineCountSummary m_projectSummary; private string m_sumMode; public string FileName { get { return m_fileName; } } public string FileType { get { return m_fileType; } } public int IconIndex { get { return m_iconIndex; } } public string SumMode { get { return m_sumMode; } set { m_sumMode = value; } } public LineCountDetails LineCountInfoDetails { get { return m_lineCountInfoDetails; } } public LineCountSummary ProjectSummary { get { return m_projectSummary; } } } #endregion }