using System;
using System.Collections;
using System.Windows.Forms;
///
/// A custom comparer for sorting ListView columns, implementing the 'IComparer' interface.
///
public class ListViewColumnSorter : IComparer
{
///
/// Case-insensitive comparer object used for comparing strings.
///
private readonly CaseInsensitiveComparer ObjectCompare;
///
/// Initializes a new instance of the ListViewColumnSorter class and sets default sorting parameters.
///
public ListViewColumnSorter()
{
// Default column index for sorting
SortColumn = 0;
// Default sorting order
Order = SortOrder.Ascending;
// Initialize the case-insensitive comparer
ObjectCompare = new CaseInsensitiveComparer();
}
///
/// Compares two ListViewItem objects based on the specified column index and sorting order.
///
/// First ListViewItem object to compare.
/// Second ListViewItem object to compare.
///
/// A signed integer indicating the relative values of x and y:
/// "0" if equal, a negative number if x is less than y, and a positive number if x is greater than y.
///
public int Compare(object x, object y)
{
int compareResult;
ListViewItem listviewX = (ListViewItem)x;
ListViewItem listviewY = (ListViewItem)y;
// Special handling for column 6 (Popularity ranking)
if (SortColumn == 6)
{
string textX = listviewX.SubItems[SortColumn].Text;
string textY = listviewY.SubItems[SortColumn].Text;
// Extract numeric values from "#1", "#10", etc.
// "-" represents unranked and should go to the end
int rankX = int.MaxValue; // Default for unranked (-)
int rankY = int.MaxValue;
if (textX.StartsWith("#") && int.TryParse(textX.Substring(1), out int parsedX))
{
rankX = parsedX;
}
if (textY.StartsWith("#") && int.TryParse(textY.Substring(1), out int parsedY))
{
rankY = parsedY;
}
// Compare the numeric ranks
compareResult = rankX.CompareTo(rankY);
}
// Special handling for column 5 (Size)
else if (SortColumn == 5)
{
string textX = listviewX.SubItems[SortColumn].Text;
string textY = listviewY.SubItems[SortColumn].Text;
double sizeX = ParseSize(textX);
double sizeY = ParseSize(textY);
// Compare the numeric sizes
compareResult = sizeX.CompareTo(sizeY);
}
else
{
// Default to string comparison for non-numeric columns
compareResult = ObjectCompare.Compare(listviewX.SubItems[SortColumn].Text, listviewY.SubItems[SortColumn].Text);
}
// Determine the return value based on the specified sort order
if (Order == SortOrder.Ascending)
{
return compareResult;
}
else if (Order == SortOrder.Descending)
{
return -compareResult;
}
else
{
return 0; // Indicate equality
}
}
///
/// Parses a numeric value from a string for accurate numeric comparison.
///
/// The string representation of the number.
/// The parsed integer value; returns 0 if parsing fails.
private int ParseNumber(string text)
{
// Directly attempt to parse the string as an integer
return int.TryParse(text, out int result) ? result : 0;
}
///
/// Parses size strings with units (GB/MB) and converts them to MB for comparison.
///
/// Size string (e.g., "1.23 GB", "123 MB")
/// Size in MB as a double
private double ParseSize(string sizeStr)
{
if (string.IsNullOrEmpty(sizeStr))
return 0;
// Remove whitespace
sizeStr = sizeStr.Trim();
// Handle new format: "1.23 GB" or "123 MB"
if (sizeStr.EndsWith(" GB", StringComparison.OrdinalIgnoreCase))
{
string numPart = sizeStr.Substring(0, sizeStr.Length - 3).Trim();
if (double.TryParse(numPart, System.Globalization.NumberStyles.Any,
System.Globalization.CultureInfo.InvariantCulture, out double gb))
{
return gb * 1024.0; // Convert GB to MB for consistent sorting
}
}
else if (sizeStr.EndsWith(" MB", StringComparison.OrdinalIgnoreCase))
{
string numPart = sizeStr.Substring(0, sizeStr.Length - 3).Trim();
if (double.TryParse(numPart, System.Globalization.NumberStyles.Any,
System.Globalization.CultureInfo.InvariantCulture, out double mb))
{
return mb;
}
}
// Fallback: try parsing as raw number
if (double.TryParse(sizeStr, System.Globalization.NumberStyles.Any,
System.Globalization.CultureInfo.InvariantCulture, out double rawMb))
{
return rawMb;
}
return 0;
}
///
/// Gets or sets the index of the column to be sorted (default is '0').
///
public int SortColumn { get; set; }
///
/// Gets or sets the order of sorting (Ascending or Descending).
///
public SortOrder Order { get; set; }
}