Source code for MSQuant: ListViewColumnSorter.vb, MSQuant/msquant/src/GUI/ListViewColumnSorter.vb.

Table of contents page.

Home page for MSQuant.

'****************************************************************************
'* Copyright (C) 2004 Peter Mortensen and Matthias Mann                     *
'* This file is part of MSQuant.                                            *
'*                                                                          *
'* MSQuant is distributed under the terms of                                *
'* the GNU General Public License. See src/COPYING.TXT or                   *
'* <http://www.gnu.org/licenses/gpl.txt> for details.                       *
'*                                                                          *
'* MSQuant 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 2 of the                             *
'* License, or (at your option) any later version.                          *
'*                                                                          *
'* MSQuant 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 MSQuant; if not, write to                      *
'* the Free Software Foundation, Inc., 59 Temple                            *
'* Place, Suite 330, Boston, MA  02111-1307  USA                            *
'*                                                                          *
'* Purpose: provides sort class to be used to sort a ListView - by          *
'*          setting the property ListViewItemSorter to instance of          *
'*          this class. Clients specify a logical column, actual column     *
'*          is determined by an instance of a listviewColumnMapper.         *
'*          Clients can specify secondary columns/keys for the sort and     *
'*          specify datatype and direction (ascending/descending) for each  *
'*          key                                                             *
'*                                                                          *
'****************************************************************************

'****************************************************************************
'*                               CEBI                                       *
'*                    Software Development Group                            *
'*                         Peter Mortensen                                  *
'*                E-mail: NUKESPAMMERSdrmortensen@get2netZZZZZZ.dk          *
'*                 WWW: http://www.cebi.sdu.dk/                             *
'*                                                                          *
'*  Program for post-processing of result from search in mass               *
'*    spectrometric data.                                                   *
'*                                                                          *
'*    FILENAME:   listviewColumnMapper.vb                                   *
'*    TYPE:  VISUAL_BASIC                                                   *
'*                                                                          *
'* CREATED: PM 2006-02-23   Vrs 1.0.                                        *
'* UPDATED: PM 2005-xx-xx                                                   *
'*                                                                          *
'****************************************************************************

'Future:
'  1. What if the column for a key does not exist in the current ListViewItem?


Option Strict On
Option Explicit On 


