/*
* Process Hacker -
* sorted list comparer
*
* Copyright (C) 2009 wj32
*
* This file is part of Process Hacker.
*
* Process Hacker is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Process Hacker is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Process Hacker. If not, see .
*/
using System;
using System.Windows.Forms;
using System.Collections;
using System.Collections.Generic;
using System.Drawing;
namespace ProcessHacker
{
///
/// Provides automatic sorting support for the ListView control.
///
///
/// myListView.ListViewItemSorter = new SortedListComparer(myListView);
///
public class SortedListComparer : IComparer
{
private ListView _list;
private bool _triState;
private IComparer _triStateComparer;
private int _sortColumn;
private SortOrder _sortOrder;
private Dictionary> _customSorters = new Dictionary>();
///
/// Creates a new sorted list manager.
///
/// The ListView to manage.
public SortedListComparer(ListView list)
{
_list = list;
_list.ColumnClick += new ColumnClickEventHandler(list_ColumnClick);
_sortColumn = 0;
_sortOrder = SortOrder.Ascending;
}
///
/// Allows three states of sorting: Ascending, Descending and None.
/// You must specify the sorter used for the None state using
/// TriStateComparer.
///
public bool TriState
{
get { return _triState; }
set { _triState = value; }
}
///
/// Specifies the sorter used for the None sorting state.
///
public IComparer TriStateComparer
{
get { return _triStateComparer; }
set { _triStateComparer = value; }
}
///
/// Specifies the index of the column to sort.
///
public int SortColumn
{
get { return _sortColumn; }
set { _sortColumn = value; }
}
///
/// Specifies the sort order/state.
///
public SortOrder SortOrder
{
get { return _sortOrder; }
set { _sortOrder = value; }
}
///
/// Allows custom sorting for individual columns.
///
public IDictionary> CustomSorters
{
get { return _customSorters; }
}
private void list_ColumnClick(object sender, ColumnClickEventArgs e)
{
if (e.Column == _sortColumn)
{
if (_triState)
{
if (_sortOrder == SortOrder.Ascending)
_sortOrder = SortOrder.Descending;
else if (_sortOrder == SortOrder.Descending)
_sortOrder = SortOrder.None;
else
_sortOrder = SortOrder.Ascending;
}
else
{
_sortOrder = _sortOrder == SortOrder.Ascending ? SortOrder.Descending : SortOrder.Ascending;
}
}
else
{
_sortColumn = e.Column;
_sortOrder = SortOrder.Ascending;
}
_list.Sort();
}
private int ModifySort(int result, SortOrder order)
{
if (order == SortOrder.Ascending)
return result;
else if (order == SortOrder.Descending)
return -result;
else
return 0;
}
///
/// Compares two ListView objects.
///
/// The first ListView.
/// The second ListView.
/// A comparison result.
public int Compare(object x, object y)
{
if (_triState && _sortOrder == SortOrder.None)
return _triStateComparer.Compare(x, y);
ListViewItem lx = x as ListViewItem;
ListViewItem ly = y as ListViewItem;
if (_customSorters.ContainsKey(_sortColumn))
return ModifySort(_customSorters[_sortColumn](lx, ly), _sortOrder);
string sx, sy;
int ix, iy;
IComparable cx, cy;
sx = lx.SubItems[_sortColumn].Text;
sy = ly.SubItems[_sortColumn].Text;
if (!int.TryParse(sx.StartsWith("0x") ? sx.Substring(2) : sx,
sx.StartsWith("0x") ? System.Globalization.NumberStyles.AllowHexSpecifier : 0,
null, out ix) ||
!int.TryParse(sy.StartsWith("0x") ? sy.Substring(2) : sy,
sy.StartsWith("0x") ? System.Globalization.NumberStyles.AllowHexSpecifier : 0,
null, out iy))
{
cx = lx.SubItems[_sortColumn].Text;
cy = ly.SubItems[_sortColumn].Text;
}
else
{
cx = ix;
cy = iy;
}
return ModifySort(cx.CompareTo(cy), _sortOrder);
}
}
}