'****************************************************************************
'*    <placeholder for header>                                              *
'****************************************************************************
Namespace CEBI_generalGUI 'Better name? Things in this name space are
    '  application independent stuff (bug fixes, extensions, 
    '  generalisations) that could be used elsewhere. It is
    '  not even mass spec specific.


    Public Enum sortingDirectionEnum
        enumAscendingSort = 293
        enumDescendingSort
    End Enum 'sortingDirectionEnum


    Public Enum datatypeEnum
        enumText = 293
        enumInteger
        enumDecimalNumber
    End Enum 'sortingDirectionEnum


    Public Structure sortKeyStructure
        Dim columnID As Integer

        Dim physicalColumn As Integer 'Helper field. For caching.
        '  Value derived from columnID.

        Dim sortDirection As sortingDirectionEnum

        Dim dataType As datatypeEnum

        'For convenience initialisation.
        Public Sub New( _
          ByRef aColumnID As Integer, _
          ByVal aDataType As datatypeEnum, _
          ByVal aSortDirection As sortingDirectionEnum)

            columnID = aColumnID
            dataType = aDataType

            sortDirection = aSortDirection
        End Sub 'New
    End Structure 'sortKeyStructure


    '****************************************************************************
    '*    <placeholder for header>                                              *
    '****************************************************************************
    Public Class ListViewColumnSorter
        Implements IComparer

        Private mColumnMapper As listviewColumnMapper

        Private mCurrentKeyList As ArrayList


        '****************************************************************************
        '*  SUBROUTINE NAME:   New                                                  *
        'd$ <summary>Constructor</summary>
        Public Sub New(ByRef anInColumnMapper As listviewColumnMapper)

            MyBase.New() 'Is this necessary? Yes!

            Trace.Assert(Not anInColumnMapper Is Nothing, _
              "PIL ASSERT. anInColumnMapper is Nothing.")

            mColumnMapper = anInColumnMapper
        End Sub 'New()


        '****************************************************************************
        '*    <placeholder for header>                                              *
        '****************************************************************************
        Public Sub prepareSort( _
          ByVal aKeylist2 As Generic.List(Of sortKeyStructure))

            'Old:
            '  ByVal aKeylist As ArrayList
            '  Item type of aKeylist is: sortKeyStructure


            'Cache the physical column number in the datastructure. Done here
            'during a deep copy of the input list.

            mCurrentKeyList = New ArrayList

            Dim someKey As sortKeyStructure
            For Each someKey In aKeylist2
                Dim copiedKey As sortKeyStructure = someKey
                copiedKey.physicalColumn = _
                  mColumnMapper.item2ColumnIndex(copiedKey.columnID)
                mCurrentKeyList.Add(copiedKey)
            Next
        End Sub 'prepareSort


        '****************************************************************************
        '*    <placeholder for header>                                              *
        '****************************************************************************
        Private Function Compare(ByVal x As Object, ByVal y As Object) As Integer _
        Implements System.Collections.IComparer.Compare

            Dim item1 As ListViewItem = CType(x, ListViewItem)
            Dim item2 As ListViewItem = CType(y, ListViewItem)

            Dim toReturn As Integer = 0 'In case 

            Dim someKey As sortKeyStructure
            For Each someKey In mCurrentKeyList

                Dim physCol As Integer = someKey.physicalColumn

                'Under normal circumstances these two
                'indices are always the same as all rows have
                'the same number of columns. But it can
                'happen that sorting is used during building
                'up of the list (by a screen update?) and
                'then a partly completed row can be compared
                'against a full row.
                Dim lastIndex1 As Integer = item1.SubItems.Count() - 1
                Dim lastIndex2 As Integer = item2.SubItems.Count() - 1

                Trace.Assert(physCol <= lastIndex1, _
                  "Index, " & physCol & ", is past last index in item1.SubItems, " & _
                  lastIndex1 & ".")
                Trace.Assert(physCol <= lastIndex2, _
                  "Index, " & physCol & ", is past last index in item1.SubItems, " & _
                  lastIndex2 & ".")

                Dim str1 As String = item1.SubItems(physCol).Text
                Dim str2 As String = item2.SubItems(physCol).Text
                If str1 = "..." Then
                    'Changed PM_QUANTCOLUMNS_SORT 2007-04-03
                    'str1 = "0"
                    str1 = "-1e-20"
                End If
                If str2 = "..." Then
                    'Changed PM_QUANTCOLUMNS_SORT 2007-04-03
                    'str2 = "0"
                    str2 = "-1e-20"
                End If

                'Changed PM_QUANTCOLUMNS_SORT 2007-04-03
                If str1 = "NaN" Then
                    str1 = "-1e-22"
                End If
                If str2 = "NaN" Then
                    str2 = "-1e-22"
                End If


                'Dim compareResult As Integer = 0
                Select Case someKey.dataType
                    Case datatypeEnum.enumText

                        'Initially ascending, but we reverse the result later
                        'if descending is specified.
                        If str1 > str2 Then
                            toReturn = 1
                        Else
                            If str1 < str2 Then
                                toReturn = -1
                            Else
                                'Equal...
                                Dim peter1 As Integer = 1
                            End If
                        End If

                    Case datatypeEnum.enumInteger
                        Dim int1 As Integer = CInt(str1)
                        Dim int2 As Integer = CInt(str2)

                        'Initially ascending, but we reverse the result later
                        'if descending is specified.
                        If int1 > int2 Then
                            toReturn = 1
                        Else
                            If int1 < int2 Then
                                toReturn = -1
                            Else
                                'Equal...
                                Dim peter1 As Integer = 1
                            End If
                        End If

                    Case datatypeEnum.enumDecimalNumber
                        'Ignore any parenthesises around the number, e.g.:  (47)

                        Dim startIndex1 As Integer = str1.IndexOf("(")
                        If startIndex1 >= 0 Then
                            Dim endIndex1 As Integer = str1.IndexOf(")")
                            If endIndex1 >= 0 Then
                                startIndex1 += 1 'Step over "("
                                Dim len1 As Integer = endIndex1 - startIndex1
                                str1 = str1.Substring(startIndex1, len1)
                            End If
                        End If

                        Dim startIndex2 As Integer = str2.IndexOf("(")
                        If startIndex2 >= 0 Then
                            Dim endIndex2 As Integer = str2.IndexOf(")")
                            If endIndex2 >= 0 Then
                                startIndex2 += 1 'Step over "("
                                Dim len2 As Integer = endIndex2 - startIndex2
                                str2 = str2.Substring(startIndex2, len2)
                            End If
                        End If

                        Dim d1 As Double = CDbl(str1)
                        Dim d2 As Double = CDbl(str2)

                        'Initially ascending, but we reverse the result later
                        'if descending is specified.
                        If d1 > d2 Then
                            toReturn = 1
                        Else
                            If d1 < d2 Then
                                toReturn = -1
                            Else
                                'Equal...
                                Dim peter1 As Integer = 1
                            End If
                        End If

                    Case Else
                        Trace.Assert(False, "PIL ASSERT. Select Case never fall-through")
                End Select

                If someKey.sortDirection = sortingDirectionEnum.enumDescendingSort Then
                    toReturn = -toReturn
                End If

                If toReturn = 0 Then
                    'The two keys are equal. We must go to a lower
                    'level key (if there are any) - by continuing the loop.
                    Dim peter1 As Integer = 1
                Else
                    Exit For 'Two current keys are not equal. We need not
                    'compare more keys. Stop.
                End If
            Next

            Return toReturn
        End Function 'Compare


    End Class 'ListViewColumnSorter


End Namespace 'CEBI_generalGUI


    

    

Generated by script codePublish.pl at 2008-09-23T11:59:18.